1 /* $OpenBSD: lcp.c,v 1.15 2024/08/09 05:16:13 deraadt Exp $ */
2
3 /*
4 * lcp.c - PPP Link Control Protocol.
5 *
6 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. The name "Carnegie Mellon University" must not be used to
21 * endorse or promote products derived from this software without
22 * prior written permission. For permission or any legal
23 * details, please contact
24 * Office of Technology Transfer
25 * Carnegie Mellon University
26 * 5000 Forbes Avenue
27 * Pittsburgh, PA 15213-3890
28 * (412) 268-4387, fax: (412) 268-7395
29 * tech-transfer@andrew.cmu.edu
30 *
31 * 4. Redistributions of any form whatsoever must retain the following
32 * acknowledgment:
33 * "This product includes software developed by Computing Services
34 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
35 *
36 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
37 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
38 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
39 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
40 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
41 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
42 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
43 */
44
45 /*
46 * TODO:
47 */
48
49 #include <stdio.h>
50 #include <string.h>
51 #include <syslog.h>
52 #include <assert.h>
53 #include <sys/ioctl.h>
54 #include <sys/types.h>
55 #include <sys/socket.h>
56 #include <sys/time.h>
57 #include <netinet/in.h>
58
59 #include "pppd.h"
60 #include "fsm.h"
61 #include "lcp.h"
62 #include "chap.h"
63 #include "magic.h"
64
65 /* global vars */
66 fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/
67 lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */
68 lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
69 lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
70 lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
71 u_int32_t xmit_accm[NUM_PPP][8]; /* extended transmit ACCM */
72
73 static u_int32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */
74 static u_int32_t lcp_echo_number = 0; /* ID number of next echo frame */
75 static u_int32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */
76
77 static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */
78
79 /*
80 * Callbacks for fsm code. (CI = Configuration Information)
81 */
82 static void lcp_resetci(fsm *); /* Reset our CI */
83 static int lcp_cilen(fsm *); /* Return length of our CI */
84 static void lcp_addci(fsm *, u_char *, int *); /* Add our CI to pkt */
85 static int lcp_ackci(fsm *, u_char *, int); /* Peer ack'd our CI */
86 static int lcp_nakci(fsm *, u_char *, int); /* Peer nak'd our CI */
87 static int lcp_rejci(fsm *, u_char *, int); /* Peer rej'd our CI */
88 static int lcp_reqci(fsm *, u_char *, int *, int); /* Rcv peer CI */
89 static void lcp_up(fsm *); /* We're UP */
90 static void lcp_down(fsm *); /* We're DOWN */
91 static void lcp_starting(fsm *); /* We need lower layer up */
92 static void lcp_finished(fsm *); /* We need lower layer down */
93 static int lcp_extcode(fsm *, int, int, u_char *, int);
94 static void lcp_rprotrej(fsm *, u_char *, int);
95
96 /*
97 * routines to send LCP echos to peer
98 */
99
100 static void lcp_echo_lowerup(int);
101 static void lcp_echo_lowerdown(int);
102 static void LcpEchoTimeout(void *);
103 static void lcp_received_echo_reply(fsm *, int, u_char *, int);
104 static void LcpSendEchoRequest(fsm *);
105 static void LcpLinkFailure(fsm *);
106 static void LcpEchoCheck(fsm *);
107
108 static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
109 lcp_resetci, /* Reset our Configuration Information */
110 lcp_cilen, /* Length of our Configuration Information */
111 lcp_addci, /* Add our Configuration Information */
112 lcp_ackci, /* ACK our Configuration Information */
113 lcp_nakci, /* NAK our Configuration Information */
114 lcp_rejci, /* Reject our Configuration Information */
115 lcp_reqci, /* Request peer's Configuration Information */
116 lcp_up, /* Called when fsm reaches OPENED state */
117 lcp_down, /* Called when fsm leaves OPENED state */
118 lcp_starting, /* Called when we want the lower layer up */
119 lcp_finished, /* Called when we want the lower layer down */
120 NULL, /* Called when Protocol-Reject received */
121 NULL, /* Retransmission is necessary */
122 lcp_extcode, /* Called to handle LCP-specific codes */
123 "LCP" /* String name of protocol */
124 };
125
126 /*
127 * Protocol entry points.
128 * Some of these are called directly.
129 */
130
131 static void lcp_init(int);
132 static void lcp_input(int, u_char *, int);
133 static void lcp_protrej(int);
134 static int lcp_printpkt(u_char *, int, void (*)(void *, char *, ...), void *);
135
136 struct protent lcp_protent = {
137 PPP_LCP,
138 lcp_init,
139 lcp_input,
140 lcp_protrej,
141 lcp_lowerup,
142 lcp_lowerdown,
143 lcp_open,
144 lcp_close,
145 lcp_printpkt,
146 NULL,
147 1,
148 "LCP",
149 NULL,
150 NULL,
151 NULL
152 };
153
154 int lcp_loopbackfail = DEFLOOPBACKFAIL;
155
156 /*
157 * Length of each type of configuration option (in octets)
158 */
159 #define CILEN_VOID 2
160 #define CILEN_CHAR 3
161 #define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */
162 #define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */
163 #define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */
164 #define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */
165 #define CILEN_CBCP 3
166
167 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \
168 (x) == CONFNAK ? "NAK" : "REJ")
169
170
171 /*
172 * lcp_init - Initialize LCP.
173 */
174 static void
lcp_init(int unit)175 lcp_init(int unit)
176 {
177 fsm *f = &lcp_fsm[unit];
178 lcp_options *wo = &lcp_wantoptions[unit];
179 lcp_options *ao = &lcp_allowoptions[unit];
180
181 f->unit = unit;
182 f->protocol = PPP_LCP;
183 f->callbacks = &lcp_callbacks;
184
185 fsm_init(f);
186
187 wo->passive = 0;
188 wo->silent = 0;
189 wo->restart = 0; /* Set to 1 in kernels or multi-line
190 implementations */
191 wo->neg_mru = 1;
192 wo->mru = DEFMRU;
193 wo->neg_asyncmap = 0;
194 wo->asyncmap = 0;
195 wo->neg_chap = 0; /* Set to 1 on server */
196 wo->neg_upap = 0; /* Set to 1 on server */
197 wo->chap_mdtype = CHAP_DIGEST_MD5;
198 wo->neg_magicnumber = 1;
199 wo->neg_pcompression = 1;
200 wo->neg_accompression = 1;
201 wo->neg_lqr = 0; /* no LQR implementation yet */
202 wo->neg_cbcp = 0;
203
204 ao->neg_mru = 1;
205 ao->mru = MAXMRU;
206 ao->neg_asyncmap = 1;
207 ao->asyncmap = 0;
208 ao->neg_chap = 1;
209 ao->chap_mdtype = CHAP_DIGEST_MD5;
210 ao->neg_upap = 1;
211 ao->neg_magicnumber = 1;
212 ao->neg_pcompression = 1;
213 ao->neg_accompression = 1;
214 ao->neg_lqr = 0; /* no LQR implementation yet */
215 #ifdef CBCP_SUPPORT
216 ao->neg_cbcp = 1;
217 #else
218 ao->neg_cbcp = 0;
219 #endif
220
221 memset(xmit_accm[unit], 0, sizeof(xmit_accm[0]));
222 xmit_accm[unit][3] = 0x60000000;
223 }
224
225
226 /*
227 * lcp_open - LCP is allowed to come up.
228 */
229 void
lcp_open(int unit)230 lcp_open(int unit)
231 {
232 fsm *f = &lcp_fsm[unit];
233 lcp_options *wo = &lcp_wantoptions[unit];
234
235 f->flags = 0;
236 if (wo->passive)
237 f->flags |= OPT_PASSIVE;
238 if (wo->silent)
239 f->flags |= OPT_SILENT;
240 fsm_open(f);
241 }
242
243
244 /*
245 * lcp_close - Take LCP down.
246 */
247 void
lcp_close(int unit,char * reason)248 lcp_close(int unit, char *reason)
249 {
250 fsm *f = &lcp_fsm[unit];
251
252 if (phase != PHASE_DEAD)
253 phase = PHASE_TERMINATE;
254 if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) {
255 /*
256 * This action is not strictly according to the FSM in RFC1548,
257 * but it does mean that the program terminates if you do a
258 * lcp_close() in passive/silent mode when a connection hasn't
259 * been established.
260 */
261 f->state = CLOSED;
262 lcp_finished(f);
263
264 } else
265 fsm_close(&lcp_fsm[unit], reason);
266 }
267
268
269 /*
270 * lcp_lowerup - The lower layer is up.
271 */
272 void
lcp_lowerup(int unit)273 lcp_lowerup(int unit)
274 {
275 lcp_options *wo = &lcp_wantoptions[unit];
276
277 /*
278 * Don't use A/C or protocol compression on transmission,
279 * but accept A/C and protocol compressed packets
280 * if we are going to ask for A/C and protocol compression.
281 */
282 ppp_set_xaccm(unit, xmit_accm[unit]);
283 ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0);
284 ppp_recv_config(unit, PPP_MRU, 0xffffffff,
285 wo->neg_pcompression, wo->neg_accompression);
286 peer_mru[unit] = PPP_MRU;
287 lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0];
288
289 fsm_lowerup(&lcp_fsm[unit]);
290 }
291
292
293 /*
294 * lcp_lowerdown - The lower layer is down.
295 */
296 void
lcp_lowerdown(int unit)297 lcp_lowerdown(int unit)
298 {
299 fsm_lowerdown(&lcp_fsm[unit]);
300 }
301
302
303 /*
304 * lcp_input - Input LCP packet.
305 */
306 static void
lcp_input(int unit,u_char * p,int len)307 lcp_input(int unit, u_char *p, int len)
308 {
309 fsm *f = &lcp_fsm[unit];
310
311 fsm_input(f, p, len);
312 }
313
314
315 /*
316 * lcp_extcode - Handle a LCP-specific code.
317 */
318 static int
lcp_extcode(fsm * f,int code,int id,u_char * inp,int len)319 lcp_extcode(fsm *f, int code, int id, u_char *inp, int len)
320 {
321 u_char *magp;
322
323 switch( code ){
324 case PROTREJ:
325 lcp_rprotrej(f, inp, len);
326 break;
327
328 case ECHOREQ:
329 if (f->state != OPENED)
330 break;
331 LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d", id));
332 magp = inp;
333 PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
334 fsm_sdata(f, ECHOREP, id, inp, len);
335 break;
336
337 case ECHOREP:
338 lcp_received_echo_reply(f, id, inp, len);
339 break;
340
341 case DISCREQ:
342 break;
343
344 default:
345 return 0;
346 }
347 return 1;
348 }
349
350
351 /*
352 * lcp_rprotrej - Receive an Protocol-Reject.
353 *
354 * Figure out which protocol is rejected and inform it.
355 */
356 static void
lcp_rprotrej(fsm * f,u_char * inp,int len)357 lcp_rprotrej(fsm *f, u_char *inp, int len)
358 {
359 int i;
360 struct protent *protp;
361 u_short prot;
362
363 LCPDEBUG((LOG_INFO, "lcp_rprotrej."));
364
365 if (len < sizeof (u_short)) {
366 LCPDEBUG((LOG_INFO,
367 "lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
368 return;
369 }
370
371 GETSHORT(prot, inp);
372
373 LCPDEBUG((LOG_INFO,
374 "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!",
375 prot));
376
377 /*
378 * Protocol-Reject packets received in any state other than the LCP
379 * OPENED state SHOULD be silently discarded.
380 */
381 if( f->state != OPENED ){
382 LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d",
383 f->state));
384 return;
385 }
386
387 /*
388 * Upcall the proper Protocol-Reject routine.
389 */
390 for (i = 0; (protp = protocols[i]) != NULL; ++i)
391 if (protp->protocol == prot && protp->enabled_flag) {
392 (*protp->protrej)(f->unit);
393 return;
394 }
395
396 syslog(LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x",
397 prot);
398 }
399
400
401 /*
402 * lcp_protrej - A Protocol-Reject was received.
403 */
404 static void
lcp_protrej(int unit)405 lcp_protrej(int unit)
406 {
407 /*
408 * Can't reject LCP!
409 */
410 LCPDEBUG((LOG_WARNING,
411 "lcp_protrej: Received Protocol-Reject for LCP!"));
412 fsm_protreject(&lcp_fsm[unit]);
413 }
414
415
416 /*
417 * lcp_sprotrej - Send a Protocol-Reject for some protocol.
418 */
419 void
lcp_sprotrej(int unit,u_char * p,int len)420 lcp_sprotrej(int unit, u_char *p, int len)
421 {
422 /*
423 * Send back the protocol and the information field of the
424 * rejected packet. We only get here if LCP is in the OPENED state.
425 */
426 p += 2;
427 len -= 2;
428
429 fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,
430 p, len);
431 }
432
433
434 /*
435 * lcp_resetci - Reset our CI.
436 */
437 static void
lcp_resetci(fsm * f)438 lcp_resetci(fsm *f)
439 {
440 lcp_wantoptions[f->unit].magicnumber = magic();
441 lcp_wantoptions[f->unit].numloops = 0;
442 lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
443 peer_mru[f->unit] = PPP_MRU;
444 auth_reset(f->unit);
445 }
446
447
448 /*
449 * lcp_cilen - Return length of our CI.
450 */
451 static int
lcp_cilen(fsm * f)452 lcp_cilen(fsm *f)
453 {
454 lcp_options *go = &lcp_gotoptions[f->unit];
455
456 #define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0)
457 #define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0)
458 #define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0)
459 #define LENCILONG(neg) ((neg) ? CILEN_LONG : 0)
460 #define LENCILQR(neg) ((neg) ? CILEN_LQR: 0)
461 #define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0)
462 /*
463 * NB: we only ask for one of CHAP and UPAP, even if we will
464 * accept either.
465 */
466 return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) +
467 LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
468 LENCICHAP(go->neg_chap) +
469 LENCISHORT(!go->neg_chap && go->neg_upap) +
470 LENCILQR(go->neg_lqr) +
471 LENCICBCP(go->neg_cbcp) +
472 LENCILONG(go->neg_magicnumber) +
473 LENCIVOID(go->neg_pcompression) +
474 LENCIVOID(go->neg_accompression));
475 }
476
477
478 /*
479 * lcp_addci - Add our desired CIs to a packet.
480 */
481 static void
lcp_addci(fsm * f,u_char * ucp,int * lenp)482 lcp_addci(fsm *f, u_char *ucp, int *lenp)
483 {
484 lcp_options *go = &lcp_gotoptions[f->unit];
485 u_char *start_ucp = ucp;
486
487 #define ADDCIVOID(opt, neg) \
488 if (neg) { \
489 PUTCHAR(opt, ucp); \
490 PUTCHAR(CILEN_VOID, ucp); \
491 }
492 #define ADDCISHORT(opt, neg, val) \
493 if (neg) { \
494 PUTCHAR(opt, ucp); \
495 PUTCHAR(CILEN_SHORT, ucp); \
496 PUTSHORT(val, ucp); \
497 }
498 #define ADDCICHAP(opt, neg, val, digest) \
499 if (neg) { \
500 PUTCHAR(opt, ucp); \
501 PUTCHAR(CILEN_CHAP, ucp); \
502 PUTSHORT(val, ucp); \
503 PUTCHAR(digest, ucp); \
504 }
505 #define ADDCILONG(opt, neg, val) \
506 if (neg) { \
507 PUTCHAR(opt, ucp); \
508 PUTCHAR(CILEN_LONG, ucp); \
509 PUTLONG(val, ucp); \
510 }
511 #define ADDCILQR(opt, neg, val) \
512 if (neg) { \
513 PUTCHAR(opt, ucp); \
514 PUTCHAR(CILEN_LQR, ucp); \
515 PUTSHORT(PPP_LQR, ucp); \
516 PUTLONG(val, ucp); \
517 }
518 #define ADDCICHAR(opt, neg, val) \
519 if (neg) { \
520 PUTCHAR(opt, ucp); \
521 PUTCHAR(CILEN_CHAR, ucp); \
522 PUTCHAR(val, ucp); \
523 }
524
525 ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
526 ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
527 go->asyncmap);
528 ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
529 ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
530 ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
531 ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
532 ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
533 ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
534 ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
535
536 if (ucp - start_ucp != *lenp) {
537 /* this should never happen, because peer_mtu should be 1500 */
538 syslog(LOG_ERR, "Bug in lcp_addci: wrong length");
539 }
540 }
541
542
543 /*
544 * lcp_ackci - Ack our CIs.
545 * This should not modify any state if the Ack is bad.
546 *
547 * Returns:
548 * 0 - Ack was bad.
549 * 1 - Ack was good.
550 */
551 static int
lcp_ackci(fsm * f,u_char * p,int len)552 lcp_ackci(fsm *f, u_char *p, int len)
553 {
554 lcp_options *go = &lcp_gotoptions[f->unit];
555 u_char cilen, citype, cichar;
556 u_short cishort;
557 u_int32_t cilong;
558
559 /*
560 * CIs must be in exactly the same order that we sent.
561 * Check packet length and CI length at each step.
562 * If we find any deviations, then this packet is bad.
563 */
564 #define ACKCIVOID(opt, neg) \
565 if (neg) { \
566 if ((len -= CILEN_VOID) < 0) \
567 goto bad; \
568 GETCHAR(citype, p); \
569 GETCHAR(cilen, p); \
570 if (cilen != CILEN_VOID || \
571 citype != opt) \
572 goto bad; \
573 }
574 #define ACKCISHORT(opt, neg, val) \
575 if (neg) { \
576 if ((len -= CILEN_SHORT) < 0) \
577 goto bad; \
578 GETCHAR(citype, p); \
579 GETCHAR(cilen, p); \
580 if (cilen != CILEN_SHORT || \
581 citype != opt) \
582 goto bad; \
583 GETSHORT(cishort, p); \
584 if (cishort != val) \
585 goto bad; \
586 }
587 #define ACKCICHAR(opt, neg, val) \
588 if (neg) { \
589 if ((len -= CILEN_CHAR) < 0) \
590 goto bad; \
591 GETCHAR(citype, p); \
592 GETCHAR(cilen, p); \
593 if (cilen != CILEN_CHAR || \
594 citype != opt) \
595 goto bad; \
596 GETCHAR(cichar, p); \
597 if (cichar != val) \
598 goto bad; \
599 }
600 #define ACKCICHAP(opt, neg, val, digest) \
601 if (neg) { \
602 if ((len -= CILEN_CHAP) < 0) \
603 goto bad; \
604 GETCHAR(citype, p); \
605 GETCHAR(cilen, p); \
606 if (cilen != CILEN_CHAP || \
607 citype != opt) \
608 goto bad; \
609 GETSHORT(cishort, p); \
610 if (cishort != val) \
611 goto bad; \
612 GETCHAR(cichar, p); \
613 if (cichar != digest) \
614 goto bad; \
615 }
616 #define ACKCILONG(opt, neg, val) \
617 if (neg) { \
618 if ((len -= CILEN_LONG) < 0) \
619 goto bad; \
620 GETCHAR(citype, p); \
621 GETCHAR(cilen, p); \
622 if (cilen != CILEN_LONG || \
623 citype != opt) \
624 goto bad; \
625 GETLONG(cilong, p); \
626 if (cilong != val) \
627 goto bad; \
628 }
629 #define ACKCILQR(opt, neg, val) \
630 if (neg) { \
631 if ((len -= CILEN_LQR) < 0) \
632 goto bad; \
633 GETCHAR(citype, p); \
634 GETCHAR(cilen, p); \
635 if (cilen != CILEN_LQR || \
636 citype != opt) \
637 goto bad; \
638 GETSHORT(cishort, p); \
639 if (cishort != PPP_LQR) \
640 goto bad; \
641 GETLONG(cilong, p); \
642 if (cilong != val) \
643 goto bad; \
644 }
645
646 ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
647 ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
648 go->asyncmap);
649 ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
650 ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
651 ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
652 ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
653 ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
654 ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
655 ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
656
657 /*
658 * If there are any remaining CIs, then this packet is bad.
659 */
660 if (len != 0)
661 goto bad;
662 return (1);
663 bad:
664 LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!"));
665 return (0);
666 }
667
668
669 /*
670 * lcp_nakci - Peer has sent a NAK for some of our CIs.
671 * This should not modify any state if the Nak is bad
672 * or if LCP is in the OPENED state.
673 *
674 * Returns:
675 * 0 - Nak was bad.
676 * 1 - Nak was good.
677 */
678 static int
lcp_nakci(fsm * f,u_char * p,int len)679 lcp_nakci(fsm *f, u_char *p, int len)
680 {
681 lcp_options *go = &lcp_gotoptions[f->unit];
682 lcp_options *wo = &lcp_wantoptions[f->unit];
683 u_char citype, cichar, *next;
684 u_short cishort;
685 u_int32_t cilong;
686 lcp_options no; /* options we've seen Naks for */
687 lcp_options try; /* options to request next time */
688 int looped_back = 0;
689 int cilen;
690
691 BZERO(&no, sizeof(no));
692 try = *go;
693
694 /*
695 * Any Nak'd CIs must be in exactly the same order that we sent.
696 * Check packet length and CI length at each step.
697 * If we find any deviations, then this packet is bad.
698 */
699 #define NAKCIVOID(opt, neg, code) \
700 if (go->neg && \
701 len >= CILEN_VOID && \
702 p[1] == CILEN_VOID && \
703 p[0] == opt) { \
704 len -= CILEN_VOID; \
705 INCPTR(CILEN_VOID, p); \
706 no.neg = 1; \
707 code \
708 }
709 #define NAKCICHAP(opt, neg, code) \
710 if (go->neg && \
711 len >= CILEN_CHAP && \
712 p[1] == CILEN_CHAP && \
713 p[0] == opt) { \
714 len -= CILEN_CHAP; \
715 INCPTR(2, p); \
716 GETSHORT(cishort, p); \
717 GETCHAR(cichar, p); \
718 no.neg = 1; \
719 code \
720 }
721 #define NAKCICHAR(opt, neg, code) \
722 if (go->neg && \
723 len >= CILEN_CHAR && \
724 p[1] == CILEN_CHAR && \
725 p[0] == opt) { \
726 len -= CILEN_CHAR; \
727 INCPTR(2, p); \
728 GETCHAR(cichar, p); \
729 no.neg = 1; \
730 code \
731 }
732 #define NAKCISHORT(opt, neg, code) \
733 if (go->neg && \
734 len >= CILEN_SHORT && \
735 p[1] == CILEN_SHORT && \
736 p[0] == opt) { \
737 len -= CILEN_SHORT; \
738 INCPTR(2, p); \
739 GETSHORT(cishort, p); \
740 no.neg = 1; \
741 code \
742 }
743 #define NAKCILONG(opt, neg, code) \
744 if (go->neg && \
745 len >= CILEN_LONG && \
746 p[1] == CILEN_LONG && \
747 p[0] == opt) { \
748 len -= CILEN_LONG; \
749 INCPTR(2, p); \
750 GETLONG(cilong, p); \
751 no.neg = 1; \
752 code \
753 }
754 #define NAKCILQR(opt, neg, code) \
755 if (go->neg && \
756 len >= CILEN_LQR && \
757 p[1] == CILEN_LQR && \
758 p[0] == opt) { \
759 len -= CILEN_LQR; \
760 INCPTR(2, p); \
761 GETSHORT(cishort, p); \
762 GETLONG(cilong, p); \
763 no.neg = 1; \
764 code \
765 }
766
767 /*
768 * We don't care if they want to send us smaller packets than
769 * we want. Therefore, accept any MRU less than what we asked for,
770 * but then ignore the new value when setting the MRU in the kernel.
771 * If they send us a bigger MRU than what we asked, accept it, up to
772 * the limit of the default MRU we'd get if we didn't negotiate.
773 */
774 if (go->neg_mru && go->mru != DEFMRU) {
775 NAKCISHORT(CI_MRU, neg_mru,
776 if (cishort <= wo->mru || cishort <= DEFMRU)
777 try.mru = cishort;
778 );
779 }
780
781 /*
782 * Add any characters they want to our (receive-side) asyncmap.
783 */
784 if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
785 NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
786 try.asyncmap = go->asyncmap | cilong;
787 );
788 }
789
790 /*
791 * If they've nak'd our authentication-protocol, check whether
792 * they are proposing a different protocol, or a different
793 * hash algorithm for CHAP.
794 */
795 if ((go->neg_chap || go->neg_upap)
796 && len >= CILEN_SHORT
797 && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
798 cilen = p[1];
799 len -= cilen;
800 no.neg_chap = go->neg_chap;
801 no.neg_upap = go->neg_upap;
802 INCPTR(2, p);
803 GETSHORT(cishort, p);
804 if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
805 /*
806 * If we were asking for CHAP, they obviously don't want to do it.
807 * If we weren't asking for CHAP, then we were asking for PAP,
808 * in which case this Nak is bad.
809 */
810 if (!go->neg_chap)
811 goto bad;
812 try.neg_chap = 0;
813
814 } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
815 GETCHAR(cichar, p);
816 if (go->neg_chap) {
817 /*
818 * We were asking for CHAP/MD5; they must want a different
819 * algorithm. If they can't do MD5, we'll have to stop
820 * asking for CHAP.
821 */
822 if (cichar != go->chap_mdtype)
823 try.neg_chap = 0;
824 } else {
825 /*
826 * Stop asking for PAP if we were asking for it.
827 */
828 try.neg_upap = 0;
829 }
830
831 } else {
832 /*
833 * We don't recognize what they're suggesting.
834 * Stop asking for what we were asking for.
835 */
836 if (go->neg_chap)
837 try.neg_chap = 0;
838 else
839 try.neg_upap = 0;
840 p += cilen - CILEN_SHORT;
841 }
842 }
843
844 /*
845 * If they can't cope with our link quality protocol, we'll have
846 * to stop asking for LQR. We haven't got any other protocol.
847 * If they Nak the reporting period, take their value XXX ?
848 */
849 NAKCILQR(CI_QUALITY, neg_lqr,
850 if (cishort != PPP_LQR)
851 try.neg_lqr = 0;
852 else
853 try.lqr_period = cilong;
854 );
855
856 /*
857 * Only implementing CBCP...not the rest of the callback options
858 */
859 NAKCICHAR(CI_CALLBACK, neg_cbcp,
860 try.neg_cbcp = 0;
861 );
862
863 /*
864 * Check for a looped-back line.
865 */
866 NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
867 try.magicnumber = magic();
868 looped_back = 1;
869 );
870
871 /*
872 * Peer shouldn't send Nak for protocol compression or
873 * address/control compression requests; they should send
874 * a Reject instead. If they send a Nak, treat it as a Reject.
875 */
876 NAKCIVOID(CI_PCOMPRESSION, neg_pcompression,
877 try.neg_pcompression = 0;
878 );
879 NAKCIVOID(CI_ACCOMPRESSION, neg_accompression,
880 try.neg_accompression = 0;
881 );
882
883 /*
884 * There may be remaining CIs, if the peer is requesting negotiation
885 * on an option that we didn't include in our request packet.
886 * If we see an option that we requested, or one we've already seen
887 * in this packet, then this packet is bad.
888 * If we wanted to respond by starting to negotiate on the requested
889 * option(s), we could, but we don't, because except for the
890 * authentication type and quality protocol, if we are not negotiating
891 * an option, it is because we were told not to.
892 * For the authentication type, the Nak from the peer means
893 * `let me authenticate myself with you' which is a bit pointless.
894 * For the quality protocol, the Nak means `ask me to send you quality
895 * reports', but if we didn't ask for them, we don't want them.
896 * An option we don't recognize represents the peer asking to
897 * negotiate some option we don't support, so ignore it.
898 */
899 while (len > CILEN_VOID) {
900 GETCHAR(citype, p);
901 GETCHAR(cilen, p);
902 if (cilen < CILEN_VOID || (len -= cilen) < 0)
903 goto bad;
904 next = p + cilen - 2;
905
906 switch (citype) {
907 case CI_MRU:
908 if ((go->neg_mru && go->mru != DEFMRU)
909 || no.neg_mru || cilen != CILEN_SHORT)
910 goto bad;
911 GETSHORT(cishort, p);
912 if (cishort < DEFMRU)
913 try.mru = cishort;
914 break;
915 case CI_ASYNCMAP:
916 if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
917 || no.neg_asyncmap || cilen != CILEN_LONG)
918 goto bad;
919 break;
920 case CI_AUTHTYPE:
921 if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap)
922 goto bad;
923 break;
924 case CI_MAGICNUMBER:
925 if (go->neg_magicnumber || no.neg_magicnumber ||
926 cilen != CILEN_LONG)
927 goto bad;
928 break;
929 case CI_PCOMPRESSION:
930 if (go->neg_pcompression || no.neg_pcompression
931 || cilen != CILEN_VOID)
932 goto bad;
933 break;
934 case CI_ACCOMPRESSION:
935 if (go->neg_accompression || no.neg_accompression
936 || cilen != CILEN_VOID)
937 goto bad;
938 break;
939 case CI_QUALITY:
940 if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
941 goto bad;
942 break;
943 }
944 p = next;
945 }
946
947 /* If there is still anything left, this packet is bad. */
948 if (len != 0)
949 goto bad;
950
951 /*
952 * OK, the Nak is good. Now we can update state.
953 */
954 if (f->state != OPENED) {
955 if (looped_back) {
956 if (++try.numloops >= lcp_loopbackfail) {
957 syslog(LOG_NOTICE, "Serial line is looped back.");
958 lcp_close(f->unit, "Loopback detected");
959 }
960 } else
961 try.numloops = 0;
962 *go = try;
963 }
964
965 return 1;
966
967 bad:
968 LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!"));
969 return 0;
970 }
971
972
973 /*
974 * lcp_rejci - Peer has Rejected some of our CIs.
975 * This should not modify any state if the Reject is bad
976 * or if LCP is in the OPENED state.
977 *
978 * Returns:
979 * 0 - Reject was bad.
980 * 1 - Reject was good.
981 */
982 static int
lcp_rejci(fsm * f,u_char * p,int len)983 lcp_rejci(fsm *f, u_char *p, int len)
984 {
985 lcp_options *go = &lcp_gotoptions[f->unit];
986 u_char cichar;
987 u_short cishort;
988 u_int32_t cilong;
989 lcp_options try; /* options to request next time */
990
991 try = *go;
992
993 /*
994 * Any Rejected CIs must be in exactly the same order that we sent.
995 * Check packet length and CI length at each step.
996 * If we find any deviations, then this packet is bad.
997 */
998 #define REJCIVOID(opt, neg) \
999 if (go->neg && \
1000 len >= CILEN_VOID && \
1001 p[1] == CILEN_VOID && \
1002 p[0] == opt) { \
1003 len -= CILEN_VOID; \
1004 INCPTR(CILEN_VOID, p); \
1005 try.neg = 0; \
1006 LCPDEBUG((LOG_INFO, "lcp_rejci rejected void opt %d", opt)); \
1007 }
1008 #define REJCISHORT(opt, neg, val) \
1009 if (go->neg && \
1010 len >= CILEN_SHORT && \
1011 p[1] == CILEN_SHORT && \
1012 p[0] == opt) { \
1013 len -= CILEN_SHORT; \
1014 INCPTR(2, p); \
1015 GETSHORT(cishort, p); \
1016 /* Check rejected value. */ \
1017 if (cishort != val) \
1018 goto bad; \
1019 try.neg = 0; \
1020 LCPDEBUG((LOG_INFO,"lcp_rejci rejected short opt %d", opt)); \
1021 }
1022 #define REJCICHAP(opt, neg, val, digest) \
1023 if (go->neg && \
1024 len >= CILEN_CHAP && \
1025 p[1] == CILEN_CHAP && \
1026 p[0] == opt) { \
1027 len -= CILEN_CHAP; \
1028 INCPTR(2, p); \
1029 GETSHORT(cishort, p); \
1030 GETCHAR(cichar, p); \
1031 /* Check rejected value. */ \
1032 if (cishort != val || cichar != digest) \
1033 goto bad; \
1034 try.neg = 0; \
1035 try.neg_upap = 0; \
1036 LCPDEBUG((LOG_INFO,"lcp_rejci rejected chap opt %d", opt)); \
1037 }
1038 #define REJCILONG(opt, neg, val) \
1039 if (go->neg && \
1040 len >= CILEN_LONG && \
1041 p[1] == CILEN_LONG && \
1042 p[0] == opt) { \
1043 len -= CILEN_LONG; \
1044 INCPTR(2, p); \
1045 GETLONG(cilong, p); \
1046 /* Check rejected value. */ \
1047 if (cilong != val) \
1048 goto bad; \
1049 try.neg = 0; \
1050 LCPDEBUG((LOG_INFO,"lcp_rejci rejected long opt %d", opt)); \
1051 }
1052 #define REJCILQR(opt, neg, val) \
1053 if (go->neg && \
1054 len >= CILEN_LQR && \
1055 p[1] == CILEN_LQR && \
1056 p[0] == opt) { \
1057 len -= CILEN_LQR; \
1058 INCPTR(2, p); \
1059 GETSHORT(cishort, p); \
1060 GETLONG(cilong, p); \
1061 /* Check rejected value. */ \
1062 if (cishort != PPP_LQR || cilong != val) \
1063 goto bad; \
1064 try.neg = 0; \
1065 LCPDEBUG((LOG_INFO,"lcp_rejci rejected LQR opt %d", opt)); \
1066 }
1067 #define REJCICBCP(opt, neg, val) \
1068 if (go->neg && \
1069 len >= CILEN_CBCP && \
1070 p[1] == CILEN_CBCP && \
1071 p[0] == opt) { \
1072 len -= CILEN_CBCP; \
1073 INCPTR(2, p); \
1074 GETCHAR(cichar, p); \
1075 /* Check rejected value. */ \
1076 if (cichar != val) \
1077 goto bad; \
1078 try.neg = 0; \
1079 LCPDEBUG((LOG_INFO,"lcp_rejci rejected Callback opt %d", opt)); \
1080 }
1081
1082 REJCISHORT(CI_MRU, neg_mru, go->mru);
1083 REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
1084 REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype);
1085 if (!go->neg_chap) {
1086 REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
1087 }
1088 REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
1089 REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
1090 REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
1091 REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
1092 REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
1093
1094 /*
1095 * If there are any remaining CIs, then this packet is bad.
1096 */
1097 if (len != 0)
1098 goto bad;
1099 /*
1100 * Now we can update state.
1101 */
1102 if (f->state != OPENED)
1103 *go = try;
1104 return 1;
1105
1106 bad:
1107 LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!"));
1108 return 0;
1109 }
1110
1111
1112 /*
1113 * lcp_reqci - Check the peer's requested CIs and send appropriate response.
1114 *
1115 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
1116 * appropriately. If reject_if_disagree is non-zero, doesn't return
1117 * CONFNAK; returns CONFREJ if it can't return CONFACK.
1118 */
1119 static int
lcp_reqci(fsm * f,u_char * inp,int * lenp,int reject_if_disagree)1120 lcp_reqci(fsm *f, u_char *inp, int *lenp, int reject_if_disagree)
1121 {
1122 lcp_options *go = &lcp_gotoptions[f->unit];
1123 lcp_options *ho = &lcp_hisoptions[f->unit];
1124 lcp_options *ao = &lcp_allowoptions[f->unit];
1125 u_char *cip, *next; /* Pointer to current and next CIs */
1126 int cilen, citype, cichar; /* Parsed len, type, char value */
1127 u_short cishort; /* Parsed short value */
1128 u_int32_t cilong; /* Parse long value */
1129 int rc = CONFACK; /* Final packet return code */
1130 int orc; /* Individual option return code */
1131 u_char *p; /* Pointer to next char to parse */
1132 u_char *rejp; /* Pointer to next char in reject frame */
1133 u_char *nakp; /* Pointer to next char in Nak frame */
1134 int l = *lenp; /* Length left */
1135
1136 /*
1137 * Reset all his options.
1138 */
1139 BZERO(ho, sizeof(*ho));
1140
1141 /*
1142 * Process all his options.
1143 */
1144 next = inp;
1145 nakp = nak_buffer;
1146 rejp = inp;
1147 while (l) {
1148 orc = CONFACK; /* Assume success */
1149 cip = p = next; /* Remember beginning of CI */
1150 if (l < 2 || /* Not enough data for CI header or */
1151 p[1] < 2 || /* CI length too small or */
1152 p[1] > l) { /* CI length too big? */
1153 LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!"));
1154 orc = CONFREJ; /* Reject bad CI */
1155 cilen = l; /* Reject till end of packet */
1156 l = 0; /* Don't loop again */
1157 citype = 0;
1158 goto endswitch;
1159 }
1160 GETCHAR(citype, p); /* Parse CI type */
1161 GETCHAR(cilen, p); /* Parse CI length */
1162 l -= cilen; /* Adjust remaining length */
1163 next += cilen; /* Step to next CI */
1164
1165 switch (citype) { /* Check CI type */
1166 case CI_MRU:
1167 LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MRU"));
1168 if (!ao->neg_mru || /* Allow option? */
1169 cilen != CILEN_SHORT) { /* Check CI length */
1170 orc = CONFREJ; /* Reject CI */
1171 break;
1172 }
1173 GETSHORT(cishort, p); /* Parse MRU */
1174 LCPDEBUG((LOG_INFO, "(%d)", cishort));
1175
1176 /*
1177 * He must be able to receive at least our minimum.
1178 * No need to check a maximum. If he sends a large number,
1179 * we'll just ignore it.
1180 */
1181 if (cishort < MINMRU) {
1182 orc = CONFNAK; /* Nak CI */
1183 PUTCHAR(CI_MRU, nakp);
1184 PUTCHAR(CILEN_SHORT, nakp);
1185 PUTSHORT(MINMRU, nakp); /* Give him a hint */
1186 break;
1187 }
1188 ho->neg_mru = 1; /* Remember he sent MRU */
1189 ho->mru = cishort; /* And remember value */
1190 break;
1191
1192 case CI_ASYNCMAP:
1193 LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ASYNCMAP"));
1194 if (!ao->neg_asyncmap ||
1195 cilen != CILEN_LONG) {
1196 orc = CONFREJ;
1197 break;
1198 }
1199 GETLONG(cilong, p);
1200 LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong));
1201
1202 /*
1203 * Asyncmap must have set at least the bits
1204 * which are set in lcp_allowoptions[unit].asyncmap.
1205 */
1206 if ((ao->asyncmap & ~cilong) != 0) {
1207 orc = CONFNAK;
1208 PUTCHAR(CI_ASYNCMAP, nakp);
1209 PUTCHAR(CILEN_LONG, nakp);
1210 PUTLONG(ao->asyncmap | cilong, nakp);
1211 break;
1212 }
1213 ho->neg_asyncmap = 1;
1214 ho->asyncmap = cilong;
1215 break;
1216
1217 case CI_AUTHTYPE:
1218 LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd AUTHTYPE"));
1219 if (cilen < CILEN_SHORT ||
1220 !(ao->neg_upap || ao->neg_chap)) {
1221 /*
1222 * Reject the option if we're not willing to authenticate.
1223 */
1224 orc = CONFREJ;
1225 break;
1226 }
1227 GETSHORT(cishort, p);
1228 LCPDEBUG((LOG_INFO, "(%x)", cishort));
1229
1230 /*
1231 * Authtype must be UPAP or CHAP.
1232 *
1233 * Note: if both ao->neg_upap and ao->neg_chap are set,
1234 * and the peer sends a Configure-Request with two
1235 * authenticate-protocol requests, one for CHAP and one
1236 * for UPAP, then we will reject the second request.
1237 * Whether we end up doing CHAP or UPAP depends then on
1238 * the ordering of the CIs in the peer's Configure-Request.
1239 */
1240
1241 if (cishort == PPP_PAP) {
1242 if (ho->neg_chap || /* we've already accepted CHAP */
1243 cilen != CILEN_SHORT) {
1244 LCPDEBUG((LOG_WARNING,
1245 "lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
1246 orc = CONFREJ;
1247 break;
1248 }
1249 if (!ao->neg_upap) { /* we don't want to do PAP */
1250 orc = CONFNAK; /* NAK it and suggest CHAP */
1251 PUTCHAR(CI_AUTHTYPE, nakp);
1252 PUTCHAR(CILEN_CHAP, nakp);
1253 PUTSHORT(PPP_CHAP, nakp);
1254 PUTCHAR(ao->chap_mdtype, nakp);
1255 break;
1256 }
1257 ho->neg_upap = 1;
1258 break;
1259 }
1260 if (cishort == PPP_CHAP) {
1261 if (ho->neg_upap || /* we've already accepted PAP */
1262 cilen != CILEN_CHAP) {
1263 LCPDEBUG((LOG_INFO,
1264 "lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
1265 orc = CONFREJ;
1266 break;
1267 }
1268 if (!ao->neg_chap) { /* we don't want to do CHAP */
1269 orc = CONFNAK; /* NAK it and suggest PAP */
1270 PUTCHAR(CI_AUTHTYPE, nakp);
1271 PUTCHAR(CILEN_SHORT, nakp);
1272 PUTSHORT(PPP_PAP, nakp);
1273 break;
1274 }
1275 GETCHAR(cichar, p); /* get digest type*/
1276 if (cichar != CHAP_DIGEST_MD5) {
1277 orc = CONFNAK;
1278 PUTCHAR(CI_AUTHTYPE, nakp);
1279 PUTCHAR(CILEN_CHAP, nakp);
1280 PUTSHORT(PPP_CHAP, nakp);
1281 PUTCHAR(ao->chap_mdtype, nakp);
1282 break;
1283 }
1284 ho->chap_mdtype = cichar; /* save md type */
1285 ho->neg_chap = 1;
1286 break;
1287 }
1288
1289 /*
1290 * We don't recognize the protocol they're asking for.
1291 * Nak it with something we're willing to do.
1292 * (At this point we know ao->neg_upap || ao->neg_chap.)
1293 */
1294 orc = CONFNAK;
1295 PUTCHAR(CI_AUTHTYPE, nakp);
1296 if (ao->neg_chap) {
1297 PUTCHAR(CILEN_CHAP, nakp);
1298 PUTSHORT(PPP_CHAP, nakp);
1299 PUTCHAR(ao->chap_mdtype, nakp);
1300 } else {
1301 PUTCHAR(CILEN_SHORT, nakp);
1302 PUTSHORT(PPP_PAP, nakp);
1303 }
1304 break;
1305
1306 case CI_QUALITY:
1307 LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd QUALITY"));
1308 if (!ao->neg_lqr ||
1309 cilen != CILEN_LQR) {
1310 orc = CONFREJ;
1311 break;
1312 }
1313
1314 GETSHORT(cishort, p);
1315 GETLONG(cilong, p);
1316 LCPDEBUG((LOG_INFO, "(%x %x)", cishort, (unsigned int) cilong));
1317
1318 /*
1319 * Check the protocol and the reporting period.
1320 * XXX When should we Nak this, and what with?
1321 */
1322 if (cishort != PPP_LQR) {
1323 orc = CONFNAK;
1324 PUTCHAR(CI_QUALITY, nakp);
1325 PUTCHAR(CILEN_LQR, nakp);
1326 PUTSHORT(PPP_LQR, nakp);
1327 PUTLONG(ao->lqr_period, nakp);
1328 break;
1329 }
1330 break;
1331
1332 case CI_MAGICNUMBER:
1333 LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MAGICNUMBER"));
1334 if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
1335 cilen != CILEN_LONG) {
1336 orc = CONFREJ;
1337 break;
1338 }
1339 GETLONG(cilong, p);
1340 LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong));
1341
1342 /*
1343 * He must have a different magic number.
1344 */
1345 if (go->neg_magicnumber &&
1346 cilong == go->magicnumber) {
1347 cilong = magic(); /* Don't put magic() inside macro! */
1348 orc = CONFNAK;
1349 PUTCHAR(CI_MAGICNUMBER, nakp);
1350 PUTCHAR(CILEN_LONG, nakp);
1351 PUTLONG(cilong, nakp);
1352 break;
1353 }
1354 ho->neg_magicnumber = 1;
1355 ho->magicnumber = cilong;
1356 break;
1357
1358
1359 case CI_PCOMPRESSION:
1360 LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd PCOMPRESSION"));
1361 if (!ao->neg_pcompression ||
1362 cilen != CILEN_VOID) {
1363 orc = CONFREJ;
1364 break;
1365 }
1366 ho->neg_pcompression = 1;
1367 break;
1368
1369 case CI_ACCOMPRESSION:
1370 LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ACCOMPRESSION"));
1371 if (!ao->neg_accompression ||
1372 cilen != CILEN_VOID) {
1373 orc = CONFREJ;
1374 break;
1375 }
1376 ho->neg_accompression = 1;
1377 break;
1378
1379 default:
1380 LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd unknown option %d",
1381 citype));
1382 orc = CONFREJ;
1383 break;
1384 }
1385
1386 endswitch:
1387 LCPDEBUG((LOG_INFO, " (%s)", CODENAME(orc)));
1388 if (orc == CONFACK && /* Good CI */
1389 rc != CONFACK) /* but prior CI wasnt? */
1390 continue; /* Don't send this one */
1391
1392 if (orc == CONFNAK) { /* Nak this CI? */
1393 if (reject_if_disagree /* Getting fed up with sending NAKs? */
1394 && citype != CI_MAGICNUMBER) {
1395 orc = CONFREJ; /* Get tough if so */
1396 } else {
1397 if (rc == CONFREJ) /* Rejecting prior CI? */
1398 continue; /* Don't send this one */
1399 rc = CONFNAK;
1400 }
1401 }
1402 if (orc == CONFREJ) { /* Reject this CI */
1403 rc = CONFREJ;
1404 if (cip != rejp) /* Need to move rejected CI? */
1405 BMOVE(cip, rejp, cilen); /* Move it (NB: overlapped regions) */
1406 INCPTR(cilen, rejp); /* Update output pointer */
1407 }
1408 }
1409
1410 /*
1411 * If we wanted to send additional NAKs (for unsent CIs), the
1412 * code would go here. The extra NAKs would go at *nakp.
1413 * At present there are no cases where we want to ask the
1414 * peer to negotiate an option.
1415 */
1416
1417 switch (rc) {
1418 case CONFACK:
1419 *lenp = next - inp;
1420 break;
1421 case CONFNAK:
1422 /*
1423 * Copy the Nak'd options from the nak_buffer to the caller's buffer.
1424 */
1425 *lenp = nakp - nak_buffer;
1426 BCOPY(nak_buffer, inp, *lenp);
1427 break;
1428 case CONFREJ:
1429 *lenp = rejp - inp;
1430 break;
1431 }
1432
1433 LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.", CODENAME(rc)));
1434 return (rc); /* Return final code */
1435 }
1436
1437
1438 /*
1439 * lcp_up - LCP has come UP.
1440 */
1441 static void
lcp_up(fsm * f)1442 lcp_up(fsm *f)
1443 {
1444 lcp_options *wo = &lcp_wantoptions[f->unit];
1445 lcp_options *ho = &lcp_hisoptions[f->unit];
1446 lcp_options *go = &lcp_gotoptions[f->unit];
1447 lcp_options *ao = &lcp_allowoptions[f->unit];
1448
1449 if (!go->neg_magicnumber)
1450 go->magicnumber = 0;
1451 if (!ho->neg_magicnumber)
1452 ho->magicnumber = 0;
1453
1454 /*
1455 * Set our MTU to the smaller of the MTU we wanted and
1456 * the MRU our peer wanted. If we negotiated an MRU,
1457 * set our MRU to the larger of value we wanted and
1458 * the value we got in the negotiation.
1459 */
1460 ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)),
1461 (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
1462 ho->neg_pcompression, ho->neg_accompression);
1463 ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU),
1464 (go->neg_asyncmap? go->asyncmap: 0xffffffff),
1465 go->neg_pcompression, go->neg_accompression);
1466
1467 if (ho->neg_mru)
1468 peer_mru[f->unit] = ho->mru;
1469
1470 lcp_echo_lowerup(f->unit); /* Enable echo messages */
1471
1472 link_established(f->unit);
1473 }
1474
1475
1476 /*
1477 * lcp_down - LCP has gone DOWN.
1478 *
1479 * Alert other protocols.
1480 */
1481 static void
lcp_down(fsm * f)1482 lcp_down(fsm *f)
1483 {
1484 lcp_options *go = &lcp_gotoptions[f->unit];
1485
1486 lcp_echo_lowerdown(f->unit);
1487
1488 link_down(f->unit);
1489
1490 ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0);
1491 ppp_recv_config(f->unit, PPP_MRU,
1492 (go->neg_asyncmap? go->asyncmap: 0xffffffff),
1493 go->neg_pcompression, go->neg_accompression);
1494 peer_mru[f->unit] = PPP_MRU;
1495 }
1496
1497
1498 /*
1499 * lcp_starting - LCP needs the lower layer up.
1500 */
1501 static void
lcp_starting(fsm * f)1502 lcp_starting(fsm *f)
1503 {
1504 link_required(f->unit);
1505 }
1506
1507
1508 /*
1509 * lcp_finished - LCP has finished with the lower layer.
1510 */
1511 static void
lcp_finished(fsm * f)1512 lcp_finished(fsm *f)
1513 {
1514 link_terminated(f->unit);
1515 }
1516
1517
1518 /*
1519 * lcp_printpkt - print the contents of an LCP packet.
1520 */
1521 static char *lcp_codenames[] = {
1522 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1523 "TermReq", "TermAck", "CodeRej", "ProtRej",
1524 "EchoReq", "EchoRep", "DiscReq"
1525 };
1526
1527 static int
lcp_printpkt(u_char * p,int plen,void (* printer)(void *,char *,...),void * arg)1528 lcp_printpkt(u_char *p, int plen, void (*printer)(void *, char *, ...), void *arg)
1529 {
1530 int code, id, len, olen;
1531 u_char *pstart, *optend;
1532 u_short cishort;
1533 u_int32_t cilong;
1534
1535 if (plen < HEADERLEN)
1536 return 0;
1537 pstart = p;
1538 GETCHAR(code, p);
1539 GETCHAR(id, p);
1540 GETSHORT(len, p);
1541 if (len < HEADERLEN || len > plen)
1542 return 0;
1543
1544 if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *))
1545 printer(arg, " %s", lcp_codenames[code-1]);
1546 else
1547 printer(arg, " code=0x%x", code);
1548 printer(arg, " id=0x%x", id);
1549 len -= HEADERLEN;
1550 switch (code) {
1551 case CONFREQ:
1552 case CONFACK:
1553 case CONFNAK:
1554 case CONFREJ:
1555 /* print option list */
1556 while (len >= 2) {
1557 GETCHAR(code, p);
1558 GETCHAR(olen, p);
1559 p -= 2;
1560 if (olen < 2 || olen > len) {
1561 break;
1562 }
1563 printer(arg, " <");
1564 len -= olen;
1565 optend = p + olen;
1566 switch (code) {
1567 case CI_MRU:
1568 if (olen == CILEN_SHORT) {
1569 p += 2;
1570 GETSHORT(cishort, p);
1571 printer(arg, "mru %d", cishort);
1572 }
1573 break;
1574 case CI_ASYNCMAP:
1575 if (olen == CILEN_LONG) {
1576 p += 2;
1577 GETLONG(cilong, p);
1578 printer(arg, "asyncmap 0x%x", cilong);
1579 }
1580 break;
1581 case CI_AUTHTYPE:
1582 if (olen >= CILEN_SHORT) {
1583 p += 2;
1584 printer(arg, "auth ");
1585 GETSHORT(cishort, p);
1586 switch (cishort) {
1587 case PPP_PAP:
1588 printer(arg, "pap");
1589 break;
1590 case PPP_CHAP:
1591 printer(arg, "chap");
1592 break;
1593 default:
1594 printer(arg, "0x%x", cishort);
1595 }
1596 }
1597 break;
1598 case CI_QUALITY:
1599 if (olen >= CILEN_SHORT) {
1600 p += 2;
1601 printer(arg, "quality ");
1602 GETSHORT(cishort, p);
1603 switch (cishort) {
1604 case PPP_LQR:
1605 printer(arg, "lqr");
1606 break;
1607 default:
1608 printer(arg, "0x%x", cishort);
1609 }
1610 }
1611 break;
1612 case CI_CALLBACK:
1613 if (olen >= CILEN_CHAR) {
1614 p += 2;
1615 printer(arg, "callback ");
1616 GETSHORT(cishort, p);
1617 switch (cishort) {
1618 case CBCP_OPT:
1619 printer(arg, "CBCP");
1620 break;
1621 default:
1622 printer(arg, "0x%x", cishort);
1623 }
1624 }
1625 break;
1626 case CI_MAGICNUMBER:
1627 if (olen == CILEN_LONG) {
1628 p += 2;
1629 GETLONG(cilong, p);
1630 printer(arg, "magic 0x%x", cilong);
1631 }
1632 break;
1633 case CI_PCOMPRESSION:
1634 if (olen == CILEN_VOID) {
1635 p += 2;
1636 printer(arg, "pcomp");
1637 }
1638 break;
1639 case CI_ACCOMPRESSION:
1640 if (olen == CILEN_VOID) {
1641 p += 2;
1642 printer(arg, "accomp");
1643 }
1644 break;
1645 }
1646 while (p < optend) {
1647 GETCHAR(code, p);
1648 printer(arg, " %.2x", code);
1649 }
1650 printer(arg, ">");
1651 }
1652 break;
1653
1654 case TERMACK:
1655 case TERMREQ:
1656 if (len > 0 && *p >= ' ' && *p < 0x7f) {
1657 printer(arg, " ");
1658 print_string(p, len, printer, arg);
1659 p += len;
1660 len = 0;
1661 }
1662 break;
1663
1664 case ECHOREQ:
1665 case ECHOREP:
1666 case DISCREQ:
1667 if (len >= 4) {
1668 GETLONG(cilong, p);
1669 printer(arg, " magic=0x%x", cilong);
1670 p += 4;
1671 len -= 4;
1672 }
1673 break;
1674 }
1675
1676 /* print the rest of the bytes in the packet */
1677 for (; len > 0; --len) {
1678 GETCHAR(code, p);
1679 printer(arg, " %.2x", code);
1680 }
1681
1682 return p - pstart;
1683 }
1684
1685 /*
1686 * Time to shut down the link because there is nothing out there.
1687 */
1688
1689 static void
LcpLinkFailure(fsm * f)1690 LcpLinkFailure(fsm *f)
1691 {
1692 if (f->state == OPENED) {
1693 syslog(LOG_INFO, "No response to %d echo-requests", lcp_echos_pending);
1694 syslog(LOG_NOTICE, "Serial link appears to be disconnected.");
1695 lcp_close(f->unit, "Peer not responding");
1696 }
1697 }
1698
1699 /*
1700 * Timer expired for the LCP echo requests from this process.
1701 */
1702
1703 static void
LcpEchoCheck(fsm * f)1704 LcpEchoCheck(fsm *f)
1705 {
1706 LcpSendEchoRequest (f);
1707
1708 /*
1709 * Start the timer for the next interval.
1710 */
1711 assert (lcp_echo_timer_running==0);
1712 TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
1713 lcp_echo_timer_running = 1;
1714 }
1715
1716 /*
1717 * LcpEchoTimeout - Timer expired on the LCP echo
1718 */
1719
1720 static void
LcpEchoTimeout(void * arg)1721 LcpEchoTimeout(void *arg)
1722 {
1723 if (lcp_echo_timer_running != 0) {
1724 lcp_echo_timer_running = 0;
1725 LcpEchoCheck ((fsm *) arg);
1726 }
1727 }
1728
1729 /*
1730 * LcpEchoReply - LCP has received a reply to the echo
1731 */
1732
1733 static void
lcp_received_echo_reply(fsm * f,int id,u_char * inp,int len)1734 lcp_received_echo_reply(fsm *f, int id, u_char *inp, int len)
1735 {
1736 u_int32_t magic;
1737
1738 /* Check the magic number - don't count replies from ourselves. */
1739 if (len < 4) {
1740 syslog(LOG_DEBUG, "lcp: received short Echo-Reply, length %d", len);
1741 return;
1742 }
1743 GETLONG(magic, inp);
1744 if (lcp_gotoptions[f->unit].neg_magicnumber
1745 && magic == lcp_gotoptions[f->unit].magicnumber) {
1746 syslog(LOG_WARNING, "appear to have received our own echo-reply!");
1747 return;
1748 }
1749
1750 /* Reset the number of outstanding echo frames */
1751 lcp_echos_pending = 0;
1752 }
1753
1754 /*
1755 * LcpSendEchoRequest - Send an echo request frame to the peer
1756 */
1757
1758 static void
LcpSendEchoRequest(fsm * f)1759 LcpSendEchoRequest(fsm *f)
1760 {
1761 u_int32_t lcp_magic;
1762 u_char pkt[4], *pktp;
1763
1764 /*
1765 * Detect the failure of the peer at this point.
1766 */
1767 if (lcp_echo_fails != 0) {
1768 if (lcp_echos_pending >= lcp_echo_fails) {
1769 LcpLinkFailure(f);
1770 lcp_echos_pending = 0;
1771 }
1772 }
1773
1774 /*
1775 * Make and send the echo request frame.
1776 */
1777 if (f->state == OPENED) {
1778 lcp_magic = lcp_gotoptions[f->unit].magicnumber;
1779 pktp = pkt;
1780 PUTLONG(lcp_magic, pktp);
1781 fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
1782 ++lcp_echos_pending;
1783 }
1784 }
1785
1786 /*
1787 * lcp_echo_lowerup - Start the timer for the LCP frame
1788 */
1789
1790 static void
lcp_echo_lowerup(int unit)1791 lcp_echo_lowerup(int unit)
1792 {
1793 fsm *f = &lcp_fsm[unit];
1794
1795 /* Clear the parameters for generating echo frames */
1796 lcp_echos_pending = 0;
1797 lcp_echo_number = 0;
1798 lcp_echo_timer_running = 0;
1799
1800 /* If a timeout interval is specified then start the timer */
1801 if (lcp_echo_interval != 0)
1802 LcpEchoCheck (f);
1803 }
1804
1805 /*
1806 * lcp_echo_lowerdown - Stop the timer for the LCP frame
1807 */
1808
1809 static void
lcp_echo_lowerdown(int unit)1810 lcp_echo_lowerdown(int unit)
1811 {
1812 fsm *f = &lcp_fsm[unit];
1813
1814 if (lcp_echo_timer_running != 0) {
1815 UNTIMEOUT (LcpEchoTimeout, f);
1816 lcp_echo_timer_running = 0;
1817 }
1818 }
1819