Deleted Added
full compact
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: head/usr.sbin/ppp/lcp.c 55146 1999-12-27 11:54:57Z brian $
20 * $FreeBSD: head/usr.sbin/ppp/lcp.c 58034 2000-03-14 01:46:54Z brian $
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 */
72struct lqrreq {
73 u_char type;
74 u_char length;
75 u_short proto; /* Quality protocol */
76 u_int32_t period; /* Reporting interval */
77};
78
79static int LcpLayerUp(struct fsm *);
80static void LcpLayerDown(struct fsm *);
81static void LcpLayerStart(struct fsm *);
82static void LcpLayerFinish(struct fsm *);
83static void LcpInitRestartCounter(struct fsm *, int);
84static void LcpSendConfigReq(struct fsm *);
85static void LcpSentTerminateReq(struct fsm *);
86static void LcpSendTerminateAck(struct fsm *, u_char);
87static void LcpDecodeConfig(struct fsm *, u_char *, int, int,
88 struct fsm_decode *);
89
90static 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
104static const char * const lcp_TimerNames[] =
105 {"LCP restart", "LCP openmode", "LCP stopped"};
106
107static const char * const 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};
107static const char *
108protoname(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
135#define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
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
145int
146lcp_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
206static u_int32_t
207GenerateMagic(void)
208{
209 /* Generate random number which will be used as magic number */
210 randinit();
211 return random();
212}
213
214void
215lcp_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
223void
224lcp_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
254void
255lcp_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
323static void
324LcpInitRestartCounter(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
343static void
344LcpSendConfigReq(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
446void
447lcp_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
454static void
455LcpSentTerminateReq(struct fsm *fp)
456{
457 /* Term REQ just sent by FSM */
458}
459
460static void
461LcpSendTerminateAck(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
472static void
473LcpLayerStart(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
483static void
484LcpLayerFinish(struct fsm *fp)
485{
486 /* We're now down */
487 log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name);
488}
489
490static int
491LcpLayerUp(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
506static void
507LcpLayerDown(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
518static int
519E164ok(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
537static void
538LcpDecodeConfig(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
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);
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) {
1110reqreject:
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
1158extern struct mbuf *
1159lcp_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}