Annotation of embedaddon/mpd/src/lcp.c, revision 1.1.1.3

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>