Deleted Added
sdiff udiff text old ( 39395 ) new ( 40561 )
full compact
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.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"
80#include "iface.h"
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);
358 if (hp && hp->h_addrtype == AF_INET)
359 memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length);
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
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{
391 struct iface *iface = ipcp->fsm.bundle->iface;
392 int pos, n;
393
394 ipcp->fsm.open_mode = 0;
395 ipcp->fsm.maxconfig = 10;
396
397 if (iplist_isvalid(&ipcp->cfg.peer_list)) {
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 */
409 ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list);
410
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));
429 } else {
430 /*
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).
436 */
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 }
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{
463 struct in_addr mask, oaddr;
464 u_int32_t addr;
465
466 addr = htonl(myaddr.s_addr);
467 if (IN_CLASSA(addr))
468 mask.s_addr = htonl(IN_CLASSA_NET);
469 else if (IN_CLASSB(addr))
470 mask.s_addr = htonl(IN_CLASSB_NET);
471 else
472 mask.s_addr = htonl(IN_CLASSC_NET);
473
474 if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY &&
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);
477
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;
483
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);
488
489 if (Enabled(bundle, OPT_SROUTES))
490 route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr);
491
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 }
502
503 return 0;
504}
505
506static struct in_addr
507ChooseHisAddr(struct bundle *bundle, struct in_addr gw)
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{
622 struct iface *iface = ipcp->fsm.bundle->iface;
623
624 route_Clean(ipcp->fsm.bundle, ipcp->route);
625
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 }
635 }
636
637 iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL);
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
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 !";
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
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);
690 char tbuff[16];
691
692 log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name);
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));
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 */
707 if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) {
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
721AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr)
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;
734 struct ipcp *ipcp = fsm2ipcp(fp);
735 int type, length, gotdns, gotdnsnak, n;
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];
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));
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)
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);
797 memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 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);
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
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
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
844 case MODE_REJ:
845 ipcp->peer_reject |= (1 << type);
846 break;
847 }
848 break;
849
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
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
907 case MODE_REJ:
908 ipcp->peer_reject |= (1 << type);
909 break;
910 }
911 break;
912
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
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
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
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
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
1022 case MODE_NAK:
1023 log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type);
1024 break;
1025
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,
1105 ipcp->cfg.peer_range.ipaddr, 0) < 0)
1106 return 0;
1107 } else
1108 return 0;
1109
1110 return 1;
1111}