xref: /freebsd/usr.sbin/ppp/lcp.c (revision 4cf49a43559ed9fdad601bdcccd2c55963008675)
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  * $FreeBSD$
21  *
22  */
23 
24 #include <sys/param.h>
25 #include <netinet/in.h>
26 #include <netinet/in_systm.h>
27 #include <netinet/ip.h>
28 #include <sys/un.h>
29 
30 #include <signal.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <termios.h>
35 #include <unistd.h>
36 
37 #include "layer.h"
38 #include "ua.h"
39 #include "defs.h"
40 #include "command.h"
41 #include "mbuf.h"
42 #include "log.h"
43 #include "timer.h"
44 #include "fsm.h"
45 #include "iplist.h"
46 #include "lcp.h"
47 #include "throughput.h"
48 #include "proto.h"
49 #include "descriptor.h"
50 #include "lqr.h"
51 #include "hdlc.h"
52 #include "ccp.h"
53 #include "async.h"
54 #include "link.h"
55 #include "physical.h"
56 #include "prompt.h"
57 #include "slcompress.h"
58 #include "ipcp.h"
59 #include "filter.h"
60 #include "mp.h"
61 #include "chat.h"
62 #include "auth.h"
63 #include "chap.h"
64 #include "cbcp.h"
65 #include "datalink.h"
66 #ifndef NORADIUS
67 #include "radius.h"
68 #endif
69 #include "bundle.h"
70 
71 /* for received LQRs */
72 struct lqrreq {
73   u_char type;
74   u_char length;
75   u_short proto;		/* Quality protocol */
76   u_int32_t period;		/* Reporting interval */
77 };
78 
79 static int LcpLayerUp(struct fsm *);
80 static void LcpLayerDown(struct fsm *);
81 static void LcpLayerStart(struct fsm *);
82 static void LcpLayerFinish(struct fsm *);
83 static void LcpInitRestartCounter(struct fsm *, int);
84 static void LcpSendConfigReq(struct fsm *);
85 static void LcpSentTerminateReq(struct fsm *);
86 static void LcpSendTerminateAck(struct fsm *, u_char);
87 static void LcpDecodeConfig(struct fsm *, u_char *, int, int,
88                             struct fsm_decode *);
89 
90 static struct fsm_callbacks lcp_Callbacks = {
91   LcpLayerUp,
92   LcpLayerDown,
93   LcpLayerStart,
94   LcpLayerFinish,
95   LcpInitRestartCounter,
96   LcpSendConfigReq,
97   LcpSentTerminateReq,
98   LcpSendTerminateAck,
99   LcpDecodeConfig,
100   fsm_NullRecvResetReq,
101   fsm_NullRecvResetAck
102 };
103 
104 static const char *lcp_TimerNames[] =
105   {"LCP restart", "LCP openmode", "LCP stopped"};
106 
107 static const char *cftypes[] = {
108   /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
109   "???",
110   "MRU",	/* 1: Maximum-Receive-Unit */
111   "ACCMAP",	/* 2: Async-Control-Character-Map */
112   "AUTHPROTO",	/* 3: Authentication-Protocol */
113   "QUALPROTO",	/* 4: Quality-Protocol */
114   "MAGICNUM",	/* 5: Magic-Number */
115   "RESERVED",	/* 6: RESERVED */
116   "PROTOCOMP",	/* 7: Protocol-Field-Compression */
117   "ACFCOMP",	/* 8: Address-and-Control-Field-Compression */
118   "FCSALT",	/* 9: FCS-Alternatives */
119   "SDP",	/* 10: Self-Describing-Pad */
120   "NUMMODE",	/* 11: Numbered-Mode */
121   "MULTIPROC",	/* 12: Multi-Link-Procedure */
122   "CALLBACK",	/* 13: Callback */
123   "CONTIME",	/* 14: Connect-Time */
124   "COMPFRAME",	/* 15: Compound-Frames */
125   "NDE",	/* 16: Nominal-Data-Encapsulation */
126   "MRRU",	/* 17: Multilink-MRRU */
127   "SHORTSEQ",	/* 18: Multilink-Short-Sequence-Number-Header */
128   "ENDDISC",	/* 19: Multilink-Endpoint-Discriminator */
129   "PROPRIETRY",	/* 20: Proprietary */
130   "DCEID",	/* 21: DCE-Identifier */
131   "MULTIPP",	/* 22: Multi-Link-Plus-Procedure */
132   "LDBACP",	/* 23: Link Discriminator for BACP */
133 };
134 
135 #define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
136 
137 int
138 lcp_ReportStatus(struct cmdargs const *arg)
139 {
140   struct link *l;
141   struct lcp *lcp;
142 
143   l = command_ChooseLink(arg);
144   lcp = &l->lcp;
145 
146   prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, lcp->fsm.name,
147                 State2Nam(lcp->fsm.state));
148   prompt_Printf(arg->prompt,
149 	        " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
150 	        "           MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
151 	        lcp->his_mru, (u_long)lcp->his_accmap,
152                 lcp->his_protocomp ? "on" : "off",
153                 lcp->his_acfcomp ? "on" : "off",
154                 (u_long)lcp->his_magic, lcp->his_mrru,
155                 lcp->his_shortseq ? "on" : "off", lcp->his_reject);
156   prompt_Printf(arg->prompt,
157 	        " my  side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
158                 "           MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
159                 lcp->want_mru, (u_long)lcp->want_accmap,
160                 lcp->want_protocomp ? "on" : "off",
161                 lcp->want_acfcomp ? "on" : "off",
162                 (u_long)lcp->want_magic, lcp->want_mrru,
163                 lcp->want_shortseq ? "on" : "off", lcp->my_reject);
164 
165   prompt_Printf(arg->prompt, "\n Defaults: MRU = %d, ", lcp->cfg.mru);
166   prompt_Printf(arg->prompt, "ACCMAP = %08lx\n", (u_long)lcp->cfg.accmap);
167   prompt_Printf(arg->prompt, "           LQR period = %us, ",
168                 lcp->cfg.lqrperiod);
169   prompt_Printf(arg->prompt, "Open Mode = %s",
170                 lcp->cfg.openmode == OPEN_PASSIVE ? "passive" : "active");
171   if (lcp->cfg.openmode > 0)
172     prompt_Printf(arg->prompt, " (delay %ds)", lcp->cfg.openmode);
173   prompt_Printf(arg->prompt, "\n           FSM retry = %us, max %u Config"
174                 " REQ%s, %u Term REQ%s\n", lcp->cfg.fsm.timeout,
175                 lcp->cfg.fsm.maxreq, lcp->cfg.fsm.maxreq == 1 ? "" : "s",
176                 lcp->cfg.fsm.maxtrm, lcp->cfg.fsm.maxtrm == 1 ? "" : "s");
177   prompt_Printf(arg->prompt, "\n Negotiation:\n");
178   prompt_Printf(arg->prompt, "           ACFCOMP =   %s\n",
179                 command_ShowNegval(lcp->cfg.acfcomp));
180   prompt_Printf(arg->prompt, "           CHAP =      %s\n",
181                 command_ShowNegval(lcp->cfg.chap05));
182 #ifdef HAVE_DES
183   prompt_Printf(arg->prompt, "           MSCHAP =    %s\n",
184                 command_ShowNegval(lcp->cfg.chap80nt));
185   prompt_Printf(arg->prompt, "           LANMan =    %s\n",
186                 command_ShowNegval(lcp->cfg.chap80lm));
187 #endif
188   prompt_Printf(arg->prompt, "           LQR =       %s\n",
189                 command_ShowNegval(lcp->cfg.lqr));
190   prompt_Printf(arg->prompt, "           PAP =       %s\n",
191                 command_ShowNegval(lcp->cfg.pap));
192   prompt_Printf(arg->prompt, "           PROTOCOMP = %s\n",
193                 command_ShowNegval(lcp->cfg.protocomp));
194 
195   return 0;
196 }
197 
198 static u_int32_t
199 GenerateMagic(void)
200 {
201   /* Generate random number which will be used as magic number */
202   randinit();
203   return random();
204 }
205 
206 void
207 lcp_SetupCallbacks(struct lcp *lcp)
208 {
209   lcp->fsm.fn = &lcp_Callbacks;
210   lcp->fsm.FsmTimer.name = lcp_TimerNames[0];
211   lcp->fsm.OpenTimer.name = lcp_TimerNames[1];
212   lcp->fsm.StoppedTimer.name = lcp_TimerNames[2];
213 }
214 
215 void
216 lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l,
217          const struct fsm_parent *parent)
218 {
219   /* Initialise ourselves */
220   int mincode = parent ? 1 : LCP_MINMPCODE;
221 
222   fsm_Init(&lcp->fsm, "LCP", PROTO_LCP, mincode, LCP_MAXCODE, LogLCP,
223            bundle, l, parent, &lcp_Callbacks, lcp_TimerNames);
224 
225   lcp->cfg.mru = DEF_MRU;
226   lcp->cfg.accmap = 0;
227   lcp->cfg.openmode = 1;
228   lcp->cfg.lqrperiod = DEF_LQRPERIOD;
229   lcp->cfg.fsm.timeout = DEF_FSMRETRY;
230   lcp->cfg.fsm.maxreq = DEF_FSMTRIES;
231   lcp->cfg.fsm.maxtrm = DEF_FSMTRIES;
232 
233   lcp->cfg.acfcomp = NEG_ENABLED|NEG_ACCEPTED;
234   lcp->cfg.chap05 = NEG_ACCEPTED;
235 #ifdef HAVE_DES
236   lcp->cfg.chap80nt = NEG_ACCEPTED;
237   lcp->cfg.chap80lm = NEG_ACCEPTED;
238 #endif
239   lcp->cfg.lqr = NEG_ACCEPTED;
240   lcp->cfg.pap = NEG_ACCEPTED;
241   lcp->cfg.protocomp = NEG_ENABLED|NEG_ACCEPTED;
242 
243   lcp_Setup(lcp, lcp->cfg.openmode);
244 }
245 
246 void
247 lcp_Setup(struct lcp *lcp, int openmode)
248 {
249   lcp->fsm.open_mode = openmode;
250 
251   lcp->his_mru = lcp->fsm.bundle->cfg.mtu;
252   if (!lcp->his_mru || lcp->his_mru > DEF_MRU)
253     lcp->his_mru = DEF_MRU;
254   lcp->his_mrru = 0;
255   lcp->his_magic = 0;
256   lcp->his_lqrperiod = 0;
257   lcp->his_acfcomp = 0;
258   lcp->his_auth = 0;
259   lcp->his_authtype = 0;
260   lcp->his_callback.opmask = 0;
261   lcp->his_shortseq = 0;
262 
263   lcp->want_mru = lcp->cfg.mru;
264   lcp->want_mrru = lcp->fsm.bundle->ncp.mp.cfg.mrru;
265   lcp->want_shortseq = IsEnabled(lcp->fsm.bundle->ncp.mp.cfg.shortseq) ? 1 : 0;
266   lcp->want_acfcomp = IsEnabled(lcp->cfg.acfcomp) ? 1 : 0;
267 
268   if (lcp->fsm.parent) {
269     struct physical *p = link2physical(lcp->fsm.link);
270 
271     lcp->his_accmap = 0xffffffff;
272     lcp->want_accmap = lcp->cfg.accmap;
273     lcp->his_protocomp = 0;
274     lcp->want_protocomp = IsEnabled(lcp->cfg.protocomp) ? 1 : 0;
275     lcp->want_magic = GenerateMagic();
276 
277     if (IsEnabled(lcp->cfg.chap05)) {
278       lcp->want_auth = PROTO_CHAP;
279       lcp->want_authtype = 0x05;
280 #ifdef HAVE_DES
281     } else if (IsEnabled(lcp->cfg.chap80nt) ||
282                IsEnabled(lcp->cfg.chap80lm)) {
283       lcp->want_auth = PROTO_CHAP;
284       lcp->want_authtype = 0x80;
285 #endif
286     } else if (IsEnabled(lcp->cfg.pap)) {
287       lcp->want_auth = PROTO_PAP;
288       lcp->want_authtype = 0;
289     } else {
290       lcp->want_auth = 0;
291       lcp->want_authtype = 0;
292     }
293 
294     if (p->type != PHYS_DIRECT)
295       memcpy(&lcp->want_callback, &p->dl->cfg.callback, sizeof(struct callback));
296     else
297       lcp->want_callback.opmask = 0;
298     lcp->want_lqrperiod = IsEnabled(lcp->cfg.lqr) ?
299                           lcp->cfg.lqrperiod * 100 : 0;
300   } else {
301     lcp->his_accmap = lcp->want_accmap = 0;
302     lcp->his_protocomp = lcp->want_protocomp = 1;
303     lcp->want_magic = 0;
304     lcp->want_auth = 0;
305     lcp->want_authtype = 0;
306     lcp->want_callback.opmask = 0;
307     lcp->want_lqrperiod = 0;
308   }
309 
310   lcp->his_reject = lcp->my_reject = 0;
311   lcp->auth_iwait = lcp->auth_ineed = 0;
312   lcp->LcpFailedMagic = 0;
313 }
314 
315 static void
316 LcpInitRestartCounter(struct fsm *fp, int what)
317 {
318   /* Set fsm timer load */
319   struct lcp *lcp = fsm2lcp(fp);
320 
321   fp->FsmTimer.load = lcp->cfg.fsm.timeout * SECTICKS;
322   switch (what) {
323     case FSM_REQ_TIMER:
324       fp->restart = lcp->cfg.fsm.maxreq;
325       break;
326     case FSM_TRM_TIMER:
327       fp->restart = lcp->cfg.fsm.maxtrm;
328       break;
329     default:
330       fp->restart = 1;
331       break;
332   }
333 }
334 
335 static void
336 LcpSendConfigReq(struct fsm *fp)
337 {
338   /* Send config REQ please */
339   struct physical *p = link2physical(fp->link);
340   struct lcp *lcp = fsm2lcp(fp);
341   u_char buff[200];
342   struct lcp_opt *o;
343   struct mp *mp;
344   u_int16_t proto;
345 
346   if (!p) {
347     log_Printf(LogERROR, "%s: LcpSendConfigReq: Not a physical link !\n",
348               fp->link->name);
349     return;
350   }
351 
352   o = (struct lcp_opt *)buff;
353   if (!physical_IsSync(p)) {
354     if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP))
355       INC_LCP_OPT(TY_ACFCOMP, 2, o);
356 
357     if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP))
358       INC_LCP_OPT(TY_PROTOCOMP, 2, o);
359 
360     if (!REJECTED(lcp, TY_ACCMAP)) {
361       ua_htonl(&lcp->want_accmap, o->data);
362       INC_LCP_OPT(TY_ACCMAP, 6, o);
363     }
364   }
365 
366   if (!REJECTED(lcp, TY_MRU)) {
367     ua_htons(&lcp->want_mru, o->data);
368     INC_LCP_OPT(TY_MRU, 4, o);
369   }
370 
371   if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) {
372     ua_htonl(&lcp->want_magic, o->data);
373     INC_LCP_OPT(TY_MAGICNUM, 6, o);
374   }
375 
376   if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
377     proto = PROTO_LQR;
378     ua_htons(&proto, o->data);
379     ua_htonl(&lcp->want_lqrperiod, o->data + 2);
380     INC_LCP_OPT(TY_QUALPROTO, 8, o);
381   }
382 
383   switch (lcp->want_auth) {
384   case PROTO_PAP:
385     proto = PROTO_PAP;
386     ua_htons(&proto, o->data);
387     INC_LCP_OPT(TY_AUTHPROTO, 4, o);
388     break;
389 
390   case PROTO_CHAP:
391     proto = PROTO_CHAP;
392     ua_htons(&proto, o->data);
393     o->data[2] = lcp->want_authtype;
394     INC_LCP_OPT(TY_AUTHPROTO, 5, o);
395     break;
396   }
397 
398   if (!REJECTED(lcp, TY_CALLBACK)) {
399     if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
400       *o->data = CALLBACK_AUTH;
401       INC_LCP_OPT(TY_CALLBACK, 3, o);
402     } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
403       *o->data = CALLBACK_CBCP;
404       INC_LCP_OPT(TY_CALLBACK, 3, o);
405     } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
406       int sz = strlen(lcp->want_callback.msg);
407 
408       if (sz > sizeof o->data - 1) {
409         sz = sizeof o->data - 1;
410         log_Printf(LogWARN, "Truncating E164 data to %d octets (oops!)\n", sz);
411       }
412       *o->data = CALLBACK_E164;
413       memcpy(o->data + 1, lcp->want_callback.msg, sz);
414       INC_LCP_OPT(TY_CALLBACK, sz + 3, o);
415     }
416   }
417 
418   if (lcp->want_mrru && !REJECTED(lcp, TY_MRRU)) {
419     ua_htons(&lcp->want_mrru, o->data);
420     INC_LCP_OPT(TY_MRRU, 4, o);
421 
422     if (lcp->want_shortseq && !REJECTED(lcp, TY_SHORTSEQ))
423       INC_LCP_OPT(TY_SHORTSEQ, 2, o);
424   }
425 
426   mp = &lcp->fsm.bundle->ncp.mp;
427   if (mp->cfg.enddisc.class != 0 && IsEnabled(mp->cfg.negenddisc) &&
428       !REJECTED(lcp, TY_ENDDISC)) {
429     *o->data = mp->cfg.enddisc.class;
430     memcpy(o->data+1, mp->cfg.enddisc.address, mp->cfg.enddisc.len);
431     INC_LCP_OPT(TY_ENDDISC, mp->cfg.enddisc.len + 3, o);
432   }
433 
434   fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
435              MB_LCPOUT);
436 }
437 
438 void
439 lcp_SendProtoRej(struct lcp *lcp, u_char *option, int count)
440 {
441   /* Don't understand `option' */
442   fsm_Output(&lcp->fsm, CODE_PROTOREJ, lcp->fsm.reqid, option, count,
443              MB_LCPOUT);
444 }
445 
446 static void
447 LcpSentTerminateReq(struct fsm *fp)
448 {
449   /* Term REQ just sent by FSM */
450 }
451 
452 static void
453 LcpSendTerminateAck(struct fsm *fp, u_char id)
454 {
455   /* Send Term ACK please */
456   struct physical *p = link2physical(fp->link);
457 
458   if (p && p->dl->state == DATALINK_CBCP)
459     cbcp_ReceiveTerminateReq(p);
460 
461   fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_LCPOUT);
462 }
463 
464 static void
465 LcpLayerStart(struct fsm *fp)
466 {
467   /* We're about to start up ! */
468   struct lcp *lcp = fsm2lcp(fp);
469 
470   log_Printf(LogLCP, "%s: LayerStart\n", fp->link->name);
471   lcp->LcpFailedMagic = 0;
472   fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
473 }
474 
475 static void
476 LcpLayerFinish(struct fsm *fp)
477 {
478   /* We're now down */
479   log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name);
480 }
481 
482 static int
483 LcpLayerUp(struct fsm *fp)
484 {
485   /* We're now up */
486   struct physical *p = link2physical(fp->link);
487   struct lcp *lcp = fsm2lcp(fp);
488 
489   log_Printf(LogLCP, "%s: LayerUp\n", fp->link->name);
490   async_SetLinkParams(&p->async, lcp);
491   lqr_Start(lcp);
492   hdlc_StartTimer(&p->hdlc);
493   fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
494 
495   return 1;
496 }
497 
498 static void
499 LcpLayerDown(struct fsm *fp)
500 {
501   /* About to come down */
502   struct physical *p = link2physical(fp->link);
503 
504   log_Printf(LogLCP, "%s: LayerDown\n", fp->link->name);
505   hdlc_StopTimer(&p->hdlc);
506   lqr_StopTimer(p);
507   lcp_Setup(fsm2lcp(fp), 0);
508 }
509 
510 static int
511 E164ok(struct callback *cb, char *req, int sz)
512 {
513   char list[sizeof cb->msg], *next;
514   int len;
515 
516   if (!strcmp(cb->msg, "*"))
517     return 1;
518 
519   strncpy(list, cb->msg, sizeof list - 1);
520   list[sizeof list - 1] = '\0';
521   for (next = strtok(list, ","); next; next = strtok(NULL, ",")) {
522     len = strlen(next);
523     if (sz == len && !memcmp(list, req, sz))
524       return 1;
525   }
526   return 0;
527 }
528 
529 static void
530 LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
531                 struct fsm_decode *dec)
532 {
533   /* Deal with incoming PROTO_LCP */
534   struct lcp *lcp = fsm2lcp(fp);
535   int type, length, sz, pos, op, callback_req;
536   u_int32_t magic, accmap;
537   u_short mtu, mru, proto;
538   struct lqrreq *req;
539   char request[20], desc[22];
540   struct mp *mp;
541   struct physical *p = link2physical(fp->link);
542 
543   sz = op = callback_req = 0;
544 
545   while (plen >= sizeof(struct fsmconfig)) {
546     type = *cp;
547     length = cp[1];
548 
549     if (type < 0 || type >= NCFTYPES)
550       snprintf(request, sizeof request, " <%d>[%d]", type, length);
551     else
552       snprintf(request, sizeof request, " %s[%d]", cftypes[type], length);
553 
554     if (length < 2) {
555       log_Printf(LogLCP, "%s:%s: Bad LCP length\n", fp->link->name, request);
556       break;
557     }
558 
559     switch (type) {
560     case TY_MRRU:
561       mp = &lcp->fsm.bundle->ncp.mp;
562       ua_ntohs(cp + 2, &mru);
563       log_Printf(LogLCP, "%s %u\n", request, mru);
564 
565       switch (mode_type) {
566       case MODE_REQ:
567         if (mp->cfg.mrru) {
568           if (REJECTED(lcp, TY_MRRU))
569             /* Ignore his previous reject so that we REQ next time */
570 	    lcp->his_reject &= ~(1 << type);
571 
572           mtu = lcp->fsm.bundle->cfg.mtu;
573           if (mru < MIN_MRU || mru < mtu) {
574             /* Push him up to MTU or MIN_MRU */
575             lcp->his_mrru = mru < mtu ? mtu : MIN_MRU;
576 	    memcpy(dec->nakend, cp, 2);
577             ua_htons(&lcp->his_mrru, dec->nakend + 2);
578 	    dec->nakend += 4;
579 	  } else {
580             lcp->his_mrru = mtu ? mtu : mru;
581 	    memcpy(dec->ackend, cp, 4);
582 	    dec->ackend += 4;
583 	  }
584 	  break;
585         } else
586 	  goto reqreject;
587         break;
588       case MODE_NAK:
589         if (mp->cfg.mrru) {
590           if (REJECTED(lcp, TY_MRRU))
591             /* Must have changed his mind ! */
592 	    lcp->his_reject &= ~(1 << type);
593 
594           if (mru > MAX_MRU)
595             lcp->want_mrru = MAX_MRU;
596           else if (mru < MIN_MRU)
597             lcp->want_mrru = MIN_MRU;
598           else
599             lcp->want_mrru = mru;
600         }
601         /* else we honour our config and don't send the suggested REQ */
602         break;
603       case MODE_REJ:
604 	lcp->his_reject |= (1 << type);
605         lcp->want_mrru = 0;		/* Ah well, no multilink :-( */
606 	break;
607       }
608       break;
609 
610     case TY_MRU:
611       ua_ntohs(cp + 2, &mru);
612       log_Printf(LogLCP, "%s %d\n", request, mru);
613 
614       switch (mode_type) {
615       case MODE_REQ:
616         mtu = lcp->fsm.bundle->cfg.mtu;
617         if (mru < MIN_MRU || (!lcp->want_mrru && mru < mtu)) {
618           /* Push him up to MTU or MIN_MRU */
619           lcp->his_mru = mru < mtu ? mtu : MIN_MRU;
620           memcpy(dec->nakend, cp, 2);
621           ua_htons(&lcp->his_mru, dec->nakend + 2);
622           dec->nakend += 4;
623         } else {
624           lcp->his_mru = mtu ? mtu : mru;
625           memcpy(dec->ackend, cp, 4);
626           dec->ackend += 4;
627         }
628 	break;
629       case MODE_NAK:
630         if (mru > MAX_MRU)
631           lcp->want_mru = MAX_MRU;
632         else if (mru < MIN_MRU)
633           lcp->want_mru = MIN_MRU;
634         else
635           lcp->want_mru = mru;
636 	break;
637       case MODE_REJ:
638 	lcp->his_reject |= (1 << type);
639 	break;
640       }
641       break;
642 
643     case TY_ACCMAP:
644       ua_ntohl(cp + 2, &accmap);
645       log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap);
646 
647       switch (mode_type) {
648       case MODE_REQ:
649 	lcp->his_accmap = accmap;
650 	memcpy(dec->ackend, cp, 6);
651 	dec->ackend += 6;
652 	break;
653       case MODE_NAK:
654 	lcp->want_accmap = accmap;
655 	break;
656       case MODE_REJ:
657 	lcp->his_reject |= (1 << type);
658 	break;
659       }
660       break;
661 
662     case TY_AUTHPROTO:
663       ua_ntohs(cp + 2, &proto);
664       log_Printf(LogLCP, "%s 0x%04x (%s)\n", request, proto,
665                  Auth2Nam(proto, length > 4 ? cp[4] : 0));
666 
667       switch (mode_type) {
668       case MODE_REQ:
669 	switch (proto) {
670 	case PROTO_PAP:
671 	  if (length != 4) {
672 	    log_Printf(LogLCP, " Bad length!\n");
673 	    goto reqreject;
674 	  }
675 	  if (IsAccepted(lcp->cfg.pap)) {
676 	    lcp->his_auth = proto;
677 	    lcp->his_authtype = 0;
678 	    memcpy(dec->ackend, cp, length);
679 	    dec->ackend += length;
680 	  } else if (IsAccepted(lcp->cfg.chap05)) {
681 	    *dec->nakend++ = *cp;
682 	    *dec->nakend++ = 5;
683 	    *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
684 	    *dec->nakend++ = (unsigned char) PROTO_CHAP;
685 	    *dec->nakend++ = 0x05;
686 #ifdef HAVE_DES
687 	  } else if (IsAccepted(lcp->cfg.chap80nt) ||
688 	             IsAccepted(lcp->cfg.chap80lm)) {
689 	    *dec->nakend++ = *cp;
690 	    *dec->nakend++ = 5;
691 	    *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
692 	    *dec->nakend++ = (unsigned char) PROTO_CHAP;
693 	    *dec->nakend++ = 0x80;
694 #endif
695 	  } else
696 	    goto reqreject;
697 	  break;
698 
699 	case PROTO_CHAP:
700 	  if (length != 5) {
701 	    log_Printf(LogLCP, " Bad length!\n");
702 	    goto reqreject;
703 	  }
704           if ((cp[4] == 0x05 && IsAccepted(lcp->cfg.chap05))
705 #ifdef HAVE_DES
706               || (cp[4] == 0x80 && (IsAccepted(lcp->cfg.chap80nt) ||
707                                    (IsAccepted(lcp->cfg.chap80lm))))
708 #endif
709              ) {
710 	    lcp->his_auth = proto;
711 	    lcp->his_authtype = cp[4];
712 	    memcpy(dec->ackend, cp, length);
713 	    dec->ackend += length;
714 	  } else {
715 #ifndef HAVE_DES
716             if (cp[4] == 0x80)
717               log_Printf(LogWARN, "CHAP 0x80 not available without DES\n");
718             else
719 #endif
720             if (cp[4] != 0x05)
721               log_Printf(LogWARN, "%s not supported\n",
722                          Auth2Nam(PROTO_CHAP, cp[4]));
723 
724             if (IsAccepted(lcp->cfg.chap05)) {
725 	      *dec->nakend++ = *cp;
726 	      *dec->nakend++ = 5;
727 	      *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
728 	      *dec->nakend++ = (unsigned char) PROTO_CHAP;
729 	      *dec->nakend++ = 0x05;
730 #ifdef HAVE_DES
731             } else if (IsAccepted(lcp->cfg.chap80nt) ||
732                        IsAccepted(lcp->cfg.chap80lm)) {
733 	      *dec->nakend++ = *cp;
734 	      *dec->nakend++ = 5;
735 	      *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
736 	      *dec->nakend++ = (unsigned char) PROTO_CHAP;
737 	      *dec->nakend++ = 0x80;
738 #endif
739             } else if (IsAccepted(lcp->cfg.pap)) {
740 	      *dec->nakend++ = *cp;
741 	      *dec->nakend++ = 4;
742 	      *dec->nakend++ = (unsigned char) (PROTO_PAP >> 8);
743 	      *dec->nakend++ = (unsigned char) PROTO_PAP;
744 	    } else
745 	      goto reqreject;
746           }
747 	  break;
748 
749 	default:
750           log_Printf(LogLCP, "%s 0x%04x - not recognised, NAK\n",
751                     request, proto);
752 	  memcpy(dec->nakend, cp, length);
753 	  dec->nakend += length;
754 	  break;
755 	}
756 	break;
757       case MODE_NAK:
758 	switch (proto) {
759 	case PROTO_PAP:
760           if (IsEnabled(lcp->cfg.pap)) {
761             lcp->want_auth = PROTO_PAP;
762             lcp->want_authtype = 0;
763           } else {
764             log_Printf(LogLCP, "Peer will only send PAP (not enabled)\n");
765 	    lcp->his_reject |= (1 << type);
766           }
767           break;
768 	case PROTO_CHAP:
769           if (cp[4] == 0x05 && IsEnabled(lcp->cfg.chap05)) {
770             lcp->want_auth = PROTO_CHAP;
771             lcp->want_authtype = 0x05;
772 #ifdef HAVE_DES
773           } else if (cp[4] == 0x80 && (IsEnabled(lcp->cfg.chap80nt) ||
774                                        IsEnabled(lcp->cfg.chap80lm))) {
775             lcp->want_auth = PROTO_CHAP;
776             lcp->want_authtype = 0x80;
777 #endif
778           } else {
779 #ifndef HAVE_DES
780             if (cp[4] == 0x80)
781               log_Printf(LogLCP, "Peer will only send MSCHAP (not available"
782                          " without DES)\n");
783             else
784 #endif
785             log_Printf(LogLCP, "Peer will only send %s (not %s)\n",
786                        Auth2Nam(PROTO_CHAP, cp[4]),
787 #ifdef HAVE_DES
788                        cp[4] == 0x80 ? "configured" :
789 #endif
790                        "supported");
791 	    lcp->his_reject |= (1 << type);
792           }
793           break;
794         default:
795           /* We've been NAK'd with something we don't understand :-( */
796 	  lcp->his_reject |= (1 << type);
797           break;
798         }
799 	break;
800       case MODE_REJ:
801 	lcp->his_reject |= (1 << type);
802 	break;
803       }
804       break;
805 
806     case TY_QUALPROTO:
807       req = (struct lqrreq *)cp;
808       log_Printf(LogLCP, "%s proto %x, interval %lums\n",
809                 request, ntohs(req->proto), (u_long)ntohl(req->period) * 10);
810       switch (mode_type) {
811       case MODE_REQ:
812 	if (ntohs(req->proto) != PROTO_LQR || !IsAccepted(lcp->cfg.lqr))
813 	  goto reqreject;
814 	else {
815 	  lcp->his_lqrperiod = ntohl(req->period);
816 	  if (lcp->his_lqrperiod < MIN_LQRPERIOD * 100)
817 	    lcp->his_lqrperiod = MIN_LQRPERIOD * 100;
818 	  req->period = htonl(lcp->his_lqrperiod);
819 	  memcpy(dec->ackend, cp, length);
820 	  dec->ackend += length;
821 	}
822 	break;
823       case MODE_NAK:
824 	break;
825       case MODE_REJ:
826 	lcp->his_reject |= (1 << type);
827 	break;
828       }
829       break;
830 
831     case TY_MAGICNUM:
832       ua_ntohl(cp + 2, &magic);
833       log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
834 
835       switch (mode_type) {
836       case MODE_REQ:
837 	if (lcp->want_magic) {
838 	  /* Validate magic number */
839 	  if (magic == lcp->want_magic) {
840 	    log_Printf(LogLCP, "Magic is same (%08lx) - %d times\n",
841                       (u_long)magic, ++lcp->LcpFailedMagic);
842 	    lcp->want_magic = GenerateMagic();
843 	    memcpy(dec->nakend, cp, 6);
844 	    dec->nakend += 6;
845             ualarm(TICKUNIT * (4 + 4 * lcp->LcpFailedMagic), 0);
846             sigpause(0);
847 	  } else {
848 	    lcp->his_magic = magic;
849 	    memcpy(dec->ackend, cp, length);
850 	    dec->ackend += length;
851             lcp->LcpFailedMagic = 0;
852 	  }
853 	} else {
854 	  goto reqreject;
855 	}
856 	break;
857       case MODE_NAK:
858 	log_Printf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
859 	lcp->want_magic = GenerateMagic();
860 	break;
861       case MODE_REJ:
862 	log_Printf(LogLCP, " Magic 0x%08x is REJected!\n", magic);
863 	lcp->want_magic = 0;
864 	lcp->his_reject |= (1 << type);
865 	break;
866       }
867       break;
868 
869     case TY_PROTOCOMP:
870       log_Printf(LogLCP, "%s\n", request);
871 
872       switch (mode_type) {
873       case MODE_REQ:
874 	if (IsAccepted(lcp->cfg.protocomp)) {
875 	  lcp->his_protocomp = 1;
876 	  memcpy(dec->ackend, cp, 2);
877 	  dec->ackend += 2;
878 	} else {
879 #ifdef OLDMST
880 	  /* MorningStar before v1.3 needs NAK */
881 	  memcpy(dec->nakend, cp, 2);
882 	  dec->nakend += 2;
883 #else
884 	  goto reqreject;
885 #endif
886 	}
887 	break;
888       case MODE_NAK:
889       case MODE_REJ:
890 	lcp->want_protocomp = 0;
891 	lcp->his_reject |= (1 << type);
892 	break;
893       }
894       break;
895 
896     case TY_ACFCOMP:
897       log_Printf(LogLCP, "%s\n", request);
898       switch (mode_type) {
899       case MODE_REQ:
900 	if (IsAccepted(lcp->cfg.acfcomp)) {
901 	  lcp->his_acfcomp = 1;
902 	  memcpy(dec->ackend, cp, 2);
903 	  dec->ackend += 2;
904 	} else {
905 #ifdef OLDMST
906 	  /* MorningStar before v1.3 needs NAK */
907 	  memcpy(dec->nakend, cp, 2);
908 	  dec->nakend += 2;
909 #else
910 	  goto reqreject;
911 #endif
912 	}
913 	break;
914       case MODE_NAK:
915       case MODE_REJ:
916 	lcp->want_acfcomp = 0;
917 	lcp->his_reject |= (1 << type);
918 	break;
919       }
920       break;
921 
922     case TY_SDP:
923       log_Printf(LogLCP, "%s\n", request);
924       switch (mode_type) {
925       case MODE_REQ:
926       case MODE_NAK:
927       case MODE_REJ:
928 	break;
929       }
930       break;
931 
932     case TY_CALLBACK:
933       if (length == 2)
934         op = CALLBACK_NONE;
935       else
936         op = (int)cp[2];
937       sz = length - 3;
938       switch (op) {
939         case CALLBACK_AUTH:
940           log_Printf(LogLCP, "%s Auth\n", request);
941           break;
942         case CALLBACK_DIALSTRING:
943           log_Printf(LogLCP, "%s Dialstring %.*s\n", request, sz, cp + 3);
944           break;
945         case CALLBACK_LOCATION:
946           log_Printf(LogLCP, "%s Location %.*s\n", request, sz, cp + 3);
947           break;
948         case CALLBACK_E164:
949           log_Printf(LogLCP, "%s E.164 (%.*s)\n", request, sz, cp + 3);
950           break;
951         case CALLBACK_NAME:
952           log_Printf(LogLCP, "%s Name %.*s\n", request, sz, cp + 3);
953           break;
954         case CALLBACK_CBCP:
955           log_Printf(LogLCP, "%s CBCP\n", request);
956           break;
957         default:
958           log_Printf(LogLCP, "%s ???\n", request);
959           break;
960       }
961 
962       switch (mode_type) {
963       case MODE_REQ:
964         callback_req = 1;
965         if (p->type != PHYS_DIRECT)
966 	  goto reqreject;
967         if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(op)) &&
968             (op != CALLBACK_AUTH || p->link.lcp.auth_ineed) &&
969             (op != CALLBACK_E164 ||
970              E164ok(&p->dl->cfg.callback, cp + 3, sz))) {
971 	  lcp->his_callback.opmask = CALLBACK_BIT(op);
972           if (sz > sizeof lcp->his_callback.msg - 1) {
973             sz = sizeof lcp->his_callback.msg - 1;
974             log_Printf(LogWARN, "Truncating option arg to %d octets\n", sz);
975           }
976 	  memcpy(lcp->his_callback.msg, cp + 3, sz);
977 	  lcp->his_callback.msg[sz] = '\0';
978 	  memcpy(dec->ackend, cp, sz + 3);
979 	  dec->ackend += sz + 3;
980         } else if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
981                     p->link.lcp.auth_ineed) {
982           *dec->nakend++ = *cp;
983           *dec->nakend++ = 3;
984           *dec->nakend++ = CALLBACK_AUTH;
985         } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
986           *dec->nakend++ = *cp;
987           *dec->nakend++ = 3;
988           *dec->nakend++ = CALLBACK_CBCP;
989         } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
990           *dec->nakend++ = *cp;
991           *dec->nakend++ = 3;
992           *dec->nakend++ = CALLBACK_E164;
993         } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
994           log_Printf(LogWARN, "Cannot insist on auth callback without"
995                      " PAP or CHAP enabled !\n");
996           *dec->nakend++ = *cp;
997           *dec->nakend++ = 2;
998         } else
999 	  goto reqreject;
1000         break;
1001       case MODE_NAK:
1002         /* We don't do what he NAKs with, we do things in our preferred order */
1003         if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH))
1004           lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_AUTH);
1005         else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1006           lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_CBCP);
1007         else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1008           lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_E164);
1009         if (lcp->want_callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) {
1010           log_Printf(LogPHASE, "Peer NAKd all callbacks, trying none\n");
1011           lcp->want_callback.opmask = 0;
1012         } else if (!lcp->want_callback.opmask) {
1013           log_Printf(LogPHASE, "Peer NAKd last configured callback\n");
1014           fsm_Close(&lcp->fsm);
1015         }
1016         break;
1017       case MODE_REJ:
1018         if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) {
1019 	  lcp->his_reject |= (1 << type);
1020           lcp->want_callback.opmask = 0;
1021         } else {
1022           log_Printf(LogPHASE, "Peer rejected *required* callback\n");
1023           fsm_Close(&lcp->fsm);
1024         }
1025 	break;
1026       }
1027       break;
1028 
1029     case TY_SHORTSEQ:
1030       mp = &lcp->fsm.bundle->ncp.mp;
1031       log_Printf(LogLCP, "%s\n", request);
1032 
1033       switch (mode_type) {
1034       case MODE_REQ:
1035         if (lcp->want_mrru && IsAccepted(mp->cfg.shortseq)) {
1036           lcp->his_shortseq = 1;
1037 	  memcpy(dec->ackend, cp, length);
1038 	  dec->ackend += length;
1039         } else
1040 	  goto reqreject;
1041         break;
1042       case MODE_NAK:
1043         /*
1044          * He's trying to get us to ask for short sequence numbers.
1045          * We ignore the NAK and honour our configuration file instead.
1046          */
1047         break;
1048       case MODE_REJ:
1049 	lcp->his_reject |= (1 << type);
1050         lcp->want_shortseq = 0;		/* For when we hit MP */
1051 	break;
1052       }
1053       break;
1054 
1055     case TY_ENDDISC:
1056       mp = &lcp->fsm.bundle->ncp.mp;
1057       log_Printf(LogLCP, "%s %s\n", request,
1058                 mp_Enddisc(cp[2], cp + 3, length - 3));
1059       switch (mode_type) {
1060       case MODE_REQ:
1061         if (!p) {
1062           log_Printf(LogLCP, " ENDDISC rejected - not a physical link\n");
1063 	  goto reqreject;
1064         } else if (!IsAccepted(mp->cfg.negenddisc))
1065 	  goto reqreject;
1066         else if (length-3 < sizeof p->dl->peer.enddisc.address &&
1067                    cp[2] <= MAX_ENDDISC_CLASS) {
1068           p->dl->peer.enddisc.class = cp[2];
1069           p->dl->peer.enddisc.len = length-3;
1070           memcpy(p->dl->peer.enddisc.address, cp + 3, length - 3);
1071           p->dl->peer.enddisc.address[length - 3] = '\0';
1072           /* XXX: If mp->active, compare and NAK with mp->peer ? */
1073 	  memcpy(dec->ackend, cp, length);
1074 	  dec->ackend += length;
1075         } else {
1076           if (cp[2] > MAX_ENDDISC_CLASS)
1077             log_Printf(LogLCP, " ENDDISC rejected - unrecognised class %d\n",
1078                       cp[2]);
1079           else
1080             log_Printf(LogLCP, " ENDDISC rejected - local max length is %ld\n",
1081                       (long)(sizeof p->dl->peer.enddisc.address - 1));
1082 	  goto reqreject;
1083         }
1084 	break;
1085 
1086       case MODE_NAK:	/* Treat this as a REJ, we don't vary our disc (yet) */
1087       case MODE_REJ:
1088 	lcp->his_reject |= (1 << type);
1089 	break;
1090       }
1091       break;
1092 
1093     default:
1094       sz = (sizeof desc - 2) / 2;
1095       if (sz > length - 2)
1096         sz = length - 2;
1097       pos = 0;
1098       desc[0] = sz ? ' ' : '\0';
1099       for (pos = 0; sz--; pos++)
1100         sprintf(desc+(pos<<1)+1, "%02x", cp[pos+2]);
1101 
1102       log_Printf(LogLCP, "%s%s\n", request, desc);
1103 
1104       if (mode_type == MODE_REQ) {
1105 reqreject:
1106         if (length > sizeof dec->rej - (dec->rejend - dec->rej)) {
1107           length = sizeof dec->rej - (dec->rejend - dec->rej);
1108           log_Printf(LogLCP, "Can't REJ length %d - trunating to %d\n",
1109 		    cp[1], length);
1110         }
1111 	memcpy(dec->rejend, cp, length);
1112 	dec->rejend += length;
1113 	lcp->my_reject |= (1 << type);
1114         if (length != cp[1])
1115           length = 0;		/* force our way out of the loop */
1116       }
1117       break;
1118     }
1119     plen -= length;
1120     cp += length;
1121   }
1122 
1123   if (mode_type != MODE_NOP) {
1124     if (mode_type == MODE_REQ && p && p->type == PHYS_DIRECT &&
1125         p->dl->cfg.callback.opmask && !callback_req &&
1126         !(p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))) {
1127       /* We *REQUIRE* that the peer requests callback */
1128       *dec->nakend++ = TY_CALLBACK;
1129       *dec->nakend++ = 3;
1130       if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1131           p->link.lcp.auth_ineed)
1132         *dec->nakend++ = CALLBACK_AUTH;
1133       else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1134         *dec->nakend++ = CALLBACK_CBCP;
1135       else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1136         *dec->nakend++ = CALLBACK_E164;
1137       else {
1138         log_Printf(LogWARN, "Cannot insist on auth callback without"
1139                    " PAP or CHAP enabled !\n");
1140         dec->nakend[-1] = 2;	/* XXX: Silly ! */
1141       }
1142     }
1143     if (dec->rejend != dec->rej) {
1144       /* rejects are preferred */
1145       dec->ackend = dec->ack;
1146       dec->nakend = dec->nak;
1147     } else if (dec->nakend != dec->nak)
1148       /* then NAKs */
1149       dec->ackend = dec->ack;
1150   }
1151 }
1152 
1153 extern struct mbuf *
1154 lcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
1155 {
1156   /* Got PROTO_LCP from link */
1157   mbuf_SetType(bp, MB_LCPIN);
1158   fsm_Input(&l->lcp.fsm, bp);
1159   return NULL;
1160 }
1161