On Mon, Feb 09, 2009 at 11:43:10AM +0100, Claudio Jeker wrote:
> On Mon, Feb 09, 2009 at 02:22:08AM -0800, patrick keshishian wrote:
> > On Mon, Feb 9, 2009 at 12:53 AM, Claudio Jeker <[email protected]> 
> > wrote:
> > >> On a hunch, I tried a 64bit and a 32 bit machine with 1 prefix each.
> > >> The 32bit machine adds routes to the kernel without complaint.  The
> > >> 64bit machine complained with send_rtmsg....
> > >>
> > >
> > > Arrg. IPv6 is once again broken by design. For some ridiculous reason
> > > struct sockaddr_in6's size is 28 bytes. So IPv6 fucks up alignment on 64 
> > > bit
> > > archs. All hail link local addressing and all the crappy workarounds
> > > needed for it.
> > 
> > Maybe it is too late for me to be thinking about this ... but could
> > you explain the diff below? Unless I'm missing something obvious, it
> > looks like it changes behavior for non-64bit archs as well.
> > 
> 
> Hmm. I think your right. I think a different approach would be better.
> Will cook up something later today.
> 

I think this is better. Just compile tested and no real time to test until
later today.

-- 
:wq Claudio

Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v
retrieving revision 1.164
diff -u -p -r1.164 kroute.c
--- kroute.c    9 Feb 2009 08:20:11 -0000       1.164
+++ kroute.c    9 Feb 2009 12:36:18 -0000
@@ -1813,8 +1813,8 @@ inet6applymask(struct in6_addr *dest, co
                dest->s6_addr[i] = src->s6_addr[i] & mask.s6_addr[i];
 }
 
-#define        ROUNDUP(a, size)        \
-    (((a) & ((size) - 1)) ? (1 + ((a) | ((size) - 1))) : (a))
+#define        ROUNDUP(a)      \
+    (((a) & ((sizeof(long)) - 1)) ? (1 + ((a) | ((sizeof(long)) - 1))) : (a))
 
 void
 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
@@ -1825,7 +1825,7 @@ get_rtaddrs(int addrs, struct sockaddr *
                if (addrs & (1 << i)) {
                        rti_info[i] = sa;
                        sa = (struct sockaddr *)((char *)(sa) +
-                           ROUNDUP(sa->sa_len, sizeof(long)));
+                           ROUNDUP(sa->sa_len));
                } else
                        rti_info[i] = NULL;
        }
@@ -2059,9 +2059,10 @@ send_rt6msg(int fd, int action, struct k
 {
        struct iovec            iov[5];
        struct rt_msghdr        hdr;
-       struct sockaddr_in6     prefix;
-       struct sockaddr_in6     nexthop;
-       struct sockaddr_in6     mask;
+       struct pad {
+               struct sockaddr_in6     addr;
+               char                    pad[sizeof(long)];
+       } prefix, nexthop, mask;
        struct sockaddr_rtlabel label;
        int                     iovcnt = 0;
 
@@ -2086,43 +2087,44 @@ send_rt6msg(int fd, int action, struct k
        iov[iovcnt++].iov_len = sizeof(hdr);
 
        bzero(&prefix, sizeof(prefix));
-       prefix.sin6_len = sizeof(prefix);
-       prefix.sin6_family = AF_INET6;
-       memcpy(&prefix.sin6_addr, &kroute->prefix, sizeof(struct in6_addr));
+       prefix.addr.sin6_len = sizeof(struct sockaddr_in6);
+       prefix.addr.sin6_family = AF_INET6;
+       memcpy(&prefix.addr.sin6_addr, &kroute->prefix,
+           sizeof(struct in6_addr));
        /* XXX scope does not matter or? */
        /* adjust header */
        hdr.rtm_addrs |= RTA_DST;
-       hdr.rtm_msglen += sizeof(prefix);
+       hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6));
        /* adjust iovec */
        iov[iovcnt].iov_base = &prefix;
-       iov[iovcnt++].iov_len = sizeof(prefix);
+       iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6));
 
        if (memcmp(&kroute->nexthop, &in6addr_any, sizeof(struct in6_addr))) {
                bzero(&nexthop, sizeof(nexthop));
-               nexthop.sin6_len = sizeof(nexthop);
-               nexthop.sin6_family = AF_INET6;
-               memcpy(&nexthop.sin6_addr, &kroute->nexthop,
+               nexthop.addr.sin6_len = sizeof(struct sockaddr_in6);
+               nexthop.addr.sin6_family = AF_INET6;
+               memcpy(&nexthop.addr.sin6_addr, &kroute->nexthop,
                    sizeof(struct in6_addr));
                /* adjust header */
                hdr.rtm_flags |= RTF_GATEWAY;
                hdr.rtm_addrs |= RTA_GATEWAY;
-               hdr.rtm_msglen += sizeof(nexthop);
+               hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6));
                /* adjust iovec */
                iov[iovcnt].iov_base = &nexthop;
-               iov[iovcnt++].iov_len = sizeof(nexthop);
+               iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6));
        }
 
        bzero(&mask, sizeof(mask));
-       mask.sin6_len = sizeof(mask);
-       mask.sin6_family = AF_INET6;
-       memcpy(&mask.sin6_addr, prefixlen2mask6(kroute->prefixlen),
+       mask.addr.sin6_len = sizeof(struct sockaddr_in6);
+       mask.addr.sin6_family = AF_INET6;
+       memcpy(&mask.addr.sin6_addr, prefixlen2mask6(kroute->prefixlen),
            sizeof(struct in6_addr));
        /* adjust header */
        hdr.rtm_addrs |= RTA_NETMASK;
-       hdr.rtm_msglen += sizeof(mask);
+       hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6));
        /* adjust iovec */
        iov[iovcnt].iov_base = &mask;
-       iov[iovcnt++].iov_len = sizeof(mask);
+       iov[iovcnt++].iov_len = ROUNDUP(sizeof(struct sockaddr_in6));
 
        if (kroute->labelid) {
                bzero(&label, sizeof(label));

Reply via email to