xref: /freebsd/usr.sbin/ppp/lcp.c (revision b5b2a90624d3d900a42e99758eb95293d04f37fa)
1 /*
2  *	      PPP Link Control Protocol (LCP) Module
3  *
4  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5  *
6  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the Internet Initiative Japan, Inc.  The name of the
14  * IIJ may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * $Id$
21  *
22  * TODO:
23  *      o Validate magic number received from peer.
24  *	o Limit data field length by MRU
25  */
26 #include <sys/time.h>
27 #include "fsm.h"
28 #include "lcp.h"
29 #include "ipcp.h"
30 #include "lcpproto.h"
31 #include "os.h"
32 #include "hdlc.h"
33 #include "ccp.h"
34 #include "lqr.h"
35 #include "phase.h"
36 #include "vars.h"
37 #include "auth.h"
38 #include <arpa/inet.h>
39 
40 extern void IpcpUp();
41 extern void IpcpOpen();
42 extern void StartPapChallenge();
43 extern void StartChapChallenge();
44 extern void SetLinkParams(struct lcpstate *);
45 extern void Prompt();
46 extern void StopIdleTimer();
47 extern void OsLinkdown();
48 extern void Cleanup();
49 extern struct pppTimer IpcpReportTimer;
50 
51 struct lcpstate LcpInfo;
52 
53 static void LcpSendConfigReq __P((struct fsm *));
54 static void LcpSendTerminateReq __P((struct fsm *fp));
55 static void LcpSendTerminateAck __P((struct fsm *fp));
56 static void LcpDecodeConfig __P((u_char *cp, int flen,int mode));
57 static void LcpInitRestartCounter __P((struct fsm *));
58 static void LcpLayerUp __P((struct fsm *));
59 static void LcpLayerDown __P((struct fsm *));
60 static void LcpLayerStart __P((struct fsm *));
61 static void LcpLayerFinish __P((struct fsm *));
62 
63 extern int ModemSpeed();
64 
65 #define	REJECTED(p, x)	(p->his_reject & (1<<x))
66 
67 static char *cftypes[] = {
68   "???", "MRU", "ACCMAP", "AUTHPROTO", "QUALPROTO", "MAGICNUM",
69   "RESERVED", "PROTOCOMP", "ACFCOMP", "FCSALT", "SDP",
70 };
71 
72 struct fsm LcpFsm = {
73   "LCP",			/* Name of protocol */
74   PROTO_LCP,			/* Protocol Number */
75   LCP_MAXCODE,
76   OPEN_ACTIVE,
77   ST_INITIAL,			/* State of machine */
78   0, 0, 0,
79 
80   0,
81   { 0, 0, 0, NULL, NULL, NULL },
82 
83   LcpLayerUp,
84   LcpLayerDown,
85   LcpLayerStart,
86   LcpLayerFinish,
87   LcpInitRestartCounter,
88   LcpSendConfigReq,
89   LcpSendTerminateReq,
90   LcpSendTerminateAck,
91   LcpDecodeConfig,
92 };
93 
94 static struct pppTimer LcpReportTimer;
95 
96 char *PhaseNames[] = {
97   "Dead", "Establish", "Authenticate", "Network", "Terminate"
98 };
99 
100 void
101 NewPhase(new)
102 int new;
103 {
104   struct lcpstate *lcp = &LcpInfo;
105 
106   phase = new;
107   LogPrintf(LOG_PHASE_BIT, "Phase: %s\n", PhaseNames[phase]);
108   switch (phase) {
109   case PHASE_AUTHENTICATE:
110     lcp->auth_ineed = lcp->want_auth;
111     lcp->auth_iwait = lcp->his_auth;
112     if (lcp->his_auth || lcp->want_auth) {
113       LogPrintf(LOG_PHASE_BIT, " his = %x, mine = %x\n", lcp->his_auth, lcp->want_auth);
114       if (lcp->his_auth == PROTO_PAP)
115 	StartAuthChallenge(&AuthPapInfo);
116       if (lcp->want_auth == PROTO_CHAP)
117 	StartAuthChallenge(&AuthChapInfo);
118     } else
119       NewPhase(PHASE_NETWORK);
120     break;
121   case PHASE_NETWORK:
122     IpcpUp();
123     IpcpOpen();
124     CcpUp();
125     CcpOpen();
126     break;
127   case PHASE_DEAD:
128     if (mode & MODE_DIRECT)
129       Cleanup(EX_DEAD);
130     break;
131   }
132 }
133 
134 static void
135 LcpReportTime()
136 {
137 #ifdef VERBOSE
138   time_t t;
139 
140   time(&t);
141   logprintf("%s", ctime(&t));
142 #endif
143   StopTimer(&LcpReportTimer);
144   LcpReportTimer.state = TIMER_STOPPED;
145   StartTimer(&LcpReportTimer);
146   HdlcErrorCheck();
147 }
148 
149 int
150 ReportLcpStatus()
151 {
152   struct lcpstate *lcp = &LcpInfo;
153   struct fsm *fp = &LcpFsm;
154 
155   printf("%s [%s]\n", fp->name, StateNames[fp->state]);
156   printf(
157     " his side: MRU %ld, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d MAGIC %08lx\n",
158     lcp->his_mru, lcp->his_accmap, lcp->his_protocomp, lcp->his_acfcomp, lcp->his_magic);
159   printf(
160     " my  side: MRU %ld, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d MAGIC %08lx\n",
161     lcp->want_mru, lcp->want_accmap, lcp->want_protocomp, lcp->want_acfcomp, lcp->want_magic);
162   printf("\nDefaults:   MRU = %ld, ACCMAP = %08x\t", VarMRU, VarAccmap);
163   printf("Open Mode: %s\n", (VarOpenMode == OPEN_ACTIVE)? "active" : "passive");
164   return(1);
165 }
166 
167 /*
168  * Generate random number which will be used as magic number.
169  */
170 u_long
171 GenerateMagic()
172 {
173   time_t tl;
174   struct timeval tval;
175 
176   time(&tl);
177   gettimeofday(&tval, NULL);
178   tl += (tval.tv_sec ^ tval.tv_usec) + getppid();
179   tl *= getpid();
180   return(tl);
181 }
182 
183 void
184 LcpInit()
185 {
186   struct lcpstate *lcp = &LcpInfo;
187 
188   FsmInit(&LcpFsm);
189   HdlcInit();
190 
191   bzero(lcp, sizeof(struct lcpstate));
192   lcp->want_mru = VarMRU;
193   lcp->his_mru = DEF_MRU;
194   lcp->his_accmap = 0xffffffff;
195   lcp->want_accmap = VarAccmap;
196   lcp->want_magic = GenerateMagic();
197   lcp->want_auth = lcp->his_auth = 0;
198   if (Enabled(ConfChap))
199     lcp->want_auth = PROTO_CHAP;
200   else if (Enabled(ConfPap))
201     lcp->want_auth = PROTO_PAP;
202   if (Enabled(ConfLqr)) lcp->want_lqrperiod = VarLqrTimeout * 100;
203   if (Enabled(ConfAcfcomp)) lcp->want_acfcomp = 1;
204   if (Enabled(ConfProtocomp)) lcp->want_protocomp = 1;
205   LcpFsm.maxconfig = 10;
206 }
207 
208 static void
209 LcpInitRestartCounter(fp)
210 struct fsm *fp;
211 {
212   fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
213   fp->restart = 5;
214 }
215 
216 void
217 PutConfValue(cpp, types, type, len, val)
218 u_char **cpp;
219 char **types;
220 u_char type;
221 int len;
222 u_long val;
223 {
224   u_char *cp;
225   struct in_addr ina;
226 
227   cp = *cpp;
228   *cp++ = type; *cp++ = len;
229   if (len == 6) {
230     if (type == TY_IPADDR) {
231       ina.s_addr = htonl(val);
232       LogPrintf(LOG_LCP_BIT, " %s [%d] %s\n",
233 	types[type], len, inet_ntoa(ina));
234     } else {
235       LogPrintf(LOG_LCP_BIT, " %s [%d] %08x\n", types[type], len, val);
236     }
237     *cp++ = (val >> 24) & 0377;
238     *cp++ = (val >> 16) & 0377;
239   } else
240     LogPrintf(LOG_LCP_BIT, " %s [%d] %d\n", types[type], len, val);
241   *cp++ = (val >> 8) & 0377;
242   *cp++ = val & 0377;
243   *cpp = cp;
244 }
245 
246 static void
247 LcpSendConfigReq(fp)
248 struct fsm *fp;
249 {
250   u_char *cp;
251   struct lcpstate *lcp = &LcpInfo;
252   struct lqrreq *req;
253 
254   LogPrintf(LOG_LCP_BIT, "%s: SendConfigReq\n", fp->name);
255   cp = ReqBuff;
256   if (!DEV_IS_SYNC) {
257     if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP)) {
258       *cp++ = TY_ACFCOMP; *cp++ = 2;
259       LogPrintf(LOG_LCP_BIT, " %s\n", cftypes[TY_ACFCOMP]);
260     }
261     if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP)) {
262       *cp++ = TY_PROTOCOMP; *cp++ = 2;
263       LogPrintf(LOG_LCP_BIT, " %s\n", cftypes[TY_PROTOCOMP]);
264     }
265     if (!REJECTED(lcp, TY_ACCMAP))
266       PutConfValue(&cp, cftypes, TY_ACCMAP, 6, lcp->want_accmap);
267   }
268   if (!REJECTED(lcp, TY_MRU))
269     PutConfValue(&cp, cftypes, TY_MRU, 4, lcp->want_mru);
270   if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM))
271     PutConfValue(&cp, cftypes, TY_MAGICNUM, 6, lcp->want_magic);
272   if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
273     req = (struct lqrreq *)cp;
274     req->type = TY_QUALPROTO; req->length = sizeof(struct lqrreq);
275     req->proto = htons(PROTO_LQR);
276     req->period = htonl(lcp->want_lqrperiod);
277     cp += sizeof(struct lqrreq);
278     LogPrintf(LOG_LCP_BIT, " %s (%d)\n", cftypes[TY_QUALPROTO], lcp->want_lqrperiod);
279   }
280   switch (lcp->want_auth) {
281   case PROTO_PAP:
282     PutConfValue(&cp, cftypes, TY_AUTHPROTO, 4, lcp->want_auth);
283     break;
284   case PROTO_CHAP:
285     PutConfValue(&cp, cftypes, TY_AUTHPROTO, 5, lcp->want_auth);
286     *cp++ = 5;		/* Use MD5 */
287     break;
288   }
289   FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
290 }
291 
292 void
293 LcpSendProtoRej(option, count)
294 u_char *option;
295 int count;
296 {
297   struct fsm *fp = &LcpFsm;
298 
299   LogPrintf(LOG_LCP_BIT, "%s: SendProtoRej\n", fp->name);
300   FsmOutput(fp, CODE_PROTOREJ, fp->reqid, option, count);
301 }
302 
303 static void
304 LcpSendTerminateReq(fp)
305 struct fsm *fp;
306 {
307    /* Most thins are done in fsm layer. Nothing to to. */
308 }
309 
310 static void
311 LcpSendTerminateAck(fp)
312 struct fsm *fp;
313 {
314   LogPrintf(LOG_LCP_BIT, "%s: SendTerminateAck.\n", fp->name);
315   FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
316 }
317 
318 static void
319 LcpLayerStart(fp)
320 struct fsm *fp;
321 {
322   LogPrintf(LOG_LCP_BIT, "%s: LayerStart\n", fp->name);
323   NewPhase(PHASE_ESTABLISH);
324 }
325 
326 static void
327 StopAllTimers()
328 {
329   StopTimer(&LcpReportTimer);
330   StopTimer(&IpcpReportTimer);
331   StopIdleTimer();
332   StopTimer(&AuthPapInfo.authtimer);
333   StopTimer(&AuthChapInfo.authtimer);
334   StopLqrTimer();
335 }
336 
337 static void
338 LcpLayerFinish(fp)
339 struct fsm *fp;
340 {
341 #ifdef VERBOSE
342   fprintf(stderr, "%s: LayerFinish\r\n", fp->name);
343 #endif
344   Prompt(1);
345   LogPrintf(LOG_LCP_BIT, "%s: LayerFinish\n", fp->name);
346 #ifdef notdef
347   OsCloseLink(0);
348 #else
349   OsCloseLink(1);
350 #endif
351   NewPhase(PHASE_DEAD);
352   StopAllTimers();
353   OsInterfaceDown(0);
354 }
355 
356 static void
357 LcpLayerUp(fp)
358 struct fsm *fp;
359 {
360   LogPrintf(LOG_LCP_BIT, "%s: LayerUp\n", fp->name);
361   OsSetInterfaceParams(23, LcpInfo.his_mru, ModemSpeed());
362   SetLinkParams(&LcpInfo);
363 
364   NewPhase(PHASE_AUTHENTICATE);
365 
366   StartLqm();
367   StopTimer(&LcpReportTimer);
368   LcpReportTimer.state = TIMER_STOPPED;
369   LcpReportTimer.load = 60 * SECTICKS;
370   LcpReportTimer.func = LcpReportTime;
371   StartTimer(&LcpReportTimer);
372 }
373 
374 static void
375 LcpLayerDown(fp)
376 struct fsm *fp;
377 {
378   LogPrintf(LOG_LCP_BIT, "%s: LayerDown\n", fp->name);
379   StopAllTimers();
380   OsLinkdown();
381   NewPhase(PHASE_TERMINATE);
382   Prompt(1);
383 }
384 
385 void
386 LcpUp()
387 {
388   FsmUp(&LcpFsm);
389 }
390 
391 void
392 LcpDown()			/* Sudden death */
393 {
394   NewPhase(PHASE_DEAD);
395   StopAllTimers();
396   FsmDown(&LcpFsm);
397 }
398 
399 void
400 LcpOpen(mode)
401 int mode;
402 {
403   LcpFsm.open_mode = mode;
404   FsmOpen(&LcpFsm);
405 }
406 
407 void
408 LcpClose()
409 {
410   FsmClose(&LcpFsm);
411 }
412 
413 /*
414  *	XXX: Should validate option length
415  */
416 static void
417 LcpDecodeConfig(cp, plen, mode)
418 u_char *cp;
419 int plen;
420 int mode;
421 {
422   char *request;
423   int type, length, mru;
424   u_long *lp, magic, accmap;
425   u_short *sp, proto;
426   struct lqrreq *req;
427 
428   ackp = AckBuff;
429   nakp = NakBuff;
430   rejp = RejBuff;
431 
432   while (plen >= sizeof(struct fsmconfig)) {
433     type = *cp;
434     length = cp[1];
435     if (type <= TY_ACFCOMP)
436       request = cftypes[type];
437     else
438       request = "???";
439 
440     switch (type) {
441     case TY_MRU:
442       sp = (u_short *)(cp + 2);
443       mru = htons(*sp);
444       LogPrintf(LOG_LCP_BIT, " %s %d\n", request, mru);
445 
446       switch (mode) {
447       case MODE_REQ:
448 	if (mru > MAX_MRU) {
449 	  *sp = htons(MAX_MRU);
450 	  bcopy(cp, nakp, 4); nakp += 4;
451 	} else if (mru < MIN_MRU) {
452 	  *sp = htons(MIN_MRU);
453 	  bcopy(cp, nakp, 4); nakp += 4;
454 	} else {
455 	  LcpInfo.his_mru = mru;
456 	  bcopy(cp, ackp, 4); ackp += 4;
457 	}
458 	break;
459       case MODE_NAK:
460 	if (mru >= MIN_MRU || mru <= MAX_MRU)
461 	  LcpInfo.want_mru = mru;
462 	break;
463       case MODE_REJ:
464 	LcpInfo.his_reject |= (1 << type);
465 	break;
466       }
467       break;
468     case TY_ACCMAP:
469       lp = (u_long *)(cp + 2);
470       accmap = htonl(*lp);
471       LogPrintf(LOG_LCP_BIT, " %s %08x\n", request, accmap);
472 
473       switch (mode) {
474       case MODE_REQ:
475 	LcpInfo.his_accmap = accmap;
476 	bcopy(cp, ackp, 6); ackp += 6;
477 	break;
478       case MODE_NAK:
479 	LcpInfo.want_accmap = accmap;
480 	break;
481       case MODE_REJ:
482 	LcpInfo.his_reject |= (1 << type);
483 	break;
484       }
485       break;
486     case TY_AUTHPROTO:
487       sp = (u_short *)(cp + 2);
488       proto = ntohs(*sp);
489       LogPrintf(LOG_LCP_BIT, " %s proto = %04x\n", request, proto);
490 
491       switch (mode) {
492       case MODE_REQ:
493 	switch (proto) {
494 	case PROTO_PAP:
495 	  if (length != 4) {
496 	    LogPrintf(LOG_LCP_BIT, " %s bad length (%d)\n", request, length);
497 	    goto reqreject;
498 	  }
499 	  if (Acceptable(ConfPap)) {
500 	    LcpInfo.his_auth = proto;
501 	    bcopy(cp, ackp, length); ackp += length;
502 	  } else if (Acceptable(ConfChap)) {
503 	    *nakp++ = *cp; *nakp++ = 5;
504 	    *nakp++ = (unsigned char)(PROTO_CHAP >> 8);
505 	    *nakp++ = (unsigned char)PROTO_CHAP;
506 	    *nakp++ = 5;
507 	  } else
508 	    goto reqreject;
509 	  break;
510 	case PROTO_CHAP:
511 	  if (length < 5) {
512 	    LogPrintf(LOG_LCP_BIT, " %s bad length (%d)\n", request, length);
513 	    goto reqreject;
514 	  }
515 	  if (Acceptable(ConfChap) && cp[4] == 5) {
516 	    LcpInfo.his_auth = proto;
517 	    bcopy(cp, ackp, length); ackp += length;
518 	  } else if (Acceptable(ConfPap)) {
519 	    *nakp++ = *cp; *nakp++ = 4;
520 	    *nakp++ = (unsigned char)(PROTO_PAP >> 8);
521 	    *nakp++ = (unsigned char)PROTO_PAP;
522 	  } else
523 	    goto reqreject;
524 	  break;
525 	default:
526  	    LogPrintf(LOG_LCP_BIT, " %s not implemented, NAK.\n", request);
527             bcopy(cp, nakp, length);
528             nakp += length;
529             break;
530 	}
531 	break;
532       case MODE_NAK:
533 	break;
534       case MODE_REJ:
535 	LcpInfo.his_reject |= (1 << type);
536 	break;
537       }
538       break;
539     case TY_QUALPROTO:
540       req = (struct lqrreq *)cp;
541       LogPrintf(LOG_LCP_BIT, " %s proto: %x, interval: %dms\n",
542 		request, ntohs(req->proto), ntohl(req->period)*10);
543       switch (mode) {
544       case MODE_REQ:
545 	if (ntohs(req->proto) != PROTO_LQR || !Acceptable(ConfLqr))
546 	  goto reqreject;
547 	else {
548 	  LcpInfo.his_lqrperiod = ntohl(req->period);
549 	  if (LcpInfo.his_lqrperiod < 500)
550 	    LcpInfo.his_lqrperiod = 500;
551 	  req->period = htonl(LcpInfo.his_lqrperiod);
552 	  bcopy(cp, ackp, length); ackp += length;
553 	}
554 	break;
555       case MODE_NAK:
556 	break;
557       case MODE_REJ:
558 	LcpInfo.his_reject |= (1 << type);
559 	break;
560       }
561       break;
562     case TY_MAGICNUM:
563       lp = (u_long *)(cp + 2);
564       magic = ntohl(*lp);
565       LogPrintf(LOG_LCP_BIT, " %s %08x\n", request, magic);
566 
567       switch (mode) {
568       case MODE_REQ:
569 	if (LcpInfo.want_magic) {
570 	  /* XXX: Shoud validate magic number */
571 	  if (magic == LcpInfo.want_magic)
572 	    logprintf("magic is same!! %x, %x, %x\n",
573 		magic, LcpInfo.want_magic, LcpInfo.his_magic);
574 	  LcpInfo.his_magic = magic;
575 	  bcopy(cp, ackp, length); ackp += length;
576 	} else {
577 	  LcpInfo.my_reject |= (1 << type);
578 	  goto reqreject;
579 	}
580 	break;
581       case MODE_NAK:
582 	LogPrintf(LOG_LCP_BIT, " %s magic %08x has NAKed\n", request, magic);
583 	LcpInfo.want_magic = GenerateMagic();
584 	break;
585       case MODE_REJ:
586 	LogPrintf(LOG_LCP_BIT, " %s magic has REJected\n", request);
587 	LcpInfo.want_magic = 0;
588 	LcpInfo.his_reject |= (1 << type);
589 	break;
590       }
591       break;
592     case TY_PROTOCOMP:
593       LogPrintf(LOG_LCP_BIT, " %s\n", request);
594 
595       switch (mode) {
596       case MODE_REQ:
597         if (Acceptable(ConfProtocomp)) {
598 	  LcpInfo.his_protocomp = 1;
599 	  bcopy(cp, ackp, 2); ackp += 2;
600         } else {
601 #ifdef OLDMST
602 	  /*
603 	   * MorningStar before v1.3 needs NAK
604 	   */
605 	  bcopy(cp, nakp, 2); nakp += 2;
606 #else
607 	  bcopy(cp, rejp, 2); rejp += 2;
608 	  LcpInfo.my_reject |= (1 << type);
609 #endif
610         }
611 	break;
612       case MODE_NAK:
613       case MODE_REJ:
614 	LcpInfo.want_protocomp = 0;
615 	LcpInfo.his_reject |= (1 << type);
616 	break;
617       }
618       break;
619     case TY_ACFCOMP:
620       LogPrintf(LOG_LCP_BIT, " %s\n", request);
621       switch (mode) {
622       case MODE_REQ:
623         if (Acceptable(ConfAcfcomp)) {
624 	  LcpInfo.his_acfcomp = 1;
625 	  bcopy(cp, ackp, 2);
626 	  ackp += 2;
627         } else {
628 #ifdef OLDMST
629 	  /*
630 	   * MorningStar before v1.3 needs NAK
631 	   */
632 	  bcopy(cp, nakp, 2);
633 	  nakp += 2;
634 #else
635 	  bcopy(cp, rejp, 2);
636 	  rejp += 2;
637 	  LcpInfo.my_reject |= (1 << type);
638 #endif
639 	}
640 	break;
641       case MODE_NAK:
642       case MODE_REJ:
643 	LcpInfo.want_acfcomp = 0;
644 	LcpInfo.his_reject |= (1 << type);
645 	break;
646       }
647       break;
648     case TY_SDP:
649       LogPrintf(LOG_LCP_BIT, " %s\n", request);
650       switch (mode) {
651       case MODE_REQ:
652       case MODE_NAK:
653       case MODE_REJ:
654 	break;
655       }
656       break;
657     default:
658       LogPrintf(LOG_LCP_BIT, " ???[%02x]\n", type);
659       if (mode == MODE_REQ) {
660 reqreject:
661         bcopy(cp, rejp, length);
662         rejp += length;
663         LcpInfo.my_reject |= (1 << type);
664       }
665       break;
666     }
667     /* to avoid inf. loop */
668     if (length == 0) {
669       LogPrintf(LOG_LCP, "LCP size zero\n");
670       break;
671     }
672 
673     plen -= length;
674     cp += length;
675   }
676 }
677 
678 void
679 LcpInput(struct mbuf *bp)
680 {
681   FsmInput(&LcpFsm, bp);
682 }
683