turns printfs back on
[freebsd-src/fkvm-freebsd.git] / usr.sbin / ppp / ipcp.c
blob8991063fba31e478220d8dc20b693d91dcb5a1b3
1 /*-
2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4 * Internet Initiative Japan, Inc (IIJ)
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
28 * $FreeBSD$
31 #include <sys/param.h>
32 #include <netinet/in_systm.h>
33 #include <netinet/in.h>
34 #include <netinet/ip.h>
35 #include <arpa/inet.h>
36 #include <sys/socket.h>
37 #include <net/if.h>
38 #include <net/route.h>
39 #include <netdb.h>
40 #include <sys/un.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <resolv.h>
45 #include <stdarg.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <sys/stat.h>
49 #include <termios.h>
50 #include <unistd.h>
52 #ifndef NONAT
53 #ifdef LOCALNAT
54 #include "alias.h"
55 #else
56 #include <alias.h>
57 #endif
58 #endif
60 #include "layer.h"
61 #include "ua.h"
62 #include "defs.h"
63 #include "command.h"
64 #include "mbuf.h"
65 #include "log.h"
66 #include "timer.h"
67 #include "fsm.h"
68 #include "proto.h"
69 #include "iplist.h"
70 #include "throughput.h"
71 #include "slcompress.h"
72 #include "lqr.h"
73 #include "hdlc.h"
74 #include "lcp.h"
75 #include "ncpaddr.h"
76 #include "ip.h"
77 #include "ipcp.h"
78 #include "filter.h"
79 #include "descriptor.h"
80 #include "vjcomp.h"
81 #include "async.h"
82 #include "ccp.h"
83 #include "link.h"
84 #include "physical.h"
85 #include "mp.h"
86 #ifndef NORADIUS
87 #include "radius.h"
88 #endif
89 #include "ipv6cp.h"
90 #include "ncp.h"
91 #include "bundle.h"
92 #include "id.h"
93 #include "arp.h"
94 #include "systems.h"
95 #include "prompt.h"
96 #include "route.h"
97 #include "iface.h"
99 #undef REJECTED
100 #define REJECTED(p, x) ((p)->peer_reject & (1<<(x)))
101 #define issep(ch) ((ch) == ' ' || (ch) == '\t')
102 #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.')
104 struct compreq {
105 u_short proto;
106 u_char slots;
107 u_char compcid;
110 static int IpcpLayerUp(struct fsm *);
111 static void IpcpLayerDown(struct fsm *);
112 static void IpcpLayerStart(struct fsm *);
113 static void IpcpLayerFinish(struct fsm *);
114 static void IpcpInitRestartCounter(struct fsm *, int);
115 static void IpcpSendConfigReq(struct fsm *);
116 static void IpcpSentTerminateReq(struct fsm *);
117 static void IpcpSendTerminateAck(struct fsm *, u_char);
118 static void IpcpDecodeConfig(struct fsm *, u_char *, u_char *, int,
119 struct fsm_decode *);
121 extern struct libalias *la;
123 static struct fsm_callbacks ipcp_Callbacks = {
124 IpcpLayerUp,
125 IpcpLayerDown,
126 IpcpLayerStart,
127 IpcpLayerFinish,
128 IpcpInitRestartCounter,
129 IpcpSendConfigReq,
130 IpcpSentTerminateReq,
131 IpcpSendTerminateAck,
132 IpcpDecodeConfig,
133 fsm_NullRecvResetReq,
134 fsm_NullRecvResetAck
137 static const char *
138 protoname(int proto)
140 static struct {
141 int id;
142 const char *txt;
143 } cftypes[] = {
144 /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */
145 { 1, "IPADDRS" }, /* IP-Addresses */ /* deprecated */
146 { 2, "COMPPROTO" }, /* IP-Compression-Protocol */
147 { 3, "IPADDR" }, /* IP-Address */
148 { 129, "PRIDNS" }, /* 129: Primary DNS Server Address */
149 { 130, "PRINBNS" }, /* 130: Primary NBNS Server Address */
150 { 131, "SECDNS" }, /* 131: Secondary DNS Server Address */
151 { 132, "SECNBNS" } /* 132: Secondary NBNS Server Address */
153 unsigned f;
155 for (f = 0; f < sizeof cftypes / sizeof *cftypes; f++)
156 if (cftypes[f].id == proto)
157 return cftypes[f].txt;
159 return NumStr(proto, NULL, 0);
162 void
163 ipcp_AddInOctets(struct ipcp *ipcp, int n)
165 throughput_addin(&ipcp->throughput, n);
168 void
169 ipcp_AddOutOctets(struct ipcp *ipcp, int n)
171 throughput_addout(&ipcp->throughput, n);
174 void
175 ipcp_LoadDNS(struct ipcp *ipcp)
177 int fd;
179 ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr = INADDR_NONE;
181 if (ipcp->ns.resolv != NULL) {
182 free(ipcp->ns.resolv);
183 ipcp->ns.resolv = NULL;
185 if (ipcp->ns.resolv_nons != NULL) {
186 free(ipcp->ns.resolv_nons);
187 ipcp->ns.resolv_nons = NULL;
189 ipcp->ns.resolver = 0;
191 if ((fd = open(_PATH_RESCONF, O_RDONLY)) != -1) {
192 struct stat st;
194 if (fstat(fd, &st) == 0) {
195 ssize_t got;
198 * Note, ns.resolv and ns.resolv_nons are assumed to always point to
199 * buffers of the same size! See the strcpy() below.
201 if ((ipcp->ns.resolv_nons = (char *)malloc(st.st_size + 1)) == NULL)
202 log_Printf(LogERROR, "Failed to malloc %lu for %s: %s\n",
203 (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno));
204 else if ((ipcp->ns.resolv = (char *)malloc(st.st_size + 1)) == NULL) {
205 log_Printf(LogERROR, "Failed(2) to malloc %lu for %s: %s\n",
206 (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno));
207 free(ipcp->ns.resolv_nons);
208 ipcp->ns.resolv_nons = NULL;
209 } else if ((got = read(fd, ipcp->ns.resolv, st.st_size)) != st.st_size) {
210 if (got == -1)
211 log_Printf(LogERROR, "Failed to read %s: %s\n",
212 _PATH_RESCONF, strerror(errno));
213 else
214 log_Printf(LogERROR, "Failed to read %s, got %lu not %lu\n",
215 _PATH_RESCONF, (unsigned long)got,
216 (unsigned long)st.st_size);
217 free(ipcp->ns.resolv_nons);
218 ipcp->ns.resolv_nons = NULL;
219 free(ipcp->ns.resolv);
220 ipcp->ns.resolv = NULL;
221 } else {
222 char *cp, *cp_nons, *ncp, ch;
223 int n;
225 ipcp->ns.resolv[st.st_size] = '\0';
226 ipcp->ns.resolver = 1;
228 cp_nons = ipcp->ns.resolv_nons;
229 cp = ipcp->ns.resolv;
230 n = 0;
232 while ((ncp = strstr(cp, "nameserver")) != NULL) {
233 if (ncp != cp) {
234 memcpy(cp_nons, cp, ncp - cp);
235 cp_nons += ncp - cp;
237 if ((ncp != cp && ncp[-1] != '\n') || !issep(ncp[10])) {
238 memcpy(cp_nons, ncp, 9);
239 cp_nons += 9;
240 cp = ncp + 9; /* Can't match "nameserver" at cp... */
241 continue;
244 for (cp = ncp + 11; issep(*cp); cp++) /* Skip whitespace */
247 for (ncp = cp; isip(*ncp); ncp++) /* Jump over IP */
250 ch = *ncp;
251 *ncp = '\0';
252 if (n < 2 && inet_aton(cp, ipcp->ns.dns))
253 n++;
254 *ncp = ch;
256 if ((cp = strchr(ncp, '\n')) == NULL) /* Point at next line */
257 cp = ncp + strlen(ncp);
258 else
259 cp++;
262 * Note, cp_nons and cp always point to buffers of the same size, so
263 * strcpy is ok!
265 strcpy(cp_nons, cp); /* Copy the end - including the NUL */
266 cp_nons += strlen(cp_nons) - 1;
267 while (cp_nons >= ipcp->ns.resolv_nons && *cp_nons == '\n')
268 *cp_nons-- = '\0';
269 if (n == 2 && ipcp->ns.dns[0].s_addr == INADDR_ANY) {
270 ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr;
271 ipcp->ns.dns[1].s_addr = INADDR_ANY;
273 bundle_AdjustDNS(ipcp->fsm.bundle);
275 } else
276 log_Printf(LogERROR, "Failed to stat opened %s: %s\n",
277 _PATH_RESCONF, strerror(errno));
279 close(fd);
284 ipcp_WriteDNS(struct ipcp *ipcp)
286 const char *paddr;
287 mode_t mask;
288 FILE *fp;
290 if (ipcp->ns.dns[0].s_addr == INADDR_ANY &&
291 ipcp->ns.dns[1].s_addr == INADDR_ANY) {
292 log_Printf(LogIPCP, "%s not modified: All nameservers NAKd\n",
293 _PATH_RESCONF);
294 return 0;
297 if (ipcp->ns.dns[0].s_addr == INADDR_ANY) {
298 ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr;
299 ipcp->ns.dns[1].s_addr = INADDR_ANY;
302 mask = umask(022);
303 if ((fp = ID0fopen(_PATH_RESCONF, "w")) != NULL) {
304 umask(mask);
305 if (ipcp->ns.resolv_nons)
306 fputs(ipcp->ns.resolv_nons, fp);
307 paddr = inet_ntoa(ipcp->ns.dns[0]);
308 log_Printf(LogIPCP, "Primary nameserver set to %s\n", paddr);
309 fprintf(fp, "\nnameserver %s\n", paddr);
310 if (ipcp->ns.dns[1].s_addr != INADDR_ANY &&
311 ipcp->ns.dns[1].s_addr != INADDR_NONE &&
312 ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) {
313 paddr = inet_ntoa(ipcp->ns.dns[1]);
314 log_Printf(LogIPCP, "Secondary nameserver set to %s\n", paddr);
315 fprintf(fp, "nameserver %s\n", paddr);
317 if (fclose(fp) == EOF) {
318 log_Printf(LogERROR, "write(): Failed updating %s: %s\n", _PATH_RESCONF,
319 strerror(errno));
320 return 0;
322 } else
323 umask(mask);
325 return 1;
328 void
329 ipcp_RestoreDNS(struct ipcp *ipcp)
331 if (ipcp->ns.resolver) {
332 ssize_t got, len;
333 int fd;
335 if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_TRUNC, 0644)) != -1) {
336 len = strlen(ipcp->ns.resolv);
337 if ((got = write(fd, ipcp->ns.resolv, len)) != len) {
338 if (got == -1)
339 log_Printf(LogERROR, "Failed rewriting %s: write: %s\n",
340 _PATH_RESCONF, strerror(errno));
341 else
342 log_Printf(LogERROR, "Failed rewriting %s: wrote %ld of %ld\n",
343 _PATH_RESCONF, (long)got, (long)len);
345 close(fd);
346 } else
347 log_Printf(LogERROR, "Failed rewriting %s: open: %s\n", _PATH_RESCONF,
348 strerror(errno));
349 } else if (remove(_PATH_RESCONF) == -1)
350 log_Printf(LogERROR, "Failed removing %s: %s\n", _PATH_RESCONF,
351 strerror(errno));
356 ipcp_Show(struct cmdargs const *arg)
358 struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
360 prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name,
361 State2Nam(ipcp->fsm.state));
362 if (ipcp->fsm.state == ST_OPENED) {
363 prompt_Printf(arg->prompt, " His side: %s, %s\n",
364 inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto));
365 prompt_Printf(arg->prompt, " My side: %s, %s\n",
366 inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto));
367 prompt_Printf(arg->prompt, " Queued packets: %lu\n",
368 (unsigned long)ipcp_QueueLen(ipcp));
371 prompt_Printf(arg->prompt, "\nDefaults:\n");
372 prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config"
373 " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout,
374 ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s",
375 ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s");
376 prompt_Printf(arg->prompt, " My Address: %s\n",
377 ncprange_ntoa(&ipcp->cfg.my_range));
378 if (ipcp->cfg.HaveTriggerAddress)
379 prompt_Printf(arg->prompt, " Trigger address: %s\n",
380 inet_ntoa(ipcp->cfg.TriggerAddress));
382 prompt_Printf(arg->prompt, " VJ compression: %s (%d slots %s slot "
383 "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg),
384 ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without");
386 if (iplist_isvalid(&ipcp->cfg.peer_list))
387 prompt_Printf(arg->prompt, " His Address: %s\n",
388 ipcp->cfg.peer_list.src);
389 else
390 prompt_Printf(arg->prompt, " His Address: %s\n",
391 ncprange_ntoa(&ipcp->cfg.peer_range));
393 prompt_Printf(arg->prompt, " DNS: %s",
394 ipcp->cfg.ns.dns[0].s_addr == INADDR_NONE ?
395 "none" : inet_ntoa(ipcp->cfg.ns.dns[0]));
396 if (ipcp->cfg.ns.dns[1].s_addr != INADDR_NONE)
397 prompt_Printf(arg->prompt, ", %s",
398 inet_ntoa(ipcp->cfg.ns.dns[1]));
399 prompt_Printf(arg->prompt, ", %s\n",
400 command_ShowNegval(ipcp->cfg.ns.dns_neg));
401 prompt_Printf(arg->prompt, " Resolver DNS: %s",
402 ipcp->ns.dns[0].s_addr == INADDR_NONE ?
403 "none" : inet_ntoa(ipcp->ns.dns[0]));
404 if (ipcp->ns.dns[1].s_addr != INADDR_NONE &&
405 ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr)
406 prompt_Printf(arg->prompt, ", %s",
407 inet_ntoa(ipcp->ns.dns[1]));
408 prompt_Printf(arg->prompt, "\n NetBIOS NS: %s, ",
409 inet_ntoa(ipcp->cfg.ns.nbns[0]));
410 prompt_Printf(arg->prompt, "%s\n\n",
411 inet_ntoa(ipcp->cfg.ns.nbns[1]));
413 throughput_disp(&ipcp->throughput, arg->prompt);
415 return 0;
419 ipcp_vjset(struct cmdargs const *arg)
421 if (arg->argc != arg->argn+2)
422 return -1;
423 if (!strcasecmp(arg->argv[arg->argn], "slots")) {
424 int slots;
426 slots = atoi(arg->argv[arg->argn+1]);
427 if (slots < 4 || slots > 16)
428 return 1;
429 arg->bundle->ncp.ipcp.cfg.vj.slots = slots;
430 return 0;
431 } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) {
432 if (!strcasecmp(arg->argv[arg->argn+1], "on"))
433 arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1;
434 else if (!strcasecmp(arg->argv[arg->argn+1], "off"))
435 arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0;
436 else
437 return 2;
438 return 0;
440 return -1;
443 void
444 ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
445 const struct fsm_parent *parent)
447 struct hostent *hp;
448 struct in_addr host;
449 char name[MAXHOSTNAMELEN];
450 static const char * const timer_names[] =
451 {"IPCP restart", "IPCP openmode", "IPCP stopped"};
453 fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP,
454 bundle, l, parent, &ipcp_Callbacks, timer_names);
456 ipcp->cfg.vj.slots = DEF_VJ_STATES;
457 ipcp->cfg.vj.slotcomp = 1;
458 memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range);
460 host.s_addr = htonl(INADDR_LOOPBACK);
461 ipcp->cfg.netmask.s_addr = INADDR_ANY;
462 if (gethostname(name, sizeof name) == 0) {
463 hp = gethostbyname(name);
464 if (hp && hp->h_addrtype == AF_INET && hp->h_length == sizeof host.s_addr)
465 memcpy(&host.s_addr, hp->h_addr, sizeof host.s_addr);
467 ncprange_setip4(&ipcp->cfg.my_range, host, ipcp->cfg.netmask);
468 ncprange_setip4(&ipcp->cfg.peer_range, ipcp->cfg.netmask, ipcp->cfg.netmask);
470 iplist_setsrc(&ipcp->cfg.peer_list, "");
471 ipcp->cfg.HaveTriggerAddress = 0;
473 ipcp->cfg.ns.dns[0].s_addr = INADDR_NONE;
474 ipcp->cfg.ns.dns[1].s_addr = INADDR_NONE;
475 ipcp->cfg.ns.dns_neg = 0;
476 ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY;
477 ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY;
479 ipcp->cfg.fsm.timeout = DEF_FSMRETRY;
480 ipcp->cfg.fsm.maxreq = DEF_FSMTRIES;
481 ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES;
482 ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED;
484 memset(&ipcp->vj, '\0', sizeof ipcp->vj);
486 ipcp->ns.resolv = NULL;
487 ipcp->ns.resolv_nons = NULL;
488 ipcp->ns.writable = 1;
489 ipcp_LoadDNS(ipcp);
491 throughput_init(&ipcp->throughput, SAMPLE_PERIOD);
492 memset(ipcp->Queue, '\0', sizeof ipcp->Queue);
493 ipcp_Setup(ipcp, INADDR_NONE);
496 void
497 ipcp_Destroy(struct ipcp *ipcp)
499 throughput_destroy(&ipcp->throughput);
501 if (ipcp->ns.resolv != NULL) {
502 free(ipcp->ns.resolv);
503 ipcp->ns.resolv = NULL;
505 if (ipcp->ns.resolv_nons != NULL) {
506 free(ipcp->ns.resolv_nons);
507 ipcp->ns.resolv_nons = NULL;
511 void
512 ipcp_SetLink(struct ipcp *ipcp, struct link *l)
514 ipcp->fsm.link = l;
517 void
518 ipcp_Setup(struct ipcp *ipcp, u_int32_t mask)
520 struct iface *iface = ipcp->fsm.bundle->iface;
521 struct ncpaddr ipaddr;
522 struct in_addr peer;
523 int pos;
524 unsigned n;
526 ipcp->fsm.open_mode = 0;
527 ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask;
529 if (iplist_isvalid(&ipcp->cfg.peer_list)) {
530 /* Try to give the peer a previously configured IP address */
531 for (n = 0; n < iface->addrs; n++) {
532 if (!ncpaddr_getip4(&iface->addr[n].peer, &peer))
533 continue;
534 if ((pos = iplist_ip2pos(&ipcp->cfg.peer_list, peer)) != -1) {
535 ncpaddr_setip4(&ipaddr, iplist_setcurpos(&ipcp->cfg.peer_list, pos));
536 break;
539 if (n == iface->addrs)
540 /* Ok, so none of 'em fit.... pick a random one */
541 ncpaddr_setip4(&ipaddr, iplist_setrandpos(&ipcp->cfg.peer_list));
543 ncprange_sethost(&ipcp->cfg.peer_range, &ipaddr);
546 ipcp->heis1172 = 0;
547 ipcp->peer_req = 0;
548 ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip);
549 ipcp->peer_compproto = 0;
551 if (ipcp->cfg.HaveTriggerAddress) {
553 * Some implementations of PPP require that we send a
554 * *special* value as our address, even though the rfc specifies
555 * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0").
557 ipcp->my_ip = ipcp->cfg.TriggerAddress;
558 log_Printf(LogIPCP, "Using trigger address %s\n",
559 inet_ntoa(ipcp->cfg.TriggerAddress));
560 } else {
562 * Otherwise, if we've used an IP number before and it's still within
563 * the network specified on the ``set ifaddr'' line, we really
564 * want to keep that IP number so that we can keep any existing
565 * connections that are bound to that IP.
567 for (n = 0; n < iface->addrs; n++) {
568 ncprange_getaddr(&iface->addr[n].ifa, &ipaddr);
569 if (ncprange_contains(&ipcp->cfg.my_range, &ipaddr)) {
570 ncpaddr_getip4(&ipaddr, &ipcp->my_ip);
571 break;
574 if (n == iface->addrs)
575 ncprange_getip4addr(&ipcp->cfg.my_range, &ipcp->my_ip);
578 if (IsEnabled(ipcp->cfg.vj.neg)
579 #ifndef NORADIUS
580 || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj)
581 #endif
583 ipcp->my_compproto = (PROTO_VJCOMP << 16) +
584 ((ipcp->cfg.vj.slots - 1) << 8) +
585 ipcp->cfg.vj.slotcomp;
586 else
587 ipcp->my_compproto = 0;
588 sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1);
590 ipcp->peer_reject = 0;
591 ipcp->my_reject = 0;
593 /* Copy startup values into ipcp->ns.dns */
594 if (ipcp->cfg.ns.dns[0].s_addr != INADDR_NONE)
595 memcpy(ipcp->ns.dns, ipcp->cfg.ns.dns, sizeof ipcp->ns.dns);
598 static int
599 numaddresses(struct in_addr mask)
601 u_int32_t bit, haddr;
602 int n;
604 haddr = ntohl(mask.s_addr);
605 bit = 1;
606 n = 1;
608 do {
609 if (!(haddr & bit))
610 n <<= 1;
611 } while (bit <<= 1);
613 return n;
616 static int
617 ipcp_proxyarp(struct ipcp *ipcp,
618 int (*proxyfun)(struct bundle *, struct in_addr),
619 const struct iface_addr *addr)
621 struct bundle *bundle = ipcp->fsm.bundle;
622 struct in_addr peer, mask, ip;
623 int n, ret;
625 if (!ncpaddr_getip4(&addr->peer, &peer)) {
626 log_Printf(LogERROR, "Oops, ipcp_proxyarp() called with unexpected addr\n");
627 return 0;
630 ret = 0;
632 if (Enabled(bundle, OPT_PROXYALL)) {
633 ncprange_getip4mask(&addr->ifa, &mask);
634 if ((n = numaddresses(mask)) > 256) {
635 log_Printf(LogWARN, "%s: Too many addresses for proxyall\n",
636 ncprange_ntoa(&addr->ifa));
637 return 0;
639 ip.s_addr = peer.s_addr & mask.s_addr;
640 if (n >= 4) {
641 ip.s_addr = htonl(ntohl(ip.s_addr) + 1);
642 n -= 2;
644 while (n) {
645 if (!((ip.s_addr ^ peer.s_addr) & mask.s_addr)) {
646 if (!(ret = (*proxyfun)(bundle, ip)))
647 break;
648 n--;
650 ip.s_addr = htonl(ntohl(ip.s_addr) + 1);
652 ret = !n;
653 } else if (Enabled(bundle, OPT_PROXY))
654 ret = (*proxyfun)(bundle, peer);
656 return ret;
659 static int
660 ipcp_SetIPaddress(struct ipcp *ipcp, struct in_addr myaddr,
661 struct in_addr hisaddr)
663 struct bundle *bundle = ipcp->fsm.bundle;
664 struct ncpaddr myncpaddr, hisncpaddr;
665 struct ncprange myrange;
666 struct in_addr mask;
667 struct sockaddr_storage ssdst, ssgw, ssmask;
668 struct sockaddr *sadst, *sagw, *samask;
670 sadst = (struct sockaddr *)&ssdst;
671 sagw = (struct sockaddr *)&ssgw;
672 samask = (struct sockaddr *)&ssmask;
674 ncpaddr_setip4(&hisncpaddr, hisaddr);
675 ncpaddr_setip4(&myncpaddr, myaddr);
676 ncprange_sethost(&myrange, &myncpaddr);
678 mask = addr2mask(myaddr);
680 if (ipcp->ifmask.s_addr != INADDR_ANY &&
681 (ipcp->ifmask.s_addr & mask.s_addr) == mask.s_addr)
682 ncprange_setip4mask(&myrange, ipcp->ifmask);
684 if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &hisncpaddr,
685 IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM))
686 return 0;
688 if (!Enabled(bundle, OPT_IFACEALIAS))
689 iface_Clear(bundle->iface, &bundle->ncp, AF_INET,
690 IFACE_CLEAR_ALIASES|IFACE_SYSTEM);
692 if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) {
693 ncprange_getsa(&myrange, &ssgw, &ssmask);
694 ncpaddr_getsa(&hisncpaddr, &ssdst);
695 rt_Update(bundle, sadst, sagw, samask);
698 if (Enabled(bundle, OPT_SROUTES))
699 route_Change(bundle, bundle->ncp.route, &myncpaddr, &hisncpaddr);
701 #ifndef NORADIUS
702 if (bundle->radius.valid)
703 route_Change(bundle, bundle->radius.routes, &myncpaddr, &hisncpaddr);
704 #endif
706 return 1; /* Ok */
709 static struct in_addr
710 ChooseHisAddr(struct bundle *bundle, struct in_addr gw)
712 struct in_addr try;
713 u_long f;
715 for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) {
716 try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list);
717 log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n",
718 f, inet_ntoa(try));
719 if (ipcp_SetIPaddress(&bundle->ncp.ipcp, gw, try)) {
720 log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try));
721 break;
725 if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) {
726 log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n");
727 try.s_addr = INADDR_ANY;
730 return try;
733 static void
734 IpcpInitRestartCounter(struct fsm *fp, int what)
736 /* Set fsm timer load */
737 struct ipcp *ipcp = fsm2ipcp(fp);
739 fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS;
740 switch (what) {
741 case FSM_REQ_TIMER:
742 fp->restart = ipcp->cfg.fsm.maxreq;
743 break;
744 case FSM_TRM_TIMER:
745 fp->restart = ipcp->cfg.fsm.maxtrm;
746 break;
747 default:
748 fp->restart = 1;
749 break;
753 static void
754 IpcpSendConfigReq(struct fsm *fp)
756 /* Send config REQ please */
757 struct physical *p = link2physical(fp->link);
758 struct ipcp *ipcp = fsm2ipcp(fp);
759 u_char buff[MAX_FSM_OPT_LEN];
760 struct fsm_opt *o;
762 o = (struct fsm_opt *)buff;
764 if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) {
765 memcpy(o->data, &ipcp->my_ip.s_addr, 4);
766 INC_FSM_OPT(TY_IPADDR, 6, o);
769 if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) {
770 if (ipcp->heis1172) {
771 u_int16_t proto = PROTO_VJCOMP;
773 ua_htons(&proto, o->data);
774 INC_FSM_OPT(TY_COMPPROTO, 4, o);
775 } else {
776 struct compreq req;
778 req.proto = htons(ipcp->my_compproto >> 16);
779 req.slots = (ipcp->my_compproto >> 8) & 255;
780 req.compcid = ipcp->my_compproto & 1;
781 memcpy(o->data, &req, 4);
782 INC_FSM_OPT(TY_COMPPROTO, 6, o);
786 if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
787 if (!REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS)) {
788 memcpy(o->data, &ipcp->ns.dns[0].s_addr, 4);
789 INC_FSM_OPT(TY_PRIMARY_DNS, 6, o);
792 if (!REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) {
793 memcpy(o->data, &ipcp->ns.dns[1].s_addr, 4);
794 INC_FSM_OPT(TY_SECONDARY_DNS, 6, o);
798 fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
799 MB_IPCPOUT);
802 static void
803 IpcpSentTerminateReq(struct fsm *fp __unused)
805 /* Term REQ just sent by FSM */
808 static void
809 IpcpSendTerminateAck(struct fsm *fp, u_char id)
811 /* Send Term ACK please */
812 fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT);
815 static void
816 IpcpLayerStart(struct fsm *fp)
818 /* We're about to start up ! */
819 struct ipcp *ipcp = fsm2ipcp(fp);
821 log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name);
822 throughput_start(&ipcp->throughput, "IPCP throughput",
823 Enabled(fp->bundle, OPT_THROUGHPUT));
824 fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3;
825 ipcp->peer_req = 0;
828 static void
829 IpcpLayerFinish(struct fsm *fp)
831 /* We're now down */
832 struct ipcp *ipcp = fsm2ipcp(fp);
834 log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name);
835 throughput_stop(&ipcp->throughput);
836 throughput_log(&ipcp->throughput, LogIPCP, NULL);
840 * Called from iface_Add() via ncp_IfaceAddrAdded()
842 void
843 ipcp_IfaceAddrAdded(struct ipcp *ipcp, const struct iface_addr *addr)
845 struct bundle *bundle = ipcp->fsm.bundle;
847 if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL))
848 ipcp_proxyarp(ipcp, arp_SetProxy, addr);
852 * Called from iface_Clear() and iface_Delete() via ncp_IfaceAddrDeleted()
854 void
855 ipcp_IfaceAddrDeleted(struct ipcp *ipcp, const struct iface_addr *addr)
857 struct bundle *bundle = ipcp->fsm.bundle;
859 if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL))
860 ipcp_proxyarp(ipcp, arp_ClearProxy, addr);
863 static void
864 IpcpLayerDown(struct fsm *fp)
866 /* About to come down */
867 struct ipcp *ipcp = fsm2ipcp(fp);
868 static int recursing;
869 char addr[16];
871 if (!recursing++) {
872 snprintf(addr, sizeof addr, "%s", inet_ntoa(ipcp->my_ip));
873 log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, addr);
875 #ifndef NORADIUS
876 radius_Flush(&fp->bundle->radius);
877 radius_Account(&fp->bundle->radius, &fp->bundle->radacct,
878 fp->bundle->links, RAD_STOP, &ipcp->throughput);
880 if (fp->bundle->radius.cfg.file && fp->bundle->radius.filterid)
881 system_Select(fp->bundle, fp->bundle->radius.filterid, LINKDOWNFILE,
882 NULL, NULL);
883 radius_StopTimer(&fp->bundle->radius);
884 #endif
887 * XXX this stuff should really live in the FSM. Our config should
888 * associate executable sections in files with events.
890 if (system_Select(fp->bundle, addr, LINKDOWNFILE, NULL, NULL) < 0) {
891 if (bundle_GetLabel(fp->bundle)) {
892 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
893 LINKDOWNFILE, NULL, NULL) < 0)
894 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
895 } else
896 system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL);
899 ipcp_Setup(ipcp, INADDR_NONE);
901 recursing--;
905 ipcp_InterfaceUp(struct ipcp *ipcp)
907 if (!ipcp_SetIPaddress(ipcp, ipcp->my_ip, ipcp->peer_ip)) {
908 log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n");
909 return 0;
912 if (!iface_SetFlags(ipcp->fsm.bundle->iface->name, IFF_UP)) {
913 log_Printf(LogERROR, "ipcp_InterfaceUp: Can't set the IFF_UP flag on %s\n",
914 ipcp->fsm.bundle->iface->name);
915 return 0;
918 #ifndef NONAT
919 if (ipcp->fsm.bundle->NatEnabled)
920 LibAliasSetAddress(la, ipcp->my_ip);
921 #endif
923 return 1;
926 static int
927 IpcpLayerUp(struct fsm *fp)
929 /* We're now up */
930 struct ipcp *ipcp = fsm2ipcp(fp);
931 char tbuff[16];
933 log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name);
934 snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip));
935 log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n",
936 tbuff, inet_ntoa(ipcp->peer_ip));
938 if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP)
939 sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255);
941 if (!ipcp_InterfaceUp(ipcp))
942 return 0;
944 #ifndef NORADIUS
945 radius_Account_Set_Ip(&fp->bundle->radacct, &ipcp->peer_ip, &ipcp->ifmask);
946 radius_Account(&fp->bundle->radius, &fp->bundle->radacct, fp->bundle->links,
947 RAD_START, &ipcp->throughput);
949 if (fp->bundle->radius.cfg.file && fp->bundle->radius.filterid)
950 system_Select(fp->bundle, fp->bundle->radius.filterid, LINKUPFILE,
951 NULL, NULL);
952 radius_StartTimer(fp->bundle);
953 #endif
956 * XXX this stuff should really live in the FSM. Our config should
957 * associate executable sections in files with events.
959 if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) {
960 if (bundle_GetLabel(fp->bundle)) {
961 if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
962 LINKUPFILE, NULL, NULL) < 0)
963 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
964 } else
965 system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL);
968 fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3;
969 log_DisplayPrompts();
971 return 1;
974 static void
975 ipcp_ValidateReq(struct ipcp *ipcp, struct in_addr ip, struct fsm_decode *dec)
977 struct bundle *bundle = ipcp->fsm.bundle;
978 struct iface *iface = bundle->iface;
979 struct in_addr myaddr, peer;
980 unsigned n;
982 if (iplist_isvalid(&ipcp->cfg.peer_list)) {
983 ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr);
984 if (ip.s_addr == INADDR_ANY ||
985 iplist_ip2pos(&ipcp->cfg.peer_list, ip) < 0 ||
986 !ipcp_SetIPaddress(ipcp, myaddr, ip)) {
987 log_Printf(LogIPCP, "%s: Address invalid or already in use\n",
988 inet_ntoa(ip));
990 * If we've already had a valid address configured for the peer,
991 * try NAKing with that so that we don't have to upset things
992 * too much.
994 for (n = 0; n < iface->addrs; n++) {
995 if (!ncpaddr_getip4(&iface->addr[n].peer, &peer))
996 continue;
997 if (iplist_ip2pos(&ipcp->cfg.peer_list, peer) >= 0) {
998 ipcp->peer_ip = peer;
999 break;
1003 if (n == iface->addrs) {
1004 /* Just pick an IP number from our list */
1005 ipcp->peer_ip = ChooseHisAddr(bundle, myaddr);
1008 if (ipcp->peer_ip.s_addr == INADDR_ANY) {
1009 *dec->rejend++ = TY_IPADDR;
1010 *dec->rejend++ = 6;
1011 memcpy(dec->rejend, &ip.s_addr, 4);
1012 dec->rejend += 4;
1013 } else {
1014 *dec->nakend++ = TY_IPADDR;
1015 *dec->nakend++ = 6;
1016 memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4);
1017 dec->nakend += 4;
1019 return;
1021 } else if (ip.s_addr == INADDR_ANY ||
1022 !ncprange_containsip4(&ipcp->cfg.peer_range, ip)) {
1024 * If the destination address is not acceptable, NAK with what we
1025 * want to use.
1027 *dec->nakend++ = TY_IPADDR;
1028 *dec->nakend++ = 6;
1029 for (n = 0; n < iface->addrs; n++)
1030 if (ncprange_contains(&ipcp->cfg.peer_range, &iface->addr[n].peer)) {
1031 /* We prefer the already-configured address */
1032 ncpaddr_getip4addr(&iface->addr[n].peer, (u_int32_t *)dec->nakend);
1033 break;
1036 if (n == iface->addrs)
1037 memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4);
1039 dec->nakend += 4;
1040 return;
1043 ipcp->peer_ip = ip;
1044 *dec->ackend++ = TY_IPADDR;
1045 *dec->ackend++ = 6;
1046 memcpy(dec->ackend, &ip.s_addr, 4);
1047 dec->ackend += 4;
1050 static void
1051 IpcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type,
1052 struct fsm_decode *dec)
1054 /* Deal with incoming PROTO_IPCP */
1055 struct ncpaddr ncpaddr;
1056 struct ipcp *ipcp = fsm2ipcp(fp);
1057 int gotdnsnak;
1058 u_int32_t compproto;
1059 struct compreq pcomp;
1060 struct in_addr ipaddr, dstipaddr, have_ip;
1061 char tbuff[100], tbuff2[100];
1062 struct fsm_opt *opt, nak;
1064 gotdnsnak = 0;
1066 while (end - cp >= (int)sizeof(opt->hdr)) {
1067 if ((opt = fsm_readopt(&cp)) == NULL)
1068 break;
1070 snprintf(tbuff, sizeof tbuff, " %s[%d]", protoname(opt->hdr.id),
1071 opt->hdr.len);
1073 switch (opt->hdr.id) {
1074 case TY_IPADDR: /* RFC1332 */
1075 memcpy(&ipaddr.s_addr, opt->data, 4);
1076 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
1078 switch (mode_type) {
1079 case MODE_REQ:
1080 ipcp->peer_req = 1;
1081 ipcp_ValidateReq(ipcp, ipaddr, dec);
1082 break;
1084 case MODE_NAK:
1085 if (ncprange_containsip4(&ipcp->cfg.my_range, ipaddr)) {
1086 /* Use address suggested by peer */
1087 snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
1088 inet_ntoa(ipcp->my_ip));
1089 log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
1090 ipcp->my_ip = ipaddr;
1091 ncpaddr_setip4(&ncpaddr, ipcp->my_ip);
1092 bundle_AdjustFilters(fp->bundle, &ncpaddr, NULL);
1093 } else {
1094 log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE,
1095 "%s: Unacceptable address!\n", inet_ntoa(ipaddr));
1096 fsm_Close(&ipcp->fsm);
1098 break;
1100 case MODE_REJ:
1101 ipcp->peer_reject |= (1 << opt->hdr.id);
1102 break;
1104 break;
1106 case TY_COMPPROTO:
1107 memcpy(&pcomp, opt->data, sizeof pcomp);
1108 compproto = (ntohs(pcomp.proto) << 16) + ((int)pcomp.slots << 8) +
1109 pcomp.compcid;
1110 log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto));
1112 switch (mode_type) {
1113 case MODE_REQ:
1114 if (!IsAccepted(ipcp->cfg.vj.neg))
1115 fsm_rej(dec, opt);
1116 else {
1117 switch (opt->hdr.len) {
1118 case 4: /* RFC1172 */
1119 if (ntohs(pcomp.proto) == PROTO_VJCOMP) {
1120 log_Printf(LogWARN, "Peer is speaking RFC1172 compression "
1121 "protocol !\n");
1122 ipcp->heis1172 = 1;
1123 ipcp->peer_compproto = compproto;
1124 fsm_ack(dec, opt);
1125 } else {
1126 pcomp.proto = htons(PROTO_VJCOMP);
1127 nak.hdr.id = TY_COMPPROTO;
1128 nak.hdr.len = 4;
1129 memcpy(nak.data, &pcomp, 2);
1130 fsm_nak(dec, &nak);
1132 break;
1133 case 6: /* RFC1332 */
1134 if (ntohs(pcomp.proto) == PROTO_VJCOMP) {
1135 /* We know pcomp.slots' max value == MAX_VJ_STATES */
1136 if (pcomp.slots >= MIN_VJ_STATES) {
1137 /* Ok, we can do that */
1138 ipcp->peer_compproto = compproto;
1139 ipcp->heis1172 = 0;
1140 fsm_ack(dec, opt);
1141 } else {
1142 /* Get as close as we can to what he wants */
1143 ipcp->heis1172 = 0;
1144 pcomp.slots = MIN_VJ_STATES;
1145 nak.hdr.id = TY_COMPPROTO;
1146 nak.hdr.len = 4;
1147 memcpy(nak.data, &pcomp, 2);
1148 fsm_nak(dec, &nak);
1150 } else {
1151 /* What we really want */
1152 pcomp.proto = htons(PROTO_VJCOMP);
1153 pcomp.slots = DEF_VJ_STATES;
1154 pcomp.compcid = 1;
1155 nak.hdr.id = TY_COMPPROTO;
1156 nak.hdr.len = 6;
1157 memcpy(nak.data, &pcomp, sizeof pcomp);
1158 fsm_nak(dec, &nak);
1160 break;
1161 default:
1162 fsm_rej(dec, opt);
1163 break;
1166 break;
1168 case MODE_NAK:
1169 if (ntohs(pcomp.proto) == PROTO_VJCOMP) {
1170 /* We know pcomp.slots' max value == MAX_VJ_STATES */
1171 if (pcomp.slots < MIN_VJ_STATES)
1172 pcomp.slots = MIN_VJ_STATES;
1173 compproto = (ntohs(pcomp.proto) << 16) + (pcomp.slots << 8) +
1174 pcomp.compcid;
1175 } else
1176 compproto = 0;
1177 log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n",
1178 tbuff, ipcp->my_compproto, compproto);
1179 ipcp->my_compproto = compproto;
1180 break;
1182 case MODE_REJ:
1183 ipcp->peer_reject |= (1 << opt->hdr.id);
1184 break;
1186 break;
1188 case TY_IPADDRS: /* RFC1172 */
1189 memcpy(&ipaddr.s_addr, opt->data, 4);
1190 memcpy(&dstipaddr.s_addr, opt->data + 4, 4);
1191 snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr));
1192 log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr));
1194 switch (mode_type) {
1195 case MODE_REQ:
1196 fsm_rej(dec, opt);
1197 break;
1199 case MODE_NAK:
1200 case MODE_REJ:
1201 break;
1203 break;
1205 case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */
1206 case TY_SECONDARY_DNS:
1207 memcpy(&ipaddr.s_addr, opt->data, 4);
1208 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
1210 switch (mode_type) {
1211 case MODE_REQ:
1212 if (!IsAccepted(ipcp->cfg.ns.dns_neg)) {
1213 ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS));
1214 fsm_rej(dec, opt);
1215 break;
1217 have_ip = ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1];
1219 if (opt->hdr.id == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr &&
1220 ipaddr.s_addr == ipcp->ns.dns[1].s_addr) {
1221 /* Swap 'em 'round */
1222 ipcp->ns.dns[0] = ipcp->ns.dns[1];
1223 ipcp->ns.dns[1] = have_ip;
1224 have_ip = ipcp->ns.dns[0];
1227 if (ipaddr.s_addr != have_ip.s_addr) {
1229 * The client has got the DNS stuff wrong (first request) so
1230 * we'll tell 'em how it is
1232 nak.hdr.id = opt->hdr.id;
1233 nak.hdr.len = 6;
1234 memcpy(nak.data, &have_ip.s_addr, 4);
1235 fsm_nak(dec, &nak);
1236 } else {
1238 * Otherwise they have it right (this time) so we send an ack packet
1239 * back confirming it... end of story
1241 fsm_ack(dec, opt);
1243 break;
1245 case MODE_NAK:
1246 if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
1247 gotdnsnak = 1;
1248 memcpy(&ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1].s_addr,
1249 opt->data, 4);
1251 break;
1253 case MODE_REJ: /* Can't do much, stop asking */
1254 ipcp->peer_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS));
1255 break;
1257 break;
1259 case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */
1260 case TY_SECONDARY_NBNS:
1261 memcpy(&ipaddr.s_addr, opt->data, 4);
1262 log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr));
1264 switch (mode_type) {
1265 case MODE_REQ:
1266 have_ip.s_addr =
1267 ipcp->cfg.ns.nbns[opt->hdr.id == TY_PRIMARY_NBNS ? 0 : 1].s_addr;
1269 if (have_ip.s_addr == INADDR_ANY) {
1270 log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n");
1271 ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS));
1272 fsm_rej(dec, opt);
1273 break;
1276 if (ipaddr.s_addr != have_ip.s_addr) {
1277 nak.hdr.id = opt->hdr.id;
1278 nak.hdr.len = 6;
1279 memcpy(nak.data, &have_ip.s_addr, 4);
1280 fsm_nak(dec, &nak);
1281 } else
1282 fsm_ack(dec, opt);
1283 break;
1285 case MODE_NAK:
1286 log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", opt->hdr.id);
1287 break;
1289 case MODE_REJ:
1290 log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", opt->hdr.id);
1291 break;
1293 break;
1295 default:
1296 if (mode_type != MODE_NOP) {
1297 ipcp->my_reject |= (1 << opt->hdr.id);
1298 fsm_rej(dec, opt);
1300 break;
1304 if (gotdnsnak) {
1305 if (ipcp->ns.writable) {
1306 log_Printf(LogDEBUG, "Updating resolver\n");
1307 if (!ipcp_WriteDNS(ipcp)) {
1308 ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS));
1309 ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS));
1310 } else
1311 bundle_AdjustDNS(fp->bundle);
1312 } else {
1313 log_Printf(LogDEBUG, "Not updating resolver (readonly)\n");
1314 bundle_AdjustDNS(fp->bundle);
1318 if (mode_type != MODE_NOP) {
1319 if (mode_type == MODE_REQ && !ipcp->peer_req) {
1320 if (dec->rejend == dec->rej && dec->nakend == dec->nak) {
1322 * Pretend the peer has requested an IP.
1323 * We do this to ensure that we only send one NAK if the only
1324 * reason for the NAK is because the peer isn't sending a
1325 * TY_IPADDR REQ. This stops us from repeatedly trying to tell
1326 * the peer that we have to have an IP address on their end.
1328 ipcp->peer_req = 1;
1330 ipaddr.s_addr = INADDR_ANY;
1331 ipcp_ValidateReq(ipcp, ipaddr, dec);
1333 fsm_opt_normalise(dec);
1337 extern struct mbuf *
1338 ipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
1340 /* Got PROTO_IPCP from link */
1341 m_settype(bp, MB_IPCPIN);
1342 if (bundle_Phase(bundle) == PHASE_NETWORK)
1343 fsm_Input(&bundle->ncp.ipcp.fsm, bp);
1344 else {
1345 if (bundle_Phase(bundle) < PHASE_NETWORK)
1346 log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n",
1347 l->name, bundle_PhaseName(bundle));
1348 m_freem(bp);
1350 return NULL;
1354 ipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr)
1356 struct ipcp *ipcp = &bundle->ncp.ipcp;
1357 struct in_addr myaddr;
1359 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
1360 iplist_reset(&ipcp->cfg.peer_list);
1361 ipcp->peer_ip = hisaddr;
1362 ncprange_setip4host(&ipcp->cfg.peer_range, hisaddr);
1363 ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr);
1365 return ipcp_SetIPaddress(ipcp, myaddr, hisaddr);
1369 ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr)
1371 struct in_addr myaddr;
1372 struct ncp *ncp = &bundle->ncp;
1373 struct ipcp *ipcp = &ncp->ipcp;
1374 struct ncpaddr ncpaddr;
1376 /* Use `hisaddr' for the peers address (set iface if `setaddr') */
1377 memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
1378 iplist_reset(&ipcp->cfg.peer_list);
1379 if (strpbrk(hisaddr, ",-")) {
1380 iplist_setsrc(&ipcp->cfg.peer_list, hisaddr);
1381 if (iplist_isvalid(&ipcp->cfg.peer_list)) {
1382 iplist_setrandpos(&ipcp->cfg.peer_list);
1383 ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip);
1384 if (ipcp->peer_ip.s_addr == INADDR_ANY) {
1385 log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src);
1386 return 0;
1388 ncprange_setip4host(&ipcp->cfg.peer_range, ipcp->peer_ip);
1389 } else {
1390 log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr);
1391 return 0;
1393 } else if (ncprange_aton(&ipcp->cfg.peer_range, ncp, hisaddr) != 0) {
1394 if (ncprange_family(&ipcp->cfg.my_range) != AF_INET) {
1395 log_Printf(LogWARN, "%s: Not an AF_INET address !\n", hisaddr);
1396 return 0;
1398 ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr);
1399 ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip);
1401 if (setaddr && !ipcp_SetIPaddress(ipcp, myaddr, ipcp->peer_ip))
1402 return 0;
1403 } else
1404 return 0;
1406 ncpaddr_setip4(&ncpaddr, ipcp->peer_ip);
1407 bundle_AdjustFilters(bundle, NULL, &ncpaddr);
1409 return 1; /* Ok */
1412 struct in_addr
1413 addr2mask(struct in_addr addr)
1415 u_int32_t haddr = ntohl(addr.s_addr);
1417 haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET :
1418 IN_CLASSB(haddr) ? IN_CLASSB_NET :
1419 IN_CLASSC_NET;
1420 addr.s_addr = htonl(haddr);
1422 return addr;
1425 size_t
1426 ipcp_QueueLen(struct ipcp *ipcp)
1428 struct mqueue *q;
1429 size_t result;
1431 result = 0;
1432 for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++)
1433 result += q->len;
1435 return result;
1439 ipcp_PushPacket(struct ipcp *ipcp, struct link *l)
1441 struct bundle *bundle = ipcp->fsm.bundle;
1442 struct mqueue *queue;
1443 struct mbuf *bp;
1444 int m_len;
1445 u_int32_t secs = 0;
1446 unsigned alivesecs = 0;
1448 if (ipcp->fsm.state != ST_OPENED)
1449 return 0;
1452 * If ccp is not open but is required, do nothing.
1454 if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) {
1455 log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name);
1456 return 0;
1459 queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1;
1460 do {
1461 if (queue->top) {
1462 bp = m_dequeue(queue);
1463 bp = mbuf_Read(bp, &secs, sizeof secs);
1464 bp = m_pullup(bp);
1465 m_len = m_length(bp);
1466 if (!FilterCheck(MBUF_CTOP(bp), AF_INET, &bundle->filter.alive,
1467 &alivesecs)) {
1468 if (secs == 0)
1469 secs = alivesecs;
1470 bundle_StartIdleTimer(bundle, secs);
1472 link_PushPacket(l, bp, bundle, 0, PROTO_IP);
1473 ipcp_AddOutOctets(ipcp, m_len);
1474 return 1;
1476 } while (queue-- != ipcp->Queue);
1478 return 0;