[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