1 /* SPDX-License-Identifier: BSD-2-Clause */
3 * dhcpcd - DHCP client daemon
4 * Copyright (c) 2006-2021 Roy Marples <roy@marples.name>
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
29 #include <sys/socket.h>
30 #include <sys/types.h>
32 #include <arpa/inet.h>
34 #include <net/route.h>
35 #include <netinet/if_ether.h>
36 #include <netinet/in.h>
54 #include "if-options.h"
62 #define IPV4_LOOPBACK_ROUTE
63 #if defined(__linux__) || defined(__sun) || (defined(BSD) && defined(RTF_LOCAL))
64 /* Linux has had loopback routes in the local table since 2.2
65 * Solaris does not seem to support loopback routes. */
66 #undef IPV4_LOOPBACK_ROUTE
70 inet_ntocidr(struct in_addr address
)
73 uint32_t mask
= htonl(address
.s_addr
);
83 inet_cidrtoaddr(int cidr
, struct in_addr
*addr
)
87 if (cidr
< 1 || cidr
> 32) {
91 ocets
= (cidr
+ 7) / NBBY
;
95 memset(&addr
->s_addr
, 255, (size_t)ocets
- 1);
96 memset((unsigned char *)&addr
->s_addr
+ (ocets
- 1),
97 (256 - (1 << (32 - cidr
) % NBBY
)), 1);
104 ipv4_getnetmask(uint32_t addr
)
113 return ntohl(IN_CLASSA_NET
);
115 return ntohl(IN_CLASSB_NET
);
117 return ntohl(IN_CLASSC_NET
);
123 ipv4_iffindaddr(struct interface
*ifp
,
124 const struct in_addr
*addr
, const struct in_addr
*mask
)
126 struct ipv4_state
*state
;
127 struct ipv4_addr
*ap
;
129 state
= IPV4_STATE(ifp
);
131 TAILQ_FOREACH(ap
, &state
->addrs
, next
) {
132 if ((addr
== NULL
|| ap
->addr
.s_addr
== addr
->s_addr
) &&
133 (mask
== NULL
|| ap
->mask
.s_addr
== mask
->s_addr
))
141 ipv4_iffindlladdr(struct interface
*ifp
)
143 struct ipv4_state
*state
;
144 struct ipv4_addr
*ap
;
146 state
= IPV4_STATE(ifp
);
148 TAILQ_FOREACH(ap
, &state
->addrs
, next
) {
149 if (IN_LINKLOCAL(ntohl(ap
->addr
.s_addr
)))
156 static struct ipv4_addr
*
157 ipv4_iffindmaskaddr(struct interface
*ifp
, const struct in_addr
*addr
)
159 struct ipv4_state
*state
;
160 struct ipv4_addr
*ap
;
162 state
= IPV4_STATE(ifp
);
164 TAILQ_FOREACH (ap
, &state
->addrs
, next
) {
165 if ((ap
->addr
.s_addr
& ap
->mask
.s_addr
) ==
166 (addr
->s_addr
& ap
->mask
.s_addr
))
173 static struct ipv4_addr
*
174 ipv4_iffindmaskbrd(struct interface
*ifp
, const struct in_addr
*addr
)
176 struct ipv4_state
*state
;
177 struct ipv4_addr
*ap
;
179 state
= IPV4_STATE(ifp
);
181 TAILQ_FOREACH (ap
, &state
->addrs
, next
) {
182 if ((ap
->brd
.s_addr
& ap
->mask
.s_addr
) ==
183 (addr
->s_addr
& ap
->mask
.s_addr
))
191 ipv4_findaddr(struct dhcpcd_ctx
*ctx
, const struct in_addr
*addr
)
193 struct interface
*ifp
;
194 struct ipv4_addr
*ap
;
196 TAILQ_FOREACH(ifp
, ctx
->ifaces
, next
) {
197 ap
= ipv4_iffindaddr(ifp
, addr
, NULL
);
205 ipv4_findmaskaddr(struct dhcpcd_ctx
*ctx
, const struct in_addr
*addr
)
207 struct interface
*ifp
;
208 struct ipv4_addr
*ap
;
210 TAILQ_FOREACH(ifp
, ctx
->ifaces
, next
) {
211 ap
= ipv4_iffindmaskaddr(ifp
, addr
);
219 ipv4_findmaskbrd(struct dhcpcd_ctx
*ctx
, const struct in_addr
*addr
)
221 struct interface
*ifp
;
222 struct ipv4_addr
*ap
;
224 TAILQ_FOREACH(ifp
, ctx
->ifaces
, next
) {
225 ap
= ipv4_iffindmaskbrd(ifp
, addr
);
233 ipv4_hasaddr(const struct interface
*ifp
)
235 const struct dhcp_state
*dstate
;
238 if (IPV4LL_STATE_RUNNING(ifp
))
242 dstate
= D_CSTATE(ifp
);
244 dstate
->added
== STATE_ADDED
&&
245 dstate
->addr
!= NULL
);
248 /* Interface comparer for working out ordering. */
250 ipv4_ifcmp(const struct interface
*si
, const struct interface
*ti
)
252 const struct dhcp_state
*sis
, *tis
;
262 /* If one has a lease and the other not, it takes precedence. */
263 if (sis
->new && !tis
->new)
265 if (!sis
->new && tis
->new)
267 /* Always prefer proper leases */
268 if (!(sis
->added
& STATE_FAKE
) && (tis
->added
& STATE_FAKE
))
270 if ((sis
->added
& STATE_FAKE
) && !(tis
->added
& STATE_FAKE
))
272 /* If we are either, they neither have a lease, or they both have.
273 * We need to check for IPv4LL and make it non-preferred. */
274 if (sis
->new && tis
->new) {
275 if (IS_DHCP(sis
->new) && !IS_DHCP(tis
->new))
277 if (!IS_DHCP(sis
->new) && IS_DHCP(tis
->new))
284 inet_dhcproutes(rb_tree_t
*routes
, struct interface
*ifp
, bool *have_default
)
286 const struct dhcp_state
*state
;
288 struct rt
*rt
, *r
= NULL
;
293 state
= D_CSTATE(ifp
);
294 if (state
== NULL
|| state
->state
!= DHS_BOUND
|| !state
->added
)
297 /* An address does have to exist. */
300 rb_tree_init(&nroutes
, &rt_compare_proto_ops
);
302 /* First, add a subnet route. */
303 if (state
->addr
->mask
.s_addr
!= INADDR_ANY
305 /* BSD adds a route in this instance */
306 && state
->addr
->mask
.s_addr
!= INADDR_BROADCAST
309 if ((rt
= rt_new(ifp
)) == NULL
)
311 rt
->rt_dflags
|= RTDF_IFA_ROUTE
;
312 in
.s_addr
= state
->addr
->addr
.s_addr
& state
->addr
->mask
.s_addr
;
313 sa_in_init(&rt
->rt_dest
, &in
);
314 in
.s_addr
= state
->addr
->mask
.s_addr
;
315 sa_in_init(&rt
->rt_netmask
, &in
);
316 //in.s_addr = INADDR_ANY;
317 //sa_in_init(&rt->rt_gateway, &in);
318 rt
->rt_gateway
.sa_family
= AF_UNSPEC
;
319 rt_proto_add(&nroutes
, rt
);
322 /* If any set routes, grab them, otherwise DHCP routes. */
323 if (RB_TREE_MIN(&ifp
->options
->routes
)) {
324 RB_TREE_FOREACH(r
, &ifp
->options
->routes
) {
325 if (sa_is_unspecified(&r
->rt_gateway
))
327 if ((rt
= rt_new0(ifp
->ctx
)) == NULL
)
329 memcpy(rt
, r
, sizeof(*rt
));
331 rt
->rt_dflags
= RTDF_STATIC
;
332 rt_proto_add(&nroutes
, rt
);
335 if (dhcp_get_routes(&nroutes
, ifp
) == -1)
339 /* If configured, install a gateway to the desintion
340 * for P2P interfaces. */
341 if (ifp
->flags
& IFF_POINTOPOINT
&&
342 has_option_mask(ifp
->options
->dstmask
, DHO_ROUTER
))
344 if ((rt
= rt_new(ifp
)) == NULL
)
346 in
.s_addr
= INADDR_ANY
;
347 sa_in_init(&rt
->rt_dest
, &in
);
348 sa_in_init(&rt
->rt_netmask
, &in
);
349 sa_in_init(&rt
->rt_gateway
, &state
->addr
->brd
);
350 sa_in_init(&rt
->rt_ifa
, &state
->addr
->addr
);
351 rt_proto_add(&nroutes
, rt
);
354 /* Copy our address as the source address and set mtu */
355 mtu
= dhcp_get_mtu(ifp
);
357 while ((rt
= RB_TREE_MIN(&nroutes
)) != NULL
) {
358 rb_tree_remove_node(&nroutes
, rt
);
360 if (!(rt
->rt_dflags
& RTDF_STATIC
))
361 rt
->rt_dflags
|= RTDF_DHCP
;
362 sa_in_init(&rt
->rt_ifa
, &state
->addr
->addr
);
363 if (rb_tree_insert_node(routes
, rt
) != rt
) {
367 if (rt_is_default(rt
))
368 *have_default
= true;
375 /* We should check to ensure the routers are on the same subnet
376 * OR supply a host route. If not, warn and add a host route. */
378 inet_routerhostroute(rb_tree_t
*routes
, struct interface
*ifp
)
380 struct rt
*rt
, *rth
, *rtp
;
381 struct sockaddr_in
*dest
, *netmask
, *gateway
;
382 const char *cp
, *cp2
, *cp3
, *cplim
;
383 struct if_options
*ifo
;
384 const struct dhcp_state
*state
;
388 /* Don't add a host route for these interfaces. */
389 if (ifp
->flags
& (IFF_LOOPBACK
| IFF_POINTOPOINT
))
392 rb_tree_init(&troutes
, &rt_compare_proto_ops
);
394 RB_TREE_FOREACH(rt
, routes
) {
395 if (rt
->rt_dest
.sa_family
!= AF_INET
)
397 if (!sa_is_unspecified(&rt
->rt_dest
) ||
398 sa_is_unspecified(&rt
->rt_gateway
))
400 gateway
= satosin(&rt
->rt_gateway
);
401 /* Scan for a route to match */
402 RB_TREE_FOREACH(rth
, routes
) {
406 if (sa_cmp(&rth
->rt_dest
, &rt
->rt_gateway
) == 0)
409 /* XXX ADD TO RT_COMARE? XXX */
410 cp
= (const char *)&gateway
->sin_addr
.s_addr
;
411 dest
= satosin(&rth
->rt_dest
);
412 cp2
= (const char *)&dest
->sin_addr
.s_addr
;
413 netmask
= satosin(&rth
->rt_netmask
);
414 cp3
= (const char *)&netmask
->sin_addr
.s_addr
;
415 cplim
= cp3
+ sizeof(netmask
->sin_addr
.s_addr
);
416 while (cp3
< cplim
) {
417 if ((*cp
++ ^ *cp2
++) & *cp3
++)
425 if ((state
= D_CSTATE(ifp
)) == NULL
)
428 if (ifp
->flags
& IFF_NOARP
) {
429 if (!(ifo
->options
& DHCPCD_ROUTER_HOST_ROUTE_WARNED
) &&
430 !(state
->added
& STATE_FAKE
))
432 char buf
[INET_MAX_ADDRSTRLEN
];
434 ifo
->options
|= DHCPCD_ROUTER_HOST_ROUTE_WARNED
;
435 logwarnx("%s: forcing router %s through "
438 sa_addrtop(&rt
->rt_gateway
,
441 gateway
->sin_addr
.s_addr
= INADDR_ANY
;
444 if (!(ifo
->options
& DHCPCD_ROUTER_HOST_ROUTE_WARNED
) &&
445 !(state
->added
& STATE_FAKE
))
447 char buf
[INET_MAX_ADDRSTRLEN
];
449 ifo
->options
|= DHCPCD_ROUTER_HOST_ROUTE_WARNED
;
450 logwarnx("%s: router %s requires a host route",
452 sa_addrtop(&rt
->rt_gateway
, buf
, sizeof(buf
)));
455 if ((rth
= rt_new(ifp
)) == NULL
)
457 rth
->rt_flags
|= RTF_HOST
;
458 sa_in_init(&rth
->rt_dest
, &gateway
->sin_addr
);
459 in
.s_addr
= INADDR_BROADCAST
;
460 sa_in_init(&rth
->rt_netmask
, &in
);
461 in
.s_addr
= INADDR_ANY
;
462 sa_in_init(&rth
->rt_gateway
, &in
);
463 rth
->rt_mtu
= dhcp_get_mtu(ifp
);
464 if (state
->addr
!= NULL
)
465 sa_in_init(&rth
->rt_ifa
, &state
->addr
->addr
);
467 rth
->rt_ifa
.sa_family
= AF_UNSPEC
;
469 /* We need to insert the host route just before the router. */
470 while ((rtp
= RB_TREE_MAX(routes
)) != NULL
) {
471 rb_tree_remove_node(routes
, rtp
);
472 rt_proto_add(&troutes
, rtp
);
476 rt_proto_add(routes
, rth
);
477 /* troutes is now reversed, so add backwards again. */
478 while ((rtp
= RB_TREE_MAX(&troutes
)) != NULL
) {
479 rb_tree_remove_node(&troutes
, rtp
);
480 rt_proto_add(routes
, rtp
);
487 inet_getroutes(struct dhcpcd_ctx
*ctx
, rb_tree_t
*routes
)
489 struct interface
*ifp
;
490 bool have_default
= false;
492 TAILQ_FOREACH(ifp
, ctx
->ifaces
, next
) {
495 if (inet_dhcproutes(routes
, ifp
, &have_default
) == -1)
498 if (ipv4ll_subnetroute(routes
, ifp
) == -1)
501 if (inet_routerhostroute(routes
, ifp
) == -1)
506 /* If there is no default route, see if we can use an IPv4LL one. */
510 TAILQ_FOREACH(ifp
, ctx
->ifaces
, next
) {
512 ipv4ll_defaultroute(routes
, ifp
) == 1)
521 ipv4_deladdr(struct ipv4_addr
*addr
, int keeparp
)
524 struct ipv4_state
*state
;
525 struct ipv4_addr
*ap
;
527 logdebugx("%s: deleting IP address %s",
528 addr
->iface
->name
, addr
->saddr
);
530 r
= if_address(RTM_DELADDR
, addr
);
532 errno
!= EADDRNOTAVAIL
&& errno
!= ESRCH
&&
533 errno
!= ENXIO
&& errno
!= ENODEV
)
534 logerr("%s: %s", addr
->iface
->name
, __func__
);
538 arp_freeaddr(addr
->iface
, &addr
->addr
);
543 state
= IPV4_STATE(addr
->iface
);
544 TAILQ_FOREACH(ap
, &state
->addrs
, next
) {
545 if (IPV4_MASK_EQ(ap
, addr
)) {
546 struct dhcp_state
*dstate
;
548 dstate
= D_STATE(ap
->iface
);
549 TAILQ_REMOVE(&state
->addrs
, ap
, next
);
552 if (dstate
&& dstate
->addr
== ap
) {
564 delete_address(struct interface
*ifp
)
567 struct if_options
*ifo
;
568 struct dhcp_state
*state
;
570 state
= D_STATE(ifp
);
572 /* The lease could have been added, but the address deleted
574 if (state
->addr
== NULL
||
575 ifo
->options
& DHCPCD_INFORM
||
576 (ifo
->options
& DHCPCD_STATIC
&& ifo
->req_addr
.s_addr
== 0))
579 arp_freeaddr(ifp
, &state
->addr
->addr
);
581 r
= ipv4_deladdr(state
->addr
, 0);
586 ipv4_getstate(struct interface
*ifp
)
588 struct ipv4_state
*state
;
590 state
= IPV4_STATE(ifp
);
592 ifp
->if_data
[IF_DATA_IPV4
] = malloc(sizeof(*state
));
593 state
= IPV4_STATE(ifp
);
598 TAILQ_INIT(&state
->addrs
);
604 /* Find the next logical aliase address we can use. */
606 ipv4_aliasaddr(struct ipv4_addr
*ia
, struct ipv4_addr
**repl
)
608 struct ipv4_state
*state
;
609 struct ipv4_addr
*iap
;
611 char alias
[IF_NAMESIZE
];
613 if (ia
->alias
[0] != '\0')
617 state
= IPV4_STATE(ia
->iface
);
619 if (if_makealias(alias
, IF_NAMESIZE
, ia
->iface
->name
, lun
) >=
625 TAILQ_FOREACH(iap
, &state
->addrs
, next
) {
626 if (iap
->alias
[0] != '\0' && iap
->addr
.s_addr
== INADDR_ANY
) {
627 /* No address assigned? Lets use it. */
628 strlcpy(ia
->alias
, iap
->alias
, sizeof(ia
->alias
));
633 if (strcmp(iap
->alias
, alias
) == 0)
638 if (lun
== UINT_MAX
) {
646 strlcpy(ia
->alias
, alias
, sizeof(ia
->alias
));
652 ipv4_addaddr(struct interface
*ifp
, const struct in_addr
*addr
,
653 const struct in_addr
*mask
, const struct in_addr
*bcast
,
654 uint32_t vltime
, uint32_t pltime
)
656 struct ipv4_state
*state
;
657 struct ipv4_addr
*ia
;
660 struct ipv4_addr
*replaced_ia
;
663 if ((state
= ipv4_getstate(ifp
)) == NULL
) {
667 if (ifp
->options
->options
& DHCPCD_NOALIAS
) {
668 struct ipv4_addr
*ian
;
670 TAILQ_FOREACH_SAFE(ia
, &state
->addrs
, next
, ian
) {
671 if (ia
->addr
.s_addr
!= addr
->s_addr
)
676 ia
= ipv4_iffindaddr(ifp
, addr
, NULL
);
678 ia
= malloc(sizeof(*ia
));
685 #ifdef IN_IFF_TENTATIVE
686 ia
->addr_flags
= IN_IFF_TENTATIVE
;
688 ia
->flags
= IPV4_AF_NEW
;
690 ia
->flags
&= ~IPV4_AF_NEW
;
695 if (ifp
->options
->options
& DHCPCD_LASTLEASE_EXTEND
) {
696 /* We don't want the kernel to expire the address. */
697 ia
->vltime
= ia
->pltime
= DHCP_INFINITE_LIFETIME
;
706 snprintf(ia
->saddr
, sizeof(ia
->saddr
), "%s/%d",
707 inet_ntoa(*addr
), inet_ntocidr(*mask
));
710 blank
= (ia
->alias
[0] == '\0');
711 if ((replaced
= ipv4_aliasaddr(ia
, &replaced_ia
)) == -1) {
712 logerr("%s: ipv4_aliasaddr", ifp
->name
);
717 logdebugx("%s: aliased %s", ia
->alias
, ia
->saddr
);
720 logdebugx("%s: adding IP address %s %s %s",
721 ifp
->name
, ia
->saddr
,
722 ifp
->flags
& IFF_POINTOPOINT
? "destination" : "broadcast",
724 if (if_address(RTM_NEWADDR
, ia
) == -1) {
726 logerr("%s: if_addaddress",
728 if (ia
->flags
& IPV4_AF_NEW
)
735 TAILQ_REMOVE(&state
->addrs
, replaced_ia
, next
);
740 if (ia
->flags
& IPV4_AF_NEW
)
741 TAILQ_INSERT_TAIL(&state
->addrs
, ia
, next
);
746 ipv4_daddaddr(struct interface
*ifp
, const struct dhcp_lease
*lease
)
748 struct dhcp_state
*state
;
749 struct ipv4_addr
*ia
;
751 ia
= ipv4_addaddr(ifp
, &lease
->addr
, &lease
->mask
, &lease
->brd
,
752 lease
->leasetime
, lease
->rebindtime
);
756 state
= D_STATE(ifp
);
757 state
->added
= STATE_ADDED
;
763 ipv4_applyaddr(void *arg
)
765 struct interface
*ifp
= arg
;
766 struct dhcp_state
*state
= D_STATE(ifp
);
767 struct dhcp_lease
*lease
;
768 struct if_options
*ifo
= ifp
->options
;
769 struct ipv4_addr
*ia
;
774 lease
= &state
->lease
;
775 if (state
->new == NULL
) {
776 if ((ifo
->options
& (DHCPCD_EXITING
| DHCPCD_PERSISTENT
)) !=
777 (DHCPCD_EXITING
| DHCPCD_PERSISTENT
))
781 rt_build(ifp
->ctx
, AF_INET
);
783 /* Announce the preferred address to
784 * kick ARP caches. */
785 arp_announceaddr(ifp
->ctx
,&lease
->addr
);
788 script_runreason(ifp
, state
->reason
);
790 rt_build(ifp
->ctx
, AF_INET
);
794 ia
= ipv4_iffindaddr(ifp
, &lease
->addr
, NULL
);
795 /* If the netmask or broadcast is different, re-add the addresss.
796 * If IP addresses do not have lifetimes, there is a very real chance
797 * that re-adding them will scrub the subnet route temporarily
798 * which is a bad thing, so avoid it. */
800 ia
->mask
.s_addr
== lease
->mask
.s_addr
&&
801 ia
->brd
.s_addr
== lease
->brd
.s_addr
)
804 logdebugx("%s: IP address %s already exists",
805 ifp
->name
, ia
->saddr
);
809 /* Linux does not change netmask/broadcast address
810 * for re-added addresses, so we need to delete the old one
816 if (ipv4_daddaddr(ifp
, lease
) == -1 && errno
!= EEXIST
)
821 if (ipv4_daddaddr(ifp
, lease
) == -1 && errno
!= EEXIST
)
825 ia
= ipv4_iffindaddr(ifp
, &lease
->addr
, NULL
);
827 logerrx("%s: added address vanished", ifp
->name
);
830 #if defined(ARP) && defined(IN_IFF_NOTUSEABLE)
831 if (ia
->addr_flags
& IN_IFF_NOTUSEABLE
)
835 /* Delete the old address if different */
837 state
->addr
->addr
.s_addr
!= lease
->addr
.s_addr
&&
838 ipv4_iffindaddr(ifp
, &lease
->addr
, NULL
))
842 state
->added
= STATE_ADDED
;
844 rt_build(ifp
->ctx
, AF_INET
);
847 arp_announceaddr(ifp
->ctx
, &state
->addr
->addr
);
850 if (state
->state
== DHS_BOUND
) {
851 script_runreason(ifp
, state
->reason
);
852 dhcpcd_daemonise(ifp
->ctx
);
858 ipv4_markaddrsstale(struct interface
*ifp
)
860 struct ipv4_state
*state
;
861 struct ipv4_addr
*ia
;
863 state
= IPV4_STATE(ifp
);
867 TAILQ_FOREACH(ia
, &state
->addrs
, next
) {
868 ia
->flags
|= IPV4_AF_STALE
;
873 ipv4_deletestaleaddrs(struct interface
*ifp
)
875 struct ipv4_state
*state
;
876 struct ipv4_addr
*ia
, *ia1
;
878 state
= IPV4_STATE(ifp
);
882 TAILQ_FOREACH_SAFE(ia
, &state
->addrs
, next
, ia1
) {
883 if (!(ia
->flags
& IPV4_AF_STALE
))
885 ipv4_handleifa(ifp
->ctx
, RTM_DELADDR
,
886 ifp
->ctx
->ifaces
, ifp
->name
,
887 &ia
->addr
, &ia
->mask
, &ia
->brd
, 0, getpid());
892 ipv4_handleifa(struct dhcpcd_ctx
*ctx
,
893 int cmd
, struct if_head
*ifs
, const char *ifname
,
894 const struct in_addr
*addr
, const struct in_addr
*mask
,
895 const struct in_addr
*brd
, int addrflags
, pid_t pid
)
897 struct interface
*ifp
;
898 struct ipv4_state
*state
;
899 struct ipv4_addr
*ia
;
903 char sbrdbuf
[INET_ADDRSTRLEN
];
907 sbrd
= inet_ntop(AF_INET
, brd
, sbrdbuf
, sizeof(sbrdbuf
));
910 logdebugx("%s: %s %s/%d %s %d", ifname
,
911 cmd
== RTM_NEWADDR
? "RTM_NEWADDR" :
912 cmd
== RTM_DELADDR
? "RTM_DELADDR" : "???",
913 inet_ntoa(*addr
), inet_ntocidr(*mask
), sbrd
, addrflags
);
922 if ((ifp
= if_find(ifs
, ifname
)) == NULL
)
924 if ((state
= ipv4_getstate(ifp
)) == NULL
) {
929 ia
= ipv4_iffindaddr(ifp
, addr
, NULL
);
933 if ((ia
= malloc(sizeof(*ia
))) == NULL
) {
943 strlcpy(ia
->alias
, ifname
, sizeof(ia
->alias
));
945 TAILQ_INSERT_TAIL(&state
->addrs
, ia
, next
);
948 /* Mask could have changed */
950 (mask
->s_addr
!= INADDR_ANY
&&
951 mask
->s_addr
!= ia
->mask
.s_addr
))
954 snprintf(ia
->saddr
, sizeof(ia
->saddr
), "%s/%d",
955 inet_ntoa(*addr
), inet_ntocidr(*mask
));
960 ia
->brd
.s_addr
= INADDR_ANY
;
961 ia
->addr_flags
= addrflags
;
962 ia
->flags
&= ~IPV4_AF_STALE
;
967 if (mask
->s_addr
!= INADDR_ANY
&&
968 mask
->s_addr
!= ia
->mask
.s_addr
)
970 TAILQ_REMOVE(&state
->addrs
, ia
, next
);
976 if (addr
->s_addr
!= INADDR_ANY
&& addr
->s_addr
!= INADDR_BROADCAST
) {
977 ia
= dhcp_handleifa(cmd
, ia
, pid
);
980 ipv4ll_handleifa(cmd
, ia
, pid
);
984 if (cmd
== RTM_DELADDR
)
989 ipv4_free(struct interface
*ifp
)
991 struct ipv4_state
*state
;
992 struct ipv4_addr
*ia
;
994 if (ifp
== NULL
|| (state
= IPV4_STATE(ifp
)) == NULL
)
997 while ((ia
= TAILQ_FIRST(&state
->addrs
))) {
998 TAILQ_REMOVE(&state
->addrs
, ia
, next
);