summaryrefslogtreecommitdiffstats
path: root/net.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2013-09-06 09:38:24 +0000
committerRoy Marples <roy@marples.name>2013-09-06 09:38:24 +0000
commit27f61373d14c2e44b06f6f2ce26baf899ad8c283 (patch)
tree28ad48c84866b297888e026ed08d14bd1e85176e /net.c
parentef0f1a1ce3b58afd8b45b689c369b42a5d4c9206 (diff)
downloaddhcpcd-27f61373d14c2e44b06f6f2ce26baf899ad8c283.tar.xz
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.
Diffstat (limited to 'net.c')
-rw-r--r--net.c34
1 files changed, 30 insertions, 4 deletions
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