From 5d82424f5d3c77c092c111b935041fd3dc4b3e98 Mon Sep 17 00:00:00 2001 From: Andreas Gustafsson Date: Wed, 9 Feb 2000 22:52:37 +0000 Subject: [PATCH] New source file netaddr.c; new functions isc_netaddr_eqprefix(), isc_netaddr_masktoprefixlen(), isc_netaddr_fromsockaddr(), isc_netaddr_fromin(), isc_netaddr_fromin6(), isc_sockaddr_fromnetaddr(); new result code ISC_R_MASKNONCONTIG --- lib/isc/Makefile.in | 4 +- lib/isc/include/isc/netaddr.h | 36 +++++++- lib/isc/include/isc/result.h | 3 +- lib/isc/include/isc/sockaddr.h | 9 +- lib/isc/include/isc/types.h | 2 + lib/isc/netaddr.c | 160 +++++++++++++++++++++++++++++++++ lib/isc/result.c | 3 +- lib/isc/sockaddr.c | 87 +++++++----------- util/copyrights | 1 + 9 files changed, 244 insertions(+), 61 deletions(-) create mode 100644 lib/isc/netaddr.c diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in index 081f13be44..077d6ed531 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -47,7 +47,7 @@ OBJS = @ISC_EXTRA_OBJS@ \ assertions.@O@ base64.@O@ bitstring.@O@ buffer.@O@ \ bufferlist.@O@ commandline.@O@ error.@O@ event.@O@ heap.@O@ \ lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \ - mem.@O@ mutexblock.@O@ quota.@O@ random.@O@ \ + mem.@O@ mutexblock.@O@ netaddr.@O@ quota.@O@ random.@O@ \ ratelimiter.@O@ result.@O@ rwlock.@O@ \ serial.@O@ sockaddr.@O@ str.@O@ symtab.@O@ \ task.@O@ taskpool.@O@ timer.@O@ version.@O@ \ @@ -58,7 +58,7 @@ SRCS = @ISC_EXTRA_SRCS@ \ assertions.c base64.c bitstring.c buffer.c \ bufferlist.c commandline.c error.c event.c heap.c \ lex.c lfsr.c lib.c log.c \ - mem.c mutexblock.c quota.c random.c \ + mem.c mutexblock.c netaddr.c quota.c random.c \ ratelimiter.c result.c rwlock.c \ serial.c sockaddr.c str.c symtab.c \ task.c taskpool.c timer.c version.c diff --git a/lib/isc/include/isc/netaddr.h b/lib/isc/include/isc/netaddr.h index 8a2236fabd..283a47da19 100644 --- a/lib/isc/include/isc/netaddr.h +++ b/lib/isc/include/isc/netaddr.h @@ -20,16 +20,48 @@ #include #include +#include ISC_LANG_BEGINDECLS -typedef struct isc_netaddr { +struct isc_netaddr { unsigned int family; union { struct in_addr in; struct in6_addr in6; } type; -} isc_netaddr_t; +}; + +isc_boolean_t +isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b, + unsigned int prefixlen); +/* + * Compare the 'prefixlen' most significant bits of the network + * addresses 'a' and 'b'. Return ISC_TRUE if they are equal, + * ISC_FALSE if not. + */ + +isc_result_t +isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp); +/* + * Convert a netmask in 's' into a prefix length in '*lenp'. + * The mask should consist of zero or more '1' bits in the most + * most significant part of the address, followed by '0' bits. + * If this is not the case, ISC_R_MASKNONCONTIG is returned. + * + * Returns: + * ISC_R_SUCCESS + * ISC_R_MASKNONCONTIG + */ + +void +isc_netaddr_fromsockaddr(isc_netaddr_t *netaddr, const isc_sockaddr_t *source); + +void +isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina); + +void +isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6); ISC_LANG_ENDDECLS diff --git a/lib/isc/include/isc/result.h b/lib/isc/include/isc/result.h index 43f16ac7ce..7cbb61e33b 100644 --- a/lib/isc/include/isc/result.h +++ b/lib/isc/include/isc/result.h @@ -62,8 +62,9 @@ ISC_LANG_BEGINDECLS #define ISC_R_UNEXPECTED 34 #define ISC_R_ALREADYRUNNING 35 #define ISC_R_IGNORE 36 +#define ISC_R_MASKNONCONTIG 37 -#define ISC_R_NRESULTS 37 /* Number of results */ +#define ISC_R_NRESULTS 38 /* Number of results */ char * isc_result_totext(isc_result_t); isc_result_t isc_result_register(unsigned int base, diff --git a/lib/isc/include/isc/sockaddr.h b/lib/isc/include/isc/sockaddr.h index 95aec07bcd..84bf4e6506 100644 --- a/lib/isc/include/isc/sockaddr.h +++ b/lib/isc/include/isc/sockaddr.h @@ -22,10 +22,11 @@ #include #include #include +#include ISC_LANG_BEGINDECLS -typedef struct isc_sockaddr { +struct isc_sockaddr { union { struct sockaddr sa; struct sockaddr_in sin; @@ -33,7 +34,7 @@ typedef struct isc_sockaddr { } type; unsigned int length; /* XXXRTH beginning? */ ISC_LINK(struct isc_sockaddr) link; -} isc_sockaddr_t; +}; typedef ISC_LIST(struct isc_sockaddr) isc_sockaddrlist_t; @@ -62,6 +63,10 @@ void isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina, in_port_t port); +void +isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na, + in_port_t port); + int isc_sockaddr_pf(const isc_sockaddr_t *sockaddr); /* diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h index f56757d335..16b42a918d 100644 --- a/lib/isc/include/isc/types.h +++ b/lib/isc/include/isc/types.h @@ -42,6 +42,8 @@ typedef struct isc_timer isc_timer_t; typedef struct isc_timermgr isc_timermgr_t; typedef struct isc_rwlock isc_rwlock_t; typedef struct isc_bitstring isc_bitstring_t; +typedef struct isc_sockaddr isc_sockaddr_t; +typedef struct isc_netaddr isc_netaddr_t; typedef void (*isc_taskaction_t)(isc_task_t *, isc_event_t *); diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c new file mode 100644 index 0000000000..e55c04f118 --- /dev/null +++ b/lib/isc/netaddr.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 1999, 2000 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +isc_boolean_t +isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b, + unsigned int prefixlen) +{ + unsigned char *pa, *pb; + unsigned int ipabytes; /* Length of whole IP address in bytes */ + unsigned int nbytes; /* Number of significant whole bytes */ + unsigned int nbits; /* Number of significant leftover bits */ + + REQUIRE(a != NULL && b != NULL); + + if (a->family != b->family) + return (ISC_FALSE); + + switch (a->family) { + case AF_INET: + pa = (unsigned char *) &a->type.in; + pb = (unsigned char *) &b->type.in; + ipabytes = 4; + break; + case AF_INET6: + pa = (unsigned char *) &a->type.in6; + pb = (unsigned char *) &b->type.in6; + ipabytes = 16; + break; + default: + pa = pb = NULL; /* Avoid silly compiler warning. */ + ipabytes = 0; /* Ditto. */ + return (ISC_FALSE); + } + + /* Don't crash if we get a pattern like 10.0.0.1/9999999. */ + if (prefixlen > ipabytes * 8) + prefixlen = ipabytes * 8; + + nbytes = prefixlen / 8; + nbits = prefixlen % 8; + + if (nbytes > 0) { + if (memcmp(pa, pb, nbytes) != 0) + return (ISC_FALSE); + } + if (nbits > 0) { + unsigned int bytea, byteb, mask; + INSIST(nbytes < ipabytes); + INSIST(nbits < 8); + bytea = pa[nbytes]; + byteb = pb[nbytes]; + mask = (0xFF << (8-nbits)) & 0xFF; + if ((bytea & mask) != (byteb & mask)) + return (ISC_FALSE); + } + return (ISC_TRUE); +} + +isc_result_t +isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) +{ + unsigned int nbits, nbytes, ipbytes, i; + unsigned char *p; + + switch (s->family) { + case AF_INET: + p = (unsigned char *) &s->type.in; + ipbytes = 4; + break; + case AF_INET6: + p = (unsigned char *) &s->type.in6; + ipbytes = 16; + break; + default: + ipbytes = 0; + return (ISC_R_NOTIMPLEMENTED); + } + nbytes = nbits = 0; + for (i = 0; i < ipbytes; i++) { + if (p[i] != 0xFF) + break; + } + nbytes = i; + if (i < ipbytes) { + unsigned int c = p[nbytes]; + while ((c & 0x80) != 0 && nbits < 8) { + c <<= 1; nbits++; + } + if ((c & 0xFF) != 0) + return (ISC_R_MASKNONCONTIG); + i++; + } + for (; i < ipbytes; i++) { + if (p[i] != 0) + return (ISC_R_MASKNONCONTIG); + i++; + } + *lenp = nbytes * 8 + nbits; + return (ISC_R_SUCCESS); +} + +void +isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) +{ + memset(netaddr, 0, sizeof *netaddr); + netaddr->family = AF_INET; + netaddr->type.in = *ina; +} + +void +isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) +{ + memset(netaddr, 0, sizeof *netaddr); + netaddr->family = AF_INET6; + netaddr->type.in6 = *ina6; +} + +void +isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) +{ + int family = s->type.sa.sa_family; + t->family = family; + switch (family) { + case AF_INET: + t->type.in = s->type.sin.sin_addr; + break; + case AF_INET6: + memcpy(&t->type.in6, &s->type.sin6.sin6_addr, 16); + break; + default: + INSIST(0); + } +} + diff --git a/lib/isc/result.c b/lib/isc/result.c index 9328c0a024..d20c4630c7 100644 --- a/lib/isc/result.c +++ b/lib/isc/result.c @@ -76,7 +76,8 @@ static char *text[ISC_R_NRESULTS] = { "quota reached", /* 33 */ "unexpected error", /* 34 */ "already running", /* 35 */ - "ignore" /* 36 */ + "ignore", /* 36 */ + "address mask not contiguous" /* 37 */ }; #define ISC_RESULT_RESULTSET 2 diff --git a/lib/isc/sockaddr.c b/lib/isc/sockaddr.c index 29b7bc22ea..931a049146 100644 --- a/lib/isc/sockaddr.c +++ b/lib/isc/sockaddr.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include isc_boolean_t isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) @@ -106,58 +106,10 @@ isc_boolean_t isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b, unsigned int prefixlen) { - unsigned char *pa, *pb; - unsigned int ipabytes; /* Length of whole IP address in bytes */ - unsigned int nbytes; /* Number of significant whole bytes */ - unsigned int nbits; /* Number of significant leftover bits */ - - REQUIRE(a != NULL && b != NULL); - - if (a->length != b->length) - return (ISC_FALSE); - - if (a->type.sa.sa_family != b->type.sa.sa_family) - return (ISC_FALSE); - - switch (a->type.sa.sa_family) { - case AF_INET: - pa = (unsigned char *) &a->type.sin.sin_addr; - pb = (unsigned char *) &b->type.sin.sin_addr; - ipabytes = 4; - break; - case AF_INET6: - pa = ((unsigned char *) &a->type.sin6.sin6_addr); - pb = ((unsigned char *) &b->type.sin6.sin6_addr); - ipabytes = 16; - break; - default: - pa = pb = NULL; /* Avoid silly compiler warning. */ - ipabytes = 0; /* Ditto. */ - return (ISC_FALSE); /* XXX got a better idea? */ - } - - /* Don't crash if we get a pattern like 10.0.0.1/9999999. */ - if (prefixlen > ipabytes * 8) - prefixlen = ipabytes * 8; - - nbytes = prefixlen / 8; - nbits = prefixlen % 8; - - if (nbytes > 0) { - if (memcmp(pa, pb, nbytes) != 0) - return (ISC_FALSE); - } - if (nbits > 0) { - unsigned int bytea, byteb, mask; - INSIST(nbytes < ipabytes); - INSIST(nbits < 8); - bytea = pa[nbytes]; - byteb = pb[nbytes]; - mask = (0xFF << (8-nbits)) & 0xFF; - if ((bytea & mask) != (byteb & mask)) - return (ISC_FALSE); - } - return (ISC_TRUE); + isc_netaddr_t na, nb; + isc_netaddr_fromsockaddr(&na, a); + isc_netaddr_fromsockaddr(&nb, b); + return (isc_netaddr_eqprefix(&na, &nb, prefixlen)); } isc_result_t @@ -324,6 +276,35 @@ isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) { #endif } +void +isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na, + in_port_t port) +{ + memset(sockaddr, 0, sizeof *sockaddr); + sockaddr->type.sin.sin_family = na->family; + switch (na->family) { + case AF_INET: + sockaddr->length = sizeof sockaddr->type.sin; +#ifdef ISC_PLATFORM_HAVESALEN + sockaddr->type.sin.sin_len = sizeof sockaddr->type.sin; +#endif + sockaddr->type.sin.sin_addr = na->type.in; + sockaddr->type.sin.sin_port = htons(port); + break; + case AF_INET6: + sockaddr->length = sizeof sockaddr->type.sin6; +#ifdef ISC_PLATFORM_HAVESALEN + sockaddr->type.sin6.sin6_len = sizeof sockaddr->type.sin6; +#endif + memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16); + sockaddr->type.sin6.sin6_port = htons(port); + break; + default: + INSIST(0); + } + ISC_LINK_INIT(sockaddr, link); +} + void isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) { switch (sockaddr->type.sa.sa_family) { diff --git a/util/copyrights b/util/copyrights index b99415a9ed..71ddb5646f 100644 --- a/util/copyrights +++ b/util/copyrights @@ -636,6 +636,7 @@ ./lib/isc/log.c C 1999,2000 ./lib/isc/mem.c C 1997,1998,1999,2000 ./lib/isc/mutexblock.c C 1999,2000 +./lib/isc/netaddr.c C 1999,2000 ./lib/isc/nls/.cvsignore X 1999,2000 ./lib/isc/nls/Makefile.in MAKE 1999,2000 ./lib/isc/nls/msgcat.c C 1999,2000