changeset 977:51d5c78d622b draft

Ensure that routes go via the correct interface and set netmask correctly.
author Roy Marples <roy@marples.name>
date Sun, 14 Sep 2008 09:07:34 +0000
parents aa7187c07fce
children 3a250c33e88d
files if-bsd.c
diffstat 1 files changed, 29 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/if-bsd.c	Sun Sep 14 09:06:22 2008 +0000
+++ b/if-bsd.c	Sun Sep 14 09:07:34 2008 +0000
@@ -116,9 +116,9 @@
 	struct rtm 
 	{
 		struct rt_msghdr hdr;
-		char buffer[sizeof(su) * 5];
+		char buffer[sizeof(su) * 4];
 	} rtm;
-	char *bp = rtm.buffer;
+	char *bp = rtm.buffer, *p;
 	size_t l;
 	int retval = 0;
 
@@ -137,57 +137,48 @@
 	rtm.hdr.rtm_flags = RTF_UP | RTF_STATIC;
 	if (netmask->s_addr == INADDR_BROADCAST)
 		rtm.hdr.rtm_flags |= RTF_HOST;
+	else
+		rtm.hdr.rtm_flags |= RTF_GATEWAY;
 
 	/* This order is important */
-	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
-	rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA;
+	rtm.hdr.rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
+	if (gateway->s_addr != INADDR_ANY)
+		rtm.hdr.rtm_addrs |= RTA_GATEWAY;
 
+#define ADDSU(_su) \
+	l = SA_SIZE(&(_su.sa)); \
+	memcpy(bp, &(_su), l); \
+	bp += l;
 #define ADDADDR(_addr) \
 	memset (&su, 0, sizeof(su)); \
 	su.sin.sin_family = AF_INET; \
 	su.sin.sin_len = sizeof(su.sin); \
 	memcpy (&su.sin.sin_addr, _addr, sizeof(su.sin.sin_addr)); \
-	l = SA_SIZE (&(su.sa)); \
-	memcpy (bp, &(su), l); \
-	bp += l;
+	ADDSU(su);
 
 	ADDADDR(destination);
+	if (gateway->s_addr != INADDR_ANY)
+		ADDADDR(gateway);
 
-	if (gateway->s_addr == INADDR_ANY) {
-		/* Make us a link layer socket */
-		memset(&su, 0, sizeof(su));
-		su.sdl.sdl_len = sizeof(su.sdl);
-		su.sdl.sdl_family = AF_LINK;
-		su.sdl.sdl_nlen = strlen(iface->name);
-		memcpy(&su.sdl.sdl_data, iface->name, (size_t)su.sdl.sdl_nlen);
-		su.sdl.sdl_alen = iface->hwlen;
-		memcpy(((unsigned char *)&su.sdl.sdl_data) + su.sdl.sdl_nlen,
-		       iface->hwaddr, (size_t)su.sdl.sdl_alen);
+	/* Ensure that netmask is set correctly */
+	memset (&su, 0, sizeof(su));
+	su.sin.sin_family = AF_INET;
+	su.sin.sin_len = sizeof(su.sin);
+	memcpy (&su.sin.sin_addr, &netmask->s_addr, sizeof(su.sin.sin_addr));
+	p = su.sa.sa_len + (char *)&su;
+	for (su.sa.sa_len = 0; p > (char *)&su; )
+		if (*--p != 0) {
+			su.sa.sa_len = 1 + p - (char *)&su;
+			break;
+		}
+	ADDSU(su);
 
-		l = SA_SIZE(&(su.sa));
-		memcpy(bp, &su, l);
-		bp += l;
-	} else {
-		rtm.hdr.rtm_flags |= RTF_GATEWAY;
-		ADDADDR(gateway);
-	}
-
-	ADDADDR(netmask);
 	/* Make us a link layer socket for IFP */
 	memset(&su, 0, sizeof(su));
+	su.sdl.sdl_family = AF_LINK;
 	su.sdl.sdl_len = sizeof(su.sdl);
-	su.sdl.sdl_family = AF_LINK;
-	su.sdl.sdl_nlen = strlen(iface->name);
-	memcpy(&su.sdl.sdl_data, iface->name, (size_t)su.sdl.sdl_nlen);
-	su.sdl.sdl_alen = iface->hwlen;
-	memcpy(((unsigned char *)&su.sdl.sdl_data) + su.sdl.sdl_nlen,
-	       iface->hwaddr, (size_t)su.sdl.sdl_alen);
-
-	l = SA_SIZE(&(su.sa));
-	memcpy(bp, &su, l);
-	bp += l;
-	ADDADDR(&iface->addr); /* IFA */
-#undef ADDADDR
+	link_addr(iface->name, &su.sdl);
+	ADDSU(su);
 
 	rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
 	if (write(s, &rtm, l) == -1)