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));