summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2010-02-23 16:22:58 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2010-02-23 16:22:58 +0000
commit05feabc6c37420e3bd1860eed19978d4a5695ee2 (patch)
treeafd33ed16e20d179537420f64bbf8867b034f2f1 /usr.sbin
parentc8f132c418c0e503fbc764107efaee741180f447 (diff)
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.
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ospf6d/kroute.c58
1 files changed, 30 insertions, 28 deletions
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 <norby@openbsd.org>
@@ -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);