summaryrefslogtreecommitdiff
path: root/zebra/rtadv.c
diff options
context:
space:
mode:
authorDavid Ward <david.ward@ll.mit.edu>2009-08-31 10:42:06 -0400
committerPaul Jakma <paul@quagga.net>2009-09-01 19:03:01 +0100
commit50adf7832004191cdaf5a908bd9a9c0b2373e993 (patch)
tree726d32636baa6c718e3fdab5a48ffae870c7b048 /zebra/rtadv.c
parent3849ce4e25281d11537ebd0db5e2fa2a7c356b33 (diff)
zebra: Fix router advertisements for non-Ethernet link layer addresses
* rtadv.c: round up when calculating the link-layer address option length; add padding to the option if needed to end on an octet boundary
Diffstat (limited to 'zebra/rtadv.c')
-rw-r--r--zebra/rtadv.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index ff96648a..0bcdafb0 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -292,19 +292,33 @@ rtadv_send_packet (int sock, struct interface *ifp)
if (sdl != NULL && sdl->sdl_alen != 0)
{
buf[len++] = ND_OPT_SOURCE_LINKADDR;
- buf[len++] = (sdl->sdl_alen + 2) >> 3;
+
+ /* Option length should be rounded up to next octet if
+ the link address does not end on an octet boundary. */
+ buf[len++] = (sdl->sdl_alen + 9) >> 3;
memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
len += sdl->sdl_alen;
+
+ /* Pad option to end on an octet boundary. */
+ memset (buf + len, 0, -(sdl->sdl_alen + 2) & 0x7);
+ len += -(sdl->sdl_alen + 2) & 0x7;
}
#else
if (ifp->hw_addr_len != 0)
{
buf[len++] = ND_OPT_SOURCE_LINKADDR;
- buf[len++] = (ifp->hw_addr_len + 2) >> 3;
+
+ /* Option length should be rounded up to next octet if
+ the link address does not end on an octet boundary. */
+ buf[len++] = (ifp->hw_addr_len + 9) >> 3;
memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
len += ifp->hw_addr_len;
+
+ /* Pad option to end on an octet boundary. */
+ memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
+ len += -(ifp->hw_addr_len + 2) & 0x7;
}
#endif /* HAVE_STRUCT_SOCKADDR_DL */