diff options
author | David Lamparter <equinox@opensourcerouting.org> | 2012-09-26 14:52:39 +0200 |
---|---|---|
committer | David Lamparter <equinox@opensourcerouting.org> | 2013-01-16 01:45:57 +0100 |
commit | ca3ccd8748434719e4670ce812d1310013fad518 (patch) | |
tree | 3fae89070206bc47704a456219350c34b5f8ea54 /zebra | |
parent | 8d083b9ec5bb0375ebb6d8b2b05c848febd92cb5 (diff) |
zebra: fix sockaddr_dl length assumptions (BZ#737)
Quagga makes bad assumptions about sockaddr_dl (on NetBSD, but possibly
on other systems as well). Particularly, sizeof(struct sockaddr_dl)
returns a size that does not include the full sdl_data field, leading to
not enough data being copied. This breaks IPv6 RAs in particular, as
a broken mac address from sockaddr_dl will be included in the packets.
From: Matthias-Christian Ott <ott@mirix.org>
Tested-by: Uwe Toenjes <6bone@6bone.informatik.uni-leipzig.de>
[further simplified + more comments]
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/kernel_socket.c | 15 | ||||
-rw-r--r-- | zebra/zserv.c | 2 |
2 files changed, 13 insertions, 4 deletions
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index cde36bd0..73fabd4c 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -477,13 +477,22 @@ ifm_read (struct if_msghdr *ifm) /* * XXX sockaddr_dl contents can be larger than the structure - * definition, so the user of the stored structure must be - * careful not to read off the end. - * + * definition. There are 2 big families here: + * - BSD has sdl_len + sdl_data[16] + overruns sdl_data + * we MUST use sdl_len here or we'll truncate data. + * - Solaris has no sdl_len, but sdl_data[244] + * presumably, it's not going to run past that, so sizeof() + * is fine here. * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid */ if (ifnlen) + { +#ifdef HAVE_STRUCT_SOCKADDR_DL_SDL_LEN + memcpy (&ifp->sdl, sdl, sdl->sdl_len); +#else memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl)); +#endif /* HAVE_STRUCT_SOCKADDR_DL_SDL_LEN */ + } if_add_update (ifp); } diff --git a/zebra/zserv.c b/zebra/zserv.c index 9e47f23f..cb8dbcb3 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -153,7 +153,7 @@ zserv_encode_interface (struct stream *s, struct interface *ifp) stream_putl (s, ifp->mtu6); stream_putl (s, ifp->bandwidth); #ifdef HAVE_STRUCT_SOCKADDR_DL - stream_put (s, &ifp->sdl, sizeof (ifp->sdl)); + stream_put (s, &ifp->sdl, sizeof (ifp->sdl_storage)); #else stream_putl (s, ifp->hw_addr_len); if (ifp->hw_addr_len) |