File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / lcp.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:39:23 2021 UTC (4 years ago) by misho
Branches: mpd, MAIN
CVS tags: v5_9p16, v5_9, HEAD
mpd 5.9

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

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