2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4 * Internet Initiative Japan, Inc (IIJ)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/param.h>
32 #include <netinet/in.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/ip.h>
35 #include <sys/socket.h>
54 #include "throughput.h"
56 #include "descriptor.h"
65 #include "slcompress.h"
83 /* for received LQRs */
87 u_short proto; /* Quality protocol */
88 u_int32_t period; /* Reporting interval */
91 static int LcpLayerUp(struct fsm *);
92 static void LcpLayerDown(struct fsm *);
93 static void LcpLayerStart(struct fsm *);
94 static void LcpLayerFinish(struct fsm *);
95 static void LcpInitRestartCounter(struct fsm *, int);
96 static void LcpSendConfigReq(struct fsm *);
97 static void LcpSentTerminateReq(struct fsm *);
98 static void LcpSendTerminateAck(struct fsm *, u_char);
99 static void LcpDecodeConfig(struct fsm *, u_char *, int, int,
100 struct fsm_decode *);
102 static struct fsm_callbacks lcp_Callbacks = {
107 LcpInitRestartCounter,
112 fsm_NullRecvResetReq,
116 static const char * const lcp_TimerNames[] =
117 {"LCP restart", "LCP openmode", "LCP stopped"};
122 static const char * const cftypes[] = {
123 /* Check out the latest ``Assigned numbers'' rfc (1700) */
125 "MRU", /* 1: Maximum-Receive-Unit */
126 "ACCMAP", /* 2: Async-Control-Character-Map */
127 "AUTHPROTO", /* 3: Authentication-Protocol */
128 "QUALPROTO", /* 4: Quality-Protocol */
129 "MAGICNUM", /* 5: Magic-Number */
130 "RESERVED", /* 6: RESERVED */
131 "PROTOCOMP", /* 7: Protocol-Field-Compression */
132 "ACFCOMP", /* 8: Address-and-Control-Field-Compression */
133 "FCSALT", /* 9: FCS-Alternatives */
134 "SDP", /* 10: Self-Describing-Pad */
135 "NUMMODE", /* 11: Numbered-Mode */
136 "MULTIPROC", /* 12: Multi-Link-Procedure */
137 "CALLBACK", /* 13: Callback */
138 "CONTIME", /* 14: Connect-Time */
139 "COMPFRAME", /* 15: Compound-Frames */
140 "NDE", /* 16: Nominal-Data-Encapsulation */
141 "MRRU", /* 17: Multilink-MRRU */
142 "SHORTSEQ", /* 18: Multilink-Short-Sequence-Number-Header */
143 "ENDDISC", /* 19: Multilink-Endpoint-Discriminator */
144 "PROPRIETRY", /* 20: Proprietary */
145 "DCEID", /* 21: DCE-Identifier */
146 "MULTIPP", /* 22: Multi-Link-Plus-Procedure */
147 "LDBACP", /* 23: Link Discriminator for BACP */
150 if (proto < 0 || proto > sizeof cftypes / sizeof *cftypes ||
151 cftypes[proto] == NULL)
152 return HexStr(proto, NULL, 0);
154 return cftypes[proto];
158 lcp_ReportStatus(struct cmdargs const *arg)
163 l = command_ChooseLink(arg);
166 prompt_Printf(arg->prompt, "%s: %s [%s]\n", l->name, lcp->fsm.name,
167 State2Nam(lcp->fsm.state));
168 prompt_Printf(arg->prompt,
169 " his side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
170 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
171 lcp->his_mru, (u_long)lcp->his_accmap,
172 lcp->his_protocomp ? "on" : "off",
173 lcp->his_acfcomp ? "on" : "off",
174 (u_long)lcp->his_magic, lcp->his_mrru,
175 lcp->his_shortseq ? "on" : "off", lcp->his_reject);
176 prompt_Printf(arg->prompt,
177 " my side: MRU %d, ACCMAP %08lx, PROTOCOMP %s, ACFCOMP %s,\n"
178 " MAGIC %08lx, MRRU %u, SHORTSEQ %s, REJECT %04x\n",
179 lcp->want_mru, (u_long)lcp->want_accmap,
180 lcp->want_protocomp ? "on" : "off",
181 lcp->want_acfcomp ? "on" : "off",
182 (u_long)lcp->want_magic, lcp->want_mrru,
183 lcp->want_shortseq ? "on" : "off", lcp->my_reject);
186 prompt_Printf(arg->prompt, "\n Defaults: MRU = %d (max %d), ",
187 lcp->cfg.mru, lcp->cfg.max_mru);
189 prompt_Printf(arg->prompt, "\n Defaults: MRU = any (max %d), ",
192 prompt_Printf(arg->prompt, "MTU = %d (max %d), ",
193 lcp->cfg.mtu, lcp->cfg.max_mtu);
195 prompt_Printf(arg->prompt, "MTU = any (max %d), ", lcp->cfg.max_mtu);
196 prompt_Printf(arg->prompt, "ACCMAP = %08lx\n", (u_long)lcp->cfg.accmap);
197 prompt_Printf(arg->prompt, " LQR period = %us, ",
199 prompt_Printf(arg->prompt, "Open Mode = %s",
200 lcp->cfg.openmode == OPEN_PASSIVE ? "passive" : "active");
201 if (lcp->cfg.openmode > 0)
202 prompt_Printf(arg->prompt, " (delay %ds)", lcp->cfg.openmode);
203 prompt_Printf(arg->prompt, "\n FSM retry = %us, max %u Config"
204 " REQ%s, %u Term REQ%s\n", lcp->cfg.fsm.timeout,
205 lcp->cfg.fsm.maxreq, lcp->cfg.fsm.maxreq == 1 ? "" : "s",
206 lcp->cfg.fsm.maxtrm, lcp->cfg.fsm.maxtrm == 1 ? "" : "s");
207 prompt_Printf(arg->prompt, " Ident: %s\n", lcp->cfg.ident);
208 prompt_Printf(arg->prompt, "\n Negotiation:\n");
209 prompt_Printf(arg->prompt, " ACFCOMP = %s\n",
210 command_ShowNegval(lcp->cfg.acfcomp));
211 prompt_Printf(arg->prompt, " CHAP = %s\n",
212 command_ShowNegval(lcp->cfg.chap05));
214 prompt_Printf(arg->prompt, " CHAP80 = %s\n",
215 command_ShowNegval(lcp->cfg.chap80nt));
216 prompt_Printf(arg->prompt, " LANMan = %s\n",
217 command_ShowNegval(lcp->cfg.chap80lm));
218 prompt_Printf(arg->prompt, " CHAP81 = %s\n",
219 command_ShowNegval(lcp->cfg.chap81));
221 prompt_Printf(arg->prompt, " LQR = %s\n",
222 command_ShowNegval(lcp->cfg.lqr));
223 prompt_Printf(arg->prompt, " PAP = %s\n",
224 command_ShowNegval(lcp->cfg.pap));
225 prompt_Printf(arg->prompt, " PROTOCOMP = %s\n",
226 command_ShowNegval(lcp->cfg.protocomp));
234 /* Generate random number which will be used as magic number */
240 lcp_SetupCallbacks(struct lcp *lcp)
242 lcp->fsm.fn = &lcp_Callbacks;
243 lcp->fsm.FsmTimer.name = lcp_TimerNames[0];
244 lcp->fsm.OpenTimer.name = lcp_TimerNames[1];
245 lcp->fsm.StoppedTimer.name = lcp_TimerNames[2];
249 lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l,
250 const struct fsm_parent *parent)
252 /* Initialise ourselves */
253 int mincode = parent ? 1 : LCP_MINMPCODE;
255 fsm_Init(&lcp->fsm, "LCP", PROTO_LCP, mincode, LCP_MAXCODE, LogLCP,
256 bundle, l, parent, &lcp_Callbacks, lcp_TimerNames);
259 lcp->cfg.max_mru = MAX_MRU;
261 lcp->cfg.max_mtu = MAX_MTU;
263 lcp->cfg.openmode = 1;
264 lcp->cfg.lqrperiod = DEF_LQRPERIOD;
265 lcp->cfg.fsm.timeout = DEF_FSMRETRY;
266 lcp->cfg.fsm.maxreq = DEF_FSMTRIES;
267 lcp->cfg.fsm.maxtrm = DEF_FSMTRIES;
269 lcp->cfg.acfcomp = NEG_ENABLED|NEG_ACCEPTED;
270 lcp->cfg.chap05 = NEG_ACCEPTED;
272 lcp->cfg.chap80nt = NEG_ACCEPTED;
273 lcp->cfg.chap80lm = 0;
274 lcp->cfg.chap81 = NEG_ACCEPTED;
276 lcp->cfg.lqr = NEG_ACCEPTED;
277 lcp->cfg.pap = NEG_ACCEPTED;
278 lcp->cfg.protocomp = NEG_ENABLED|NEG_ACCEPTED;
279 *lcp->cfg.ident = '\0';
281 lcp_Setup(lcp, lcp->cfg.openmode);
285 lcp_Setup(struct lcp *lcp, int openmode)
287 struct physical *p = link2physical(lcp->fsm.link);
289 lcp->fsm.open_mode = openmode;
291 lcp->his_mru = DEF_MRU;
294 lcp->his_lqrperiod = 0;
295 lcp->his_acfcomp = 0;
297 lcp->his_authtype = 0;
298 lcp->his_callback.opmask = 0;
299 lcp->his_shortseq = 0;
302 if ((lcp->want_mru = lcp->cfg.mru) == 0)
303 lcp->want_mru = DEF_MRU;
304 lcp->want_mrru = lcp->fsm.bundle->ncp.mp.cfg.mrru;
305 lcp->want_shortseq = IsEnabled(lcp->fsm.bundle->ncp.mp.cfg.shortseq) ? 1 : 0;
306 lcp->want_acfcomp = IsEnabled(lcp->cfg.acfcomp) ? 1 : 0;
308 if (lcp->fsm.parent) {
309 lcp->his_accmap = 0xffffffff;
310 lcp->want_accmap = lcp->cfg.accmap;
311 lcp->his_protocomp = 0;
312 lcp->want_protocomp = IsEnabled(lcp->cfg.protocomp) ? 1 : 0;
313 lcp->want_magic = GenerateMagic();
315 if (IsEnabled(lcp->cfg.chap05)) {
316 lcp->want_auth = PROTO_CHAP;
317 lcp->want_authtype = 0x05;
319 } else if (IsEnabled(lcp->cfg.chap80nt) ||
320 IsEnabled(lcp->cfg.chap80lm)) {
321 lcp->want_auth = PROTO_CHAP;
322 lcp->want_authtype = 0x80;
323 } else if (IsEnabled(lcp->cfg.chap81)) {
324 lcp->want_auth = PROTO_CHAP;
325 lcp->want_authtype = 0x81;
327 } else if (IsEnabled(lcp->cfg.pap)) {
328 lcp->want_auth = PROTO_PAP;
329 lcp->want_authtype = 0;
332 lcp->want_authtype = 0;
335 if (p->type != PHYS_DIRECT)
336 memcpy(&lcp->want_callback, &p->dl->cfg.callback,
337 sizeof(struct callback));
339 lcp->want_callback.opmask = 0;
340 lcp->want_lqrperiod = IsEnabled(lcp->cfg.lqr) ?
341 lcp->cfg.lqrperiod * 100 : 0;
343 lcp->his_accmap = lcp->want_accmap = 0;
344 lcp->his_protocomp = lcp->want_protocomp = 1;
347 lcp->want_authtype = 0;
348 lcp->want_callback.opmask = 0;
349 lcp->want_lqrperiod = 0;
352 lcp->his_reject = lcp->my_reject = 0;
353 lcp->auth_iwait = lcp->auth_ineed = 0;
354 lcp->LcpFailedMagic = 0;
358 LcpInitRestartCounter(struct fsm *fp, int what)
360 /* Set fsm timer load */
361 struct lcp *lcp = fsm2lcp(fp);
363 fp->FsmTimer.load = lcp->cfg.fsm.timeout * SECTICKS;
366 fp->restart = lcp->cfg.fsm.maxreq;
369 fp->restart = lcp->cfg.fsm.maxtrm;
378 LcpSendConfigReq(struct fsm *fp)
380 /* Send config REQ please */
381 struct physical *p = link2physical(fp->link);
382 struct lcp *lcp = fsm2lcp(fp);
390 log_Printf(LogERROR, "%s: LcpSendConfigReq: Not a physical link !\n",
395 o = (struct lcp_opt *)buff;
396 if (!physical_IsSync(p)) {
397 if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP))
398 INC_LCP_OPT(TY_ACFCOMP, 2, o);
400 if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP))
401 INC_LCP_OPT(TY_PROTOCOMP, 2, o);
403 if (!REJECTED(lcp, TY_ACCMAP)) {
404 ua_htonl(&lcp->want_accmap, o->data);
405 INC_LCP_OPT(TY_ACCMAP, 6, o);
409 maxmru = p ? physical_DeviceMTU(p) : 0;
410 if (lcp->cfg.max_mru && (!maxmru || maxmru > lcp->cfg.max_mru))
411 maxmru = lcp->cfg.max_mru;
412 if (maxmru && lcp->want_mru > maxmru) {
413 log_Printf(LogWARN, "%s: Reducing configured MRU from %u to %u\n",
414 fp->link->name, lcp->want_mru, maxmru);
415 lcp->want_mru = maxmru;
417 if (!REJECTED(lcp, TY_MRU)) {
418 ua_htons(&lcp->want_mru, o->data);
419 INC_LCP_OPT(TY_MRU, 4, o);
422 if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM)) {
423 ua_htonl(&lcp->want_magic, o->data);
424 INC_LCP_OPT(TY_MAGICNUM, 6, o);
427 if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
429 ua_htons(&proto, o->data);
430 ua_htonl(&lcp->want_lqrperiod, o->data + 2);
431 INC_LCP_OPT(TY_QUALPROTO, 8, o);
434 switch (lcp->want_auth) {
437 ua_htons(&proto, o->data);
438 INC_LCP_OPT(TY_AUTHPROTO, 4, o);
443 ua_htons(&proto, o->data);
444 o->data[2] = lcp->want_authtype;
445 INC_LCP_OPT(TY_AUTHPROTO, 5, o);
449 if (!REJECTED(lcp, TY_CALLBACK)) {
450 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
451 *o->data = CALLBACK_AUTH;
452 INC_LCP_OPT(TY_CALLBACK, 3, o);
453 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
454 *o->data = CALLBACK_CBCP;
455 INC_LCP_OPT(TY_CALLBACK, 3, o);
456 } else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
457 int sz = strlen(lcp->want_callback.msg);
459 if (sz > sizeof o->data - 1) {
460 sz = sizeof o->data - 1;
461 log_Printf(LogWARN, "Truncating E164 data to %d octets (oops!)\n", sz);
463 *o->data = CALLBACK_E164;
464 memcpy(o->data + 1, lcp->want_callback.msg, sz);
465 INC_LCP_OPT(TY_CALLBACK, sz + 3, o);
469 if (lcp->want_mrru && !REJECTED(lcp, TY_MRRU)) {
470 ua_htons(&lcp->want_mrru, o->data);
471 INC_LCP_OPT(TY_MRRU, 4, o);
473 if (lcp->want_shortseq && !REJECTED(lcp, TY_SHORTSEQ))
474 INC_LCP_OPT(TY_SHORTSEQ, 2, o);
477 mp = &lcp->fsm.bundle->ncp.mp;
478 if (mp->cfg.enddisc.class != 0 && IsEnabled(mp->cfg.negenddisc) &&
479 !REJECTED(lcp, TY_ENDDISC)) {
480 *o->data = mp->cfg.enddisc.class;
481 memcpy(o->data+1, mp->cfg.enddisc.address, mp->cfg.enddisc.len);
482 INC_LCP_OPT(TY_ENDDISC, mp->cfg.enddisc.len + 3, o);
485 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
490 lcp_SendProtoRej(struct lcp *lcp, u_char *option, int count)
492 /* Don't understand `option' */
493 fsm_Output(&lcp->fsm, CODE_PROTOREJ, lcp->fsm.reqid, option, count,
498 lcp_SendIdentification(struct lcp *lcp)
500 static u_char id; /* Use a private id */
501 u_char msg[DEF_MRU - 3];
505 if (*lcp->cfg.ident == '\0')
508 argv[0] = lcp->cfg.ident;
511 command_Expand(exp, 1, argv, lcp->fsm.bundle, 1, getpid());
513 ua_htonl(&lcp->want_magic, msg);
514 strncpy(msg + 4, exp[0], sizeof msg - 5);
515 msg[sizeof msg - 1] = '\0';
517 log_Printf(LogLCP, "Sending ident magic %08x text %s\n", lcp->want_magic,
519 fsm_Output(&lcp->fsm, CODE_IDENT, id++, msg, 4 + strlen(msg + 4), MB_LCPOUT);
521 command_Free(1, exp);
526 lcp_RecvIdentification(struct lcp *lcp, char *data)
528 log_Printf(LogLCP, "Received ident: %s\n", data);
532 LcpSentTerminateReq(struct fsm *fp)
534 /* Term REQ just sent by FSM */
538 LcpSendTerminateAck(struct fsm *fp, u_char id)
540 /* Send Term ACK please */
541 struct physical *p = link2physical(fp->link);
543 if (p && p->dl->state == DATALINK_CBCP)
544 cbcp_ReceiveTerminateReq(p);
546 fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_LCPOUT);
550 LcpLayerStart(struct fsm *fp)
552 /* We're about to start up ! */
553 struct lcp *lcp = fsm2lcp(fp);
555 log_Printf(LogLCP, "%s: LayerStart\n", fp->link->name);
556 lcp->LcpFailedMagic = 0;
557 fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
562 LcpLayerFinish(struct fsm *fp)
565 log_Printf(LogLCP, "%s: LayerFinish\n", fp->link->name);
569 LcpLayerUp(struct fsm *fp)
572 struct physical *p = link2physical(fp->link);
573 struct lcp *lcp = fsm2lcp(fp);
575 log_Printf(LogLCP, "%s: LayerUp\n", fp->link->name);
576 physical_SetAsyncParams(p, lcp->want_accmap, lcp->his_accmap);
578 hdlc_StartTimer(&p->hdlc);
579 fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3;
581 lcp_SendIdentification(lcp);
587 LcpLayerDown(struct fsm *fp)
589 /* About to come down */
590 struct physical *p = link2physical(fp->link);
592 log_Printf(LogLCP, "%s: LayerDown\n", fp->link->name);
593 hdlc_StopTimer(&p->hdlc);
595 lcp_Setup(fsm2lcp(fp), 0);
599 E164ok(struct callback *cb, char *req, int sz)
601 char list[sizeof cb->msg], *next;
604 if (!strcmp(cb->msg, "*"))
607 strncpy(list, cb->msg, sizeof list - 1);
608 list[sizeof list - 1] = '\0';
609 for (next = strtok(list, ","); next; next = strtok(NULL, ",")) {
611 if (sz == len && !memcmp(list, req, sz))
618 LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
619 struct fsm_decode *dec)
621 /* Deal with incoming PROTO_LCP */
622 struct lcp *lcp = fsm2lcp(fp);
623 int type, length, sz, pos, op, callback_req;
624 u_int32_t magic, accmap;
625 u_short mru, phmtu, maxmtu, maxmru, wantmtu, wantmru, proto;
627 char request[20], desc[22];
629 struct physical *p = link2physical(fp->link);
631 sz = op = callback_req = 0;
633 while (plen >= sizeof(struct fsmconfig)) {
637 snprintf(request, sizeof request, " %s[%d]", protoname(type), length);
640 log_Printf(LogLCP, "%s:%s: Bad LCP length\n", fp->link->name, request);
646 mp = &lcp->fsm.bundle->ncp.mp;
647 ua_ntohs(cp + 2, &mru);
648 log_Printf(LogLCP, "%s %u\n", request, mru);
653 if (REJECTED(lcp, TY_MRRU))
654 /* Ignore his previous reject so that we REQ next time */
655 lcp->his_reject &= ~(1 << type);
658 /* Push him down to MAX_MRU */
659 lcp->his_mrru = MAX_MRU;
660 memcpy(dec->nakend, cp, 2);
661 ua_htons(&lcp->his_mrru, dec->nakend + 2);
663 } else if (mru < MIN_MRU) {
664 /* Push him up to MIN_MRU */
665 lcp->his_mrru = MIN_MRU;
666 memcpy(dec->nakend, cp, 2);
667 ua_htons(&lcp->his_mrru, dec->nakend + 2);
671 memcpy(dec->ackend, cp, 4);
680 if (REJECTED(lcp, TY_MRRU))
681 /* Must have changed his mind ! */
682 lcp->his_reject &= ~(1 << type);
685 lcp->want_mrru = MAX_MRU;
686 else if (mru < MIN_MRU)
687 lcp->want_mrru = MIN_MRU;
689 lcp->want_mrru = mru;
691 /* else we honour our config and don't send the suggested REQ */
694 lcp->his_reject |= (1 << type);
695 lcp->want_mrru = 0; /* Ah well, no multilink :-( */
702 ua_ntohs(cp + 2, &mru);
703 log_Printf(LogLCP, "%s %d\n", request, mru);
707 maxmtu = p ? physical_DeviceMTU(p) : 0;
708 if (lcp->cfg.max_mtu && (!maxmtu || maxmtu > lcp->cfg.max_mtu))
709 maxmtu = lcp->cfg.max_mtu;
710 wantmtu = lcp->cfg.mtu;
711 if (maxmtu && wantmtu > maxmtu) {
712 log_Printf(LogWARN, "%s: Reducing configured MTU from %u to %u\n",
713 fp->link->name, wantmtu, maxmtu);
717 if (maxmtu && mru > maxmtu) {
718 lcp->his_mru = maxmtu;
719 memcpy(dec->nakend, cp, 2);
720 ua_htons(&lcp->his_mru, dec->nakend + 2);
722 } else if (wantmtu && mru < wantmtu) {
723 /* Push him up to MTU or MIN_MRU */
724 lcp->his_mru = wantmtu;
725 memcpy(dec->nakend, cp, 2);
726 ua_htons(&lcp->his_mru, dec->nakend + 2);
730 memcpy(dec->ackend, cp, 4);
735 maxmru = p ? physical_DeviceMTU(p) : 0;
736 if (lcp->cfg.max_mru && (!maxmru || maxmru > lcp->cfg.max_mru))
737 maxmru = lcp->cfg.max_mru;
738 wantmru = lcp->cfg.mru > maxmru ? maxmru : lcp->cfg.mru;
740 if (wantmru && mru > wantmru)
741 lcp->want_mru = wantmru;
742 else if (mru > maxmru)
743 lcp->want_mru = maxmru;
744 else if (mru < MIN_MRU)
745 lcp->want_mru = MIN_MRU;
750 lcp->his_reject |= (1 << type);
756 ua_ntohl(cp + 2, &accmap);
757 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)accmap);
761 lcp->his_accmap = accmap;
762 memcpy(dec->ackend, cp, 6);
766 lcp->want_accmap = accmap;
769 lcp->his_reject |= (1 << type);
775 ua_ntohs(cp + 2, &proto);
776 log_Printf(LogLCP, "%s 0x%04x (%s)\n", request, proto,
777 Auth2Nam(proto, length > 4 ? cp[4] : 0));
784 log_Printf(LogLCP, " Bad length!\n");
787 if (IsAccepted(lcp->cfg.pap)) {
788 lcp->his_auth = proto;
789 lcp->his_authtype = 0;
790 memcpy(dec->ackend, cp, length);
791 dec->ackend += length;
792 } else if (IsAccepted(lcp->cfg.chap05)) {
793 *dec->nakend++ = *cp;
795 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
796 *dec->nakend++ = (unsigned char) PROTO_CHAP;
797 *dec->nakend++ = 0x05;
799 } else if (IsAccepted(lcp->cfg.chap80nt) ||
800 IsAccepted(lcp->cfg.chap80lm)) {
801 *dec->nakend++ = *cp;
803 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
804 *dec->nakend++ = (unsigned char) PROTO_CHAP;
805 *dec->nakend++ = 0x80;
806 } else if (IsAccepted(lcp->cfg.chap81)) {
807 *dec->nakend++ = *cp;
809 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
810 *dec->nakend++ = (unsigned char) PROTO_CHAP;
811 *dec->nakend++ = 0x81;
819 log_Printf(LogLCP, " Bad length!\n");
822 if ((cp[4] == 0x05 && IsAccepted(lcp->cfg.chap05))
824 || (cp[4] == 0x80 && (IsAccepted(lcp->cfg.chap80nt) ||
825 (IsAccepted(lcp->cfg.chap80lm))))
826 || (cp[4] == 0x81 && IsAccepted(lcp->cfg.chap81))
829 lcp->his_auth = proto;
830 lcp->his_authtype = cp[4];
831 memcpy(dec->ackend, cp, length);
832 dec->ackend += length;
836 log_Printf(LogWARN, "CHAP 0x80 not available without DES\n");
837 } else if (cp[4] == 0x81) {
838 log_Printf(LogWARN, "CHAP 0x81 not available without DES\n");
842 log_Printf(LogWARN, "%s not supported\n",
843 Auth2Nam(PROTO_CHAP, cp[4]));
845 if (IsAccepted(lcp->cfg.chap05)) {
846 *dec->nakend++ = *cp;
848 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
849 *dec->nakend++ = (unsigned char) PROTO_CHAP;
850 *dec->nakend++ = 0x05;
852 } else if (IsAccepted(lcp->cfg.chap80nt) ||
853 IsAccepted(lcp->cfg.chap80lm)) {
854 *dec->nakend++ = *cp;
856 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
857 *dec->nakend++ = (unsigned char) PROTO_CHAP;
858 *dec->nakend++ = 0x80;
859 } else if (IsAccepted(lcp->cfg.chap81)) {
860 *dec->nakend++ = *cp;
862 *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
863 *dec->nakend++ = (unsigned char) PROTO_CHAP;
864 *dec->nakend++ = 0x81;
866 } else if (IsAccepted(lcp->cfg.pap)) {
867 *dec->nakend++ = *cp;
869 *dec->nakend++ = (unsigned char) (PROTO_PAP >> 8);
870 *dec->nakend++ = (unsigned char) PROTO_PAP;
877 log_Printf(LogLCP, "%s 0x%04x - not recognised, NAK\n",
879 memcpy(dec->nakend, cp, length);
880 dec->nakend += length;
887 if (IsEnabled(lcp->cfg.pap)) {
888 lcp->want_auth = PROTO_PAP;
889 lcp->want_authtype = 0;
891 log_Printf(LogLCP, "Peer will only send PAP (not enabled)\n");
892 lcp->his_reject |= (1 << type);
896 if (cp[4] == 0x05 && IsEnabled(lcp->cfg.chap05)) {
897 lcp->want_auth = PROTO_CHAP;
898 lcp->want_authtype = 0x05;
900 } else if (cp[4] == 0x80 && (IsEnabled(lcp->cfg.chap80nt) ||
901 IsEnabled(lcp->cfg.chap80lm))) {
902 lcp->want_auth = PROTO_CHAP;
903 lcp->want_authtype = 0x80;
904 } else if (cp[4] == 0x81 && IsEnabled(lcp->cfg.chap81)) {
905 lcp->want_auth = PROTO_CHAP;
906 lcp->want_authtype = 0x81;
911 log_Printf(LogLCP, "Peer will only send MSCHAP (not available"
913 } else if (cp[4] == 0x81) {
914 log_Printf(LogLCP, "Peer will only send MSCHAPV2 (not available"
918 log_Printf(LogLCP, "Peer will only send %s (not %s)\n",
919 Auth2Nam(PROTO_CHAP, cp[4]),
921 (cp[4] == 0x80 || cp[4] == 0x81) ? "configured" :
924 lcp->his_reject |= (1 << type);
928 /* We've been NAK'd with something we don't understand :-( */
929 lcp->his_reject |= (1 << type);
934 lcp->his_reject |= (1 << type);
940 req = (struct lqrreq *)cp;
941 log_Printf(LogLCP, "%s proto %x, interval %lums\n",
942 request, ntohs(req->proto), (u_long)ntohl(req->period) * 10);
945 if (ntohs(req->proto) != PROTO_LQR || !IsAccepted(lcp->cfg.lqr))
948 lcp->his_lqrperiod = ntohl(req->period);
949 if (lcp->his_lqrperiod < MIN_LQRPERIOD * 100)
950 lcp->his_lqrperiod = MIN_LQRPERIOD * 100;
951 req->period = htonl(lcp->his_lqrperiod);
952 memcpy(dec->ackend, cp, length);
953 dec->ackend += length;
959 lcp->his_reject |= (1 << type);
965 ua_ntohl(cp + 2, &magic);
966 log_Printf(LogLCP, "%s 0x%08lx\n", request, (u_long)magic);
970 if (lcp->want_magic) {
971 /* Validate magic number */
972 if (magic == lcp->want_magic) {
975 log_Printf(LogLCP, "Magic is same (%08lx) - %d times\n",
976 (u_long)magic, ++lcp->LcpFailedMagic);
977 lcp->want_magic = GenerateMagic();
978 memcpy(dec->nakend, cp, 6);
980 ualarm(TICKUNIT * (4 + 4 * lcp->LcpFailedMagic), 0);
981 sigemptyset(&emptyset);
982 sigsuspend(&emptyset);
984 lcp->his_magic = magic;
985 memcpy(dec->ackend, cp, length);
986 dec->ackend += length;
987 lcp->LcpFailedMagic = 0;
994 log_Printf(LogLCP, " Magic 0x%08lx is NAKed!\n", (u_long)magic);
995 lcp->want_magic = GenerateMagic();
998 log_Printf(LogLCP, " Magic 0x%08x is REJected!\n", magic);
1000 lcp->his_reject |= (1 << type);
1006 log_Printf(LogLCP, "%s\n", request);
1008 switch (mode_type) {
1010 if (IsAccepted(lcp->cfg.protocomp)) {
1011 lcp->his_protocomp = 1;
1012 memcpy(dec->ackend, cp, 2);
1016 /* MorningStar before v1.3 needs NAK */
1017 memcpy(dec->nakend, cp, 2);
1026 lcp->want_protocomp = 0;
1027 lcp->his_reject |= (1 << type);
1033 log_Printf(LogLCP, "%s\n", request);
1034 switch (mode_type) {
1036 if (IsAccepted(lcp->cfg.acfcomp)) {
1037 lcp->his_acfcomp = 1;
1038 memcpy(dec->ackend, cp, 2);
1042 /* MorningStar before v1.3 needs NAK */
1043 memcpy(dec->nakend, cp, 2);
1052 lcp->want_acfcomp = 0;
1053 lcp->his_reject |= (1 << type);
1059 log_Printf(LogLCP, "%s\n", request);
1060 switch (mode_type) {
1076 log_Printf(LogLCP, "%s Auth\n", request);
1078 case CALLBACK_DIALSTRING:
1079 log_Printf(LogLCP, "%s Dialstring %.*s\n", request, sz, cp + 3);
1081 case CALLBACK_LOCATION:
1082 log_Printf(LogLCP, "%s Location %.*s\n", request, sz, cp + 3);
1085 log_Printf(LogLCP, "%s E.164 (%.*s)\n", request, sz, cp + 3);
1088 log_Printf(LogLCP, "%s Name %.*s\n", request, sz, cp + 3);
1091 log_Printf(LogLCP, "%s CBCP\n", request);
1094 log_Printf(LogLCP, "%s ???\n", request);
1098 switch (mode_type) {
1101 if (p->type != PHYS_DIRECT)
1103 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(op)) &&
1104 (op != CALLBACK_AUTH || p->link.lcp.want_auth) &&
1105 (op != CALLBACK_E164 ||
1106 E164ok(&p->dl->cfg.callback, cp + 3, sz))) {
1107 lcp->his_callback.opmask = CALLBACK_BIT(op);
1108 if (sz > sizeof lcp->his_callback.msg - 1) {
1109 sz = sizeof lcp->his_callback.msg - 1;
1110 log_Printf(LogWARN, "Truncating option arg to %d octets\n", sz);
1112 memcpy(lcp->his_callback.msg, cp + 3, sz);
1113 lcp->his_callback.msg[sz] = '\0';
1114 memcpy(dec->ackend, cp, sz + 3);
1115 dec->ackend += sz + 3;
1116 } else if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1117 p->link.lcp.auth_ineed) {
1118 *dec->nakend++ = *cp;
1120 *dec->nakend++ = CALLBACK_AUTH;
1121 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP)) {
1122 *dec->nakend++ = *cp;
1124 *dec->nakend++ = CALLBACK_CBCP;
1125 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164)) {
1126 *dec->nakend++ = *cp;
1128 *dec->nakend++ = CALLBACK_E164;
1129 } else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) {
1130 log_Printf(LogWARN, "Cannot insist on auth callback without"
1131 " PAP or CHAP enabled !\n");
1132 *dec->nakend++ = *cp;
1138 /* We don't do what he NAKs with, we do things in our preferred order */
1139 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_AUTH))
1140 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_AUTH);
1141 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1142 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_CBCP);
1143 else if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1144 lcp->want_callback.opmask &= ~CALLBACK_BIT(CALLBACK_E164);
1145 if (lcp->want_callback.opmask == CALLBACK_BIT(CALLBACK_NONE)) {
1146 log_Printf(LogPHASE, "Peer NAKd all callbacks, trying none\n");
1147 lcp->want_callback.opmask = 0;
1148 } else if (!lcp->want_callback.opmask) {
1149 log_Printf(LogPHASE, "Peer NAKd last configured callback\n");
1150 fsm_Close(&lcp->fsm);
1154 if (lcp->want_callback.opmask & CALLBACK_BIT(CALLBACK_NONE)) {
1155 lcp->his_reject |= (1 << type);
1156 lcp->want_callback.opmask = 0;
1158 log_Printf(LogPHASE, "Peer rejected *required* callback\n");
1159 fsm_Close(&lcp->fsm);
1166 mp = &lcp->fsm.bundle->ncp.mp;
1167 log_Printf(LogLCP, "%s\n", request);
1169 switch (mode_type) {
1171 if (lcp->want_mrru && IsAccepted(mp->cfg.shortseq)) {
1172 lcp->his_shortseq = 1;
1173 memcpy(dec->ackend, cp, length);
1174 dec->ackend += length;
1180 * He's trying to get us to ask for short sequence numbers.
1181 * We ignore the NAK and honour our configuration file instead.
1185 lcp->his_reject |= (1 << type);
1186 lcp->want_shortseq = 0; /* For when we hit MP */
1192 mp = &lcp->fsm.bundle->ncp.mp;
1193 log_Printf(LogLCP, "%s %s\n", request,
1194 mp_Enddisc(cp[2], cp + 3, length - 3));
1195 switch (mode_type) {
1198 log_Printf(LogLCP, " ENDDISC rejected - not a physical link\n");
1200 } else if (!IsAccepted(mp->cfg.negenddisc))
1202 else if (length-3 < sizeof p->dl->peer.enddisc.address &&
1203 cp[2] <= MAX_ENDDISC_CLASS) {
1204 p->dl->peer.enddisc.class = cp[2];
1205 p->dl->peer.enddisc.len = length-3;
1206 memcpy(p->dl->peer.enddisc.address, cp + 3, length - 3);
1207 p->dl->peer.enddisc.address[length - 3] = '\0';
1208 /* XXX: If mp->active, compare and NAK with mp->peer ? */
1209 memcpy(dec->ackend, cp, length);
1210 dec->ackend += length;
1212 if (cp[2] > MAX_ENDDISC_CLASS)
1213 log_Printf(LogLCP, " ENDDISC rejected - unrecognised class %d\n",
1216 log_Printf(LogLCP, " ENDDISC rejected - local max length is %ld\n",
1217 (long)(sizeof p->dl->peer.enddisc.address - 1));
1222 case MODE_NAK: /* Treat this as a REJ, we don't vary our disc (yet) */
1224 lcp->his_reject |= (1 << type);
1230 sz = (sizeof desc - 2) / 2;
1231 if (sz > length - 2)
1234 desc[0] = sz ? ' ' : '\0';
1235 for (pos = 0; sz--; pos++)
1236 sprintf(desc+(pos<<1)+1, "%02x", cp[pos+2]);
1238 log_Printf(LogLCP, "%s%s\n", request, desc);
1240 if (mode_type == MODE_REQ) {
1242 if (length > sizeof dec->rej - (dec->rejend - dec->rej)) {
1243 length = sizeof dec->rej - (dec->rejend - dec->rej);
1244 log_Printf(LogLCP, "Can't REJ length %d - trunating to %d\n",
1247 memcpy(dec->rejend, cp, length);
1248 dec->rejend += length;
1249 lcp->my_reject |= (1 << type);
1250 if (length != cp[1])
1251 length = 0; /* force our way out of the loop */
1259 if (mode_type != MODE_NOP) {
1260 if (mode_type == MODE_REQ && p && p->type == PHYS_DIRECT &&
1261 p->dl->cfg.callback.opmask && !callback_req &&
1262 !(p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_NONE))) {
1263 /* We *REQUIRE* that the peer requests callback */
1264 *dec->nakend++ = TY_CALLBACK;
1266 if ((p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_AUTH)) &&
1267 p->link.lcp.want_auth)
1268 *dec->nakend++ = CALLBACK_AUTH;
1269 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_CBCP))
1270 *dec->nakend++ = CALLBACK_CBCP;
1271 else if (p->dl->cfg.callback.opmask & CALLBACK_BIT(CALLBACK_E164))
1272 *dec->nakend++ = CALLBACK_E164;
1274 log_Printf(LogWARN, "Cannot insist on auth callback without"
1275 " PAP or CHAP enabled !\n");
1276 dec->nakend[-1] = 2; /* XXX: Silly ! */
1279 if (mode_type == MODE_REQ && !lcp->mru_req) {
1281 phmtu = p ? physical_DeviceMTU(p) : 0;
1282 if (phmtu && mru > phmtu)
1284 if (mru > lcp->cfg.max_mtu)
1285 mru = lcp->cfg.max_mtu;
1286 if (mru < DEF_MRU) {
1287 /* Don't let the peer use the default MRU */
1288 lcp->his_mru = lcp->cfg.mtu && lcp->cfg.mtu < mru ? lcp->cfg.mtu : mru;
1289 *dec->nakend++ = TY_MRU;
1291 ua_htons(&lcp->his_mru, dec->nakend);
1293 lcp->mru_req = 1; /* Don't keep NAK'ing this */
1296 if (dec->rejend != dec->rej) {
1297 /* rejects are preferred */
1298 dec->ackend = dec->ack;
1299 dec->nakend = dec->nak;
1300 } else if (dec->nakend != dec->nak)
1302 dec->ackend = dec->ack;
1306 extern struct mbuf *
1307 lcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
1309 /* Got PROTO_LCP from link */
1310 m_settype(bp, MB_LCPIN);
1311 fsm_Input(&l->lcp.fsm, bp);