1 /*
2 * ipcp.c - PPP IP Control Protocol.
3 *
4 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5 * Use is subject to license terms.
6 *
7 * Copyright (c) 1989 Carnegie Mellon University.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms are permitted
11 * provided that the above copyright notice and this paragraph are
12 * duplicated in all such forms and that any documentation,
13 * advertising materials, and other materials related to such
14 * distribution and use acknowledge that the software was developed
15 * by Carnegie Mellon University. The name of the
16 * University may not be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 */
22 /*
23 * Copyright (c) 2016 by Delphix. All rights reserved.
24 */
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <netdb.h>
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #if defined(_linux_) || defined(__linux__)
33 #define __FAVOR_BSD
34 #endif
35 #include <netinet/in.h>
36 #include <netinet/tcp.h>
37 #include <arpa/inet.h>
38
39 #include "pppd.h"
40 #include "fsm.h"
41 #include "ipcp.h"
42 #include "pathnames.h"
43
44 /* global vars */
45 ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
46 ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
47 ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
48 ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
49
50 bool ipcp_from_hostname = 0; /* Local IP address is from hostname lookup */
51
52 /* Hook for a plugin to know when IP protocol has come up */
53 void (*ip_up_hook) __P((void)) = NULL;
54
55 /* Hook for a plugin to know when IP protocol has come down */
56 void (*ip_down_hook) __P((void)) = NULL;
57
58 /* local vars */
59 static bool default_route_set[NUM_PPP]; /* Have set up a default route */
60 static bool proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */
61 static bool ipcp_is_up[NUM_PPP]; /* have called np_up() */
62 static bool proxy_arp_quiet[NUM_PPP]; /* We should be quiet on error */
63 static bool disable_defaultip = 0; /* Don't use hostname for IP addr */
64
65 /*
66 * Callbacks for fsm code. (CI = Configuration Information)
67 */
68 static void ipcp_resetci __P((fsm *)); /* Reset our CI */
69 static int ipcp_cilen __P((fsm *)); /* Return length of our CI */
70 static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
71 static int ipcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
72 static int ipcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
73 static int ipcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
74 static int ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
75 static void ipcp_up __P((fsm *)); /* We're UP */
76 static void ipcp_down __P((fsm *)); /* We're DOWN */
77 static void ipcp_finished __P((fsm *)); /* Don't need lower layer */
78 static int setmsservaddr __P((char *, u_int32_t *));
79
80 fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
81
82 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
83 ipcp_resetci, /* Reset our Configuration Information */
84 ipcp_cilen, /* Length of our Configuration Information */
85 ipcp_addci, /* Add our Configuration Information */
86 ipcp_ackci, /* ACK our Configuration Information */
87 ipcp_nakci, /* NAK our Configuration Information */
88 ipcp_rejci, /* Reject our Configuration Information */
89 ipcp_reqci, /* Request peer's Configuration Information */
90 ipcp_up, /* Called when fsm reaches OPENED state */
91 ipcp_down, /* Called when fsm leaves OPENED state */
92 NULL, /* Called when we want the lower layer up */
93 ipcp_finished, /* Called when we want the lower layer down */
94 NULL, /* Retransmission is necessary */
95 NULL, /* Called to handle protocol-specific codes */
96 "IPCP", /* String name of protocol */
97 NULL /* Peer rejected a code number */
98 };
99
100 /*
101 * Command-line options.
102 */
103 static int setvjslots __P((char **));
104 static int setdnsaddr __P((char **));
105 static int setwinsaddr __P((char **));
106 static int autoproxyarp __P((char **));
107
108 static option_t ipcp_option_list[] = {
109 { "noip", o_bool, &ipcp_protent.enabled_flag,
110 "Disable IP and IPCP" },
111 { "-ip", o_bool, &ipcp_protent.enabled_flag,
112 "Disable IP and IPCP" },
113 { "novj", o_bool, &ipcp_wantoptions[0].neg_vj,
114 "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj },
115 { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj,
116 "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj },
117 { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag,
118 "Disable VJ connection-ID compression", OPT_A2COPY,
119 &ipcp_allowoptions[0].cflag },
120 { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag,
121 "Disable VJ connection-ID compression", OPT_A2COPY,
122 &ipcp_allowoptions[0].cflag },
123 { "vj-max-slots", o_special, (void *)setvjslots,
124 "Set maximum VJ header slots" },
125 { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local,
126 "Accept peer's address for us", 1 },
127 { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote,
128 "Accept peer's address for it", 1 },
129 { "ipparam", o_string, &ipparam,
130 "Set ip script parameter" },
131 { "noipdefault", o_bool, &disable_defaultip,
132 "Don't use name for default IP adrs", 1 },
133 { "ms-dns", o_special, (void *)setdnsaddr,
134 "DNS address for the peer's use" },
135 { "ms-wins", o_special, (void *)setwinsaddr,
136 "Nameserver for SMB over TCP/IP for peer" },
137 { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime,
138 "Set timeout for IPCP" },
139 { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits,
140 "Set max #xmits for term-reqs" },
141 { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits,
142 "Set max #xmits for conf-reqs" },
143 { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops,
144 "Set max #conf-naks for IPCP" },
145 { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route,
146 "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route },
147 { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route,
148 "disable defaultroute option", OPT_A2COPY,
149 &ipcp_wantoptions[0].default_route },
150 { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
151 "disable defaultroute option", OPT_A2COPY,
152 &ipcp_wantoptions[0].default_route },
153 { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
154 "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
155 { "autoproxyarp", o_special_noarg, (void *)autoproxyarp,
156 "Add proxy ARP entry if needed", OPT_ENABLE,
157 &ipcp_allowoptions[0].proxy_arp },
158 { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
159 "disable proxyarp option", OPT_A2COPY, &ipcp_wantoptions[0].proxy_arp },
160 { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
161 "disable proxyarp option", OPT_A2COPY, &ipcp_wantoptions[0].proxy_arp },
162 { "usepeerdns", o_bool, &ipcp_wantoptions[0].req_dns1,
163 "Ask peer for DNS address(es)", OPT_A2COPY|1,
164 &ipcp_wantoptions[0].req_dns2 },
165 { NULL }
166 };
167
168 /*
169 * Protocol entry points from main code.
170 */
171 static void ipcp_init __P((int));
172 static void ipcp_open __P((int));
173 static void ipcp_close __P((int, char *));
174 static void ipcp_lowerup __P((int));
175 static void ipcp_lowerdown __P((int));
176 static void ipcp_input __P((int, u_char *, int));
177 static void ipcp_protrej __P((int));
178 static int ipcp_printpkt __P((u_char *, int,
179 void (*) __P((void *, const char *, ...)), void *));
180 static void ip_check_options __P((void));
181 static int ip_demand_conf __P((int));
182 static int ip_active_pkt __P((u_char *, int));
183 static void ipcp_print_stat __P((int, FILE *));
184
185 static void create_resolv __P((u_int32_t, u_int32_t));
186
187 struct protent ipcp_protent = {
188 PPP_IPCP,
189 ipcp_init,
190 ipcp_input,
191 ipcp_protrej,
192 ipcp_lowerup,
193 ipcp_lowerdown,
194 ipcp_open,
195 ipcp_close,
196 ipcp_printpkt,
197 NULL,
198 1,
199 "IPCP",
200 "IP",
201 ipcp_option_list,
202 ip_check_options,
203 ip_demand_conf,
204 ip_active_pkt,
205 ipcp_print_stat
206 };
207
208 static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t));
209 static void ipcp_script __P((char *)); /* Run an up/down script */
210 static void ipcp_script_done __P((void *, int));
211
212 /*
213 * Lengths of configuration options.
214 */
215 #define CILEN_VOID 2
216 #define CILEN_COMPRESS 4 /* min length for compression protocol opt. */
217 #define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */
218 #define CILEN_ADDR 6 /* new-style single address option */
219 #define CILEN_ADDRS 10 /* old-style dual address option */
220
221
222 /*
223 * This state variable is used to ensure that we don't
224 * run an ipcp-up/down script while one is already running.
225 */
226 static enum script_state {
227 s_down,
228 s_up
229 } ipcp_script_state;
230 static pid_t ipcp_script_pid;
231
232 /*
233 * Make a string representation of a network IP address.
234 */
235 char *
ip_ntoa(ipaddr)236 ip_ntoa(ipaddr)
237 u_int32_t ipaddr;
238 {
239 static char b[64];
240
241 (void) slprintf(b, sizeof(b), "%I", ipaddr);
242 return b;
243 }
244
245 /*
246 * Option parsing.
247 */
248
249 /*
250 * setvjslots - set maximum number of connection slots for VJ compression
251 */
252 static int
setvjslots(argv)253 setvjslots(argv)
254 char **argv;
255 {
256 int value;
257
258 if (!int_option(*argv, &value))
259 return 0;
260 if (value < 2 || value > 16) {
261 option_error("vj-max-slots value must be between 2 and 16");
262 return 0;
263 }
264 ipcp_wantoptions [0].maxslotindex =
265 ipcp_allowoptions[0].maxslotindex = value - 1;
266 return 1;
267 }
268
269 /*
270 * setmsservaddr - Set the primary and secondary server addresses in the
271 * array. setdnsaddr() and setwinsaddr() call this function with either
272 * dnsaddr[] or winsaddr[] as the serverarray argument.
273 */
274 static int
setmsservaddr(servname,serverarray)275 setmsservaddr(servname, serverarray)
276 char *servname;
277 u_int32_t *serverarray;
278 {
279 u_int32_t addr;
280 struct hostent *hp = NULL;
281
282 addr = inet_addr(servname);
283 if (addr == (u_int32_t) -1) {
284 if ((hp = gethostbyname(servname)) == NULL)
285 return 0;
286 BCOPY(hp->h_addr, &addr, sizeof (u_int32_t));
287 }
288
289 /*
290 * If there is no primary then this is the first instance of the
291 * option, we must set the primary. In that case, try to set the
292 * secondary to h_addr_list[1]. If the primary is already set, then
293 * this is the second instance of the option, and we must set
294 * the secondary.
295 */
296 if (serverarray[0] == 0) {
297 serverarray[0] = addr;
298 if (hp != NULL && hp->h_addr_list[1] != NULL)
299 BCOPY(hp->h_addr_list[1], &serverarray[1], sizeof (u_int32_t));
300 else
301 serverarray[1] = addr;
302 } else {
303 serverarray[1] = addr;
304 }
305
306 return (1);
307 }
308
309 /*
310 * setdnsaddr - set the dns address(es)
311 */
312 static int
setdnsaddr(argv)313 setdnsaddr(argv)
314 char **argv;
315 {
316 if (setmsservaddr(*argv, &(ipcp_allowoptions[0].dnsaddr[0])) == 0) {
317 option_error("invalid address parameter '%s' for ms-dns option", *argv);
318 return (0);
319 }
320
321 return (1);
322 }
323
324 /*
325 * setwinsaddr - set the wins address(es)
326 * This is primrarly used with the Samba package under UNIX or for pointing
327 * the caller to the existing WINS server on a Windows NT platform.
328 */
329 static int
setwinsaddr(argv)330 setwinsaddr(argv)
331 char **argv;
332 {
333 if (setmsservaddr(*argv, &(ipcp_allowoptions[0].winsaddr[0])) == 0) {
334 option_error("invalid address parameter '%s' for ms-wins option",
335 *argv);
336 return (0);
337 }
338
339 return (1);
340 }
341
342 /*
343 * autoproxyarp -- enable proxy ARP but don't emit error messages if
344 * it's not actually needed.
345 */
346 /*ARGSUSED*/
347 static int
autoproxyarp(argv)348 autoproxyarp(argv)
349 char **argv;
350 {
351 ipcp_wantoptions[0].proxy_arp = 1;
352 proxy_arp_quiet[0] = 1;
353
354 return (1);
355 }
356
357
358 /*
359 * ipcp_init - Initialize IPCP.
360 */
361 static void
ipcp_init(unit)362 ipcp_init(unit)
363 int unit;
364 {
365 fsm *f = &ipcp_fsm[unit];
366 ipcp_options *wo = &ipcp_wantoptions[unit];
367 ipcp_options *ao = &ipcp_allowoptions[unit];
368
369 f->unit = unit;
370 f->protocol = PPP_IPCP;
371 f->callbacks = &ipcp_callbacks;
372 fsm_init(&ipcp_fsm[unit]);
373
374 BZERO(wo, sizeof(*wo));
375 BZERO(ao, sizeof(*ao));
376
377 wo->neg_addr = wo->old_addrs = 1;
378 wo->neg_vj = 1;
379 wo->vj_protocol = IPCP_VJ_COMP;
380 wo->maxslotindex = MAX_STATES - 1; /* really max index */
381 wo->cflag = 1;
382
383 ao->neg_addr = ao->old_addrs = 1;
384 ao->neg_vj = 1;
385 ao->maxslotindex = MAX_STATES - 1;
386 ao->cflag = 1;
387
388 /*
389 * These aren't actually negotiated. Instead, they control
390 * whether the user may use the proxyarp and defaultroute options.
391 */
392 ao->proxy_arp = 1;
393 ao->default_route = 1;
394 proxy_arp_quiet[unit] = 0;
395 }
396
397
398 /*
399 * ipcp_open - IPCP is allowed to come up.
400 */
401 static void
ipcp_open(unit)402 ipcp_open(unit)
403 int unit;
404 {
405 fsm_open(&ipcp_fsm[unit]);
406 }
407
408
409 /*
410 * ipcp_close - Take IPCP down.
411 */
412 static void
ipcp_close(unit,reason)413 ipcp_close(unit, reason)
414 int unit;
415 char *reason;
416 {
417 fsm_close(&ipcp_fsm[unit], reason);
418 }
419
420
421 /*
422 * ipcp_lowerup - The lower layer is up.
423 */
424 static void
ipcp_lowerup(unit)425 ipcp_lowerup(unit)
426 int unit;
427 {
428 fsm_lowerup(&ipcp_fsm[unit]);
429 }
430
431
432 /*
433 * ipcp_lowerdown - The lower layer is down.
434 */
435 static void
ipcp_lowerdown(unit)436 ipcp_lowerdown(unit)
437 int unit;
438 {
439 fsm_lowerdown(&ipcp_fsm[unit]);
440 }
441
442
443 /*
444 * ipcp_input - Input IPCP packet.
445 */
446 static void
ipcp_input(unit,p,len)447 ipcp_input(unit, p, len)
448 int unit;
449 u_char *p;
450 int len;
451 {
452 fsm_input(&ipcp_fsm[unit], p, len);
453 }
454
455
456 /*
457 * ipcp_protrej - A Protocol-Reject was received for IPCP.
458 */
459 static void
ipcp_protrej(unit)460 ipcp_protrej(unit)
461 int unit;
462 {
463 fsm_protreject(&ipcp_fsm[unit]);
464 }
465
466
467 /*
468 * ipcp_resetci - Reset our CI.
469 * Called by fsm_sconfreq, Send Configure Request.
470 */
471 static void
ipcp_resetci(f)472 ipcp_resetci(f)
473 fsm *f;
474 {
475 ipcp_options *wo = &ipcp_wantoptions[f->unit];
476 ipcp_options *go = &ipcp_gotoptions[f->unit];
477 ipcp_options *ao = &ipcp_allowoptions[f->unit];
478
479 wo->req_addr = (wo->neg_addr || wo->old_addrs) &&
480 (ao->neg_addr || ao->old_addrs);
481 if (wo->ouraddr == 0 || disable_defaultip)
482 wo->accept_local = 1;
483 if (wo->hisaddr == 0)
484 wo->accept_remote = 1;
485 *go = *wo;
486 if (disable_defaultip)
487 go->ouraddr = 0;
488 }
489
490
491 /*
492 * ipcp_cilen - Return length of our CI.
493 * Called by fsm_sconfreq, Send Configure Request.
494 */
495 static int
ipcp_cilen(f)496 ipcp_cilen(f)
497 fsm *f;
498 {
499 ipcp_options *go = &ipcp_gotoptions[f->unit];
500 ipcp_options *wo = &ipcp_wantoptions[f->unit];
501 ipcp_options *ho = &ipcp_hisoptions[f->unit];
502
503 #define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0)
504 #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
505 #define LENCIADDR(neg) (neg ? (CILEN_ADDR) : 0)
506
507 /*
508 * First see if we want to change our options to the old
509 * forms because we have received old forms from the peer.
510 */
511 if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs)
512 /* use the old style of address negotiation */
513 go->neg_addr = 0;
514 if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
515 /* try an older style of VJ negotiation */
516 /* use the old style only if the peer did */
517 if (ho->neg_vj && ho->old_vj) {
518 go->neg_vj = 1;
519 go->old_vj = 1;
520 go->vj_protocol = ho->vj_protocol;
521 }
522 }
523
524 return (LENCIADDRS(!go->neg_addr && go->old_addrs) +
525 LENCIVJ(go->neg_vj, go->old_vj) +
526 LENCIADDR(go->neg_addr) +
527 LENCIADDR(go->req_dns1) +
528 LENCIADDR(go->req_dns2)) ;
529 }
530
531
532 /*
533 * ipcp_addci - Add our desired CIs to a packet.
534 * Called by fsm_sconfreq, Send Configure Request.
535 */
536 static void
ipcp_addci(f,ucp,lenp)537 ipcp_addci(f, ucp, lenp)
538 fsm *f;
539 u_char *ucp;
540 int *lenp;
541 {
542 ipcp_options *go = &ipcp_gotoptions[f->unit];
543 int len = *lenp;
544
545 #define ADDCIADDRS(opt, neg, val1, val2) \
546 if (neg) { \
547 if (len >= CILEN_ADDRS) { \
548 PUTCHAR(opt, ucp); \
549 PUTCHAR(CILEN_ADDRS, ucp); \
550 PUTNLONG(val1, ucp); \
551 PUTNLONG(val2, ucp); \
552 len -= CILEN_ADDRS; \
553 } else \
554 go->old_addrs = 0; \
555 }
556
557 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
558 if (neg) { \
559 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
560 if (len >= vjlen) { \
561 PUTCHAR(opt, ucp); \
562 PUTCHAR(vjlen, ucp); \
563 PUTSHORT(val, ucp); \
564 if (!old) { \
565 PUTCHAR(maxslotindex, ucp); \
566 PUTCHAR(cflag, ucp); \
567 } \
568 len -= vjlen; \
569 } else \
570 neg = 0; \
571 }
572
573 #define ADDCIADDR(opt, neg, val) \
574 if (neg) { \
575 if (len >= CILEN_ADDR) { \
576 PUTCHAR(opt, ucp); \
577 PUTCHAR(CILEN_ADDR, ucp); \
578 PUTNLONG(val, ucp); \
579 len -= CILEN_ADDR; \
580 } else \
581 neg = 0; \
582 }
583
584 ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
585 go->hisaddr);
586
587 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
588 go->maxslotindex, go->cflag);
589
590 ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr);
591
592 ADDCIADDR(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
593
594 ADDCIADDR(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
595
596 *lenp -= len;
597 }
598
599
600 /*
601 * ipcp_ackci - Ack our CIs.
602 * Called by fsm_rconfack, Receive Configure ACK.
603 *
604 * Returns:
605 * 0 - Ack was bad.
606 * 1 - Ack was good.
607 */
608 static int
ipcp_ackci(f,p,len)609 ipcp_ackci(f, p, len)
610 fsm *f;
611 u_char *p;
612 int len;
613 {
614 ipcp_options *go = &ipcp_gotoptions[f->unit];
615 u_short cilen, citype, cishort;
616 u_int32_t cilong;
617 u_char cimaxslotindex, cicflag;
618
619 /*
620 * CIs must be in exactly the same order that we sent...
621 * Check packet length and CI length at each step.
622 * If we find any deviations, then this packet is bad.
623 */
624
625 #define ACKCHECK(opt, olen) \
626 if ((len -= olen) < 0) \
627 goto bad; \
628 GETCHAR(citype, p); \
629 GETCHAR(cilen, p); \
630 if (cilen != olen || \
631 citype != opt) \
632 goto bad;
633
634 #define ACKCIADDRS(opt, neg, val1, val2) \
635 if (neg) { \
636 ACKCHECK(opt, CILEN_ADDRS) \
637 GETNLONG(cilong, p); \
638 if (val1 != cilong) \
639 goto bad; \
640 GETNLONG(cilong, p); \
641 if (val2 != cilong) \
642 goto bad; \
643 }
644
645 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
646 if (neg) { \
647 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
648 ACKCHECK(opt, vjlen) \
649 GETSHORT(cishort, p); \
650 if (cishort != val) \
651 goto bad; \
652 if (!old) { \
653 GETCHAR(cimaxslotindex, p); \
654 if (cimaxslotindex != maxslotindex) \
655 goto bad; \
656 GETCHAR(cicflag, p); \
657 if (cicflag != cflag) \
658 goto bad; \
659 } \
660 }
661
662 #define ACKCIADDR(opt, neg, val) \
663 if (neg) { \
664 ACKCHECK(opt, CILEN_ADDR) \
665 GETNLONG(cilong, p); \
666 if (val != cilong) \
667 goto bad; \
668 }
669
670 ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
671 go->hisaddr);
672
673 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
674 go->maxslotindex, go->cflag);
675
676 ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr);
677
678 ACKCIADDR(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
679
680 ACKCIADDR(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
681
682 /*
683 * If there are any remaining CIs, then this packet is bad.
684 */
685 if (len != 0)
686 goto bad;
687 return (1);
688
689 bad:
690 IPCPDEBUG(("ipcp_ackci: received bad Ack!"));
691 return (0);
692 }
693
694 /*
695 * ipcp_nakci - Peer has sent a NAK for some of our CIs.
696 * This should not modify any state if the Nak is bad
697 * or if IPCP is in the OPENED state.
698 * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
699 *
700 * Returns:
701 * 0 - Nak was bad.
702 * 1 - Nak was good.
703 */
704 static int
ipcp_nakci(f,p,len)705 ipcp_nakci(f, p, len)
706 fsm *f;
707 u_char *p;
708 int len;
709 {
710 ipcp_options *go = &ipcp_gotoptions[f->unit];
711 u_char cimaxslotindex, cicflag;
712 u_char citype, cilen, *next;
713 u_short cishort;
714 u_int32_t ciaddr1, ciaddr2;
715 ipcp_options no; /* options we've seen Naks for */
716 ipcp_options try; /* options to request next time */
717
718 BZERO(&no, sizeof(no));
719 try = *go;
720
721 /*
722 * Any Nak'd CIs must be in exactly the same order that we sent.
723 * Check packet length and CI length at each step.
724 * If we find any deviations, then this packet is bad.
725 */
726 #define NAKCIADDRS(opt, neg, code) \
727 if ((neg) && \
728 (cilen = p[1]) == CILEN_ADDRS && \
729 len >= cilen && \
730 p[0] == opt) { \
731 len -= cilen; \
732 INCPTR(2, p); \
733 GETNLONG(ciaddr1, p); \
734 GETNLONG(ciaddr2, p); \
735 no.old_addrs = 1; \
736 code \
737 }
738
739 #define NAKCIVJ(opt, neg, code) \
740 if (go->neg && \
741 ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
742 len >= cilen && \
743 p[0] == opt) { \
744 len -= cilen; \
745 INCPTR(2, p); \
746 GETSHORT(cishort, p); \
747 no.neg = 1; \
748 code \
749 }
750
751 #define NAKCIADDR(opt, neg, code) \
752 if (go->neg && \
753 (cilen = p[1]) == CILEN_ADDR && \
754 len >= cilen && \
755 p[0] == opt) { \
756 len -= cilen; \
757 INCPTR(2, p); \
758 GETNLONG(ciaddr1, p); \
759 no.neg = 1; \
760 code \
761 }
762
763 /*
764 * Accept the peer's idea of {our,its} address, if different
765 * from our idea, only if the accept_{local,remote} flag is set.
766 */
767 NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
768 if (go->accept_local && ciaddr1) { /* Do we know our address? */
769 try.ouraddr = ciaddr1;
770 }
771 if (go->accept_remote && ciaddr2) { /* Does it know its? */
772 try.hisaddr = ciaddr2;
773 }
774 );
775
776 /*
777 * Accept the peer's value of maxslotindex provided that it
778 * is less than what we asked for. Turn off slot-ID compression
779 * if the peer wants. Send old-style compress-type option if
780 * the peer wants.
781 */
782 NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
783 if (cilen == CILEN_VJ) {
784 GETCHAR(cimaxslotindex, p);
785 GETCHAR(cicflag, p);
786 if (cishort == IPCP_VJ_COMP) {
787 try.old_vj = 0;
788 if (cimaxslotindex < go->maxslotindex)
789 try.maxslotindex = cimaxslotindex;
790 if (!cicflag)
791 try.cflag = 0;
792 } else {
793 try.neg_vj = 0;
794 }
795 } else {
796 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
797 try.old_vj = 1;
798 try.vj_protocol = cishort;
799 } else {
800 try.neg_vj = 0;
801 }
802 }
803 );
804
805 NAKCIADDR(CI_ADDR, neg_addr,
806 if (go->accept_local && ciaddr1) { /* Do we know our address? */
807 try.ouraddr = ciaddr1;
808 }
809 );
810
811 NAKCIADDR(CI_MS_DNS1, req_dns1,
812 try.dnsaddr[0] = ciaddr1;
813 );
814
815 NAKCIADDR(CI_MS_DNS2, req_dns2,
816 try.dnsaddr[1] = ciaddr1;
817 );
818
819 /*
820 * There may be remaining CIs, if the peer is requesting negotiation
821 * on an option that we didn't include in our request packet.
822 * If they want to negotiate about IP addresses, we comply.
823 * If they want us to ask for compression, we refuse.
824 */
825 while (len > CILEN_VOID) {
826 GETCHAR(citype, p);
827 GETCHAR(cilen, p);
828 if( (len -= cilen) < 0 )
829 goto bad;
830 next = p + cilen - 2;
831
832 switch (citype) {
833 case CI_COMPRESSTYPE:
834 if (go->neg_vj || no.neg_vj ||
835 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
836 goto bad;
837 no.neg_vj = 1;
838 break;
839 case CI_ADDRS:
840 if ((!go->neg_addr && go->old_addrs) || no.old_addrs
841 || cilen != CILEN_ADDRS)
842 goto bad;
843 try.neg_addr = 1;
844 try.old_addrs = 1;
845 GETNLONG(ciaddr1, p);
846 if (ciaddr1 && go->accept_local)
847 try.ouraddr = ciaddr1;
848 GETNLONG(ciaddr2, p);
849 if (ciaddr2 && go->accept_remote)
850 try.hisaddr = ciaddr2;
851 no.old_addrs = 1;
852 break;
853 case CI_ADDR:
854 if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
855 goto bad;
856 try.old_addrs = 0;
857 GETNLONG(ciaddr1, p);
858 if (ciaddr1 && go->accept_local)
859 try.ouraddr = ciaddr1;
860 if (try.ouraddr != 0)
861 try.neg_addr = 1;
862 no.neg_addr = 1;
863 break;
864 }
865 p = next;
866 }
867
868 /*
869 * OK, the Nak is good. Now we can update state.
870 * If there are any remaining options, we ignore them.
871 */
872 if (f->state != OPENED)
873 *go = try;
874
875 return 1;
876
877 bad:
878 IPCPDEBUG(("ipcp_nakci: received bad Nak!"));
879 return 0;
880 }
881
882
883 /*
884 * ipcp_rejci - Reject some of our CIs.
885 * Callback from fsm_rconfnakrej.
886 */
887 static int
ipcp_rejci(f,p,len)888 ipcp_rejci(f, p, len)
889 fsm *f;
890 u_char *p;
891 int len;
892 {
893 ipcp_options *go = &ipcp_gotoptions[f->unit];
894 u_char cimaxslotindex, ciflag, cilen;
895 u_short cishort;
896 u_int32_t cilong;
897 ipcp_options try; /* options to request next time */
898
899 try = *go;
900 /*
901 * Any Rejected CIs must be in exactly the same order that we sent.
902 * Check packet length and CI length at each step.
903 * If we find any deviations, then this packet is bad.
904 */
905 #define REJCIADDRS(opt, neg, val1, val2) \
906 if ((neg) && \
907 (cilen = p[1]) == CILEN_ADDRS && \
908 len >= cilen && \
909 p[0] == opt) { \
910 len -= cilen; \
911 INCPTR(2, p); \
912 GETNLONG(cilong, p); \
913 /* Check rejected value. */ \
914 if (cilong != val1) \
915 goto bad; \
916 GETNLONG(cilong, p); \
917 /* Check rejected value. */ \
918 if (cilong != val2) \
919 goto bad; \
920 try.old_addrs = 0; \
921 }
922
923 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
924 if (go->neg && \
925 p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
926 len >= p[1] && \
927 p[0] == opt) { \
928 len -= p[1]; \
929 INCPTR(2, p); \
930 GETSHORT(cishort, p); \
931 /* Check rejected value. */ \
932 if (cishort != val) \
933 goto bad; \
934 if (!old) { \
935 GETCHAR(cimaxslotindex, p); \
936 if (cimaxslotindex != maxslot) \
937 goto bad; \
938 GETCHAR(ciflag, p); \
939 if (ciflag != cflag) \
940 goto bad; \
941 } \
942 try.neg = 0; \
943 }
944
945 #define REJCIADDR(opt, neg, addr) \
946 if (go->neg && \
947 ((cilen = p[1]) == CILEN_ADDR) && \
948 len >= cilen && \
949 p[0] == opt) { \
950 len -= cilen; \
951 INCPTR(2, p); \
952 GETNLONG(cilong, p); \
953 /* Check rejected value. */ \
954 if (cilong != addr) \
955 goto bad; \
956 try.neg = 0; \
957 }
958
959 REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
960 go->ouraddr, go->hisaddr);
961
962 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
963 go->maxslotindex, go->cflag);
964
965 REJCIADDR(CI_ADDR, neg_addr, go->ouraddr);
966
967 REJCIADDR(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
968
969 REJCIADDR(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
970
971 /*
972 * If there are any remaining CIs, then this packet is bad.
973 */
974 if (len != 0)
975 goto bad;
976 /*
977 * Now we can update state.
978 */
979 if (f->state != OPENED)
980 *go = try;
981 return 1;
982
983 bad:
984 IPCPDEBUG(("ipcp_rejci: received bad Reject!"));
985 return 0;
986 }
987
988
989 /*
990 * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
991 * Callback from fsm_rconfreq, Receive Configure Request
992 *
993 * Returns: CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and input
994 * packet modified appropriately. If reject_if_disagree is non-zero,
995 * doesn't return CODE_CONFNAK; returns CODE_CONFREJ if it can't
996 * return CODE_CONFACK.
997 */
998 static int
ipcp_reqci(f,p,lenp,dont_nak)999 ipcp_reqci(f, p, lenp, dont_nak)
1000 fsm *f;
1001 u_char *p; /* Requested CIs */
1002 int *lenp; /* Length of requested CIs */
1003 bool dont_nak;
1004 {
1005 ipcp_options *wo = &ipcp_wantoptions[f->unit];
1006 ipcp_options *ho = &ipcp_hisoptions[f->unit];
1007 ipcp_options *ao = &ipcp_allowoptions[f->unit];
1008 ipcp_options *go = &ipcp_gotoptions[f->unit];
1009 int ret, newret;
1010 u_char *p0, *nakp, *rejp, *prev;
1011 u_short cishort;
1012 int len, cilen, type;
1013 u_int32_t tl, ciaddr1, ciaddr2; /* Parsed address values */
1014 u_char maxslotindex, cflag;
1015 int d;
1016
1017 ret = CODE_CONFACK;
1018 rejp = p0 = p;
1019 nakp = nak_buffer;
1020
1021 /*
1022 * Reset all its options.
1023 */
1024 BZERO(ho, sizeof(*ho));
1025
1026 /*
1027 * Process all its options.
1028 */
1029 for (len = *lenp; len > 0; len -= cilen, p = prev + cilen) {
1030 if ((len < 2) || p[1] > len) {
1031 /*
1032 * RFC 1661 page 40 -- if the option extends beyond the
1033 * packet, then discard the entire packet.
1034 */
1035 return (0);
1036 }
1037
1038 newret = CODE_CONFACK;
1039 prev = p;
1040 GETCHAR(type, p);
1041 GETCHAR(cilen, p);
1042
1043 switch (type) { /* Check CI type */
1044 case CI_ADDRS:
1045 if (!ao->old_addrs || ho->neg_addr) {
1046 newret = CODE_CONFREJ;
1047 break;
1048 }
1049
1050 if (cilen != CILEN_ADDRS) {
1051 /*
1052 * rfc1661, page 40 -- a recongnized option with an
1053 * invalid length should be Nak'ed.
1054 */
1055 newret = CODE_CONFNAK;
1056 ciaddr1 = wo->hisaddr;
1057 ciaddr2 = wo->ouraddr;
1058 } else {
1059
1060 /*
1061 * If it has no address, or if we both have its
1062 * address but disagree about it, then NAK it with our
1063 * idea. In particular, if we don't know its address,
1064 * but it does, then accept it.
1065 */
1066 GETNLONG(ciaddr1, p);
1067 if (ciaddr1 != wo->hisaddr &&
1068 (ciaddr1 == 0 || !wo->accept_remote)) {
1069 newret = CODE_CONFNAK;
1070 ciaddr1 = wo->hisaddr;
1071 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1072 /*
1073 * If neither we nor he knows his address, reject
1074 * the option.
1075 */
1076 newret = CODE_CONFREJ;
1077 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
1078 break;
1079 } else if (ciaddr1 != 0) {
1080 go->hisaddr = ciaddr1;
1081 }
1082
1083 /*
1084 * If he doesn't know our address, or if we both have
1085 * our address * but disagree about it, then NAK it
1086 * with our idea.
1087 */
1088 GETNLONG(ciaddr2, p);
1089 if (ciaddr2 != wo->ouraddr) {
1090 if (ciaddr2 == 0 || !wo->accept_local) {
1091 newret = CODE_CONFNAK;
1092 ciaddr2 = wo->ouraddr;
1093 } else {
1094 go->ouraddr = ciaddr2; /* accept peer's idea */
1095 }
1096 }
1097 }
1098
1099 if (newret == CODE_CONFNAK) {
1100 PUTCHAR(type, nakp);
1101 PUTCHAR(CILEN_ADDRS, nakp);
1102 PUTNLONG(ciaddr1, nakp);
1103 PUTNLONG(ciaddr2, nakp);
1104 }
1105
1106 ho->old_addrs = 1;
1107 ho->hisaddr = ciaddr1;
1108 ho->ouraddr = ciaddr2;
1109 break;
1110
1111 case CI_ADDR:
1112 if (!ao->neg_addr || ho->old_addrs) {
1113 newret = CODE_CONFREJ;
1114 break;
1115 }
1116
1117 if (cilen != CILEN_ADDR) {
1118 /*
1119 * rfc1661, page 40 -- a recongnized option with an
1120 * invalid length should be Nak'ed.
1121 */
1122 newret = CODE_CONFNAK;
1123 ciaddr1 = wo->hisaddr;
1124 } else {
1125
1126 /*
1127 * If he has no address, or if we both have his
1128 * address but disagree about it, then NAK it with our
1129 * idea. In particular, if we don't know his address,
1130 * but he does, then accept it.
1131 */
1132 GETNLONG(ciaddr1, p);
1133 if (ciaddr1 != wo->hisaddr &&
1134 (ciaddr1 == 0 || !wo->accept_remote)) {
1135 newret = CODE_CONFNAK;
1136 ciaddr1 = wo->hisaddr;
1137 } else if (ciaddr1 == 0 && wo->hisaddr == 0 &&
1138 wo->default_route != 0) {
1139 newret = CODE_CONFNAK;
1140 /*
1141 * If this is a dialup line (default_route is
1142 * set), and neither side knows about its address,
1143 * suggest an arbitrary rfc1918 address.
1144 */
1145 ciaddr1 = htonl(0xc0a80101 + ifunit);
1146 dbglog("Peer address unknown; suggesting %I", ciaddr1);
1147 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1148 /*
1149 * If this is not a dialup line, don't ACK an
1150 * address of 0.0.0.0 - reject it instead.
1151 */
1152 newret = CODE_CONFREJ;
1153 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
1154 break;
1155 }
1156 }
1157
1158 if (newret == CODE_CONFNAK) {
1159 PUTCHAR(type, nakp);
1160 PUTCHAR(CILEN_ADDR, nakp);
1161 PUTNLONG(ciaddr1, nakp);
1162 }
1163
1164 ho->neg_addr = 1;
1165 ho->hisaddr = ciaddr1;
1166 break;
1167
1168 case CI_MS_DNS1:
1169 case CI_MS_DNS2:
1170 /* Warning -- these options work backwards. */
1171 /* Microsoft primary or secondary DNS request */
1172 d = (type == CI_MS_DNS2 ? 1 : 0);
1173
1174 if (ao->dnsaddr[d] == 0) {
1175 newret = CODE_CONFREJ;
1176 break;
1177 }
1178
1179 if (cilen != CILEN_ADDR) {
1180 newret = CODE_CONFNAK;
1181 } else {
1182 GETNLONG(tl, p);
1183 if (tl != ao->dnsaddr[d]) {
1184 newret = CODE_CONFNAK;
1185 }
1186 }
1187
1188 if (newret == CODE_CONFNAK) {
1189 PUTCHAR(type, nakp);
1190 PUTCHAR(CILEN_ADDR, nakp);
1191 PUTNLONG(ao->dnsaddr[d], nakp);
1192 }
1193 break;
1194
1195 case CI_MS_WINS1:
1196 case CI_MS_WINS2:
1197 /* Warning -- these options work backwards. */
1198 /* Microsoft primary or secondary WINS request */
1199 d = (type == CI_MS_WINS2 ? 1 : 0);
1200
1201 if (ao->winsaddr[d] == 0) {
1202 newret = CODE_CONFREJ;
1203 break;
1204 }
1205
1206 if (cilen != CILEN_ADDR) {
1207 newret = CODE_CONFNAK;
1208 } else {
1209 GETNLONG(tl, p);
1210 if (tl != ao->winsaddr[d]) {
1211 newret = CODE_CONFNAK;
1212 }
1213 }
1214
1215 if (newret == CODE_CONFNAK) {
1216 PUTCHAR(type, nakp);
1217 PUTCHAR(CILEN_ADDR, nakp);
1218 PUTNLONG(ao->winsaddr[d], nakp);
1219 }
1220 break;
1221
1222 case CI_COMPRESSTYPE:
1223 if (!ao->neg_vj) {
1224 newret = CODE_CONFREJ;
1225 break;
1226 }
1227
1228 maxslotindex = ao->maxslotindex;
1229 cflag = ao->cflag;
1230 if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
1231 newret = CODE_CONFNAK;
1232 cishort = IPCP_VJ_COMP;
1233 } else {
1234 GETSHORT(cishort, p);
1235 if (cishort != IPCP_VJ_COMP &&
1236 (cishort != IPCP_VJ_COMP_OLD || cilen != CILEN_COMPRESS)) {
1237 newret = CODE_CONFNAK;
1238 cishort = IPCP_VJ_COMP;
1239 } else if (cilen == CILEN_VJ) {
1240 GETCHAR(maxslotindex, p);
1241 if (maxslotindex > ao->maxslotindex) {
1242 newret = CODE_CONFNAK;
1243 maxslotindex = ao->maxslotindex;
1244 }
1245 GETCHAR(cflag, p);
1246 if (cflag != 0 && ao->cflag == 0) {
1247 newret = CODE_CONFNAK;
1248 cflag = 0;
1249 }
1250 } else {
1251 ho->old_vj = 1;
1252 maxslotindex = MAX_STATES - 1;
1253 cflag = 1;
1254 }
1255 }
1256
1257 if (newret == CODE_CONFNAK) {
1258 PUTCHAR(type, nakp);
1259 if (cishort == IPCP_VJ_COMP) {
1260 PUTCHAR(CILEN_VJ, nakp);
1261 PUTSHORT(cishort, nakp);
1262 PUTCHAR(maxslotindex, nakp);
1263 PUTCHAR(cflag, nakp);
1264 } else {
1265 PUTCHAR(CILEN_COMPRESS, nakp);
1266 PUTSHORT(cishort, nakp);
1267 }
1268 }
1269 ho->neg_vj = 1;
1270 ho->vj_protocol = cishort;
1271 ho->maxslotindex = maxslotindex;
1272 ho->cflag = cflag;
1273 break;
1274
1275 default:
1276 newret = CODE_CONFREJ;
1277 break;
1278 }
1279
1280 /* Cope with confused peers. */
1281 if (cilen < 2)
1282 cilen = 2;
1283
1284 /*
1285 * If this is an Ack'able CI, but we're sending back a Nak,
1286 * don't include this CI.
1287 */
1288 if (newret == CODE_CONFACK && ret != CODE_CONFACK)
1289 continue;
1290
1291 if (newret == CODE_CONFNAK) {
1292 if (dont_nak) {
1293 newret = CODE_CONFREJ;
1294 } else {
1295 /* Ignore subsequent Nak'able things if rejecting. */
1296 if (ret == CODE_CONFREJ)
1297 continue;
1298 ret = CODE_CONFNAK;
1299 }
1300 }
1301
1302 if (newret == CODE_CONFREJ) {
1303 ret = CODE_CONFREJ;
1304 if (prev != rejp)
1305 BCOPY(prev, rejp, cilen);
1306 rejp += cilen;
1307 }
1308 }
1309
1310 /*
1311 * If we aren't rejecting this packet, and we want to negotiate
1312 * their address, and they didn't send their address, then we
1313 * send a NAK with a CI_ADDR option appended. We assume the
1314 * input buffer is long enough that we can append the extra
1315 * option safely.
1316 */
1317 if (ret != CODE_CONFREJ && !ho->neg_addr && !ho->old_addrs &&
1318 wo->req_addr && !dont_nak) {
1319 if (ret == CODE_CONFACK)
1320 wo->req_addr = 0; /* don't ask again */
1321 ret = CODE_CONFNAK;
1322 PUTCHAR(CI_ADDR, nakp);
1323 PUTCHAR(CILEN_ADDR, nakp);
1324 PUTNLONG(wo->hisaddr, nakp);
1325 }
1326
1327 switch (ret) {
1328 case CODE_CONFACK:
1329 *lenp = p - p0;
1330 sys_block_proto(PPP_IP);
1331 break;
1332 case CODE_CONFNAK:
1333 *lenp = nakp - nak_buffer;
1334 BCOPY(nak_buffer, p0, *lenp);
1335 break;
1336 case CODE_CONFREJ:
1337 *lenp = rejp - p0;
1338 break;
1339 }
1340
1341 return (ret); /* Return final code */
1342 }
1343
1344
1345 /*
1346 * ip_check_options - check that any IP-related options are OK,
1347 * and assign appropriate defaults.
1348 */
1349 static void
ip_check_options()1350 ip_check_options()
1351 {
1352 struct hostent *hp;
1353 u_int32_t local;
1354 ipcp_options *wo = &ipcp_wantoptions[0];
1355
1356 /*
1357 * Default our local IP address based on our hostname.
1358 * If local IP address already given, don't bother.
1359 */
1360 if (wo->ouraddr == 0) {
1361 /*
1362 * Look up our hostname (possibly with domain name appended)
1363 * and take the first IP address as our local IP address.
1364 * If there isn't an IP address for our hostname, too bad.
1365 */
1366 wo->accept_local = 1; /* don't insist on this default value */
1367 if ((hp = gethostbyname(hostname)) != NULL) {
1368 BCOPY(hp->h_addr, &local, sizeof (hp->h_addr));
1369 if (local != 0 && !bad_ip_adrs(local)) {
1370 wo->ouraddr = local;
1371 ipcp_from_hostname = 1;
1372 }
1373 }
1374 }
1375 }
1376
1377
1378 /*
1379 * ip_demand_conf - configure the interface as though
1380 * IPCP were up, for use with dial-on-demand.
1381 */
1382 static int
ip_demand_conf(u)1383 ip_demand_conf(u)
1384 int u;
1385 {
1386 ipcp_options *wo = &ipcp_wantoptions[u];
1387
1388 if (wo->hisaddr == 0) {
1389 /* make up an arbitrary address for the peer */
1390 wo->hisaddr = htonl(0x0a707070 + ifunit);
1391 wo->accept_remote = 1;
1392 }
1393 if (wo->ouraddr == 0) {
1394 /* make up an arbitrary address for us */
1395 wo->ouraddr = htonl(0x0a404040 + ifunit);
1396 wo->accept_local = 1;
1397 disable_defaultip = 1; /* don't tell the peer this address */
1398 }
1399 if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
1400 return 0;
1401 if (!sifup(u))
1402 return 0;
1403 if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
1404 return 0;
1405 if (wo->default_route && sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
1406 default_route_set[u] = 1;
1407 if (wo->proxy_arp && sifproxyarp(u, wo->hisaddr, proxy_arp_quiet[u]))
1408 proxy_arp_set[u] = 1;
1409
1410 notice("local IP address %I", wo->ouraddr);
1411 notice("remote IP address %I", wo->hisaddr);
1412
1413 return 1;
1414 }
1415
1416
1417 /*
1418 * ipcp_up - IPCP has come UP.
1419 *
1420 * Configure the IP network interface appropriately and bring it up.
1421 */
1422 static void
ipcp_up(f)1423 ipcp_up(f)
1424 fsm *f;
1425 {
1426 u_int32_t mask;
1427 ipcp_options *ho = &ipcp_hisoptions[f->unit];
1428 ipcp_options *go = &ipcp_gotoptions[f->unit];
1429 ipcp_options *wo = &ipcp_wantoptions[f->unit];
1430
1431 IPCPDEBUG(("ipcp: up"));
1432
1433 /*
1434 * We must have a non-zero IP address for both ends of the link.
1435 */
1436 if (ho->hisaddr == 0)
1437 ho->hisaddr = wo->hisaddr;
1438
1439 if (ho->hisaddr == 0) {
1440 if (wo->accept_remote) {
1441 /* Pick some rfc1918 address. */
1442 ho->hisaddr = htonl(0xc0a80101 + ifunit);
1443 dbglog("Peer refused to provide his address; assuming %I",
1444 ho->hisaddr);
1445 } else {
1446 error("Could not determine remote IP address");
1447 ipcp_close(f->unit, "Could not determine remote IP address");
1448 return;
1449 }
1450 }
1451 if (go->ouraddr == 0) {
1452 error("Could not determine local IP address");
1453 ipcp_close(f->unit, "Could not determine local IP address");
1454 return;
1455 }
1456 script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0);
1457 script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1);
1458
1459 /*
1460 * Check that the peer is allowed to use the IP address it wants.
1461 */
1462 if (!auth_ip_addr(f->unit, ho->hisaddr)) {
1463 error("Peer is not authorized to use remote address %I", ho->hisaddr);
1464 ipcp_close(f->unit, "Unauthorized remote IP address");
1465 return;
1466 }
1467
1468 if ((go->req_dns1 && go->dnsaddr[0] != 0) ||
1469 (go->req_dns2 && go->dnsaddr[1] != 0)) {
1470 script_setenv("USEPEERDNS", "1", 0);
1471 if (go->dnsaddr[0] != 0)
1472 script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0);
1473 if (go->dnsaddr[1] != 0)
1474 script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0);
1475 create_resolv(go->dnsaddr[0], go->dnsaddr[1]);
1476 }
1477
1478 /* set tcp compression */
1479 if (sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex) != 1) {
1480 ipcp_close(f->unit, "Could not enable VJ TCP header compression");
1481 return;
1482 }
1483
1484 /*
1485 * If we are doing dial-on-demand, the interface is already
1486 * configured, so we put out any saved-up packets, then set the
1487 * interface to pass IP packets.
1488 */
1489 if (demand) {
1490 if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
1491 ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
1492 if (go->ouraddr != wo->ouraddr) {
1493 warn("Local IP address changed to %I", go->ouraddr);
1494 script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
1495 wo->ouraddr = go->ouraddr;
1496 } else
1497 script_unsetenv("OLDIPLOCAL");
1498 if (ho->hisaddr != wo->hisaddr) {
1499 warn("Remote IP address changed to %I", ho->hisaddr);
1500 script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0);
1501 wo->hisaddr = ho->hisaddr;
1502 } else
1503 script_unsetenv("OLDIPREMOTE");
1504
1505 /* Set the interface to the new addresses */
1506 mask = GetMask(go->ouraddr);
1507 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1508 warn("Interface configuration failed");
1509 ipcp_close(f->unit, "Interface configuration failed");
1510 return;
1511 }
1512
1513 /* assign a default route through the interface if required */
1514 if (wo->default_route)
1515 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1516 default_route_set[f->unit] = 1;
1517
1518 /* Make a proxy ARP entry if requested. */
1519 if (wo->proxy_arp &&
1520 sifproxyarp(f->unit, ho->hisaddr, proxy_arp_quiet[f->unit]))
1521 proxy_arp_set[f->unit] = 1;
1522
1523 }
1524 demand_rexmit(PPP_IP);
1525 if (sifnpmode(f->unit, PPP_IP, NPMODE_PASS) != 1) {
1526 ipcp_close(f->unit, "Interface configuration failed.");
1527 return;
1528 }
1529
1530 } else {
1531 /*
1532 * Set IP addresses and (if specified) netmask.
1533 */
1534 mask = GetMask(go->ouraddr);
1535
1536 #if SIFUPFIRST
1537 /* bring the interface up for IP */
1538 if (!sifup(f->unit)) {
1539 warn("Interface failed to come up");
1540 ipcp_close(f->unit, "Interface configuration failed");
1541 return;
1542 }
1543 #endif
1544
1545 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1546 warn("Interface configuration failed");
1547 ipcp_close(f->unit, "Interface configuration failed");
1548 return;
1549 }
1550
1551 #if !SIFUPFIRST
1552 /* bring the interface up for IP */
1553 if (!sifup(f->unit)) {
1554 warn("Interface failed to come up");
1555 ipcp_close(f->unit, "Interface configuration failed");
1556 return;
1557 }
1558 #endif
1559
1560 if (sifnpmode(f->unit, PPP_IP, NPMODE_PASS) != 1) {
1561 ipcp_close(f->unit, "Interface configuration failed.");
1562 return;
1563 }
1564
1565 /* assign a default route through the interface if required */
1566 if (wo->default_route)
1567 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1568 default_route_set[f->unit] = 1;
1569
1570 /* Make a proxy ARP entry if requested. */
1571 if (wo->proxy_arp &&
1572 sifproxyarp(f->unit, ho->hisaddr, proxy_arp_quiet[f->unit]))
1573 proxy_arp_set[f->unit] = 1;
1574
1575 wo->ouraddr = go->ouraddr;
1576
1577 notice("local IP address %I", go->ouraddr);
1578 notice("remote IP address %I", ho->hisaddr);
1579 if (go->dnsaddr[0] != 0)
1580 notice("primary DNS address %I", go->dnsaddr[0]);
1581 if (go->dnsaddr[1] != 0)
1582 notice("secondary DNS address %I", go->dnsaddr[1]);
1583 }
1584
1585 np_up(f->unit, PPP_IP);
1586 ipcp_is_up[f->unit] = 1;
1587
1588 if (ip_up_hook != NULL)
1589 (*ip_up_hook)();
1590
1591 /*
1592 * Execute the ip-up script, like this:
1593 * /etc/ppp/ip-up interface tty speed local-IP remote-IP
1594 */
1595 if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
1596 ipcp_script_state = s_up;
1597 ipcp_script(_PATH_IPUP);
1598 }
1599 sys_unblock_proto(PPP_IP);
1600 }
1601
1602
1603 /*
1604 * ipcp_down - IPCP has gone DOWN.
1605 *
1606 * Take the IP network interface down, clear its addresses
1607 * and delete routes through it.
1608 */
1609 static void
ipcp_down(f)1610 ipcp_down(f)
1611 fsm *f;
1612 {
1613 IPCPDEBUG(("ipcp: down"));
1614 /* XXX a bit IPv4-centric here, we only need to get the stats
1615 * before the interface is marked down. */
1616 update_link_stats(f->unit);
1617 if (ip_down_hook != NULL)
1618 (*ip_down_hook)();
1619 if (ipcp_is_up[f->unit]) {
1620 ipcp_is_up[f->unit] = 0;
1621 np_down(f->unit, PPP_IP);
1622 }
1623 if (sifvjcomp(f->unit, 0, 0, 0) != 1) {
1624 if (debug)
1625 warn("Failed to disable VJ TCP header compression.");
1626 }
1627
1628 /*
1629 * If we are doing dial-on-demand, set the interface
1630 * to queue up outgoing packets (for now).
1631 */
1632 if (demand) {
1633 if (sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE) != 1) {
1634 if (debug)
1635 warn("Failed to enable Queueing on outgoing packets.");
1636 }
1637 } else {
1638 if (sifnpmode(f->unit, PPP_IP, NPMODE_ERROR) != 1) {
1639 if (debug)
1640 warn("Could not set interface to drop packets.");
1641 }
1642 if (sifdown(f->unit) != 1)
1643 warn("Could not bring interface down.");
1644 ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
1645 ipcp_hisoptions[f->unit].hisaddr);
1646 }
1647
1648 /* Execute the ip-down script */
1649 if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
1650 ipcp_script_state = s_down;
1651 ipcp_script(_PATH_IPDOWN);
1652 }
1653 }
1654
1655
1656 /*
1657 * ipcp_clear_addrs() - clear the interface addresses, routes,
1658 * proxy arp entries, etc.
1659 */
1660 static void
ipcp_clear_addrs(unit,ouraddr,hisaddr)1661 ipcp_clear_addrs(unit, ouraddr, hisaddr)
1662 int unit;
1663 u_int32_t ouraddr; /* local address */
1664 u_int32_t hisaddr; /* remote address */
1665 {
1666 if (proxy_arp_set[unit]) {
1667 (void) cifproxyarp(unit, hisaddr);
1668 proxy_arp_set[unit] = 0;
1669 }
1670 if (default_route_set[unit]) {
1671 (void) cifdefaultroute(unit, ouraddr, hisaddr);
1672 default_route_set[unit] = 0;
1673 }
1674 if (cifaddr(unit, ouraddr, hisaddr) != 1)
1675 warn("Could not clear addresses");
1676 }
1677
1678
1679 /*
1680 * ipcp_finished - possibly shut down the lower layers.
1681 */
1682 static void
ipcp_finished(f)1683 ipcp_finished(f)
1684 fsm *f;
1685 {
1686 np_finished(f->unit, PPP_IP);
1687 }
1688
1689
1690 /*
1691 * ipcp_script_done - called when the ip-up or ip-down script
1692 * has finished.
1693 */
1694 /*ARGSUSED*/
1695 static void
ipcp_script_done(arg,status)1696 ipcp_script_done(arg, status)
1697 void *arg;
1698 int status;
1699 {
1700 ipcp_script_pid = 0;
1701 switch (ipcp_script_state) {
1702 case s_up:
1703 if (ipcp_fsm[0].state != OPENED) {
1704 ipcp_script_state = s_down;
1705 ipcp_script(_PATH_IPDOWN);
1706 }
1707 break;
1708 case s_down:
1709 if (ipcp_fsm[0].state == OPENED) {
1710 ipcp_script_state = s_up;
1711 ipcp_script(_PATH_IPUP);
1712 }
1713 break;
1714 }
1715 }
1716
1717
1718 /*
1719 * ipcp_script - Execute a script with arguments
1720 * interface-name tty-name speed local-IP remote-IP.
1721 */
1722 static void
ipcp_script(script)1723 ipcp_script(script)
1724 char *script;
1725 {
1726 char strspeed[32], strlocal[32], strremote[32];
1727 char *argv[8];
1728
1729 (void) slprintf(strspeed, sizeof(strspeed), "%d", baud_rate);
1730 (void) slprintf(strlocal, sizeof(strlocal), "%I",
1731 ipcp_gotoptions[0].ouraddr);
1732 (void) slprintf(strremote, sizeof(strremote), "%I",
1733 ipcp_hisoptions[0].hisaddr);
1734
1735 argv[0] = script;
1736 argv[1] = ifname;
1737 argv[2] = devnam;
1738 argv[3] = strspeed;
1739 argv[4] = strlocal;
1740 argv[5] = strremote;
1741 argv[6] = ipparam;
1742 argv[7] = NULL;
1743 ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done, NULL);
1744 }
1745
1746 /*
1747 * create_resolv - create the replacement resolv.conf file
1748 */
1749 static void
create_resolv(peerdns1,peerdns2)1750 create_resolv(peerdns1, peerdns2)
1751 u_int32_t peerdns1, peerdns2;
1752 {
1753 FILE *f;
1754
1755 f = fopen(_PATH_RESOLV, "w");
1756 if (f == NULL) {
1757 error("Failed to create %s: %m", _PATH_RESOLV);
1758 return;
1759 }
1760
1761 if (peerdns1)
1762 if (fprintf(f, "nameserver %s\n", ip_ntoa(peerdns1)) <= 0)
1763 error("Write failed to %s: %m", _PATH_RESOLV);
1764
1765 if (peerdns2)
1766 if (fprintf(f, "nameserver %s\n", ip_ntoa(peerdns2)) <= 0)
1767 error("Write failed to %s: %m", _PATH_RESOLV);
1768
1769 if (fclose(f) != 0)
1770 error("Failed to close %s: %m", _PATH_RESOLV);
1771 }
1772
1773 /*
1774 * ipcp_printpkt - print the contents of an IPCP packet.
1775 */
1776 static int
ipcp_printpkt(p,plen,printer,arg)1777 ipcp_printpkt(p, plen, printer, arg)
1778 u_char *p;
1779 int plen;
1780 void (*printer) __P((void *, const char *, ...));
1781 void *arg;
1782 {
1783 int code, id, len, olen;
1784 u_char *pstart, *optend;
1785 u_short cishort;
1786 u_int32_t cilong;
1787
1788 if (plen < HEADERLEN)
1789 return 0;
1790 pstart = p;
1791 GETCHAR(code, p);
1792 GETCHAR(id, p);
1793 GETSHORT(len, p);
1794 if (len < HEADERLEN || len > plen)
1795 return 0;
1796
1797 printer(arg, " %s id=0x%x", code_name(code, 1), id);
1798 len -= HEADERLEN;
1799 switch (code) {
1800 case CODE_CONFREQ:
1801 case CODE_CONFACK:
1802 case CODE_CONFNAK:
1803 case CODE_CONFREJ:
1804 /* print option list */
1805 while (len >= 2) {
1806 GETCHAR(code, p);
1807 GETCHAR(olen, p);
1808 p -= 2;
1809 if (olen < 2 || olen > len) {
1810 break;
1811 }
1812 printer(arg, " <");
1813 len -= olen;
1814 optend = p + olen;
1815 switch (code) {
1816 case CI_ADDRS:
1817 if (olen == CILEN_ADDRS) {
1818 p += 2;
1819 GETNLONG(cilong, p);
1820 printer(arg, "addrs %I", cilong);
1821 GETNLONG(cilong, p);
1822 printer(arg, " %I", cilong);
1823 }
1824 break;
1825 case CI_COMPRESSTYPE:
1826 if (olen >= CILEN_COMPRESS) {
1827 p += 2;
1828 GETSHORT(cishort, p);
1829 printer(arg, "compress ");
1830 switch (cishort) {
1831 case IPCP_VJ_COMP:
1832 printer(arg, "VJ");
1833 break;
1834 case IPCP_VJ_COMP_OLD:
1835 printer(arg, "old-VJ");
1836 break;
1837 default:
1838 printer(arg, "0x%x", cishort);
1839 }
1840 }
1841 break;
1842 case CI_ADDR:
1843 if (olen == CILEN_ADDR) {
1844 p += 2;
1845 GETNLONG(cilong, p);
1846 printer(arg, "addr %I", cilong);
1847 }
1848 break;
1849 case CI_MS_DNS1:
1850 case CI_MS_DNS2:
1851 p += 2;
1852 GETNLONG(cilong, p);
1853 printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1 ? 1 : 2),
1854 cilong);
1855 break;
1856 case CI_MS_WINS1:
1857 case CI_MS_WINS2:
1858 p += 2;
1859 GETNLONG(cilong, p);
1860 printer(arg, "ms-wins%d %I", (code == CI_MS_WINS1 ? 1 : 2),
1861 cilong);
1862 break;
1863 case CI_SUBNET:
1864 p += 2;
1865 GETNLONG(cilong, p);
1866 printer(arg, "subnet %I", cilong);
1867 break;
1868 }
1869 while (p < optend) {
1870 GETCHAR(code, p);
1871 printer(arg, " %.2x", code);
1872 }
1873 printer(arg, ">");
1874 }
1875 break;
1876
1877 case CODE_TERMACK:
1878 case CODE_TERMREQ:
1879 if (len > 0 && *p >= ' ' && *p < 0x7f) {
1880 printer(arg, " ");
1881 print_string((char *)p, len, printer, arg);
1882 p += len;
1883 len = 0;
1884 }
1885 break;
1886 }
1887
1888 /* print the rest of the bytes in the packet */
1889 for (; len > 0; --len) {
1890 GETCHAR(code, p);
1891 printer(arg, " %.2x", code);
1892 }
1893
1894 return p - pstart;
1895 }
1896
1897 char *
tcp_flag_decode(val)1898 tcp_flag_decode(val)
1899 int val;
1900 {
1901 static char buf[32];
1902 char *cp = buf;
1903
1904 if (val & TH_URG)
1905 *cp++ = 'U';
1906 if (val & TH_ACK)
1907 *cp++ = 'A';
1908 if (val & TH_PUSH)
1909 *cp++ = 'P';
1910 if (val & TH_RST)
1911 *cp++ = 'R';
1912 if (val & TH_SYN)
1913 *cp++ = 'S';
1914 if (val & TH_FIN)
1915 *cp++ = 'F';
1916 if (cp != buf)
1917 *cp++ = ' ';
1918 *cp = '\0';
1919 return buf;
1920 }
1921
1922 /*
1923 * ip_active_pkt - see if this IP packet is worth bringing the link up for.
1924 * We don't bring the link up for IP fragments or for TCP FIN packets
1925 * with no data.
1926 */
1927
1928 static int
ip_active_pkt(pkt,len)1929 ip_active_pkt(pkt, len)
1930 u_char *pkt;
1931 int len;
1932 {
1933 u_char *tcp;
1934 struct protoent *pep;
1935 int val;
1936 int hlen;
1937 char buf[32], *cp;
1938 u_int32_t src, dst;
1939
1940 len -= PPP_HDRLEN;
1941 pkt += PPP_HDRLEN;
1942 if (len < IP_HDRLEN) {
1943 dbglog("IP packet of length %d is not activity", len);
1944 return 0;
1945 }
1946 src = get_ipsrc(pkt);
1947 dst = get_ipdst(pkt);
1948 if ((get_ipoff(pkt) & IP_OFFMASK) != 0) {
1949 dbglog("IP fragment from %I->%I is not activity", src, dst);
1950 return 0;
1951 }
1952 val = get_ipproto(pkt);
1953 if (val != IPPROTO_TCP) {
1954 if (debug) {
1955 if ((pep = getprotobynumber(val)) != NULL) {
1956 cp = pep->p_name;
1957 } else {
1958 (void) slprintf(buf, sizeof (buf), "IP proto %d", val);
1959 cp = buf;
1960 }
1961 info("%s from %I->%I is activity", cp, src, dst);
1962 }
1963 return 1;
1964 }
1965 hlen = get_iphl(pkt) * 4;
1966 if (len < hlen + TCP_HDRLEN) {
1967 dbglog("Bad TCP length %d<%d+%d %I->%I is not activity", len, hlen,
1968 TCP_HDRLEN, src, dst);
1969 return 0;
1970 }
1971 tcp = pkt + hlen;
1972 val = get_tcpflags(tcp);
1973 hlen += get_tcpoff(tcp) * 4;
1974 if ((val & TH_FIN) != 0 && len == hlen) {
1975 dbglog("Empty TCP FIN %I->%I is not activity", src, dst);
1976 return 0;
1977 }
1978 info("TCP %d data %s%I->%I is activity", len - hlen,
1979 tcp_flag_decode(get_tcpflags(tcp)), src, dst);
1980 return 1;
1981 }
1982
1983 static void
ipcp_print_stat(unit,strptr)1984 ipcp_print_stat(unit, strptr)
1985 int unit;
1986 FILE *strptr;
1987 {
1988 ipcp_options *go = &ipcp_gotoptions[unit];
1989 ipcp_options *ho = &ipcp_hisoptions[unit];
1990 char *proto_name = ipcp_protent.name;
1991
1992 if (!ipcp_protent.enabled_flag) {
1993 (void) flprintf(strptr, "%s disabled\n", proto_name);
1994 return;
1995 }
1996
1997 (void) flprintf(strptr, "%s state: %s", proto_name,
1998 fsm_state(ipcp_fsm[unit].state));
1999 (void) flprintf(strptr, "%s local %I remote %I", proto_name, go->ouraddr,
2000 ho->ouraddr);
2001 }
2002