Module Name:    src
Committed By:   tteras
Date:           Fri Dec  3 09:46:24 UTC 2010

Modified Files:
        src/crypto/dist/ipsec-tools/src/racoon: grabmyaddr.c

Log Message:
Netlink deletion notification does not guarentee actual address deletion:
it might still exist on some other interface. Make sure we do not unbind
unless the address is really gone.


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 \
    src/crypto/dist/ipsec-tools/src/racoon/grabmyaddr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/crypto/dist/ipsec-tools/src/racoon/grabmyaddr.c
diff -u src/crypto/dist/ipsec-tools/src/racoon/grabmyaddr.c:1.26 src/crypto/dist/ipsec-tools/src/racoon/grabmyaddr.c:1.27
--- src/crypto/dist/ipsec-tools/src/racoon/grabmyaddr.c:1.26	Fri Oct 22 06:26:26 2010
+++ src/crypto/dist/ipsec-tools/src/racoon/grabmyaddr.c	Fri Dec  3 09:46:24 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: grabmyaddr.c,v 1.26 2010/10/22 06:26:26 tteras Exp $	*/
+/*	$NetBSD: grabmyaddr.c,v 1.27 2010/12/03 09:46:24 tteras Exp $	*/
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  * Copyright (C) 2008 Timo Teras <timo.te...@iki.fi>.
@@ -319,6 +319,11 @@
 
 #if defined(USE_NETLINK)
 
+static int netlink_fd = -1;
+
+#define NLMSG_TAIL(nmsg) \
+	((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+
 static void
 parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
 {
@@ -331,6 +336,24 @@
 }
 
 static int
+netlink_add_rtattr_l(struct nlmsghdr *n, int maxlen, int type,
+		     const void *data, int alen)
+{
+	int len = RTA_LENGTH(alen);
+	struct rtattr *rta;
+
+	if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen)
+		return FALSE;
+
+	rta = NLMSG_TAIL(n);
+	rta->rta_type = type;
+	rta->rta_len = len;
+	memcpy(RTA_DATA(rta), data, alen);
+	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
+	return TRUE;
+}
+
+static int
 netlink_enumerate(fd, family, type)
 	int fd;
 	int family;
@@ -410,6 +433,42 @@
 #endif
 
 static int
+netlink_route_is_local(int family, const unsigned char *addr, size_t addr_len)
+{
+	struct {
+		struct nlmsghdr n;
+		struct rtmsg    r;
+		char            buf[1024];
+	} req;
+	struct rtmsg *r = NLMSG_DATA(&req.n);
+	struct rtattr *rta[RTA_MAX+1];
+	struct sockaddr_nl nladdr;
+	ssize_t rlen;
+
+	memset(&req, 0, sizeof(req));
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = RTM_GETROUTE;
+	req.r.rtm_family = family;
+	netlink_add_rtattr_l(&req.n, sizeof(req), RTA_DST,
+			     addr, addr_len);
+	req.r.rtm_dst_len = addr_len * 8;
+
+	memset(&nladdr, 0, sizeof(nladdr));
+	nladdr.nl_family = AF_NETLINK;
+
+	if (sendto(netlink_fd, &req, sizeof(req), 0,
+		   (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0)
+		return 0;
+	rlen = recv(netlink_fd, &req, sizeof(req), 0);
+	if (rlen < 0)
+		return 0;
+
+	return  req.n.nlmsg_type == RTM_NEWROUTE &&
+		req.r.rtm_type == RTN_LOCAL;
+}
+
+static int
 netlink_process_route(struct nlmsghdr *h)
 {
 	struct sockaddr_storage addr;
@@ -455,6 +514,18 @@
 		return 0;
 	}
 
+	/* If local route was deleted, check if there is still local
+	 * route for the same IP on another interface */
+	if (h->nlmsg_type == RTM_DELROUTE &&
+	    netlink_route_is_local(rtm->rtm_family,
+				   RTA_DATA(rta[RTA_DST]),
+				   RTA_PAYLOAD(rta[RTA_DST]))) {
+		plog(LLV_DEBUG, LOCATION, NULL,
+			"Netlink: not deleting %s yet, it exists still\n",
+			saddrwop2str((struct sockaddr *) &addr));
+		return 0;
+	}
+
 	netlink_add_del_address(h->nlmsg_type == RTM_NEWROUTE,
 				(struct sockaddr *) &addr);
 	return 0;
@@ -518,9 +589,8 @@
 }
 
 static int
-kernel_open_socket()
+netlink_open_socket()
 {
-	struct sockaddr_nl nl;
 	int fd;
 
 	fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
@@ -535,6 +605,25 @@
 		plog(LLV_WARNING, LOCATION, NULL,
 		     "failed to put socket in non-blocking mode\n");
 
+	return fd;
+}
+
+static int
+kernel_open_socket()
+{
+	struct sockaddr_nl nl;
+	int fd;
+
+	if (netlink_fd < 0) {
+		netlink_fd = netlink_open_socket();
+		if (netlink_fd < 0)
+			return -1;
+	}
+
+	fd = netlink_open_socket();
+	if (fd < 0)
+		return fd;
+
 	/* We monitor IPv4 addresses using RTMGRP_IPV4_ROUTE group
 	 * the get the RTN_LOCAL routes which are automatically added
 	 * by kernel. This is because:

Reply via email to