1 /* $OpenBSD: ipcp.c,v 1.17 2024/08/10 05:32:28 jsg Exp $ */
2
3 /*
4 * ipcp.c - PPP IP 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 <sys/types.h>
50 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <syslog.h>
56 #include <netdb.h>
57
58 #include "pppd.h"
59 #include "fsm.h"
60 #include "ipcp.h"
61 #include "pathnames.h"
62
63 /* global vars */
64 ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
65 ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
66 ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
67 ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
68
69 /* local vars */
70 static int cis_received[NUM_PPP]; /* # Conf-Reqs received */
71 static int default_route_set[NUM_PPP]; /* Have set up a default route */
72 static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */
73
74 /*
75 * Callbacks for fsm code. (CI = Configuration Information)
76 */
77 static void ipcp_resetci(fsm *); /* Reset our CI */
78 static int ipcp_cilen(fsm *); /* Return length of our CI */
79 static void ipcp_addci(fsm *, u_char *, int *); /* Add our CI */
80 static int ipcp_ackci(fsm *, u_char *, int); /* Peer ack'd our CI */
81 static int ipcp_nakci(fsm *, u_char *, int); /* Peer nak'd our CI */
82 static int ipcp_rejci(fsm *, u_char *, int); /* Peer rej'd our CI */
83 static int ipcp_reqci(fsm *, u_char *, int *, int); /* Rcv CI */
84 static void ipcp_up(fsm *); /* We're UP */
85 static void ipcp_down(fsm *); /* We're DOWN */
86 static void ipcp_script(fsm *, char *); /* Run an up/down script */
87 static void ipcp_finished(fsm *); /* Don't need lower layer */
88
89 fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
90
91 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
92 ipcp_resetci, /* Reset our Configuration Information */
93 ipcp_cilen, /* Length of our Configuration Information */
94 ipcp_addci, /* Add our Configuration Information */
95 ipcp_ackci, /* ACK our Configuration Information */
96 ipcp_nakci, /* NAK our Configuration Information */
97 ipcp_rejci, /* Reject our Configuration Information */
98 ipcp_reqci, /* Request peer's Configuration Information */
99 ipcp_up, /* Called when fsm reaches OPENED state */
100 ipcp_down, /* Called when fsm leaves OPENED state */
101 NULL, /* Called when we want the lower layer up */
102 ipcp_finished, /* Called when we want the lower layer down */
103 NULL, /* Called when Protocol-Reject received */
104 NULL, /* Retransmission is necessary */
105 NULL, /* Called to handle protocol-specific codes */
106 "IPCP" /* String name of protocol */
107 };
108
109 /*
110 * Protocol entry points from main code.
111 */
112 static void ipcp_init(int);
113 static void ipcp_open(int);
114 static void ipcp_close(int, char *);
115 static void ipcp_lowerup(int);
116 static void ipcp_lowerdown(int);
117 static void ipcp_input(int, u_char *, int);
118 static void ipcp_protrej(int);
119 static int ipcp_printpkt(u_char *, int, void (*)(void *, char *, ...), void *);
120 static void ip_check_options(void);
121 static int ip_demand_conf(int);
122 static int ip_active_pkt(u_char *, int);
123
124 struct protent ipcp_protent = {
125 PPP_IPCP,
126 ipcp_init,
127 ipcp_input,
128 ipcp_protrej,
129 ipcp_lowerup,
130 ipcp_lowerdown,
131 ipcp_open,
132 ipcp_close,
133 ipcp_printpkt,
134 NULL,
135 1,
136 "IPCP",
137 ip_check_options,
138 ip_demand_conf,
139 ip_active_pkt
140 };
141
142 static void ipcp_clear_addrs(int);
143
144 /*
145 * Lengths of configuration options.
146 */
147 #define CILEN_VOID 2
148 #define CILEN_COMPRESS 4 /* min length for compression protocol opt. */
149 #define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */
150 #define CILEN_ADDR 6 /* new-style single address option */
151 #define CILEN_ADDRS 10 /* old-style dual address option */
152
153
154 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \
155 (x) == CONFNAK ? "NAK" : "REJ")
156
157
158 /*
159 * Make a string representation of a network IP address.
160 */
161 char *
ip_ntoa(u_int32_t ipaddr)162 ip_ntoa(u_int32_t ipaddr)
163 {
164 static char b[64];
165
166 ipaddr = ntohl(ipaddr);
167
168 snprintf(b, sizeof b, "%d.%d.%d.%d",
169 (u_char)(ipaddr >> 24),
170 (u_char)(ipaddr >> 16),
171 (u_char)(ipaddr >> 8),
172 (u_char)(ipaddr));
173 return b;
174 }
175
176
177 /*
178 * ipcp_init - Initialize IPCP.
179 */
180 static void
ipcp_init(int unit)181 ipcp_init(int unit)
182 {
183 fsm *f = &ipcp_fsm[unit];
184 ipcp_options *wo = &ipcp_wantoptions[unit];
185 ipcp_options *ao = &ipcp_allowoptions[unit];
186
187 f->unit = unit;
188 f->protocol = PPP_IPCP;
189 f->callbacks = &ipcp_callbacks;
190 fsm_init(&ipcp_fsm[unit]);
191
192 memset(wo, 0, sizeof(*wo));
193 memset(ao, 0, sizeof(*ao));
194
195 wo->neg_addr = 1;
196 wo->neg_vj = 1;
197 wo->vj_protocol = IPCP_VJ_COMP;
198 wo->maxslotindex = MAX_STATES - 1; /* really max index */
199 wo->cflag = 1;
200
201 /* max slots and slot-id compression are currently hardwired in */
202 /* ppp_if.c to 16 and 1, this needs to be changed (among other */
203 /* things) gmc */
204
205 ao->neg_addr = 1;
206 ao->neg_vj = 1;
207 ao->maxslotindex = MAX_STATES - 1;
208 ao->cflag = 1;
209
210 /*
211 * XXX These control whether the user may use the proxyarp
212 * and defaultroute options.
213 */
214 ao->proxy_arp = 1;
215 ao->default_route = 1;
216 }
217
218
219 /*
220 * ipcp_open - IPCP is allowed to come up.
221 */
222 static void
ipcp_open(int unit)223 ipcp_open(int unit)
224 {
225 fsm_open(&ipcp_fsm[unit]);
226 }
227
228
229 /*
230 * ipcp_close - Take IPCP down.
231 */
232 static void
ipcp_close(int unit,char * reason)233 ipcp_close(int unit, char *reason)
234 {
235 fsm_close(&ipcp_fsm[unit], reason);
236 }
237
238
239 /*
240 * ipcp_lowerup - The lower layer is up.
241 */
242 static void
ipcp_lowerup(int unit)243 ipcp_lowerup(int unit)
244 {
245 fsm_lowerup(&ipcp_fsm[unit]);
246 }
247
248
249 /*
250 * ipcp_lowerdown - The lower layer is down.
251 */
252 static void
ipcp_lowerdown(int unit)253 ipcp_lowerdown(int unit)
254 {
255 fsm_lowerdown(&ipcp_fsm[unit]);
256 }
257
258
259 /*
260 * ipcp_input - Input IPCP packet.
261 */
262 static void
ipcp_input(int unit,u_char * p,int len)263 ipcp_input(int unit, u_char *p, int len)
264 {
265 fsm_input(&ipcp_fsm[unit], p, len);
266 }
267
268
269 /*
270 * ipcp_protrej - A Protocol-Reject was received for IPCP.
271 *
272 * Pretend the lower layer went down, so we shut up.
273 */
274 static void
ipcp_protrej(int unit)275 ipcp_protrej(int unit)
276 {
277 fsm_lowerdown(&ipcp_fsm[unit]);
278 }
279
280
281 /*
282 * ipcp_resetci - Reset our CI.
283 */
284 static void
ipcp_resetci(fsm * f)285 ipcp_resetci(fsm *f)
286 {
287 ipcp_options *wo = &ipcp_wantoptions[f->unit];
288
289 wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
290 if (wo->ouraddr == 0)
291 wo->accept_local = 1;
292 if (wo->hisaddr == 0)
293 wo->accept_remote = 1;
294 ipcp_gotoptions[f->unit] = *wo;
295 cis_received[f->unit] = 0;
296 }
297
298
299 /*
300 * ipcp_cilen - Return length of our CI.
301 */
302 static int
ipcp_cilen(fsm * f)303 ipcp_cilen(fsm *f)
304 {
305 ipcp_options *go = &ipcp_gotoptions[f->unit];
306 ipcp_options *wo = &ipcp_wantoptions[f->unit];
307 ipcp_options *ho = &ipcp_hisoptions[f->unit];
308
309 #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
310 #define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
311
312 /*
313 * First see if we want to change our options to the old
314 * forms because we have received old forms from the peer.
315 */
316 if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
317 /* use the old style of address negotiation */
318 go->neg_addr = 1;
319 go->old_addrs = 1;
320 }
321 if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
322 /* try an older style of VJ negotiation */
323 if (cis_received[f->unit] == 0) {
324 /* keep trying the new style until we see some CI from the peer */
325 go->neg_vj = 1;
326 } else {
327 /* use the old style only if the peer did */
328 if (ho->neg_vj && ho->old_vj) {
329 go->neg_vj = 1;
330 go->old_vj = 1;
331 go->vj_protocol = ho->vj_protocol;
332 }
333 }
334 }
335
336 return (LENCIADDR(go->neg_addr, go->old_addrs) +
337 LENCIVJ(go->neg_vj, go->old_vj));
338 }
339
340
341 /*
342 * ipcp_addci - Add our desired CIs to a packet.
343 */
344 static void
ipcp_addci(fsm * f,u_char * ucp,int * lenp)345 ipcp_addci(fsm *f, u_char *ucp, int *lenp)
346 {
347 ipcp_options *go = &ipcp_gotoptions[f->unit];
348 int len = *lenp;
349
350 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
351 if (neg) { \
352 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
353 if (len >= vjlen) { \
354 PUTCHAR(opt, ucp); \
355 PUTCHAR(vjlen, ucp); \
356 PUTSHORT(val, ucp); \
357 if (!old) { \
358 PUTCHAR(maxslotindex, ucp); \
359 PUTCHAR(cflag, ucp); \
360 } \
361 len -= vjlen; \
362 } else \
363 neg = 0; \
364 }
365
366 #define ADDCIADDR(opt, neg, old, val1, val2) \
367 if (neg) { \
368 int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
369 if (len >= addrlen) { \
370 u_int32_t l; \
371 PUTCHAR(opt, ucp); \
372 PUTCHAR(addrlen, ucp); \
373 l = ntohl(val1); \
374 PUTLONG(l, ucp); \
375 if (old) { \
376 l = ntohl(val2); \
377 PUTLONG(l, ucp); \
378 } \
379 len -= addrlen; \
380 } else \
381 neg = 0; \
382 }
383
384 ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
385 go->old_addrs, go->ouraddr, go->hisaddr);
386
387 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
388 go->maxslotindex, go->cflag);
389
390 *lenp -= len;
391 }
392
393
394 /*
395 * ipcp_ackci - Ack our CIs.
396 *
397 * Returns:
398 * 0 - Ack was bad.
399 * 1 - Ack was good.
400 */
401 static int
ipcp_ackci(fsm * f,u_char * p,int len)402 ipcp_ackci(fsm *f, u_char *p, int len)
403 {
404 ipcp_options *go = &ipcp_gotoptions[f->unit];
405 u_short cilen, citype, cishort;
406 u_int32_t cilong;
407 u_char cimaxslotindex, cicflag;
408
409 /*
410 * CIs must be in exactly the same order that we sent...
411 * Check packet length and CI length at each step.
412 * If we find any deviations, then this packet is bad.
413 */
414
415 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
416 if (neg) { \
417 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
418 if ((len -= vjlen) < 0) \
419 goto bad; \
420 GETCHAR(citype, p); \
421 GETCHAR(cilen, p); \
422 if (cilen != vjlen || \
423 citype != opt) \
424 goto bad; \
425 GETSHORT(cishort, p); \
426 if (cishort != val) \
427 goto bad; \
428 if (!old) { \
429 GETCHAR(cimaxslotindex, p); \
430 if (cimaxslotindex != maxslotindex) \
431 goto bad; \
432 GETCHAR(cicflag, p); \
433 if (cicflag != cflag) \
434 goto bad; \
435 } \
436 }
437
438 #define ACKCIADDR(opt, neg, old, val1, val2) \
439 if (neg) { \
440 int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
441 u_int32_t l; \
442 if ((len -= addrlen) < 0) \
443 goto bad; \
444 GETCHAR(citype, p); \
445 GETCHAR(cilen, p); \
446 if (cilen != addrlen || \
447 citype != opt) \
448 goto bad; \
449 GETLONG(l, p); \
450 cilong = htonl(l); \
451 if (val1 != cilong) \
452 goto bad; \
453 if (old) { \
454 GETLONG(l, p); \
455 cilong = htonl(l); \
456 if (val2 != cilong) \
457 goto bad; \
458 } \
459 }
460
461 ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
462 go->old_addrs, go->ouraddr, go->hisaddr);
463
464 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
465 go->maxslotindex, go->cflag);
466
467 /*
468 * If there are any remaining CIs, then this packet is bad.
469 */
470 if (len != 0)
471 goto bad;
472 return (1);
473
474 bad:
475 IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!"));
476 return (0);
477 }
478
479 /*
480 * ipcp_nakci - Peer has sent a NAK for some of our CIs.
481 * This should not modify any state if the Nak is bad
482 * or if IPCP is in the OPENED state.
483 *
484 * Returns:
485 * 0 - Nak was bad.
486 * 1 - Nak was good.
487 */
488 static int
ipcp_nakci(fsm * f,u_char * p,int len)489 ipcp_nakci(fsm *f, u_char *p, int len)
490 {
491 ipcp_options *go = &ipcp_gotoptions[f->unit];
492 u_char cimaxslotindex, cicflag;
493 u_char citype, cilen, *next;
494 u_short cishort;
495 u_int32_t ciaddr1, ciaddr2, l;
496 ipcp_options no; /* options we've seen Naks for */
497 ipcp_options try; /* options to request next time */
498
499 BZERO(&no, sizeof(no));
500 try = *go;
501
502 /*
503 * Any Nak'd CIs must be in exactly the same order that we sent.
504 * Check packet length and CI length at each step.
505 * If we find any deviations, then this packet is bad.
506 */
507 #define NAKCIADDR(opt, neg, old, code) \
508 if (go->neg && \
509 len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
510 p[1] == cilen && \
511 p[0] == opt) { \
512 len -= cilen; \
513 INCPTR(2, p); \
514 GETLONG(l, p); \
515 ciaddr1 = htonl(l); \
516 if (old) { \
517 GETLONG(l, p); \
518 ciaddr2 = htonl(l); \
519 no.old_addrs = 1; \
520 } else \
521 ciaddr2 = 0; \
522 no.neg = 1; \
523 code \
524 }
525
526 #define NAKCIVJ(opt, neg, code) \
527 if (go->neg && \
528 ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
529 len >= cilen && \
530 p[0] == opt) { \
531 len -= cilen; \
532 INCPTR(2, p); \
533 GETSHORT(cishort, p); \
534 no.neg = 1; \
535 code \
536 }
537
538 /*
539 * Accept the peer's idea of {our,his} address, if different
540 * from our idea, only if the accept_{local,remote} flag is set.
541 */
542 NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
543 if (go->accept_local && ciaddr1) { /* Do we know our address? */
544 try.ouraddr = ciaddr1;
545 IPCPDEBUG((LOG_INFO, "local IP address %s",
546 ip_ntoa(ciaddr1)));
547 }
548 if (go->accept_remote && ciaddr2) { /* Does he know his? */
549 try.hisaddr = ciaddr2;
550 IPCPDEBUG((LOG_INFO, "remote IP address %s",
551 ip_ntoa(ciaddr2)));
552 }
553 );
554
555 /*
556 * Accept the peer's value of maxslotindex provided that it
557 * is less than what we asked for. Turn off slot-ID compression
558 * if the peer wants. Send old-style compress-type option if
559 * the peer wants.
560 */
561 NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
562 if (cilen == CILEN_VJ) {
563 GETCHAR(cimaxslotindex, p);
564 GETCHAR(cicflag, p);
565 if (cishort == IPCP_VJ_COMP) {
566 try.old_vj = 0;
567 if (cimaxslotindex < go->maxslotindex)
568 try.maxslotindex = cimaxslotindex;
569 if (!cicflag)
570 try.cflag = 0;
571 } else {
572 try.neg_vj = 0;
573 }
574 } else {
575 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
576 try.old_vj = 1;
577 try.vj_protocol = cishort;
578 } else {
579 try.neg_vj = 0;
580 }
581 }
582 );
583
584 /*
585 * There may be remaining CIs, if the peer is requesting negotiation
586 * on an option that we didn't include in our request packet.
587 * If they want to negotiate about IP addresses, we comply.
588 * If they want us to ask for compression, we refuse.
589 */
590 while (len > CILEN_VOID) {
591 GETCHAR(citype, p);
592 GETCHAR(cilen, p);
593 if( (len -= cilen) < 0 )
594 goto bad;
595 next = p + cilen - 2;
596
597 switch (citype) {
598 case CI_COMPRESSTYPE:
599 if (go->neg_vj || no.neg_vj ||
600 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
601 goto bad;
602 no.neg_vj = 1;
603 break;
604 case CI_ADDRS:
605 if ((go->neg_addr && go->old_addrs) || no.old_addrs
606 || cilen != CILEN_ADDRS)
607 goto bad;
608 try.neg_addr = 1;
609 try.old_addrs = 1;
610 GETLONG(l, p);
611 ciaddr1 = htonl(l);
612 if (ciaddr1 && go->accept_local)
613 try.ouraddr = ciaddr1;
614 GETLONG(l, p);
615 ciaddr2 = htonl(l);
616 if (ciaddr2 && go->accept_remote)
617 try.hisaddr = ciaddr2;
618 no.old_addrs = 1;
619 break;
620 case CI_ADDR:
621 if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
622 goto bad;
623 try.old_addrs = 0;
624 GETLONG(l, p);
625 ciaddr1 = htonl(l);
626 if (ciaddr1 && go->accept_local)
627 try.ouraddr = ciaddr1;
628 if (try.ouraddr != 0)
629 try.neg_addr = 1;
630 no.neg_addr = 1;
631 break;
632 }
633 p = next;
634 }
635
636 /* If there is still anything left, this packet is bad. */
637 if (len != 0)
638 goto bad;
639
640 /*
641 * OK, the Nak is good. Now we can update state.
642 */
643 if (f->state != OPENED)
644 *go = try;
645
646 return 1;
647
648 bad:
649 IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!"));
650 return 0;
651 }
652
653
654 /*
655 * ipcp_rejci - Reject some of our CIs.
656 */
657 static int
ipcp_rejci(fsm * f,u_char * p,int len)658 ipcp_rejci(fsm *f, u_char *p, int len)
659 {
660 ipcp_options *go = &ipcp_gotoptions[f->unit];
661 u_char cimaxslotindex, ciflag, cilen;
662 u_short cishort;
663 u_int32_t cilong;
664 ipcp_options try; /* options to request next time */
665
666 try = *go;
667 /*
668 * Any Rejected CIs must be in exactly the same order that we sent.
669 * Check packet length and CI length at each step.
670 * If we find any deviations, then this packet is bad.
671 */
672 #define REJCIADDR(opt, neg, old, val1, val2) \
673 if (go->neg && \
674 len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
675 p[1] == cilen && \
676 p[0] == opt) { \
677 u_int32_t l; \
678 len -= cilen; \
679 INCPTR(2, p); \
680 GETLONG(l, p); \
681 cilong = htonl(l); \
682 /* Check rejected value. */ \
683 if (cilong != val1) \
684 goto bad; \
685 if (old) { \
686 GETLONG(l, p); \
687 cilong = htonl(l); \
688 /* Check rejected value. */ \
689 if (cilong != val2) \
690 goto bad; \
691 } \
692 try.neg = 0; \
693 }
694
695 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
696 if (go->neg && \
697 p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
698 len >= p[1] && \
699 p[0] == opt) { \
700 len -= p[1]; \
701 INCPTR(2, p); \
702 GETSHORT(cishort, p); \
703 /* Check rejected value. */ \
704 if (cishort != val) \
705 goto bad; \
706 if (!old) { \
707 GETCHAR(cimaxslotindex, p); \
708 if (cimaxslotindex != maxslot) \
709 goto bad; \
710 GETCHAR(ciflag, p); \
711 if (ciflag != cflag) \
712 goto bad; \
713 } \
714 try.neg = 0; \
715 }
716
717 REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,
718 go->old_addrs, go->ouraddr, go->hisaddr);
719
720 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
721 go->maxslotindex, go->cflag);
722
723 /*
724 * If there are any remaining CIs, then this packet is bad.
725 */
726 if (len != 0)
727 goto bad;
728 /*
729 * Now we can update state.
730 */
731 if (f->state != OPENED)
732 *go = try;
733 return 1;
734
735 bad:
736 IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!"));
737 return 0;
738 }
739
740
741 /*
742 * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
743 *
744 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
745 * appropriately. If reject_if_disagree is non-zero, doesn't return
746 * CONFNAK; returns CONFREJ if it can't return CONFACK.
747 */
748 static int
ipcp_reqci(fsm * f,u_char * inp,int * len,int reject_if_disagree)749 ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree)
750 {
751 ipcp_options *wo = &ipcp_wantoptions[f->unit];
752 ipcp_options *ho = &ipcp_hisoptions[f->unit];
753 ipcp_options *ao = &ipcp_allowoptions[f->unit];
754 ipcp_options *go = &ipcp_gotoptions[f->unit];
755 u_char *cip, *next; /* Pointer to current and next CIs */
756 u_short cilen, citype; /* Parsed len, type */
757 u_short cishort; /* Parsed short value */
758 u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */
759 int rc = CONFACK; /* Final packet return code */
760 int orc; /* Individual option return code */
761 u_char *p; /* Pointer to next char to parse */
762 u_char *ucp = inp; /* Pointer to current output char */
763 int l = *len; /* Length left */
764 u_char maxslotindex, cflag;
765 int d;
766
767 cis_received[f->unit] = 1;
768
769 /*
770 * Reset all his options.
771 */
772 BZERO(ho, sizeof(*ho));
773
774 /*
775 * Process all his options.
776 */
777 next = inp;
778 while (l) {
779 orc = CONFACK; /* Assume success */
780 cip = p = next; /* Remember beginning of CI */
781 if (l < 2 || /* Not enough data for CI header or */
782 p[1] < 2 || /* CI length too small or */
783 p[1] > l) { /* CI length too big? */
784 IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!"));
785 orc = CONFREJ; /* Reject bad CI */
786 cilen = l; /* Reject till end of packet */
787 l = 0; /* Don't loop again */
788 goto endswitch;
789 }
790 GETCHAR(citype, p); /* Parse CI type */
791 GETCHAR(cilen, p); /* Parse CI length */
792 l -= cilen; /* Adjust remaining length */
793 next += cilen; /* Step to next CI */
794
795 switch (citype) { /* Check CI type */
796 case CI_ADDRS:
797 IPCPDEBUG((LOG_INFO, "ipcp: received ADDRS "));
798 if (!ao->neg_addr ||
799 cilen != CILEN_ADDRS) { /* Check CI length */
800 orc = CONFREJ; /* Reject CI */
801 break;
802 }
803
804 /*
805 * If he has no address, or if we both have his address but
806 * disagree about it, then NAK it with our idea.
807 * In particular, if we don't know his address, but he does,
808 * then accept it.
809 */
810 GETLONG(tl, p); /* Parse source address (his) */
811 ciaddr1 = htonl(tl);
812 IPCPDEBUG((LOG_INFO, "(%s:", ip_ntoa(ciaddr1)));
813 if (ciaddr1 != wo->hisaddr
814 && (ciaddr1 == 0 || !wo->accept_remote)) {
815 orc = CONFNAK;
816 if (!reject_if_disagree) {
817 DECPTR(sizeof(u_int32_t), p);
818 tl = ntohl(wo->hisaddr);
819 PUTLONG(tl, p);
820 }
821 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
822 /*
823 * If neither we nor he knows his address, reject the option.
824 */
825 orc = CONFREJ;
826 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
827 break;
828 }
829
830 /*
831 * If he doesn't know our address, or if we both have our address
832 * but disagree about it, then NAK it with our idea.
833 */
834 GETLONG(tl, p); /* Parse destination address (ours) */
835 ciaddr2 = htonl(tl);
836 IPCPDEBUG((LOG_INFO, "%s)", ip_ntoa(ciaddr2)));
837 if (ciaddr2 != wo->ouraddr) {
838 if (ciaddr2 == 0 || !wo->accept_local) {
839 orc = CONFNAK;
840 if (!reject_if_disagree) {
841 DECPTR(sizeof(u_int32_t), p);
842 tl = ntohl(wo->ouraddr);
843 PUTLONG(tl, p);
844 }
845 } else {
846 go->ouraddr = ciaddr2; /* accept peer's idea */
847 }
848 }
849
850 ho->neg_addr = 1;
851 ho->old_addrs = 1;
852 ho->hisaddr = ciaddr1;
853 ho->ouraddr = ciaddr2;
854 break;
855
856 case CI_ADDR:
857 IPCPDEBUG((LOG_INFO, "ipcp: received ADDR "));
858
859 if (!ao->neg_addr ||
860 cilen != CILEN_ADDR) { /* Check CI length */
861 orc = CONFREJ; /* Reject CI */
862 break;
863 }
864
865 /*
866 * If he has no address, or if we both have his address but
867 * disagree about it, then NAK it with our idea.
868 * In particular, if we don't know his address, but he does,
869 * then accept it.
870 */
871 GETLONG(tl, p); /* Parse source address (his) */
872 ciaddr1 = htonl(tl);
873 IPCPDEBUG((LOG_INFO, "(%s)", ip_ntoa(ciaddr1)));
874 if (ciaddr1 != wo->hisaddr
875 && (ciaddr1 == 0 || !wo->accept_remote)) {
876 orc = CONFNAK;
877 if (!reject_if_disagree) {
878 DECPTR(sizeof(u_int32_t), p);
879 tl = ntohl(wo->hisaddr);
880 PUTLONG(tl, p);
881 }
882 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
883 /*
884 * Don't ACK an address of 0.0.0.0 - reject it instead.
885 */
886 orc = CONFREJ;
887 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
888 break;
889 }
890
891 ho->neg_addr = 1;
892 ho->hisaddr = ciaddr1;
893 break;
894
895 case CI_MS_DNS1:
896 case CI_MS_DNS2:
897 /* Microsoft primary or secondary DNS request */
898 d = citype == CI_MS_DNS2;
899 IPCPDEBUG((LOG_INFO, "ipcp: received DNS%d Request ", d+1));
900
901 /* If we do not have a DNS address then we cannot send it */
902 if (ao->dnsaddr[d] == 0 ||
903 cilen != CILEN_ADDR) { /* Check CI length */
904 orc = CONFREJ; /* Reject CI */
905 break;
906 }
907 GETLONG(tl, p);
908 if (htonl(tl) != ao->dnsaddr[d]) {
909 DECPTR(sizeof(u_int32_t), p);
910 tl = ntohl(ao->dnsaddr[d]);
911 PUTLONG(tl, p);
912 orc = CONFNAK;
913 }
914 break;
915
916 case CI_MS_WINS1:
917 case CI_MS_WINS2:
918 /* Microsoft primary or secondary WINS request */
919 d = citype == CI_MS_WINS2;
920 IPCPDEBUG((LOG_INFO, "ipcp: received WINS%d Request ", d+1));
921
922 /* If we do not have a DNS address then we cannot send it */
923 if (ao->winsaddr[d] == 0 ||
924 cilen != CILEN_ADDR) { /* Check CI length */
925 orc = CONFREJ; /* Reject CI */
926 break;
927 }
928 GETLONG(tl, p);
929 if (htonl(tl) != ao->winsaddr[d]) {
930 DECPTR(sizeof(u_int32_t), p);
931 tl = ntohl(ao->winsaddr[d]);
932 PUTLONG(tl, p);
933 orc = CONFNAK;
934 }
935 break;
936
937 case CI_COMPRESSTYPE:
938 IPCPDEBUG((LOG_INFO, "ipcp: received COMPRESSTYPE "));
939 if (!ao->neg_vj ||
940 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
941 orc = CONFREJ;
942 break;
943 }
944 GETSHORT(cishort, p);
945 IPCPDEBUG((LOG_INFO, "(%d)", cishort));
946
947 if (!(cishort == IPCP_VJ_COMP ||
948 (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
949 orc = CONFREJ;
950 break;
951 }
952
953 ho->neg_vj = 1;
954 ho->vj_protocol = cishort;
955 if (cilen == CILEN_VJ) {
956 GETCHAR(maxslotindex, p);
957 if (maxslotindex > ao->maxslotindex) {
958 orc = CONFNAK;
959 if (!reject_if_disagree){
960 DECPTR(1, p);
961 PUTCHAR(ao->maxslotindex, p);
962 }
963 }
964 GETCHAR(cflag, p);
965 if (cflag && !ao->cflag) {
966 orc = CONFNAK;
967 if (!reject_if_disagree){
968 DECPTR(1, p);
969 PUTCHAR(wo->cflag, p);
970 }
971 }
972 ho->maxslotindex = maxslotindex;
973 ho->cflag = cflag;
974 } else {
975 ho->old_vj = 1;
976 ho->maxslotindex = MAX_STATES - 1;
977 ho->cflag = 1;
978 }
979 break;
980
981 default:
982 orc = CONFREJ;
983 break;
984 }
985
986 endswitch:
987 IPCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc)));
988
989 if (orc == CONFACK && /* Good CI */
990 rc != CONFACK) /* but prior CI wasnt? */
991 continue; /* Don't send this one */
992
993 if (orc == CONFNAK) { /* Nak this CI? */
994 if (reject_if_disagree) /* Getting fed up with sending NAKs? */
995 orc = CONFREJ; /* Get tough if so */
996 else {
997 if (rc == CONFREJ) /* Rejecting prior CI? */
998 continue; /* Don't send this one */
999 if (rc == CONFACK) { /* Ack'd all prior CIs? */
1000 rc = CONFNAK; /* Not anymore... */
1001 ucp = inp; /* Backup */
1002 }
1003 }
1004 }
1005
1006 if (orc == CONFREJ && /* Reject this CI */
1007 rc != CONFREJ) { /* but no prior ones? */
1008 rc = CONFREJ;
1009 ucp = inp; /* Backup */
1010 }
1011
1012 /* Need to move CI? */
1013 if (ucp != cip)
1014 BCOPY(cip, ucp, cilen); /* Move it */
1015
1016 /* Update output pointer */
1017 INCPTR(cilen, ucp);
1018 }
1019
1020 /*
1021 * If we aren't rejecting this packet, and we want to negotiate
1022 * their address, and they didn't send their address, then we
1023 * send a NAK with a CI_ADDR option appended. We assume the
1024 * input buffer is long enough that we can append the extra
1025 * option safely.
1026 */
1027 if (rc != CONFREJ && !ho->neg_addr &&
1028 wo->req_addr && !reject_if_disagree) {
1029 if (rc == CONFACK) {
1030 rc = CONFNAK;
1031 ucp = inp; /* reset pointer */
1032 wo->req_addr = 0; /* don't ask again */
1033 }
1034 PUTCHAR(CI_ADDR, ucp);
1035 PUTCHAR(CILEN_ADDR, ucp);
1036 tl = ntohl(wo->hisaddr);
1037 PUTLONG(tl, ucp);
1038 }
1039
1040 *len = ucp - inp; /* Compute output length */
1041 IPCPDEBUG((LOG_INFO, "ipcp: returning Configure-%s", CODENAME(rc)));
1042 return (rc); /* Return final code */
1043 }
1044
1045
1046 /*
1047 * ip_check_options - check that any IP-related options are OK,
1048 * and assign appropriate defaults.
1049 */
1050 static void
ip_check_options(void)1051 ip_check_options(void)
1052 {
1053 struct hostent *hp;
1054 u_int32_t local;
1055 ipcp_options *wo = &ipcp_wantoptions[0];
1056
1057 /*
1058 * Default our local IP address based on our hostname.
1059 * If local IP address already given, don't bother.
1060 */
1061 if (wo->ouraddr == 0 && !disable_defaultip) {
1062 /*
1063 * Look up our hostname (possibly with domain name appended)
1064 * and take the first IP address as our local IP address.
1065 * If there isn't an IP address for our hostname, too bad.
1066 */
1067 wo->accept_local = 1; /* don't insist on this default value */
1068 if ((hp = gethostbyname(hostname)) != NULL) {
1069 local = *(u_int32_t *)hp->h_addr;
1070 if (local != 0 && !bad_ip_adrs(local))
1071 wo->ouraddr = local;
1072 }
1073 }
1074
1075 if (demand && wo->hisaddr == 0) {
1076 option_error("remote IP address required for demand-dialling\n");
1077 exit(1);
1078 }
1079 #if 0
1080 if (demand && wo->accept_remote) {
1081 option_error("ipcp-accept-remote is incompatible with demand\n");
1082 exit(1);
1083 }
1084 #endif
1085 }
1086
1087
1088 /*
1089 * ip_demand_conf - configure the interface as though
1090 * IPCP were up, for use with dial-on-demand.
1091 */
1092 static int
ip_demand_conf(int u)1093 ip_demand_conf(int u)
1094 {
1095 ipcp_options *wo = &ipcp_wantoptions[u];
1096
1097 if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
1098 return 0;
1099 if (!sifup(u))
1100 return 0;
1101 if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
1102 return 0;
1103 if (wo->default_route)
1104 if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
1105 default_route_set[u] = 1;
1106 if (wo->proxy_arp)
1107 if (sifproxyarp(u, wo->hisaddr))
1108 proxy_arp_set[u] = 1;
1109
1110 syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(wo->ouraddr));
1111 syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(wo->hisaddr));
1112
1113 return 1;
1114 }
1115
1116
1117 /*
1118 * ipcp_up - IPCP has come UP.
1119 *
1120 * Configure the IP network interface appropriately and bring it up.
1121 */
1122 static void
ipcp_up(fsm * f)1123 ipcp_up(fsm *f)
1124 {
1125 u_int32_t mask;
1126 ipcp_options *ho = &ipcp_hisoptions[f->unit];
1127 ipcp_options *go = &ipcp_gotoptions[f->unit];
1128 ipcp_options *wo = &ipcp_wantoptions[f->unit];
1129
1130 np_up(f->unit, PPP_IP);
1131 IPCPDEBUG((LOG_INFO, "ipcp: up"));
1132
1133 /*
1134 * We must have a non-zero IP address for both ends of the link.
1135 */
1136 if (!ho->neg_addr)
1137 ho->hisaddr = wo->hisaddr;
1138
1139 if (ho->hisaddr == 0) {
1140 syslog(LOG_ERR, "Could not determine remote IP address");
1141 ipcp_close(f->unit, "Could not determine remote IP address");
1142 return;
1143 }
1144 if (go->ouraddr == 0) {
1145 syslog(LOG_ERR, "Could not determine local IP address");
1146 ipcp_close(f->unit, "Could not determine local IP address");
1147 return;
1148 }
1149 script_setenv("IPLOCAL", ip_ntoa(go->ouraddr));
1150 script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr));
1151
1152 /*
1153 * Check that the peer is allowed to use the IP address it wants.
1154 */
1155 if (!auth_ip_addr(f->unit, ho->hisaddr)) {
1156 syslog(LOG_ERR, "Peer is not authorized to use remote address %s",
1157 ip_ntoa(ho->hisaddr));
1158 ipcp_close(f->unit, "Unauthorized remote IP address");
1159 return;
1160 }
1161
1162 /* set tcp compression */
1163 sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
1164
1165 /*
1166 * If we are doing dial-on-demand, the interface is already
1167 * configured, so we put out any saved-up packets, then set the
1168 * interface to pass IP packets.
1169 */
1170 if (demand) {
1171 if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
1172 if (go->ouraddr != wo->ouraddr)
1173 syslog(LOG_WARNING, "Local IP address changed to %s",
1174 ip_ntoa(go->ouraddr));
1175 if (ho->hisaddr != wo->hisaddr)
1176 syslog(LOG_WARNING, "Remote IP address changed to %s",
1177 ip_ntoa(ho->hisaddr));
1178 ipcp_clear_addrs(f->unit);
1179
1180 /* Set the interface to the new addresses */
1181 mask = GetMask(go->ouraddr);
1182 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1183 IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
1184 ipcp_close(f->unit, "Interface configuration failed");
1185 return;
1186 }
1187
1188 /* assign a default route through the interface if required */
1189 if (ipcp_wantoptions[f->unit].default_route)
1190 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1191 default_route_set[f->unit] = 1;
1192
1193 /* Make a proxy ARP entry if requested. */
1194 if (ipcp_wantoptions[f->unit].proxy_arp)
1195 if (sifproxyarp(f->unit, ho->hisaddr))
1196 proxy_arp_set[f->unit] = 1;
1197
1198 }
1199 demand_rexmit(PPP_IP);
1200 sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1201
1202 } else {
1203 /*
1204 * Set IP addresses and (if specified) netmask.
1205 */
1206 mask = GetMask(go->ouraddr);
1207
1208 #if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
1209 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1210 IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
1211 ipcp_close(f->unit, "Interface configuration failed");
1212 return;
1213 }
1214 #endif
1215
1216 /* bring the interface up for IP */
1217 if (!sifup(f->unit)) {
1218 IPCPDEBUG((LOG_WARNING, "sifup failed"));
1219 ipcp_close(f->unit, "Interface configuration failed");
1220 return;
1221 }
1222
1223 #if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
1224 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1225 IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
1226 ipcp_close(f->unit, "Interface configuration failed");
1227 return;
1228 }
1229 #endif
1230 sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1231
1232 /* assign a default route through the interface if required */
1233 if (ipcp_wantoptions[f->unit].default_route)
1234 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1235 default_route_set[f->unit] = 1;
1236
1237 /* Make a proxy ARP entry if requested. */
1238 if (ipcp_wantoptions[f->unit].proxy_arp)
1239 if (sifproxyarp(f->unit, ho->hisaddr))
1240 proxy_arp_set[f->unit] = 1;
1241
1242 syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(go->ouraddr));
1243 syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(ho->hisaddr));
1244 }
1245
1246 /*
1247 * Execute the ip-up script, like this:
1248 * /etc/ppp/ip-up interface tty speed local-IP remote-IP
1249 */
1250 ipcp_script(f, _PATH_IPUP);
1251
1252 }
1253
1254
1255 /*
1256 * ipcp_down - IPCP has gone DOWN.
1257 *
1258 * Take the IP network interface down, clear its addresses
1259 * and delete routes through it.
1260 */
1261 static void
ipcp_down(fsm * f)1262 ipcp_down(fsm *f)
1263 {
1264 IPCPDEBUG((LOG_INFO, "ipcp: down"));
1265 np_down(f->unit, PPP_IP);
1266 sifvjcomp(f->unit, 0, 0, 0);
1267
1268 /*
1269 * If we are doing dial-on-demand, set the interface
1270 * to queue up outgoing packets (for now).
1271 */
1272 if (demand) {
1273 sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
1274 } else {
1275 sifdown(f->unit);
1276 ipcp_clear_addrs(f->unit);
1277 }
1278
1279 /* Execute the ip-down script */
1280 ipcp_script(f, _PATH_IPDOWN);
1281 }
1282
1283
1284 /*
1285 * ipcp_clear_addrs() - clear the interface addresses, routes,
1286 * proxy arp entries, etc.
1287 */
1288 static void
ipcp_clear_addrs(int unit)1289 ipcp_clear_addrs(int unit)
1290 {
1291 u_int32_t ouraddr, hisaddr;
1292
1293 ouraddr = ipcp_gotoptions[unit].ouraddr;
1294 hisaddr = ipcp_hisoptions[unit].hisaddr;
1295 if (proxy_arp_set[unit]) {
1296 cifproxyarp(unit, hisaddr);
1297 proxy_arp_set[unit] = 0;
1298 }
1299 if (default_route_set[unit]) {
1300 cifdefaultroute(unit, ouraddr, hisaddr);
1301 default_route_set[unit] = 0;
1302 }
1303 cifaddr(unit, ouraddr, hisaddr);
1304 }
1305
1306
1307 /*
1308 * ipcp_finished - possibly shut down the lower layers.
1309 */
1310 static void
ipcp_finished(fsm * f)1311 ipcp_finished(fsm *f)
1312 {
1313 np_finished(f->unit, PPP_IP);
1314 }
1315
1316
1317 /*
1318 * ipcp_script - Execute a script with arguments
1319 * interface-name tty-name speed local-IP remote-IP.
1320 */
1321 static void
ipcp_script(fsm * f,char * script)1322 ipcp_script(fsm *f, char *script)
1323 {
1324 char strspeed[32], strlocal[32], strremote[32];
1325 char *argv[8];
1326
1327 snprintf(strspeed, sizeof strspeed, "%d", baud_rate);
1328 strlcpy(strlocal, ip_ntoa(ipcp_gotoptions[f->unit].ouraddr),
1329 sizeof strlocal);
1330 strlcpy(strremote, ip_ntoa(ipcp_hisoptions[f->unit].hisaddr),
1331 sizeof strremote);
1332
1333 argv[0] = script;
1334 argv[1] = ifname;
1335 argv[2] = devnam;
1336 argv[3] = strspeed;
1337 argv[4] = strlocal;
1338 argv[5] = strremote;
1339 argv[6] = ipparam;
1340 argv[7] = NULL;
1341 run_program(script, argv, 0);
1342 }
1343
1344 /*
1345 * ipcp_printpkt - print the contents of an IPCP packet.
1346 */
1347 static char *ipcp_codenames[] = {
1348 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1349 "TermReq", "TermAck", "CodeRej"
1350 };
1351
1352 static int
ipcp_printpkt(u_char * p,int plen,void (* printer)(void *,char *,...),void * arg)1353 ipcp_printpkt(u_char *p, int plen, void (*printer)(void *, char *, ...), void *arg)
1354 {
1355 int code, id, len, olen;
1356 u_char *pstart, *optend;
1357 u_short cishort;
1358 u_int32_t cilong;
1359
1360 if (plen < HEADERLEN)
1361 return 0;
1362 pstart = p;
1363 GETCHAR(code, p);
1364 GETCHAR(id, p);
1365 GETSHORT(len, p);
1366 if (len < HEADERLEN || len > plen)
1367 return 0;
1368
1369 if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))
1370 printer(arg, " %s", ipcp_codenames[code-1]);
1371 else
1372 printer(arg, " code=0x%x", code);
1373 printer(arg, " id=0x%x", id);
1374 len -= HEADERLEN;
1375 switch (code) {
1376 case CONFREQ:
1377 case CONFACK:
1378 case CONFNAK:
1379 case CONFREJ:
1380 /* print option list */
1381 while (len >= 2) {
1382 GETCHAR(code, p);
1383 GETCHAR(olen, p);
1384 p -= 2;
1385 if (olen < 2 || olen > len) {
1386 break;
1387 }
1388 printer(arg, " <");
1389 len -= olen;
1390 optend = p + olen;
1391 switch (code) {
1392 case CI_ADDRS:
1393 if (olen == CILEN_ADDRS) {
1394 p += 2;
1395 GETLONG(cilong, p);
1396 printer(arg, "addrs %I", htonl(cilong));
1397 GETLONG(cilong, p);
1398 printer(arg, " %I", htonl(cilong));
1399 }
1400 break;
1401 case CI_COMPRESSTYPE:
1402 if (olen >= CILEN_COMPRESS) {
1403 p += 2;
1404 GETSHORT(cishort, p);
1405 printer(arg, "compress ");
1406 switch (cishort) {
1407 case IPCP_VJ_COMP:
1408 printer(arg, "VJ");
1409 break;
1410 case IPCP_VJ_COMP_OLD:
1411 printer(arg, "old-VJ");
1412 break;
1413 default:
1414 printer(arg, "0x%x", cishort);
1415 }
1416 }
1417 break;
1418 case CI_ADDR:
1419 if (olen == CILEN_ADDR) {
1420 p += 2;
1421 GETLONG(cilong, p);
1422 printer(arg, "addr %I", htonl(cilong));
1423 }
1424 break;
1425 case CI_MS_DNS1:
1426 case CI_MS_DNS2:
1427 p += 2;
1428 GETLONG(cilong, p);
1429 printer(arg, "ms-dns %I", htonl(cilong));
1430 break;
1431 case CI_MS_WINS1:
1432 case CI_MS_WINS2:
1433 p += 2;
1434 GETLONG(cilong, p);
1435 printer(arg, "ms-wins %I", htonl(cilong));
1436 break;
1437 }
1438 while (p < optend) {
1439 GETCHAR(code, p);
1440 printer(arg, " %.2x", code);
1441 }
1442 printer(arg, ">");
1443 }
1444 break;
1445
1446 case TERMACK:
1447 case TERMREQ:
1448 if (len > 0 && *p >= ' ' && *p < 0x7f) {
1449 printer(arg, " ");
1450 print_string(p, len, printer, arg);
1451 p += len;
1452 len = 0;
1453 }
1454 break;
1455 }
1456
1457 /* print the rest of the bytes in the packet */
1458 for (; len > 0; --len) {
1459 GETCHAR(code, p);
1460 printer(arg, " %.2x", code);
1461 }
1462
1463 return p - pstart;
1464 }
1465
1466 /*
1467 * ip_active_pkt - see if this IP packet is worth bringing the link up for.
1468 * We don't bring the link up for IP fragments or for TCP FIN packets
1469 * with no data.
1470 */
1471 #define IP_HDRLEN 20 /* bytes */
1472 #define IP_OFFMASK 0x1fff
1473 #define IPPROTO_TCP 6
1474 #define TCP_HDRLEN 20
1475 #define TH_FIN 0x01
1476
1477 /*
1478 * We use these macros because the IP header may be at an odd address,
1479 * and some compilers might use word loads to get th_off or ip_hl.
1480 */
1481
1482 #define net_short(x) (((x)[0] << 8) + (x)[1])
1483 #define get_iphl(x) (((unsigned char *)(x))[0] & 0xF)
1484 #define get_ipoff(x) net_short((unsigned char *)(x) + 6)
1485 #define get_ipproto(x) (((unsigned char *)(x))[9])
1486 #define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4)
1487 #define get_tcpflags(x) (((unsigned char *)(x))[13])
1488
1489 static int
ip_active_pkt(u_char * pkt,int len)1490 ip_active_pkt(u_char *pkt, int len)
1491 {
1492 u_char *tcp;
1493 int hlen;
1494
1495 len -= PPP_HDRLEN;
1496 pkt += PPP_HDRLEN;
1497 if (len < IP_HDRLEN)
1498 return 0;
1499 if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
1500 return 0;
1501 if (get_ipproto(pkt) != IPPROTO_TCP)
1502 return 1;
1503 hlen = get_iphl(pkt) * 4;
1504 if (len < hlen + TCP_HDRLEN)
1505 return 0;
1506 tcp = pkt + hlen;
1507 if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
1508 return 0;
1509 return 1;
1510 }
1511