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)
This commit is contained in:
Greg Troxel 2014-12-02 14:51:49 -05:00 committed by Daniel Walton
parent 9b97a19b10
commit cfa0ed0949

View File

@ -43,22 +43,52 @@
extern struct zebra_privs_t zserv_privs; extern struct zebra_privs_t zserv_privs;
/* /*
* Given a sockaddr length, round it up to include pad bytes following * Historically, the BSD routing socket has aligned data following a
* it. Assumes the kernel pads to sizeof(long). * 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 * Alignment of zero-sized sockaddrs is nonsensical, but historically
* length anyway (< sizeof (struct sockaddr)), so this shouldn't * BSD defines RT_ROUNDUP(0) to be the alignment interval (rather than
* matter. * 0). We follow this practice without questioning it, but it is a
* On OS X, both 32, 64bit syatems align on 4 byte boundary * bug if quagga calls ROUNDUP with 0.
*/ */
/*
* Because of these varying conventions, the only sane approach is for
* the <net/route.h> 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__ #ifdef __APPLE__
#define ROUNDUP(a) \ #define ROUNDUP_TYPE long
((a) > 0 ? (1 + (((a) - 1) | (sizeof(int) - 1))) : sizeof(int))
#else #else
#define ROUNDUP(a) \ #define ROUNDUP_TYPE int
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#endif #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 * Given a pointer (sockaddr or void *), return the number of bytes
* taken up by the sockaddr and any padding needed for alignment. * taken up by the sockaddr and any padding needed for alignment.