kernel-pfroute: struct sockaddr arguments are 4 byte aligned
authorTobias Brunner <tobias@strongswan.org>
Tue, 18 Jun 2013 14:55:03 +0000 (16:55 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 21 Jun 2013 15:03:22 +0000 (17:03 +0200)
This was noticed on Mac OS X where, if the default route is returned,
RTA_NETMASK has sa_len set to 0, but skipping zero bytes to read the
next address makes no sense, of course.  Using 0 for sa_len seems
a bit strange, in particular, because struct sockaddr has by definition
a minimum length of 16 bytes.  But it seems FreeBSD actually does the
same.

src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c

index acb21d3..0dfb295 100644 (file)
 #error Cannot compile this plugin on systems where 'struct sockaddr' has no sa_len member.
 #endif
 
+/** properly align sockaddrs */
+#define SA_ALIGN 4
+#define SA_LEN(len) ((len) > 0 ? (((len)+SA_ALIGN-1) & ~(SA_ALIGN-1)) : SA_ALIGN)
+
 /** delay before firing roam events (ms) */
 #define ROAM_DELAY 100
 
@@ -344,8 +348,8 @@ METHOD(enumerator_t, rt_enumerate, bool,
                        this->types &= ~type;
                        *addr = this->addr;
                        *xtype = i;
-                       this->remaining -= this->addr->sa_len;
-                       this->addr = (void*)this->addr + this->addr->sa_len;
+                       this->remaining -= SA_LEN(this->addr->sa_len);
+                       this->addr = (char*)this->addr + SA_LEN(this->addr->sa_len);
                        return TRUE;
                }
        }
@@ -941,7 +945,7 @@ static void add_rt_addr(struct rt_msghdr *hdr, int type, host_t *addr)
 
                len = *addr->get_sockaddr_len(addr);
                memcpy((char*)hdr + hdr->rtm_msglen, addr->get_sockaddr(addr), len);
-               hdr->rtm_msglen += len;
+               hdr->rtm_msglen += SA_LEN(len);
                hdr->rtm_addrs |= type;
        }
 }
@@ -976,7 +980,7 @@ static void add_rt_ifname(struct rt_msghdr *hdr, int type, char *name)
        {
                memcpy(sdl.sdl_data, name, sdl.sdl_nlen);
                memcpy((char*)hdr + hdr->rtm_msglen, &sdl, sdl.sdl_len);
-               hdr->rtm_msglen += sdl.sdl_len;
+               hdr->rtm_msglen += SA_LEN(sdl.sdl_len);
                hdr->rtm_addrs |= type;
        }
 }