Deleted Added
full compact
ipcp.c (39395) ipcp.c (40561)
1/*
2 * PPP IP Control Protocol (IPCP) Module
3 *
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc. The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
1/*
2 * PPP IP Control Protocol (IPCP) Module
3 *
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc. The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id: ipcp.c,v 1.65 1998/09/04 18:25:59 brian Exp $
20 * $Id: ipcp.c,v 1.66 1998/09/17 00:45:26 brian Exp $
21 *
22 * TODO:
23 * o More RFC1772 backward compatibility
24 */
25#include <sys/param.h>
26#include <netinet/in_systm.h>
27#include <netinet/in.h>
28#include <netinet/ip.h>
29#include <arpa/inet.h>
30#include <sys/socket.h>
31#include <netdb.h>
32#include <net/if.h>
33#include <sys/sockio.h>
34#include <sys/un.h>
35
36#include <fcntl.h>
37#include <resolv.h>
38#include <stdlib.h>
39#include <string.h>
40#include <sys/errno.h>
41#include <termios.h>
42#include <unistd.h>
43
44#ifndef NOALIAS
45#ifdef __OpenBSD__
46#include "alias.h"
47#else
48#include <alias.h>
49#endif
50#endif
51#include "ua.h"
52#include "defs.h"
53#include "command.h"
54#include "mbuf.h"
55#include "log.h"
56#include "timer.h"
57#include "fsm.h"
58#include "lcpproto.h"
59#include "lcp.h"
60#include "iplist.h"
61#include "throughput.h"
62#include "slcompress.h"
63#include "lqr.h"
64#include "hdlc.h"
65#include "ipcp.h"
66#include "filter.h"
67#include "descriptor.h"
68#include "vjcomp.h"
69#include "async.h"
70#include "ccp.h"
71#include "link.h"
72#include "physical.h"
73#include "mp.h"
74#include "bundle.h"
75#include "id.h"
76#include "arp.h"
77#include "systems.h"
78#include "prompt.h"
79#include "route.h"
21 *
22 * TODO:
23 * o More RFC1772 backward compatibility
24 */
25#include <sys/param.h>
26#include <netinet/in_systm.h>
27#include <netinet/in.h>
28#include <netinet/ip.h>
29#include <arpa/inet.h>
30#include <sys/socket.h>
31#include <netdb.h>
32#include <net/if.h>
33#include <sys/sockio.h>
34#include <sys/un.h>
35
36#include <fcntl.h>
37#include <resolv.h>
38#include <stdlib.h>
39#include <string.h>
40#include <sys/errno.h>
41#include <termios.h>
42#include <unistd.h>
43
44#ifndef NOALIAS
45#ifdef __OpenBSD__
46#include "alias.h"
47#else
48#include <alias.h>
49#endif
50#endif
51#include "ua.h"
52#include "defs.h"
53#include "command.h"
54#include "mbuf.h"
55#include "log.h"
56#include "timer.h"
57#include "fsm.h"
58#include "lcpproto.h"
59#include "lcp.h"
60#include "iplist.h"
61#include "throughput.h"
62#include "slcompress.h"
63#include "lqr.h"
64#include "hdlc.h"
65#include "ipcp.h"
66#include "filter.h"
67#include "descriptor.h"
68#include "vjcomp.h"
69#include "async.h"
70#include "ccp.h"
71#include "link.h"
72#include "physical.h"
73#include "mp.h"
74#include "bundle.h"
75#include "id.h"
76#include "arp.h"
77#include "systems.h"
78#include "prompt.h"
79#include "route.h"
80#include "iface.h"
80
81#undef REJECTED
82#define REJECTED(p, x) ((p)->peer_reject & (1<<(x)))
83#define issep(ch) ((ch) == ' ' || (ch) == '\t')
84#define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.')
85
86struct compreq {
87 u_short proto;
88 u_char slots;
89 u_char compcid;
90};
91
92static int IpcpLayerUp(struct fsm *);
93static void IpcpLayerDown(struct fsm *);
94static void IpcpLayerStart(struct fsm *);
95static void IpcpLayerFinish(struct fsm *);
96static void IpcpInitRestartCounter(struct fsm *);
97static void IpcpSendConfigReq(struct fsm *);
98static void IpcpSentTerminateReq(struct fsm *);
99static void IpcpSendTerminateAck(struct fsm *, u_char);
100static void IpcpDecodeConfig(struct fsm *, u_char *, int, int,
101 struct fsm_decode *);
102
103static struct fsm_callbacks ipcp_Callbacks = {
104 IpcpLayerUp,
105 IpcpLayerDown,
106 IpcpLayerStart,
107 IpcpLayerFinish,
108 IpcpInitRestartCounter,
109 IpcpSendConfigReq,
110 IpcpSentTerminateReq,
111 IpcpSendTerminateAck,
112 IpcpDecodeConfig,
113 fsm_NullRecvResetReq,
114 fsm_NullRecvResetAck
115};
116
117static const char *cftypes[] = {
118 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
119 "???",
120 "IPADDRS", /* 1: IP-Addresses */ /* deprecated */
121 "COMPPROTO", /* 2: IP-Compression-Protocol */
122 "IPADDR", /* 3: IP-Address */
123};
124
125#define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
126
127static const char *cftypes128[] = {
128 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
129 "???",
130 "PRIDNS", /* 129: Primary DNS Server Address */
131 "PRINBNS", /* 130: Primary NBNS Server Address */
132 "SECDNS", /* 131: Secondary DNS Server Address */
133 "SECNBNS", /* 132: Secondary NBNS Server Address */
134};
135
136#define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0])
137
138void
139ipcp_AddInOctets(struct ipcp *ipcp, int n)
140{
141 throughput_addin(&ipcp->throughput, n);
142}
143
144void
145ipcp_AddOutOctets(struct ipcp *ipcp, int n)
146{
147 throughput_addout(&ipcp->throughput, n);
148}
149
150static void
151getdns(struct ipcp *ipcp, struct in_addr addr[2])
152{
153 FILE *fp;
154
155 addr[0].s_addr = addr[1].s_addr = INADDR_ANY;
156 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
157 char buf[LINE_LEN], *cp, *end;
158 int n;
159
160 n = 0;
161 buf[sizeof buf - 1] = '\0';
162 while (fgets(buf, sizeof buf - 1, fp)) {
163 if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) {
164 for (cp = buf + 11; issep(*cp); cp++)
165 ;
166 for (end = cp; isip(*end); end++)
167 ;
168 *end = '\0';
169 if (inet_aton(cp, addr+n) && ++n == 2)
170 break;
171 }
172 }
173 if (n == 1)
174 addr[1] = addr[0];
175 fclose(fp);
176 }
177}
178
179static int
180setdns(struct ipcp *ipcp, struct in_addr addr[2])
181{
182 FILE *fp;
183 char wbuf[LINE_LEN + 54];
184 int wlen;
185
186 if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) {
187 struct in_addr old[2];
188
189 getdns(ipcp, old);
190 if (addr[0].s_addr == INADDR_ANY)
191 addr[0] = old[0];
192 if (addr[1].s_addr == INADDR_ANY)
193 addr[1] = old[1];
194 }
195
196 if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) {
197 log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n",
198 _PATH_RESCONF);
199 return 0;
200 }
201
202 wlen = 0;
203 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
204 char buf[LINE_LEN];
205 int len;
206
207 buf[sizeof buf - 1] = '\0';
208 while (fgets(buf, sizeof buf - 1, fp)) {
209 if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) {
210 len = strlen(buf);
211 if (len > sizeof wbuf - wlen) {
212 log_Printf(LogWARN, "%s: Can only cope with max file size %d\n",
213 _PATH_RESCONF, LINE_LEN);
214 fclose(fp);
215 return 0;
216 }
217 memcpy(wbuf + wlen, buf, len);
218 wlen += len;
219 }
220 }
221 fclose(fp);
222 }
223
224 if (addr[0].s_addr != INADDR_ANY) {
225 snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n",
226 inet_ntoa(addr[0]));
227 log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11);
228 wlen += strlen(wbuf + wlen);
229 }
230
231 if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) {
232 snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n",
233 inet_ntoa(addr[1]));
234 log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11);
235 wlen += strlen(wbuf + wlen);
236 }
237
238 if (wlen) {
239 int fd;
240
241 if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) {
242 if (write(fd, wbuf, wlen) != wlen) {
243 log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno));
244 close(fd);
245 return 0;
246 }
247 if (ftruncate(fd, wlen) == -1) {
248 log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno));
249 close(fd);
250 return 0;
251 }
252 close(fd);
253 } else {
254 log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno));
255 return 0;
256 }
257 }
258
259 return 1;
260}
261
262int
263ipcp_Show(struct cmdargs const *arg)
264{
265 struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
266
267 prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name,
268 State2Nam(ipcp->fsm.state));
269 if (ipcp->fsm.state == ST_OPENED) {
270 prompt_Printf(arg->prompt, " His side: %s, %s\n",
271 inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto));
272 prompt_Printf(arg->prompt, " My side: %s, %s\n",
273 inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto));
274 }
275
276 if (ipcp->route) {
277 prompt_Printf(arg->prompt, "\n");
278 route_ShowSticky(arg->prompt, ipcp->route);
279 }
280
281 prompt_Printf(arg->prompt, "\nDefaults:\n");
282 prompt_Printf(arg->prompt, " My Address: %s/%d",
283 inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width);
284
285 if (ipcp->cfg.HaveTriggerAddress)
286 prompt_Printf(arg->prompt, " (trigger with %s)",
287 inet_ntoa(ipcp->cfg.TriggerAddress));
288 prompt_Printf(arg->prompt, "\n VJ compression: %s (%d slots %s slot "
289 "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg),
290 ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without");
291
292 if (iplist_isvalid(&ipcp->cfg.peer_list))
293 prompt_Printf(arg->prompt, " His Address: %s\n",
294 ipcp->cfg.peer_list.src);
295 else
296 prompt_Printf(arg->prompt, " His Address: %s/%d\n",
297 inet_ntoa(ipcp->cfg.peer_range.ipaddr),
298 ipcp->cfg.peer_range.width);
299
300 prompt_Printf(arg->prompt, " DNS: %s, ",
301 inet_ntoa(ipcp->cfg.ns.dns[0]));
302 prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]),
303 command_ShowNegval(ipcp->cfg.ns.dns_neg));
304 prompt_Printf(arg->prompt, " NetBIOS NS: %s, ",
305 inet_ntoa(ipcp->cfg.ns.nbns[0]));
306 prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1]));
307
308 prompt_Printf(arg->prompt, "\n");
309 throughput_disp(&ipcp->throughput, arg->prompt);
310
311 return 0;
312}
313
314int
315ipcp_vjset(struct cmdargs const *arg)
316{
317 if (arg->argc != arg->argn+2)
318 return -1;
319 if (!strcasecmp(arg->argv[arg->argn], "slots")) {
320 int slots;
321
322 slots = atoi(arg->argv[arg->argn+1]);
323 if (slots < 4 || slots > 16)
324 return 1;
325 arg->bundle->ncp.ipcp.cfg.vj.slots = slots;
326 return 0;
327 } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) {
328 if (!strcasecmp(arg->argv[arg->argn+1], "on"))
329 arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1;
330 else if (!strcasecmp(arg->argv[arg->argn+1], "off"))
331 arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0;
332 else
333 return 2;
334 return 0;
335 }
336 return -1;
337}
338
339void
340ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
341 const struct fsm_parent *parent)
342{
343 struct hostent *hp;
344 char name[MAXHOSTNAMELEN];
345 static const char *timer_names[] =
346 {"IPCP restart", "IPCP openmode", "IPCP stopped"};
347
348 fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, 10, LogIPCP,
349 bundle, l, parent, &ipcp_Callbacks, timer_names);
350
351 ipcp->route = NULL;
352 ipcp->cfg.vj.slots = DEF_VJ_STATES;
353 ipcp->cfg.vj.slotcomp = 1;
354 memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range);
355 if (gethostname(name, sizeof name) == 0) {
356 hp = gethostbyname(name);
81
82#undef REJECTED
83#define REJECTED(p, x) ((p)->peer_reject & (1<<(x)))
84#define issep(ch) ((ch) == ' ' || (ch) == '\t')
85#define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.')
86
87struct compreq {
88 u_short proto;
89 u_char slots;
90 u_char compcid;
91};
92
93static int IpcpLayerUp(struct fsm *);
94static void IpcpLayerDown(struct fsm *);
95static void IpcpLayerStart(struct fsm *);
96static void IpcpLayerFinish(struct fsm *);
97static void IpcpInitRestartCounter(struct fsm *);
98static void IpcpSendConfigReq(struct fsm *);
99static void IpcpSentTerminateReq(struct fsm *);
100static void IpcpSendTerminateAck(struct fsm *, u_char);
101static void IpcpDecodeConfig(struct fsm *, u_char *, int, int,
102 struct fsm_decode *);
103
104static struct fsm_callbacks ipcp_Callbacks = {
105 IpcpLayerUp,
106 IpcpLayerDown,
107 IpcpLayerStart,
108 IpcpLayerFinish,
109 IpcpInitRestartCounter,
110 IpcpSendConfigReq,
111 IpcpSentTerminateReq,
112 IpcpSendTerminateAck,
113 IpcpDecodeConfig,
114 fsm_NullRecvResetReq,
115 fsm_NullRecvResetAck
116};
117
118static const char *cftypes[] = {
119 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
120 "???",
121 "IPADDRS", /* 1: IP-Addresses */ /* deprecated */
122 "COMPPROTO", /* 2: IP-Compression-Protocol */
123 "IPADDR", /* 3: IP-Address */
124};
125
126#define NCFTYPES (sizeof cftypes/sizeof cftypes[0])
127
128static const char *cftypes128[] = {
129 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
130 "???",
131 "PRIDNS", /* 129: Primary DNS Server Address */
132 "PRINBNS", /* 130: Primary NBNS Server Address */
133 "SECDNS", /* 131: Secondary DNS Server Address */
134 "SECNBNS", /* 132: Secondary NBNS Server Address */
135};
136
137#define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0])
138
139void
140ipcp_AddInOctets(struct ipcp *ipcp, int n)
141{
142 throughput_addin(&ipcp->throughput, n);
143}
144
145void
146ipcp_AddOutOctets(struct ipcp *ipcp, int n)
147{
148 throughput_addout(&ipcp->throughput, n);
149}
150
151static void
152getdns(struct ipcp *ipcp, struct in_addr addr[2])
153{
154 FILE *fp;
155
156 addr[0].s_addr = addr[1].s_addr = INADDR_ANY;
157 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
158 char buf[LINE_LEN], *cp, *end;
159 int n;
160
161 n = 0;
162 buf[sizeof buf - 1] = '\0';
163 while (fgets(buf, sizeof buf - 1, fp)) {
164 if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) {
165 for (cp = buf + 11; issep(*cp); cp++)
166 ;
167 for (end = cp; isip(*end); end++)
168 ;
169 *end = '\0';
170 if (inet_aton(cp, addr+n) && ++n == 2)
171 break;
172 }
173 }
174 if (n == 1)
175 addr[1] = addr[0];
176 fclose(fp);
177 }
178}
179
180static int
181setdns(struct ipcp *ipcp, struct in_addr addr[2])
182{
183 FILE *fp;
184 char wbuf[LINE_LEN + 54];
185 int wlen;
186
187 if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) {
188 struct in_addr old[2];
189
190 getdns(ipcp, old);
191 if (addr[0].s_addr == INADDR_ANY)
192 addr[0] = old[0];
193 if (addr[1].s_addr == INADDR_ANY)
194 addr[1] = old[1];
195 }
196
197 if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) {
198 log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n",
199 _PATH_RESCONF);
200 return 0;
201 }
202
203 wlen = 0;
204 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
205 char buf[LINE_LEN];
206 int len;
207
208 buf[sizeof buf - 1] = '\0';
209 while (fgets(buf, sizeof buf - 1, fp)) {
210 if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) {
211 len = strlen(buf);
212 if (len > sizeof wbuf - wlen) {
213 log_Printf(LogWARN, "%s: Can only cope with max file size %d\n",
214 _PATH_RESCONF, LINE_LEN);
215 fclose(fp);
216 return 0;
217 }
218 memcpy(wbuf + wlen, buf, len);
219 wlen += len;
220 }
221 }
222 fclose(fp);
223 }
224
225 if (addr[0].s_addr != INADDR_ANY) {
226 snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n",
227 inet_ntoa(addr[0]));
228 log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11);
229 wlen += strlen(wbuf + wlen);
230 }
231
232 if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) {
233 snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n",
234 inet_ntoa(addr[1]));
235 log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11);
236 wlen += strlen(wbuf + wlen);
237 }
238
239 if (wlen) {
240 int fd;
241
242 if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) {
243 if (write(fd, wbuf, wlen) != wlen) {
244 log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno));
245 close(fd);
246 return 0;
247 }
248 if (ftruncate(fd, wlen) == -1) {
249 log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno));
250 close(fd);
251 return 0;
252 }
253 close(fd);
254 } else {
255 log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno));
256 return 0;
257 }
258 }
259
260 return 1;
261}
262
263int
264ipcp_Show(struct cmdargs const *arg)
265{
266 struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
267
268 prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name,
269 State2Nam(ipcp->fsm.state));
270 if (ipcp->fsm.state == ST_OPENED) {
271 prompt_Printf(arg->prompt, " His side: %s, %s\n",
272 inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto));
273 prompt_Printf(arg->prompt, " My side: %s, %s\n",
274 inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto));
275 }
276
277 if (ipcp->route) {
278 prompt_Printf(arg->prompt, "\n");
279 route_ShowSticky(arg->prompt, ipcp->route);
280 }
281
282 prompt_Printf(arg->prompt, "\nDefaults:\n");
283 prompt_Printf(arg->prompt, " My Address: %s/%d",
284 inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width);
285
286 if (ipcp->cfg.HaveTriggerAddress)
287 prompt_Printf(arg->prompt, " (trigger with %s)",
288 inet_ntoa(ipcp->cfg.TriggerAddress));
289 prompt_Printf(arg->prompt, "\n VJ compression: %s (%d slots %s slot "
290 "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg),
291 ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without");
292
293 if (iplist_isvalid(&ipcp->cfg.peer_list))
294 prompt_Printf(arg->prompt, " His Address: %s\n",
295 ipcp->cfg.peer_list.src);
296 else
297 prompt_Printf(arg->prompt, " His Address: %s/%d\n",
298 inet_ntoa(ipcp->cfg.peer_range.ipaddr),
299 ipcp->cfg.peer_range.width);
300
301 prompt_Printf(arg->prompt, " DNS: %s, ",
302 inet_ntoa(ipcp->cfg.ns.dns[0]));
303 prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]),
304 command_ShowNegval(ipcp->cfg.ns.dns_neg));
305 prompt_Printf(arg->prompt, " NetBIOS NS: %s, ",
306 inet_ntoa(ipcp->cfg.ns.nbns[0]));
307 prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1]));
308
309 prompt_Printf(arg->prompt, "\n");
310 throughput_disp(&ipcp->throughput, arg->prompt);
311
312 return 0;
313}
314
315int
316ipcp_vjset(struct cmdargs const *arg)
317{
318 if (arg->argc != arg->argn+2)
319 return -1;
320 if (!strcasecmp(arg->argv[arg->argn], "slots")) {
321 int slots;
322
323 slots = atoi(arg->argv[arg->argn+1]);
324 if (slots < 4 || slots > 16)
325 return 1;
326 arg->bundle->ncp.ipcp.cfg.vj.slots = slots;
327 return 0;
328 } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) {
329 if (!strcasecmp(arg->argv[arg->argn+1], "on"))
330 arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1;
331 else if (!strcasecmp(arg->argv[arg->argn+1], "off"))
332 arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0;
333 else
334 return 2;
335 return 0;
336 }
337 return -1;
338}
339
340void
341ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
342 const struct fsm_parent *parent)
343{
344 struct hostent *hp;
345 char name[MAXHOSTNAMELEN];
346 static const char *timer_names[] =
347 {"IPCP restart", "IPCP openmode", "IPCP stopped"};
348
349 fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, 10, LogIPCP,
350 bundle, l, parent, &ipcp_Callbacks, timer_names);
351
352 ipcp->route = NULL;
353 ipcp->cfg.vj.slots = DEF_VJ_STATES;
354 ipcp->cfg.vj.slotcomp = 1;
355 memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range);
356 if (gethostname(name, sizeof name) == 0) {
357 hp = gethostbyname(name);
357 if (hp && hp->h_addrtype == AF_INET) {
358 if (hp && hp->h_addrtype == AF_INET)
358 memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length);
359 memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length);
359 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
360 ipcp->cfg.peer_range.width = 32;
361 }
362 }
363 ipcp->cfg.netmask.s_addr = INADDR_ANY;
364 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
365 iplist_setsrc(&ipcp->cfg.peer_list, "");
366 ipcp->cfg.HaveTriggerAddress = 0;
367
368 ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY;
369 ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY;
370 ipcp->cfg.ns.dns_neg = 0;
371 ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY;
372 ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY;
373
374 ipcp->cfg.fsmretry = DEF_FSMRETRY;
375 ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED;
376
377 memset(&ipcp->vj, '\0', sizeof ipcp->vj);
378
360 }
361 ipcp->cfg.netmask.s_addr = INADDR_ANY;
362 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
363 iplist_setsrc(&ipcp->cfg.peer_list, "");
364 ipcp->cfg.HaveTriggerAddress = 0;
365
366 ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY;
367 ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY;
368 ipcp->cfg.ns.dns_neg = 0;
369 ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY;
370 ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY;
371
372 ipcp->cfg.fsmretry = DEF_FSMRETRY;
373 ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED;
374
375 memset(&ipcp->vj, '\0', sizeof ipcp->vj);
376
379 ipcp->my_ifip.s_addr = INADDR_ANY;
380 ipcp->peer_ifip.s_addr = INADDR_ANY;
381
382 throughput_init(&ipcp->throughput);
383 memset(ipcp->Queue, '\0', sizeof ipcp->Queue);
384 ipcp_Setup(ipcp);
385}
386
387void
388ipcp_SetLink(struct ipcp *ipcp, struct link *l)
389{
390 ipcp->fsm.link = l;
391}
392
393void
394ipcp_Setup(struct ipcp *ipcp)
395{
377 throughput_init(&ipcp->throughput);
378 memset(ipcp->Queue, '\0', sizeof ipcp->Queue);
379 ipcp_Setup(ipcp);
380}
381
382void
383ipcp_SetLink(struct ipcp *ipcp, struct link *l)
384{
385 ipcp->fsm.link = l;
386}
387
388void
389ipcp_Setup(struct ipcp *ipcp)
390{
396 int pos;
391 struct iface *iface = ipcp->fsm.bundle->iface;
392 int pos, n;
397
398 ipcp->fsm.open_mode = 0;
399 ipcp->fsm.maxconfig = 10;
400
401 if (iplist_isvalid(&ipcp->cfg.peer_list)) {
393
394 ipcp->fsm.open_mode = 0;
395 ipcp->fsm.maxconfig = 10;
396
397 if (iplist_isvalid(&ipcp->cfg.peer_list)) {
402 if (ipcp->my_ifip.s_addr != INADDR_ANY &&
403 (pos = iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->my_ifip)) != -1)
404 ipcp->cfg.peer_range.ipaddr = iplist_setcurpos(&ipcp->cfg.peer_list, pos);
405 else
398 /* Try to give the peer a previously configured IP address */
399 for (n = 0; n < iface->in_addrs; n++) {
400 pos = iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd);
401 if (pos != -1) {
402 ipcp->cfg.peer_range.ipaddr =
403 iplist_setcurpos(&ipcp->cfg.peer_list, pos);
404 break;
405 }
406 }
407 if (n == iface->in_addrs)
408 /* Ok, so none of 'em fit.... pick a random one */
406 ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list);
409 ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list);
410
407 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
408 ipcp->cfg.peer_range.width = 32;
409 }
410
411 ipcp->heis1172 = 0;
412
413 ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr;
414 ipcp->peer_compproto = 0;
415
416 if (ipcp->cfg.HaveTriggerAddress) {
417 /*
418 * Some implementations of PPP require that we send a
419 * *special* value as our address, even though the rfc specifies
420 * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
421 */
422 ipcp->my_ip = ipcp->cfg.TriggerAddress;
423 log_Printf(LogIPCP, "Using trigger address %s\n",
424 inet_ntoa(ipcp->cfg.TriggerAddress));
411 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
412 ipcp->cfg.peer_range.width = 32;
413 }
414
415 ipcp->heis1172 = 0;
416
417 ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr;
418 ipcp->peer_compproto = 0;
419
420 if (ipcp->cfg.HaveTriggerAddress) {
421 /*
422 * Some implementations of PPP require that we send a
423 * *special* value as our address, even though the rfc specifies
424 * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
425 */
426 ipcp->my_ip = ipcp->cfg.TriggerAddress;
427 log_Printf(LogIPCP, "Using trigger address %s\n",
428 inet_ntoa(ipcp->cfg.TriggerAddress));
425 } else if ((ipcp->my_ifip.s_addr & ipcp->cfg.my_range.mask.s_addr) ==
426 (ipcp->cfg.my_range.ipaddr.s_addr &
427 ipcp->cfg.my_range.mask.s_addr))
429 } else {
428 /*
430 /*
429 * Otherwise, if we've been assigned an IP number before, we really
430 * want to keep the same IP number so that we can keep any existing
431 * connections that are bound to that IP.
431 * Otherwise, if we've used an IP number before and it's still within
432 * the network specified on the ``set ifaddr'' line, we really
433 * want to keep that IP number so that we can keep any existing
434 * connections that are bound to that IP (assuming we're not
435 * ``iface-alias''ing).
432 */
436 */
433 ipcp->my_ip = ipcp->my_ifip;
434 else
435 ipcp->my_ip = ipcp->cfg.my_range.ipaddr;
437 for (n = 0; n < iface->in_addrs; n++)
438 if ((iface->in_addr[n].ifa.s_addr & ipcp->cfg.my_range.mask.s_addr) ==
439 (ipcp->cfg.my_range.ipaddr.s_addr & ipcp->cfg.my_range.mask.s_addr)) {
440 ipcp->my_ip = iface->in_addr[n].ifa;
441 break;
442 }
443 if (n == iface->in_addrs)
444 ipcp->my_ip = ipcp->cfg.my_range.ipaddr;
445 }
436
437 if (IsEnabled(ipcp->cfg.vj.neg))
438 ipcp->my_compproto = (PROTO_VJCOMP << 16) +
439 ((ipcp->cfg.vj.slots - 1) << 8) +
440 ipcp->cfg.vj.slotcomp;
441 else
442 ipcp->my_compproto = 0;
443 sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1);
444
445 ipcp->peer_reject = 0;
446 ipcp->my_reject = 0;
447}
448
449static int
450ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr,
451 struct in_addr hisaddr, int silent)
452{
446
447 if (IsEnabled(ipcp->cfg.vj.neg))
448 ipcp->my_compproto = (PROTO_VJCOMP << 16) +
449 ((ipcp->cfg.vj.slots - 1) << 8) +
450 ipcp->cfg.vj.slotcomp;
451 else
452 ipcp->my_compproto = 0;
453 sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1);
454
455 ipcp->peer_reject = 0;
456 ipcp->my_reject = 0;
457}
458
459static int
460ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr,
461 struct in_addr hisaddr, int silent)
462{
453 struct sockaddr_in *sock_in;
454 int s;
455 u_int32_t mask, addr;
456 struct ifaliasreq ifra;
463 struct in_addr mask, oaddr;
464 u_int32_t addr;
457
465
458 /* If given addresses are alreay set, then ignore this request */
459 if (bundle->ncp.ipcp.my_ifip.s_addr == myaddr.s_addr &&
460 bundle->ncp.ipcp.peer_ifip.s_addr == hisaddr.s_addr)
461 return 0;
462
463 ipcp_CleanInterface(&bundle->ncp.ipcp);
464
465 s = ID0socket(AF_INET, SOCK_DGRAM, 0);
466 if (s < 0) {
467 log_Printf(LogERROR, "SetIPaddress: socket(): %s\n", strerror(errno));
468 return (-1);
469 }
470
471 memset(&ifra, '\0', sizeof ifra);
472 strncpy(ifra.ifra_name, bundle->ifp.Name, sizeof ifra.ifra_name - 1);
473 ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0';
474
475 /* Set interface address */
476 sock_in = (struct sockaddr_in *)&ifra.ifra_addr;
477 sock_in->sin_family = AF_INET;
478 sock_in->sin_addr = myaddr;
479 sock_in->sin_len = sizeof *sock_in;
480
481 /* Set destination address */
482 sock_in = (struct sockaddr_in *)&ifra.ifra_broadaddr;
483 sock_in->sin_family = AF_INET;
484 sock_in->sin_addr = hisaddr;
485 sock_in->sin_len = sizeof *sock_in;
486
487 addr = ntohl(myaddr.s_addr);
466 addr = htonl(myaddr.s_addr);
488 if (IN_CLASSA(addr))
467 if (IN_CLASSA(addr))
489 mask = IN_CLASSA_NET;
468 mask.s_addr = htonl(IN_CLASSA_NET);
490 else if (IN_CLASSB(addr))
469 else if (IN_CLASSB(addr))
491 mask = IN_CLASSB_NET;
470 mask.s_addr = htonl(IN_CLASSB_NET);
492 else
471 else
493 mask = IN_CLASSC_NET;
472 mask.s_addr = htonl(IN_CLASSC_NET);
494
473
495 /* if subnet mask is given, use it instead of class mask */
496 if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY &&
474 if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY &&
497 (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask) == mask)
498 mask = ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr);
475 (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask.s_addr) == mask.s_addr)
476 mask.s_addr = htonl(bundle->ncp.ipcp.cfg.netmask.s_addr);
499
477
500 sock_in = (struct sockaddr_in *)&ifra.ifra_mask;
501 sock_in->sin_family = AF_INET;
502 sock_in->sin_addr.s_addr = htonl(mask);
503 sock_in->sin_len = sizeof *sock_in;
478 oaddr.s_addr = bundle->iface->in_addrs ?
479 bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY;
480 if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr,
481 IFACE_ADD_FIRST|IFACE_FORCE_ADD))
482 return -1;
504
483
505 if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) {
506 if (!silent)
507 log_Printf(LogERROR, "SetIPaddress: ioctl(SIOCAIFADDR): %s\n",
508 strerror(errno));
509 close(s);
510 return (-1);
511 }
484 if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1
485 && myaddr.s_addr != oaddr.s_addr)
486 /* Nuke the old one */
487 iface_inDelete(bundle->iface, oaddr);
512
513 if (Enabled(bundle, OPT_SROUTES))
514 route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr);
515
488
489 if (Enabled(bundle, OPT_SROUTES))
490 route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr);
491
516 bundle->ncp.ipcp.peer_ifip.s_addr = hisaddr.s_addr;
517 bundle->ncp.ipcp.my_ifip.s_addr = myaddr.s_addr;
492 if (Enabled(bundle, OPT_PROXY)) {
493 int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
494 if (s < 0)
495 log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n",
496 strerror(errno));
497 else {
498 arp_SetProxy(bundle, hisaddr, s);
499 close(s);
500 }
501 }
518
502
519 if (Enabled(bundle, OPT_PROXY))
520 arp_SetProxy(bundle, bundle->ncp.ipcp.peer_ifip, s);
521
522 close(s);
523 return (0);
503 return 0;
524}
525
526static struct in_addr
504}
505
506static struct in_addr
527ChooseHisAddr(struct bundle *bundle, const struct in_addr gw)
507ChooseHisAddr(struct bundle *bundle, struct in_addr gw)
528{
529 struct in_addr try;
530 u_long f;
531
532 for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) {
533 try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list);
534 log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n",
535 f, inet_ntoa(try));
536 if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) {
537 log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try));
538 break;
539 }
540 }
541
542 if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) {
543 log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n");
544 try.s_addr = INADDR_ANY;
545 }
546
547 return try;
548}
549
550static void
551IpcpInitRestartCounter(struct fsm * fp)
552{
553 /* Set fsm timer load */
554 struct ipcp *ipcp = fsm2ipcp(fp);
555
556 fp->FsmTimer.load = ipcp->cfg.fsmretry * SECTICKS;
557 fp->restart = DEF_REQs;
558}
559
560static void
561IpcpSendConfigReq(struct fsm *fp)
562{
563 /* Send config REQ please */
564 struct physical *p = link2physical(fp->link);
565 struct ipcp *ipcp = fsm2ipcp(fp);
566 u_char buff[24];
567 struct lcp_opt *o;
568
569 o = (struct lcp_opt *)buff;
570
571 if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) {
572 memcpy(o->data, &ipcp->my_ip.s_addr, 4);
573 INC_LCP_OPT(TY_IPADDR, 6, o);
574 }
575
576 if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) {
577 if (ipcp->heis1172) {
578 u_int16_t proto = PROTO_VJCOMP;
579
580 ua_htons(&proto, o->data);
581 INC_LCP_OPT(TY_COMPPROTO, 4, o);
582 } else {
583 ua_htonl(&ipcp->my_compproto, o->data);
584 INC_LCP_OPT(TY_COMPPROTO, 6, o);
585 }
586 }
587
588 if (IsEnabled(ipcp->cfg.ns.dns_neg) &&
589 !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) &&
590 !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) {
591 struct in_addr dns[2];
592 getdns(ipcp, dns);
593 memcpy(o->data, &dns[0].s_addr, 4);
594 INC_LCP_OPT(TY_PRIMARY_DNS, 6, o);
595 memcpy(o->data, &dns[1].s_addr, 4);
596 INC_LCP_OPT(TY_SECONDARY_DNS, 6, o);
597 }
598
599 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff);
600}
601
602static void
603IpcpSentTerminateReq(struct fsm * fp)
604{
605 /* Term REQ just sent by FSM */
606}
607
608static void
609IpcpSendTerminateAck(struct fsm *fp, u_char id)
610{
611 /* Send Term ACK please */
612 fsm_Output(fp, CODE_TERMACK, id, NULL, 0);
613}
614
615static void
616IpcpLayerStart(struct fsm *fp)
617{
618 /* We're about to start up ! */
619 struct ipcp *ipcp = fsm2ipcp(fp);
620
621 log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name);
622 throughput_start(&ipcp->throughput, "IPCP throughput",
623 Enabled(fp->bundle, OPT_THROUGHPUT));
624
625 /* This is where we should be setting up the interface in AUTO mode */
626}
627
628static void
629IpcpLayerFinish(struct fsm *fp)
630{
631 /* We're now down */
632 struct ipcp *ipcp = fsm2ipcp(fp);
633
634 log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name);
635 throughput_stop(&ipcp->throughput);
636 throughput_log(&ipcp->throughput, LogIPCP, NULL);
637}
638
639void
640ipcp_CleanInterface(struct ipcp *ipcp)
641{
508{
509 struct in_addr try;
510 u_long f;
511
512 for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) {
513 try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list);
514 log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n",
515 f, inet_ntoa(try));
516 if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) {
517 log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try));
518 break;
519 }
520 }
521
522 if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) {
523 log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n");
524 try.s_addr = INADDR_ANY;
525 }
526
527 return try;
528}
529
530static void
531IpcpInitRestartCounter(struct fsm * fp)
532{
533 /* Set fsm timer load */
534 struct ipcp *ipcp = fsm2ipcp(fp);
535
536 fp->FsmTimer.load = ipcp->cfg.fsmretry * SECTICKS;
537 fp->restart = DEF_REQs;
538}
539
540static void
541IpcpSendConfigReq(struct fsm *fp)
542{
543 /* Send config REQ please */
544 struct physical *p = link2physical(fp->link);
545 struct ipcp *ipcp = fsm2ipcp(fp);
546 u_char buff[24];
547 struct lcp_opt *o;
548
549 o = (struct lcp_opt *)buff;
550
551 if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) {
552 memcpy(o->data, &ipcp->my_ip.s_addr, 4);
553 INC_LCP_OPT(TY_IPADDR, 6, o);
554 }
555
556 if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) {
557 if (ipcp->heis1172) {
558 u_int16_t proto = PROTO_VJCOMP;
559
560 ua_htons(&proto, o->data);
561 INC_LCP_OPT(TY_COMPPROTO, 4, o);
562 } else {
563 ua_htonl(&ipcp->my_compproto, o->data);
564 INC_LCP_OPT(TY_COMPPROTO, 6, o);
565 }
566 }
567
568 if (IsEnabled(ipcp->cfg.ns.dns_neg) &&
569 !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) &&
570 !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) {
571 struct in_addr dns[2];
572 getdns(ipcp, dns);
573 memcpy(o->data, &dns[0].s_addr, 4);
574 INC_LCP_OPT(TY_PRIMARY_DNS, 6, o);
575 memcpy(o->data, &dns[1].s_addr, 4);
576 INC_LCP_OPT(TY_SECONDARY_DNS, 6, o);
577 }
578
579 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff);
580}
581
582static void
583IpcpSentTerminateReq(struct fsm * fp)
584{
585 /* Term REQ just sent by FSM */
586}
587
588static void
589IpcpSendTerminateAck(struct fsm *fp, u_char id)
590{
591 /* Send Term ACK please */
592 fsm_Output(fp, CODE_TERMACK, id, NULL, 0);
593}
594
595static void
596IpcpLayerStart(struct fsm *fp)
597{
598 /* We're about to start up ! */
599 struct ipcp *ipcp = fsm2ipcp(fp);
600
601 log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name);
602 throughput_start(&ipcp->throughput, "IPCP throughput",
603 Enabled(fp->bundle, OPT_THROUGHPUT));
604
605 /* This is where we should be setting up the interface in AUTO mode */
606}
607
608static void
609IpcpLayerFinish(struct fsm *fp)
610{
611 /* We're now down */
612 struct ipcp *ipcp = fsm2ipcp(fp);
613
614 log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name);
615 throughput_stop(&ipcp->throughput);
616 throughput_log(&ipcp->throughput, LogIPCP, NULL);
617}
618
619void
620ipcp_CleanInterface(struct ipcp *ipcp)
621{
642 struct ifaliasreq ifra;
643 struct sockaddr_in *me, *peer;
644 int s;
622 struct iface *iface = ipcp->fsm.bundle->iface;
645
623
646 s = ID0socket(AF_INET, SOCK_DGRAM, 0);
647 if (s < 0) {
648 log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", strerror(errno));
649 return;
650 }
651
652 route_Clean(ipcp->fsm.bundle, ipcp->route);
653
624 route_Clean(ipcp->fsm.bundle, ipcp->route);
625
654 if (Enabled(ipcp->fsm.bundle, OPT_PROXY))
655 arp_ClearProxy(ipcp->fsm.bundle, ipcp->peer_ifip, s);
656
657 if (ipcp->my_ifip.s_addr != INADDR_ANY ||
658 ipcp->peer_ifip.s_addr != INADDR_ANY) {
659 memset(&ifra, '\0', sizeof ifra);
660 strncpy(ifra.ifra_name, ipcp->fsm.bundle->ifp.Name,
661 sizeof ifra.ifra_name - 1);
662 ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0';
663 me = (struct sockaddr_in *)&ifra.ifra_addr;
664 peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
665 me->sin_family = peer->sin_family = AF_INET;
666 me->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
667 me->sin_addr = ipcp->my_ifip;
668 peer->sin_addr = ipcp->peer_ifip;
669 if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0)
670 log_Printf(LogERROR, "ipcp_CleanInterface: ioctl(SIOCDIFADDR): %s\n",
671 strerror(errno));
672 ipcp->my_ifip.s_addr = ipcp->peer_ifip.s_addr = INADDR_ANY;
626 if (iface->in_addrs && Enabled(ipcp->fsm.bundle, OPT_PROXY)) {
627 int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
628 if (s < 0)
629 log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n",
630 strerror(errno));
631 else {
632 arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s);
633 close(s);
634 }
673 }
674
635 }
636
675 close(s);
637 iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL);
676}
677
678static void
679IpcpLayerDown(struct fsm *fp)
680{
681 /* About to come down */
682 struct ipcp *ipcp = fsm2ipcp(fp);
683 const char *s;
684
638}
639
640static void
641IpcpLayerDown(struct fsm *fp)
642{
643 /* About to come down */
644 struct ipcp *ipcp = fsm2ipcp(fp);
645 const char *s;
646
685 s = inet_ntoa(ipcp->peer_ifip);
647 if (ipcp->fsm.bundle->iface->in_addrs)
648 s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa);
649 else
650 s = "Interface configuration error !";
686 log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s);
687
688 /*
689 * XXX this stuff should really live in the FSM. Our config should
690 * associate executable sections in files with events.
691 */
692 if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) {
693 if (bundle_GetLabel(fp->bundle)) {
694 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
695 LINKDOWNFILE, NULL, NULL) < 0)
696 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
697 } else
698 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
699 }
700
651 log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s);
652
653 /*
654 * XXX this stuff should really live in the FSM. Our config should
655 * associate executable sections in files with events.
656 */
657 if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) {
658 if (bundle_GetLabel(fp->bundle)) {
659 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
660 LINKDOWNFILE, NULL, NULL) < 0)
661 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
662 } else
663 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
664 }
665
701 if (!(ipcp->fsm.bundle->phys_type.all & PHYS_AUTO))
702 ipcp_CleanInterface(ipcp);
703
704 ipcp_Setup(ipcp);
705}
706
707int
708ipcp_InterfaceUp(struct ipcp *ipcp)
709{
710 if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) {
711 log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n");
712 return 0;
713 }
714
715#ifndef NOALIAS
716 if (ipcp->fsm.bundle->AliasEnabled)
717 PacketAliasSetAddress(ipcp->my_ip);
718#endif
719
720 return 1;
721}
722
723static int
724IpcpLayerUp(struct fsm *fp)
725{
726 /* We're now up */
727 struct ipcp *ipcp = fsm2ipcp(fp);
666 ipcp_Setup(ipcp);
667}
668
669int
670ipcp_InterfaceUp(struct ipcp *ipcp)
671{
672 if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) {
673 log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n");
674 return 0;
675 }
676
677#ifndef NOALIAS
678 if (ipcp->fsm.bundle->AliasEnabled)
679 PacketAliasSetAddress(ipcp->my_ip);
680#endif
681
682 return 1;
683}
684
685static int
686IpcpLayerUp(struct fsm *fp)
687{
688 /* We're now up */
689 struct ipcp *ipcp = fsm2ipcp(fp);
728 char tbuff[100];
690 char tbuff[16];
729
730 log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name);
691
692 log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name);
731 snprintf(tbuff, sizeof tbuff, "myaddr = %s ", inet_ntoa(ipcp->my_ip));
732 log_Printf(LogIPCP, " %s hisaddr = %s\n", tbuff, inet_ntoa(ipcp->peer_ip));
693 snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip));
694 log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n",
695 tbuff, inet_ntoa(ipcp->peer_ip));
733
734 if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP)
735 sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255);
736
737 if (!ipcp_InterfaceUp(ipcp))
738 return 0;
739
740 /*
741 * XXX this stuff should really live in the FSM. Our config should
742 * associate executable sections in files with events.
743 */
696
697 if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP)
698 sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255);
699
700 if (!ipcp_InterfaceUp(ipcp))
701 return 0;
702
703 /*
704 * XXX this stuff should really live in the FSM. Our config should
705 * associate executable sections in files with events.
706 */
744 if (system_Select(fp->bundle, inet_ntoa(ipcp->my_ifip), LINKUPFILE,
745 NULL, NULL) < 0) {
707 if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) {
746 if (bundle_GetLabel(fp->bundle)) {
747 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
748 LINKUPFILE, NULL, NULL) < 0)
749 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
750 } else
751 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
752 }
753
754 log_DisplayPrompts();
755 return 1;
756}
757
758static int
708 if (bundle_GetLabel(fp->bundle)) {
709 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
710 LINKUPFILE, NULL, NULL) < 0)
711 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
712 } else
713 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
714 }
715
716 log_DisplayPrompts();
717 return 1;
718}
719
720static int
759AcceptableAddr(struct in_range *prange, struct in_addr ipaddr)
721AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr)
760{
761 /* Is the given IP in the given range ? */
762 return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
763 (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
764}
765
766static void
767IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
768 struct fsm_decode *dec)
769{
770 /* Deal with incoming PROTO_IPCP */
722{
723 /* Is the given IP in the given range ? */
724 return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
725 (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
726}
727
728static void
729IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type,
730 struct fsm_decode *dec)
731{
732 /* Deal with incoming PROTO_IPCP */
733 struct iface *iface = fp->bundle->iface;
771 struct ipcp *ipcp = fsm2ipcp(fp);
734 struct ipcp *ipcp = fsm2ipcp(fp);
772 int type, length;
735 int type, length, gotdns, gotdnsnak, n;
773 u_int32_t compproto;
774 struct compreq *pcomp;
775 struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2];
776 char tbuff[100], tbuff2[100];
736 u_int32_t compproto;
737 struct compreq *pcomp;
738 struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2];
739 char tbuff[100], tbuff2[100];
777 int gotdns, gotdnsnak;
778
779 gotdns = 0;
780 gotdnsnak = 0;
781 dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY;
782
783 while (plen >= sizeof(struct fsmconfig)) {
784 type = *cp;
785 length = cp[1];
786
787 if (length == 0) {
788 log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name);
789 break;
790 }
791
792 if (type < NCFTYPES)
793 snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length);
794 else if (type > 128 && type < 128 + NCFTYPES128)
795 snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length);
796 else
797 snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length);
798
799 switch (type) {
800 case TY_IPADDR: /* RFC1332 */
801 memcpy(&ipaddr.s_addr, cp + 2, 4);
802 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
803
804 switch (mode_type) {
805 case MODE_REQ:
806 if (iplist_isvalid(&ipcp->cfg.peer_list)) {
807 if (ipaddr.s_addr == INADDR_ANY ||
808 iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 ||
809 ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr,
810 ipaddr, 1)) {
811 log_Printf(LogIPCP, "%s: Address invalid or already in use\n",
812 inet_ntoa(ipaddr));
740
741 gotdns = 0;
742 gotdnsnak = 0;
743 dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY;
744
745 while (plen >= sizeof(struct fsmconfig)) {
746 type = *cp;
747 length = cp[1];
748
749 if (length == 0) {
750 log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name);
751 break;
752 }
753
754 if (type < NCFTYPES)
755 snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length);
756 else if (type > 128 && type < 128 + NCFTYPES128)
757 snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length);
758 else
759 snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length);
760
761 switch (type) {
762 case TY_IPADDR: /* RFC1332 */
763 memcpy(&ipaddr.s_addr, cp + 2, 4);
764 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
765
766 switch (mode_type) {
767 case MODE_REQ:
768 if (iplist_isvalid(&ipcp->cfg.peer_list)) {
769 if (ipaddr.s_addr == INADDR_ANY ||
770 iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 ||
771 ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr,
772 ipaddr, 1)) {
773 log_Printf(LogIPCP, "%s: Address invalid or already in use\n",
774 inet_ntoa(ipaddr));
813 if (iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->peer_ifip) >= 0)
814 /*
815 * If we've already got a valid address configured for the peer
816 * (in AUTO mode), try NAKing with that so that we don't
817 * have to upset things too much.
818 */
819 ipcp->peer_ip = ipcp->peer_ifip;
820 else
775 /*
776 * If we've already had a valid address configured for the peer,
777 * try NAKing with that so that we don't have to upset things
778 * too much.
779 */
780 for (n = 0; n < iface->in_addrs; n++)
781 if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd)
782 >=0) {
783 ipcp->peer_ip = iface->in_addr[n].brd;
784 break;
785 }
786
787 if (n == iface->in_addrs)
821 /* Just pick an IP number from our list */
822 ipcp->peer_ip = ChooseHisAddr
823 (fp->bundle, ipcp->cfg.my_range.ipaddr);
824
825 if (ipcp->peer_ip.s_addr == INADDR_ANY) {
826 memcpy(dec->rejend, cp, length);
827 dec->rejend += length;
828 } else {
829 memcpy(dec->nakend, cp, 2);
788 /* Just pick an IP number from our list */
789 ipcp->peer_ip = ChooseHisAddr
790 (fp->bundle, ipcp->cfg.my_range.ipaddr);
791
792 if (ipcp->peer_ip.s_addr == INADDR_ANY) {
793 memcpy(dec->rejend, cp, length);
794 dec->rejend += length;
795 } else {
796 memcpy(dec->nakend, cp, 2);
830 memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2);
797 memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2);
831 dec->nakend += length;
832 }
833 break;
834 }
835 } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) {
836 /*
837 * If destination address is not acceptable, NAK with what we
838 * want to use.
839 */
840 memcpy(dec->nakend, cp, 2);
798 dec->nakend += length;
799 }
800 break;
801 }
802 } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) {
803 /*
804 * If destination address is not acceptable, NAK with what we
805 * want to use.
806 */
807 memcpy(dec->nakend, cp, 2);
841 if ((ipcp->peer_ifip.s_addr & ipcp->cfg.peer_range.mask.s_addr) ==
842 (ipcp->cfg.peer_range.ipaddr.s_addr &
843 ipcp->cfg.peer_range.mask.s_addr))
844 /* We prefer the already-configured address */
845 memcpy(dec->nakend+2, &ipcp->peer_ifip.s_addr, length - 2);
846 else
847 memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2);
808 for (n = 0; n < iface->in_addrs; n++)
809 if ((iface->in_addr[n].brd.s_addr &
810 ipcp->cfg.peer_range.mask.s_addr)
811 == (ipcp->cfg.peer_range.ipaddr.s_addr &
812 ipcp->cfg.peer_range.mask.s_addr)) {
813 /* We prefer the already-configured address */
814 memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr,
815 length - 2);
816 break;
817 }
818
819 if (n == iface->in_addrs)
820 memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2);
821
848 dec->nakend += length;
849 break;
850 }
851 ipcp->peer_ip = ipaddr;
852 memcpy(dec->ackend, cp, length);
853 dec->ackend += length;
854 break;
822 dec->nakend += length;
823 break;
824 }
825 ipcp->peer_ip = ipaddr;
826 memcpy(dec->ackend, cp, length);
827 dec->ackend += length;
828 break;
829
855 case MODE_NAK:
856 if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) {
857 /* Use address suggested by peer */
858 snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
859 inet_ntoa(ipcp->my_ip));
860 log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
861 ipcp->my_ip = ipaddr;
862 } else {
863 log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE,
864 "%s: Unacceptable address!\n", inet_ntoa(ipaddr));
865 fsm_Close(&ipcp->fsm);
866 }
867 break;
830 case MODE_NAK:
831 if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) {
832 /* Use address suggested by peer */
833 snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
834 inet_ntoa(ipcp->my_ip));
835 log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
836 ipcp->my_ip = ipaddr;
837 } else {
838 log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE,
839 "%s: Unacceptable address!\n", inet_ntoa(ipaddr));
840 fsm_Close(&ipcp->fsm);
841 }
842 break;
843
868 case MODE_REJ:
869 ipcp->peer_reject |= (1 << type);
870 break;
871 }
872 break;
844 case MODE_REJ:
845 ipcp->peer_reject |= (1 << type);
846 break;
847 }
848 break;
849
873 case TY_COMPPROTO:
874 memcpy(&compproto, cp + 2, 4);
875 log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
876
877 switch (mode_type) {
878 case MODE_REQ:
879 if (!IsAccepted(ipcp->cfg.vj.neg)) {
880 memcpy(dec->rejend, cp, length);
881 dec->rejend += length;
882 } else {
883 pcomp = (struct compreq *) (cp + 2);
884 switch (length) {
885 case 4: /* RFC1172 */
886 if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
887 log_Printf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
888 ipcp->heis1172 = 1;
889 ipcp->peer_compproto = compproto;
890 memcpy(dec->ackend, cp, length);
891 dec->ackend += length;
892 } else {
893 memcpy(dec->nakend, cp, 2);
894 pcomp->proto = htons(PROTO_VJCOMP);
895 memcpy(dec->nakend+2, &pcomp, 2);
896 dec->nakend += length;
897 }
898 break;
899 case 6: /* RFC1332 */
900 if (ntohs(pcomp->proto) == PROTO_VJCOMP
901 && pcomp->slots <= MAX_VJ_STATES
902 && pcomp->slots >= MIN_VJ_STATES) {
903 ipcp->peer_compproto = compproto;
904 ipcp->heis1172 = 0;
905 memcpy(dec->ackend, cp, length);
906 dec->ackend += length;
907 } else {
908 memcpy(dec->nakend, cp, 2);
909 pcomp->proto = htons(PROTO_VJCOMP);
910 pcomp->slots = DEF_VJ_STATES;
911 pcomp->compcid = 0;
912 memcpy(dec->nakend+2, &pcomp, sizeof pcomp);
913 dec->nakend += length;
914 }
915 break;
916 default:
917 memcpy(dec->rejend, cp, length);
918 dec->rejend += length;
919 break;
920 }
921 }
922 break;
850 case TY_COMPPROTO:
851 memcpy(&compproto, cp + 2, 4);
852 log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
853
854 switch (mode_type) {
855 case MODE_REQ:
856 if (!IsAccepted(ipcp->cfg.vj.neg)) {
857 memcpy(dec->rejend, cp, length);
858 dec->rejend += length;
859 } else {
860 pcomp = (struct compreq *) (cp + 2);
861 switch (length) {
862 case 4: /* RFC1172 */
863 if (ntohs(pcomp->proto) == PROTO_VJCOMP) {
864 log_Printf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n");
865 ipcp->heis1172 = 1;
866 ipcp->peer_compproto = compproto;
867 memcpy(dec->ackend, cp, length);
868 dec->ackend += length;
869 } else {
870 memcpy(dec->nakend, cp, 2);
871 pcomp->proto = htons(PROTO_VJCOMP);
872 memcpy(dec->nakend+2, &pcomp, 2);
873 dec->nakend += length;
874 }
875 break;
876 case 6: /* RFC1332 */
877 if (ntohs(pcomp->proto) == PROTO_VJCOMP
878 && pcomp->slots <= MAX_VJ_STATES
879 && pcomp->slots >= MIN_VJ_STATES) {
880 ipcp->peer_compproto = compproto;
881 ipcp->heis1172 = 0;
882 memcpy(dec->ackend, cp, length);
883 dec->ackend += length;
884 } else {
885 memcpy(dec->nakend, cp, 2);
886 pcomp->proto = htons(PROTO_VJCOMP);
887 pcomp->slots = DEF_VJ_STATES;
888 pcomp->compcid = 0;
889 memcpy(dec->nakend+2, &pcomp, sizeof pcomp);
890 dec->nakend += length;
891 }
892 break;
893 default:
894 memcpy(dec->rejend, cp, length);
895 dec->rejend += length;
896 break;
897 }
898 }
899 break;
900
923 case MODE_NAK:
924 log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
925 tbuff, ipcp->my_compproto, compproto);
926 ipcp->my_compproto = compproto;
927 break;
901 case MODE_NAK:
902 log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
903 tbuff, ipcp->my_compproto, compproto);
904 ipcp->my_compproto = compproto;
905 break;
906
928 case MODE_REJ:
929 ipcp->peer_reject |= (1 << type);
930 break;
931 }
932 break;
907 case MODE_REJ:
908 ipcp->peer_reject |= (1 << type);
909 break;
910 }
911 break;
912
933 case TY_IPADDRS: /* RFC1172 */
934 memcpy(&ipaddr.s_addr, cp + 2, 4);
935 memcpy(&dstipaddr.s_addr, cp + 6, 4);
936 snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr));
937 log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
938
939 switch (mode_type) {
940 case MODE_REQ:
941 ipcp->peer_ip = ipaddr;
942 ipcp->my_ip = dstipaddr;
943 memcpy(dec->ackend, cp, length);
944 dec->ackend += length;
945 break;
913 case TY_IPADDRS: /* RFC1172 */
914 memcpy(&ipaddr.s_addr, cp + 2, 4);
915 memcpy(&dstipaddr.s_addr, cp + 6, 4);
916 snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr));
917 log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
918
919 switch (mode_type) {
920 case MODE_REQ:
921 ipcp->peer_ip = ipaddr;
922 ipcp->my_ip = dstipaddr;
923 memcpy(dec->ackend, cp, length);
924 dec->ackend += length;
925 break;
926
946 case MODE_NAK:
947 snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff,
948 inet_ntoa(ipcp->my_ip));
949 log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
950 ipcp->my_ip = ipaddr;
951 ipcp->peer_ip = dstipaddr;
952 break;
927 case MODE_NAK:
928 snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff,
929 inet_ntoa(ipcp->my_ip));
930 log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
931 ipcp->my_ip = ipaddr;
932 ipcp->peer_ip = dstipaddr;
933 break;
934
953 case MODE_REJ:
954 ipcp->peer_reject |= (1 << type);
955 break;
956 }
957 break;
958
959 case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */
960 case TY_SECONDARY_DNS:
961 memcpy(&ipaddr.s_addr, cp + 2, 4);
962 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
963
964 switch (mode_type) {
965 case MODE_REQ:
966 if (!IsAccepted(ipcp->cfg.ns.dns_neg)) {
967 ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
968 memcpy(dec->rejend, cp, length);
969 dec->rejend += length;
970 break;
971 }
972 if (!gotdns) {
973 dns[0] = ipcp->cfg.ns.dns[0];
974 dns[1] = ipcp->cfg.ns.dns[1];
975 if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY)
976 getdns(ipcp, dns);
977 gotdns = 1;
978 }
979 have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1];
980
981 if (ipaddr.s_addr != have_ip.s_addr) {
982 /*
983 * The client has got the DNS stuff wrong (first request) so
984 * we'll tell 'em how it is
985 */
986 memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */
987 memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2);
988 dec->nakend += length;
989 } else {
990 /*
991 * Otherwise they have it right (this time) so we send a ack packet
992 * back confirming it... end of story
993 */
994 memcpy(dec->ackend, cp, length);
995 dec->ackend += length;
996 }
997 break;
935 case MODE_REJ:
936 ipcp->peer_reject |= (1 << type);
937 break;
938 }
939 break;
940
941 case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */
942 case TY_SECONDARY_DNS:
943 memcpy(&ipaddr.s_addr, cp + 2, 4);
944 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
945
946 switch (mode_type) {
947 case MODE_REQ:
948 if (!IsAccepted(ipcp->cfg.ns.dns_neg)) {
949 ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
950 memcpy(dec->rejend, cp, length);
951 dec->rejend += length;
952 break;
953 }
954 if (!gotdns) {
955 dns[0] = ipcp->cfg.ns.dns[0];
956 dns[1] = ipcp->cfg.ns.dns[1];
957 if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY)
958 getdns(ipcp, dns);
959 gotdns = 1;
960 }
961 have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1];
962
963 if (ipaddr.s_addr != have_ip.s_addr) {
964 /*
965 * The client has got the DNS stuff wrong (first request) so
966 * we'll tell 'em how it is
967 */
968 memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */
969 memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2);
970 dec->nakend += length;
971 } else {
972 /*
973 * Otherwise they have it right (this time) so we send a ack packet
974 * back confirming it... end of story
975 */
976 memcpy(dec->ackend, cp, length);
977 dec->ackend += length;
978 }
979 break;
980
998 case MODE_NAK: /* what does this mean?? */
999 if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
1000 gotdnsnak = 1;
1001 memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4);
1002 }
1003 break;
981 case MODE_NAK: /* what does this mean?? */
982 if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
983 gotdnsnak = 1;
984 memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4);
985 }
986 break;
987
1004 case MODE_REJ: /* Can't do much, stop asking */
1005 ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS));
1006 break;
1007 }
1008 break;
1009
1010 case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */
1011 case TY_SECONDARY_NBNS:
1012 memcpy(&ipaddr.s_addr, cp + 2, 4);
1013 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
1014
1015 switch (mode_type) {
1016 case MODE_REQ:
1017 have_ip.s_addr =
1018 ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr;
1019
1020 if (have_ip.s_addr == INADDR_ANY) {
1021 log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n");
1022 ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
1023 memcpy(dec->rejend, cp, length);
1024 dec->rejend += length;
1025 break;
1026 }
1027
1028 if (ipaddr.s_addr != have_ip.s_addr) {
1029 memcpy(dec->nakend, cp, 2);
1030 memcpy(dec->nakend+2, &have_ip.s_addr, length);
1031 dec->nakend += length;
1032 } else {
1033 memcpy(dec->ackend, cp, length);
1034 dec->ackend += length;
1035 }
1036 break;
988 case MODE_REJ: /* Can't do much, stop asking */
989 ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS));
990 break;
991 }
992 break;
993
994 case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */
995 case TY_SECONDARY_NBNS:
996 memcpy(&ipaddr.s_addr, cp + 2, 4);
997 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
998
999 switch (mode_type) {
1000 case MODE_REQ:
1001 have_ip.s_addr =
1002 ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr;
1003
1004 if (have_ip.s_addr == INADDR_ANY) {
1005 log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n");
1006 ipcp->my_reject |= (1 << (type - TY_ADJUST_NS));
1007 memcpy(dec->rejend, cp, length);
1008 dec->rejend += length;
1009 break;
1010 }
1011
1012 if (ipaddr.s_addr != have_ip.s_addr) {
1013 memcpy(dec->nakend, cp, 2);
1014 memcpy(dec->nakend+2, &have_ip.s_addr, length);
1015 dec->nakend += length;
1016 } else {
1017 memcpy(dec->ackend, cp, length);
1018 dec->ackend += length;
1019 }
1020 break;
1021
1037 case MODE_NAK:
1038 log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
1039 break;
1022 case MODE_NAK:
1023 log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
1024 break;
1025
1040 case MODE_REJ:
1041 log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
1042 break;
1043 }
1044 break;
1045
1046 default:
1047 if (mode_type != MODE_NOP) {
1048 ipcp->my_reject |= (1 << type);
1049 memcpy(dec->rejend, cp, length);
1050 dec->rejend += length;
1051 }
1052 break;
1053 }
1054 plen -= length;
1055 cp += length;
1056 }
1057
1058 if (gotdnsnak)
1059 if (!setdns(ipcp, dnsnak)) {
1060 ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS));
1061 ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS));
1062 }
1063
1064 if (mode_type != MODE_NOP) {
1065 if (dec->rejend != dec->rej) {
1066 /* rejects are preferred */
1067 dec->ackend = dec->ack;
1068 dec->nakend = dec->nak;
1069 } else if (dec->nakend != dec->nak)
1070 /* then NAKs */
1071 dec->ackend = dec->ack;
1072 }
1073}
1074
1075void
1076ipcp_Input(struct ipcp *ipcp, struct bundle *bundle, struct mbuf *bp)
1077{
1078 /* Got PROTO_IPCP from link */
1079 if (bundle_Phase(bundle) == PHASE_NETWORK)
1080 fsm_Input(&ipcp->fsm, bp);
1081 else {
1082 if (bundle_Phase(bundle) < PHASE_NETWORK)
1083 log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n",
1084 ipcp->fsm.link->name, bundle_PhaseName(bundle));
1085 mbuf_Free(bp);
1086 }
1087}
1088
1089int
1090ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr)
1091{
1092 struct ipcp *ipcp = &bundle->ncp.ipcp;
1093
1094 /* Use `hisaddr' for the peers address (set iface if `setaddr') */
1095 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
1096 iplist_reset(&ipcp->cfg.peer_list);
1097 if (strpbrk(hisaddr, ",-")) {
1098 iplist_setsrc(&ipcp->cfg.peer_list, hisaddr);
1099 if (iplist_isvalid(&ipcp->cfg.peer_list)) {
1100 iplist_setrandpos(&ipcp->cfg.peer_list);
1101 ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip);
1102 if (ipcp->peer_ip.s_addr == INADDR_ANY) {
1103 log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src);
1104 return(0);
1105 }
1106 ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr;
1107 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
1108 ipcp->cfg.peer_range.width = 32;
1109 } else {
1110 log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr);
1111 return 0;
1112 }
1113 } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr,
1114 &ipcp->cfg.peer_range.mask,
1115 &ipcp->cfg.peer_range.width) != 0) {
1116 ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr;
1117
1118 if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr,
1026 case MODE_REJ:
1027 log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type);
1028 break;
1029 }
1030 break;
1031
1032 default:
1033 if (mode_type != MODE_NOP) {
1034 ipcp->my_reject |= (1 << type);
1035 memcpy(dec->rejend, cp, length);
1036 dec->rejend += length;
1037 }
1038 break;
1039 }
1040 plen -= length;
1041 cp += length;
1042 }
1043
1044 if (gotdnsnak)
1045 if (!setdns(ipcp, dnsnak)) {
1046 ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS));
1047 ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS));
1048 }
1049
1050 if (mode_type != MODE_NOP) {
1051 if (dec->rejend != dec->rej) {
1052 /* rejects are preferred */
1053 dec->ackend = dec->ack;
1054 dec->nakend = dec->nak;
1055 } else if (dec->nakend != dec->nak)
1056 /* then NAKs */
1057 dec->ackend = dec->ack;
1058 }
1059}
1060
1061void
1062ipcp_Input(struct ipcp *ipcp, struct bundle *bundle, struct mbuf *bp)
1063{
1064 /* Got PROTO_IPCP from link */
1065 if (bundle_Phase(bundle) == PHASE_NETWORK)
1066 fsm_Input(&ipcp->fsm, bp);
1067 else {
1068 if (bundle_Phase(bundle) < PHASE_NETWORK)
1069 log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n",
1070 ipcp->fsm.link->name, bundle_PhaseName(bundle));
1071 mbuf_Free(bp);
1072 }
1073}
1074
1075int
1076ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr)
1077{
1078 struct ipcp *ipcp = &bundle->ncp.ipcp;
1079
1080 /* Use `hisaddr' for the peers address (set iface if `setaddr') */
1081 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
1082 iplist_reset(&ipcp->cfg.peer_list);
1083 if (strpbrk(hisaddr, ",-")) {
1084 iplist_setsrc(&ipcp->cfg.peer_list, hisaddr);
1085 if (iplist_isvalid(&ipcp->cfg.peer_list)) {
1086 iplist_setrandpos(&ipcp->cfg.peer_list);
1087 ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip);
1088 if (ipcp->peer_ip.s_addr == INADDR_ANY) {
1089 log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src);
1090 return(0);
1091 }
1092 ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr;
1093 ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
1094 ipcp->cfg.peer_range.width = 32;
1095 } else {
1096 log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr);
1097 return 0;
1098 }
1099 } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr,
1100 &ipcp->cfg.peer_range.mask,
1101 &ipcp->cfg.peer_range.width) != 0) {
1102 ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr;
1103
1104 if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr,
1119 ipcp->cfg.peer_range.ipaddr, 0) < 0) {
1120 ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY;
1121 ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY;
1105 ipcp->cfg.peer_range.ipaddr, 0) < 0)
1122 return 0;
1106 return 0;
1123 }
1124 } else
1125 return 0;
1126
1127 return 1;
1128}
1107 } else
1108 return 0;
1109
1110 return 1;
1111}