Deleted Added
sdiff udiff text old ( 55146 ) new ( 58034 )
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 $
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};
134
135#define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
136
137int
138lcp_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
198static u_int32_t
199GenerateMagic(void)
200{
201 /* Generate random number which will be used as magic number */
202 randinit();
203 return random();
204}
205
206void
207lcp_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
215void
216lcp_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
246void
247lcp_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
315static void
316LcpInitRestartCounter(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
335static void
336LcpSendConfigReq(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
438void
439lcp_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
446static void
447LcpSentTerminateReq(struct fsm *fp)
448{
449 /* Term REQ just sent by FSM */
450}
451
452static void
453LcpSendTerminateAck(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
464static void
465LcpLayerStart(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
475static void
476LcpLayerFinish(struct fsm *fp)
477{
478 /* We're now down */
479 log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name);
480}
481
482static int
483LcpLayerUp(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
498static void
499LcpLayerDown(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
510static int
511E164ok(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
529static void
530LcpDecodeConfig(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) {
1105reqreject:
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
1153extern struct mbuf *
1154lcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
1155{
1156 /* Got PROTO_LCP from link */
1157 m_settype(bp, MB_LCPIN);
1158 fsm_Input(&l->lcp.fsm, bp);
1159 return NULL;
1160}