Deleted Added
full compact
lcp.c (28679) lcp.c (28974)
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 *
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 * $Id: lcp.c,v 1.26 1997/08/20 23:47:45 brian Exp $
20 * $Id: lcp.c,v 1.27 1997/08/25 00:29:15 brian Exp $
21 *
22 * TODO:
23 * o Validate magic number received from peer.
24 * o Limit data field length by MRU
25 */
26#include <sys/time.h>
27#include "fsm.h"
28#include "lcp.h"
29#include "ipcp.h"
30#include "lcpproto.h"
31#include "os.h"
32#include "hdlc.h"
33#include "ccp.h"
34#include "lqr.h"
35#include "phase.h"
36#include "loadalias.h"
37#include "vars.h"
38#include "auth.h"
39#include <arpa/inet.h>
40
41extern void IpcpUp();
42extern void IpcpOpen();
43extern void SetLinkParams(struct lcpstate *);
44extern void Prompt();
45extern void StopIdleTimer();
46extern void OsLinkdown();
47extern void Cleanup();
48extern struct pppTimer IpcpReportTimer;
49extern int randinit;
50
51struct lcpstate LcpInfo;
52
53static void LcpSendConfigReq(struct fsm *);
54static void LcpSendTerminateReq(struct fsm * fp);
55static void LcpSendTerminateAck(struct fsm * fp);
56static void LcpDecodeConfig(u_char * cp, int flen, int mode);
57static void LcpInitRestartCounter(struct fsm *);
58static void LcpLayerUp(struct fsm *);
59static void LcpLayerDown(struct fsm *);
60static void LcpLayerStart(struct fsm *);
61static void LcpLayerFinish(struct fsm *);
62
63extern int ModemSpeed();
64
65#define REJECTED(p, x) (p->his_reject & (1<<x))
66
67static char *cftypes[] = {
68 "???", "MRU", "ACCMAP", "AUTHPROTO", "QUALPROTO", "MAGICNUM",
69 "RESERVED", "PROTOCOMP", "ACFCOMP", "FCSALT", "SDP",
70};
71
72struct fsm LcpFsm = {
73 "LCP", /* Name of protocol */
74 PROTO_LCP, /* Protocol Number */
75 LCP_MAXCODE,
76 OPEN_ACTIVE,
77 ST_INITIAL, /* State of machine */
78 0, 0, 0,
79 0,
80 {0, 0, 0, NULL, NULL, NULL},
81 {0, 0, 0, NULL, NULL, NULL},
82 LogLCP,
83
84 LcpLayerUp,
85 LcpLayerDown,
86 LcpLayerStart,
87 LcpLayerFinish,
88 LcpInitRestartCounter,
89 LcpSendConfigReq,
90 LcpSendTerminateReq,
91 LcpSendTerminateAck,
92 LcpDecodeConfig,
93};
94
95static struct pppTimer LcpReportTimer;
96
97char *PhaseNames[] = {
98 "Dead", "Establish", "Authenticate", "Network", "Terminate"
99};
100
101void
102NewPhase(int new)
103{
104 struct lcpstate *lcp = &LcpInfo;
105
106 phase = new;
107 LogPrintf(LogPHASE, "NewPhase: %s\n", PhaseNames[phase]);
108 switch (phase) {
109 case PHASE_AUTHENTICATE:
110 lcp->auth_ineed = lcp->want_auth;
111 lcp->auth_iwait = lcp->his_auth;
112 if (lcp->his_auth || lcp->want_auth) {
113 LogPrintf(LogPHASE, " his = %x, mine = %x\n", lcp->his_auth, lcp->want_auth);
114 if (lcp->his_auth == PROTO_PAP)
115 StartAuthChallenge(&AuthPapInfo);
116 if (lcp->want_auth == PROTO_CHAP)
117 StartAuthChallenge(&AuthChapInfo);
118 } else
119 NewPhase(PHASE_NETWORK);
120 break;
121 case PHASE_NETWORK:
122 IpcpUp();
123 IpcpOpen();
124 CcpUp();
125 CcpOpen();
126 break;
127 case PHASE_DEAD:
128 if (mode & MODE_DIRECT)
129 Cleanup(EX_DEAD);
130 if (mode & MODE_BACKGROUND && reconnectState != RECON_TRUE)
131 Cleanup(EX_DEAD);
132 break;
133 }
134}
135
136static void
137LcpReportTime()
138{
139 if (LogIsKept(LogDEBUG)) {
140 time_t t;
141
142 time(&t);
21 *
22 * TODO:
23 * o Validate magic number received from peer.
24 * o Limit data field length by MRU
25 */
26#include <sys/time.h>
27#include "fsm.h"
28#include "lcp.h"
29#include "ipcp.h"
30#include "lcpproto.h"
31#include "os.h"
32#include "hdlc.h"
33#include "ccp.h"
34#include "lqr.h"
35#include "phase.h"
36#include "loadalias.h"
37#include "vars.h"
38#include "auth.h"
39#include <arpa/inet.h>
40
41extern void IpcpUp();
42extern void IpcpOpen();
43extern void SetLinkParams(struct lcpstate *);
44extern void Prompt();
45extern void StopIdleTimer();
46extern void OsLinkdown();
47extern void Cleanup();
48extern struct pppTimer IpcpReportTimer;
49extern int randinit;
50
51struct lcpstate LcpInfo;
52
53static void LcpSendConfigReq(struct fsm *);
54static void LcpSendTerminateReq(struct fsm * fp);
55static void LcpSendTerminateAck(struct fsm * fp);
56static void LcpDecodeConfig(u_char * cp, int flen, int mode);
57static void LcpInitRestartCounter(struct fsm *);
58static void LcpLayerUp(struct fsm *);
59static void LcpLayerDown(struct fsm *);
60static void LcpLayerStart(struct fsm *);
61static void LcpLayerFinish(struct fsm *);
62
63extern int ModemSpeed();
64
65#define REJECTED(p, x) (p->his_reject & (1<<x))
66
67static char *cftypes[] = {
68 "???", "MRU", "ACCMAP", "AUTHPROTO", "QUALPROTO", "MAGICNUM",
69 "RESERVED", "PROTOCOMP", "ACFCOMP", "FCSALT", "SDP",
70};
71
72struct fsm LcpFsm = {
73 "LCP", /* Name of protocol */
74 PROTO_LCP, /* Protocol Number */
75 LCP_MAXCODE,
76 OPEN_ACTIVE,
77 ST_INITIAL, /* State of machine */
78 0, 0, 0,
79 0,
80 {0, 0, 0, NULL, NULL, NULL},
81 {0, 0, 0, NULL, NULL, NULL},
82 LogLCP,
83
84 LcpLayerUp,
85 LcpLayerDown,
86 LcpLayerStart,
87 LcpLayerFinish,
88 LcpInitRestartCounter,
89 LcpSendConfigReq,
90 LcpSendTerminateReq,
91 LcpSendTerminateAck,
92 LcpDecodeConfig,
93};
94
95static struct pppTimer LcpReportTimer;
96
97char *PhaseNames[] = {
98 "Dead", "Establish", "Authenticate", "Network", "Terminate"
99};
100
101void
102NewPhase(int new)
103{
104 struct lcpstate *lcp = &LcpInfo;
105
106 phase = new;
107 LogPrintf(LogPHASE, "NewPhase: %s\n", PhaseNames[phase]);
108 switch (phase) {
109 case PHASE_AUTHENTICATE:
110 lcp->auth_ineed = lcp->want_auth;
111 lcp->auth_iwait = lcp->his_auth;
112 if (lcp->his_auth || lcp->want_auth) {
113 LogPrintf(LogPHASE, " his = %x, mine = %x\n", lcp->his_auth, lcp->want_auth);
114 if (lcp->his_auth == PROTO_PAP)
115 StartAuthChallenge(&AuthPapInfo);
116 if (lcp->want_auth == PROTO_CHAP)
117 StartAuthChallenge(&AuthChapInfo);
118 } else
119 NewPhase(PHASE_NETWORK);
120 break;
121 case PHASE_NETWORK:
122 IpcpUp();
123 IpcpOpen();
124 CcpUp();
125 CcpOpen();
126 break;
127 case PHASE_DEAD:
128 if (mode & MODE_DIRECT)
129 Cleanup(EX_DEAD);
130 if (mode & MODE_BACKGROUND && reconnectState != RECON_TRUE)
131 Cleanup(EX_DEAD);
132 break;
133 }
134}
135
136static void
137LcpReportTime()
138{
139 if (LogIsKept(LogDEBUG)) {
140 time_t t;
141
142 time(&t);
143 LogPrintf(LogDEBUG, "LcpReportTime: %s", ctime(&t));
143 LogPrintf(LogDEBUG, "LcpReportTime: %s\n", ctime(&t));
144 }
145 StopTimer(&LcpReportTimer);
146 LcpReportTimer.state = TIMER_STOPPED;
147 StartTimer(&LcpReportTimer);
148 HdlcErrorCheck();
149}
150
151int
152ReportLcpStatus()
153{
154 struct lcpstate *lcp = &LcpInfo;
155 struct fsm *fp = &LcpFsm;
156
157 if (!VarTerm)
158 return 1;
159
160 fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
161 fprintf(VarTerm,
162 " his side: MRU %ld, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d, MAGIC %08lx,\n"
163 " REJECT %04lx\n",
164 lcp->his_mru, lcp->his_accmap, lcp->his_protocomp, lcp->his_acfcomp,
165 lcp->his_magic, lcp->his_reject);
166 fprintf(VarTerm,
167 " my side: MRU %ld, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d, MAGIC %08lx,\n"
168 " REJECT %04lx\n",
169 lcp->want_mru, lcp->want_accmap, lcp->want_protocomp, lcp->want_acfcomp,
170 lcp->want_magic, lcp->my_reject);
171 fprintf(VarTerm, "\nDefaults: MRU = %ld, ACCMAP = %08x\t", VarMRU, VarAccmap);
172 fprintf(VarTerm, "Open Mode: %s\n", (VarOpenMode == OPEN_ACTIVE) ? "active" : "passive");
173 return 0;
174}
175
176/*
177 * Generate random number which will be used as magic number.
178 */
179u_long
180GenerateMagic()
181{
182 if (!randinit) {
183 randinit = 1;
184 srandomdev();
185 }
186 return (random());
187}
188
189void
190LcpInit()
191{
192 struct lcpstate *lcp = &LcpInfo;
193
194 FsmInit(&LcpFsm);
195 HdlcInit();
196
197 bzero(lcp, sizeof(struct lcpstate));
198 lcp->want_mru = VarMRU;
199 lcp->his_mru = DEF_MRU;
200 lcp->his_accmap = 0xffffffff;
201 lcp->want_accmap = VarAccmap;
202 lcp->want_magic = GenerateMagic();
203 lcp->want_auth = lcp->his_auth = 0;
204 if (Enabled(ConfChap))
205 lcp->want_auth = PROTO_CHAP;
206 else if (Enabled(ConfPap))
207 lcp->want_auth = PROTO_PAP;
208 if (Enabled(ConfLqr))
209 lcp->want_lqrperiod = VarLqrTimeout * 100;
210 if (Enabled(ConfAcfcomp))
211 lcp->want_acfcomp = 1;
212 if (Enabled(ConfProtocomp))
213 lcp->want_protocomp = 1;
214 LcpFsm.maxconfig = 10;
215}
216
217static void
218LcpInitRestartCounter(struct fsm * fp)
219{
220 fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
221 fp->restart = 5;
222}
223
224void
225PutConfValue(u_char ** cpp, char **types, u_char type, int len, u_long val)
226{
227 u_char *cp;
228 struct in_addr ina;
229
230 cp = *cpp;
231 *cp++ = type;
232 *cp++ = len;
233 if (len == 6) {
234 if (type == TY_IPADDR) {
235 ina.s_addr = htonl(val);
236 LogPrintf(LogLCP, " %s [%d] %s\n",
237 types[type], len, inet_ntoa(ina));
238 } else {
239 LogPrintf(LogLCP, " %s [%d] %08x\n", types[type], len, val);
240 }
241 *cp++ = (val >> 24) & 0377;
242 *cp++ = (val >> 16) & 0377;
243 } else
244 LogPrintf(LogLCP, " %s [%d] %d\n", types[type], len, val);
245 *cp++ = (val >> 8) & 0377;
246 *cp++ = val & 0377;
247 *cpp = cp;
248}
249
250static void
251LcpSendConfigReq(struct fsm * fp)
252{
253 u_char *cp;
254 struct lcpstate *lcp = &LcpInfo;
255 struct lqrreq *req;
256
257 LogPrintf(LogLCP, "LcpSendConfigReq\n");
258 cp = ReqBuff;
259 if (!DEV_IS_SYNC) {
260 if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP)) {
261 *cp++ = TY_ACFCOMP;
262 *cp++ = 2;
263 LogPrintf(LogLCP, " %s\n", cftypes[TY_ACFCOMP]);
264 }
265 if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP)) {
266 *cp++ = TY_PROTOCOMP;
267 *cp++ = 2;
268 LogPrintf(LogLCP, " %s\n", cftypes[TY_PROTOCOMP]);
269 }
270 if (!REJECTED(lcp, TY_ACCMAP))
271 PutConfValue(&cp, cftypes, TY_ACCMAP, 6, lcp->want_accmap);
272 }
273 if (!REJECTED(lcp, TY_MRU))
274 PutConfValue(&cp, cftypes, TY_MRU, 4, lcp->want_mru);
275 if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM))
276 PutConfValue(&cp, cftypes, TY_MAGICNUM, 6, lcp->want_magic);
277 if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
278 req = (struct lqrreq *) cp;
279 req->type = TY_QUALPROTO;
280 req->length = sizeof(struct lqrreq);
281 req->proto = htons(PROTO_LQR);
282 req->period = htonl(lcp->want_lqrperiod);
283 cp += sizeof(struct lqrreq);
284 LogPrintf(LogLCP, " %s (%d)\n", cftypes[TY_QUALPROTO], lcp->want_lqrperiod);
285 }
286 switch (lcp->want_auth) {
287 case PROTO_PAP:
288 PutConfValue(&cp, cftypes, TY_AUTHPROTO, 4, lcp->want_auth);
289 break;
290 case PROTO_CHAP:
291 PutConfValue(&cp, cftypes, TY_AUTHPROTO, 5, lcp->want_auth);
292 *cp++ = 5; /* Use MD5 */
293 break;
294 }
295 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
296}
297
298void
299LcpSendProtoRej(u_char * option, int count)
300{
301 struct fsm *fp = &LcpFsm;
302
303 LogPrintf(LogLCP, "LcpSendProtoRej\n");
304 FsmOutput(fp, CODE_PROTOREJ, fp->reqid, option, count);
305}
306
307static void
308LcpSendTerminateReq(struct fsm * fp)
309{
310 /* Most thins are done in fsm layer. Nothing to to. */
311}
312
313static void
314LcpSendTerminateAck(struct fsm * fp)
315{
316 LogPrintf(LogLCP, "LcpSendTerminateAck.\n");
317 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
318}
319
320static void
321LcpLayerStart(struct fsm * fp)
322{
323 LogPrintf(LogLCP, "LcpLayerStart\n");
324 NewPhase(PHASE_ESTABLISH);
325}
326
327static void
328StopAllTimers()
329{
330 StopTimer(&LcpReportTimer);
331 StopTimer(&IpcpReportTimer);
332 StopIdleTimer();
333 StopTimer(&AuthPapInfo.authtimer);
334 StopTimer(&AuthChapInfo.authtimer);
335 StopLqrTimer();
336}
337
338static void
339LcpLayerFinish(struct fsm * fp)
340{
341 LogPrintf(LogLCP, "LcpLayerFinish\n");
342 OsCloseLink(1);
343 NewPhase(PHASE_DEAD);
344 StopAllTimers();
345 (void) OsInterfaceDown(0);
346 Prompt();
347}
348
349static void
350LcpLayerUp(struct fsm * fp)
351{
352 LogPrintf(LogLCP, "LcpLayerUp\n");
353 OsSetInterfaceParams(23, LcpInfo.his_mru, ModemSpeed());
354 SetLinkParams(&LcpInfo);
355
356 NewPhase(PHASE_AUTHENTICATE);
357
358 StartLqm();
359 StopTimer(&LcpReportTimer);
360 LcpReportTimer.state = TIMER_STOPPED;
361 LcpReportTimer.load = 60 * SECTICKS;
362 LcpReportTimer.func = LcpReportTime;
363 StartTimer(&LcpReportTimer);
364}
365
366static void
367LcpLayerDown(struct fsm * fp)
368{
369 LogPrintf(LogLCP, "LcpLayerDown\n");
370 StopAllTimers();
371 OsLinkdown();
372 NewPhase(PHASE_TERMINATE);
373}
374
375void
376LcpUp()
377{
378 FsmUp(&LcpFsm);
379}
380
381void
382LcpDown()
383{ /* Sudden death */
384 NewPhase(PHASE_DEAD);
385 StopAllTimers();
386 FsmDown(&LcpFsm);
387}
388
389void
390LcpOpen(int mode)
391{
392 LcpFsm.open_mode = mode;
393 FsmOpen(&LcpFsm);
394}
395
396void
397LcpClose()
398{
399 FsmClose(&LcpFsm);
400}
401
402/*
403 * XXX: Should validate option length
404 */
405static void
406LcpDecodeConfig(u_char * cp, int plen, int mode)
407{
408 char *request;
409 int type, length, mru;
410 u_long *lp, magic, accmap;
411 u_short *sp, proto;
412 struct lqrreq *req;
413
414 ackp = AckBuff;
415 nakp = NakBuff;
416 rejp = RejBuff;
417
418 while (plen >= sizeof(struct fsmconfig)) {
419 type = *cp;
420 length = cp[1];
421 if (type <= TY_ACFCOMP)
422 request = cftypes[type];
423 else
424 request = "???";
425
426 switch (type) {
427 case TY_MRU:
428 sp = (u_short *) (cp + 2);
429 mru = htons(*sp);
430 LogPrintf(LogLCP, " %s %d\n", request, mru);
431
432 switch (mode) {
433 case MODE_REQ:
434 if (mru > MAX_MRU) {
435 *sp = htons(MAX_MRU);
436 bcopy(cp, nakp, 4);
437 nakp += 4;
438 } else if (mru < MIN_MRU) {
439 *sp = htons(MIN_MRU);
440 bcopy(cp, nakp, 4);
441 nakp += 4;
442 } else {
443 LcpInfo.his_mru = mru;
444 bcopy(cp, ackp, 4);
445 ackp += 4;
446 }
447 break;
448 case MODE_NAK:
449 if (mru >= MIN_MRU || mru <= MAX_MRU)
450 LcpInfo.want_mru = mru;
451 break;
452 case MODE_REJ:
453 LcpInfo.his_reject |= (1 << type);
454 break;
455 }
456 break;
457 case TY_ACCMAP:
458 lp = (u_long *) (cp + 2);
459 accmap = htonl(*lp);
460 LogPrintf(LogLCP, " %s %08x\n", request, accmap);
461
462 switch (mode) {
463 case MODE_REQ:
464 LcpInfo.his_accmap = accmap;
465 bcopy(cp, ackp, 6);
466 ackp += 6;
467 break;
468 case MODE_NAK:
469 LcpInfo.want_accmap = accmap;
470 break;
471 case MODE_REJ:
472 LcpInfo.his_reject |= (1 << type);
473 break;
474 }
475 break;
476 case TY_AUTHPROTO:
477 sp = (u_short *) (cp + 2);
478 proto = ntohs(*sp);
479 LogPrintf(LogLCP, " %s proto = %04x\n", request, proto);
480
481 switch (mode) {
482 case MODE_REQ:
483 switch (proto) {
484 case PROTO_PAP:
485 if (length != 4) {
486 LogPrintf(LogLCP, " %s bad length (%d)\n", request, length);
487 goto reqreject;
488 }
489 if (Acceptable(ConfPap)) {
490 LcpInfo.his_auth = proto;
491 bcopy(cp, ackp, length);
492 ackp += length;
493 } else if (Acceptable(ConfChap)) {
494 *nakp++ = *cp;
495 *nakp++ = 5;
496 *nakp++ = (unsigned char) (PROTO_CHAP >> 8);
497 *nakp++ = (unsigned char) PROTO_CHAP;
498 *nakp++ = 5;
499 } else
500 goto reqreject;
501 break;
502 case PROTO_CHAP:
503 if (length < 5) {
504 LogPrintf(LogLCP, " %s bad length (%d)\n", request, length);
505 goto reqreject;
506 }
507 if (Acceptable(ConfChap) && cp[4] == 5) {
508 LcpInfo.his_auth = proto;
509 bcopy(cp, ackp, length);
510 ackp += length;
511 } else if (Acceptable(ConfPap)) {
512 *nakp++ = *cp;
513 *nakp++ = 4;
514 *nakp++ = (unsigned char) (PROTO_PAP >> 8);
515 *nakp++ = (unsigned char) PROTO_PAP;
516 } else
517 goto reqreject;
518 break;
519 default:
520 LogPrintf(LogLCP, " %s not implemented, NAK.\n", request);
521 bcopy(cp, nakp, length);
522 nakp += length;
523 break;
524 }
525 break;
526 case MODE_NAK:
527 break;
528 case MODE_REJ:
529 LcpInfo.his_reject |= (1 << type);
530 break;
531 }
532 break;
533 case TY_QUALPROTO:
534 req = (struct lqrreq *) cp;
535 LogPrintf(LogLCP, " %s proto: %x, interval: %dms\n",
536 request, ntohs(req->proto), ntohl(req->period) * 10);
537 switch (mode) {
538 case MODE_REQ:
539 if (ntohs(req->proto) != PROTO_LQR || !Acceptable(ConfLqr))
540 goto reqreject;
541 else {
542 LcpInfo.his_lqrperiod = ntohl(req->period);
543 if (LcpInfo.his_lqrperiod < 500)
544 LcpInfo.his_lqrperiod = 500;
545 req->period = htonl(LcpInfo.his_lqrperiod);
546 bcopy(cp, ackp, length);
547 ackp += length;
548 }
549 break;
550 case MODE_NAK:
551 break;
552 case MODE_REJ:
553 LcpInfo.his_reject |= (1 << type);
554 break;
555 }
556 break;
557 case TY_MAGICNUM:
558 lp = (u_long *) (cp + 2);
559 magic = ntohl(*lp);
560 LogPrintf(LogLCP, " %s %08x\n", request, magic);
561
562 switch (mode) {
563 case MODE_REQ:
564 if (LcpInfo.want_magic) {
565 /* Validate magic number */
566 if (magic == LcpInfo.want_magic) {
567 LogPrintf(LogLCP, "Magic is same (%08x)\n", magic);
568 LcpInfo.want_magic = GenerateMagic();
569 bcopy(cp, nakp, 6);
570 nakp += 6;
571 } else {
572 LcpInfo.his_magic = magic;
573 bcopy(cp, ackp, length);
574 ackp += length;
575 }
576 } else {
577 LcpInfo.my_reject |= (1 << type);
578 goto reqreject;
579 }
580 break;
581 case MODE_NAK:
582 LogPrintf(LogLCP, " %s magic %08x has NAKed\n", request, magic);
583 LcpInfo.want_magic = GenerateMagic();
584 break;
585 case MODE_REJ:
586 LogPrintf(LogLCP, " %s magic has REJected\n", request);
587 LcpInfo.want_magic = 0;
588 LcpInfo.his_reject |= (1 << type);
589 break;
590 }
591 break;
592 case TY_PROTOCOMP:
593 LogPrintf(LogLCP, " %s\n", request);
594
595 switch (mode) {
596 case MODE_REQ:
597 if (Acceptable(ConfProtocomp)) {
598 LcpInfo.his_protocomp = 1;
599 bcopy(cp, ackp, 2);
600 ackp += 2;
601 } else {
602#ifdef OLDMST
603
604 /*
605 * MorningStar before v1.3 needs NAK
606 */
607 bcopy(cp, nakp, 2);
608 nakp += 2;
609#else
610 bcopy(cp, rejp, 2);
611 rejp += 2;
612 LcpInfo.my_reject |= (1 << type);
613#endif
614 }
615 break;
616 case MODE_NAK:
617 case MODE_REJ:
618 LcpInfo.want_protocomp = 0;
619 LcpInfo.his_reject |= (1 << type);
620 break;
621 }
622 break;
623 case TY_ACFCOMP:
624 LogPrintf(LogLCP, " %s\n", request);
625 switch (mode) {
626 case MODE_REQ:
627 if (Acceptable(ConfAcfcomp)) {
628 LcpInfo.his_acfcomp = 1;
629 bcopy(cp, ackp, 2);
630 ackp += 2;
631 } else {
632#ifdef OLDMST
633
634 /*
635 * MorningStar before v1.3 needs NAK
636 */
637 bcopy(cp, nakp, 2);
638 nakp += 2;
639#else
640 bcopy(cp, rejp, 2);
641 rejp += 2;
642 LcpInfo.my_reject |= (1 << type);
643#endif
644 }
645 break;
646 case MODE_NAK:
647 case MODE_REJ:
648 LcpInfo.want_acfcomp = 0;
649 LcpInfo.his_reject |= (1 << type);
650 break;
651 }
652 break;
653 case TY_SDP:
654 LogPrintf(LogLCP, " %s\n", request);
655 switch (mode) {
656 case MODE_REQ:
657 case MODE_NAK:
658 case MODE_REJ:
659 break;
660 }
661 break;
662 default:
663 LogPrintf(LogLCP, " ???[%02x]\n", type);
664 if (mode == MODE_REQ) {
665 reqreject:
666 bcopy(cp, rejp, length);
667 rejp += length;
668 LcpInfo.my_reject |= (1 << type);
669 }
670 break;
671 }
672 /* to avoid inf. loop */
673 if (length == 0) {
674 LogPrintf(LogLCP, "LCP size zero\n");
675 break;
676 }
677 plen -= length;
678 cp += length;
679 }
680}
681
682void
683LcpInput(struct mbuf * bp)
684{
685 FsmInput(&LcpFsm, bp);
686}
144 }
145 StopTimer(&LcpReportTimer);
146 LcpReportTimer.state = TIMER_STOPPED;
147 StartTimer(&LcpReportTimer);
148 HdlcErrorCheck();
149}
150
151int
152ReportLcpStatus()
153{
154 struct lcpstate *lcp = &LcpInfo;
155 struct fsm *fp = &LcpFsm;
156
157 if (!VarTerm)
158 return 1;
159
160 fprintf(VarTerm, "%s [%s]\n", fp->name, StateNames[fp->state]);
161 fprintf(VarTerm,
162 " his side: MRU %ld, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d, MAGIC %08lx,\n"
163 " REJECT %04lx\n",
164 lcp->his_mru, lcp->his_accmap, lcp->his_protocomp, lcp->his_acfcomp,
165 lcp->his_magic, lcp->his_reject);
166 fprintf(VarTerm,
167 " my side: MRU %ld, ACCMAP %08lx, PROTOCOMP %d, ACFCOMP %d, MAGIC %08lx,\n"
168 " REJECT %04lx\n",
169 lcp->want_mru, lcp->want_accmap, lcp->want_protocomp, lcp->want_acfcomp,
170 lcp->want_magic, lcp->my_reject);
171 fprintf(VarTerm, "\nDefaults: MRU = %ld, ACCMAP = %08x\t", VarMRU, VarAccmap);
172 fprintf(VarTerm, "Open Mode: %s\n", (VarOpenMode == OPEN_ACTIVE) ? "active" : "passive");
173 return 0;
174}
175
176/*
177 * Generate random number which will be used as magic number.
178 */
179u_long
180GenerateMagic()
181{
182 if (!randinit) {
183 randinit = 1;
184 srandomdev();
185 }
186 return (random());
187}
188
189void
190LcpInit()
191{
192 struct lcpstate *lcp = &LcpInfo;
193
194 FsmInit(&LcpFsm);
195 HdlcInit();
196
197 bzero(lcp, sizeof(struct lcpstate));
198 lcp->want_mru = VarMRU;
199 lcp->his_mru = DEF_MRU;
200 lcp->his_accmap = 0xffffffff;
201 lcp->want_accmap = VarAccmap;
202 lcp->want_magic = GenerateMagic();
203 lcp->want_auth = lcp->his_auth = 0;
204 if (Enabled(ConfChap))
205 lcp->want_auth = PROTO_CHAP;
206 else if (Enabled(ConfPap))
207 lcp->want_auth = PROTO_PAP;
208 if (Enabled(ConfLqr))
209 lcp->want_lqrperiod = VarLqrTimeout * 100;
210 if (Enabled(ConfAcfcomp))
211 lcp->want_acfcomp = 1;
212 if (Enabled(ConfProtocomp))
213 lcp->want_protocomp = 1;
214 LcpFsm.maxconfig = 10;
215}
216
217static void
218LcpInitRestartCounter(struct fsm * fp)
219{
220 fp->FsmTimer.load = VarRetryTimeout * SECTICKS;
221 fp->restart = 5;
222}
223
224void
225PutConfValue(u_char ** cpp, char **types, u_char type, int len, u_long val)
226{
227 u_char *cp;
228 struct in_addr ina;
229
230 cp = *cpp;
231 *cp++ = type;
232 *cp++ = len;
233 if (len == 6) {
234 if (type == TY_IPADDR) {
235 ina.s_addr = htonl(val);
236 LogPrintf(LogLCP, " %s [%d] %s\n",
237 types[type], len, inet_ntoa(ina));
238 } else {
239 LogPrintf(LogLCP, " %s [%d] %08x\n", types[type], len, val);
240 }
241 *cp++ = (val >> 24) & 0377;
242 *cp++ = (val >> 16) & 0377;
243 } else
244 LogPrintf(LogLCP, " %s [%d] %d\n", types[type], len, val);
245 *cp++ = (val >> 8) & 0377;
246 *cp++ = val & 0377;
247 *cpp = cp;
248}
249
250static void
251LcpSendConfigReq(struct fsm * fp)
252{
253 u_char *cp;
254 struct lcpstate *lcp = &LcpInfo;
255 struct lqrreq *req;
256
257 LogPrintf(LogLCP, "LcpSendConfigReq\n");
258 cp = ReqBuff;
259 if (!DEV_IS_SYNC) {
260 if (lcp->want_acfcomp && !REJECTED(lcp, TY_ACFCOMP)) {
261 *cp++ = TY_ACFCOMP;
262 *cp++ = 2;
263 LogPrintf(LogLCP, " %s\n", cftypes[TY_ACFCOMP]);
264 }
265 if (lcp->want_protocomp && !REJECTED(lcp, TY_PROTOCOMP)) {
266 *cp++ = TY_PROTOCOMP;
267 *cp++ = 2;
268 LogPrintf(LogLCP, " %s\n", cftypes[TY_PROTOCOMP]);
269 }
270 if (!REJECTED(lcp, TY_ACCMAP))
271 PutConfValue(&cp, cftypes, TY_ACCMAP, 6, lcp->want_accmap);
272 }
273 if (!REJECTED(lcp, TY_MRU))
274 PutConfValue(&cp, cftypes, TY_MRU, 4, lcp->want_mru);
275 if (lcp->want_magic && !REJECTED(lcp, TY_MAGICNUM))
276 PutConfValue(&cp, cftypes, TY_MAGICNUM, 6, lcp->want_magic);
277 if (lcp->want_lqrperiod && !REJECTED(lcp, TY_QUALPROTO)) {
278 req = (struct lqrreq *) cp;
279 req->type = TY_QUALPROTO;
280 req->length = sizeof(struct lqrreq);
281 req->proto = htons(PROTO_LQR);
282 req->period = htonl(lcp->want_lqrperiod);
283 cp += sizeof(struct lqrreq);
284 LogPrintf(LogLCP, " %s (%d)\n", cftypes[TY_QUALPROTO], lcp->want_lqrperiod);
285 }
286 switch (lcp->want_auth) {
287 case PROTO_PAP:
288 PutConfValue(&cp, cftypes, TY_AUTHPROTO, 4, lcp->want_auth);
289 break;
290 case PROTO_CHAP:
291 PutConfValue(&cp, cftypes, TY_AUTHPROTO, 5, lcp->want_auth);
292 *cp++ = 5; /* Use MD5 */
293 break;
294 }
295 FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff);
296}
297
298void
299LcpSendProtoRej(u_char * option, int count)
300{
301 struct fsm *fp = &LcpFsm;
302
303 LogPrintf(LogLCP, "LcpSendProtoRej\n");
304 FsmOutput(fp, CODE_PROTOREJ, fp->reqid, option, count);
305}
306
307static void
308LcpSendTerminateReq(struct fsm * fp)
309{
310 /* Most thins are done in fsm layer. Nothing to to. */
311}
312
313static void
314LcpSendTerminateAck(struct fsm * fp)
315{
316 LogPrintf(LogLCP, "LcpSendTerminateAck.\n");
317 FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0);
318}
319
320static void
321LcpLayerStart(struct fsm * fp)
322{
323 LogPrintf(LogLCP, "LcpLayerStart\n");
324 NewPhase(PHASE_ESTABLISH);
325}
326
327static void
328StopAllTimers()
329{
330 StopTimer(&LcpReportTimer);
331 StopTimer(&IpcpReportTimer);
332 StopIdleTimer();
333 StopTimer(&AuthPapInfo.authtimer);
334 StopTimer(&AuthChapInfo.authtimer);
335 StopLqrTimer();
336}
337
338static void
339LcpLayerFinish(struct fsm * fp)
340{
341 LogPrintf(LogLCP, "LcpLayerFinish\n");
342 OsCloseLink(1);
343 NewPhase(PHASE_DEAD);
344 StopAllTimers();
345 (void) OsInterfaceDown(0);
346 Prompt();
347}
348
349static void
350LcpLayerUp(struct fsm * fp)
351{
352 LogPrintf(LogLCP, "LcpLayerUp\n");
353 OsSetInterfaceParams(23, LcpInfo.his_mru, ModemSpeed());
354 SetLinkParams(&LcpInfo);
355
356 NewPhase(PHASE_AUTHENTICATE);
357
358 StartLqm();
359 StopTimer(&LcpReportTimer);
360 LcpReportTimer.state = TIMER_STOPPED;
361 LcpReportTimer.load = 60 * SECTICKS;
362 LcpReportTimer.func = LcpReportTime;
363 StartTimer(&LcpReportTimer);
364}
365
366static void
367LcpLayerDown(struct fsm * fp)
368{
369 LogPrintf(LogLCP, "LcpLayerDown\n");
370 StopAllTimers();
371 OsLinkdown();
372 NewPhase(PHASE_TERMINATE);
373}
374
375void
376LcpUp()
377{
378 FsmUp(&LcpFsm);
379}
380
381void
382LcpDown()
383{ /* Sudden death */
384 NewPhase(PHASE_DEAD);
385 StopAllTimers();
386 FsmDown(&LcpFsm);
387}
388
389void
390LcpOpen(int mode)
391{
392 LcpFsm.open_mode = mode;
393 FsmOpen(&LcpFsm);
394}
395
396void
397LcpClose()
398{
399 FsmClose(&LcpFsm);
400}
401
402/*
403 * XXX: Should validate option length
404 */
405static void
406LcpDecodeConfig(u_char * cp, int plen, int mode)
407{
408 char *request;
409 int type, length, mru;
410 u_long *lp, magic, accmap;
411 u_short *sp, proto;
412 struct lqrreq *req;
413
414 ackp = AckBuff;
415 nakp = NakBuff;
416 rejp = RejBuff;
417
418 while (plen >= sizeof(struct fsmconfig)) {
419 type = *cp;
420 length = cp[1];
421 if (type <= TY_ACFCOMP)
422 request = cftypes[type];
423 else
424 request = "???";
425
426 switch (type) {
427 case TY_MRU:
428 sp = (u_short *) (cp + 2);
429 mru = htons(*sp);
430 LogPrintf(LogLCP, " %s %d\n", request, mru);
431
432 switch (mode) {
433 case MODE_REQ:
434 if (mru > MAX_MRU) {
435 *sp = htons(MAX_MRU);
436 bcopy(cp, nakp, 4);
437 nakp += 4;
438 } else if (mru < MIN_MRU) {
439 *sp = htons(MIN_MRU);
440 bcopy(cp, nakp, 4);
441 nakp += 4;
442 } else {
443 LcpInfo.his_mru = mru;
444 bcopy(cp, ackp, 4);
445 ackp += 4;
446 }
447 break;
448 case MODE_NAK:
449 if (mru >= MIN_MRU || mru <= MAX_MRU)
450 LcpInfo.want_mru = mru;
451 break;
452 case MODE_REJ:
453 LcpInfo.his_reject |= (1 << type);
454 break;
455 }
456 break;
457 case TY_ACCMAP:
458 lp = (u_long *) (cp + 2);
459 accmap = htonl(*lp);
460 LogPrintf(LogLCP, " %s %08x\n", request, accmap);
461
462 switch (mode) {
463 case MODE_REQ:
464 LcpInfo.his_accmap = accmap;
465 bcopy(cp, ackp, 6);
466 ackp += 6;
467 break;
468 case MODE_NAK:
469 LcpInfo.want_accmap = accmap;
470 break;
471 case MODE_REJ:
472 LcpInfo.his_reject |= (1 << type);
473 break;
474 }
475 break;
476 case TY_AUTHPROTO:
477 sp = (u_short *) (cp + 2);
478 proto = ntohs(*sp);
479 LogPrintf(LogLCP, " %s proto = %04x\n", request, proto);
480
481 switch (mode) {
482 case MODE_REQ:
483 switch (proto) {
484 case PROTO_PAP:
485 if (length != 4) {
486 LogPrintf(LogLCP, " %s bad length (%d)\n", request, length);
487 goto reqreject;
488 }
489 if (Acceptable(ConfPap)) {
490 LcpInfo.his_auth = proto;
491 bcopy(cp, ackp, length);
492 ackp += length;
493 } else if (Acceptable(ConfChap)) {
494 *nakp++ = *cp;
495 *nakp++ = 5;
496 *nakp++ = (unsigned char) (PROTO_CHAP >> 8);
497 *nakp++ = (unsigned char) PROTO_CHAP;
498 *nakp++ = 5;
499 } else
500 goto reqreject;
501 break;
502 case PROTO_CHAP:
503 if (length < 5) {
504 LogPrintf(LogLCP, " %s bad length (%d)\n", request, length);
505 goto reqreject;
506 }
507 if (Acceptable(ConfChap) && cp[4] == 5) {
508 LcpInfo.his_auth = proto;
509 bcopy(cp, ackp, length);
510 ackp += length;
511 } else if (Acceptable(ConfPap)) {
512 *nakp++ = *cp;
513 *nakp++ = 4;
514 *nakp++ = (unsigned char) (PROTO_PAP >> 8);
515 *nakp++ = (unsigned char) PROTO_PAP;
516 } else
517 goto reqreject;
518 break;
519 default:
520 LogPrintf(LogLCP, " %s not implemented, NAK.\n", request);
521 bcopy(cp, nakp, length);
522 nakp += length;
523 break;
524 }
525 break;
526 case MODE_NAK:
527 break;
528 case MODE_REJ:
529 LcpInfo.his_reject |= (1 << type);
530 break;
531 }
532 break;
533 case TY_QUALPROTO:
534 req = (struct lqrreq *) cp;
535 LogPrintf(LogLCP, " %s proto: %x, interval: %dms\n",
536 request, ntohs(req->proto), ntohl(req->period) * 10);
537 switch (mode) {
538 case MODE_REQ:
539 if (ntohs(req->proto) != PROTO_LQR || !Acceptable(ConfLqr))
540 goto reqreject;
541 else {
542 LcpInfo.his_lqrperiod = ntohl(req->period);
543 if (LcpInfo.his_lqrperiod < 500)
544 LcpInfo.his_lqrperiod = 500;
545 req->period = htonl(LcpInfo.his_lqrperiod);
546 bcopy(cp, ackp, length);
547 ackp += length;
548 }
549 break;
550 case MODE_NAK:
551 break;
552 case MODE_REJ:
553 LcpInfo.his_reject |= (1 << type);
554 break;
555 }
556 break;
557 case TY_MAGICNUM:
558 lp = (u_long *) (cp + 2);
559 magic = ntohl(*lp);
560 LogPrintf(LogLCP, " %s %08x\n", request, magic);
561
562 switch (mode) {
563 case MODE_REQ:
564 if (LcpInfo.want_magic) {
565 /* Validate magic number */
566 if (magic == LcpInfo.want_magic) {
567 LogPrintf(LogLCP, "Magic is same (%08x)\n", magic);
568 LcpInfo.want_magic = GenerateMagic();
569 bcopy(cp, nakp, 6);
570 nakp += 6;
571 } else {
572 LcpInfo.his_magic = magic;
573 bcopy(cp, ackp, length);
574 ackp += length;
575 }
576 } else {
577 LcpInfo.my_reject |= (1 << type);
578 goto reqreject;
579 }
580 break;
581 case MODE_NAK:
582 LogPrintf(LogLCP, " %s magic %08x has NAKed\n", request, magic);
583 LcpInfo.want_magic = GenerateMagic();
584 break;
585 case MODE_REJ:
586 LogPrintf(LogLCP, " %s magic has REJected\n", request);
587 LcpInfo.want_magic = 0;
588 LcpInfo.his_reject |= (1 << type);
589 break;
590 }
591 break;
592 case TY_PROTOCOMP:
593 LogPrintf(LogLCP, " %s\n", request);
594
595 switch (mode) {
596 case MODE_REQ:
597 if (Acceptable(ConfProtocomp)) {
598 LcpInfo.his_protocomp = 1;
599 bcopy(cp, ackp, 2);
600 ackp += 2;
601 } else {
602#ifdef OLDMST
603
604 /*
605 * MorningStar before v1.3 needs NAK
606 */
607 bcopy(cp, nakp, 2);
608 nakp += 2;
609#else
610 bcopy(cp, rejp, 2);
611 rejp += 2;
612 LcpInfo.my_reject |= (1 << type);
613#endif
614 }
615 break;
616 case MODE_NAK:
617 case MODE_REJ:
618 LcpInfo.want_protocomp = 0;
619 LcpInfo.his_reject |= (1 << type);
620 break;
621 }
622 break;
623 case TY_ACFCOMP:
624 LogPrintf(LogLCP, " %s\n", request);
625 switch (mode) {
626 case MODE_REQ:
627 if (Acceptable(ConfAcfcomp)) {
628 LcpInfo.his_acfcomp = 1;
629 bcopy(cp, ackp, 2);
630 ackp += 2;
631 } else {
632#ifdef OLDMST
633
634 /*
635 * MorningStar before v1.3 needs NAK
636 */
637 bcopy(cp, nakp, 2);
638 nakp += 2;
639#else
640 bcopy(cp, rejp, 2);
641 rejp += 2;
642 LcpInfo.my_reject |= (1 << type);
643#endif
644 }
645 break;
646 case MODE_NAK:
647 case MODE_REJ:
648 LcpInfo.want_acfcomp = 0;
649 LcpInfo.his_reject |= (1 << type);
650 break;
651 }
652 break;
653 case TY_SDP:
654 LogPrintf(LogLCP, " %s\n", request);
655 switch (mode) {
656 case MODE_REQ:
657 case MODE_NAK:
658 case MODE_REJ:
659 break;
660 }
661 break;
662 default:
663 LogPrintf(LogLCP, " ???[%02x]\n", type);
664 if (mode == MODE_REQ) {
665 reqreject:
666 bcopy(cp, rejp, length);
667 rejp += length;
668 LcpInfo.my_reject |= (1 << type);
669 }
670 break;
671 }
672 /* to avoid inf. loop */
673 if (length == 0) {
674 LogPrintf(LogLCP, "LCP size zero\n");
675 break;
676 }
677 plen -= length;
678 cp += length;
679 }
680}
681
682void
683LcpInput(struct mbuf * bp)
684{
685 FsmInput(&LcpFsm, bp);
686}