]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra/kernel_socket.c: Use platform alignment
authorGreg Troxel <gdt@ir.bbn.com>
Tue, 2 Dec 2014 19:51:49 +0000 (14:51 -0500)
committerDaniel Walton <dwalton@cumulusnetworks.com>
Thu, 26 May 2016 15:24:50 +0000 (15:24 +0000)
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)

zebra/kernel_socket.c

index a8ce4d07df46b05eadb658e92addc17446201094..5d5206a2f92bc0f37c1b202a8668b01ae058ca98 100644 (file)
 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 <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__
-#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.