diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2010-12-21 14:28:59 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2010-12-21 14:28:59 +0000 |
commit | c60c16e6b6f517057bf7b13c0423b156f6883117 (patch) | |
tree | 536260e75f0ef2be147000643889a4f1f279a8f5 | |
parent | 25f28a828c93ac124047dae57bd5aa71f55bd8a6 (diff) |
Convert netmask from sockaddr to prefixlen correctly as noticed
by axel rau, axel dot rau at chaos1 dot de. The actual convert
functions are taken from bgpd(8). OK reyk
-rw-r--r-- | sbin/iked/parse.y | 81 |
1 files changed, 70 insertions, 11 deletions
diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y index 2ee66bea193..84db9dbe536 100644 --- a/sbin/iked/parse.y +++ b/sbin/iked/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.14 2010/11/17 16:43:45 ckuethe Exp $ */ +/* $OpenBSD: parse.y,v 1.15 2010/12/21 14:28:58 mikeb Exp $ */ /* $vantronix: parse.y,v 1.22 2010/06/03 11:08:34 reyk Exp $ */ /* @@ -266,6 +266,8 @@ struct ipsec_addr_wrap *host_v4(const char *, int); struct ipsec_addr_wrap *host_dns(const char *, int); struct ipsec_addr_wrap *host_if(const char *, int); struct ipsec_addr_wrap *host_any(void); +u_int8_t mask2prefixlen(struct sockaddr_in *); +u_int8_t mask2prefixlen6(struct sockaddr_in6 *); void ifa_load(void); int ifa_exists(const char *); struct ipsec_addr_wrap *ifa_lookup(const char *ifa_name); @@ -1712,6 +1714,65 @@ host_any(void) return (ipa); } +u_int8_t +mask2prefixlen(struct sockaddr_in *sa_in) +{ + in_addr_t ina = sa_in->sin_addr.s_addr; + + if (ina == 0) + return (0); + else + return (33 - ffs(ntohl(ina))); +} + +u_int8_t +mask2prefixlen6(struct sockaddr_in6 *sa_in6) +{ + u_int8_t l = 0, *ap, *ep; + + /* + * sin6_len is the size of the sockaddr so substract the offset of + * the possibly truncated sin6_addr struct. + */ + ap = (u_int8_t *)&sa_in6->sin6_addr; + ep = (u_int8_t *)sa_in6 + sa_in6->sin6_len; + for (; ap < ep; ap++) { + /* this "beauty" is adopted from sbin/route/show.c ... */ + switch (*ap) { + case 0xff: + l += 8; + break; + case 0xfe: + l += 7; + return (l); + case 0xfc: + l += 6; + return (l); + case 0xf8: + l += 5; + return (l); + case 0xf0: + l += 4; + return (l); + case 0xe0: + l += 3; + return (l); + case 0xc0: + l += 2; + return (l); + case 0x80: + l += 1; + return (l); + case 0x00: + return (l); + default: + fatalx("non continguous inet6 netmask"); + } + } + + return (l); +} + /* interface lookup routintes */ struct ipsec_addr_wrap *iftab; @@ -1721,6 +1782,8 @@ ifa_load(void) { struct ifaddrs *ifap, *ifa; struct ipsec_addr_wrap *n = NULL, *h = NULL; + struct sockaddr_in *sa_in; + struct sockaddr_in6 *sa_in6; if (getifaddrs(&ifap) < 0) err(1, "ifa_load: getifaddrs"); @@ -1737,17 +1800,13 @@ ifa_load(void) if ((n->name = strdup(ifa->ifa_name)) == NULL) err(1, "ifa_load: strdup"); if (n->af == AF_INET) { - n->af = AF_INET; - memcpy(&n->address, ifa->ifa_addr, - sizeof(struct sockaddr_in)); - memcpy(&n->mask, ifa->ifa_addr, - sizeof(struct sockaddr_in)); + sa_in = (struct sockaddr_in *)ifa->ifa_addr; + memcpy(&n->address, sa_in, sizeof(*sa_in)); + n->mask = mask2prefixlen(sa_in); } else if (n->af == AF_INET6) { - n->af = AF_INET6; - memcpy(&n->address, ifa->ifa_addr, - sizeof(struct sockaddr_in6)); - memcpy(&n->mask, ifa->ifa_addr, - sizeof(struct sockaddr_in6)); + sa_in6 = (struct sockaddr_in6 *)ifa->ifa_addr; + memcpy(&n->address, sa_in6, sizeof(*sa_in6)); + n->mask = mask2prefixlen6(sa_in6); } n->next = NULL; n->tail = n; |