Annotation of embedaddon/mpd/src/lcp.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * lcp.c
! 4: *
! 5: * Written by Toshiharu OHNO <tony-o@iij.ad.jp>
! 6: * Copyright (c) 1993, Internet Initiative Japan, Inc. All rights reserved.
! 7: * See ``COPYRIGHT.iij''
! 8: *
! 9: * Rewritten by Archie Cobbs <archie@freebsd.org>
! 10: * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
! 11: * See ``COPYRIGHT.whistle''
! 12: */
! 13:
! 14: #include "ppp.h"
! 15: #include "lcp.h"
! 16: #include "fsm.h"
! 17: #include "mp.h"
! 18: #include "phys.h"
! 19: #include "link.h"
! 20: #include "msg.h"
! 21: #include "util.h"
! 22:
! 23: /*
! 24: * DEFINITIONS
! 25: */
! 26:
! 27: #define LCP_ECHO_INTERVAL 5 /* Enable keep alive by default */
! 28: #define LCP_ECHO_TIMEOUT 40
! 29:
! 30: #define LCP_KNOWN_CODES ( (1 << CODE_CONFIGREQ) \
! 31: | (1 << CODE_CONFIGACK) \
! 32: | (1 << CODE_CONFIGNAK) \
! 33: | (1 << CODE_CONFIGREJ) \
! 34: | (1 << CODE_TERMREQ) \
! 35: | (1 << CODE_TERMACK) \
! 36: | (1 << CODE_CODEREJ) \
! 37: | (1 << CODE_PROTOREJ) \
! 38: | (1 << CODE_ECHOREQ) \
! 39: | (1 << CODE_ECHOREP) \
! 40: | (1 << CODE_DISCREQ) \
! 41: | (1 << CODE_IDENT) \
! 42: | (1 << CODE_TIMEREM) )
! 43:
! 44: #define LCP_PEER_REJECTED(p,x) ((p)->peer_reject & (1<<x))
! 45: #define LCP_PEER_REJ(p,x) do{(p)->peer_reject |= (1<<(x));}while(0)
! 46: #define LCP_PEER_UNREJ(p,x) do{(p)->peer_reject &= ~(1<<(x));}while(0)
! 47:
! 48: /*
! 49: * INTERNAL FUNCTIONS
! 50: */
! 51:
! 52: static void LcpConfigure(Fsm fp);
! 53: static void LcpNewState(Fsm fp, enum fsm_state old, enum fsm_state new);
! 54: static void LcpNewPhase(Link l, enum lcp_phase new);
! 55:
! 56: static u_char *LcpBuildConfigReq(Fsm fp, u_char *cp);
! 57: static void LcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode);
! 58: static void LcpLayerDown(Fsm fp);
! 59: static void LcpLayerStart(Fsm fp);
! 60: static void LcpLayerFinish(Fsm fp);
! 61: static int LcpRecvProtoRej(Fsm fp, int proto, Mbuf bp);
! 62: static void LcpFailure(Fsm fp, enum fsmfail reason);
! 63: static const struct fsmoption *LcpAuthProtoNak(ushort proto, u_char alg);
! 64: static short LcpFindAuthProto(ushort proto, u_char alg);
! 65: static void LcpRecvIdent(Fsm fp, Mbuf bp);
! 66: static void LcpStopActivity(Link l);
! 67:
! 68: /*
! 69: * INTERNAL VARIABLES
! 70: */
! 71:
! 72: static const struct fsmoptinfo gLcpConfOpts[] = {
! 73: { "VENDOR", TY_VENDOR, 4, 255, TRUE },
! 74: { "MRU", TY_MRU, 2, 2, TRUE },
! 75: { "ACCMAP", TY_ACCMAP, 4, 4, TRUE },
! 76: { "AUTHPROTO", TY_AUTHPROTO, 2, 255, TRUE },
! 77: { "QUALPROTO", TY_QUALPROTO, 0, 0, FALSE },
! 78: { "MAGICNUM", TY_MAGICNUM, 4, 4, TRUE },
! 79: { "RESERVED", TY_RESERVED, 0, 0, FALSE }, /* DEPRECATED */
! 80: { "PROTOCOMP", TY_PROTOCOMP, 0, 0, TRUE },
! 81: { "ACFCOMP", TY_ACFCOMP, 0, 0, TRUE },
! 82: { "FCSALT", TY_FCSALT, 0, 0, FALSE },
! 83: { "SDP", TY_SDP, 0, 0, FALSE },
! 84: { "NUMMODE", TY_NUMMODE, 0, 0, FALSE },
! 85: { "MULTILINK", TY_MULTILINK, 0, 0, FALSE }, /* DEPRECATED */
! 86: { "CALLBACK", TY_CALLBACK, 1, 255, TRUE },
! 87: { "CONNECTTIME", TY_CONNECTTIME, 0, 0, FALSE }, /* DEPRECATED */
! 88: { "COMPFRAME", TY_COMPFRAME, 0, 0, FALSE }, /* DEPRECATED */
! 89: { "NDS", TY_NDS, 0, 0, FALSE }, /* DEPRECATED */
! 90: { "MP MRRU", TY_MRRU, 2, 2, TRUE },
! 91: { "MP SHORTSEQ", TY_SHORTSEQNUM, 0, 0, TRUE },
! 92: { "ENDPOINTDISC", TY_ENDPOINTDISC, 1, 255, TRUE },
! 93: { "PROPRIETARY", TY_PROPRIETARY, 0, 0, FALSE },
! 94: { "DCEIDENTIFIER", TY_DCEIDENTIFIER, 0, 0, FALSE },
! 95: { "MULTILINKPLUS", TY_MULTILINKPLUS, 0, 0, FALSE },
! 96: { "BACP", TY_BACP, 0, 0, FALSE },
! 97: { "LCPAUTHOPT", TY_LCPAUTHOPT, 0, 0, FALSE },
! 98: { "COBS", TY_COBS, 0, 0, FALSE },
! 99: { "PREFIXELISION", TY_PREFIXELISION, 0, 0, FALSE },
! 100: { "MULTILINKHEADERFMT", TY_MULTILINKHEADERFMT, 0, 0, FALSE },
! 101: { "INTERNAT", TY_INTERNAT, 0, 0, FALSE },
! 102: { "SDATALINKSONET", TY_SDATALINKSONET, 0, 0, FALSE },
! 103: { NULL }
! 104: };
! 105:
! 106: static struct fsmtype gLcpFsmType = {
! 107: "LCP", /* Name of protocol */
! 108: PROTO_LCP, /* Protocol Number */
! 109: LCP_KNOWN_CODES,
! 110: TRUE,
! 111: LG_LCP, LG_LCP2,
! 112: LcpNewState,
! 113: NULL,
! 114: LcpLayerDown,
! 115: LcpLayerStart,
! 116: LcpLayerFinish,
! 117: LcpBuildConfigReq,
! 118: LcpDecodeConfig,
! 119: LcpConfigure,
! 120: NULL,
! 121: NULL,
! 122: NULL,
! 123: NULL,
! 124: LcpRecvProtoRej,
! 125: LcpFailure,
! 126: NULL,
! 127: NULL,
! 128: LcpRecvIdent,
! 129: };
! 130:
! 131: /* List of possible Authentication Protocols */
! 132: static struct lcpauthproto gLcpAuthProtos[] = {
! 133: {
! 134: PROTO_PAP,
! 135: 0,
! 136: LINK_CONF_PAP,
! 137: },
! 138: {
! 139: PROTO_CHAP,
! 140: CHAP_ALG_MD5,
! 141: LINK_CONF_CHAPMD5
! 142: },
! 143: {
! 144: PROTO_CHAP,
! 145: CHAP_ALG_MSOFT,
! 146: LINK_CONF_CHAPMSv1
! 147: },
! 148: {
! 149: PROTO_CHAP,
! 150: CHAP_ALG_MSOFTv2,
! 151: LINK_CONF_CHAPMSv2
! 152: },
! 153: {
! 154: PROTO_EAP,
! 155: 0,
! 156: LINK_CONF_EAP
! 157: }
! 158:
! 159: };
! 160:
! 161: static const char *PhaseNames[] = {
! 162: "DEAD",
! 163: "ESTABLISH",
! 164: "AUTHENTICATE",
! 165: "NETWORK",
! 166: "TERMINATE",
! 167: };
! 168:
! 169: /*
! 170: * LcpInit()
! 171: */
! 172:
! 173: void
! 174: LcpInit(Link l)
! 175: {
! 176: LcpState const lcp = &l->lcp;
! 177:
! 178: memset(lcp, 0, sizeof(*lcp));
! 179: FsmInit(&lcp->fsm, &gLcpFsmType, l);
! 180: lcp->fsm.conf.echo_int = LCP_ECHO_INTERVAL;
! 181: lcp->fsm.conf.echo_max = LCP_ECHO_TIMEOUT;
! 182: lcp->phase = PHASE_DEAD;
! 183:
! 184: AuthInit(l);
! 185: }
! 186:
! 187: /*
! 188: * LcpInst()
! 189: */
! 190:
! 191: void
! 192: LcpInst(Link l, Link lt)
! 193: {
! 194: LcpState const lcp = &l->lcp;
! 195:
! 196: memcpy(lcp, <->lcp, sizeof(*lcp));
! 197: FsmInst(&lcp->fsm, <->lcp.fsm, l);
! 198: AuthInst(&lcp->auth, <->lcp.auth);
! 199: }
! 200:
! 201: /*
! 202: * LcpShutdown()
! 203: */
! 204:
! 205: void
! 206: LcpShutdown(Link l)
! 207: {
! 208: AuthShutdown(l);
! 209: }
! 210:
! 211: /*
! 212: * LcpConfigure()
! 213: */
! 214:
! 215: static void
! 216: LcpConfigure(Fsm fp)
! 217: {
! 218: Link l = (Link)fp->arg;
! 219: LcpState const lcp = &l->lcp;
! 220: short i;
! 221:
! 222: /* FSM stuff */
! 223: lcp->fsm.conf.passive = Enabled(&l->conf.options, LINK_CONF_PASSIVE);
! 224: lcp->fsm.conf.check_magic =
! 225: Enabled(&l->conf.options, LINK_CONF_CHECK_MAGIC);
! 226: lcp->peer_reject = 0;
! 227:
! 228: /* Initialize normal LCP stuff */
! 229: lcp->peer_mru = l->conf.mtu;
! 230: lcp->want_mru = l->conf.mru;
! 231: if (l->type && (lcp->want_mru > l->type->mru))
! 232: lcp->want_mru = l->type->mru;
! 233: lcp->peer_accmap = 0xffffffff;
! 234: lcp->want_accmap = l->conf.accmap;
! 235: lcp->peer_acfcomp = FALSE;
! 236: lcp->want_acfcomp = Enabled(&l->conf.options, LINK_CONF_ACFCOMP);
! 237: lcp->peer_protocomp = FALSE;
! 238: lcp->want_protocomp = Enabled(&l->conf.options, LINK_CONF_PROTOCOMP);
! 239: lcp->peer_magic = 0;
! 240: lcp->want_magic = Enabled(&l->conf.options,
! 241: LINK_CONF_MAGICNUM) ? GenerateMagic() : 0;
! 242: if (l->originate == LINK_ORIGINATE_LOCAL)
! 243: lcp->want_callback = Enabled(&l->conf.options, LINK_CONF_CALLBACK);
! 244: else
! 245: lcp->want_callback = FALSE;
! 246:
! 247: /* Authentication stuff */
! 248: lcp->peer_auth = 0;
! 249: lcp->want_auth = 0;
! 250: lcp->peer_alg = 0;
! 251: lcp->want_alg = 0;
! 252: lcp->peer_ident[0] = 0;
! 253:
! 254: memset(lcp->want_protos, 0, sizeof(lcp->want_protos));
! 255: /* fill my list of possible auth-protos, most to least secure */
! 256: /* prefer MS-CHAP to others to get encryption keys */
! 257: lcp->want_protos[0] = &gLcpAuthProtos[LINK_CONF_CHAPMSv2];
! 258: lcp->want_protos[1] = &gLcpAuthProtos[LINK_CONF_CHAPMSv1];
! 259: lcp->want_protos[2] = &gLcpAuthProtos[LINK_CONF_CHAPMD5];
! 260: lcp->want_protos[3] = &gLcpAuthProtos[LINK_CONF_PAP];
! 261: lcp->want_protos[4] = &gLcpAuthProtos[LINK_CONF_EAP];
! 262:
! 263: /* Use the same list for the MODE_REQ */
! 264: memcpy(lcp->peer_protos, lcp->want_protos, sizeof(lcp->peer_protos));
! 265:
! 266: for (i = 0; i < LCP_NUM_AUTH_PROTOS; i++) {
! 267: if (Enabled(&l->conf.options, lcp->want_protos[i]->conf) && lcp->want_auth == 0) {
! 268: lcp->want_auth = lcp->want_protos[i]->proto;
! 269: lcp->want_alg = lcp->want_protos[i]->alg;
! 270: /* avoid re-requesting this proto, if it was nak'd by the peer */
! 271: lcp->want_protos[i] = NULL;
! 272: } else if (!Enabled(&l->conf.options, lcp->want_protos[i]->conf)) {
! 273: /* don't request disabled Protos */
! 274: lcp->want_protos[i] = NULL;
! 275: }
! 276:
! 277: /* remove all denied protos */
! 278: if (!Acceptable(&l->conf.options, lcp->peer_protos[i]->conf))
! 279: lcp->peer_protos[i] = NULL;
! 280: }
! 281:
! 282: /* Multi-link stuff */
! 283: lcp->peer_mrru = 0;
! 284: lcp->peer_shortseq = FALSE;
! 285: if (Enabled(&l->conf.options, LINK_CONF_MULTILINK)) {
! 286: lcp->want_mrru = l->conf.mrru;
! 287: lcp->want_shortseq = Enabled(&l->conf.options, LINK_CONF_SHORTSEQ);
! 288: } else {
! 289: lcp->want_mrru = 0;
! 290: lcp->want_shortseq = FALSE;
! 291: }
! 292:
! 293: /* Peer discriminator */
! 294: lcp->peer_discrim.class = DISCRIM_CLASS_NULL;
! 295: lcp->peer_discrim.len = 0;
! 296: }
! 297:
! 298: /*
! 299: * LcpNewState()
! 300: *
! 301: * Keep track of phase shifts
! 302: */
! 303:
! 304: static void
! 305: LcpNewState(Fsm fp, enum fsm_state old, enum fsm_state new)
! 306: {
! 307: Link l = (Link)fp->arg;
! 308:
! 309: switch (old) {
! 310: case ST_INITIAL: /* DEAD */
! 311: case ST_STARTING:
! 312: switch (new) {
! 313: case ST_INITIAL:
! 314: /* fall through */
! 315: case ST_STARTING:
! 316: break;
! 317: default:
! 318: LcpNewPhase(l, PHASE_ESTABLISH);
! 319: break;
! 320: }
! 321: break;
! 322:
! 323: case ST_CLOSED: /* ESTABLISH */
! 324: case ST_STOPPED:
! 325: switch (new) {
! 326: case ST_INITIAL:
! 327: case ST_STARTING:
! 328: LcpNewPhase(l, PHASE_DEAD);
! 329: break;
! 330: default:
! 331: break;
! 332: }
! 333: break;
! 334:
! 335: case ST_CLOSING: /* TERMINATE */
! 336: case ST_STOPPING:
! 337: switch (new) {
! 338: case ST_INITIAL:
! 339: case ST_STARTING:
! 340: LcpNewPhase(l, PHASE_DEAD);
! 341: break;
! 342: case ST_CLOSED:
! 343: case ST_STOPPED:
! 344: LcpNewPhase(l, PHASE_ESTABLISH);
! 345: break;
! 346: default:
! 347: break;
! 348: }
! 349: break;
! 350:
! 351: case ST_REQSENT: /* ESTABLISH */
! 352: case ST_ACKRCVD:
! 353: case ST_ACKSENT:
! 354: switch (new) {
! 355: case ST_INITIAL:
! 356: case ST_STARTING:
! 357: LcpNewPhase(l, PHASE_DEAD);
! 358: break;
! 359: case ST_CLOSING:
! 360: case ST_STOPPING:
! 361: LcpNewPhase(l, PHASE_TERMINATE);
! 362: break;
! 363: case ST_OPENED:
! 364: LcpNewPhase(l, PHASE_AUTHENTICATE);
! 365: break;
! 366: default:
! 367: break;
! 368: }
! 369: break;
! 370:
! 371: case ST_OPENED: /* AUTHENTICATE, NETWORK */
! 372: switch (new) {
! 373: case ST_STARTING:
! 374: LcpNewPhase(l, PHASE_DEAD);
! 375: break;
! 376: case ST_REQSENT:
! 377: case ST_ACKSENT:
! 378: LcpNewPhase(l, PHASE_ESTABLISH);
! 379: break;
! 380: case ST_CLOSING:
! 381: case ST_STOPPING:
! 382: LcpNewPhase(l, PHASE_TERMINATE);
! 383: break;
! 384: default:
! 385: assert(0);
! 386: }
! 387: break;
! 388:
! 389: default:
! 390: assert(0);
! 391: }
! 392:
! 393: LinkShutdownCheck(l, new);
! 394: }
! 395:
! 396: /*
! 397: * LcpNewPhase()
! 398: */
! 399:
! 400: static void
! 401: LcpNewPhase(Link l, enum lcp_phase new)
! 402: {
! 403: LcpState const lcp = &l->lcp;
! 404: enum lcp_phase old = lcp->phase;
! 405:
! 406: /* Logit */
! 407: Log(LG_LCP2, ("[%s] %s: phase shift %s --> %s",
! 408: Pref(&lcp->fsm), Fsm(&lcp->fsm), PhaseNames[old], PhaseNames[new]));
! 409:
! 410: /* Sanity check transition (The picture on RFC 1661 p. 6 is incomplete) */
! 411: switch (old) {
! 412: case PHASE_DEAD:
! 413: assert(new == PHASE_ESTABLISH);
! 414: break;
! 415: case PHASE_ESTABLISH:
! 416: assert(new == PHASE_DEAD
! 417: || new == PHASE_TERMINATE
! 418: || new == PHASE_AUTHENTICATE);
! 419: break;
! 420: case PHASE_AUTHENTICATE:
! 421: assert(new == PHASE_TERMINATE
! 422: || new == PHASE_ESTABLISH
! 423: || new == PHASE_NETWORK
! 424: || new == PHASE_DEAD);
! 425: break;
! 426: case PHASE_NETWORK:
! 427: assert(new == PHASE_TERMINATE
! 428: || new == PHASE_ESTABLISH
! 429: || new == PHASE_DEAD);
! 430: break;
! 431: case PHASE_TERMINATE:
! 432: assert(new == PHASE_ESTABLISH
! 433: || new == PHASE_DEAD);
! 434: break;
! 435: default:
! 436: assert(0);
! 437: }
! 438:
! 439: /* Change phase now */
! 440: lcp->phase = new;
! 441:
! 442: /* Do whatever for leaving old phase */
! 443: switch (old) {
! 444: case PHASE_AUTHENTICATE:
! 445: if (new != PHASE_NETWORK)
! 446: AuthCleanup(l);
! 447: break;
! 448:
! 449: case PHASE_NETWORK:
! 450: if (l->joined_bund)
! 451: BundLeave(l);
! 452: AuthCleanup(l);
! 453: break;
! 454:
! 455: default:
! 456: break;
! 457: }
! 458:
! 459: /* Do whatever for entering new phase */
! 460: switch (new) {
! 461: case PHASE_ESTABLISH:
! 462: break;
! 463:
! 464: case PHASE_AUTHENTICATE:
! 465: if (!PhysIsSync(l))
! 466: PhysSetAccm(l, lcp->peer_accmap, lcp->want_accmap);
! 467: AuthStart(l);
! 468: break;
! 469:
! 470: case PHASE_NETWORK:
! 471: /* Send ident string, if configured */
! 472: if (l->conf.ident != NULL)
! 473: FsmSendIdent(&lcp->fsm, l->conf.ident);
! 474:
! 475: /* Send Time-Remaining if known */
! 476: if (Enabled(&l->conf.options, LINK_CONF_TIMEREMAIN) &&
! 477: lcp->auth.params.session_timeout != 0)
! 478: FsmSendTimeRemaining(&lcp->fsm, lcp->auth.params.session_timeout);
! 479:
! 480: /* Join my bundle */
! 481: if (!BundJoin(l)) {
! 482: Log(LG_LINK|LG_BUND,
! 483: ("[%s] link did not validate in bundle",
! 484: l->name));
! 485: RecordLinkUpDownReason(NULL, l,
! 486: 0, STR_PROTO_ERR, "%s", STR_MULTI_FAIL);
! 487: FsmFailure(&l->lcp.fsm, FAIL_NEGOT_FAILURE);
! 488: } else {
! 489: /* If link connection complete, reset redial counter */
! 490: l->num_redial = 0;
! 491: }
! 492: break;
! 493:
! 494: case PHASE_TERMINATE:
! 495: break;
! 496:
! 497: case PHASE_DEAD:
! 498: break;
! 499:
! 500: default:
! 501: assert(0);
! 502: }
! 503: }
! 504:
! 505: /*
! 506: * LcpAuthResult()
! 507: */
! 508:
! 509: void
! 510: LcpAuthResult(Link l, int success)
! 511: {
! 512: Log(LG_AUTH|LG_LCP, ("[%s] %s: authorization %s",
! 513: Pref(&l->lcp.fsm), Fsm(&l->lcp.fsm), success ? "successful" : "failed"));
! 514: if (success) {
! 515: if (l->lcp.phase != PHASE_NETWORK)
! 516: LcpNewPhase(l, PHASE_NETWORK);
! 517: } else {
! 518: RecordLinkUpDownReason(NULL, l, 0, STR_LOGIN_FAIL,
! 519: "%s", STR_PPP_AUTH_FAILURE);
! 520: FsmFailure(&l->lcp.fsm, FAIL_NEGOT_FAILURE);
! 521: }
! 522: }
! 523:
! 524: /*
! 525: * LcpStat()
! 526: */
! 527:
! 528: int
! 529: LcpStat(Context ctx, int ac, char *av[], void *arg)
! 530: {
! 531: Link const l = ctx->lnk;
! 532: LcpState const lcp = &l->lcp;
! 533: char buf[64];
! 534:
! 535: Printf("%s [%s]\r\n", lcp->fsm.type->name, FsmStateName(lcp->fsm.state));
! 536:
! 537: Printf("Self:\r\n");
! 538: Printf( "\tMRU : %d bytes\r\n"
! 539: "\tMAGIC : 0x%08x\r\n"
! 540: "\tACCMAP : 0x%08x\r\n"
! 541: "\tACFCOMP : %s\r\n"
! 542: "\tPROTOCOMP: %s\r\n"
! 543: "\tAUTHTYPE : %s\r\n",
! 544: (int) lcp->want_mru,
! 545: (int) lcp->want_magic,
! 546: (int) lcp->want_accmap,
! 547: lcp->want_acfcomp ? "Yes" : "No",
! 548: lcp->want_protocomp ? "Yes" : "No",
! 549: (lcp->want_auth)?ProtoName(lcp->want_auth):"none");
! 550:
! 551: if (lcp->want_mrru) {
! 552: Printf( "\tMRRU : %d bytes\r\n", (int) lcp->want_mrru);
! 553: Printf( "\tSHORTSEQ : %s\r\n", lcp->want_shortseq ? "Yes" : "No");
! 554: Printf( "\tENDPOINTDISC: %s\r\n", MpDiscrimText(&self_discrim, buf, sizeof(buf)));
! 555: }
! 556: if (l->conf.ident)
! 557: Printf( "\tIDENT : %s\r\n", l->conf.ident);
! 558:
! 559: Printf("Peer:\r\n");
! 560: Printf( "\tMRU : %d bytes\r\n"
! 561: "\tMAGIC : 0x%08x\r\n"
! 562: "\tACCMAP : 0x%08x\r\n"
! 563: "\tACFCOMP : %s\r\n"
! 564: "\tPROTOCOMP: %s\r\n"
! 565: "\tAUTHTYPE : %s\r\n",
! 566: (int) lcp->peer_mru,
! 567: (int) lcp->peer_magic,
! 568: (int) lcp->peer_accmap,
! 569: lcp->peer_acfcomp ? "Yes" : "No",
! 570: lcp->peer_protocomp ? "Yes" : "No",
! 571: (lcp->peer_auth)?ProtoName(lcp->peer_auth):"none");
! 572:
! 573: if (lcp->peer_mrru) {
! 574: Printf( "\tMRRU : %d bytes\r\n", (int) lcp->peer_mrru);
! 575: Printf( "\tSHORTSEQ : %s\r\n", lcp->peer_shortseq ? "Yes" : "No");
! 576: Printf( "\tENDPOINTDISC: %s\r\n", MpDiscrimText(&lcp->peer_discrim, buf, sizeof(buf)));
! 577: }
! 578: if (lcp->peer_ident[0])
! 579: Printf( "\tIDENT : %s\r\n", lcp->peer_ident);
! 580:
! 581: return(0);
! 582: }
! 583:
! 584: /*
! 585: * LcpBuildConfigReq()
! 586: */
! 587:
! 588: static u_char *
! 589: LcpBuildConfigReq(Fsm fp, u_char *cp)
! 590: {
! 591: Link l = (Link)fp->arg;
! 592: LcpState const lcp = &l->lcp;
! 593:
! 594: /* Standard stuff */
! 595: if (lcp->want_acfcomp && !LCP_PEER_REJECTED(lcp, TY_ACFCOMP))
! 596: cp = FsmConfValue(cp, TY_ACFCOMP, 0, NULL);
! 597: if (lcp->want_protocomp && !LCP_PEER_REJECTED(lcp, TY_PROTOCOMP))
! 598: cp = FsmConfValue(cp, TY_PROTOCOMP, 0, NULL);
! 599: if ((!PhysIsSync(l)) && (!LCP_PEER_REJECTED(lcp, TY_ACCMAP)))
! 600: cp = FsmConfValue(cp, TY_ACCMAP, -4, &lcp->want_accmap);
! 601: if (!LCP_PEER_REJECTED(lcp, TY_MRU))
! 602: cp = FsmConfValue(cp, TY_MRU, -2, &lcp->want_mru);
! 603: if (lcp->want_magic && !LCP_PEER_REJECTED(lcp, TY_MAGICNUM))
! 604: cp = FsmConfValue(cp, TY_MAGICNUM, -4, &lcp->want_magic);
! 605: if (lcp->want_callback && !LCP_PEER_REJECTED(lcp, TY_CALLBACK)) {
! 606: struct {
! 607: u_char op;
! 608: u_char data[0];
! 609: } s_callback;
! 610:
! 611: s_callback.op = 0;
! 612: cp = FsmConfValue(cp, TY_CALLBACK, 1, &s_callback);
! 613: }
! 614:
! 615: /* Authorization stuff */
! 616: switch (lcp->want_auth) {
! 617: case PROTO_PAP:
! 618: case PROTO_EAP:
! 619: cp = FsmConfValue(cp, TY_AUTHPROTO, -2, &lcp->want_auth);
! 620: break;
! 621: case PROTO_CHAP: {
! 622: struct {
! 623: u_short want_auth;
! 624: u_char alg;
! 625: } s_mdx;
! 626:
! 627: s_mdx.want_auth = htons(PROTO_CHAP);
! 628: s_mdx.alg = lcp->want_alg;
! 629: cp = FsmConfValue(cp, TY_AUTHPROTO, 3, &s_mdx);
! 630: }
! 631: break;
! 632: }
! 633:
! 634: /* Multi-link stuff */
! 635: if (Enabled(&l->conf.options, LINK_CONF_MULTILINK)
! 636: && !LCP_PEER_REJECTED(lcp, TY_MRRU)) {
! 637: cp = FsmConfValue(cp, TY_MRRU, -2, &lcp->want_mrru);
! 638: if (lcp->want_shortseq && !LCP_PEER_REJECTED(lcp, TY_SHORTSEQNUM))
! 639: cp = FsmConfValue(cp, TY_SHORTSEQNUM, 0, NULL);
! 640: if (!LCP_PEER_REJECTED(lcp, TY_ENDPOINTDISC))
! 641: cp = FsmConfValue(cp, TY_ENDPOINTDISC, 1 + self_discrim.len, &self_discrim.class);
! 642: }
! 643:
! 644: /* Done */
! 645: return(cp);
! 646: }
! 647:
! 648: static void
! 649: LcpLayerStart(Fsm fp)
! 650: {
! 651: Link l = (Link)fp->arg;
! 652:
! 653: LinkNgInit(l);
! 654: if (!TimerStarted(&l->openTimer))
! 655: PhysOpen(l);
! 656: }
! 657:
! 658: static void
! 659: LcpStopActivity(Link l)
! 660: {
! 661: AuthStop(l);
! 662: }
! 663:
! 664: static void
! 665: LcpLayerFinish(Fsm fp)
! 666: {
! 667: Link l = (Link)fp->arg;
! 668:
! 669: LcpStopActivity(l);
! 670: if (!l->rep) {
! 671: PhysClose(l);
! 672: LinkNgShutdown(l);
! 673: }
! 674: }
! 675:
! 676: /*
! 677: * LcpLayerDown()
! 678: */
! 679:
! 680: static void
! 681: LcpLayerDown(Fsm fp)
! 682: {
! 683: Link l = (Link)fp->arg;
! 684: LcpStopActivity(l);
! 685: }
! 686:
! 687: void LcpOpen(Link l)
! 688: {
! 689: FsmOpen(&l->lcp.fsm);
! 690: }
! 691:
! 692: void LcpClose(Link l)
! 693: {
! 694: FsmClose(&l->lcp.fsm);
! 695: }
! 696:
! 697: void LcpUp(Link l)
! 698: {
! 699: FsmUp(&l->lcp.fsm);
! 700: }
! 701:
! 702: void LcpDown(Link l)
! 703: {
! 704: FsmDown(&l->lcp.fsm);
! 705: }
! 706:
! 707: /*
! 708: * LcpRecvProtoRej()
! 709: */
! 710:
! 711: static int
! 712: LcpRecvProtoRej(Fsm fp, int proto, Mbuf bp)
! 713: {
! 714: Link l = (Link)fp->arg;
! 715: int fatal = FALSE;
! 716: Fsm rej = NULL;
! 717:
! 718: /* Which protocol? */
! 719: switch (proto) {
! 720: case PROTO_CCP:
! 721: case PROTO_COMPD:
! 722: rej = l->bund ? &l->bund->ccp.fsm : NULL;
! 723: break;
! 724: case PROTO_ECP:
! 725: case PROTO_CRYPT:
! 726: rej = l->bund ? &l->bund->ecp.fsm : NULL;
! 727: break;
! 728: case PROTO_IPCP:
! 729: rej = l->bund ? &l->bund->ipcp.fsm : NULL;
! 730: break;
! 731: case PROTO_IPV6CP:
! 732: rej = l->bund ? &l->bund->ipv6cp.fsm : NULL;
! 733: break;
! 734: default:
! 735: break;
! 736: }
! 737:
! 738: /* Turn off whatever protocol got rejected */
! 739: if (rej)
! 740: FsmFailure(rej, FAIL_WAS_PROTREJ);
! 741: return(fatal);
! 742: }
! 743:
! 744: /*
! 745: * LcpRecvIdent()
! 746: */
! 747:
! 748: static void
! 749: LcpRecvIdent(Fsm fp, Mbuf bp)
! 750: {
! 751: Link l = (Link)fp->arg;
! 752: int len, clen;
! 753:
! 754: if (bp == NULL)
! 755: return;
! 756:
! 757: if (l->lcp.peer_ident[0] != 0)
! 758: strlcat(l->lcp.peer_ident, " ", sizeof(l->lcp.peer_ident));
! 759:
! 760: len = strlen(l->lcp.peer_ident);
! 761: clen = sizeof(l->lcp.peer_ident) - len - 1;
! 762: if (clen > MBLEN(bp))
! 763: clen = MBLEN(bp);
! 764: memcpy(l->lcp.peer_ident + len, (char *) MBDATAU(bp), clen);
! 765: l->lcp.peer_ident[len + clen] = 0;
! 766: }
! 767:
! 768: /*
! 769: * LcpFailure()
! 770: */
! 771:
! 772: static void
! 773: LcpFailure(Fsm fp, enum fsmfail reason)
! 774: {
! 775: Link l = (Link)fp->arg;
! 776: char buf[100];
! 777:
! 778: snprintf(buf, sizeof(buf), STR_LCP_FAILED, FsmFailureStr(reason));
! 779: RecordLinkUpDownReason(NULL, l, 0, reason == FAIL_ECHO_TIMEOUT ?
! 780: STR_ECHO_TIMEOUT : STR_PROTO_ERR, "%s", buf);
! 781: }
! 782:
! 783: /*
! 784: * LcpDecodeConfig()
! 785: */
! 786:
! 787: static void
! 788: LcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
! 789: {
! 790: Link l = (Link)fp->arg;
! 791: LcpState const lcp = &l->lcp;
! 792: int k;
! 793:
! 794: /* If we have got request, forget the previous values */
! 795: if (mode == MODE_REQ) {
! 796: lcp->peer_mru = l->conf.mtu;
! 797: lcp->peer_accmap = 0xffffffff;
! 798: lcp->peer_acfcomp = FALSE;
! 799: lcp->peer_protocomp = FALSE;
! 800: lcp->peer_magic = 0;
! 801: lcp->peer_auth = 0;
! 802: lcp->peer_alg = 0;
! 803: lcp->peer_mrru = 0;
! 804: lcp->peer_shortseq = FALSE;
! 805: }
! 806:
! 807: /* Decode each config option */
! 808: for (k = 0; k < num; k++) {
! 809: FsmOption const opt = &list[k];
! 810: FsmOptInfo const oi = FsmFindOptInfo(gLcpConfOpts, opt->type);
! 811:
! 812: /* Check option */
! 813: if (!oi) {
! 814: Log(LG_LCP, ("[%s] UNKNOWN[%d] len=%d", l->name, opt->type, opt->len));
! 815: if (mode == MODE_REQ)
! 816: FsmRej(fp, opt);
! 817: continue;
! 818: }
! 819: if (!oi->supported) {
! 820: Log(LG_LCP, ("[%s] %s", l->name, oi->name));
! 821: if (mode == MODE_REQ) {
! 822: Log(LG_LCP, ("[%s] Not supported", l->name));
! 823: FsmRej(fp, opt);
! 824: }
! 825: continue;
! 826: }
! 827: if (opt->len < oi->minLen + 2 || opt->len > oi->maxLen + 2) {
! 828: Log(LG_LCP, ("[%s] %s", l->name, oi->name));
! 829: if (mode == MODE_REQ) {
! 830: Log(LG_LCP, ("[%s] Bogus length=%d", l->name, opt->len));
! 831: FsmRej(fp, opt);
! 832: }
! 833: continue;
! 834: }
! 835:
! 836: /* Do whatever */
! 837: switch (opt->type) {
! 838: case TY_MRU: /* link MRU */
! 839: {
! 840: u_int16_t mru;
! 841:
! 842: memcpy(&mru, opt->data, 2);
! 843: mru = ntohs(mru);
! 844: Log(LG_LCP, ("[%s] %s %d", l->name, oi->name, mru));
! 845: switch (mode) {
! 846: case MODE_REQ:
! 847: if (mru < LCP_MIN_MRU) {
! 848: mru = htons(LCP_MIN_MRU);
! 849: memcpy(opt->data, &mru, 2);
! 850: FsmNak(fp, opt);
! 851: break;
! 852: }
! 853: if (mru < lcp->peer_mru)
! 854: lcp->peer_mru = mru;
! 855: FsmAck(fp, opt);
! 856: break;
! 857: case MODE_NAK:
! 858: /* Windows 2000 PPPoE bug workaround */
! 859: if (mru == lcp->want_mru) {
! 860: LCP_PEER_REJ(lcp, opt->type);
! 861: break;
! 862: }
! 863: if (mru >= LCP_MIN_MRU
! 864: && (mru <= l->type->mru || mru < lcp->want_mru))
! 865: lcp->want_mru = mru;
! 866: break;
! 867: case MODE_REJ:
! 868: LCP_PEER_REJ(lcp, opt->type);
! 869: break;
! 870: }
! 871: }
! 872: break;
! 873:
! 874: case TY_ACCMAP: /* async control character escape map */
! 875: {
! 876: u_int32_t accm;
! 877:
! 878: memcpy(&accm, opt->data, 4);
! 879: accm = ntohl(accm);
! 880: Log(LG_LCP, ("[%s] %s 0x%08x", l->name, oi->name, accm));
! 881: switch (mode) {
! 882: case MODE_REQ:
! 883: lcp->peer_accmap = accm;
! 884: FsmAck(fp, opt);
! 885: break;
! 886: case MODE_NAK:
! 887: lcp->want_accmap = accm;
! 888: break;
! 889: case MODE_REJ:
! 890: LCP_PEER_REJ(lcp, opt->type);
! 891: break;
! 892: }
! 893: }
! 894: break;
! 895:
! 896: case TY_AUTHPROTO: /* authentication protocol */
! 897: {
! 898: u_int16_t proto;
! 899: int bogus = 0, i, protoPos = -1;
! 900: LcpAuthProto authProto = NULL;
! 901:
! 902: memcpy(&proto, opt->data, 2);
! 903: proto = ntohs(proto);
! 904:
! 905: /* Display it */
! 906: switch (proto) {
! 907: case PROTO_CHAP:
! 908: if (opt->len >= 5) {
! 909: char buf[20];
! 910: const char *ts;
! 911:
! 912: switch (opt->data[2]) {
! 913: case CHAP_ALG_MD5:
! 914: ts = "MD5";
! 915: break;
! 916: case CHAP_ALG_MSOFT:
! 917: ts = "MSOFT";
! 918: break;
! 919: case CHAP_ALG_MSOFTv2:
! 920: ts = "MSOFTv2";
! 921: break;
! 922: default:
! 923: snprintf(buf, sizeof(buf), "0x%02x", opt->data[2]);
! 924: ts = buf;
! 925: break;
! 926: }
! 927: Log(LG_LCP, ("[%s] %s %s %s", l->name, oi->name, ProtoName(proto), ts));
! 928: break;
! 929: }
! 930: break;
! 931: default:
! 932: Log(LG_LCP, ("[%s] %s %s", l->name, oi->name, ProtoName(proto)));
! 933: break;
! 934: }
! 935:
! 936: /* Sanity check */
! 937: switch (proto) {
! 938: case PROTO_PAP:
! 939: if (opt->len != 4) {
! 940: Log(LG_LCP, ("[%s] Bad len=%d", l->name, opt->len));
! 941: bogus = 1;
! 942: }
! 943: break;
! 944: case PROTO_CHAP:
! 945: if (opt->len != 5) {
! 946: Log(LG_LCP, ("[%s] Bad len=%d", l->name, opt->len));
! 947: bogus = 1;
! 948: }
! 949: break;
! 950: }
! 951: if (!bogus) {
! 952: protoPos = LcpFindAuthProto(proto, proto == PROTO_CHAP ? opt->data[2] : 0);
! 953: authProto = (protoPos == -1) ? NULL : &gLcpAuthProtos[protoPos];
! 954: }
! 955:
! 956: /* Deal with it */
! 957: switch (mode) {
! 958: case MODE_REQ:
! 959:
! 960: /* let us check, whether the requested auth-proto is acceptable */
! 961: if ((authProto != NULL) && Acceptable(&l->conf.options, authProto->conf)) {
! 962: lcp->peer_auth = proto;
! 963: if (proto == PROTO_CHAP)
! 964: lcp->peer_alg = opt->data[2];
! 965: FsmAck(fp, opt);
! 966: break;
! 967: }
! 968:
! 969: /* search an acceptable proto */
! 970: for(i = 0; i < LCP_NUM_AUTH_PROTOS; i++) {
! 971: if (lcp->peer_protos[i] != NULL) {
! 972: FsmNak(fp, LcpAuthProtoNak(lcp->peer_protos[i]->proto, lcp->peer_protos[i]->alg));
! 973: break;
! 974: }
! 975: }
! 976:
! 977: /* no other acceptable auth-proto found */
! 978: if (i == LCP_NUM_AUTH_PROTOS)
! 979: FsmRej(fp, opt);
! 980: break;
! 981:
! 982: case MODE_NAK:
! 983: /* this should never happen */
! 984: if (authProto == NULL)
! 985: break;
! 986:
! 987: /* let us check, whether the requested auth-proto is enabled */
! 988: if (Enabled(&l->conf.options, authProto->conf)) {
! 989: lcp->want_auth = proto;
! 990: if (proto == PROTO_CHAP)
! 991: lcp->want_alg = opt->data[2];
! 992: break;
! 993: }
! 994:
! 995: /* Remove the disabled proto from my list */
! 996: lcp->want_protos[protoPos] = NULL;
! 997:
! 998: /* Search the next enabled proto */
! 999: for(i = 0; i < LCP_NUM_AUTH_PROTOS; i++) {
! 1000: if (lcp->want_protos[i] != NULL) {
! 1001: lcp->want_auth = lcp->want_protos[i]->proto;
! 1002: lcp->want_alg = lcp->want_protos[i]->alg;
! 1003: break;
! 1004: }
! 1005: }
! 1006: break;
! 1007:
! 1008: case MODE_REJ:
! 1009: LCP_PEER_REJ(lcp, opt->type);
! 1010: if (l->originate == LINK_ORIGINATE_LOCAL
! 1011: && Enabled(&l->conf.options, LINK_CONF_NO_ORIG_AUTH)) {
! 1012: lcp->want_auth = 0;
! 1013: }
! 1014: break;
! 1015: }
! 1016: }
! 1017: break;
! 1018:
! 1019: case TY_MRRU: /* multi-link MRRU */
! 1020: {
! 1021: u_int16_t mrru;
! 1022:
! 1023: memcpy(&mrru, opt->data, 2);
! 1024: mrru = ntohs(mrru);
! 1025: Log(LG_LCP, ("[%s] %s %d", l->name, oi->name, mrru));
! 1026: switch (mode) {
! 1027: case MODE_REQ:
! 1028: if (!Enabled(&l->conf.options, LINK_CONF_MULTILINK)) {
! 1029: FsmRej(fp, opt);
! 1030: break;
! 1031: }
! 1032: if (mrru < MP_MIN_MRRU) {
! 1033: mrru = htons(MP_MIN_MRRU);
! 1034: memcpy(opt->data, &mrru, 2);
! 1035: FsmNak(fp, opt);
! 1036: break;
! 1037: }
! 1038: lcp->peer_mrru = mrru;
! 1039: FsmAck(fp, opt);
! 1040: break;
! 1041: case MODE_NAK:
! 1042: {
! 1043: /* Let the peer to change it's mind. */
! 1044: if (LCP_PEER_REJECTED(lcp, opt->type)) {
! 1045: LCP_PEER_UNREJ(lcp, opt->type);
! 1046: if (Enabled(&l->conf.options, LINK_CONF_MULTILINK))
! 1047: lcp->want_mrru = l->conf.mrru;
! 1048: }
! 1049: /* Make sure we don't violate any rules by changing MRRU now */
! 1050: if (mrru > lcp->want_mrru) /* too big */
! 1051: break;
! 1052: if (mrru < MP_MIN_MRRU) /* too small; clip */
! 1053: mrru = MP_MIN_MRRU;
! 1054:
! 1055: /* Update our links */
! 1056: lcp->want_mrru = mrru;
! 1057: }
! 1058: break;
! 1059: case MODE_REJ:
! 1060: lcp->want_mrru = 0;
! 1061: LCP_PEER_REJ(lcp, opt->type);
! 1062: break;
! 1063: }
! 1064: }
! 1065: break;
! 1066:
! 1067: case TY_SHORTSEQNUM: /* multi-link short sequence numbers */
! 1068: Log(LG_LCP, ("[%s] %s", l->name, oi->name));
! 1069: switch (mode) {
! 1070: case MODE_REQ:
! 1071: if (!Enabled(&l->conf.options, LINK_CONF_MULTILINK) ||
! 1072: !Acceptable(&l->conf.options, LINK_CONF_SHORTSEQ)) {
! 1073: FsmRej(fp, opt);
! 1074: break;
! 1075: }
! 1076: lcp->peer_shortseq = TRUE;
! 1077: FsmAck(fp, opt);
! 1078: break;
! 1079: case MODE_NAK:
! 1080: /* Let the peer to change it's mind. */
! 1081: if (LCP_PEER_REJECTED(lcp, opt->type)) {
! 1082: LCP_PEER_UNREJ(lcp, opt->type);
! 1083: if (Enabled(&l->conf.options, LINK_CONF_MULTILINK))
! 1084: lcp->want_shortseq = Enabled(&l->conf.options, LINK_CONF_SHORTSEQ);
! 1085: }
! 1086: break;
! 1087: case MODE_REJ:
! 1088: lcp->want_shortseq = FALSE;
! 1089: LCP_PEER_REJ(lcp, opt->type);
! 1090: break;
! 1091: }
! 1092: break;
! 1093:
! 1094: case TY_ENDPOINTDISC: /* multi-link endpoint discriminator */
! 1095: {
! 1096: struct discrim dis;
! 1097: char buf[64];
! 1098:
! 1099: if (opt->len < 3 || opt->len > sizeof(dis.bytes)) {
! 1100: Log(LG_LCP, ("[%s] %s bad len=%d", l->name, oi->name, opt->len));
! 1101: if (mode == MODE_REQ)
! 1102: FsmRej(fp, opt);
! 1103: break;
! 1104: }
! 1105: memcpy(&dis.class, opt->data, opt->len - 2);
! 1106: dis.len = opt->len - 3;
! 1107: Log(LG_LCP, ("[%s] %s %s", l->name, oi->name, MpDiscrimText(&dis, buf, sizeof(buf))));
! 1108: switch (mode) {
! 1109: case MODE_REQ:
! 1110: lcp->peer_discrim = dis;
! 1111: FsmAck(fp, opt);
! 1112: break;
! 1113: case MODE_NAK:
! 1114: /* Let the peer to change it's mind. */
! 1115: LCP_PEER_UNREJ(lcp, opt->type);
! 1116: break;
! 1117: case MODE_REJ:
! 1118: LCP_PEER_REJ(lcp, opt->type);
! 1119: break;
! 1120: }
! 1121: }
! 1122: break;
! 1123:
! 1124: case TY_MAGICNUM: /* magic number */
! 1125: {
! 1126: u_int32_t magic;
! 1127:
! 1128: memcpy(&magic, opt->data, 4);
! 1129: magic = ntohl(magic);
! 1130: Log(LG_LCP, ("[%s] %s %08x", l->name, oi->name, magic));
! 1131: switch (mode) {
! 1132: case MODE_REQ:
! 1133: if (lcp->want_magic) {
! 1134: if (magic == lcp->want_magic) {
! 1135: Log(LG_LCP, ("[%s] Same magic! Detected loopback condition", l->name));
! 1136: magic = htonl(~magic);
! 1137: memcpy(opt->data, &magic, 4);
! 1138: FsmNak(fp, opt);
! 1139: break;
! 1140: }
! 1141: lcp->peer_magic = magic;
! 1142: FsmAck(fp, opt);
! 1143: break;
! 1144: }
! 1145: FsmRej(fp, opt);
! 1146: break;
! 1147: case MODE_NAK:
! 1148: lcp->want_magic = GenerateMagic();
! 1149: break;
! 1150: case MODE_REJ:
! 1151: lcp->want_magic = 0;
! 1152: LCP_PEER_REJ(lcp, opt->type);
! 1153: break;
! 1154: }
! 1155: }
! 1156: break;
! 1157:
! 1158: case TY_PROTOCOMP: /* Protocol field compression */
! 1159: Log(LG_LCP, ("[%s] %s", l->name, oi->name));
! 1160: switch (mode) {
! 1161: case MODE_REQ:
! 1162: if (Acceptable(&l->conf.options, LINK_CONF_PROTOCOMP)) {
! 1163: lcp->peer_protocomp = TRUE;
! 1164: FsmAck(fp, opt);
! 1165: break;
! 1166: }
! 1167: FsmRej(fp, opt);
! 1168: break;
! 1169: case MODE_NAK: /* a NAK here doesn't make sense */
! 1170: case MODE_REJ:
! 1171: lcp->want_protocomp = FALSE;
! 1172: LCP_PEER_REJ(lcp, opt->type);
! 1173: break;
! 1174: }
! 1175: break;
! 1176:
! 1177: case TY_ACFCOMP: /* Address field compression */
! 1178: Log(LG_LCP, ("[%s] %s", l->name, oi->name));
! 1179: switch (mode) {
! 1180: case MODE_REQ:
! 1181: if (Acceptable(&l->conf.options, LINK_CONF_ACFCOMP)) {
! 1182: lcp->peer_acfcomp = TRUE;
! 1183: FsmAck(fp, opt);
! 1184: break;
! 1185: }
! 1186: FsmRej(fp, opt);
! 1187: break;
! 1188: case MODE_NAK: /* a NAK here doesn't make sense */
! 1189: case MODE_REJ:
! 1190: lcp->want_acfcomp = FALSE;
! 1191: LCP_PEER_REJ(lcp, opt->type);
! 1192: break;
! 1193: }
! 1194: break;
! 1195:
! 1196: case TY_CALLBACK: /* Callback */
! 1197: Log(LG_LCP, ("[%s] %s %d", l->name, oi->name, opt->data[0]));
! 1198: switch (mode) {
! 1199: case MODE_REQ: /* we only support peer calling us back */
! 1200: FsmRej(fp, opt);
! 1201: break;
! 1202: case MODE_NAK: /* we only know one way to do it */
! 1203: /* fall through */
! 1204: case MODE_REJ:
! 1205: lcp->want_callback = FALSE;
! 1206: LCP_PEER_REJ(lcp, opt->type);
! 1207: break;
! 1208: }
! 1209: break;
! 1210:
! 1211: case TY_VENDOR:
! 1212: {
! 1213: Log(LG_LCP, ("[%s] %s %02x%02x%02x:%d", l->name, oi->name,
! 1214: opt->data[0], opt->data[1], opt->data[2], opt->data[3]));
! 1215: switch (mode) {
! 1216: case MODE_REQ:
! 1217: FsmRej(fp, opt);
! 1218: break;
! 1219: case MODE_NAK:
! 1220: /* fall through */
! 1221: case MODE_REJ:
! 1222: LCP_PEER_REJ(lcp, opt->type);
! 1223: break;
! 1224: }
! 1225: break;
! 1226: }
! 1227: break;
! 1228:
! 1229: default:
! 1230: assert(0);
! 1231: }
! 1232: }
! 1233: }
! 1234:
! 1235: /*
! 1236: * LcpInput()
! 1237: */
! 1238:
! 1239: void
! 1240: LcpInput(Link l, Mbuf bp)
! 1241: {
! 1242: FsmInput(&l->lcp.fsm, bp);
! 1243: }
! 1244:
! 1245: static const struct fsmoption *
! 1246: LcpAuthProtoNak(ushort proto, u_char alg)
! 1247: {
! 1248: static const u_char chapmd5cf[] =
! 1249: { PROTO_CHAP >> 8, PROTO_CHAP & 0xff, CHAP_ALG_MD5 };
! 1250: static const struct fsmoption chapmd5Nak =
! 1251: { TY_AUTHPROTO, 2 + sizeof(chapmd5cf), (u_char *) chapmd5cf };
! 1252:
! 1253: static const u_char chapmsv1cf[] =
! 1254: { PROTO_CHAP >> 8, PROTO_CHAP & 0xff, CHAP_ALG_MSOFT };
! 1255: static const struct fsmoption chapmsv1Nak =
! 1256: { TY_AUTHPROTO, 2 + sizeof(chapmsv1cf), (u_char *) chapmsv1cf };
! 1257:
! 1258: static const u_char chapmsv2cf[] =
! 1259: { PROTO_CHAP >> 8, PROTO_CHAP & 0xff, CHAP_ALG_MSOFTv2 };
! 1260: static const struct fsmoption chapmsv2Nak =
! 1261: { TY_AUTHPROTO, 2 + sizeof(chapmsv2cf), (u_char *) chapmsv2cf };
! 1262:
! 1263: static const u_char papcf[] =
! 1264: { PROTO_PAP >> 8, PROTO_PAP & 0xff };
! 1265: static const struct fsmoption papNak =
! 1266: { TY_AUTHPROTO, 2 + sizeof(papcf), (u_char *) papcf };
! 1267:
! 1268: static const u_char eapcf[] =
! 1269: { PROTO_EAP >> 8, PROTO_EAP & 0xff };
! 1270: static const struct fsmoption eapNak =
! 1271: { TY_AUTHPROTO, 2 + sizeof(eapcf), (u_char *) eapcf };
! 1272:
! 1273: if (proto == PROTO_PAP) {
! 1274: return &papNak;
! 1275: } else if (proto == PROTO_EAP) {
! 1276: return &eapNak;
! 1277: } else {
! 1278: switch (alg) {
! 1279: case CHAP_ALG_MSOFTv2:
! 1280: return &chapmsv2Nak;
! 1281:
! 1282: case CHAP_ALG_MSOFT:
! 1283: return &chapmsv1Nak;
! 1284:
! 1285: case CHAP_ALG_MD5:
! 1286: return &chapmd5Nak;
! 1287:
! 1288: default:
! 1289: return NULL;
! 1290: }
! 1291: }
! 1292:
! 1293: }
! 1294:
! 1295: /*
! 1296: * LcpFindAuthProto()
! 1297: *
! 1298: */
! 1299: static short
! 1300: LcpFindAuthProto(ushort proto, u_char alg)
! 1301: {
! 1302: int i;
! 1303:
! 1304: for(i = 0; i < LCP_NUM_AUTH_PROTOS; i++) {
! 1305: if (gLcpAuthProtos[i].proto == proto && gLcpAuthProtos[i].alg == alg) {
! 1306: return i;
! 1307: }
! 1308: }
! 1309:
! 1310: return -1;
! 1311:
! 1312: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>