ReactOS 0.4.16-dev-819-g75c0dc0
ipcp.c
Go to the documentation of this file.
1/*
2 * ipcp.c - PPP IP Control Protocol.
3 *
4 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * 3. The name "Carnegie Mellon University" must not be used to
19 * endorse or promote products derived from this software without
20 * prior written permission. For permission or any legal
21 * details, please contact
22 * Office of Technology Transfer
23 * Carnegie Mellon University
24 * 5000 Forbes Avenue
25 * Pittsburgh, PA 15213-3890
26 * (412) 268-4387, fax: (412) 268-7395
27 * tech-transfer@andrew.cmu.edu
28 *
29 * 4. Redistributions of any form whatsoever must retain the following
30 * acknowledgment:
31 * "This product includes software developed by Computing Services
32 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33 *
34 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41 */
42
43#include "netif/ppp/ppp_opts.h"
44#if PPP_SUPPORT && PPP_IPV4_SUPPORT /* don't build if not configured for use in lwipopts.h */
45
46/*
47 * @todo:
48 */
49
50#if 0 /* UNUSED */
51#include <stdio.h>
52#include <string.h>
53#include <stdlib.h>
54#include <netdb.h>
55#include <sys/param.h>
56#include <sys/types.h>
57#include <sys/socket.h>
58#include <netinet/in.h>
59#include <arpa/inet.h>
60#endif /* UNUSED */
61
62#include "netif/ppp/ppp_impl.h"
63
64#include "netif/ppp/fsm.h"
65#include "netif/ppp/ipcp.h"
66
67#if 0 /* UNUSED */
68/* global vars */
69u32_t netmask = 0; /* IP netmask to set on interface */
70#endif /* UNUSED */
71
72#if 0 /* UNUSED */
73bool disable_defaultip = 0; /* Don't use hostname for default IP adrs */
74#endif /* UNUSED */
75
76#if 0 /* moved to ppp_settings */
77bool noremoteip = 0; /* Let him have no IP address */
78#endif /* moved to ppp_setting */
79
80#if 0 /* UNUSED */
81/* Hook for a plugin to know when IP protocol has come up */
82void (*ip_up_hook) (void) = NULL;
83
84/* Hook for a plugin to know when IP protocol has come down */
85void (*ip_down_hook) (void) = NULL;
86
87/* Hook for a plugin to choose the remote IP address */
88void (*ip_choose_hook) (u32_t *) = NULL;
89#endif /* UNUSED */
90
91#if PPP_NOTIFY
92/* Notifiers for when IPCP goes up and down */
93struct notifier *ip_up_notifier = NULL;
94struct notifier *ip_down_notifier = NULL;
95#endif /* PPP_NOTIFY */
96
97/* local vars */
98#if 0 /* moved to ppp_pcb */
99static int default_route_set[NUM_PPP]; /* Have set up a default route */
100static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */
101static int ipcp_is_up; /* have called np_up() */
102static int ipcp_is_open; /* haven't called np_finished() */
103static bool ask_for_local; /* request our address from peer */
104#endif /* moved to ppp_pcb */
105#if 0 /* UNUSED */
106static char vj_value[8]; /* string form of vj option value */
107static char netmask_str[20]; /* string form of netmask value */
108#endif /* UNUSED */
109
110/*
111 * Callbacks for fsm code. (CI = Configuration Information)
112 */
113static void ipcp_resetci(fsm *f); /* Reset our CI */
114static int ipcp_cilen(fsm *f); /* Return length of our CI */
115static void ipcp_addci(fsm *f, u_char *ucp, int *lenp); /* Add our CI */
116static int ipcp_ackci(fsm *f, u_char *p, int len); /* Peer ack'd our CI */
117static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject);/* Peer nak'd our CI */
118static int ipcp_rejci(fsm *f, u_char *p, int len); /* Peer rej'd our CI */
119static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree); /* Rcv CI */
120static void ipcp_up(fsm *f); /* We're UP */
121static void ipcp_down(fsm *f); /* We're DOWN */
122static void ipcp_finished(fsm *f); /* Don't need lower layer */
123
124static const fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
125 ipcp_resetci, /* Reset our Configuration Information */
126 ipcp_cilen, /* Length of our Configuration Information */
127 ipcp_addci, /* Add our Configuration Information */
128 ipcp_ackci, /* ACK our Configuration Information */
129 ipcp_nakci, /* NAK our Configuration Information */
130 ipcp_rejci, /* Reject our Configuration Information */
131 ipcp_reqci, /* Request peer's Configuration Information */
132 ipcp_up, /* Called when fsm reaches OPENED state */
133 ipcp_down, /* Called when fsm leaves OPENED state */
134 NULL, /* Called when we want the lower layer up */
135 ipcp_finished, /* Called when we want the lower layer down */
136 NULL, /* Called when Protocol-Reject received */
137 NULL, /* Retransmission is necessary */
138 NULL, /* Called to handle protocol-specific codes */
139 "IPCP" /* String name of protocol */
140};
141
142/*
143 * Command-line options.
144 */
145#if PPP_OPTIONS
146static int setvjslots (char **);
147static int setdnsaddr (char **);
148static int setwinsaddr (char **);
149static int setnetmask (char **);
150int setipaddr (char *, char **, int);
151
152static void printipaddr (option_t *, void (*)(void *, char *,...),void *);
153
154static option_t ipcp_option_list[] = {
155 { "noip", o_bool, &ipcp_protent.enabled_flag,
156 "Disable IP and IPCP" },
157 { "-ip", o_bool, &ipcp_protent.enabled_flag,
158 "Disable IP and IPCP", OPT_ALIAS },
159
160 { "novj", o_bool, &ipcp_wantoptions[0].neg_vj,
161 "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj },
162 { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj,
163 "Disable VJ compression", OPT_ALIAS | OPT_A2CLR,
164 &ipcp_allowoptions[0].neg_vj },
165
166 { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag,
167 "Disable VJ connection-ID compression", OPT_A2CLR,
168 &ipcp_allowoptions[0].cflag },
169 { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag,
170 "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR,
171 &ipcp_allowoptions[0].cflag },
172
173 { "vj-max-slots", o_special, (void *)setvjslots,
174 "Set maximum VJ header slots",
175 OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value },
176
177 { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local,
178 "Accept peer's address for us", 1 },
179 { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote,
180 "Accept peer's address for it", 1 },
181
182 { "ipparam", o_string, &ipparam,
183 "Set ip script parameter", OPT_PRIO },
184
185 { "noipdefault", o_bool, &disable_defaultip,
186 "Don't use name for default IP adrs", 1 },
187
188 { "ms-dns", 1, (void *)setdnsaddr,
189 "DNS address for the peer's use" },
190 { "ms-wins", 1, (void *)setwinsaddr,
191 "Nameserver for SMB over TCP/IP for peer" },
192
193 { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime,
194 "Set timeout for IPCP", OPT_PRIO },
195 { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits,
196 "Set max #xmits for term-reqs", OPT_PRIO },
197 { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits,
198 "Set max #xmits for conf-reqs", OPT_PRIO },
199 { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops,
200 "Set max #conf-naks for IPCP", OPT_PRIO },
201
202 { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route,
203 "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route },
204 { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route,
205 "disable defaultroute option", OPT_A2CLR,
206 &ipcp_wantoptions[0].default_route },
207 { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
208 "disable defaultroute option", OPT_ALIAS | OPT_A2CLR,
209 &ipcp_wantoptions[0].default_route },
210
211 { "replacedefaultroute", o_bool,
212 &ipcp_wantoptions[0].replace_default_route,
213 "Replace default route", 1
214 },
215 { "noreplacedefaultroute", o_bool,
216 &ipcp_allowoptions[0].replace_default_route,
217 "Never replace default route", OPT_A2COPY,
218 &ipcp_wantoptions[0].replace_default_route },
219 { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
220 "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
221 { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
222 "disable proxyarp option", OPT_A2CLR,
223 &ipcp_wantoptions[0].proxy_arp },
224 { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
225 "disable proxyarp option", OPT_ALIAS | OPT_A2CLR,
226 &ipcp_wantoptions[0].proxy_arp },
227
228 { "usepeerdns", o_bool, &usepeerdns,
229 "Ask peer for DNS address(es)", 1 },
230
231 { "netmask", o_special, (void *)setnetmask,
232 "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str },
233
234 { "ipcp-no-addresses", o_bool, &ipcp_wantoptions[0].old_addrs,
235 "Disable old-style IP-Addresses usage", OPT_A2CLR,
236 &ipcp_allowoptions[0].old_addrs },
237 { "ipcp-no-address", o_bool, &ipcp_wantoptions[0].neg_addr,
238 "Disable IP-Address usage", OPT_A2CLR,
239 &ipcp_allowoptions[0].neg_addr },
240
241 { "noremoteip", o_bool, &noremoteip,
242 "Allow peer to have no IP address", 1 },
243
244 { "nosendip", o_bool, &ipcp_wantoptions[0].neg_addr,
245 "Don't send our IP address to peer", OPT_A2CLR,
246 &ipcp_wantoptions[0].old_addrs},
247
248 { "IP addresses", o_wild, (void *) &setipaddr,
249 "set local and remote IP addresses",
250 OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr },
251
252 { NULL }
253};
254#endif /* PPP_OPTIONS */
255
256/*
257 * Protocol entry points from main code.
258 */
259static void ipcp_init(ppp_pcb *pcb);
260static void ipcp_open(ppp_pcb *pcb);
261static void ipcp_close(ppp_pcb *pcb, const char *reason);
262static void ipcp_lowerup(ppp_pcb *pcb);
263static void ipcp_lowerdown(ppp_pcb *pcb);
264static void ipcp_input(ppp_pcb *pcb, u_char *p, int len);
265static void ipcp_protrej(ppp_pcb *pcb);
266#if PRINTPKT_SUPPORT
267static int ipcp_printpkt(const u_char *p, int plen,
268 void (*printer) (void *, const char *, ...), void *arg);
269#endif /* PRINTPKT_SUPPORT */
270#if PPP_OPTIONS
271static void ip_check_options (void);
272#endif /* PPP_OPTIONS */
273#if DEMAND_SUPPORT
274static int ip_demand_conf (int);
275static int ip_active_pkt (u_char *, int);
276#endif /* DEMAND_SUPPORT */
277#if 0 /* UNUSED */
278static void create_resolv (u32_t, u32_t);
279#endif /* UNUSED */
280
281const struct protent ipcp_protent = {
282 PPP_IPCP,
283 ipcp_init,
284 ipcp_input,
285 ipcp_protrej,
286 ipcp_lowerup,
287 ipcp_lowerdown,
288 ipcp_open,
289 ipcp_close,
290#if PRINTPKT_SUPPORT
291 ipcp_printpkt,
292#endif /* PRINTPKT_SUPPORT */
293#if PPP_DATAINPUT
294 NULL,
295#endif /* PPP_DATAINPUT */
296#if PRINTPKT_SUPPORT
297 "IPCP",
298 "IP",
299#endif /* PRINTPKT_SUPPORT */
300#if PPP_OPTIONS
301 ipcp_option_list,
302 ip_check_options,
303#endif /* PPP_OPTIONS */
304#if DEMAND_SUPPORT
305 ip_demand_conf,
306 ip_active_pkt
307#endif /* DEMAND_SUPPORT */
308};
309
310static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute);
311
312/*
313 * Lengths of configuration options.
314 */
315#define CILEN_VOID 2
316#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */
317#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */
318#define CILEN_ADDR 6 /* new-style single address option */
319#define CILEN_ADDRS 10 /* old-style dual address option */
320
321
322#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
323 (x) == CONFNAK ? "NAK" : "REJ")
324
325#if 0 /* UNUSED, already defined by lwIP */
326/*
327 * Make a string representation of a network IP address.
328 */
329char *
330ip_ntoa(ipaddr)
331u32_t ipaddr;
332{
333 static char b[64];
334
335 slprintf(b, sizeof(b), "%I", ipaddr);
336 return b;
337}
338#endif /* UNUSED, already defined by lwIP */
339
340/*
341 * Option parsing.
342 */
343#if PPP_OPTIONS
344/*
345 * setvjslots - set maximum number of connection slots for VJ compression
346 */
347static int
348setvjslots(argv)
349 char **argv;
350{
351 int value;
352
353 if (!int_option(*argv, &value))
354 return 0;
355
356 if (value < 2 || value > 16) {
357 option_error("vj-max-slots value must be between 2 and 16");
358 return 0;
359 }
360 ipcp_wantoptions [0].maxslotindex =
361 ipcp_allowoptions[0].maxslotindex = value - 1;
362 slprintf(vj_value, sizeof(vj_value), "%d", value);
363 return 1;
364}
365
366/*
367 * setdnsaddr - set the dns address(es)
368 */
369static int
370setdnsaddr(argv)
371 char **argv;
372{
373 u32_t dns;
374 struct hostent *hp;
375
376 dns = inet_addr(*argv);
377 if (dns == (u32_t) -1) {
378 if ((hp = gethostbyname(*argv)) == NULL) {
379 option_error("invalid address parameter '%s' for ms-dns option",
380 *argv);
381 return 0;
382 }
383 dns = *(u32_t *)hp->h_addr;
384 }
385
386 /* We take the last 2 values given, the 2nd-last as the primary
387 and the last as the secondary. If only one is given it
388 becomes both primary and secondary. */
389 if (ipcp_allowoptions[0].dnsaddr[1] == 0)
390 ipcp_allowoptions[0].dnsaddr[0] = dns;
391 else
392 ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1];
393
394 /* always set the secondary address value. */
395 ipcp_allowoptions[0].dnsaddr[1] = dns;
396
397 return (1);
398}
399
400/*
401 * setwinsaddr - set the wins address(es)
402 * This is primrarly used with the Samba package under UNIX or for pointing
403 * the caller to the existing WINS server on a Windows NT platform.
404 */
405static int
406setwinsaddr(argv)
407 char **argv;
408{
409 u32_t wins;
410 struct hostent *hp;
411
412 wins = inet_addr(*argv);
413 if (wins == (u32_t) -1) {
414 if ((hp = gethostbyname(*argv)) == NULL) {
415 option_error("invalid address parameter '%s' for ms-wins option",
416 *argv);
417 return 0;
418 }
419 wins = *(u32_t *)hp->h_addr;
420 }
421
422 /* We take the last 2 values given, the 2nd-last as the primary
423 and the last as the secondary. If only one is given it
424 becomes both primary and secondary. */
425 if (ipcp_allowoptions[0].winsaddr[1] == 0)
426 ipcp_allowoptions[0].winsaddr[0] = wins;
427 else
428 ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1];
429
430 /* always set the secondary address value. */
431 ipcp_allowoptions[0].winsaddr[1] = wins;
432
433 return (1);
434}
435
436/*
437 * setipaddr - Set the IP address
438 * If doit is 0, the call is to check whether this option is
439 * potentially an IP address specification.
440 * Not static so that plugins can call it to set the addresses
441 */
442int
443setipaddr(arg, argv, doit)
444 char *arg;
445 char **argv;
446 int doit;
447{
448 struct hostent *hp;
449 char *colon;
450 u32_t local, remote;
451 ipcp_options *wo = &ipcp_wantoptions[0];
452 static int prio_local = 0, prio_remote = 0;
453
454 /*
455 * IP address pair separated by ":".
456 */
457 if ((colon = strchr(arg, ':')) == NULL)
458 return 0;
459 if (!doit)
460 return 1;
461
462 /*
463 * If colon first character, then no local addr.
464 */
465 if (colon != arg && option_priority >= prio_local) {
466 *colon = '\0';
467 if ((local = inet_addr(arg)) == (u32_t) -1) {
468 if ((hp = gethostbyname(arg)) == NULL) {
469 option_error("unknown host: %s", arg);
470 return 0;
471 }
472 local = *(u32_t *)hp->h_addr;
473 }
474 if (bad_ip_adrs(local)) {
475 option_error("bad local IP address %s", ip_ntoa(local));
476 return 0;
477 }
478 if (local != 0)
479 wo->ouraddr = local;
480 *colon = ':';
481 prio_local = option_priority;
482 }
483
484 /*
485 * If colon last character, then no remote addr.
486 */
487 if (*++colon != '\0' && option_priority >= prio_remote) {
488 if ((remote = inet_addr(colon)) == (u32_t) -1) {
489 if ((hp = gethostbyname(colon)) == NULL) {
490 option_error("unknown host: %s", colon);
491 return 0;
492 }
493 remote = *(u32_t *)hp->h_addr;
494 if (remote_name[0] == 0)
495 strlcpy(remote_name, colon, sizeof(remote_name));
496 }
497 if (bad_ip_adrs(remote)) {
498 option_error("bad remote IP address %s", ip_ntoa(remote));
499 return 0;
500 }
501 if (remote != 0)
502 wo->hisaddr = remote;
503 prio_remote = option_priority;
504 }
505
506 return 1;
507}
508
509static void
510printipaddr(opt, printer, arg)
511 option_t *opt;
512 void (*printer) (void *, char *, ...);
513 void *arg;
514{
515 ipcp_options *wo = &ipcp_wantoptions[0];
516
517 if (wo->ouraddr != 0)
518 printer(arg, "%I", wo->ouraddr);
519 printer(arg, ":");
520 if (wo->hisaddr != 0)
521 printer(arg, "%I", wo->hisaddr);
522}
523
524/*
525 * setnetmask - set the netmask to be used on the interface.
526 */
527static int
528setnetmask(argv)
529 char **argv;
530{
531 u32_t mask;
532 int n;
533 char *p;
534
535 /*
536 * Unfortunately, if we use inet_addr, we can't tell whether
537 * a result of all 1s is an error or a valid 255.255.255.255.
538 */
539 p = *argv;
540 n = parse_dotted_ip(p, &mask);
541
543
544 if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) {
545 option_error("invalid netmask value '%s'", *argv);
546 return 0;
547 }
548
549 netmask = mask;
550 slprintf(netmask_str, sizeof(netmask_str), "%I", mask);
551
552 return (1);
553}
554
555int
556parse_dotted_ip(p, vp)
557 char *p;
558 u32_t *vp;
559{
560 int n;
561 u32_t v, b;
562 char *endp, *p0 = p;
563
564 v = 0;
565 for (n = 3;; --n) {
566 b = strtoul(p, &endp, 0);
567 if (endp == p)
568 return 0;
569 if (b > 255) {
570 if (n < 3)
571 return 0;
572 /* accept e.g. 0xffffff00 */
573 *vp = b;
574 return endp - p0;
575 }
576 v |= b << (n * 8);
577 p = endp;
578 if (n == 0)
579 break;
580 if (*p != '.')
581 return 0;
582 ++p;
583 }
584 *vp = v;
585 return p - p0;
586}
587#endif /* PPP_OPTIONS */
588
589/*
590 * ipcp_init - Initialize IPCP.
591 */
592static void ipcp_init(ppp_pcb *pcb) {
593 fsm *f = &pcb->ipcp_fsm;
594
595 ipcp_options *wo = &pcb->ipcp_wantoptions;
596 ipcp_options *ao = &pcb->ipcp_allowoptions;
597
598 f->pcb = pcb;
599 f->protocol = PPP_IPCP;
600 f->callbacks = &ipcp_callbacks;
601 fsm_init(f);
602
603 /*
604 * Some 3G modems use repeated IPCP NAKs as a way of stalling
605 * until they can contact a server on the network, so we increase
606 * the default number of NAKs we accept before we start treating
607 * them as rejects.
608 */
609 f->maxnakloops = 100;
610
611#if 0 /* Not necessary, everything is cleared in ppp_new() */
612 memset(wo, 0, sizeof(*wo));
613 memset(ao, 0, sizeof(*ao));
614#endif /* 0 */
615
616 wo->neg_addr = wo->old_addrs = 1;
617#if VJ_SUPPORT
618 wo->neg_vj = 1;
619 wo->vj_protocol = IPCP_VJ_COMP;
620 wo->maxslotindex = MAX_STATES - 1; /* really max index */
621 wo->cflag = 1;
622#endif /* VJ_SUPPORT */
623
624#if 0 /* UNUSED */
625 /* wanting default route by default */
626 wo->default_route = 1;
627#endif /* UNUSED */
628
629 ao->neg_addr = ao->old_addrs = 1;
630#if VJ_SUPPORT
631 /* max slots and slot-id compression are currently hardwired in */
632 /* ppp_if.c to 16 and 1, this needs to be changed (among other */
633 /* things) gmc */
634
635 ao->neg_vj = 1;
636 ao->maxslotindex = MAX_STATES - 1;
637 ao->cflag = 1;
638#endif /* #if VJ_SUPPORT */
639
640#if 0 /* UNUSED */
641 /*
642 * XXX These control whether the user may use the proxyarp
643 * and defaultroute options.
644 */
645 ao->proxy_arp = 1;
646 ao->default_route = 1;
647#endif /* UNUSED */
648}
649
650
651/*
652 * ipcp_open - IPCP is allowed to come up.
653 */
654static void ipcp_open(ppp_pcb *pcb) {
655 fsm *f = &pcb->ipcp_fsm;
656 fsm_open(f);
657 pcb->ipcp_is_open = 1;
658}
659
660
661/*
662 * ipcp_close - Take IPCP down.
663 */
664static void ipcp_close(ppp_pcb *pcb, const char *reason) {
665 fsm *f = &pcb->ipcp_fsm;
666 fsm_close(f, reason);
667}
668
669
670/*
671 * ipcp_lowerup - The lower layer is up.
672 */
673static void ipcp_lowerup(ppp_pcb *pcb) {
674 fsm *f = &pcb->ipcp_fsm;
675 fsm_lowerup(f);
676}
677
678
679/*
680 * ipcp_lowerdown - The lower layer is down.
681 */
682static void ipcp_lowerdown(ppp_pcb *pcb) {
683 fsm *f = &pcb->ipcp_fsm;
684 fsm_lowerdown(f);
685}
686
687
688/*
689 * ipcp_input - Input IPCP packet.
690 */
691static void ipcp_input(ppp_pcb *pcb, u_char *p, int len) {
692 fsm *f = &pcb->ipcp_fsm;
693 fsm_input(f, p, len);
694}
695
696
697/*
698 * ipcp_protrej - A Protocol-Reject was received for IPCP.
699 *
700 * Pretend the lower layer went down, so we shut up.
701 */
702static void ipcp_protrej(ppp_pcb *pcb) {
703 fsm *f = &pcb->ipcp_fsm;
704 fsm_lowerdown(f);
705}
706
707
708/*
709 * ipcp_resetci - Reset our CI.
710 * Called by fsm_sconfreq, Send Configure Request.
711 */
712static void ipcp_resetci(fsm *f) {
713 ppp_pcb *pcb = f->pcb;
714 ipcp_options *wo = &pcb->ipcp_wantoptions;
715 ipcp_options *go = &pcb->ipcp_gotoptions;
716 ipcp_options *ao = &pcb->ipcp_allowoptions;
717
718 wo->req_addr = (wo->neg_addr || wo->old_addrs) &&
719 (ao->neg_addr || ao->old_addrs);
720 if (wo->ouraddr == 0)
721 wo->accept_local = 1;
722 if (wo->hisaddr == 0)
723 wo->accept_remote = 1;
724#if LWIP_DNS
725 wo->req_dns1 = wo->req_dns2 = pcb->settings.usepeerdns; /* Request DNS addresses from the peer */
726#endif /* LWIP_DNS */
727 *go = *wo;
728 if (!pcb->ask_for_local)
729 go->ouraddr = 0;
730#if 0 /* UNUSED */
731 if (ip_choose_hook) {
732 ip_choose_hook(&wo->hisaddr);
733 if (wo->hisaddr) {
734 wo->accept_remote = 0;
735 }
736 }
737#endif /* UNUSED */
738 BZERO(&pcb->ipcp_hisoptions, sizeof(ipcp_options));
739}
740
741
742/*
743 * ipcp_cilen - Return length of our CI.
744 * Called by fsm_sconfreq, Send Configure Request.
745 */
746static int ipcp_cilen(fsm *f) {
747 ppp_pcb *pcb = f->pcb;
748 ipcp_options *go = &pcb->ipcp_gotoptions;
749#if VJ_SUPPORT
750 ipcp_options *wo = &pcb->ipcp_wantoptions;
751#endif /* VJ_SUPPORT */
752 ipcp_options *ho = &pcb->ipcp_hisoptions;
753
754#define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0)
755#if VJ_SUPPORT
756#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
757#endif /* VJ_SUPPORT */
758#define LENCIADDR(neg) (neg ? CILEN_ADDR : 0)
759#if LWIP_DNS
760#define LENCIDNS(neg) LENCIADDR(neg)
761#endif /* LWIP_DNS */
762#if 0 /* UNUSED - WINS */
763#define LENCIWINS(neg) LENCIADDR(neg)
764#endif /* UNUSED - WINS */
765
766 /*
767 * First see if we want to change our options to the old
768 * forms because we have received old forms from the peer.
769 */
770 if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs)
771 go->neg_addr = 0;
772
773#if VJ_SUPPORT
774 if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
775 /* try an older style of VJ negotiation */
776 /* use the old style only if the peer did */
777 if (ho->neg_vj && ho->old_vj) {
778 go->neg_vj = 1;
779 go->old_vj = 1;
780 go->vj_protocol = ho->vj_protocol;
781 }
782 }
783#endif /* VJ_SUPPORT */
784
785 return (LENCIADDRS(!go->neg_addr && go->old_addrs) +
786#if VJ_SUPPORT
787 LENCIVJ(go->neg_vj, go->old_vj) +
788#endif /* VJ_SUPPORT */
789 LENCIADDR(go->neg_addr) +
790#if LWIP_DNS
791 LENCIDNS(go->req_dns1) +
792 LENCIDNS(go->req_dns2) +
793#endif /* LWIP_DNS */
794#if 0 /* UNUSED - WINS */
795 LENCIWINS(go->winsaddr[0]) +
796 LENCIWINS(go->winsaddr[1]) +
797#endif /* UNUSED - WINS */
798 0);
799}
800
801
802/*
803 * ipcp_addci - Add our desired CIs to a packet.
804 * Called by fsm_sconfreq, Send Configure Request.
805 */
806static void ipcp_addci(fsm *f, u_char *ucp, int *lenp) {
807 ppp_pcb *pcb = f->pcb;
808 ipcp_options *go = &pcb->ipcp_gotoptions;
809 int len = *lenp;
810
811#define ADDCIADDRS(opt, neg, val1, val2) \
812 if (neg) { \
813 if (len >= CILEN_ADDRS) { \
814 u32_t l; \
815 PUTCHAR(opt, ucp); \
816 PUTCHAR(CILEN_ADDRS, ucp); \
817 l = lwip_ntohl(val1); \
818 PUTLONG(l, ucp); \
819 l = lwip_ntohl(val2); \
820 PUTLONG(l, ucp); \
821 len -= CILEN_ADDRS; \
822 } else \
823 go->old_addrs = 0; \
824 }
825
826#if VJ_SUPPORT
827#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
828 if (neg) { \
829 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
830 if (len >= vjlen) { \
831 PUTCHAR(opt, ucp); \
832 PUTCHAR(vjlen, ucp); \
833 PUTSHORT(val, ucp); \
834 if (!old) { \
835 PUTCHAR(maxslotindex, ucp); \
836 PUTCHAR(cflag, ucp); \
837 } \
838 len -= vjlen; \
839 } else \
840 neg = 0; \
841 }
842#endif /* VJ_SUPPORT */
843
844#define ADDCIADDR(opt, neg, val) \
845 if (neg) { \
846 if (len >= CILEN_ADDR) { \
847 u32_t l; \
848 PUTCHAR(opt, ucp); \
849 PUTCHAR(CILEN_ADDR, ucp); \
850 l = lwip_ntohl(val); \
851 PUTLONG(l, ucp); \
852 len -= CILEN_ADDR; \
853 } else \
854 neg = 0; \
855 }
856
857#if LWIP_DNS
858#define ADDCIDNS(opt, neg, addr) \
859 if (neg) { \
860 if (len >= CILEN_ADDR) { \
861 u32_t l; \
862 PUTCHAR(opt, ucp); \
863 PUTCHAR(CILEN_ADDR, ucp); \
864 l = lwip_ntohl(addr); \
865 PUTLONG(l, ucp); \
866 len -= CILEN_ADDR; \
867 } else \
868 neg = 0; \
869 }
870#endif /* LWIP_DNS */
871
872#if 0 /* UNUSED - WINS */
873#define ADDCIWINS(opt, addr) \
874 if (addr) { \
875 if (len >= CILEN_ADDR) { \
876 u32_t l; \
877 PUTCHAR(opt, ucp); \
878 PUTCHAR(CILEN_ADDR, ucp); \
879 l = lwip_ntohl(addr); \
880 PUTLONG(l, ucp); \
881 len -= CILEN_ADDR; \
882 } else \
883 addr = 0; \
884 }
885#endif /* UNUSED - WINS */
886
887 ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
888 go->hisaddr);
889
890#if VJ_SUPPORT
891 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
892 go->maxslotindex, go->cflag);
893#endif /* VJ_SUPPORT */
894
895 ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr);
896
897#if LWIP_DNS
898 ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
899
900 ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
901#endif /* LWIP_DNS */
902
903#if 0 /* UNUSED - WINS */
904 ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]);
905
906 ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]);
907#endif /* UNUSED - WINS */
908
909 *lenp -= len;
910}
911
912
913/*
914 * ipcp_ackci - Ack our CIs.
915 * Called by fsm_rconfack, Receive Configure ACK.
916 *
917 * Returns:
918 * 0 - Ack was bad.
919 * 1 - Ack was good.
920 */
921static int ipcp_ackci(fsm *f, u_char *p, int len) {
922 ppp_pcb *pcb = f->pcb;
923 ipcp_options *go = &pcb->ipcp_gotoptions;
924 u_short cilen, citype;
925 u32_t cilong;
926#if VJ_SUPPORT
927 u_short cishort;
928 u_char cimaxslotindex, cicflag;
929#endif /* VJ_SUPPORT */
930
931 /*
932 * CIs must be in exactly the same order that we sent...
933 * Check packet length and CI length at each step.
934 * If we find any deviations, then this packet is bad.
935 */
936
937#define ACKCIADDRS(opt, neg, val1, val2) \
938 if (neg) { \
939 u32_t l; \
940 if ((len -= CILEN_ADDRS) < 0) \
941 goto bad; \
942 GETCHAR(citype, p); \
943 GETCHAR(cilen, p); \
944 if (cilen != CILEN_ADDRS || \
945 citype != opt) \
946 goto bad; \
947 GETLONG(l, p); \
948 cilong = lwip_htonl(l); \
949 if (val1 != cilong) \
950 goto bad; \
951 GETLONG(l, p); \
952 cilong = lwip_htonl(l); \
953 if (val2 != cilong) \
954 goto bad; \
955 }
956
957#if VJ_SUPPORT
958#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
959 if (neg) { \
960 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
961 if ((len -= vjlen) < 0) \
962 goto bad; \
963 GETCHAR(citype, p); \
964 GETCHAR(cilen, p); \
965 if (cilen != vjlen || \
966 citype != opt) \
967 goto bad; \
968 GETSHORT(cishort, p); \
969 if (cishort != val) \
970 goto bad; \
971 if (!old) { \
972 GETCHAR(cimaxslotindex, p); \
973 if (cimaxslotindex != maxslotindex) \
974 goto bad; \
975 GETCHAR(cicflag, p); \
976 if (cicflag != cflag) \
977 goto bad; \
978 } \
979 }
980#endif /* VJ_SUPPORT */
981
982#define ACKCIADDR(opt, neg, val) \
983 if (neg) { \
984 u32_t l; \
985 if ((len -= CILEN_ADDR) < 0) \
986 goto bad; \
987 GETCHAR(citype, p); \
988 GETCHAR(cilen, p); \
989 if (cilen != CILEN_ADDR || \
990 citype != opt) \
991 goto bad; \
992 GETLONG(l, p); \
993 cilong = lwip_htonl(l); \
994 if (val != cilong) \
995 goto bad; \
996 }
997
998#if LWIP_DNS
999#define ACKCIDNS(opt, neg, addr) \
1000 if (neg) { \
1001 u32_t l; \
1002 if ((len -= CILEN_ADDR) < 0) \
1003 goto bad; \
1004 GETCHAR(citype, p); \
1005 GETCHAR(cilen, p); \
1006 if (cilen != CILEN_ADDR || citype != opt) \
1007 goto bad; \
1008 GETLONG(l, p); \
1009 cilong = lwip_htonl(l); \
1010 if (addr != cilong) \
1011 goto bad; \
1012 }
1013#endif /* LWIP_DNS */
1014
1015#if 0 /* UNUSED - WINS */
1016#define ACKCIWINS(opt, addr) \
1017 if (addr) { \
1018 u32_t l; \
1019 if ((len -= CILEN_ADDR) < 0) \
1020 goto bad; \
1021 GETCHAR(citype, p); \
1022 GETCHAR(cilen, p); \
1023 if (cilen != CILEN_ADDR || citype != opt) \
1024 goto bad; \
1025 GETLONG(l, p); \
1026 cilong = lwip_htonl(l); \
1027 if (addr != cilong) \
1028 goto bad; \
1029 }
1030#endif /* UNUSED - WINS */
1031
1032 ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
1033 go->hisaddr);
1034
1035#if VJ_SUPPORT
1036 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
1037 go->maxslotindex, go->cflag);
1038#endif /* VJ_SUPPORT */
1039
1040 ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr);
1041
1042#if LWIP_DNS
1043 ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
1044
1045 ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
1046#endif /* LWIP_DNS */
1047
1048#if 0 /* UNUSED - WINS */
1049 ACKCIWINS(CI_MS_WINS1, go->winsaddr[0]);
1050
1051 ACKCIWINS(CI_MS_WINS2, go->winsaddr[1]);
1052#endif /* UNUSED - WINS */
1053
1054 /*
1055 * If there are any remaining CIs, then this packet is bad.
1056 */
1057 if (len != 0)
1058 goto bad;
1059 return (1);
1060
1061bad:
1062 IPCPDEBUG(("ipcp_ackci: received bad Ack!"));
1063 return (0);
1064}
1065
1066/*
1067 * ipcp_nakci - Peer has sent a NAK for some of our CIs.
1068 * This should not modify any state if the Nak is bad
1069 * or if IPCP is in the OPENED state.
1070 * Callback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
1071 *
1072 * Returns:
1073 * 0 - Nak was bad.
1074 * 1 - Nak was good.
1075 */
1076static int ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject) {
1077 ppp_pcb *pcb = f->pcb;
1078 ipcp_options *go = &pcb->ipcp_gotoptions;
1079 u_char citype, cilen, *next;
1080#if VJ_SUPPORT
1081 u_char cimaxslotindex, cicflag;
1082 u_short cishort;
1083#endif /* VJ_SUPPORT */
1084 u32_t ciaddr1, ciaddr2, l;
1085#if LWIP_DNS
1086 u32_t cidnsaddr;
1087#endif /* LWIP_DNS */
1088 ipcp_options no; /* options we've seen Naks for */
1089 ipcp_options try_; /* options to request next time */
1090
1091 BZERO(&no, sizeof(no));
1092 try_ = *go;
1093
1094 /*
1095 * Any Nak'd CIs must be in exactly the same order that we sent.
1096 * Check packet length and CI length at each step.
1097 * If we find any deviations, then this packet is bad.
1098 */
1099#define NAKCIADDRS(opt, neg, code) \
1100 if ((neg) && \
1101 (cilen = p[1]) == CILEN_ADDRS && \
1102 len >= cilen && \
1103 p[0] == opt) { \
1104 len -= cilen; \
1105 INCPTR(2, p); \
1106 GETLONG(l, p); \
1107 ciaddr1 = lwip_htonl(l); \
1108 GETLONG(l, p); \
1109 ciaddr2 = lwip_htonl(l); \
1110 no.old_addrs = 1; \
1111 code \
1112 }
1113
1114#if VJ_SUPPORT
1115#define NAKCIVJ(opt, neg, code) \
1116 if (go->neg && \
1117 ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
1118 len >= cilen && \
1119 p[0] == opt) { \
1120 len -= cilen; \
1121 INCPTR(2, p); \
1122 GETSHORT(cishort, p); \
1123 no.neg = 1; \
1124 code \
1125 }
1126#endif /* VJ_SUPPORT */
1127
1128#define NAKCIADDR(opt, neg, code) \
1129 if (go->neg && \
1130 (cilen = p[1]) == CILEN_ADDR && \
1131 len >= cilen && \
1132 p[0] == opt) { \
1133 len -= cilen; \
1134 INCPTR(2, p); \
1135 GETLONG(l, p); \
1136 ciaddr1 = lwip_htonl(l); \
1137 no.neg = 1; \
1138 code \
1139 }
1140
1141#if LWIP_DNS
1142#define NAKCIDNS(opt, neg, code) \
1143 if (go->neg && \
1144 ((cilen = p[1]) == CILEN_ADDR) && \
1145 len >= cilen && \
1146 p[0] == opt) { \
1147 len -= cilen; \
1148 INCPTR(2, p); \
1149 GETLONG(l, p); \
1150 cidnsaddr = lwip_htonl(l); \
1151 no.neg = 1; \
1152 code \
1153 }
1154#endif /* LWIP_DNS */
1155
1156 /*
1157 * Accept the peer's idea of {our,his} address, if different
1158 * from our idea, only if the accept_{local,remote} flag is set.
1159 */
1160 NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
1161 if (treat_as_reject) {
1162 try_.old_addrs = 0;
1163 } else {
1164 if (go->accept_local && ciaddr1) {
1165 /* take his idea of our address */
1166 try_.ouraddr = ciaddr1;
1167 }
1168 if (go->accept_remote && ciaddr2) {
1169 /* take his idea of his address */
1170 try_.hisaddr = ciaddr2;
1171 }
1172 }
1173 );
1174
1175#if VJ_SUPPORT
1176 /*
1177 * Accept the peer's value of maxslotindex provided that it
1178 * is less than what we asked for. Turn off slot-ID compression
1179 * if the peer wants. Send old-style compress-type option if
1180 * the peer wants.
1181 */
1182 NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
1183 if (treat_as_reject) {
1184 try_.neg_vj = 0;
1185 } else if (cilen == CILEN_VJ) {
1186 GETCHAR(cimaxslotindex, p);
1187 GETCHAR(cicflag, p);
1188 if (cishort == IPCP_VJ_COMP) {
1189 try_.old_vj = 0;
1190 if (cimaxslotindex < go->maxslotindex)
1191 try_.maxslotindex = cimaxslotindex;
1192 if (!cicflag)
1193 try_.cflag = 0;
1194 } else {
1195 try_.neg_vj = 0;
1196 }
1197 } else {
1198 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
1199 try_.old_vj = 1;
1200 try_.vj_protocol = cishort;
1201 } else {
1202 try_.neg_vj = 0;
1203 }
1204 }
1205 );
1206#endif /* VJ_SUPPORT */
1207
1208 NAKCIADDR(CI_ADDR, neg_addr,
1209 if (treat_as_reject) {
1210 try_.neg_addr = 0;
1211 try_.old_addrs = 0;
1212 } else if (go->accept_local && ciaddr1) {
1213 /* take his idea of our address */
1214 try_.ouraddr = ciaddr1;
1215 }
1216 );
1217
1218#if LWIP_DNS
1219 NAKCIDNS(CI_MS_DNS1, req_dns1,
1220 if (treat_as_reject) {
1221 try_.req_dns1 = 0;
1222 } else {
1223 try_.dnsaddr[0] = cidnsaddr;
1224 }
1225 );
1226
1227 NAKCIDNS(CI_MS_DNS2, req_dns2,
1228 if (treat_as_reject) {
1229 try_.req_dns2 = 0;
1230 } else {
1231 try_.dnsaddr[1] = cidnsaddr;
1232 }
1233 );
1234#endif /* #if LWIP_DNS */
1235
1236 /*
1237 * There may be remaining CIs, if the peer is requesting negotiation
1238 * on an option that we didn't include in our request packet.
1239 * If they want to negotiate about IP addresses, we comply.
1240 * If they want us to ask for compression, we refuse.
1241 * If they want us to ask for ms-dns, we do that, since some
1242 * peers get huffy if we don't.
1243 */
1244 while (len >= CILEN_VOID) {
1245 GETCHAR(citype, p);
1246 GETCHAR(cilen, p);
1247 if ( cilen < CILEN_VOID || (len -= cilen) < 0 )
1248 goto bad;
1249 next = p + cilen - 2;
1250
1251 switch (citype) {
1252#if VJ_SUPPORT
1253 case CI_COMPRESSTYPE:
1254 if (go->neg_vj || no.neg_vj ||
1255 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
1256 goto bad;
1257 no.neg_vj = 1;
1258 break;
1259#endif /* VJ_SUPPORT */
1260 case CI_ADDRS:
1261 if ((!go->neg_addr && go->old_addrs) || no.old_addrs
1262 || cilen != CILEN_ADDRS)
1263 goto bad;
1264 try_.neg_addr = 0;
1265 GETLONG(l, p);
1266 ciaddr1 = lwip_htonl(l);
1267 if (ciaddr1 && go->accept_local)
1268 try_.ouraddr = ciaddr1;
1269 GETLONG(l, p);
1270 ciaddr2 = lwip_htonl(l);
1271 if (ciaddr2 && go->accept_remote)
1272 try_.hisaddr = ciaddr2;
1273 no.old_addrs = 1;
1274 break;
1275 case CI_ADDR:
1276 if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
1277 goto bad;
1278 try_.old_addrs = 0;
1279 GETLONG(l, p);
1280 ciaddr1 = lwip_htonl(l);
1281 if (ciaddr1 && go->accept_local)
1282 try_.ouraddr = ciaddr1;
1283 if (try_.ouraddr != 0)
1284 try_.neg_addr = 1;
1285 no.neg_addr = 1;
1286 break;
1287#if LWIP_DNS
1288 case CI_MS_DNS1:
1289 if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR)
1290 goto bad;
1291 GETLONG(l, p);
1292 try_.dnsaddr[0] = lwip_htonl(l);
1293 try_.req_dns1 = 1;
1294 no.req_dns1 = 1;
1295 break;
1296 case CI_MS_DNS2:
1297 if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR)
1298 goto bad;
1299 GETLONG(l, p);
1300 try_.dnsaddr[1] = lwip_htonl(l);
1301 try_.req_dns2 = 1;
1302 no.req_dns2 = 1;
1303 break;
1304#endif /* LWIP_DNS */
1305#if 0 /* UNUSED - WINS */
1306 case CI_MS_WINS1:
1307 case CI_MS_WINS2:
1308 if (cilen != CILEN_ADDR)
1309 goto bad;
1310 GETLONG(l, p);
1311 ciaddr1 = lwip_htonl(l);
1312 if (ciaddr1)
1313 try_.winsaddr[citype == CI_MS_WINS2] = ciaddr1;
1314 break;
1315#endif /* UNUSED - WINS */
1316 default:
1317 break;
1318 }
1319 p = next;
1320 }
1321
1322 /*
1323 * OK, the Nak is good. Now we can update state.
1324 * If there are any remaining options, we ignore them.
1325 */
1326 if (f->state != PPP_FSM_OPENED)
1327 *go = try_;
1328
1329 return 1;
1330
1331bad:
1332 IPCPDEBUG(("ipcp_nakci: received bad Nak!"));
1333 return 0;
1334}
1335
1336
1337/*
1338 * ipcp_rejci - Reject some of our CIs.
1339 * Callback from fsm_rconfnakrej.
1340 */
1341static int ipcp_rejci(fsm *f, u_char *p, int len) {
1342 ppp_pcb *pcb = f->pcb;
1343 ipcp_options *go = &pcb->ipcp_gotoptions;
1344 u_char cilen;
1345#if VJ_SUPPORT
1346 u_char cimaxslotindex, ciflag;
1347 u_short cishort;
1348#endif /* VJ_SUPPORT */
1349 u32_t cilong;
1350 ipcp_options try_; /* options to request next time */
1351
1352 try_ = *go;
1353 /*
1354 * Any Rejected CIs must be in exactly the same order that we sent.
1355 * Check packet length and CI length at each step.
1356 * If we find any deviations, then this packet is bad.
1357 */
1358#define REJCIADDRS(opt, neg, val1, val2) \
1359 if ((neg) && \
1360 (cilen = p[1]) == CILEN_ADDRS && \
1361 len >= cilen && \
1362 p[0] == opt) { \
1363 u32_t l; \
1364 len -= cilen; \
1365 INCPTR(2, p); \
1366 GETLONG(l, p); \
1367 cilong = lwip_htonl(l); \
1368 /* Check rejected value. */ \
1369 if (cilong != val1) \
1370 goto bad; \
1371 GETLONG(l, p); \
1372 cilong = lwip_htonl(l); \
1373 /* Check rejected value. */ \
1374 if (cilong != val2) \
1375 goto bad; \
1376 try_.old_addrs = 0; \
1377 }
1378
1379#if VJ_SUPPORT
1380#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
1381 if (go->neg && \
1382 p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
1383 len >= p[1] && \
1384 p[0] == opt) { \
1385 len -= p[1]; \
1386 INCPTR(2, p); \
1387 GETSHORT(cishort, p); \
1388 /* Check rejected value. */ \
1389 if (cishort != val) \
1390 goto bad; \
1391 if (!old) { \
1392 GETCHAR(cimaxslotindex, p); \
1393 if (cimaxslotindex != maxslot) \
1394 goto bad; \
1395 GETCHAR(ciflag, p); \
1396 if (ciflag != cflag) \
1397 goto bad; \
1398 } \
1399 try_.neg = 0; \
1400 }
1401#endif /* VJ_SUPPORT */
1402
1403#define REJCIADDR(opt, neg, val) \
1404 if (go->neg && \
1405 (cilen = p[1]) == CILEN_ADDR && \
1406 len >= cilen && \
1407 p[0] == opt) { \
1408 u32_t l; \
1409 len -= cilen; \
1410 INCPTR(2, p); \
1411 GETLONG(l, p); \
1412 cilong = lwip_htonl(l); \
1413 /* Check rejected value. */ \
1414 if (cilong != val) \
1415 goto bad; \
1416 try_.neg = 0; \
1417 }
1418
1419#if LWIP_DNS
1420#define REJCIDNS(opt, neg, dnsaddr) \
1421 if (go->neg && \
1422 ((cilen = p[1]) == CILEN_ADDR) && \
1423 len >= cilen && \
1424 p[0] == opt) { \
1425 u32_t l; \
1426 len -= cilen; \
1427 INCPTR(2, p); \
1428 GETLONG(l, p); \
1429 cilong = lwip_htonl(l); \
1430 /* Check rejected value. */ \
1431 if (cilong != dnsaddr) \
1432 goto bad; \
1433 try_.neg = 0; \
1434 }
1435#endif /* LWIP_DNS */
1436
1437#if 0 /* UNUSED - WINS */
1438#define REJCIWINS(opt, addr) \
1439 if (addr && \
1440 ((cilen = p[1]) == CILEN_ADDR) && \
1441 len >= cilen && \
1442 p[0] == opt) { \
1443 u32_t l; \
1444 len -= cilen; \
1445 INCPTR(2, p); \
1446 GETLONG(l, p); \
1447 cilong = lwip_htonl(l); \
1448 /* Check rejected value. */ \
1449 if (cilong != addr) \
1450 goto bad; \
1451 try_.winsaddr[opt == CI_MS_WINS2] = 0; \
1452 }
1453#endif /* UNUSED - WINS */
1454
1455 REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
1456 go->ouraddr, go->hisaddr);
1457
1458#if VJ_SUPPORT
1459 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
1460 go->maxslotindex, go->cflag);
1461#endif /* VJ_SUPPORT */
1462
1463 REJCIADDR(CI_ADDR, neg_addr, go->ouraddr);
1464
1465#if LWIP_DNS
1466 REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
1467
1468 REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
1469#endif /* LWIP_DNS */
1470
1471#if 0 /* UNUSED - WINS */
1472 REJCIWINS(CI_MS_WINS1, go->winsaddr[0]);
1473
1474 REJCIWINS(CI_MS_WINS2, go->winsaddr[1]);
1475#endif /* UNUSED - WINS */
1476
1477 /*
1478 * If there are any remaining CIs, then this packet is bad.
1479 */
1480 if (len != 0)
1481 goto bad;
1482 /*
1483 * Now we can update state.
1484 */
1485 if (f->state != PPP_FSM_OPENED)
1486 *go = try_;
1487 return 1;
1488
1489bad:
1490 IPCPDEBUG(("ipcp_rejci: received bad Reject!"));
1491 return 0;
1492}
1493
1494
1495/*
1496 * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
1497 * Callback from fsm_rconfreq, Receive Configure Request
1498 *
1499 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
1500 * appropriately. If reject_if_disagree is non-zero, doesn't return
1501 * CONFNAK; returns CONFREJ if it can't return CONFACK.
1502 *
1503 * inp = Requested CIs
1504 * len = Length of requested CIs
1505 */
1506static int ipcp_reqci(fsm *f, u_char *inp, int *len, int reject_if_disagree) {
1507 ppp_pcb *pcb = f->pcb;
1508 ipcp_options *wo = &pcb->ipcp_wantoptions;
1509 ipcp_options *ho = &pcb->ipcp_hisoptions;
1510 ipcp_options *ao = &pcb->ipcp_allowoptions;
1511 u_char *cip, *next; /* Pointer to current and next CIs */
1512 u_short cilen, citype; /* Parsed len, type */
1513#if VJ_SUPPORT
1514 u_short cishort; /* Parsed short value */
1515#endif /* VJ_SUPPORT */
1516 u32_t tl, ciaddr1, ciaddr2;/* Parsed address values */
1517 int rc = CONFACK; /* Final packet return code */
1518 int orc; /* Individual option return code */
1519 u_char *p; /* Pointer to next char to parse */
1520 u_char *ucp = inp; /* Pointer to current output char */
1521 int l = *len; /* Length left */
1522#if VJ_SUPPORT
1523 u_char maxslotindex, cflag;
1524#endif /* VJ_SUPPORT */
1525#if LWIP_DNS
1526 int d;
1527#endif /* LWIP_DNS */
1528
1529 /*
1530 * Reset all his options.
1531 */
1532 BZERO(ho, sizeof(*ho));
1533
1534 /*
1535 * Process all his options.
1536 */
1537 next = inp;
1538 while (l) {
1539 orc = CONFACK; /* Assume success */
1540 cip = p = next; /* Remember beginning of CI */
1541 if (l < 2 || /* Not enough data for CI header or */
1542 p[1] < 2 || /* CI length too small or */
1543 p[1] > l) { /* CI length too big? */
1544 IPCPDEBUG(("ipcp_reqci: bad CI length!"));
1545 orc = CONFREJ; /* Reject bad CI */
1546 cilen = l; /* Reject till end of packet */
1547 l = 0; /* Don't loop again */
1548 goto endswitch;
1549 }
1550 GETCHAR(citype, p); /* Parse CI type */
1551 GETCHAR(cilen, p); /* Parse CI length */
1552 l -= cilen; /* Adjust remaining length */
1553 next += cilen; /* Step to next CI */
1554
1555 switch (citype) { /* Check CI type */
1556 case CI_ADDRS:
1557 if (!ao->old_addrs || ho->neg_addr ||
1558 cilen != CILEN_ADDRS) { /* Check CI length */
1559 orc = CONFREJ; /* Reject CI */
1560 break;
1561 }
1562
1563 /*
1564 * If he has no address, or if we both have his address but
1565 * disagree about it, then NAK it with our idea.
1566 * In particular, if we don't know his address, but he does,
1567 * then accept it.
1568 */
1569 GETLONG(tl, p); /* Parse source address (his) */
1570 ciaddr1 = lwip_htonl(tl);
1571 if (ciaddr1 != wo->hisaddr
1572 && (ciaddr1 == 0 || !wo->accept_remote)) {
1573 orc = CONFNAK;
1574 if (!reject_if_disagree) {
1575 DECPTR(sizeof(u32_t), p);
1576 tl = lwip_ntohl(wo->hisaddr);
1577 PUTLONG(tl, p);
1578 }
1579 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1580 /*
1581 * If neither we nor he knows his address, reject the option.
1582 */
1583 orc = CONFREJ;
1584 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
1585 break;
1586 }
1587
1588 /*
1589 * If he doesn't know our address, or if we both have our address
1590 * but disagree about it, then NAK it with our idea.
1591 */
1592 GETLONG(tl, p); /* Parse destination address (ours) */
1593 ciaddr2 = lwip_htonl(tl);
1594 if (ciaddr2 != wo->ouraddr) {
1595 if (ciaddr2 == 0 || !wo->accept_local) {
1596 orc = CONFNAK;
1597 if (!reject_if_disagree) {
1598 DECPTR(sizeof(u32_t), p);
1599 tl = lwip_ntohl(wo->ouraddr);
1600 PUTLONG(tl, p);
1601 }
1602 } else {
1603 wo->ouraddr = ciaddr2; /* accept peer's idea */
1604 }
1605 }
1606
1607 ho->old_addrs = 1;
1608 ho->hisaddr = ciaddr1;
1609 ho->ouraddr = ciaddr2;
1610 break;
1611
1612 case CI_ADDR:
1613 if (!ao->neg_addr || ho->old_addrs ||
1614 cilen != CILEN_ADDR) { /* Check CI length */
1615 orc = CONFREJ; /* Reject CI */
1616 break;
1617 }
1618
1619 /*
1620 * If he has no address, or if we both have his address but
1621 * disagree about it, then NAK it with our idea.
1622 * In particular, if we don't know his address, but he does,
1623 * then accept it.
1624 */
1625 GETLONG(tl, p); /* Parse source address (his) */
1626 ciaddr1 = lwip_htonl(tl);
1627 if (ciaddr1 != wo->hisaddr
1628 && (ciaddr1 == 0 || !wo->accept_remote)) {
1629 orc = CONFNAK;
1630 if (!reject_if_disagree) {
1631 DECPTR(sizeof(u32_t), p);
1632 tl = lwip_ntohl(wo->hisaddr);
1633 PUTLONG(tl, p);
1634 }
1635 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1636 /*
1637 * Don't ACK an address of 0.0.0.0 - reject it instead.
1638 */
1639 orc = CONFREJ;
1640 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
1641 break;
1642 }
1643
1644 ho->neg_addr = 1;
1645 ho->hisaddr = ciaddr1;
1646 break;
1647
1648#if LWIP_DNS
1649 case CI_MS_DNS1:
1650 case CI_MS_DNS2:
1651 /* Microsoft primary or secondary DNS request */
1652 d = citype == CI_MS_DNS2;
1653
1654 /* If we do not have a DNS address then we cannot send it */
1655 if (ao->dnsaddr[d] == 0 ||
1656 cilen != CILEN_ADDR) { /* Check CI length */
1657 orc = CONFREJ; /* Reject CI */
1658 break;
1659 }
1660 GETLONG(tl, p);
1661 if (lwip_htonl(tl) != ao->dnsaddr[d]) {
1662 DECPTR(sizeof(u32_t), p);
1663 tl = lwip_ntohl(ao->dnsaddr[d]);
1664 PUTLONG(tl, p);
1665 orc = CONFNAK;
1666 }
1667 break;
1668#endif /* LWIP_DNS */
1669
1670#if 0 /* UNUSED - WINS */
1671 case CI_MS_WINS1:
1672 case CI_MS_WINS2:
1673 /* Microsoft primary or secondary WINS request */
1674 d = citype == CI_MS_WINS2;
1675
1676 /* If we do not have a DNS address then we cannot send it */
1677 if (ao->winsaddr[d] == 0 ||
1678 cilen != CILEN_ADDR) { /* Check CI length */
1679 orc = CONFREJ; /* Reject CI */
1680 break;
1681 }
1682 GETLONG(tl, p);
1683 if (lwip_htonl(tl) != ao->winsaddr[d]) {
1684 DECPTR(sizeof(u32_t), p);
1685 tl = lwip_ntohl(ao->winsaddr[d]);
1686 PUTLONG(tl, p);
1687 orc = CONFNAK;
1688 }
1689 break;
1690#endif /* UNUSED - WINS */
1691
1692#if VJ_SUPPORT
1693 case CI_COMPRESSTYPE:
1694 if (!ao->neg_vj ||
1695 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
1696 orc = CONFREJ;
1697 break;
1698 }
1699 GETSHORT(cishort, p);
1700
1701 if (!(cishort == IPCP_VJ_COMP ||
1702 (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
1703 orc = CONFREJ;
1704 break;
1705 }
1706
1707 ho->neg_vj = 1;
1708 ho->vj_protocol = cishort;
1709 if (cilen == CILEN_VJ) {
1710 GETCHAR(maxslotindex, p);
1711 if (maxslotindex > ao->maxslotindex) {
1712 orc = CONFNAK;
1713 if (!reject_if_disagree){
1714 DECPTR(1, p);
1715 PUTCHAR(ao->maxslotindex, p);
1716 }
1717 }
1718 GETCHAR(cflag, p);
1719 if (cflag && !ao->cflag) {
1720 orc = CONFNAK;
1721 if (!reject_if_disagree){
1722 DECPTR(1, p);
1723 PUTCHAR(wo->cflag, p);
1724 }
1725 }
1726 ho->maxslotindex = maxslotindex;
1727 ho->cflag = cflag;
1728 } else {
1729 ho->old_vj = 1;
1730 ho->maxslotindex = MAX_STATES - 1;
1731 ho->cflag = 1;
1732 }
1733 break;
1734#endif /* VJ_SUPPORT */
1735
1736 default:
1737 orc = CONFREJ;
1738 break;
1739 }
1740endswitch:
1741 if (orc == CONFACK && /* Good CI */
1742 rc != CONFACK) /* but prior CI wasn't? */
1743 continue; /* Don't send this one */
1744
1745 if (orc == CONFNAK) { /* Nak this CI? */
1746 if (reject_if_disagree) /* Getting fed up with sending NAKs? */
1747 orc = CONFREJ; /* Get tough if so */
1748 else {
1749 if (rc == CONFREJ) /* Rejecting prior CI? */
1750 continue; /* Don't send this one */
1751 if (rc == CONFACK) { /* Ack'd all prior CIs? */
1752 rc = CONFNAK; /* Not anymore... */
1753 ucp = inp; /* Backup */
1754 }
1755 }
1756 }
1757
1758 if (orc == CONFREJ && /* Reject this CI */
1759 rc != CONFREJ) { /* but no prior ones? */
1760 rc = CONFREJ;
1761 ucp = inp; /* Backup */
1762 }
1763
1764 /* Need to move CI? */
1765 if (ucp != cip)
1766 MEMCPY(ucp, cip, cilen); /* Move it */
1767
1768 /* Update output pointer */
1769 INCPTR(cilen, ucp);
1770 }
1771
1772 /*
1773 * If we aren't rejecting this packet, and we want to negotiate
1774 * their address, and they didn't send their address, then we
1775 * send a NAK with a CI_ADDR option appended. We assume the
1776 * input buffer is long enough that we can append the extra
1777 * option safely.
1778 */
1779 if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs &&
1780 wo->req_addr && !reject_if_disagree && !pcb->settings.noremoteip) {
1781 if (rc == CONFACK) {
1782 rc = CONFNAK;
1783 ucp = inp; /* reset pointer */
1784 wo->req_addr = 0; /* don't ask again */
1785 }
1786 PUTCHAR(CI_ADDR, ucp);
1787 PUTCHAR(CILEN_ADDR, ucp);
1788 tl = lwip_ntohl(wo->hisaddr);
1789 PUTLONG(tl, ucp);
1790 }
1791
1792 *len = ucp - inp; /* Compute output length */
1793 IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc)));
1794 return (rc); /* Return final code */
1795}
1796
1797
1798#if 0 /* UNUSED */
1799/*
1800 * ip_check_options - check that any IP-related options are OK,
1801 * and assign appropriate defaults.
1802 */
1803static void
1804ip_check_options()
1805{
1806 struct hostent *hp;
1807 u32_t local;
1808 ipcp_options *wo = &ipcp_wantoptions[0];
1809
1810 /*
1811 * Default our local IP address based on our hostname.
1812 * If local IP address already given, don't bother.
1813 */
1814 if (wo->ouraddr == 0 && !disable_defaultip) {
1815 /*
1816 * Look up our hostname (possibly with domain name appended)
1817 * and take the first IP address as our local IP address.
1818 * If there isn't an IP address for our hostname, too bad.
1819 */
1820 wo->accept_local = 1; /* don't insist on this default value */
1821 if ((hp = gethostbyname(hostname)) != NULL) {
1822 local = *(u32_t *)hp->h_addr;
1823 if (local != 0 && !bad_ip_adrs(local))
1824 wo->ouraddr = local;
1825 }
1826 }
1827 ask_for_local = wo->ouraddr != 0 || !disable_defaultip;
1828}
1829#endif /* UNUSED */
1830
1831#if DEMAND_SUPPORT
1832/*
1833 * ip_demand_conf - configure the interface as though
1834 * IPCP were up, for use with dial-on-demand.
1835 */
1836static int
1837ip_demand_conf(u)
1838 int u;
1839{
1840 ppp_pcb *pcb = &ppp_pcb_list[u];
1841 ipcp_options *wo = &ipcp_wantoptions[u];
1842
1843 if (wo->hisaddr == 0 && !pcb->settings.noremoteip) {
1844 /* make up an arbitrary address for the peer */
1845 wo->hisaddr = lwip_htonl(0x0a707070 + ifunit);
1846 wo->accept_remote = 1;
1847 }
1848 if (wo->ouraddr == 0) {
1849 /* make up an arbitrary address for us */
1850 wo->ouraddr = lwip_htonl(0x0a404040 + ifunit);
1851 wo->accept_local = 1;
1852 ask_for_local = 0; /* don't tell the peer this address */
1853 }
1854 if (!sifaddr(pcb, wo->ouraddr, wo->hisaddr, get_mask(wo->ouraddr)))
1855 return 0;
1856 if (!sifup(pcb))
1857 return 0;
1858 if (!sifnpmode(pcb, PPP_IP, NPMODE_QUEUE))
1859 return 0;
1860#if 0 /* UNUSED */
1861 if (wo->default_route)
1862 if (sifdefaultroute(pcb, wo->ouraddr, wo->hisaddr,
1863 wo->replace_default_route))
1864 default_route_set[u] = 1;
1865#endif /* UNUSED */
1866#if 0 /* UNUSED - PROXY ARP */
1867 if (wo->proxy_arp)
1868 if (sifproxyarp(pcb, wo->hisaddr))
1869 proxy_arp_set[u] = 1;
1870#endif /* UNUSED - PROXY ARP */
1871
1872 ppp_notice(("local IP address %I", wo->ouraddr));
1873 if (wo->hisaddr)
1874 ppp_notice(("remote IP address %I", wo->hisaddr));
1875
1876 return 1;
1877}
1878#endif /* DEMAND_SUPPORT */
1879
1880/*
1881 * ipcp_up - IPCP has come UP.
1882 *
1883 * Configure the IP network interface appropriately and bring it up.
1884 */
1885static void ipcp_up(fsm *f) {
1886 ppp_pcb *pcb = f->pcb;
1887 u32_t mask;
1888 ipcp_options *ho = &pcb->ipcp_hisoptions;
1889 ipcp_options *go = &pcb->ipcp_gotoptions;
1890 ipcp_options *wo = &pcb->ipcp_wantoptions;
1891
1892 IPCPDEBUG(("ipcp: up"));
1893
1894 /*
1895 * We must have a non-zero IP address for both ends of the link.
1896 */
1897 if (!ho->neg_addr && !ho->old_addrs)
1898 ho->hisaddr = wo->hisaddr;
1899
1900 if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs)
1901 && wo->ouraddr != 0) {
1902 ppp_error(("Peer refused to agree to our IP address"));
1903 ipcp_close(f->pcb, "Refused our IP address");
1904 return;
1905 }
1906 if (go->ouraddr == 0) {
1907 ppp_error(("Could not determine local IP address"));
1908 ipcp_close(f->pcb, "Could not determine local IP address");
1909 return;
1910 }
1911 if (ho->hisaddr == 0 && !pcb->settings.noremoteip) {
1912 ho->hisaddr = lwip_htonl(0x0a404040);
1913 ppp_warn(("Could not determine remote IP address: defaulting to %I",
1914 ho->hisaddr));
1915 }
1916#if 0 /* UNUSED */
1917 script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0);
1918 if (ho->hisaddr != 0)
1919 script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1);
1920#endif /* UNUSED */
1921
1922#if LWIP_DNS
1923 if (!go->req_dns1)
1924 go->dnsaddr[0] = 0;
1925 if (!go->req_dns2)
1926 go->dnsaddr[1] = 0;
1927#if 0 /* UNUSED */
1928 if (go->dnsaddr[0])
1929 script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0);
1930 if (go->dnsaddr[1])
1931 script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0);
1932#endif /* UNUSED */
1933 if (pcb->settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
1934 sdns(pcb, go->dnsaddr[0], go->dnsaddr[1]);
1935#if 0 /* UNUSED */
1936 script_setenv("USEPEERDNS", "1", 0);
1937 create_resolv(go->dnsaddr[0], go->dnsaddr[1]);
1938#endif /* UNUSED */
1939 }
1940#endif /* LWIP_DNS */
1941
1942 /*
1943 * Check that the peer is allowed to use the IP address it wants.
1944 */
1945 if (ho->hisaddr != 0) {
1946 u32_t addr = lwip_ntohl(ho->hisaddr);
1947 if ((addr >> IP_CLASSA_NSHIFT) == IP_LOOPBACKNET
1948 || IP_MULTICAST(addr) || IP_BADCLASS(addr)
1949 /*
1950 * For now, consider that PPP in server mode with peer required
1951 * to authenticate must provide the peer IP address, reject any
1952 * IP address wanted by peer different than the one we wanted.
1953 */
1954#if PPP_SERVER && PPP_AUTH_SUPPORT
1955 || (pcb->settings.auth_required && wo->hisaddr != ho->hisaddr)
1956#endif /* PPP_SERVER && PPP_AUTH_SUPPORT */
1957 ) {
1958 ppp_error(("Peer is not authorized to use remote address %I", ho->hisaddr));
1959 ipcp_close(pcb, "Unauthorized remote IP address");
1960 return;
1961 }
1962 }
1963#if 0 /* Unused */
1964 /* Upstream checking code */
1965 if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) {
1966 ppp_error(("Peer is not authorized to use remote address %I", ho->hisaddr));
1967 ipcp_close(f->unit, "Unauthorized remote IP address");
1968 return;
1969 }
1970#endif /* Unused */
1971
1972#if VJ_SUPPORT
1973 /* set tcp compression */
1974 sifvjcomp(pcb, ho->neg_vj, ho->cflag, ho->maxslotindex);
1975#endif /* VJ_SUPPORT */
1976
1977#if DEMAND_SUPPORT
1978 /*
1979 * If we are doing dial-on-demand, the interface is already
1980 * configured, so we put out any saved-up packets, then set the
1981 * interface to pass IP packets.
1982 */
1983 if (demand) {
1984 if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
1985 ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr,
1986 wo->replace_default_route);
1987 if (go->ouraddr != wo->ouraddr) {
1988 ppp_warn(("Local IP address changed to %I", go->ouraddr));
1989 script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
1990 wo->ouraddr = go->ouraddr;
1991 } else
1992 script_unsetenv("OLDIPLOCAL");
1993 if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) {
1994 ppp_warn(("Remote IP address changed to %I", ho->hisaddr));
1995 script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0);
1996 wo->hisaddr = ho->hisaddr;
1997 } else
1998 script_unsetenv("OLDIPREMOTE");
1999
2000 /* Set the interface to the new addresses */
2001 mask = get_mask(go->ouraddr);
2002 if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) {
2003#if PPP_DEBUG
2004 ppp_warn(("Interface configuration failed"));
2005#endif /* PPP_DEBUG */
2006 ipcp_close(f->unit, "Interface configuration failed");
2007 return;
2008 }
2009
2010 /* assign a default route through the interface if required */
2011 if (ipcp_wantoptions[f->unit].default_route)
2012 if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr,
2013 wo->replace_default_route))
2014 default_route_set[f->unit] = 1;
2015
2016#if 0 /* UNUSED - PROXY ARP */
2017 /* Make a proxy ARP entry if requested. */
2018 if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp)
2019 if (sifproxyarp(pcb, ho->hisaddr))
2020 proxy_arp_set[f->unit] = 1;
2021#endif /* UNUSED - PROXY ARP */
2022
2023 }
2024 demand_rexmit(PPP_IP,go->ouraddr);
2025 sifnpmode(pcb, PPP_IP, NPMODE_PASS);
2026
2027 } else
2028#endif /* DEMAND_SUPPORT */
2029 {
2030 /*
2031 * Set IP addresses and (if specified) netmask.
2032 */
2033 mask = get_mask(go->ouraddr);
2034
2035#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
2036 if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) {
2037#if PPP_DEBUG
2038 ppp_warn(("Interface configuration failed"));
2039#endif /* PPP_DEBUG */
2040 ipcp_close(f->pcb, "Interface configuration failed");
2041 return;
2042 }
2043#endif
2044
2045 /* bring the interface up for IP */
2046 if (!sifup(pcb)) {
2047#if PPP_DEBUG
2048 ppp_warn(("Interface failed to come up"));
2049#endif /* PPP_DEBUG */
2050 ipcp_close(f->pcb, "Interface configuration failed");
2051 return;
2052 }
2053
2054#if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
2055 if (!sifaddr(pcb, go->ouraddr, ho->hisaddr, mask)) {
2056#if PPP_DEBUG
2057 ppp_warn(("Interface configuration failed"));
2058#endif /* PPP_DEBUG */
2059 ipcp_close(f->unit, "Interface configuration failed");
2060 return;
2061 }
2062#endif
2063#if DEMAND_SUPPORT
2064 sifnpmode(pcb, PPP_IP, NPMODE_PASS);
2065#endif /* DEMAND_SUPPORT */
2066
2067#if 0 /* UNUSED */
2068 /* assign a default route through the interface if required */
2069 if (wo->default_route)
2070 if (sifdefaultroute(pcb, go->ouraddr, ho->hisaddr,
2071 wo->replace_default_route))
2072 pcb->default_route_set = 1;
2073#endif /* UNUSED */
2074
2075#if 0 /* UNUSED - PROXY ARP */
2076 /* Make a proxy ARP entry if requested. */
2077 if (ho->hisaddr != 0 && wo->proxy_arp)
2078 if (sifproxyarp(pcb, ho->hisaddr))
2079 pcb->proxy_arp_set = 1;
2080#endif /* UNUSED - PROXY ARP */
2081
2082 wo->ouraddr = go->ouraddr;
2083
2084 ppp_notice(("local IP address %I", go->ouraddr));
2085 if (ho->hisaddr != 0)
2086 ppp_notice(("remote IP address %I", ho->hisaddr));
2087#if LWIP_DNS
2088 if (go->dnsaddr[0])
2089 ppp_notice(("primary DNS address %I", go->dnsaddr[0]));
2090 if (go->dnsaddr[1])
2091 ppp_notice(("secondary DNS address %I", go->dnsaddr[1]));
2092#endif /* LWIP_DNS */
2093 }
2094
2095#if PPP_STATS_SUPPORT
2096 reset_link_stats(f->unit);
2097#endif /* PPP_STATS_SUPPORT */
2098
2099 np_up(pcb, PPP_IP);
2100 pcb->ipcp_is_up = 1;
2101
2102#if PPP_NOTIFY
2103 notify(ip_up_notifier, 0);
2104#endif /* PPP_NOTIFY */
2105#if 0 /* UNUSED */
2106 if (ip_up_hook)
2107 ip_up_hook();
2108#endif /* UNUSED */
2109}
2110
2111
2112/*
2113 * ipcp_down - IPCP has gone DOWN.
2114 *
2115 * Take the IP network interface down, clear its addresses
2116 * and delete routes through it.
2117 */
2118static void ipcp_down(fsm *f) {
2119 ppp_pcb *pcb = f->pcb;
2120 ipcp_options *ho = &pcb->ipcp_hisoptions;
2121 ipcp_options *go = &pcb->ipcp_gotoptions;
2122
2123 IPCPDEBUG(("ipcp: down"));
2124#if PPP_STATS_SUPPORT
2125 /* XXX a bit IPv4-centric here, we only need to get the stats
2126 * before the interface is marked down. */
2127 /* XXX more correct: we must get the stats before running the notifiers,
2128 * at least for the radius plugin */
2129 update_link_stats(f->unit);
2130#endif /* PPP_STATS_SUPPORT */
2131#if PPP_NOTIFY
2132 notify(ip_down_notifier, 0);
2133#endif /* PPP_NOTIFY */
2134#if 0 /* UNUSED */
2135 if (ip_down_hook)
2136 ip_down_hook();
2137#endif /* UNUSED */
2138 if (pcb->ipcp_is_up) {
2139 pcb->ipcp_is_up = 0;
2140 np_down(pcb, PPP_IP);
2141 }
2142#if VJ_SUPPORT
2143 sifvjcomp(pcb, 0, 0, 0);
2144#endif /* VJ_SUPPORT */
2145
2146#if PPP_STATS_SUPPORT
2147 print_link_stats(); /* _after_ running the notifiers and ip_down_hook(),
2148 * because print_link_stats() sets link_stats_valid
2149 * to 0 (zero) */
2150#endif /* PPP_STATS_SUPPORT */
2151
2152#if DEMAND_SUPPORT
2153 /*
2154 * If we are doing dial-on-demand, set the interface
2155 * to queue up outgoing packets (for now).
2156 */
2157 if (demand) {
2158 sifnpmode(pcb, PPP_IP, NPMODE_QUEUE);
2159 } else
2160#endif /* DEMAND_SUPPORT */
2161 {
2162#if DEMAND_SUPPORT
2163 sifnpmode(pcb, PPP_IP, NPMODE_DROP);
2164#endif /* DEMAND_SUPPORT */
2165 sifdown(pcb);
2166 ipcp_clear_addrs(pcb, go->ouraddr,
2167 ho->hisaddr, 0);
2168#if LWIP_DNS
2169 cdns(pcb, go->dnsaddr[0], go->dnsaddr[1]);
2170#endif /* LWIP_DNS */
2171 }
2172}
2173
2174
2175/*
2176 * ipcp_clear_addrs() - clear the interface addresses, routes,
2177 * proxy arp entries, etc.
2178 */
2179static void ipcp_clear_addrs(ppp_pcb *pcb, u32_t ouraddr, u32_t hisaddr, u8_t replacedefaultroute) {
2180 LWIP_UNUSED_ARG(replacedefaultroute);
2181
2182#if 0 /* UNUSED - PROXY ARP */
2183 if (pcb->proxy_arp_set) {
2184 cifproxyarp(pcb, hisaddr);
2185 pcb->proxy_arp_set = 0;
2186 }
2187#endif /* UNUSED - PROXY ARP */
2188#if 0 /* UNUSED */
2189 /* If replacedefaultroute, sifdefaultroute will be called soon
2190 * with replacedefaultroute set and that will overwrite the current
2191 * default route. This is the case only when doing demand, otherwise
2192 * during demand, this cifdefaultroute would restore the old default
2193 * route which is not what we want in this case. In the non-demand
2194 * case, we'll delete the default route and restore the old if there
2195 * is one saved by an sifdefaultroute with replacedefaultroute.
2196 */
2197 if (!replacedefaultroute && pcb->default_route_set) {
2198 cifdefaultroute(pcb, ouraddr, hisaddr);
2199 pcb->default_route_set = 0;
2200 }
2201#endif /* UNUSED */
2202 cifaddr(pcb, ouraddr, hisaddr);
2203}
2204
2205
2206/*
2207 * ipcp_finished - possibly shut down the lower layers.
2208 */
2209static void ipcp_finished(fsm *f) {
2210 ppp_pcb *pcb = f->pcb;
2211 if (pcb->ipcp_is_open) {
2212 pcb->ipcp_is_open = 0;
2213 np_finished(pcb, PPP_IP);
2214 }
2215}
2216
2217
2218#if 0 /* UNUSED */
2219/*
2220 * create_resolv - create the replacement resolv.conf file
2221 */
2222static void
2223create_resolv(peerdns1, peerdns2)
2224 u32_t peerdns1, peerdns2;
2225{
2226
2227}
2228#endif /* UNUSED */
2229
2230#if PRINTPKT_SUPPORT
2231/*
2232 * ipcp_printpkt - print the contents of an IPCP packet.
2233 */
2234static const char* const ipcp_codenames[] = {
2235 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
2236 "TermReq", "TermAck", "CodeRej"
2237};
2238
2239static int ipcp_printpkt(const u_char *p, int plen,
2240 void (*printer) (void *, const char *, ...), void *arg) {
2241 int code, id, len, olen;
2242 const u_char *pstart, *optend;
2243#if VJ_SUPPORT
2244 u_short cishort;
2245#endif /* VJ_SUPPORT */
2246 u32_t cilong;
2247
2248 if (plen < HEADERLEN)
2249 return 0;
2250 pstart = p;
2251 GETCHAR(code, p);
2252 GETCHAR(id, p);
2253 GETSHORT(len, p);
2254 if (len < HEADERLEN || len > plen)
2255 return 0;
2256
2257 if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(ipcp_codenames))
2258 printer(arg, " %s", ipcp_codenames[code-1]);
2259 else
2260 printer(arg, " code=0x%x", code);
2261 printer(arg, " id=0x%x", id);
2262 len -= HEADERLEN;
2263 switch (code) {
2264 case CONFREQ:
2265 case CONFACK:
2266 case CONFNAK:
2267 case CONFREJ:
2268 /* print option list */
2269 while (len >= 2) {
2270 GETCHAR(code, p);
2271 GETCHAR(olen, p);
2272 p -= 2;
2273 if (olen < 2 || olen > len) {
2274 break;
2275 }
2276 printer(arg, " <");
2277 len -= olen;
2278 optend = p + olen;
2279 switch (code) {
2280 case CI_ADDRS:
2281 if (olen == CILEN_ADDRS) {
2282 p += 2;
2283 GETLONG(cilong, p);
2284 printer(arg, "addrs %I", lwip_htonl(cilong));
2285 GETLONG(cilong, p);
2286 printer(arg, " %I", lwip_htonl(cilong));
2287 }
2288 break;
2289#if VJ_SUPPORT
2290 case CI_COMPRESSTYPE:
2291 if (olen >= CILEN_COMPRESS) {
2292 p += 2;
2293 GETSHORT(cishort, p);
2294 printer(arg, "compress ");
2295 switch (cishort) {
2296 case IPCP_VJ_COMP:
2297 printer(arg, "VJ");
2298 break;
2299 case IPCP_VJ_COMP_OLD:
2300 printer(arg, "old-VJ");
2301 break;
2302 default:
2303 printer(arg, "0x%x", cishort);
2304 }
2305 }
2306 break;
2307#endif /* VJ_SUPPORT */
2308 case CI_ADDR:
2309 if (olen == CILEN_ADDR) {
2310 p += 2;
2311 GETLONG(cilong, p);
2312 printer(arg, "addr %I", lwip_htonl(cilong));
2313 }
2314 break;
2315#if LWIP_DNS
2316 case CI_MS_DNS1:
2317 case CI_MS_DNS2:
2318 p += 2;
2319 GETLONG(cilong, p);
2320 printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2),
2321 htonl(cilong));
2322 break;
2323#endif /* LWIP_DNS */
2324#if 0 /* UNUSED - WINS */
2325 case CI_MS_WINS1:
2326 case CI_MS_WINS2:
2327 p += 2;
2328 GETLONG(cilong, p);
2329 printer(arg, "ms-wins %I", lwip_htonl(cilong));
2330 break;
2331#endif /* UNUSED - WINS */
2332 default:
2333 break;
2334 }
2335 while (p < optend) {
2336 GETCHAR(code, p);
2337 printer(arg, " %.2x", code);
2338 }
2339 printer(arg, ">");
2340 }
2341 break;
2342
2343 case TERMACK:
2344 case TERMREQ:
2345 if (len > 0 && *p >= ' ' && *p < 0x7f) {
2346 printer(arg, " ");
2347 ppp_print_string(p, len, printer, arg);
2348 p += len;
2349 len = 0;
2350 }
2351 break;
2352 default:
2353 break;
2354 }
2355
2356 /* print the rest of the bytes in the packet */
2357 for (; len > 0; --len) {
2358 GETCHAR(code, p);
2359 printer(arg, " %.2x", code);
2360 }
2361
2362 return p - pstart;
2363}
2364#endif /* PRINTPKT_SUPPORT */
2365
2366#if DEMAND_SUPPORT
2367/*
2368 * ip_active_pkt - see if this IP packet is worth bringing the link up for.
2369 * We don't bring the link up for IP fragments or for TCP FIN packets
2370 * with no data.
2371 */
2372#define IP_HDRLEN 20 /* bytes */
2373#define IP_OFFMASK 0x1fff
2374#ifndef IPPROTO_TCP
2375#define IPPROTO_TCP 6
2376#endif
2377#define TCP_HDRLEN 20
2378#define TH_FIN 0x01
2379
2380/*
2381 * We use these macros because the IP header may be at an odd address,
2382 * and some compilers might use word loads to get th_off or ip_hl.
2383 */
2384
2385#define net_short(x) (((x)[0] << 8) + (x)[1])
2386#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF)
2387#define get_ipoff(x) net_short((unsigned char *)(x) + 6)
2388#define get_ipproto(x) (((unsigned char *)(x))[9])
2389#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4)
2390#define get_tcpflags(x) (((unsigned char *)(x))[13])
2391
2392static int
2393ip_active_pkt(pkt, len)
2394 u_char *pkt;
2395 int len;
2396{
2397 u_char *tcp;
2398 int hlen;
2399
2400 len -= PPP_HDRLEN;
2401 pkt += PPP_HDRLEN;
2402 if (len < IP_HDRLEN)
2403 return 0;
2404 if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
2405 return 0;
2406 if (get_ipproto(pkt) != IPPROTO_TCP)
2407 return 1;
2408 hlen = get_iphl(pkt) * 4;
2409 if (len < hlen + TCP_HDRLEN)
2410 return 0;
2411 tcp = pkt + hlen;
2412 if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
2413 return 0;
2414 return 1;
2415}
2416#endif /* DEMAND_SUPPORT */
2417
2418#endif /* PPP_SUPPORT && PPP_IPV4_SUPPORT */
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
char * strchr(const char *String, int ch)
Definition: utclib.c:501
ULONG WSAAPI inet_addr(IN CONST CHAR FAR *cp)
Definition: addrconv.c:71
char * hostname
Definition: ftp.c:88
size_t strlcpy(char *d, const char *s, size_t bufsize)
Definition: compat.c:3
r l[0]
Definition: byte_order.h:168
#define LWIP_ARRAYSIZE(x)
Definition: def.h:69
#define lwip_ntohl(x)
Definition: def.h:89
#define lwip_htonl(x)
Definition: def.h:88
#define IP_OFFMASK
Definition: dhcpd.h:72
#define NULL
Definition: types.h:112
unsigned short u_short
Definition: types.h:81
UCHAR u_char
Definition: types.h:80
static WCHAR no[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2340
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
#define IPPROTO_TCP
Definition: ip.h:196
#define doit(a, b)
Definition: fieldoff.c:4
#define local
Definition: zutil.h:30
PHOSTENT WSAAPI gethostbyname(IN const char FAR *name)
Definition: getxbyxx.c:221
const GLdouble * v
Definition: gl.h:2040
GLdouble n
Definition: glext.h:7729
GLenum GLint GLuint mask
Definition: glext.h:6028
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum const GLvoid * addr
Definition: glext.h:9621
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
uint32_t u32_t
Definition: arch.h:129
uint8_t u8_t
Definition: arch.h:125
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
#define LWIP_DNS
Definition: opt.h:1135
#define d
Definition: ke_i.h:81
#define b
Definition: ke_i.h:79
if(dx< 0)
Definition: linetemp.h:194
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
const char * optend(char *fmt) const
Definition: mkisofs.c:1691
#define htonl(x)
Definition: module.h:214
#define argv
Definition: mplay32.c:18
int notify
Definition: msacm.c:1366
#define TH_FIN
Definition: netiodef.h:349
static unsigned __int64 next
Definition: rand_nt.c:6
#define memset(x, y, z)
Definition: compat.h:39
Definition: inflate.c:139
Definition: pdh_main.c:94
void * arg
Definition: msvc.h:10