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