xref: /freebsd/usr.sbin/ppp/ipcp.c (revision 26af0ae96638b0453bcc87cae6031eb0b3988171)
1af57ed9fSAtsushi Murai /*
2af57ed9fSAtsushi Murai  *	PPP IP Control Protocol (IPCP) Module
3af57ed9fSAtsushi Murai  *
4af57ed9fSAtsushi Murai  *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5af57ed9fSAtsushi Murai  *
6af57ed9fSAtsushi Murai  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7af57ed9fSAtsushi Murai  *
8af57ed9fSAtsushi Murai  * Redistribution and use in source and binary forms are permitted
9af57ed9fSAtsushi Murai  * provided that the above copyright notice and this paragraph are
10af57ed9fSAtsushi Murai  * duplicated in all such forms and that any documentation,
11af57ed9fSAtsushi Murai  * advertising materials, and other materials related to such
12af57ed9fSAtsushi Murai  * distribution and use acknowledge that the software was developed
13af57ed9fSAtsushi Murai  * by the Internet Initiative Japan, Inc.  The name of the
14af57ed9fSAtsushi Murai  * IIJ may not be used to endorse or promote products derived
15af57ed9fSAtsushi Murai  * from this software without specific prior written permission.
16af57ed9fSAtsushi Murai  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17af57ed9fSAtsushi Murai  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18af57ed9fSAtsushi Murai  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19af57ed9fSAtsushi Murai  *
2097d92980SPeter Wemm  * $FreeBSD$
21af57ed9fSAtsushi Murai  *
22af57ed9fSAtsushi Murai  *	TODO:
235d9e6103SBrian Somers  *		o Support IPADDRS properly
245d9e6103SBrian Somers  *		o Validate the length in IpcpDecodeConfig
25af57ed9fSAtsushi Murai  */
2675240ed1SBrian Somers #include <sys/param.h>
275b4c5b00SBrian Somers #include <netinet/in_systm.h>
285b4c5b00SBrian Somers #include <netinet/in.h>
295b4c5b00SBrian Somers #include <netinet/ip.h>
305b4c5b00SBrian Somers #include <arpa/inet.h>
315b4c5b00SBrian Somers #include <sys/socket.h>
323afe5ccbSBrian Somers #include <net/route.h>
3375240ed1SBrian Somers #include <netdb.h>
341fa665f5SBrian Somers #include <sys/un.h>
3575240ed1SBrian Somers 
36119386a3SBrian Somers #include <errno.h>
373edeb0c6SBrian Somers #include <fcntl.h>
383edeb0c6SBrian Somers #include <resolv.h>
39d1a3ea47SBrian Somers #include <stdlib.h>
4075240ed1SBrian Somers #include <string.h>
416140ba11SBrian Somers #include <termios.h>
4275240ed1SBrian Somers #include <unistd.h>
4375240ed1SBrian Somers 
4467b072f7SBrian Somers #ifndef NONAT
457884358fSBrian Somers #ifdef __FreeBSD__
461595bacdSBrian Somers #include <alias.h>
477884358fSBrian Somers #else
487884358fSBrian Somers #include "alias.h"
491595bacdSBrian Somers #endif
501595bacdSBrian Somers #endif
515d9e6103SBrian Somers #include "layer.h"
529e8ec64bSBrian Somers #include "ua.h"
53c9e11a11SBrian Somers #include "defs.h"
54b6e82f33SBrian Somers #include "command.h"
5575240ed1SBrian Somers #include "mbuf.h"
5675240ed1SBrian Somers #include "log.h"
5775240ed1SBrian Somers #include "timer.h"
58af57ed9fSAtsushi Murai #include "fsm.h"
595d9e6103SBrian Somers #include "proto.h"
60af57ed9fSAtsushi Murai #include "lcp.h"
61bcc332bdSBrian Somers #include "iplist.h"
629a0b991fSBrian Somers #include "throughput.h"
631ae349f5Scvs2svn #include "slcompress.h"
645a72b6edSBrian Somers #include "lqr.h"
655a72b6edSBrian Somers #include "hdlc.h"
66eaa4df37SBrian Somers #include "ipcp.h"
679c97abd8SBrian Somers #include "filter.h"
682f786681SBrian Somers #include "descriptor.h"
691ae349f5Scvs2svn #include "vjcomp.h"
706140ba11SBrian Somers #include "async.h"
713b0f8d2eSBrian Somers #include "ccp.h"
728c07a7b2SBrian Somers #include "link.h"
7363b73463SBrian Somers #include "physical.h"
743b0f8d2eSBrian Somers #include "mp.h"
75972a1bcfSBrian Somers #ifndef NORADIUS
76972a1bcfSBrian Somers #include "radius.h"
77972a1bcfSBrian Somers #endif
783b0f8d2eSBrian Somers #include "bundle.h"
79455aabc3SBrian Somers #include "id.h"
80455aabc3SBrian Somers #include "arp.h"
81455aabc3SBrian Somers #include "systems.h"
8285b542cfSBrian Somers #include "prompt.h"
83610b185fSBrian Somers #include "route.h"
848fa6ebe4SBrian Somers #include "iface.h"
85442f8495SBrian Somers #include "ip.h"
86af57ed9fSAtsushi Murai 
87503a7782SBrian Somers #undef REJECTED
88503a7782SBrian Somers #define	REJECTED(p, x)	((p)->peer_reject & (1<<(x)))
893edeb0c6SBrian Somers #define issep(ch) ((ch) == ' ' || (ch) == '\t')
903edeb0c6SBrian Somers #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.')
91d8e55738SJordan K. Hubbard 
92da477886SBrian Somers static u_short default_urgent_tcp_ports[] = {
93442f8495SBrian Somers   21,	/* ftp */
94442f8495SBrian Somers   22,	/* ssh */
95442f8495SBrian Somers   23,	/* telnet */
96442f8495SBrian Somers   513,	/* login */
97442f8495SBrian Somers   514,	/* shell */
98442f8495SBrian Somers   543,	/* klogin */
99442f8495SBrian Somers   544	/* kshell */
100442f8495SBrian Somers };
101442f8495SBrian Somers 
102da477886SBrian Somers static u_short default_urgent_udp_ports[] = { };
103da477886SBrian Somers 
104da477886SBrian Somers #define NDEFTCPPORTS \
105da477886SBrian Somers   (sizeof default_urgent_tcp_ports / sizeof default_urgent_tcp_ports[0])
106da477886SBrian Somers #define NDEFUDPPORTS \
107da477886SBrian Somers   (sizeof default_urgent_udp_ports / sizeof default_urgent_udp_ports[0])
108442f8495SBrian Somers 
109442f8495SBrian Somers int
110da477886SBrian Somers ipcp_IsUrgentPort(struct port_range *range, u_short src, u_short dst)
111442f8495SBrian Somers {
112442f8495SBrian Somers   int f;
113442f8495SBrian Somers 
114da477886SBrian Somers   for (f = 0; f < range->nports; f++)
115da477886SBrian Somers     if (range->port[f] == src || range->port[f] == dst)
116442f8495SBrian Somers       return 1;
117442f8495SBrian Somers 
118442f8495SBrian Somers   return 0;
119442f8495SBrian Somers }
120442f8495SBrian Somers 
121442f8495SBrian Somers void
122da477886SBrian Somers ipcp_AddUrgentPort(struct port_range *range, u_short port)
123442f8495SBrian Somers {
124442f8495SBrian Somers   u_short *newport;
125442f8495SBrian Somers   int p;
126442f8495SBrian Somers 
127da477886SBrian Somers   if (range->nports == range->maxports) {
128da477886SBrian Somers     range->maxports += 10;
129da477886SBrian Somers     newport = (u_short *)realloc(range->port,
130da477886SBrian Somers                                  range->maxports * sizeof(u_short));
131442f8495SBrian Somers     if (newport == NULL) {
132442f8495SBrian Somers       log_Printf(LogERROR, "ipcp_AddUrgentPort: realloc: %s\n",
133442f8495SBrian Somers                  strerror(errno));
134da477886SBrian Somers       range->maxports -= 10;
135442f8495SBrian Somers       return;
136442f8495SBrian Somers     }
137da477886SBrian Somers     range->port = newport;
138442f8495SBrian Somers   }
139442f8495SBrian Somers 
140da477886SBrian Somers   for (p = 0; p < range->nports; p++)
141da477886SBrian Somers     if (range->port[p] == port) {
142442f8495SBrian Somers       log_Printf(LogWARN, "%u: Port already set to urgent\n", port);
143442f8495SBrian Somers       break;
144da477886SBrian Somers     } else if (range->port[p] > port) {
145da477886SBrian Somers       memmove(range->port + p + 1, range->port + p,
146da477886SBrian Somers               (range->nports - p) * sizeof(u_short));
147da477886SBrian Somers       range->port[p] = port;
148da477886SBrian Somers       range->nports++;
149442f8495SBrian Somers       break;
150442f8495SBrian Somers     }
151442f8495SBrian Somers 
152da477886SBrian Somers   if (p == range->nports)
153da477886SBrian Somers     range->port[range->nports++] = port;
154442f8495SBrian Somers }
155442f8495SBrian Somers 
156442f8495SBrian Somers void
157da477886SBrian Somers ipcp_RemoveUrgentPort(struct port_range *range, u_short port)
158442f8495SBrian Somers {
159442f8495SBrian Somers   int p;
160442f8495SBrian Somers 
161da477886SBrian Somers   for (p = 0; p < range->nports; p++)
162da477886SBrian Somers     if (range->port[p] == port) {
163da477886SBrian Somers       if (p != range->nports - 1)
164da477886SBrian Somers         memmove(range->port + p, range->port + p + 1,
165da477886SBrian Somers                 (range->nports - p - 1) * sizeof(u_short));
166da477886SBrian Somers       range->nports--;
167442f8495SBrian Somers       return;
168442f8495SBrian Somers     }
169442f8495SBrian Somers 
170da477886SBrian Somers   if (p == range->nports)
171442f8495SBrian Somers     log_Printf(LogWARN, "%u: Port not set to urgent\n", port);
172442f8495SBrian Somers }
173442f8495SBrian Somers 
174442f8495SBrian Somers void
175da477886SBrian Somers ipcp_ClearUrgentPorts(struct port_range *range)
176442f8495SBrian Somers {
177da477886SBrian Somers   range->nports = 0;
178442f8495SBrian Somers }
179442f8495SBrian Somers 
18029e275ceSBrian Somers struct compreq {
18129e275ceSBrian Somers   u_short proto;
18229e275ceSBrian Somers   u_char slots;
18329e275ceSBrian Somers   u_char compcid;
18429e275ceSBrian Somers };
18575240ed1SBrian Somers 
1866f384573SBrian Somers static int IpcpLayerUp(struct fsm *);
1871ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *);
188927145beSBrian Somers static void IpcpLayerStart(struct fsm *);
189927145beSBrian Somers static void IpcpLayerFinish(struct fsm *);
190479508cfSBrian Somers static void IpcpInitRestartCounter(struct fsm *, int);
1917308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *);
1922267893fSBrian Somers static void IpcpSentTerminateReq(struct fsm *);
1932267893fSBrian Somers static void IpcpSendTerminateAck(struct fsm *, u_char);
19430c2f2ffSBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, int, int,
19530c2f2ffSBrian Somers                              struct fsm_decode *);
196af57ed9fSAtsushi Murai 
19783d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = {
198af57ed9fSAtsushi Murai   IpcpLayerUp,
199af57ed9fSAtsushi Murai   IpcpLayerDown,
200af57ed9fSAtsushi Murai   IpcpLayerStart,
201af57ed9fSAtsushi Murai   IpcpLayerFinish,
202af57ed9fSAtsushi Murai   IpcpInitRestartCounter,
203af57ed9fSAtsushi Murai   IpcpSendConfigReq,
2042267893fSBrian Somers   IpcpSentTerminateReq,
205af57ed9fSAtsushi Murai   IpcpSendTerminateAck,
206af57ed9fSAtsushi Murai   IpcpDecodeConfig,
207dd7e2610SBrian Somers   fsm_NullRecvResetReq,
208dd7e2610SBrian Somers   fsm_NullRecvResetAck
209af57ed9fSAtsushi Murai };
210af57ed9fSAtsushi Murai 
211b6e82f33SBrian Somers static const char *cftypes[] = {
2129e836af5SBrian Somers   /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
2139e836af5SBrian Somers   "???",
2149e836af5SBrian Somers   "IPADDRS",	/* 1: IP-Addresses */	/* deprecated */
2159e836af5SBrian Somers   "COMPPROTO",	/* 2: IP-Compression-Protocol */
2169e836af5SBrian Somers   "IPADDR",	/* 3: IP-Address */
217af57ed9fSAtsushi Murai };
218af57ed9fSAtsushi Murai 
21970ee81ffSBrian Somers #define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
2209e836af5SBrian Somers 
221b6e82f33SBrian Somers static const char *cftypes128[] = {
2229e836af5SBrian Somers   /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
2239e836af5SBrian Somers   "???",
2249e836af5SBrian Somers   "PRIDNS",	/* 129: Primary DNS Server Address */
2259e836af5SBrian Somers   "PRINBNS",	/* 130: Primary NBNS Server Address */
2269e836af5SBrian Somers   "SECDNS",	/* 131: Secondary DNS Server Address */
2279e836af5SBrian Somers   "SECNBNS",	/* 132: Secondary NBNS Server Address */
2289e836af5SBrian Somers };
2299e836af5SBrian Somers 
23070ee81ffSBrian Somers #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0])
2319e836af5SBrian Somers 
2329a0b991fSBrian Somers void
2335828db6dSBrian Somers ipcp_AddInOctets(struct ipcp *ipcp, int n)
234af57ed9fSAtsushi Murai {
2355828db6dSBrian Somers   throughput_addin(&ipcp->throughput, n);
236af57ed9fSAtsushi Murai }
237af57ed9fSAtsushi Murai 
2389a0b991fSBrian Somers void
2395828db6dSBrian Somers ipcp_AddOutOctets(struct ipcp *ipcp, int n)
240af57ed9fSAtsushi Murai {
2415828db6dSBrian Somers   throughput_addout(&ipcp->throughput, n);
2421ae349f5Scvs2svn }
2431ae349f5Scvs2svn 
2443edeb0c6SBrian Somers static void
2453edeb0c6SBrian Somers getdns(struct ipcp *ipcp, struct in_addr addr[2])
2463edeb0c6SBrian Somers {
2473edeb0c6SBrian Somers   FILE *fp;
2483edeb0c6SBrian Somers 
2493edeb0c6SBrian Somers   addr[0].s_addr = addr[1].s_addr = INADDR_ANY;
2503edeb0c6SBrian Somers   if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
2513edeb0c6SBrian Somers     char buf[LINE_LEN], *cp, *end;
2523edeb0c6SBrian Somers     int n;
2533edeb0c6SBrian Somers 
2543edeb0c6SBrian Somers     n = 0;
2553edeb0c6SBrian Somers     buf[sizeof buf - 1] = '\0';
2563edeb0c6SBrian Somers     while (fgets(buf, sizeof buf - 1, fp)) {
2573edeb0c6SBrian Somers       if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) {
2583edeb0c6SBrian Somers         for (cp = buf + 11; issep(*cp); cp++)
2593edeb0c6SBrian Somers           ;
2603edeb0c6SBrian Somers         for (end = cp; isip(*end); end++)
2613edeb0c6SBrian Somers           ;
2623edeb0c6SBrian Somers         *end = '\0';
2633edeb0c6SBrian Somers         if (inet_aton(cp, addr+n) && ++n == 2)
2643edeb0c6SBrian Somers           break;
2653edeb0c6SBrian Somers       }
2663edeb0c6SBrian Somers     }
2673edeb0c6SBrian Somers     if (n == 1)
2683edeb0c6SBrian Somers       addr[1] = addr[0];
2693edeb0c6SBrian Somers     fclose(fp);
2703edeb0c6SBrian Somers   }
2713edeb0c6SBrian Somers }
2723edeb0c6SBrian Somers 
2733edeb0c6SBrian Somers static int
2743edeb0c6SBrian Somers setdns(struct ipcp *ipcp, struct in_addr addr[2])
2753edeb0c6SBrian Somers {
2763edeb0c6SBrian Somers   FILE *fp;
2773edeb0c6SBrian Somers   char wbuf[LINE_LEN + 54];
2783edeb0c6SBrian Somers   int wlen;
2793edeb0c6SBrian Somers 
2803edeb0c6SBrian Somers   if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) {
2813edeb0c6SBrian Somers     struct in_addr old[2];
2823edeb0c6SBrian Somers 
2833edeb0c6SBrian Somers     getdns(ipcp, old);
2843edeb0c6SBrian Somers     if (addr[0].s_addr == INADDR_ANY)
2853edeb0c6SBrian Somers       addr[0] = old[0];
2863edeb0c6SBrian Somers     if (addr[1].s_addr == INADDR_ANY)
2873edeb0c6SBrian Somers       addr[1] = old[1];
2883edeb0c6SBrian Somers   }
2893edeb0c6SBrian Somers 
2903edeb0c6SBrian Somers   if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) {
291dd7e2610SBrian Somers     log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n",
2923edeb0c6SBrian Somers               _PATH_RESCONF);
2933edeb0c6SBrian Somers     return 0;
2943edeb0c6SBrian Somers   }
2953edeb0c6SBrian Somers 
2963edeb0c6SBrian Somers   wlen = 0;
2973edeb0c6SBrian Somers   if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
2983edeb0c6SBrian Somers     char buf[LINE_LEN];
2993edeb0c6SBrian Somers     int len;
3003edeb0c6SBrian Somers 
3013edeb0c6SBrian Somers     buf[sizeof buf - 1] = '\0';
3023edeb0c6SBrian Somers     while (fgets(buf, sizeof buf - 1, fp)) {
3033edeb0c6SBrian Somers       if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) {
3043edeb0c6SBrian Somers         len = strlen(buf);
3053edeb0c6SBrian Somers         if (len > sizeof wbuf - wlen) {
306dd7e2610SBrian Somers           log_Printf(LogWARN, "%s: Can only cope with max file size %d\n",
3073edeb0c6SBrian Somers                     _PATH_RESCONF, LINE_LEN);
3083edeb0c6SBrian Somers           fclose(fp);
3093edeb0c6SBrian Somers           return 0;
3103edeb0c6SBrian Somers         }
3113edeb0c6SBrian Somers         memcpy(wbuf + wlen, buf, len);
3123edeb0c6SBrian Somers         wlen += len;
3133edeb0c6SBrian Somers       }
3143edeb0c6SBrian Somers     }
3153edeb0c6SBrian Somers     fclose(fp);
3163edeb0c6SBrian Somers   }
3173edeb0c6SBrian Somers 
3183edeb0c6SBrian Somers   if (addr[0].s_addr != INADDR_ANY) {
3193edeb0c6SBrian Somers     snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n",
3203edeb0c6SBrian Somers              inet_ntoa(addr[0]));
321dd7e2610SBrian Somers     log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11);
3223edeb0c6SBrian Somers     wlen += strlen(wbuf + wlen);
3233edeb0c6SBrian Somers   }
3243edeb0c6SBrian Somers 
3253edeb0c6SBrian Somers   if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) {
3263edeb0c6SBrian Somers     snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n",
3273edeb0c6SBrian Somers              inet_ntoa(addr[1]));
328dd7e2610SBrian Somers     log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11);
3293edeb0c6SBrian Somers     wlen += strlen(wbuf + wlen);
3303edeb0c6SBrian Somers   }
3313edeb0c6SBrian Somers 
3323edeb0c6SBrian Somers   if (wlen) {
3333edeb0c6SBrian Somers     int fd;
3343edeb0c6SBrian Somers 
3353edeb0c6SBrian Somers     if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) {
3363edeb0c6SBrian Somers       if (write(fd, wbuf, wlen) != wlen) {
337dd7e2610SBrian Somers         log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno));
3383edeb0c6SBrian Somers         close(fd);
3393edeb0c6SBrian Somers         return 0;
3403edeb0c6SBrian Somers       }
3413edeb0c6SBrian Somers       if (ftruncate(fd, wlen) == -1) {
342dd7e2610SBrian Somers         log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno));
3433edeb0c6SBrian Somers         close(fd);
3443edeb0c6SBrian Somers         return 0;
3453edeb0c6SBrian Somers       }
3463edeb0c6SBrian Somers       close(fd);
3473edeb0c6SBrian Somers     } else {
348dd7e2610SBrian Somers       log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno));
3493edeb0c6SBrian Somers       return 0;
3503edeb0c6SBrian Somers     }
3513edeb0c6SBrian Somers   }
3523edeb0c6SBrian Somers 
3533edeb0c6SBrian Somers   return 1;
354af57ed9fSAtsushi Murai }
355af57ed9fSAtsushi Murai 
356274e766cSBrian Somers int
357dd7e2610SBrian Somers ipcp_Show(struct cmdargs const *arg)
358af57ed9fSAtsushi Murai {
359610b185fSBrian Somers   struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
360442f8495SBrian Somers   int p;
361af57ed9fSAtsushi Murai 
362610b185fSBrian Somers   prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name,
363610b185fSBrian Somers                 State2Nam(ipcp->fsm.state));
364610b185fSBrian Somers   if (ipcp->fsm.state == ST_OPENED) {
365b6217683SBrian Somers     prompt_Printf(arg->prompt, " His side:        %s, %s\n",
366610b185fSBrian Somers 	          inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto));
367b6217683SBrian Somers     prompt_Printf(arg->prompt, " My side:         %s, %s\n",
368610b185fSBrian Somers 	          inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto));
369442f8495SBrian Somers     prompt_Printf(arg->prompt, " Queued packets:  %d\n", ip_QueueLen(ipcp));
370d1a3ea47SBrian Somers   }
3715b4c5b00SBrian Somers 
372610b185fSBrian Somers   if (ipcp->route) {
373610b185fSBrian Somers     prompt_Printf(arg->prompt, "\n");
374972a1bcfSBrian Somers     route_ShowSticky(arg->prompt, ipcp->route, "Sticky routes", 1);
3751ae349f5Scvs2svn   }
376927145beSBrian Somers 
377b6217683SBrian Somers   prompt_Printf(arg->prompt, "\nDefaults:\n");
378479508cfSBrian Somers   prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config"
379479508cfSBrian Somers                 " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout,
380479508cfSBrian Somers                 ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s",
381479508cfSBrian Somers                 ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s");
38250abd4c8SBrian Somers   prompt_Printf(arg->prompt, " My Address:      %s/%d",
383610b185fSBrian Somers 	        inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width);
384bc76350eSBrian Somers   prompt_Printf(arg->prompt, ", netmask %s\n", inet_ntoa(ipcp->cfg.netmask));
385610b185fSBrian Somers   if (ipcp->cfg.HaveTriggerAddress)
386bc76350eSBrian Somers     prompt_Printf(arg->prompt, " Trigger address: %s\n",
387610b185fSBrian Somers                   inet_ntoa(ipcp->cfg.TriggerAddress));
388bc76350eSBrian Somers 
389bc76350eSBrian Somers   prompt_Printf(arg->prompt, " VJ compression:  %s (%d slots %s slot "
390610b185fSBrian Somers                 "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg),
391610b185fSBrian Somers                 ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without");
39250abd4c8SBrian Somers 
393610b185fSBrian Somers   if (iplist_isvalid(&ipcp->cfg.peer_list))
394b6217683SBrian Somers     prompt_Printf(arg->prompt, " His Address:     %s\n",
395610b185fSBrian Somers                   ipcp->cfg.peer_list.src);
3961ae349f5Scvs2svn   else
397b6217683SBrian Somers     prompt_Printf(arg->prompt, " His Address:     %s/%d\n",
398610b185fSBrian Somers 	          inet_ntoa(ipcp->cfg.peer_range.ipaddr),
399610b185fSBrian Somers                   ipcp->cfg.peer_range.width);
40050abd4c8SBrian Somers 
4013edeb0c6SBrian Somers   prompt_Printf(arg->prompt, " DNS:             %s, ",
402610b185fSBrian Somers                 inet_ntoa(ipcp->cfg.ns.dns[0]));
403610b185fSBrian Somers   prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]),
404610b185fSBrian Somers                 command_ShowNegval(ipcp->cfg.ns.dns_neg));
4053edeb0c6SBrian Somers   prompt_Printf(arg->prompt, " NetBIOS NS:      %s, ",
406610b185fSBrian Somers 	        inet_ntoa(ipcp->cfg.ns.nbns[0]));
407610b185fSBrian Somers   prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1]));
4081342caedSBrian Somers 
409da477886SBrian Somers   prompt_Printf(arg->prompt, " Urgent ports\n");
410da477886SBrian Somers   prompt_Printf(arg->prompt, "          TCP:    ");
411da477886SBrian Somers   if (ipcp->cfg.urgent.tcp.nports == 0)
412442f8495SBrian Somers     prompt_Printf(arg->prompt, "none");
413442f8495SBrian Somers   else
414da477886SBrian Somers     for (p = 0; p < ipcp->cfg.urgent.tcp.nports; p++) {
415442f8495SBrian Somers       if (p)
416442f8495SBrian Somers         prompt_Printf(arg->prompt, ", ");
417da477886SBrian Somers       prompt_Printf(arg->prompt, "%u", ipcp->cfg.urgent.tcp.port[p]);
418da477886SBrian Somers     }
419da477886SBrian Somers   prompt_Printf(arg->prompt, "\n          UDP:    ");
420da477886SBrian Somers   if (ipcp->cfg.urgent.udp.nports == 0)
421da477886SBrian Somers     prompt_Printf(arg->prompt, "none");
422da477886SBrian Somers   else
423da477886SBrian Somers     for (p = 0; p < ipcp->cfg.urgent.udp.nports; p++) {
424da477886SBrian Somers       if (p)
425da477886SBrian Somers         prompt_Printf(arg->prompt, ", ");
426da477886SBrian Somers       prompt_Printf(arg->prompt, "%u", ipcp->cfg.urgent.udp.port[p]);
427442f8495SBrian Somers     }
428442f8495SBrian Somers 
429442f8495SBrian Somers   prompt_Printf(arg->prompt, "\n\n");
430610b185fSBrian Somers   throughput_disp(&ipcp->throughput, arg->prompt);
4319a0b991fSBrian Somers 
432927145beSBrian Somers   return 0;
433af57ed9fSAtsushi Murai }
434af57ed9fSAtsushi Murai 
435d1a3ea47SBrian Somers int
436dd7e2610SBrian Somers ipcp_vjset(struct cmdargs const *arg)
437d1a3ea47SBrian Somers {
43825092092SBrian Somers   if (arg->argc != arg->argn+2)
439d1a3ea47SBrian Somers     return -1;
44025092092SBrian Somers   if (!strcasecmp(arg->argv[arg->argn], "slots")) {
441d1a3ea47SBrian Somers     int slots;
442d1a3ea47SBrian Somers 
44325092092SBrian Somers     slots = atoi(arg->argv[arg->argn+1]);
444d1a3ea47SBrian Somers     if (slots < 4 || slots > 16)
445d1a3ea47SBrian Somers       return 1;
4461342caedSBrian Somers     arg->bundle->ncp.ipcp.cfg.vj.slots = slots;
447d1a3ea47SBrian Somers     return 0;
44825092092SBrian Somers   } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) {
44925092092SBrian Somers     if (!strcasecmp(arg->argv[arg->argn+1], "on"))
4501342caedSBrian Somers       arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1;
45125092092SBrian Somers     else if (!strcasecmp(arg->argv[arg->argn+1], "off"))
4521342caedSBrian Somers       arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0;
453d1a3ea47SBrian Somers     else
454d1a3ea47SBrian Somers       return 2;
455d1a3ea47SBrian Somers     return 0;
456d1a3ea47SBrian Somers   }
457d1a3ea47SBrian Somers   return -1;
458d1a3ea47SBrian Somers }
459d1a3ea47SBrian Somers 
4601ae349f5Scvs2svn void
4616d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
4626d666775SBrian Somers           const struct fsm_parent *parent)
463d1a3ea47SBrian Somers {
464503a7782SBrian Somers   struct hostent *hp;
465503a7782SBrian Somers   char name[MAXHOSTNAMELEN];
4663b0f8d2eSBrian Somers   static const char *timer_names[] =
4673b0f8d2eSBrian Somers     {"IPCP restart", "IPCP openmode", "IPCP stopped"};
46829e275ceSBrian Somers 
469479508cfSBrian Somers   fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP,
4703b0f8d2eSBrian Somers            bundle, l, parent, &ipcp_Callbacks, timer_names);
471503a7782SBrian Somers 
472610b185fSBrian Somers   ipcp->route = NULL;
4731342caedSBrian Somers   ipcp->cfg.vj.slots = DEF_VJ_STATES;
4741342caedSBrian Somers   ipcp->cfg.vj.slotcomp = 1;
475503a7782SBrian Somers   memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range);
476503a7782SBrian Somers   if (gethostname(name, sizeof name) == 0) {
477503a7782SBrian Somers     hp = gethostbyname(name);
4788fa6ebe4SBrian Somers     if (hp && hp->h_addrtype == AF_INET)
479503a7782SBrian Somers       memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length);
480503a7782SBrian Somers   }
48130c2f2ffSBrian Somers   ipcp->cfg.netmask.s_addr = INADDR_ANY;
482503a7782SBrian Somers   memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
483503a7782SBrian Somers   iplist_setsrc(&ipcp->cfg.peer_list, "");
484503a7782SBrian Somers   ipcp->cfg.HaveTriggerAddress = 0;
485503a7782SBrian Somers 
4863edeb0c6SBrian Somers   ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY;
4873edeb0c6SBrian Somers   ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY;
4883edeb0c6SBrian Somers   ipcp->cfg.ns.dns_neg = 0;
4893edeb0c6SBrian Somers   ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY;
4903edeb0c6SBrian Somers   ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY;
491cd9647a1SBrian Somers 
492da477886SBrian Somers   ipcp->cfg.urgent.tcp.nports = ipcp->cfg.urgent.tcp.maxports = NDEFTCPPORTS;
493da477886SBrian Somers   ipcp->cfg.urgent.tcp.port = (u_short *)malloc(NDEFTCPPORTS * sizeof(u_short));
494da477886SBrian Somers   memcpy(ipcp->cfg.urgent.tcp.port, default_urgent_tcp_ports,
495da477886SBrian Somers          NDEFTCPPORTS * sizeof(u_short));
496da477886SBrian Somers 
497da477886SBrian Somers   ipcp->cfg.urgent.udp.nports = ipcp->cfg.urgent.udp.maxports = NDEFUDPPORTS;
498da477886SBrian Somers   ipcp->cfg.urgent.udp.port = (u_short *)malloc(NDEFUDPPORTS * sizeof(u_short));
499da477886SBrian Somers   memcpy(ipcp->cfg.urgent.udp.port, default_urgent_udp_ports,
500da477886SBrian Somers          NDEFUDPPORTS * sizeof(u_short));
501442f8495SBrian Somers 
502479508cfSBrian Somers   ipcp->cfg.fsm.timeout = DEF_FSMRETRY;
503479508cfSBrian Somers   ipcp->cfg.fsm.maxreq = DEF_FSMTRIES;
504479508cfSBrian Somers   ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES;
5051342caedSBrian Somers   ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED;
506503a7782SBrian Somers 
507eaa4df37SBrian Somers   memset(&ipcp->vj, '\0', sizeof ipcp->vj);
508eaa4df37SBrian Somers 
509ab2de065SBrian Somers   throughput_init(&ipcp->throughput, SAMPLE_PERIOD);
5105a72b6edSBrian Somers   memset(ipcp->Queue, '\0', sizeof ipcp->Queue);
511972a1bcfSBrian Somers   ipcp_Setup(ipcp, INADDR_NONE);
512d1a3ea47SBrian Somers }
513d1a3ea47SBrian Somers 
514af57ed9fSAtsushi Murai void
515442f8495SBrian Somers ipcp_Destroy(struct ipcp *ipcp)
516442f8495SBrian Somers {
517da477886SBrian Somers   if (ipcp->cfg.urgent.tcp.maxports) {
518da477886SBrian Somers     ipcp->cfg.urgent.tcp.nports = ipcp->cfg.urgent.tcp.maxports = 0;
519da477886SBrian Somers     free(ipcp->cfg.urgent.tcp.port);
520da477886SBrian Somers     ipcp->cfg.urgent.tcp.port = NULL;
521da477886SBrian Somers   }
522da477886SBrian Somers   if (ipcp->cfg.urgent.udp.maxports) {
523da477886SBrian Somers     ipcp->cfg.urgent.udp.nports = ipcp->cfg.urgent.udp.maxports = 0;
524da477886SBrian Somers     free(ipcp->cfg.urgent.udp.port);
525da477886SBrian Somers     ipcp->cfg.urgent.udp.port = NULL;
526442f8495SBrian Somers   }
527442f8495SBrian Somers }
528442f8495SBrian Somers 
529442f8495SBrian Somers void
530ce828a6eSBrian Somers ipcp_SetLink(struct ipcp *ipcp, struct link *l)
531af57ed9fSAtsushi Murai {
532ce828a6eSBrian Somers   ipcp->fsm.link = l;
533af57ed9fSAtsushi Murai }
534549d663dSAtsushi Murai 
535ce828a6eSBrian Somers void
536972a1bcfSBrian Somers ipcp_Setup(struct ipcp *ipcp, u_int32_t mask)
537503a7782SBrian Somers {
5388fa6ebe4SBrian Somers   struct iface *iface = ipcp->fsm.bundle->iface;
5398fa6ebe4SBrian Somers   int pos, n;
540503a7782SBrian Somers 
541503a7782SBrian Somers   ipcp->fsm.open_mode = 0;
542972a1bcfSBrian Somers   ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask;
543503a7782SBrian Somers 
544503a7782SBrian Somers   if (iplist_isvalid(&ipcp->cfg.peer_list)) {
5458fa6ebe4SBrian Somers     /* Try to give the peer a previously configured IP address */
5468fa6ebe4SBrian Somers     for (n = 0; n < iface->in_addrs; n++) {
5478fa6ebe4SBrian Somers       pos = iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd);
5488fa6ebe4SBrian Somers       if (pos != -1) {
5498fa6ebe4SBrian Somers         ipcp->cfg.peer_range.ipaddr =
5508fa6ebe4SBrian Somers           iplist_setcurpos(&ipcp->cfg.peer_list, pos);
5518fa6ebe4SBrian Somers         break;
5528fa6ebe4SBrian Somers       }
5538fa6ebe4SBrian Somers     }
5548fa6ebe4SBrian Somers     if (n == iface->in_addrs)
5558fa6ebe4SBrian Somers       /* Ok, so none of 'em fit.... pick a random one */
556503a7782SBrian Somers       ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list);
5578fa6ebe4SBrian Somers 
558503a7782SBrian Somers     ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
559503a7782SBrian Somers     ipcp->cfg.peer_range.width = 32;
560503a7782SBrian Somers   }
561503a7782SBrian Somers 
562503a7782SBrian Somers   ipcp->heis1172 = 0;
563503a7782SBrian Somers 
564503a7782SBrian Somers   ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr;
565503a7782SBrian Somers   ipcp->peer_compproto = 0;
5661ae349f5Scvs2svn 
5678390b576SBrian Somers   if (ipcp->cfg.HaveTriggerAddress) {
568549d663dSAtsushi Murai     /*
5695b4c5b00SBrian Somers      * Some implementations of PPP require that we send a
5705b4c5b00SBrian Somers      * *special* value as our address, even though the rfc specifies
5715b4c5b00SBrian Somers      * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
572549d663dSAtsushi Murai      */
573503a7782SBrian Somers     ipcp->my_ip = ipcp->cfg.TriggerAddress;
574dd7e2610SBrian Somers     log_Printf(LogIPCP, "Using trigger address %s\n",
575503a7782SBrian Somers               inet_ntoa(ipcp->cfg.TriggerAddress));
5768fa6ebe4SBrian Somers   } else {
5778390b576SBrian Somers     /*
5788fa6ebe4SBrian Somers      * Otherwise, if we've used an IP number before and it's still within
5798fa6ebe4SBrian Somers      * the network specified on the ``set ifaddr'' line, we really
5808fa6ebe4SBrian Somers      * want to keep that IP number so that we can keep any existing
5818fa6ebe4SBrian Somers      * connections that are bound to that IP (assuming we're not
5828fa6ebe4SBrian Somers      * ``iface-alias''ing).
5838390b576SBrian Somers      */
5848fa6ebe4SBrian Somers     for (n = 0; n < iface->in_addrs; n++)
5858fa6ebe4SBrian Somers       if ((iface->in_addr[n].ifa.s_addr & ipcp->cfg.my_range.mask.s_addr) ==
5868fa6ebe4SBrian Somers           (ipcp->cfg.my_range.ipaddr.s_addr & ipcp->cfg.my_range.mask.s_addr)) {
5878fa6ebe4SBrian Somers         ipcp->my_ip = iface->in_addr[n].ifa;
5888fa6ebe4SBrian Somers         break;
5898fa6ebe4SBrian Somers       }
5908fa6ebe4SBrian Somers     if (n == iface->in_addrs)
591503a7782SBrian Somers       ipcp->my_ip = ipcp->cfg.my_range.ipaddr;
5928fa6ebe4SBrian Somers   }
59329e275ceSBrian Somers 
594972a1bcfSBrian Somers   if (IsEnabled(ipcp->cfg.vj.neg)
595972a1bcfSBrian Somers #ifndef NORADIUS
596972a1bcfSBrian Somers       || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj)
597972a1bcfSBrian Somers #endif
598972a1bcfSBrian Somers      )
599503a7782SBrian Somers     ipcp->my_compproto = (PROTO_VJCOMP << 16) +
6001342caedSBrian Somers                          ((ipcp->cfg.vj.slots - 1) << 8) +
6011342caedSBrian Somers                          ipcp->cfg.vj.slotcomp;
6021ae349f5Scvs2svn   else
603503a7782SBrian Somers     ipcp->my_compproto = 0;
6041342caedSBrian Somers   sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1);
60529e275ceSBrian Somers 
606503a7782SBrian Somers   ipcp->peer_reject = 0;
607503a7782SBrian Somers   ipcp->my_reject = 0;
6081ae349f5Scvs2svn }
6091ae349f5Scvs2svn 
610455aabc3SBrian Somers static int
6113afe5ccbSBrian Somers ipcp_doproxyall(struct bundle *bundle,
6123afe5ccbSBrian Somers                 int (*proxyfun)(struct bundle *, struct in_addr, int), int s)
6133afe5ccbSBrian Somers {
6143afe5ccbSBrian Somers   int n, ret;
6153afe5ccbSBrian Somers   struct sticky_route *rp;
6163afe5ccbSBrian Somers   struct in_addr addr;
6173afe5ccbSBrian Somers   struct ipcp *ipcp;
6183afe5ccbSBrian Somers 
6193afe5ccbSBrian Somers   ipcp = &bundle->ncp.ipcp;
6203afe5ccbSBrian Somers   for (rp = ipcp->route; rp != NULL; rp = rp->next) {
621bc76350eSBrian Somers     if (rp->mask.s_addr == INADDR_BROADCAST)
6223afe5ccbSBrian Somers         continue;
623bc76350eSBrian Somers     n = ntohl(INADDR_BROADCAST) - ntohl(rp->mask.s_addr) - 1;
6243afe5ccbSBrian Somers     if (n > 0 && n <= 254 && rp->dst.s_addr != INADDR_ANY) {
6253afe5ccbSBrian Somers       addr = rp->dst;
6263afe5ccbSBrian Somers       while (n--) {
6273afe5ccbSBrian Somers         addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
6283afe5ccbSBrian Somers 	log_Printf(LogDEBUG, "ipcp_doproxyall: %s\n", inet_ntoa(addr));
6293afe5ccbSBrian Somers 	ret = (*proxyfun)(bundle, addr, s);
6303afe5ccbSBrian Somers 	if (!ret)
6313afe5ccbSBrian Somers 	  return ret;
6323afe5ccbSBrian Somers       }
6333afe5ccbSBrian Somers     }
6343afe5ccbSBrian Somers   }
6353afe5ccbSBrian Somers 
6363afe5ccbSBrian Somers   return 0;
6373afe5ccbSBrian Somers }
6383afe5ccbSBrian Somers 
6393afe5ccbSBrian Somers static int
64030c2f2ffSBrian Somers ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr,
64130c2f2ffSBrian Somers                   struct in_addr hisaddr, int silent)
642455aabc3SBrian Somers {
64368645f39SBrian Somers   struct in_addr mask, oaddr, none = { INADDR_ANY };
644455aabc3SBrian Somers 
645bc76350eSBrian Somers   mask = addr2mask(myaddr);
646455aabc3SBrian Somers 
647972a1bcfSBrian Somers   if (bundle->ncp.ipcp.ifmask.s_addr != INADDR_ANY &&
648bc76350eSBrian Somers       (bundle->ncp.ipcp.ifmask.s_addr & mask.s_addr) == mask.s_addr)
649bc76350eSBrian Somers     mask.s_addr = bundle->ncp.ipcp.ifmask.s_addr;
650455aabc3SBrian Somers 
6518fa6ebe4SBrian Somers   oaddr.s_addr = bundle->iface->in_addrs ?
6528fa6ebe4SBrian Somers                  bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY;
6538fa6ebe4SBrian Somers   if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr,
6548fa6ebe4SBrian Somers                  IFACE_ADD_FIRST|IFACE_FORCE_ADD))
6558fa6ebe4SBrian Somers     return -1;
656455aabc3SBrian Somers 
6578fa6ebe4SBrian Somers   if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1
6588fa6ebe4SBrian Somers       && myaddr.s_addr != oaddr.s_addr)
6598fa6ebe4SBrian Somers     /* Nuke the old one */
6608fa6ebe4SBrian Somers     iface_inDelete(bundle->iface, oaddr);
661455aabc3SBrian Somers 
6623afe5ccbSBrian Somers   if (bundle->ncp.ipcp.cfg.sendpipe > 0 || bundle->ncp.ipcp.cfg.recvpipe > 0)
6633afe5ccbSBrian Somers     bundle_SetRoute(bundle, RTM_CHANGE, hisaddr, myaddr, none, 0, 0);
6643afe5ccbSBrian Somers 
665610b185fSBrian Somers   if (Enabled(bundle, OPT_SROUTES))
666610b185fSBrian Somers     route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr);
667610b185fSBrian Somers 
668972a1bcfSBrian Somers #ifndef NORADIUS
669972a1bcfSBrian Somers   if (bundle->radius.valid)
670972a1bcfSBrian Somers     route_Change(bundle, bundle->radius.routes, myaddr, hisaddr);
671972a1bcfSBrian Somers #endif
672972a1bcfSBrian Somers 
6733afe5ccbSBrian Somers   if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) {
6748fa6ebe4SBrian Somers     int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
6758fa6ebe4SBrian Somers     if (s < 0)
6768fa6ebe4SBrian Somers       log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n",
6778fa6ebe4SBrian Somers                  strerror(errno));
6788fa6ebe4SBrian Somers     else {
6793afe5ccbSBrian Somers       if (Enabled(bundle, OPT_PROXYALL))
6803afe5ccbSBrian Somers         ipcp_doproxyall(bundle, arp_SetProxy, s);
6813afe5ccbSBrian Somers       else if (Enabled(bundle, OPT_PROXY))
6828fa6ebe4SBrian Somers         arp_SetProxy(bundle, hisaddr, s);
683455aabc3SBrian Somers       close(s);
6848fa6ebe4SBrian Somers     }
6858fa6ebe4SBrian Somers   }
6868fa6ebe4SBrian Somers 
6878fa6ebe4SBrian Somers   return 0;
688455aabc3SBrian Somers }
689455aabc3SBrian Somers 
690455aabc3SBrian Somers static struct in_addr
6918fa6ebe4SBrian Somers ChooseHisAddr(struct bundle *bundle, struct in_addr gw)
692455aabc3SBrian Somers {
693455aabc3SBrian Somers   struct in_addr try;
6943a2e4f62SBrian Somers   u_long f;
695455aabc3SBrian Somers 
6965828db6dSBrian Somers   for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) {
6975828db6dSBrian Somers     try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list);
6983a2e4f62SBrian Somers     log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n",
699455aabc3SBrian Somers               f, inet_ntoa(try));
70030c2f2ffSBrian Somers     if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) {
701dd7e2610SBrian Somers       log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try));
702455aabc3SBrian Somers       break;
703455aabc3SBrian Somers     }
704455aabc3SBrian Somers   }
705455aabc3SBrian Somers 
7065828db6dSBrian Somers   if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) {
707dd7e2610SBrian Somers     log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n");
708455aabc3SBrian Somers     try.s_addr = INADDR_ANY;
709455aabc3SBrian Somers   }
710455aabc3SBrian Somers 
711455aabc3SBrian Somers   return try;
712af57ed9fSAtsushi Murai }
713af57ed9fSAtsushi Murai 
714af57ed9fSAtsushi Murai static void
715479508cfSBrian Somers IpcpInitRestartCounter(struct fsm *fp, int what)
716af57ed9fSAtsushi Murai {
7177308ec68SBrian Somers   /* Set fsm timer load */
718cd9647a1SBrian Somers   struct ipcp *ipcp = fsm2ipcp(fp);
719cd9647a1SBrian Somers 
720479508cfSBrian Somers   fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS;
721479508cfSBrian Somers   switch (what) {
722479508cfSBrian Somers     case FSM_REQ_TIMER:
723479508cfSBrian Somers       fp->restart = ipcp->cfg.fsm.maxreq;
724479508cfSBrian Somers       break;
725479508cfSBrian Somers     case FSM_TRM_TIMER:
726479508cfSBrian Somers       fp->restart = ipcp->cfg.fsm.maxtrm;
727479508cfSBrian Somers       break;
728479508cfSBrian Somers     default:
729479508cfSBrian Somers       fp->restart = 1;
730479508cfSBrian Somers       break;
731479508cfSBrian Somers   }
732af57ed9fSAtsushi Murai }
733af57ed9fSAtsushi Murai 
734af57ed9fSAtsushi Murai static void
735944f7098SBrian Somers IpcpSendConfigReq(struct fsm *fp)
736af57ed9fSAtsushi Murai {
7377308ec68SBrian Somers   /* Send config REQ please */
7388c07a7b2SBrian Somers   struct physical *p = link2physical(fp->link);
739aad81d1eSBrian Somers   struct ipcp *ipcp = fsm2ipcp(fp);
7403edeb0c6SBrian Somers   u_char buff[24];
7412267893fSBrian Somers   struct lcp_opt *o;
742af57ed9fSAtsushi Murai 
7432267893fSBrian Somers   o = (struct lcp_opt *)buff;
74430c2f2ffSBrian Somers 
745dd7e2610SBrian Somers   if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) {
7469e8ec64bSBrian Somers     memcpy(o->data, &ipcp->my_ip.s_addr, 4);
7472267893fSBrian Somers     INC_LCP_OPT(TY_IPADDR, 6, o);
7480053cc58SBrian Somers   }
7490053cc58SBrian Somers 
750e43ebac1SBrian Somers   if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) {
75183d1af55SBrian Somers     if (ipcp->heis1172) {
7529e8ec64bSBrian Somers       u_int16_t proto = PROTO_VJCOMP;
7539e8ec64bSBrian Somers 
7549e8ec64bSBrian Somers       ua_htons(&proto, o->data);
7552267893fSBrian Somers       INC_LCP_OPT(TY_COMPPROTO, 4, o);
7560053cc58SBrian Somers     } else {
7577686a200SBrian Somers       struct compreq req;
7587686a200SBrian Somers 
7597686a200SBrian Somers       req.proto = htons(ipcp->my_compproto >> 16);
7607686a200SBrian Somers       req.slots = (ipcp->my_compproto >> 8) & 255;
7617686a200SBrian Somers       req.compcid = ipcp->my_compproto & 1;
7627686a200SBrian Somers       memcpy(o->data, &req, 4);
7632267893fSBrian Somers       INC_LCP_OPT(TY_COMPPROTO, 6, o);
7640053cc58SBrian Somers     }
765af57ed9fSAtsushi Murai   }
7662267893fSBrian Somers 
7673edeb0c6SBrian Somers   if (IsEnabled(ipcp->cfg.ns.dns_neg) &&
7683edeb0c6SBrian Somers       !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) &&
7693edeb0c6SBrian Somers       !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) {
7703edeb0c6SBrian Somers     struct in_addr dns[2];
7713edeb0c6SBrian Somers     getdns(ipcp, dns);
7729e8ec64bSBrian Somers     memcpy(o->data, &dns[0].s_addr, 4);
7733edeb0c6SBrian Somers     INC_LCP_OPT(TY_PRIMARY_DNS, 6, o);
7749e8ec64bSBrian Somers     memcpy(o->data, &dns[1].s_addr, 4);
7753edeb0c6SBrian Somers     INC_LCP_OPT(TY_SECONDARY_DNS, 6, o);
7763edeb0c6SBrian Somers   }
7773edeb0c6SBrian Somers 
778411675baSBrian Somers   fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
779411675baSBrian Somers              MB_IPCPOUT);
780af57ed9fSAtsushi Murai }
781af57ed9fSAtsushi Murai 
782af57ed9fSAtsushi Murai static void
7832267893fSBrian Somers IpcpSentTerminateReq(struct fsm *fp)
784af57ed9fSAtsushi Murai {
7857308ec68SBrian Somers   /* Term REQ just sent by FSM */
786af57ed9fSAtsushi Murai }
787af57ed9fSAtsushi Murai 
788af57ed9fSAtsushi Murai static void
7892267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id)
790af57ed9fSAtsushi Murai {
7917308ec68SBrian Somers   /* Send Term ACK please */
792411675baSBrian Somers   fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT);
793af57ed9fSAtsushi Murai }
794af57ed9fSAtsushi Murai 
795af57ed9fSAtsushi Murai static void
796944f7098SBrian Somers IpcpLayerStart(struct fsm *fp)
797af57ed9fSAtsushi Murai {
7987308ec68SBrian Somers   /* We're about to start up ! */
799897f9429SBrian Somers   struct ipcp *ipcp = fsm2ipcp(fp);
800897f9429SBrian Somers 
8013a2e4f62SBrian Somers   log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name);
802897f9429SBrian Somers   throughput_start(&ipcp->throughput, "IPCP throughput",
803897f9429SBrian Somers                    Enabled(fp->bundle, OPT_THROUGHPUT));
804479508cfSBrian Somers   fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3;
805af57ed9fSAtsushi Murai }
806af57ed9fSAtsushi Murai 
807af57ed9fSAtsushi Murai static void
808944f7098SBrian Somers IpcpLayerFinish(struct fsm *fp)
809af57ed9fSAtsushi Murai {
8107308ec68SBrian Somers   /* We're now down */
811897f9429SBrian Somers   struct ipcp *ipcp = fsm2ipcp(fp);
812897f9429SBrian Somers 
8133a2e4f62SBrian Somers   log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name);
814897f9429SBrian Somers   throughput_stop(&ipcp->throughput);
815897f9429SBrian Somers   throughput_log(&ipcp->throughput, LogIPCP, NULL);
8161ae349f5Scvs2svn }
8171ae349f5Scvs2svn 
81868a0f0ccSBrian Somers void
819dd7e2610SBrian Somers ipcp_CleanInterface(struct ipcp *ipcp)
82068a0f0ccSBrian Somers {
8218fa6ebe4SBrian Somers   struct iface *iface = ipcp->fsm.bundle->iface;
82268a0f0ccSBrian Somers 
823610b185fSBrian Somers   route_Clean(ipcp->fsm.bundle, ipcp->route);
824610b185fSBrian Somers 
8253afe5ccbSBrian Somers   if (iface->in_addrs && (Enabled(ipcp->fsm.bundle, OPT_PROXY) ||
8263afe5ccbSBrian Somers                           Enabled(ipcp->fsm.bundle, OPT_PROXYALL))) {
8278fa6ebe4SBrian Somers     int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
8288fa6ebe4SBrian Somers     if (s < 0)
8298fa6ebe4SBrian Somers       log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n",
83068a0f0ccSBrian Somers                  strerror(errno));
8318fa6ebe4SBrian Somers     else {
8323afe5ccbSBrian Somers       if (Enabled(ipcp->fsm.bundle, OPT_PROXYALL))
8333afe5ccbSBrian Somers         ipcp_doproxyall(ipcp->fsm.bundle, arp_ClearProxy, s);
8343afe5ccbSBrian Somers       else if (Enabled(ipcp->fsm.bundle, OPT_PROXY))
8358fa6ebe4SBrian Somers         arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s);
8368fa6ebe4SBrian Somers       close(s);
8378fa6ebe4SBrian Somers     }
83868a0f0ccSBrian Somers   }
83968a0f0ccSBrian Somers 
8408fa6ebe4SBrian Somers   iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL);
841af57ed9fSAtsushi Murai }
842af57ed9fSAtsushi Murai 
843af57ed9fSAtsushi Murai static void
844944f7098SBrian Somers IpcpLayerDown(struct fsm *fp)
845af57ed9fSAtsushi Murai {
8467308ec68SBrian Somers   /* About to come down */
847aa857470SBrian Somers   static int recursing;
848aad81d1eSBrian Somers   struct ipcp *ipcp = fsm2ipcp(fp);
849455aabc3SBrian Somers   const char *s;
850455aabc3SBrian Somers 
851aa857470SBrian Somers   if (!recursing++) {
8528fa6ebe4SBrian Somers     if (ipcp->fsm.bundle->iface->in_addrs)
8538fa6ebe4SBrian Somers       s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa);
8548fa6ebe4SBrian Somers     else
8558fa6ebe4SBrian Somers       s = "Interface configuration error !";
8563a2e4f62SBrian Somers     log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s);
857455aabc3SBrian Somers 
858455aabc3SBrian Somers     /*
859455aabc3SBrian Somers      * XXX this stuff should really live in the FSM.  Our config should
860455aabc3SBrian Somers      * associate executable sections in files with events.
861455aabc3SBrian Somers      */
86230291ffbSBrian Somers     if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) {
86349052c95SBrian Somers       if (bundle_GetLabel(fp->bundle)) {
864dd7e2610SBrian Somers          if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
86530291ffbSBrian Somers                           LINKDOWNFILE, NULL, NULL) < 0)
86630291ffbSBrian Somers          system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
867455aabc3SBrian Somers       } else
86830291ffbSBrian Somers         system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
869af57ed9fSAtsushi Murai     }
870af57ed9fSAtsushi Murai 
871972a1bcfSBrian Somers     ipcp_Setup(ipcp, INADDR_NONE);
8721ae349f5Scvs2svn   }
873aa857470SBrian Somers   recursing--;
874aa857470SBrian Somers }
8751ae349f5Scvs2svn 
876dd0645c5SBrian Somers int
877dd0645c5SBrian Somers ipcp_InterfaceUp(struct ipcp *ipcp)
878dd0645c5SBrian Somers {
879dd0645c5SBrian Somers   if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) {
880a33b2ef7SBrian Somers     log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n");
881dd0645c5SBrian Somers     return 0;
882dd0645c5SBrian Somers   }
883dd0645c5SBrian Somers 
88467b072f7SBrian Somers #ifndef NONAT
88567b072f7SBrian Somers   if (ipcp->fsm.bundle->NatEnabled)
886615ad4f9SBrian Somers     PacketAliasSetAddress(ipcp->my_ip);
887dd0645c5SBrian Somers #endif
888dd0645c5SBrian Somers 
889dd0645c5SBrian Somers   return 1;
890dd0645c5SBrian Somers }
891dd0645c5SBrian Somers 
8926f384573SBrian Somers static int
893944f7098SBrian Somers IpcpLayerUp(struct fsm *fp)
894af57ed9fSAtsushi Murai {
8957308ec68SBrian Somers   /* We're now up */
896aad81d1eSBrian Somers   struct ipcp *ipcp = fsm2ipcp(fp);
8978fa6ebe4SBrian Somers   char tbuff[16];
898af57ed9fSAtsushi Murai 
8993a2e4f62SBrian Somers   log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name);
9008fa6ebe4SBrian Somers   snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip));
9018fa6ebe4SBrian Somers   log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n",
9028fa6ebe4SBrian Somers              tbuff, inet_ntoa(ipcp->peer_ip));
90303604f35SBrian Somers 
904503a7782SBrian Somers   if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP)
905eaa4df37SBrian Somers     sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255);
90603604f35SBrian Somers 
907dd0645c5SBrian Somers   if (!ipcp_InterfaceUp(ipcp))
9086f384573SBrian Somers     return 0;
909455aabc3SBrian Somers 
910455aabc3SBrian Somers   /*
911455aabc3SBrian Somers    * XXX this stuff should really live in the FSM.  Our config should
912455aabc3SBrian Somers    * associate executable sections in files with events.
913455aabc3SBrian Somers    */
9148fa6ebe4SBrian Somers   if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) {
91549052c95SBrian Somers     if (bundle_GetLabel(fp->bundle)) {
916dd7e2610SBrian Somers       if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
91730291ffbSBrian Somers                        LINKUPFILE, NULL, NULL) < 0)
91830291ffbSBrian Somers         system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
919455aabc3SBrian Somers     } else
92030291ffbSBrian Somers       system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
921af57ed9fSAtsushi Murai   }
922af57ed9fSAtsushi Murai 
923479508cfSBrian Somers   fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3;
9240f2f3eb3SBrian Somers   log_DisplayPrompts();
925479508cfSBrian Somers 
9266f384573SBrian Somers   return 1;
927af57ed9fSAtsushi Murai }
928af57ed9fSAtsushi Murai 
929af57ed9fSAtsushi Murai static int
9308fa6ebe4SBrian Somers AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr)
931af57ed9fSAtsushi Murai {
9327308ec68SBrian Somers   /* Is the given IP in the given range ? */
933057df964SBrian Somers   return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
934057df964SBrian Somers     (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
935af57ed9fSAtsushi Murai }
936af57ed9fSAtsushi Murai 
937af57ed9fSAtsushi Murai static void
93830c2f2ffSBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
93930c2f2ffSBrian Somers                  struct fsm_decode *dec)
940af57ed9fSAtsushi Murai {
9417308ec68SBrian Somers   /* Deal with incoming PROTO_IPCP */
9428fa6ebe4SBrian Somers   struct iface *iface = fp->bundle->iface;
943aad81d1eSBrian Somers   struct ipcp *ipcp = fsm2ipcp(fp);
9448fa6ebe4SBrian Somers   int type, length, gotdns, gotdnsnak, n;
945fe3125a0SBrian Somers   u_int32_t compproto;
946af57ed9fSAtsushi Murai   struct compreq *pcomp;
9473edeb0c6SBrian Somers   struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2];
94830c2f2ffSBrian Somers   char tbuff[100], tbuff2[100];
949af57ed9fSAtsushi Murai 
9503edeb0c6SBrian Somers   gotdns = 0;
9513edeb0c6SBrian Somers   gotdnsnak = 0;
9523edeb0c6SBrian Somers   dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY;
953af57ed9fSAtsushi Murai 
954af57ed9fSAtsushi Murai   while (plen >= sizeof(struct fsmconfig)) {
955af57ed9fSAtsushi Murai     type = *cp;
956af57ed9fSAtsushi Murai     length = cp[1];
957d47dceb8SBrian Somers 
958d47dceb8SBrian Somers     if (length == 0) {
959dd7e2610SBrian Somers       log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name);
960d47dceb8SBrian Somers       break;
961d47dceb8SBrian Somers     }
962d47dceb8SBrian Somers 
9639e836af5SBrian Somers     if (type < NCFTYPES)
96470ee81ffSBrian Somers       snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length);
9659e836af5SBrian Somers     else if (type > 128 && type < 128 + NCFTYPES128)
96670ee81ffSBrian Somers       snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length);
967af57ed9fSAtsushi Murai     else
96870ee81ffSBrian Somers       snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length);
969af57ed9fSAtsushi Murai 
970af57ed9fSAtsushi Murai     switch (type) {
971af57ed9fSAtsushi Murai     case TY_IPADDR:		/* RFC1332 */
9729e8ec64bSBrian Somers       memcpy(&ipaddr.s_addr, cp + 2, 4);
973dd7e2610SBrian Somers       log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
974af57ed9fSAtsushi Murai 
9759780ef31SBrian Somers       switch (mode_type) {
976af57ed9fSAtsushi Murai       case MODE_REQ:
977503a7782SBrian Somers         if (iplist_isvalid(&ipcp->cfg.peer_list)) {
978f5fb6bd0SBrian Somers           if (ipaddr.s_addr == INADDR_ANY ||
979503a7782SBrian Somers               iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 ||
98030c2f2ffSBrian Somers               ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr,
98130c2f2ffSBrian Somers                                 ipaddr, 1)) {
982dd7e2610SBrian Somers             log_Printf(LogIPCP, "%s: Address invalid or already in use\n",
983bcc332bdSBrian Somers                       inet_ntoa(ipaddr));
9848390b576SBrian Somers             /*
9858fa6ebe4SBrian Somers              * If we've already had a valid address configured for the peer,
9868fa6ebe4SBrian Somers              * try NAKing with that so that we don't have to upset things
9878fa6ebe4SBrian Somers              * too much.
9888390b576SBrian Somers              */
9898fa6ebe4SBrian Somers             for (n = 0; n < iface->in_addrs; n++)
9908fa6ebe4SBrian Somers               if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd)
9918fa6ebe4SBrian Somers                   >=0) {
9928fa6ebe4SBrian Somers                 ipcp->peer_ip = iface->in_addr[n].brd;
9938fa6ebe4SBrian Somers                 break;
9948fa6ebe4SBrian Somers               }
9958fa6ebe4SBrian Somers 
9968fa6ebe4SBrian Somers             if (n == iface->in_addrs)
9978390b576SBrian Somers               /* Just pick an IP number from our list */
998503a7782SBrian Somers               ipcp->peer_ip = ChooseHisAddr
99930c2f2ffSBrian Somers                 (fp->bundle, ipcp->cfg.my_range.ipaddr);
10008390b576SBrian Somers 
1001503a7782SBrian Somers             if (ipcp->peer_ip.s_addr == INADDR_ANY) {
100230c2f2ffSBrian Somers 	      memcpy(dec->rejend, cp, length);
100330c2f2ffSBrian Somers 	      dec->rejend += length;
1004bcc332bdSBrian Somers             } else {
100530c2f2ffSBrian Somers 	      memcpy(dec->nakend, cp, 2);
100630c2f2ffSBrian Somers 	      memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2);
100730c2f2ffSBrian Somers 	      dec->nakend += length;
1008bcc332bdSBrian Somers             }
1009bcc332bdSBrian Somers 	    break;
1010bcc332bdSBrian Somers           }
1011503a7782SBrian Somers 	} else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) {
1012af57ed9fSAtsushi Murai 	  /*
10138390b576SBrian Somers 	   * If destination address is not acceptable, NAK with what we
1014944f7098SBrian Somers 	   * want to use.
1015af57ed9fSAtsushi Murai 	   */
101630c2f2ffSBrian Somers 	  memcpy(dec->nakend, cp, 2);
10178fa6ebe4SBrian Somers           for (n = 0; n < iface->in_addrs; n++)
10188fa6ebe4SBrian Somers             if ((iface->in_addr[n].brd.s_addr &
10198fa6ebe4SBrian Somers                  ipcp->cfg.peer_range.mask.s_addr)
10208fa6ebe4SBrian Somers                 == (ipcp->cfg.peer_range.ipaddr.s_addr &
10218fa6ebe4SBrian Somers                     ipcp->cfg.peer_range.mask.s_addr)) {
10228390b576SBrian Somers               /* We prefer the already-configured address */
10238fa6ebe4SBrian Somers 	      memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr,
10248fa6ebe4SBrian Somers                      length - 2);
10258fa6ebe4SBrian Somers               break;
10268fa6ebe4SBrian Somers             }
10278fa6ebe4SBrian Somers 
10288fa6ebe4SBrian Somers           if (n == iface->in_addrs)
102930c2f2ffSBrian Somers 	    memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2);
10308fa6ebe4SBrian Somers 
103130c2f2ffSBrian Somers 	  dec->nakend += length;
1032af57ed9fSAtsushi Murai 	  break;
1033af57ed9fSAtsushi Murai 	}
1034503a7782SBrian Somers 	ipcp->peer_ip = ipaddr;
103530c2f2ffSBrian Somers 	memcpy(dec->ackend, cp, length);
103630c2f2ffSBrian Somers 	dec->ackend += length;
1037af57ed9fSAtsushi Murai 	break;
10388fa6ebe4SBrian Somers 
1039af57ed9fSAtsushi Murai       case MODE_NAK:
1040503a7782SBrian Somers 	if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) {
1041bcc332bdSBrian Somers 	  /* Use address suggested by peer */
104270ee81ffSBrian Somers 	  snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
1043503a7782SBrian Somers 		   inet_ntoa(ipcp->my_ip));
1044dd7e2610SBrian Somers 	  log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
1045503a7782SBrian Somers 	  ipcp->my_ip = ipaddr;
10461d1fc017SBrian Somers           bundle_AdjustFilters(fp->bundle, &ipcp->my_ip, NULL);
1047bcc332bdSBrian Somers 	} else {
1048dd7e2610SBrian Somers 	  log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE,
10498390b576SBrian Somers                     "%s: Unacceptable address!\n", inet_ntoa(ipaddr));
1050dd7e2610SBrian Somers           fsm_Close(&ipcp->fsm);
1051af57ed9fSAtsushi Murai 	}
1052af57ed9fSAtsushi Murai 	break;
10538fa6ebe4SBrian Somers 
1054af57ed9fSAtsushi Murai       case MODE_REJ:
1055503a7782SBrian Somers 	ipcp->peer_reject |= (1 << type);
1056af57ed9fSAtsushi Murai 	break;
1057af57ed9fSAtsushi Murai       }
1058af57ed9fSAtsushi Murai       break;
10598fa6ebe4SBrian Somers 
1060af57ed9fSAtsushi Murai     case TY_COMPPROTO:
10617686a200SBrian Somers       pcomp = (struct compreq *)(cp + 2);
10627686a200SBrian Somers       compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) +
10637686a200SBrian Somers                   pcomp->compcid;
1064dd7e2610SBrian Somers       log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
1065af57ed9fSAtsushi Murai 
10669780ef31SBrian Somers       switch (mode_type) {
1067af57ed9fSAtsushi Murai       case MODE_REQ:
10681342caedSBrian Somers 	if (!IsAccepted(ipcp->cfg.vj.neg)) {
106930c2f2ffSBrian Somers 	  memcpy(dec->rejend, cp, length);
107030c2f2ffSBrian Somers 	  dec->rejend += length;
1071af57ed9fSAtsushi Murai 	} else {
1072af57ed9fSAtsushi Murai 	  switch (length) {
1073af57ed9fSAtsushi Murai 	  case 4:		/* RFC1172 */
1074af57ed9fSAtsushi Murai 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
10757686a200SBrian Somers 	      log_Printf(LogWARN, "Peer is speaking RFC1172 compression "
10767686a200SBrian Somers                          "protocol !\n");
107783d1af55SBrian Somers 	      ipcp->heis1172 = 1;
1078503a7782SBrian Somers 	      ipcp->peer_compproto = compproto;
107930c2f2ffSBrian Somers 	      memcpy(dec->ackend, cp, length);
108030c2f2ffSBrian Somers 	      dec->ackend += length;
1081af57ed9fSAtsushi Murai 	    } else {
108230c2f2ffSBrian Somers 	      memcpy(dec->nakend, cp, 2);
1083af57ed9fSAtsushi Murai 	      pcomp->proto = htons(PROTO_VJCOMP);
108430c2f2ffSBrian Somers 	      memcpy(dec->nakend+2, &pcomp, 2);
108530c2f2ffSBrian Somers 	      dec->nakend += length;
1086af57ed9fSAtsushi Murai 	    }
1087af57ed9fSAtsushi Murai 	    break;
1088af57ed9fSAtsushi Murai 	  case 6:		/* RFC1332 */
10897686a200SBrian Somers 	    if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
10907686a200SBrian Somers               if (pcomp->slots <= MAX_VJ_STATES
1091503a7782SBrian Somers                   && pcomp->slots >= MIN_VJ_STATES) {
10927686a200SBrian Somers                 /* Ok, we can do that */
1093503a7782SBrian Somers 	        ipcp->peer_compproto = compproto;
109483d1af55SBrian Somers 	        ipcp->heis1172 = 0;
109530c2f2ffSBrian Somers 	        memcpy(dec->ackend, cp, length);
109630c2f2ffSBrian Somers 	        dec->ackend += length;
1097af57ed9fSAtsushi Murai 	      } else {
10987686a200SBrian Somers                 /* Get as close as we can to what he wants */
10997686a200SBrian Somers 	        ipcp->heis1172 = 0;
11007686a200SBrian Somers 	        memcpy(dec->nakend, cp, 2);
11017686a200SBrian Somers 	        pcomp->slots = pcomp->slots < MIN_VJ_STATES ?
11027686a200SBrian Somers                                MIN_VJ_STATES : MAX_VJ_STATES;
11037686a200SBrian Somers 	        memcpy(dec->nakend+2, &pcomp, sizeof pcomp);
11047686a200SBrian Somers 	        dec->nakend += length;
11057686a200SBrian Somers               }
11067686a200SBrian Somers 	    } else {
11077686a200SBrian Somers               /* What we really want */
110830c2f2ffSBrian Somers 	      memcpy(dec->nakend, cp, 2);
1109af57ed9fSAtsushi Murai 	      pcomp->proto = htons(PROTO_VJCOMP);
1110503a7782SBrian Somers 	      pcomp->slots = DEF_VJ_STATES;
11117686a200SBrian Somers 	      pcomp->compcid = 1;
111230c2f2ffSBrian Somers 	      memcpy(dec->nakend+2, &pcomp, sizeof pcomp);
111330c2f2ffSBrian Somers 	      dec->nakend += length;
1114af57ed9fSAtsushi Murai 	    }
1115af57ed9fSAtsushi Murai 	    break;
1116af57ed9fSAtsushi Murai 	  default:
111730c2f2ffSBrian Somers 	    memcpy(dec->rejend, cp, length);
111830c2f2ffSBrian Somers 	    dec->rejend += length;
1119af57ed9fSAtsushi Murai 	    break;
1120af57ed9fSAtsushi Murai 	  }
1121af57ed9fSAtsushi Murai 	}
1122af57ed9fSAtsushi Murai 	break;
11238fa6ebe4SBrian Somers 
1124af57ed9fSAtsushi Murai       case MODE_NAK:
11257686a200SBrian Somers 	if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
11267686a200SBrian Somers           if (pcomp->slots > MAX_VJ_STATES)
11277686a200SBrian Somers             pcomp->slots = MAX_VJ_STATES;
11287686a200SBrian Somers           else if (pcomp->slots < MIN_VJ_STATES)
11297686a200SBrian Somers             pcomp->slots = MIN_VJ_STATES;
11307686a200SBrian Somers           compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) +
11317686a200SBrian Somers                       pcomp->compcid;
11327686a200SBrian Somers         } else
11337686a200SBrian Somers           compproto = 0;
1134dd7e2610SBrian Somers 	log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
1135503a7782SBrian Somers 		  tbuff, ipcp->my_compproto, compproto);
1136503a7782SBrian Somers         ipcp->my_compproto = compproto;
1137af57ed9fSAtsushi Murai 	break;
11388fa6ebe4SBrian Somers 
1139af57ed9fSAtsushi Murai       case MODE_REJ:
1140503a7782SBrian Somers 	ipcp->peer_reject |= (1 << type);
1141af57ed9fSAtsushi Murai 	break;
1142af57ed9fSAtsushi Murai       }
1143af57ed9fSAtsushi Murai       break;
11448fa6ebe4SBrian Somers 
1145af57ed9fSAtsushi Murai     case TY_IPADDRS:		/* RFC1172 */
11469e8ec64bSBrian Somers       memcpy(&ipaddr.s_addr, cp + 2, 4);
11479e8ec64bSBrian Somers       memcpy(&dstipaddr.s_addr, cp + 6, 4);
114870ee81ffSBrian Somers       snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr));
1149dd7e2610SBrian Somers       log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
1150af57ed9fSAtsushi Murai 
11519780ef31SBrian Somers       switch (mode_type) {
1152af57ed9fSAtsushi Murai       case MODE_REQ:
11535d9e6103SBrian Somers 	memcpy(dec->rejend, cp, length);
11545d9e6103SBrian Somers 	dec->rejend += length;
1155af57ed9fSAtsushi Murai 	break;
11568fa6ebe4SBrian Somers 
1157af57ed9fSAtsushi Murai       case MODE_NAK:
1158af57ed9fSAtsushi Murai       case MODE_REJ:
1159af57ed9fSAtsushi Murai 	break;
1160af57ed9fSAtsushi Murai       }
1161af57ed9fSAtsushi Murai       break;
1162d8e55738SJordan K. Hubbard 
11633edeb0c6SBrian Somers     case TY_PRIMARY_DNS:	/* DNS negotiation (rfc1877) */
1164d8e55738SJordan K. Hubbard     case TY_SECONDARY_DNS:
11659e8ec64bSBrian Somers       memcpy(&ipaddr.s_addr, cp + 2, 4);
1166dd7e2610SBrian Somers       log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
11673edeb0c6SBrian Somers 
11689780ef31SBrian Somers       switch (mode_type) {
1169d8e55738SJordan K. Hubbard       case MODE_REQ:
11703edeb0c6SBrian Somers         if (!IsAccepted(ipcp->cfg.ns.dns_neg)) {
11713edeb0c6SBrian Somers           ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
117230c2f2ffSBrian Somers 	  memcpy(dec->rejend, cp, length);
117330c2f2ffSBrian Somers 	  dec->rejend += length;
1174d8e55738SJordan K. Hubbard 	  break;
1175d8e55738SJordan K. Hubbard         }
11763edeb0c6SBrian Somers         if (!gotdns) {
11773edeb0c6SBrian Somers           dns[0] = ipcp->cfg.ns.dns[0];
11783edeb0c6SBrian Somers           dns[1] = ipcp->cfg.ns.dns[1];
11793edeb0c6SBrian Somers           if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY)
11803edeb0c6SBrian Somers             getdns(ipcp, dns);
11813edeb0c6SBrian Somers           gotdns = 1;
11823edeb0c6SBrian Somers         }
11833edeb0c6SBrian Somers         have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1];
1184944f7098SBrian Somers 
11853edeb0c6SBrian Somers 	if (ipaddr.s_addr != have_ip.s_addr) {
11861ae349f5Scvs2svn 	  /*
11873edeb0c6SBrian Somers 	   * The client has got the DNS stuff wrong (first request) so
11881ae349f5Scvs2svn 	   * we'll tell 'em how it is
11891ae349f5Scvs2svn 	   */
119030c2f2ffSBrian Somers 	  memcpy(dec->nakend, cp, 2);	/* copy first two (type/length) */
11913edeb0c6SBrian Somers 	  memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2);
119230c2f2ffSBrian Somers 	  dec->nakend += length;
11933edeb0c6SBrian Somers 	} else {
1194d8e55738SJordan K. Hubbard 	  /*
1195944f7098SBrian Somers 	   * Otherwise they have it right (this time) so we send a ack packet
1196944f7098SBrian Somers 	   * back confirming it... end of story
1197d8e55738SJordan K. Hubbard 	   */
119830c2f2ffSBrian Somers 	  memcpy(dec->ackend, cp, length);
119930c2f2ffSBrian Somers 	  dec->ackend += length;
12003edeb0c6SBrian Somers         }
1201d8e55738SJordan K. Hubbard 	break;
12028fa6ebe4SBrian Somers 
1203d8e55738SJordan K. Hubbard       case MODE_NAK:		/* what does this mean?? */
12043edeb0c6SBrian Somers         if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
12053edeb0c6SBrian Somers           gotdnsnak = 1;
12069e8ec64bSBrian Somers           memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4);
12073edeb0c6SBrian Somers 	}
1208d8e55738SJordan K. Hubbard 	break;
12098fa6ebe4SBrian Somers 
12103edeb0c6SBrian Somers       case MODE_REJ:		/* Can't do much, stop asking */
12113edeb0c6SBrian Somers         ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS));
1212d8e55738SJordan K. Hubbard 	break;
1213d8e55738SJordan K. Hubbard       }
1214d8e55738SJordan K. Hubbard       break;
1215d8e55738SJordan K. Hubbard 
12163edeb0c6SBrian Somers     case TY_PRIMARY_NBNS:	/* M$ NetBIOS nameserver hack (rfc1877) */
1217d8e55738SJordan K. Hubbard     case TY_SECONDARY_NBNS:
12189e8ec64bSBrian Somers       memcpy(&ipaddr.s_addr, cp + 2, 4);
1219dd7e2610SBrian Somers       log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
12203edeb0c6SBrian Somers 
12219780ef31SBrian Somers       switch (mode_type) {
1222d8e55738SJordan K. Hubbard       case MODE_REQ:
12233edeb0c6SBrian Somers 	have_ip.s_addr =
12243edeb0c6SBrian Somers           ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr;
12253edeb0c6SBrian Somers 
12263edeb0c6SBrian Somers         if (have_ip.s_addr == INADDR_ANY) {
1227dd7e2610SBrian Somers 	  log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n");
12283edeb0c6SBrian Somers           ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
122930c2f2ffSBrian Somers 	  memcpy(dec->rejend, cp, length);
123030c2f2ffSBrian Somers 	  dec->rejend += length;
1231d8e55738SJordan K. Hubbard 	  break;
1232d8e55738SJordan K. Hubbard         }
12333edeb0c6SBrian Somers 
12343edeb0c6SBrian Somers 	if (ipaddr.s_addr != have_ip.s_addr) {
123530c2f2ffSBrian Somers 	  memcpy(dec->nakend, cp, 2);
12363edeb0c6SBrian Somers 	  memcpy(dec->nakend+2, &have_ip.s_addr, length);
123730c2f2ffSBrian Somers 	  dec->nakend += length;
12383edeb0c6SBrian Somers 	} else {
123930c2f2ffSBrian Somers 	  memcpy(dec->ackend, cp, length);
124030c2f2ffSBrian Somers 	  dec->ackend += length;
12413edeb0c6SBrian Somers         }
1242d8e55738SJordan K. Hubbard 	break;
12438fa6ebe4SBrian Somers 
1244d8e55738SJordan K. Hubbard       case MODE_NAK:
1245dd7e2610SBrian Somers 	log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
1246d8e55738SJordan K. Hubbard 	break;
12478fa6ebe4SBrian Somers 
1248d8e55738SJordan K. Hubbard       case MODE_REJ:
1249dd7e2610SBrian Somers 	log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
1250d8e55738SJordan K. Hubbard 	break;
1251d8e55738SJordan K. Hubbard       }
1252d8e55738SJordan K. Hubbard       break;
1253d8e55738SJordan K. Hubbard 
1254af57ed9fSAtsushi Murai     default:
125530c2f2ffSBrian Somers       if (mode_type != MODE_NOP) {
125683d1af55SBrian Somers         ipcp->my_reject |= (1 << type);
125730c2f2ffSBrian Somers         memcpy(dec->rejend, cp, length);
125830c2f2ffSBrian Somers         dec->rejend += length;
125930c2f2ffSBrian Somers       }
1260af57ed9fSAtsushi Murai       break;
1261af57ed9fSAtsushi Murai     }
1262af57ed9fSAtsushi Murai     plen -= length;
1263af57ed9fSAtsushi Murai     cp += length;
1264af57ed9fSAtsushi Murai   }
12651342caedSBrian Somers 
12663edeb0c6SBrian Somers   if (gotdnsnak)
12673edeb0c6SBrian Somers     if (!setdns(ipcp, dnsnak)) {
12683edeb0c6SBrian Somers       ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS));
12693edeb0c6SBrian Somers       ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS));
12703edeb0c6SBrian Somers     }
12713edeb0c6SBrian Somers 
1272e43ebac1SBrian Somers   if (mode_type != MODE_NOP) {
12731342caedSBrian Somers     if (dec->rejend != dec->rej) {
12741342caedSBrian Somers       /* rejects are preferred */
12751342caedSBrian Somers       dec->ackend = dec->ack;
12761342caedSBrian Somers       dec->nakend = dec->nak;
12771342caedSBrian Somers     } else if (dec->nakend != dec->nak)
12781342caedSBrian Somers       /* then NAKs */
12791342caedSBrian Somers       dec->ackend = dec->ack;
12801ae349f5Scvs2svn   }
1281af57ed9fSAtsushi Murai }
1282af57ed9fSAtsushi Murai 
12835d9e6103SBrian Somers extern struct mbuf *
12845d9e6103SBrian Somers ipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
1285af57ed9fSAtsushi Murai {
12867308ec68SBrian Somers   /* Got PROTO_IPCP from link */
128726af0ae9SBrian Somers   m_settype(bp, MB_IPCPIN);
1288641684cdSBrian Somers   if (bundle_Phase(bundle) == PHASE_NETWORK)
12895d9e6103SBrian Somers     fsm_Input(&bundle->ncp.ipcp.fsm, bp);
1290641684cdSBrian Somers   else {
1291641684cdSBrian Somers     if (bundle_Phase(bundle) < PHASE_NETWORK)
1292641684cdSBrian Somers       log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n",
12935d9e6103SBrian Somers                  l->name, bundle_PhaseName(bundle));
129426af0ae9SBrian Somers     m_freem(bp);
1295641684cdSBrian Somers   }
12965d9e6103SBrian Somers   return NULL;
1297af57ed9fSAtsushi Murai }
12989c97abd8SBrian Somers 
12999c97abd8SBrian Somers int
1300972a1bcfSBrian Somers ipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr)
1301972a1bcfSBrian Somers {
1302972a1bcfSBrian Somers   struct ipcp *ipcp = &bundle->ncp.ipcp;
1303972a1bcfSBrian Somers 
1304972a1bcfSBrian Somers   memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
1305972a1bcfSBrian Somers   iplist_reset(&ipcp->cfg.peer_list);
1306972a1bcfSBrian Somers   ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr = hisaddr;
1307972a1bcfSBrian Somers   ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
1308972a1bcfSBrian Somers   ipcp->cfg.peer_range.width = 32;
1309972a1bcfSBrian Somers 
1310972a1bcfSBrian Somers   if (ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, hisaddr, 0) < 0)
1311972a1bcfSBrian Somers     return 0;
1312972a1bcfSBrian Somers 
1313972a1bcfSBrian Somers   return 1;	/* Ok */
1314972a1bcfSBrian Somers }
1315972a1bcfSBrian Somers 
1316972a1bcfSBrian Somers int
1317dd7e2610SBrian Somers ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr)
13189c97abd8SBrian Somers {
13195828db6dSBrian Somers   struct ipcp *ipcp = &bundle->ncp.ipcp;
13205828db6dSBrian Somers 
13217308ec68SBrian Somers   /* Use `hisaddr' for the peers address (set iface if `setaddr') */
13225828db6dSBrian Somers   memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
13235828db6dSBrian Somers   iplist_reset(&ipcp->cfg.peer_list);
13249c97abd8SBrian Somers   if (strpbrk(hisaddr, ",-")) {
13255828db6dSBrian Somers     iplist_setsrc(&ipcp->cfg.peer_list, hisaddr);
13265828db6dSBrian Somers     if (iplist_isvalid(&ipcp->cfg.peer_list)) {
13275828db6dSBrian Somers       iplist_setrandpos(&ipcp->cfg.peer_list);
132830c2f2ffSBrian Somers       ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip);
13295828db6dSBrian Somers       if (ipcp->peer_ip.s_addr == INADDR_ANY) {
1330dd7e2610SBrian Somers         log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src);
13311d1fc017SBrian Somers         return 0;
13329c97abd8SBrian Somers       }
13335828db6dSBrian Somers       ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr;
13345828db6dSBrian Somers       ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
13355828db6dSBrian Somers       ipcp->cfg.peer_range.width = 32;
13369c97abd8SBrian Somers     } else {
1337dd7e2610SBrian Somers       log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr);
13389c97abd8SBrian Somers       return 0;
13399c97abd8SBrian Somers     }
1340972a1bcfSBrian Somers   } else if (ParseAddr(ipcp, hisaddr, &ipcp->cfg.peer_range.ipaddr,
13415828db6dSBrian Somers 		       &ipcp->cfg.peer_range.mask,
13425828db6dSBrian Somers                        &ipcp->cfg.peer_range.width) != 0) {
13435828db6dSBrian Somers     ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr;
13449c97abd8SBrian Somers 
134530c2f2ffSBrian Somers     if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr,
13468fa6ebe4SBrian Somers                                      ipcp->cfg.peer_range.ipaddr, 0) < 0)
13479c97abd8SBrian Somers       return 0;
13489c97abd8SBrian Somers   } else
13499c97abd8SBrian Somers     return 0;
13509c97abd8SBrian Somers 
13511d1fc017SBrian Somers   bundle_AdjustFilters(bundle, NULL, &ipcp->peer_ip);
13521d1fc017SBrian Somers 
13531d1fc017SBrian Somers   return 1;	/* Ok */
13549c97abd8SBrian Somers }
1355bc76350eSBrian Somers 
1356bc76350eSBrian Somers struct in_addr
1357bc76350eSBrian Somers addr2mask(struct in_addr addr)
1358bc76350eSBrian Somers {
1359bc76350eSBrian Somers   u_int32_t haddr = ntohl(addr.s_addr);
1360bc76350eSBrian Somers 
1361bc76350eSBrian Somers   haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET :
1362bc76350eSBrian Somers           IN_CLASSB(haddr) ? IN_CLASSB_NET :
1363bc76350eSBrian Somers           IN_CLASSC_NET;
1364bc76350eSBrian Somers   addr.s_addr = htonl(haddr);
1365bc76350eSBrian Somers 
1366bc76350eSBrian Somers   return addr;
1367bc76350eSBrian Somers }
1368