From: Roy Marples Date: Fri, 6 Sep 2013 09:38:24 +0000 (+0000) Subject: It seems that FreeBSD will send RTM_DELADDR + RTM_NEWADDR when X-Git-Tag: v6.1.0~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=27f61373d14c2e44b06f6f2ce26baf899ad8c283;p=thirdparty%2Fdhcpcd.git It seems that FreeBSD will send RTM_DELADDR + RTM_NEWADDR when replacing an existing IPv4 address with the same values. As such, we need to maintain a list of configured IPv4 addresses for each interface so we know when to add it and when to skip it to avoid receiving bogus RTM_DELADDR messages from ourself. --- diff --git a/dhcp.c b/dhcp.c index 30c1ecd6..b13778c2 100644 --- a/dhcp.c +++ b/dhcp.c @@ -1699,7 +1699,6 @@ dhcp_rebind(void *arg) send_rebind(ifp); } - void dhcp_bind(void *arg) { @@ -1721,10 +1720,10 @@ dhcp_bind(void *arg) state->offer = NULL; get_lease(lease, state->new); if (ifo->options & DHCPCD_STATIC) { - syslog(LOG_INFO, "%s: using static address %s", - iface->name, inet_ntoa(lease->addr)); + syslog(LOG_INFO, "%s: using static address %s/%d", + iface->name, inet_ntoa(lease->addr), + inet_ntocidr(lease->net)); lease->leasetime = ~0U; - lease->net.s_addr = ifo->req_mask.s_addr; state->reason = "STATIC"; } else if (state->new->cookie != htonl(MAGIC_COOKIE)) { syslog(LOG_INFO, "%s: using IPv4LL address %s", @@ -1831,7 +1830,7 @@ dhcp_timeout(void *arg) } struct dhcp_message * -dhcp_message_new(struct in_addr *addr, struct in_addr *mask) +dhcp_message_new(const struct in_addr *addr, const struct in_addr *mask) { struct dhcp_message *dhcp; uint8_t *p; @@ -1851,60 +1850,65 @@ dhcp_message_new(struct in_addr *addr, struct in_addr *mask) return dhcp; } -static int -handle_3rdparty(struct interface *ifp) +static void +dhcp_static(struct interface *ifp) { struct if_options *ifo; struct dhcp_state *state; - struct in_addr addr, net, dst; + state = D_STATE(ifp); ifo = ifp->options; - if (ifo->req_addr.s_addr != INADDR_ANY) - return 0; - - if (ipv4_getaddress(ifp->name, &addr, &net, &dst) == 1) - ipv4_handleifa(RTM_NEWADDR, ifp->name, &addr, &net, &dst); - else { + if (ifo->req_addr.s_addr == INADDR_ANY) { syslog(LOG_INFO, - "%s: waiting for 3rd party to configure IP address", + "%s: waiting for 3rd party to " + "configure IP address", ifp->name); - state = D_STATE(ifp); state->reason = "3RDPARTY"; script_runreason(ifp, state->reason); - } - return 1; -} - -static void -dhcp_static(struct interface *ifp) -{ - struct if_options *ifo; - struct dhcp_state *state; - - if (handle_3rdparty(ifp)) return; - ifo = ifp->options; - state = D_STATE(ifp); + } state->offer = dhcp_message_new(&ifo->req_addr, &ifo->req_mask); - eloop_timeout_delete(NULL, ifp); - dhcp_bind(ifp); + if (state->offer) { + eloop_timeout_delete(NULL, ifp); + dhcp_bind(ifp); + } } void dhcp_inform(struct interface *ifp) { struct dhcp_state *state; - - if (handle_3rdparty(ifp)) - return; + struct if_options *ifo; + struct ipv4_addr *ap; state = D_STATE(ifp); + ifo = ifp->options; if (options & DHCPCD_TEST) { - state->addr.s_addr = ifp->options->req_addr.s_addr; - state->net.s_addr = ifp->options->req_mask.s_addr; + state->addr.s_addr = ifo->req_addr.s_addr; + state->net.s_addr = ifo->req_mask.s_addr; } else { - ifp->options->options |= DHCPCD_STATIC; - dhcp_static(ifp); + if (ifo->req_addr.s_addr == INADDR_ANY) { + state = D_STATE(ifp); + ap = ipv4_findaddr(ifp, NULL, NULL); + if (ap == NULL) { + syslog(LOG_INFO, + "%s: waiting for 3rd party to " + "configure IP address", + ifp->name); + state->reason = "3RDPARTY"; + script_runreason(ifp, state->reason); + return; + } + state->offer = + dhcp_message_new(&ap->addr, &ap->net); + } else + state->offer = + dhcp_message_new(&ifo->req_addr, &ifo->req_mask); + if (state->offer) { + ifo->options |= DHCPCD_STATIC; + dhcp_bind(ifp); + ifo->options &= ~DHCPCD_STATIC; + } } state->state = DHS_INFORM; @@ -2217,6 +2221,8 @@ dhcp_handle(struct interface *iface, struct dhcp_message **dhcpp, if (!(ifo->options & DHCPCD_INFORM)) log_dhcp(LOG_DEBUG, "acknowledged", iface, dhcp, from); + else + ifo->options &= ~DHCPCD_STATIC; } /* BOOTP could have already assigned this above, so check we still @@ -2241,7 +2247,7 @@ dhcp_handle(struct interface *iface, struct dhcp_message **dhcpp, /* If the interface already has the address configured * then we can't ARP for duplicate detection. */ addr.s_addr = state->offer->yiaddr; - if (ipv4_hasaddress(iface->name, &addr, NULL) != 1) { + if (!ipv4_findaddr(iface, &addr, NULL)) { state->claims = 0; state->probes = 0; state->conflicts = 0; @@ -2684,3 +2690,65 @@ dhcp_start(struct interface *ifp) else dhcp_reboot(ifp); } + +void +dhcp_handleifa(int type, struct interface *ifp, + const struct in_addr *addr, + const struct in_addr *net, + const struct in_addr *dst) +{ + struct dhcp_state *state; + struct if_options *ifo; + int i; + + state = D_STATE(ifp); + if (state == NULL) + return; + + if (type == RTM_DELADDR) { + if (state->new && + state->new->yiaddr == addr->s_addr) + syslog(LOG_INFO, "%s: removing IP address %s/%d", + ifp->name, inet_ntoa(state->lease.addr), + inet_ntocidr(state->lease.net)); + return; + } + + if (type != RTM_NEWADDR) + return; + + ifo = ifp->options; + if (ifo->options & DHCPCD_INFORM) { + if (state->state != DHS_INFORM) + dhcp_inform(ifp); + return; + } + + if (!(ifo->options & DHCPCD_STATIC)) + return; + if (ifo->req_addr.s_addr != INADDR_ANY) + return; + + free(state->old); + state->old = state->new; + state->new = dhcp_message_new(addr, net); + if (state->new == NULL) + return; + state->dst.s_addr = dst ? dst->s_addr : INADDR_ANY; + if (dst) { + for (i = 1; i < 255; i++) + if (i != DHO_ROUTER && has_option_mask(ifo->dstmask,i)) + dhcp_message_add_addr(state->new, i, *dst); + } + state->reason = "STATIC"; + ipv4_buildroutes(); + script_runreason(ifp, state->reason); + if (ifo->options & DHCPCD_INFORM) { + state->state = DHS_INFORM; + state->xid = dhcp_xid(ifp); + state->lease.server.s_addr = dst ? dst->s_addr : INADDR_ANY; + state->addr = *addr; + state->net = *net; + dhcp_inform(ifp); + } +} diff --git a/dhcp.h b/dhcp.h index 60586988..986fd98a 100644 --- a/dhcp.h +++ b/dhcp.h @@ -259,8 +259,8 @@ ssize_t dhcp_env(char **, const char *, const struct dhcp_message *, const struct interface *); uint32_t dhcp_xid(const struct interface *); -struct dhcp_message *dhcp_message_new(struct in_addr *addr, - struct in_addr *mask); +struct dhcp_message *dhcp_message_new(const struct in_addr *addr, + const struct in_addr *mask); int dhcp_message_add_addr(struct dhcp_message *, uint8_t, struct in_addr); ssize_t make_message(struct dhcp_message **, const struct interface *, uint8_t); @@ -270,6 +270,9 @@ ssize_t write_lease(const struct interface *, const struct dhcp_message *); struct dhcp_message *read_lease(const struct interface *); void get_lease(struct dhcp_lease *, const struct dhcp_message *); +void dhcp_handleifa(int, struct interface *, + const struct in_addr *, const struct in_addr *, const struct in_addr *); + void dhcp_drop(struct interface *, const char *); void dhcp_start(struct interface *); void dhcp_stop(struct interface *); diff --git a/dhcpcd.h b/dhcpcd.h index a55cef7c..4f0f56f5 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -43,11 +43,12 @@ #define LINK_UNKNOWN 0 #define LINK_DOWN -1 -#define IF_DATA_DHCP 0 -#define IF_DATA_IPV6 1 -#define IF_DATA_IPV6ND 2 -#define IF_DATA_DHCP6 3 -#define IF_DATA_MAX 4 +#define IF_DATA_IPV4 0 +#define IF_DATA_DHCP 1 +#define IF_DATA_IPV6 2 +#define IF_DATA_IPV6ND 3 +#define IF_DATA_DHCP6 4 +#define IF_DATA_MAX 5 struct interface { TAILQ_ENTRY(interface) next; diff --git a/if-bsd.c b/if-bsd.c index ba607e3b..d7e466f8 100644 --- a/if-bsd.c +++ b/if-bsd.c @@ -659,7 +659,8 @@ manage_link(int fd) COPYOUT(rt.dest, rti_info[RTAX_IFA]); COPYOUT(rt.net, rti_info[RTAX_NETMASK]); COPYOUT(rt.gate, rti_info[RTAX_BRD]); - ipv4_handleifa(rtm->rtm_type, ifname, + ipv4_handleifa(rtm->rtm_type, + NULL, ifname, &rt.dest, &rt.net, &rt.gate); break; #endif diff --git a/if-options.h b/if-options.h index a3ef0514..69c7200a 100644 --- a/if-options.h +++ b/if-options.h @@ -36,8 +36,6 @@ #include #include -#include "ipv4.h" - /* Don't set any optional arguments here so we retain POSIX * compatibility with getopt */ #define IF_OPTS "46bc:de:f:gh:i:kl:m:no:pqr:s:t:u:v:wxy:z:ABC:DEF:GHI:JKLO:Q:S:TUVW:X:Z:" diff --git a/ipv4.c b/ipv4.c index bd33ad6b..06dc761a 100644 --- a/ipv4.c +++ b/ipv4.c @@ -25,6 +25,7 @@ * SUCH DAMAGE. */ +#include #include #include @@ -47,6 +48,7 @@ #include "config.h" #include "common.h" +#include "dhcpcd.h" #include "dhcp.h" #include "if-options.h" #include "if-pref.h" @@ -109,74 +111,45 @@ ipv4_getnetmask(uint32_t addr) return 0; } +struct ipv4_addr * +ipv4_findaddr(struct interface *ifp, + const struct in_addr *addr, const struct in_addr *net) +{ + struct ipv4_state *state; + struct ipv4_addr *ap; + + state = IPV4_STATE(ifp); + if (state) { + TAILQ_FOREACH(ap, &state->addrs, next) { + if ((addr == NULL || ap->addr.s_addr == addr->s_addr) && + (net == NULL || ap->net.s_addr == net->s_addr)) + return ap; + } + } + return NULL; +} + int ipv4_addrexists(const struct in_addr *addr) { - const struct interface *ifp; - const struct dhcp_state *state; + struct interface *ifp; + struct dhcp_state *state; TAILQ_FOREACH(ifp, ifaces, next) { - state = D_CSTATE(ifp); + state = D_STATE(ifp); if (state) { if (addr == NULL) { - if (state->addr.s_addr) + if (state->addr.s_addr != INADDR_ANY) return 1; - } else if (memcmp(&addr->s_addr, - &state->addr.s_addr, - sizeof(state->addr.s_addr)) == 0) + } else if (addr->s_addr == state->addr.s_addr) return 1; } + if (addr != NULL && ipv4_findaddr(ifp, addr, NULL)) + return 1; } return 0; } -int -ipv4_doaddress(const char *ifname, - struct in_addr *addr, struct in_addr *net, struct in_addr *dst, int act) -{ - struct ifaddrs *ifaddrs, *ifa; - const struct sockaddr_in *a, *n, *d; - int retval; - - if (getifaddrs(&ifaddrs) == -1) - return -1; - - retval = 0; - for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr == NULL || - ifa->ifa_addr->sa_family != AF_INET || - strcmp(ifa->ifa_name, ifname) != 0) - continue; - a = (const struct sockaddr_in *)(void *)ifa->ifa_addr; - n = (const struct sockaddr_in *)(void *)ifa->ifa_netmask; - if (ifa->ifa_flags & IFF_POINTOPOINT) - d = (const struct sockaddr_in *)(void *) - ifa->ifa_dstaddr; - else - d = NULL; - if (act == 1) { - addr->s_addr = a->sin_addr.s_addr; - net->s_addr = n->sin_addr.s_addr; - if (dst) { - if (ifa->ifa_flags & IFF_POINTOPOINT) - dst->s_addr = d->sin_addr.s_addr; - else - dst->s_addr = INADDR_ANY; - } - retval = 1; - break; - } - if (addr->s_addr == a->sin_addr.s_addr && - (net == NULL || net->s_addr == n->sin_addr.s_addr)) - { - retval = 1; - break; - } - } - freeifaddrs(ifaddrs); - return retval; -} - void ipv4_freeroutes(struct rt_head *rts) { @@ -586,26 +559,49 @@ ipv4_buildroutes(void) } static int -delete_address(struct interface *iface) +delete_address1(struct interface *ifp, + const struct in_addr *addr, const struct in_addr *net) { - int retval; + int r; + struct ipv4_state *state; + struct ipv4_addr *ap; + + syslog(LOG_DEBUG, "%s: deleting IP address %s/%d", + ifp->name, inet_ntoa(*addr), inet_ntocidr(*net)); + r = ipv4_deleteaddress(ifp, addr, net); + if (r == -1 && errno != EADDRNOTAVAIL && errno != ENXIO && + errno != ENODEV) + syslog(LOG_ERR, "%s: %s: %m", ifp->name, __func__); + + state = IPV4_STATE(ifp); + TAILQ_FOREACH(ap, &state->addrs, next) { + if (ap->addr.s_addr == addr->s_addr && + ap->net.s_addr == net->s_addr) + { + TAILQ_REMOVE(&state->addrs, ap, next); + free(ap); + break; + } + } + return r; +} + +static int +delete_address(struct interface *ifp) +{ + int r; struct if_options *ifo; struct dhcp_state *state; - state = D_STATE(iface); - ifo = iface->options; + state = D_STATE(ifp); + ifo = ifp->options; if (ifo->options & DHCPCD_INFORM || (ifo->options & DHCPCD_STATIC && ifo->req_addr.s_addr == 0)) return 0; - syslog(LOG_DEBUG, "%s: deleting IP address %s/%d", - iface->name, inet_ntoa(state->addr), inet_ntocidr(state->net)); - retval = ipv4_deleteaddress(iface, &state->addr, &state->net); - if (retval == -1 && errno != EADDRNOTAVAIL && errno != ENXIO && - errno != ENODEV) - syslog(LOG_ERR, "del_address: %m"); + r = delete_address1(ifp, &state->addr, &state->net); state->addr.s_addr = 0; state->net.s_addr = 0; - return retval; + return r; } void @@ -616,6 +612,7 @@ ipv4_applyaddr(void *arg) struct dhcp_message *dhcp; struct dhcp_lease *lease; struct if_options *ifo = ifp->options; + struct ipv4_addr *ap; struct rt *rt; int r; @@ -640,10 +637,16 @@ ipv4_applyaddr(void *arg) return; } - /* This also changes netmask */ - if (!(ifo->options & DHCPCD_INFORM) || - !ipv4_hasaddress(ifp->name, &lease->addr, &lease->net)) - { + /* If the netmask is different, delete the addresss */ + ap = ipv4_findaddr(ifp, &lease->addr, NULL); + if (ap && ap->net.s_addr != lease->net.s_addr) + delete_address1(ifp, &ap->addr, &ap->net); + + if (ipv4_findaddr(ifp, &lease->addr, &lease->net)) + syslog(LOG_DEBUG, "%s: IP address %s/%d already exists", + ifp->name, inet_ntoa(lease->addr), + inet_ntocidr(lease->net)); + else { syslog(LOG_DEBUG, "%s: adding IP address %s/%d", ifp->name, inet_ntoa(lease->addr), inet_ntocidr(lease->net)); @@ -687,62 +690,74 @@ ipv4_applyaddr(void *arg) } void -ipv4_handleifa(int type, const char *ifname, - struct in_addr *addr, struct in_addr *net, struct in_addr *dst) +ipv4_handleifa(int type, struct if_head *ifs, const char *ifname, + const struct in_addr *addr, const struct in_addr *net, + const struct in_addr *dst) { struct interface *ifp; - struct if_options *ifo; - struct dhcp_state *state; - int i; + struct ipv4_state *state; + struct ipv4_addr *ap; + if (ifs == NULL) + ifs = ifaces; + if (ifs == NULL) + return; if (addr->s_addr == INADDR_ANY) return; - TAILQ_FOREACH(ifp, ifaces, next) { + + TAILQ_FOREACH(ifp, ifs, next) { if (strcmp(ifp->name, ifname) == 0) break; } if (ifp == NULL) return; - state = D_STATE(ifp); - if (state == NULL) - return; - - if (type == RTM_DELADDR) { - if (state->new && - state->new->yiaddr == addr->s_addr) - syslog(LOG_INFO, "%s: removing IP address %s/%d", - ifp->name, inet_ntoa(state->lease.addr), - inet_ntocidr(state->lease.net)); - return; + state = IPV4_STATE(ifp); + if (state == NULL) { + ifp->if_data[IF_DATA_IPV4] = malloc(sizeof(*state)); + state = IPV4_STATE(ifp); + if (state == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + return; + } + TAILQ_INIT(&state->addrs); + ap = NULL; + } else + ap = ipv4_findaddr(ifp, addr, net); + if (type == RTM_NEWADDR && ap == NULL) { + ap = malloc(sizeof(*ap)); + if (ap == NULL) { + syslog(LOG_ERR, "%s: %m", __func__); + return; + } + ap->addr.s_addr = addr->s_addr; + ap->net.s_addr = net->s_addr; + if (dst) + ap->dst.s_addr = dst->s_addr; + else + ap->dst.s_addr = INADDR_ANY; + TAILQ_INSERT_TAIL(&state->addrs, ap, next); + } else if (type == RTM_DELADDR) { + if (ap == NULL) + return; + TAILQ_REMOVE(&state->addrs, ap, next); + free(ap); } - if (type != RTM_NEWADDR) - return; - - ifo = ifp->options; - if ((ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)) == 0 || - ifo->req_addr.s_addr != INADDR_ANY) - return; + dhcp_handleifa(type, ifp, addr, net, dst); +} - free(state->old); - state->old = state->new; - state->new = dhcp_message_new(addr, net); - state->dst.s_addr = dst ? dst->s_addr : INADDR_ANY; - if (dst) { - for (i = 1; i < 255; i++) - if (i != DHO_ROUTER && has_option_mask(ifo->dstmask,i)) - dhcp_message_add_addr(state->new, i, *dst); - } - state->reason = "STATIC"; - ipv4_buildroutes(); - script_runreason(ifp, state->reason); - if (ifo->options & DHCPCD_INFORM) { - state->state = DHS_INFORM; - state->xid = dhcp_xid(ifp); - state->lease.server.s_addr = dst ? dst->s_addr : INADDR_ANY; - state->addr = *addr; - state->net = *net; - dhcp_inform(ifp); +void +ipv4_free(struct interface *ifp) +{ + struct ipv4_state *state; + struct ipv4_addr *addr; + + state = IPV4_STATE(ifp); + if (state) { + while ((addr = TAILQ_FIRST(&state->addrs))) { + TAILQ_REMOVE(&state->addrs, addr, next); + free(addr); + } } } diff --git a/ipv4.h b/ipv4.h index eec0000a..ebab2cd3 100644 --- a/ipv4.h +++ b/ipv4.h @@ -41,6 +41,23 @@ struct rt { }; TAILQ_HEAD(rt_head, rt); +struct ipv4_addr { + TAILQ_ENTRY(ipv4_addr) next; + struct in_addr addr; + struct in_addr net; + struct in_addr dst; +}; +TAILQ_HEAD(ipv4_addrhead, ipv4_addr); + +struct ipv4_state { + struct ipv4_addrhead addrs; +}; + +#define IPV4_STATE(ifp) \ + ((struct ipv4_state *)(ifp)->if_data[IF_DATA_IPV4]) +#define IPV4_CSTATE(ifp) \ + ((const struct ipv4_state *)(ifp)->if_data[IF_DATA_IPV4]) + #ifdef INET int ipv4_init(void); int inet_ntocidr(struct in_addr); @@ -52,11 +69,11 @@ void ipv4_buildroutes(void); void ipv4_applyaddr(void *); int ipv4_routedeleted(const struct rt *); -void ipv4_handleifa(int, const char *, - struct in_addr *, struct in_addr *, struct in_addr *); +struct ipv4_addr *ipv4_findaddr(struct interface *, + const struct in_addr *, const struct in_addr *); +void ipv4_handleifa(int, struct if_head *, const char *, + const struct in_addr *, const struct in_addr *, const struct in_addr *); -int ipv4_doaddress(const char *, - struct in_addr *, struct in_addr *, struct in_addr *, int); int if_address(const struct interface *, const struct in_addr *, const struct in_addr *, const struct in_addr *, int); @@ -66,10 +83,6 @@ int if_address(const struct interface *, if_address(iface, addr, net, brd, 2) #define ipv4_deleteaddress(iface, addr, net) \ if_address(iface, addr, net, NULL, -1) -#define ipv4_hasaddress(iface, addr, net) \ - ipv4_doaddress(iface, addr, net, NULL, 0) -#define ipv4_getaddress(iface, addr, net, dst) \ - ipv4_doaddress(iface, addr, net, dst, 1) int if_route(const struct rt *rt, int); #define ipv4_addroute(rt) if_route(rt, 1) @@ -82,6 +95,7 @@ int ipv4_opensocket(struct interface *, int); ssize_t ipv4_sendrawpacket(const struct interface *, int, const void *, ssize_t); ssize_t ipv4_getrawpacket(struct interface *, int, void *, ssize_t, int *); +void ipv4_free(struct interface *); #else #define ipv4_init() -1 #define ipv4_applyaddr(a) {} diff --git a/net.c b/net.c index 898b2221..0720a0f4 100644 --- a/net.c +++ b/net.c @@ -70,6 +70,7 @@ #include "dhcp.h" #include "dhcp6.h" #include "if-options.h" +#include "ipv4.h" #include "ipv6nd.h" #include "net.h" @@ -138,6 +139,7 @@ free_interface(struct interface *ifp) if (ifp == NULL) return; + ipv4_free(ifp); dhcp_free(ifp); ipv6_free(ifp); dhcp6_free(ifp); @@ -223,6 +225,10 @@ discover_interfaces(int argc, char * const *argv) #ifdef __linux__ char ifn[IF_NAMESIZE]; #endif +#ifdef INET + const struct sockaddr_in *addr; + const struct sockaddr_in *net; + const struct sockaddr_in *dst; #ifdef INET6 const struct sockaddr_in6 *sin6; int ifa_flags; @@ -441,11 +447,29 @@ discover_interfaces(int argc, char * const *argv) TAILQ_INSERT_TAIL(ifs, ifp, next); } -#ifdef INET6 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { - if (ifa->ifa_addr != NULL && - ifa->ifa_addr->sa_family == AF_INET6) - { + if (ifa->ifa_addr == NULL) + continue; + switch(ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + addr = (const struct sockaddr_in *) + (void *)ifa->ifa_addr; + net = (const struct sockaddr_in *) + (void *)ifa->ifa_netmask; + if (ifa->ifa_flags & IFF_POINTOPOINT) + dst = (const struct sockaddr_in *) + (void *)ifa->ifa_dstaddr; + else + dst = NULL; + ipv4_handleifa(RTM_NEWADDR, ifs, ifa->ifa_name, + &addr->sin_addr, + &net->sin_addr, + dst ? &dst->sin_addr : NULL); + break; +#endif +#ifdef INET6 + case AF_INET6: sin6 = (const struct sockaddr_in6 *) (void *)ifa->ifa_addr; ifa_flags = in6_addr_flags(ifa->ifa_name, @@ -454,6 +478,8 @@ discover_interfaces(int argc, char * const *argv) ipv6_handleifa(RTM_NEWADDR, ifs, ifa->ifa_name, &sin6->sin6_addr, ifa_flags); + break; +#endif } } #endif