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