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)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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>
38 #include <net/route.h>
70 #include "throughput.h"
71 #include "slcompress.h"
79 #include "descriptor.h"
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) == '.')
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
= {
128 IpcpInitRestartCounter
,
130 IpcpSentTerminateReq
,
131 IpcpSendTerminateAck
,
133 fsm_NullRecvResetReq
,
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 */
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);
163 ipcp_AddInOctets(struct ipcp
*ipcp
, int n
)
165 throughput_addin(&ipcp
->throughput
, n
);
169 ipcp_AddOutOctets(struct ipcp
*ipcp
, int n
)
171 throughput_addout(&ipcp
->throughput
, n
);
175 ipcp_LoadDNS(struct ipcp
*ipcp
)
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) {
194 if (fstat(fd
, &st
) == 0) {
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
) {
211 log_Printf(LogERROR
, "Failed to read %s: %s\n",
212 _PATH_RESCONF
, strerror(errno
));
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
;
222 char *cp
, *cp_nons
, *ncp
, ch
;
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
;
232 while ((ncp
= strstr(cp
, "nameserver")) != NULL
) {
234 memcpy(cp_nons
, cp
, ncp
- cp
);
237 if ((ncp
!= cp
&& ncp
[-1] != '\n') || !issep(ncp
[10])) {
238 memcpy(cp_nons
, ncp
, 9);
240 cp
= ncp
+ 9; /* Can't match "nameserver" at cp... */
244 for (cp
= ncp
+ 11; issep(*cp
); cp
++) /* Skip whitespace */
247 for (ncp
= cp
; isip(*ncp
); ncp
++) /* Jump over IP */
252 if (n
< 2 && inet_aton(cp
, ipcp
->ns
.dns
))
256 if ((cp
= strchr(ncp
, '\n')) == NULL
) /* Point at next line */
257 cp
= ncp
+ strlen(ncp
);
262 * Note, cp_nons and cp always point to buffers of the same size, so
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')
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
);
276 log_Printf(LogERROR
, "Failed to stat opened %s: %s\n",
277 _PATH_RESCONF
, strerror(errno
));
284 ipcp_WriteDNS(struct ipcp
*ipcp
)
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",
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
;
303 if ((fp
= ID0fopen(_PATH_RESCONF
, "w")) != NULL
) {
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
,
329 ipcp_RestoreDNS(struct ipcp
*ipcp
)
331 if (ipcp
->ns
.resolver
) {
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
) {
339 log_Printf(LogERROR
, "Failed rewriting %s: write: %s\n",
340 _PATH_RESCONF
, strerror(errno
));
342 log_Printf(LogERROR
, "Failed rewriting %s: wrote %ld of %ld\n",
343 _PATH_RESCONF
, (long)got
, (long)len
);
347 log_Printf(LogERROR
, "Failed rewriting %s: open: %s\n", _PATH_RESCONF
,
349 } else if (remove(_PATH_RESCONF
) == -1)
350 log_Printf(LogERROR
, "Failed removing %s: %s\n", _PATH_RESCONF
,
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
);
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
);
419 ipcp_vjset(struct cmdargs
const *arg
)
421 if (arg
->argc
!= arg
->argn
+2)
423 if (!strcasecmp(arg
->argv
[arg
->argn
], "slots")) {
426 slots
= atoi(arg
->argv
[arg
->argn
+1]);
427 if (slots
< 4 || slots
> 16)
429 arg
->bundle
->ncp
.ipcp
.cfg
.vj
.slots
= slots
;
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;
444 ipcp_Init(struct ipcp
*ipcp
, struct bundle
*bundle
, struct link
*l
,
445 const struct fsm_parent
*parent
)
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;
491 throughput_init(&ipcp
->throughput
, SAMPLE_PERIOD
);
492 memset(ipcp
->Queue
, '\0', sizeof ipcp
->Queue
);
493 ipcp_Setup(ipcp
, INADDR_NONE
);
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
;
512 ipcp_SetLink(struct ipcp
*ipcp
, struct link
*l
)
518 ipcp_Setup(struct ipcp
*ipcp
, u_int32_t mask
)
520 struct iface
*iface
= ipcp
->fsm
.bundle
->iface
;
521 struct ncpaddr ipaddr
;
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
))
534 if ((pos
= iplist_ip2pos(&ipcp
->cfg
.peer_list
, peer
)) != -1) {
535 ncpaddr_setip4(&ipaddr
, iplist_setcurpos(&ipcp
->cfg
.peer_list
, pos
));
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
);
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
));
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
);
574 if (n
== iface
->addrs
)
575 ncprange_getip4addr(&ipcp
->cfg
.my_range
, &ipcp
->my_ip
);
578 if (IsEnabled(ipcp
->cfg
.vj
.neg
)
580 || (ipcp
->fsm
.bundle
->radius
.valid
&& ipcp
->fsm
.bundle
->radius
.vj
)
583 ipcp
->my_compproto
= (PROTO_VJCOMP
<< 16) +
584 ((ipcp
->cfg
.vj
.slots
- 1) << 8) +
585 ipcp
->cfg
.vj
.slotcomp
;
587 ipcp
->my_compproto
= 0;
588 sl_compress_init(&ipcp
->vj
.cslc
, ipcp
->cfg
.vj
.slots
- 1);
590 ipcp
->peer_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
);
599 numaddresses(struct in_addr mask
)
601 u_int32_t bit
, haddr
;
604 haddr
= ntohl(mask
.s_addr
);
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
;
625 if (!ncpaddr_getip4(&addr
->peer
, &peer
)) {
626 log_Printf(LogERROR
, "Oops, ipcp_proxyarp() called with unexpected addr\n");
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
));
639 ip
.s_addr
= peer
.s_addr
& mask
.s_addr
;
641 ip
.s_addr
= htonl(ntohl(ip
.s_addr
) + 1);
645 if (!((ip
.s_addr
^ peer
.s_addr
) & mask
.s_addr
)) {
646 if (!(ret
= (*proxyfun
)(bundle
, ip
)))
650 ip
.s_addr
= htonl(ntohl(ip
.s_addr
) + 1);
653 } else if (Enabled(bundle
, OPT_PROXY
))
654 ret
= (*proxyfun
)(bundle
, peer
);
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
;
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
))
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
);
702 if (bundle
->radius
.valid
)
703 route_Change(bundle
, bundle
->radius
.routes
, &myncpaddr
, &hisncpaddr
);
709 static struct in_addr
710 ChooseHisAddr(struct bundle
*bundle
, struct in_addr gw
)
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",
719 if (ipcp_SetIPaddress(&bundle
->ncp
.ipcp
, gw
, try)) {
720 log_Printf(LogIPCP
, "Selected IP address %s\n", inet_ntoa(try));
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
;
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
;
742 fp
->restart
= ipcp
->cfg
.fsm
.maxreq
;
745 fp
->restart
= ipcp
->cfg
.fsm
.maxtrm
;
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
];
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
);
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
,
803 IpcpSentTerminateReq(struct fsm
*fp __unused
)
805 /* Term REQ just sent by FSM */
809 IpcpSendTerminateAck(struct fsm
*fp
, u_char id
)
811 /* Send Term ACK please */
812 fsm_Output(fp
, CODE_TERMACK
, id
, NULL
, 0, MB_IPCPOUT
);
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;
829 IpcpLayerFinish(struct fsm
*fp
)
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()
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()
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
);
864 IpcpLayerDown(struct fsm
*fp
)
866 /* About to come down */
867 struct ipcp
*ipcp
= fsm2ipcp(fp
);
868 static int recursing
;
872 snprintf(addr
, sizeof addr
, "%s", inet_ntoa(ipcp
->my_ip
));
873 log_Printf(LogIPCP
, "%s: LayerDown: %s\n", fp
->link
->name
, addr
);
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
,
883 radius_StopTimer(&fp
->bundle
->radius
);
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
);
896 system_Select(fp
->bundle
, "MYADDR", LINKDOWNFILE
, NULL
, NULL
);
899 ipcp_Setup(ipcp
, INADDR_NONE
);
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");
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
);
919 if (ipcp
->fsm
.bundle
->NatEnabled
)
920 LibAliasSetAddress(la
, ipcp
->my_ip
);
927 IpcpLayerUp(struct fsm
*fp
)
930 struct ipcp
*ipcp
= fsm2ipcp(fp
);
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
))
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
,
952 radius_StartTimer(fp
->bundle
);
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
);
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();
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
;
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",
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
994 for (n
= 0; n
< iface
->addrs
; n
++) {
995 if (!ncpaddr_getip4(&iface
->addr
[n
].peer
, &peer
))
997 if (iplist_ip2pos(&ipcp
->cfg
.peer_list
, peer
) >= 0) {
998 ipcp
->peer_ip
= peer
;
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
;
1011 memcpy(dec
->rejend
, &ip
.s_addr
, 4);
1014 *dec
->nakend
++ = TY_IPADDR
;
1016 memcpy(dec
->nakend
, &ipcp
->peer_ip
.s_addr
, 4);
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
1027 *dec
->nakend
++ = TY_IPADDR
;
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
);
1036 if (n
== iface
->addrs
)
1037 memcpy(dec
->nakend
, &ipcp
->peer_ip
.s_addr
, 4);
1044 *dec
->ackend
++ = TY_IPADDR
;
1046 memcpy(dec
->ackend
, &ip
.s_addr
, 4);
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
);
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
;
1066 while (end
- cp
>= (int)sizeof(opt
->hdr
)) {
1067 if ((opt
= fsm_readopt(&cp
)) == NULL
)
1070 snprintf(tbuff
, sizeof tbuff
, " %s[%d]", protoname(opt
->hdr
.id
),
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
) {
1081 ipcp_ValidateReq(ipcp
, ipaddr
, dec
);
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
);
1094 log_Printf(log_IsKept(LogIPCP
) ? LogIPCP
: LogPHASE
,
1095 "%s: Unacceptable address!\n", inet_ntoa(ipaddr
));
1096 fsm_Close(&ipcp
->fsm
);
1101 ipcp
->peer_reject
|= (1 << opt
->hdr
.id
);
1107 memcpy(&pcomp
, opt
->data
, sizeof pcomp
);
1108 compproto
= (ntohs(pcomp
.proto
) << 16) + ((int)pcomp
.slots
<< 8) +
1110 log_Printf(LogIPCP
, "%s %s\n", tbuff
, vj2asc(compproto
));
1112 switch (mode_type
) {
1114 if (!IsAccepted(ipcp
->cfg
.vj
.neg
))
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 "
1123 ipcp
->peer_compproto
= compproto
;
1126 pcomp
.proto
= htons(PROTO_VJCOMP
);
1127 nak
.hdr
.id
= TY_COMPPROTO
;
1129 memcpy(nak
.data
, &pcomp
, 2);
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
;
1142 /* Get as close as we can to what he wants */
1144 pcomp
.slots
= MIN_VJ_STATES
;
1145 nak
.hdr
.id
= TY_COMPPROTO
;
1147 memcpy(nak
.data
, &pcomp
, 2);
1151 /* What we really want */
1152 pcomp
.proto
= htons(PROTO_VJCOMP
);
1153 pcomp
.slots
= DEF_VJ_STATES
;
1155 nak
.hdr
.id
= TY_COMPPROTO
;
1157 memcpy(nak
.data
, &pcomp
, sizeof pcomp
);
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) +
1177 log_Printf(LogIPCP
, "%s changing compproto: %08x --> %08x\n",
1178 tbuff
, ipcp
->my_compproto
, compproto
);
1179 ipcp
->my_compproto
= compproto
;
1183 ipcp
->peer_reject
|= (1 << opt
->hdr
.id
);
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
) {
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
) {
1212 if (!IsAccepted(ipcp
->cfg
.ns
.dns_neg
)) {
1213 ipcp
->my_reject
|= (1 << (opt
->hdr
.id
- TY_ADJUST_NS
));
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
;
1234 memcpy(nak
.data
, &have_ip
.s_addr
, 4);
1238 * Otherwise they have it right (this time) so we send an ack packet
1239 * back confirming it... end of story
1246 if (IsEnabled(ipcp
->cfg
.ns
.dns_neg
)) {
1248 memcpy(&ipcp
->ns
.dns
[opt
->hdr
.id
== TY_PRIMARY_DNS
? 0 : 1].s_addr
,
1253 case MODE_REJ
: /* Can't do much, stop asking */
1254 ipcp
->peer_reject
|= (1 << (opt
->hdr
.id
- TY_ADJUST_NS
));
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
) {
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
));
1276 if (ipaddr
.s_addr
!= have_ip
.s_addr
) {
1277 nak
.hdr
.id
= opt
->hdr
.id
;
1279 memcpy(nak
.data
, &have_ip
.s_addr
, 4);
1286 log_Printf(LogIPCP
, "MS NBNS req %d - NAK??\n", opt
->hdr
.id
);
1290 log_Printf(LogIPCP
, "MS NBNS req %d - REJ??\n", opt
->hdr
.id
);
1296 if (mode_type
!= MODE_NOP
) {
1297 ipcp
->my_reject
|= (1 << opt
->hdr
.id
);
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
));
1311 bundle_AdjustDNS(fp
->bundle
);
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.
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
);
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
));
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
);
1388 ncprange_setip4host(&ipcp
->cfg
.peer_range
, ipcp
->peer_ip
);
1390 log_Printf(LogWARN
, "%s: Invalid range !\n", hisaddr
);
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
);
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
))
1406 ncpaddr_setip4(&ncpaddr
, ipcp
->peer_ip
);
1407 bundle_AdjustFilters(bundle
, NULL
, &ncpaddr
);
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
:
1420 addr
.s_addr
= htonl(haddr
);
1426 ipcp_QueueLen(struct ipcp
*ipcp
)
1432 for (q
= ipcp
->Queue
; q
< ipcp
->Queue
+ IPCP_QUEUES(ipcp
); q
++)
1439 ipcp_PushPacket(struct ipcp
*ipcp
, struct link
*l
)
1441 struct bundle
*bundle
= ipcp
->fsm
.bundle
;
1442 struct mqueue
*queue
;
1446 unsigned alivesecs
= 0;
1448 if (ipcp
->fsm
.state
!= ST_OPENED
)
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
);
1459 queue
= ipcp
->Queue
+ IPCP_QUEUES(ipcp
) - 1;
1462 bp
= m_dequeue(queue
);
1463 bp
= mbuf_Read(bp
, &secs
, sizeof secs
);
1465 m_len
= m_length(bp
);
1466 if (!FilterCheck(MBUF_CTOP(bp
), AF_INET
, &bundle
->filter
.alive
,
1470 bundle_StartIdleTimer(bundle
, secs
);
1472 link_PushPacket(l
, bp
, bundle
, 0, PROTO_IP
);
1473 ipcp_AddOutOctets(ipcp
, m_len
);
1476 } while (queue
-- != ipcp
->Queue
);