From: Greg Troxel Date: Tue, 2 Dec 2014 19:51:49 +0000 (-0500) Subject: zebra/kernel_socket.c: Use platform alignment X-Git-Tag: frr-2.0-rc1~776 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=cfa0ed0949284a978e6d1710de66cf40474594c9;p=matthieu%2Ffrr.git zebra/kernel_socket.c: Use platform alignment Use the platform-provided RT_ROUNDUP macro to align sockaddrs on the routing socket, rather than using hard-coded assumptions about alignment. Emit a warning if the OS doesn't define alignment macros. Resolves failure of ripngd on NetBSD 6 i386, which changed alignment to uint64_t from long. (cherry picked from commit 273b1bd341afff86ba571e0be296d88dba627136) --- diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index a8ce4d07df..5d5206a2f9 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -43,22 +43,52 @@ extern struct zebra_privs_t zserv_privs; /* - * Given a sockaddr length, round it up to include pad bytes following - * it. Assumes the kernel pads to sizeof(long). + * Historically, the BSD routing socket has aligned data following a + * struct sockaddr to sizeof(long), which was 4 bytes on some + * platforms, and 8 bytes on others. NetBSD 6 changed the routing + * socket to align to sizeof(uint64_t), which is 8 bytes. OS X + * appears to align to sizeof(int), which is 4 bytes. * - * XXX: why is ROUNDUP(0) sizeof(long)? 0 is an illegal sockaddr - * length anyway (< sizeof (struct sockaddr)), so this shouldn't - * matter. - * On OS X, both 32, 64bit syatems align on 4 byte boundary + * Alignment of zero-sized sockaddrs is nonsensical, but historically + * BSD defines RT_ROUNDUP(0) to be the alignment interval (rather than + * 0). We follow this practice without questioning it, but it is a + * bug if quagga calls ROUNDUP with 0. */ + +/* + * Because of these varying conventions, the only sane approach is for + * the header to define some flavor of ROUNDUP macro. + */ +#if defined(RT_ROUNDUP) +#define ROUNDUP(a) RT_ROUNDUP(a) +#endif /* defined(RT_ROUNDUP) */ + +/* + * If ROUNDUP has not yet been defined in terms of platform-provided + * defines, attempt to cope with heuristics. + */ +#if !defined(ROUNDUP) + +/* + * It's a bug for a platform not to define rounding/alignment for + * sockaddrs on the routing socket. This warning really is + * intentional, to provoke filing bug reports with operating systems + * that don't define RT_ROUNDUP or equivalent. + */ +#warning "net/route.h does not define RT_ROUNDUP; making unwarranted assumptions!" + +/* OS X (Xcode as of 2014-12) is known not to define RT_ROUNDUP */ #ifdef __APPLE__ -#define ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(int) - 1))) : sizeof(int)) +#define ROUNDUP_TYPE long #else -#define ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ROUNDUP_TYPE int #endif +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(ROUNDUP_TYPE) - 1))) : sizeof(ROUNDUP_TYPE)) + +#endif /* defined(ROUNDUP) */ + /* * Given a pointer (sockaddr or void *), return the number of bytes * taken up by the sockaddr and any padding needed for alignment.