diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2008-10-21 13:32:57 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2008-10-21 13:32:57 +0000 |
commit | e515147e7a8a7d5cd8b8272a9226b796fd84ca36 (patch) | |
tree | 3620ae9b516ba8b62d17d3d187c85d70a37318f2 /sbin | |
parent | 0b52d38672cff20f0f23c8e9e4946bc189b4d9f5 (diff) |
do not listen on tentative (during DAD), duplicated (after DAD) or
detached addresses. bind(2) will not allow this. ok hshoexer, fries
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/isakmpd/virtual.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/sbin/isakmpd/virtual.c b/sbin/isakmpd/virtual.c index 1b681edc4bc..8d60cf24089 100644 --- a/sbin/isakmpd/virtual.c +++ b/sbin/isakmpd/virtual.c @@ -1,4 +1,4 @@ -/* $OpenBSD: virtual.c,v 1.28 2007/04/16 13:01:39 moritz Exp $ */ +/* $OpenBSD: virtual.c,v 1.29 2008/10/21 13:32:56 markus Exp $ */ /* * Copyright (c) 2004 Håkan Olsson. All rights reserved. @@ -30,6 +30,7 @@ #include <sys/sockio.h> #include <net/if.h> #include <netinet/in.h> +#include <netinet6/in6_var.h> #include <arpa/inet.h> #include <ctype.h> #include <limits.h> @@ -329,6 +330,7 @@ virtual_bind_if(char *ifname, struct sockaddr *if_addr, void *arg) struct sockaddr *addr; struct transport *t; struct ifreq flags_ifr; + struct in6_ifreq flags_ifr6; char *addr_str; int s, error; @@ -407,9 +409,36 @@ virtual_bind_if(char *ifname, struct sockaddr *if_addr, void *arg) close(s); return -1; } - close(s); - if (!(flags_ifr.ifr_flags & IFF_UP)) + if (!(flags_ifr.ifr_flags & IFF_UP)) { + close(s); return 0; + } + /* Also skip tentative addresses during DAD since bind(2) would fail. */ + if (if_addr->sa_family == AF_INET6) { + memset(&flags_ifr6, 0, sizeof(flags_ifr6)); + strlcpy(flags_ifr6.ifr_name, ifname, sizeof flags_ifr6.ifr_name); + flags_ifr6.ifr_addr = *(struct sockaddr_in6 *)if_addr; + if (ioctl(s, SIOCGIFAFLAG_IN6, (caddr_t)&flags_ifr6) < 0) { + log_error("virtual_bind_if: " + "ioctl (%d, SIOCGIFAFLAG_IN6, ...) failed", s); + close(s); + return 0; + } + if (flags_ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_ANYCAST| + IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED|IN6_IFF_DETACHED)) { + error = sockaddr2text(if_addr, &addr_str, 0); + log_print("virtual_bind_if: " + "IPv6 address %s not ready (flags 0x%x)", + error ? "unknown" : addr_str, + flags_ifr6.ifr_ifru.ifru_flags6); + /* XXX schedule an interface rescan */ + if (!error) + free(addr_str); + close(s); + return 0; + } + } + close(s); /* Set the port number to zero. */ switch (if_addr->sa_family) { |