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

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