From 05feabc6c37420e3bd1860eed19978d4a5695ee2 Mon Sep 17 00:00:00 2001 From: Claudio Jeker Date: Tue, 23 Feb 2010 16:22:58 +0000 Subject: This is a total dejavu of bgpd/kroute.c 1.165. Because IPv6 fucked up and created a badly sized struct sockaddr_in6 we need to add some magic pading on 64bit archs. Code stolen from bgpd after a painful afternoon of bug hunting, head scratching and violent cursing. Now ospf6d works on 64bit archs. --- usr.sbin/ospf6d/kroute.c | 58 +++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 28 deletions(-) (limited to 'usr.sbin') diff --git a/usr.sbin/ospf6d/kroute.c b/usr.sbin/ospf6d/kroute.c index fbebd40abb3..d1aea1f860b 100644 --- a/usr.sbin/ospf6d/kroute.c +++ b/usr.sbin/ospf6d/kroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.18 2009/12/23 15:11:41 claudio Exp $ */ +/* $OpenBSD: kroute.c,v 1.19 2010/02/23 16:22:57 claudio Exp $ */ /* * Copyright (c) 2004 Esben Norby @@ -772,8 +772,8 @@ inet6applymask(struct in6_addr *dest, const struct in6_addr *src, int prefixlen) 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) @@ -784,7 +784,7 @@ get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 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; } @@ -933,9 +933,10 @@ send_rtmsg(int fd, int action, struct kroute *kroute) { 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)]; /* thank you IPv6 */ + } prefix, nexthop, mask; struct sockaddr_rtlabel sa_rl; int iovcnt = 0; const char *label; @@ -947,62 +948,63 @@ send_rtmsg(int fd, int action, struct kroute *kroute) bzero(&hdr, sizeof(hdr)); hdr.rtm_version = RTM_VERSION; hdr.rtm_type = action; - hdr.rtm_flags = RTF_UP|RTF_PROTO2; + hdr.rtm_flags = RTF_UP; hdr.rtm_priority = RTP_OSPF; - if (action == RTM_CHANGE) /* force PROTO2 reset the other flags */ - hdr.rtm_fmask = RTF_PROTO2|RTF_PROTO1|RTF_REJECT|RTF_BLACKHOLE; + if (action == RTM_CHANGE) + hdr.rtm_fmask = RTF_REJECT|RTF_BLACKHOLE; hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ + hdr.rtm_hdrlen = sizeof(hdr); hdr.rtm_msglen = sizeof(hdr); /* adjust iovec */ iov[iovcnt].iov_base = &hdr; iov[iovcnt++].iov_len = sizeof(hdr); bzero(&prefix, sizeof(prefix)); - prefix.sin6_len = sizeof(prefix); - prefix.sin6_family = AF_INET6; - prefix.sin6_addr = kroute->prefix; + prefix.addr.sin6_len = sizeof(struct sockaddr_in6); + prefix.addr.sin6_family = AF_INET6; + prefix.addr.sin6_addr = kroute->prefix; /* 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 (!IN6_IS_ADDR_UNSPECIFIED(&kroute->nexthop)) { bzero(&nexthop, sizeof(nexthop)); - nexthop.sin6_len = sizeof(nexthop); - nexthop.sin6_family = AF_INET6; - nexthop.sin6_addr = kroute->nexthop; + nexthop.addr.sin6_len = sizeof(struct sockaddr_in6); + nexthop.addr.sin6_family = AF_INET6; + nexthop.addr.sin6_addr = kroute->nexthop; /* * XXX we should set the sin6_scope_id but the kernel * XXX does not expect it that way. It must be fiddled * XXX into the sin6_addr. Welcome to the typical * XXX IPv6 insanity and all without wine bottles. */ - /* nexthop.sin6_scope_id = kroute->scope; */ - nexthop.sin6_addr.s6_addr[2] = (kroute->scope >> 8) & 0xff; - nexthop.sin6_addr.s6_addr[3] = kroute->scope & 0xff; + /* nexthop.addr.sin6_scope_id = kroute->scope; */ + nexthop.addr.sin6_addr.s6_addr[2] = (kroute->scope >> 8) & 0xff; + nexthop.addr.sin6_addr.s6_addr[3] = kroute->scope & 0xff; /* 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; - mask.sin6_addr = *prefixlen2mask(kroute->prefixlen); + mask.addr.sin6_len = sizeof(struct sockaddr_in6); + mask.addr.sin6_family = AF_INET6; + mask.addr.sin6_addr = *prefixlen2mask(kroute->prefixlen); /* adjust header */ if (kroute->prefixlen == 128) hdr.rtm_flags |= RTF_HOST; 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->rtlabel != 0) { sa_rl.sr_len = sizeof(sa_rl); -- cgit v1.2.3