summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2005-06-07 18:43:32 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2005-06-07 18:43:32 +0000
commit41577ec4a7ce2a821c924e540c78ea43bb104876 (patch)
treeab1b59599169e90cb2d61f24c3c35794434500ce
parentb7e47a80cdc66f2726bd38e4b86ede0e27c29d02 (diff)
Fix the mask2prefixlen6() function once and for all. Netmasks are stored in
an own AF independent radix tree. So the passed sockaddrs are often smaller than the actual AF specific struct, especially sockaddr_in6. So the crap Henning saw in the mask was acctually the next struct sockaddr that was passed in the routing message. So pass the struct sockaddr_in6 and compare only the specified number of bytes (minus the offset of sin6_addr in the struct sockaddr_in6). Amazing!.. OK henning@
-rw-r--r--usr.sbin/bgpd/kroute.c55
1 files changed, 23 insertions, 32 deletions
diff --git a/usr.sbin/bgpd/kroute.c b/usr.sbin/bgpd/kroute.c
index 0732ee88ab3..48c6456ab73 100644
--- a/usr.sbin/bgpd/kroute.c
+++ b/usr.sbin/bgpd/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.134 2005/06/06 17:15:07 henning Exp $ */
+/* $OpenBSD: kroute.c,v 1.135 2005/06/07 18:43:31 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -123,7 +123,7 @@ void kroute_detach_nexthop(struct knexthop_node *);
int protect_lo(void);
u_int8_t prefixlen_classful(in_addr_t);
u_int8_t mask2prefixlen(in_addr_t);
-u_int8_t mask2prefixlen6(struct in6_addr *);
+u_int8_t mask2prefixlen6(struct sockaddr_in6 *);
void get_rtaddrs(int, struct sockaddr *, struct sockaddr **);
void if_change(u_short, int, struct if_data *);
void if_announce(void *);
@@ -1467,56 +1467,48 @@ mask2prefixlen(in_addr_t ina)
}
u_int8_t
-mask2prefixlen6(struct in6_addr *in6a)
+mask2prefixlen6(struct sockaddr_in6 *sa_in6)
{
- u_int8_t l = 0, i;
- int final = 0;
+ u_int8_t l = 0, i, len;
- for (i = 0; i < 16; i ++) {
+ /*
+ * sin6_len is the size of the sockaddr so substract the offset of
+ * the possibly truncated sin6_addr struct.
+ */
+ len = sa_in6->sin6_len -
+ (u_int8_t)(&((struct sockaddr_in6 *)NULL)->sin6_addr);
+ for (i = 0; i < len; i++) {
/* this "beauty" is adopted from sbin/route/show.c ... */
- switch (in6a->s6_addr[i]) {
+ switch (sa_in6->sin6_addr.s6_addr[i]) {
case 0xff:
l += 8;
break;
case 0xfe:
l += 7;
- final++;
- break;
+ return (l);
case 0xfc:
l += 6;
- final++;
- break;
+ return (l);
case 0xf8:
l += 5;
- final++;
- break;
+ return (l);
case 0xf0:
l += 4;
- final++;
- break;
+ return (l);
case 0xe0:
l += 3;
- final++;
- break;
+ return (l);
case 0xc0:
l += 2;
- final++;
- break;
+ return (l);
case 0x80:
l += 1;
- final++;
- break;
+ return (l);
case 0x00:
- final++;
- break;
+ return (l);
default:
- /* XXX why is there crap in the mask??? */
- in6a->s6_addr[i] = 0x00;
- final++;
- break;
+ fatalx("non continguous inet6 netmask");
}
- if (final)
- return (l);
}
return (l);
@@ -1930,8 +1922,7 @@ fetchtable(void)
if (sa_in6 != NULL) {
if (sa_in6->sin6_len == 0)
break;
- kr6->r.prefixlen =
- mask2prefixlen6(&sa_in6->sin6_addr);
+ kr6->r.prefixlen = mask2prefixlen6(sa_in6);
} else if (rtm->rtm_flags & RTF_HOST)
kr6->r.prefixlen = 128;
else
@@ -2148,7 +2139,7 @@ dispatch_rtmsg_addr(struct rt_msghdr *rtm, struct sockaddr *rti_info[RTAX_MAX])
flags |= F_STATIC;
if (sa_in6 != NULL) {
if (sa_in6->sin6_len != 0)
- prefixlen = mask2prefixlen6(&sa_in6->sin6_addr);
+ prefixlen = mask2prefixlen6(sa_in6);
} else if (rtm->rtm_flags & RTF_HOST)
prefixlen = 128;
else