Annotation of embedaddon/mpd/src/lcp.c, revision 1.1.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, &lt->lcp, sizeof(*lcp));
                    197:   FsmInst(&lcp->fsm, &lt->lcp.fsm, l);
                    198:   AuthInst(&lcp->auth, &lt->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>