summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2008-10-21 13:32:57 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2008-10-21 13:32:57 +0000
commite515147e7a8a7d5cd8b8272a9226b796fd84ca36 (patch)
tree3620ae9b516ba8b62d17d3d187c85d70a37318f2
parent0b52d38672cff20f0f23c8e9e4946bc189b4d9f5 (diff)
do not listen on tentative (during DAD), duplicated (after DAD) or
detached addresses. bind(2) will not allow this. ok hshoexer, fries
-rw-r--r--sbin/isakmpd/virtual.c35
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) {