[radvd-devel-l] [PATCH 1/2] RADVD: Don't accept inappropriate RS

YOSHIFUJI Hideaki / 吉藤英明 yoshfuji at linux-ipv6.org
Thu Dec 22 11:36:09 EST 2005


Hello.

Current radvd happens to accept inappropriate RSs, wich as
one with zero-length option etc.
We need to check options no matter what the source address is.

This is required to pass the IPv6 Ready Logo Phase-2 IPv6 Core
Protocols Self Test.

Related Tests: Phase-2 Router ND #8, #9, #119, #120

Regards,

Index: process.c
===================================================================
RCS file: /work/cvsroot/radvd/process.c,v
retrieving revision 1.11
diff -u -r1.11 process.c
--- process.c	18 Oct 2005 19:17:29 -0000	1.11
+++ process.c	22 Dec 2005 15:26:22 -0000
@@ -18,12 +18,12 @@
 #include <includes.h>
 #include <radvd.h>
 
-static void process_rs(int, struct Interface *, struct sockaddr_in6 *);
+static void process_rs(int, struct Interface *, unsigned char *msg,
+		       int len, struct sockaddr_in6 *);
 static void process_ra(struct Interface *, unsigned char *msg, int len,
 	struct sockaddr_in6 *);
 static int  addr_match(struct in6_addr *a1, struct in6_addr *a2,
 	int prefixlen);
-static int rs_has_srclladdr(unsigned char *, int);
 
 void
 process(int sock, struct Interface *ifacel, unsigned char *msg, int len, 
@@ -84,14 +84,6 @@
 				len);
 			return;
 		}
-		
-		if (IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
-		    rs_has_srclladdr(msg, len))
-		{
-			flog(LOG_WARNING, "received icmpv6 RS packet with unspecified source address and there is a lladdr option"); 
-			return;
-		}
-				
 	}			
 
 	if (icmph->icmp6_code != 0)
@@ -138,7 +130,7 @@
 
 	if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
 	{
-		process_rs(sock, iface, addr);
+		process_rs(sock, iface, msg, len, addr);
 	}
 	else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
 	{
@@ -147,11 +139,51 @@
 }
 
 static void
-process_rs(int sock, struct Interface *iface, struct sockaddr_in6 *addr)
+process_rs(int sock, struct Interface *iface, unsigned char *msg, int len,
+	struct sockaddr_in6 *addr)
 {
 	double delay;
 	double next;
 	struct timeval tv;
+	uint8_t *opt_str;
+
+	/* validation */
+	len -= sizeof(struct nd_router_solicit);
+
+	opt_str = (uint8_t *)(msg + sizeof(struct nd_router_solicit));
+
+	while (len > 0)
+	{
+		int optlen;
+
+		if (len < 2)
+		{
+			flog(LOG_WARNING, "trailing garbage in RS");
+			return;
+		}
+
+		optlen = (opt_str[1] << 3);
+
+		if (optlen == 0)
+		{
+			flog(LOG_WARNING, "zero length option in RS");
+			return;
+		}
+		else if (optlen > len)
+		{
+			flog(LOG_WARNING, "option length greater than total length in RS");
+			return;
+		}
+
+		if (*opt_str == ND_OPT_SOURCE_LINKADDR &&
+		    IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr)) {
+			flog(LOG_WARNING, "received icmpv6 RS packet with unspecified source address and there is a lladdr option"); 
+			return;
+		}
+
+		len -= optlen;
+		opt_str += optlen;
+	}
 
 	gettimeofday(&tv, NULL);
 
@@ -377,52 +409,3 @@
 	return 1;
 }
 
-static int
-rs_has_srclladdr(unsigned char *msg, int len)
-{
-	uint8_t *opt_str;
-	int	has_lladdr = 0;
-
-	len -= sizeof(struct nd_router_solicit);
-
-	if (len == 0)
-	{		/* no option */
-		return 0;
-	}
-
-	opt_str = (uint8_t *)(msg + sizeof(struct nd_router_solicit));
-
-	while (len > 0)
-	{
-		int optlen;
-
-		if (len < 2)
-		{
-			flog(LOG_WARNING, "trailing garbage in RS");
-			break;
-		}
-
-		optlen = (opt_str[1] << 3);
-
-		if (optlen == 0)
-		{
-			flog(LOG_WARNING, "zero length option in RS");
-			break;
-		}
-		else if (optlen > len)
-		{
-			flog(LOG_WARNING, "option length greater than total length in RS");
-			break;
-		}
-
-		if (*opt_str == ND_OPT_SOURCE_LINKADDR)
-		{
-			has_lladdr = 1;
-		}
-
-		len -= optlen;
-		opt_str += optlen;
-	}
-
-	return has_lladdr;
-}



More information about the radvd-devel-l mailing list