From 21fcee4d6e84a10a35d21e920106590570511048 Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sun, 21 Dec 2008 03:36:37 -0500 Subject: [PATCH] Use BIND's resolver in libc. This also syncs some code from FreeBSD bringing along bug fixes and more thread-safe routines. Obtained-from: FreeBSD --- contrib/bind-9.3/lib/bind/include/isc/list.h | 5 + contrib/bind-9.3/lib/bind/inet/inet_addr.c | 13 +- .../bind-9.3/lib/bind/inet/inet_cidr_pton.c | 5 + contrib/bind-9.3/lib/bind/inet/inet_lnaof.c | 13 +- .../bind-9.3/lib/bind/inet/inet_makeaddr.c | 11 +- .../bind-9.3/lib/bind/inet/inet_net_pton.c | 14 + contrib/bind-9.3/lib/bind/inet/inet_neta.c | 13 +- contrib/bind-9.3/lib/bind/inet/inet_netof.c | 13 +- contrib/bind-9.3/lib/bind/inet/inet_network.c | 21 +- contrib/bind-9.3/lib/bind/inet/inet_ntoa.c | 18 + contrib/bind-9.3/lib/bind/inet/inet_ntop.c | 39 +- contrib/bind-9.3/lib/bind/inet/inet_pton.c | 13 +- contrib/bind-9.3/lib/bind/inet/nsap_addr.c | 11 + contrib/bind-9.3/lib/bind/isc/ev_streams.c | 10 +- contrib/bind-9.3/lib/bind/isc/ev_timers.c | 17 +- contrib/bind-9.3/lib/bind/isc/eventlib_p.h | 8 + contrib/bind-9.3/lib/bind/nameser/ns_print.c | 9 + .../bind-9.3/lib/bind/nameser/ns_samedomain.c | 2 + contrib/bind-9.3/lib/bind/resolv/herror.c | 12 + contrib/bind-9.3/lib/bind/resolv/mtctxres.c | 14 +- contrib/bind-9.3/lib/bind/resolv/res_comp.c | 11 + contrib/bind-9.3/lib/bind/resolv/res_data.c | 43 + contrib/bind-9.3/lib/bind/resolv/res_debug.c | 27 +- .../lib/bind/resolv/res_findzonecut.c | 4 +- contrib/bind-9.3/lib/bind/resolv/res_init.c | 88 +- .../bind-9.3/lib/bind/resolv/res_mkquery.c | 2 + .../bind-9.3/lib/bind/resolv/res_mkupdate.c | 31 +- contrib/bind-9.3/lib/bind/resolv/res_query.c | 53 +- contrib/bind-9.3/lib/bind/resolv/res_send.c | 162 +- contrib/bind-9.3/lib/bind/resolv/res_update.c | 10 +- include/Makefile | 3 +- include/arpa/inet.h | 89 +- include/arpa/nameser.h | 332 ++- include/arpa/nameser_compat.h | 23 +- include/netdb.h | 154 +- include/res_update.h | 73 + include/resolv.h | 437 ++-- lib/libc/Makefile.inc | 1 + lib/libc/include/isc/platform.h | 37 + lib/libc/include/port_after.h | 11 + lib/libc/include/port_before.h | 22 + lib/libc/net/Makefile.inc | 15 +- lib/libc/net/gai_strerror.c | 60 + lib/libc/net/getaddrinfo.3 | 54 +- lib/libc/net/getaddrinfo.c | 1739 +++++++++----- lib/libc/net/gethostbydns.c | 562 +++-- lib/libc/net/gethostbyht.c | 265 ++- lib/libc/net/gethostbyname.3 | 102 +- lib/libc/net/gethostbynis.c | 283 ++- lib/libc/net/gethostnamadr.c | 467 +++- lib/libc/net/getnameinfo.3 | 38 +- lib/libc/net/getnameinfo.c | 139 +- lib/libc/net/getnetbydns.c | 318 ++- lib/libc/net/getnetbyht.c | 231 +- lib/libc/net/getnetbynis.c | 150 +- lib/libc/net/getnetnamadr.c | 388 +++- lib/libc/net/herror.c | 104 - lib/libc/net/inet_addr.c | 191 -- lib/libc/net/inet_lnaof.c | 62 - lib/libc/net/inet_makeaddr.c | 65 - lib/libc/net/inet_net_ntop.c | 136 -- lib/libc/net/inet_net_pton.c | 206 -- lib/libc/net/inet_neta.c | 86 - lib/libc/net/inet_netof.c | 61 - lib/libc/net/inet_network.c | 93 - lib/libc/net/inet_ntop.c | 184 -- lib/libc/net/inet_pton.c | 220 -- lib/libc/net/name6.c | 2044 +++++------------ lib/libc/net/netdb_private.h | 12 +- lib/libc/net/ns_name.c | 592 ----- lib/libc/net/ns_netint.c | 53 - lib/libc/net/ns_parse.c | 189 -- lib/libc/net/ns_print.c | 742 ------ lib/libc/net/ns_ttl.c | 150 -- lib/libc/net/res_comp.c | 259 --- lib/libc/net/res_config.h | 6 +- lib/libc/net/res_data.c | 82 - lib/libc/net/res_debug.c | 991 -------- lib/libc/net/res_init.c | 576 ----- lib/libc/net/res_mkquery.c | 239 -- lib/libc/net/res_mkupdate.c | 416 ---- lib/libc/net/res_query.c | 430 ---- lib/libc/net/res_send.c | 915 -------- lib/libc/net/res_update.c | 520 ----- lib/libc/resolv/Makefile.inc | 21 + .../{net/inet_ntoa.c => resolv/h_errno.c} | 49 +- lib/libc/resolv/res_state.c | 87 + 87 files changed, 5486 insertions(+), 10980 deletions(-) create mode 100644 include/res_update.h create mode 100644 lib/libc/include/isc/platform.h create mode 100644 lib/libc/include/port_after.h create mode 100644 lib/libc/include/port_before.h create mode 100644 lib/libc/net/gai_strerror.c delete mode 100644 lib/libc/net/herror.c delete mode 100644 lib/libc/net/inet_addr.c delete mode 100644 lib/libc/net/inet_lnaof.c delete mode 100644 lib/libc/net/inet_makeaddr.c delete mode 100644 lib/libc/net/inet_net_ntop.c delete mode 100644 lib/libc/net/inet_net_pton.c delete mode 100644 lib/libc/net/inet_neta.c delete mode 100644 lib/libc/net/inet_netof.c delete mode 100644 lib/libc/net/inet_network.c delete mode 100644 lib/libc/net/inet_ntop.c delete mode 100644 lib/libc/net/inet_pton.c delete mode 100644 lib/libc/net/ns_name.c delete mode 100644 lib/libc/net/ns_netint.c delete mode 100644 lib/libc/net/ns_parse.c delete mode 100644 lib/libc/net/ns_print.c delete mode 100644 lib/libc/net/ns_ttl.c delete mode 100644 lib/libc/net/res_comp.c delete mode 100644 lib/libc/net/res_data.c delete mode 100644 lib/libc/net/res_debug.c delete mode 100644 lib/libc/net/res_init.c delete mode 100644 lib/libc/net/res_mkquery.c delete mode 100644 lib/libc/net/res_mkupdate.c delete mode 100644 lib/libc/net/res_query.c delete mode 100644 lib/libc/net/res_send.c delete mode 100644 lib/libc/net/res_update.c create mode 100644 lib/libc/resolv/Makefile.inc rename lib/libc/{net/inet_ntoa.c => resolv/h_errno.c} (52%) create mode 100644 lib/libc/resolv/res_state.c diff --git a/contrib/bind-9.3/lib/bind/include/isc/list.h b/contrib/bind-9.3/lib/bind/include/isc/list.h index 4e27eb19ba..f79617ae9e 100644 --- a/contrib/bind-9.3/lib/bind/include/isc/list.h +++ b/contrib/bind-9.3/lib/bind/include/isc/list.h @@ -17,7 +17,12 @@ #ifndef LIST_H #define LIST_H 1 +#ifdef _LIBC +#include +#define INSIST(cond) assert(cond) +#else #include +#endif #define LIST(type) struct { type *head, *tail; } #define INIT_LIST(list) \ diff --git a/contrib/bind-9.3/lib/bind/inet/inet_addr.c b/contrib/bind-9.3/lib/bind/inet/inet_addr.c index b967dc2203..82bbe7ef54 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_addr.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_addr.c @@ -89,7 +89,7 @@ static const char rcsid[] = "$Id: inet_addr.c,v 1.2.206.2 2004/03/17 00:29:45 ma * Ascii internet address interpretation routine. * The value returned is in network order. */ -u_long +in_addr_t inet_addr(const char *cp) { struct in_addr val; @@ -204,3 +204,14 @@ inet_aton(const char *cp, struct in_addr *addr) { addr->s_addr = htonl(val); return (1); } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_addr +__weak_reference(__inet_addr, inet_addr); +#undef inet_aton +__weak_reference(__inet_aton, inet_aton); +#endif diff --git a/contrib/bind-9.3/lib/bind/inet/inet_cidr_pton.c b/contrib/bind-9.3/lib/bind/inet/inet_cidr_pton.c index 5bfef71ba7..0341c388b2 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_cidr_pton.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_cidr_pton.c @@ -27,7 +27,12 @@ static const char rcsid[] = "$Id: inet_cidr_pton.c,v 1.2.2.1.8.2 2004/03/17 00:2 #include #include +#ifdef _LIBC +#include +#define INSIST(x) assert(x) +#else #include +#endif #include #include #include diff --git a/contrib/bind-9.3/lib/bind/inet/inet_lnaof.c b/contrib/bind-9.3/lib/bind/inet/inet_lnaof.c index 97b80cffdb..5666be31f5 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_lnaof.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_lnaof.c @@ -48,11 +48,11 @@ static const char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93"; * internet address; handles class a/b/c network * number formats. */ -u_long +in_addr_t inet_lnaof(in) struct in_addr in; { - register u_long i = ntohl(in.s_addr); + in_addr_t i = ntohl(in.s_addr); if (IN_CLASSA(i)) return ((i)&IN_CLASSA_HOST); @@ -61,3 +61,12 @@ inet_lnaof(in) else return ((i)&IN_CLASSC_HOST); } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_lnaof +__weak_reference(__inet_lnaof, inet_lnaof); +#endif diff --git a/contrib/bind-9.3/lib/bind/inet/inet_makeaddr.c b/contrib/bind-9.3/lib/bind/inet/inet_makeaddr.c index 6e4ecc37cc..1b013a85e8 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_makeaddr.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_makeaddr.c @@ -49,7 +49,7 @@ static const char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93"; */ struct in_addr inet_makeaddr(net, host) - u_long net, host; + in_addr_t net, host; { struct in_addr a; @@ -64,3 +64,12 @@ inet_makeaddr(net, host) a.s_addr = htonl(a.s_addr); return (a); } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_makeaddr +__weak_reference(__inet_makeaddr, inet_makeaddr); +#endif diff --git a/contrib/bind-9.3/lib/bind/inet/inet_net_pton.c b/contrib/bind-9.3/lib/bind/inet/inet_net_pton.c index abecfc79cd..06eb476ddf 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_net_pton.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_net_pton.c @@ -27,7 +27,12 @@ static const char rcsid[] = "$Id: inet_net_pton.c,v 1.4.2.1.8.2 2004/03/17 00:29 #include #include +#ifdef _LIBC +#include +#define INSIST(cond) assert(cond) +#else #include +#endif #include #include #include @@ -403,3 +408,12 @@ inet_net_pton(int af, const char *src, void *dst, size_t size) { return (-1); } } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_net_pton +__weak_reference(__inet_net_pton, inet_net_pton); +#endif diff --git a/contrib/bind-9.3/lib/bind/inet/inet_neta.c b/contrib/bind-9.3/lib/bind/inet/inet_neta.c index 325b7ce814..f394122299 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_neta.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_neta.c @@ -41,7 +41,7 @@ static const char rcsid[] = "$Id: inet_neta.c,v 1.1.206.1 2004/03/09 08:33:33 ma /* * char * * inet_neta(src, dst, size) - * format a u_long network number into presentation format. + * format a in_addr_t network number into presentation format. * return: * pointer to dst, or NULL if an error occurred (check errno). * note: @@ -51,7 +51,7 @@ static const char rcsid[] = "$Id: inet_neta.c,v 1.1.206.1 2004/03/09 08:33:33 ma */ char * inet_neta(src, dst, size) - u_long src; + in_addr_t src; char *dst; size_t size; { @@ -85,3 +85,12 @@ inet_neta(src, dst, size) errno = EMSGSIZE; return (NULL); } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_neta +__weak_reference(__inet_neta, inet_neta); +#endif diff --git a/contrib/bind-9.3/lib/bind/inet/inet_netof.c b/contrib/bind-9.3/lib/bind/inet/inet_netof.c index e887530088..faf4524e5c 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_netof.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_netof.c @@ -47,11 +47,11 @@ static const char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93"; * Return the network number from an internet * address; handles class a/b/c network #'s. */ -u_long +in_addr_t inet_netof(in) struct in_addr in; { - register u_long i = ntohl(in.s_addr); + in_addr_t i = ntohl(in.s_addr); if (IN_CLASSA(i)) return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); @@ -60,3 +60,12 @@ inet_netof(in) else return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_netof +__weak_reference(__inet_netof, inet_netof); +#endif diff --git a/contrib/bind-9.3/lib/bind/inet/inet_network.c b/contrib/bind-9.3/lib/bind/inet/inet_network.c index aaa50c8315..f10558c33a 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_network.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_network.c @@ -49,14 +49,14 @@ static const char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93"; * The library routines call this routine to interpret * network numbers. */ -u_long +in_addr_t inet_network(cp) - register const char *cp; + const char *cp; { - register u_long val, base, n, i; - register char c; - u_long parts[4], *pp = parts; - int digit; + in_addr_t val, base, n; + char c; + in_addr_t parts[4], *pp = parts; + int i, digit; again: val = 0; base = 10; digit = 0; @@ -102,3 +102,12 @@ again: } return (val); } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_network +__weak_reference(__inet_network, inet_network); +#endif diff --git a/contrib/bind-9.3/lib/bind/inet/inet_ntoa.c b/contrib/bind-9.3/lib/bind/inet/inet_ntoa.c index 7fad4b8902..31d32a546b 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_ntoa.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_ntoa.c @@ -60,3 +60,21 @@ inet_ntoa(struct in_addr in) { (void) inet_ntop(AF_INET, &in, ret, sizeof ret); return (ret); } + +#ifdef _LIBC +char * +inet_ntoa_r(struct in_addr in, char *buf, socklen_t size) +{ + + inet_ntop(AF_INET, &in, buf, size); + return (buf); +} + +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_ntoa +__weak_reference(__inet_ntoa, inet_ntoa); +__weak_reference(__inet_ntoa_r, inet_ntoa_r); +#endif diff --git a/contrib/bind-9.3/lib/bind/inet/inet_ntop.c b/contrib/bind-9.3/lib/bind/inet/inet_ntop.c index cd502ab758..eefc5214be 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_ntop.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_ntop.c @@ -35,19 +35,13 @@ static const char rcsid[] = "$Id: inet_ntop.c,v 1.1.2.1.8.2 2005/11/03 23:08:40 #include "port_after.h" -#ifdef SPRINTF_CHAR -# define SPRINTF(x) strlen(sprintf/**/x) -#else -# define SPRINTF(x) ((size_t)sprintf x) -#endif - /* * WARNING: Don't even consider trying to compile this on a system where * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ -static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size)); -static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size)); +static const char *inet_ntop4 __P((const u_char *src, char *dst, socklen_t size)); +static const char *inet_ntop6 __P((const u_char *src, char *dst, socklen_t size)); /* char * * inet_ntop(af, src, dst, size) @@ -60,9 +54,9 @@ static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size)); const char * inet_ntop(af, src, dst, size) int af; - const void *src; - char *dst; - size_t size; + const void * __restrict src; + char * __restrict dst; + socklen_t size; { switch (af) { case AF_INET: @@ -91,16 +85,18 @@ static const char * inet_ntop4(src, dst, size) const u_char *src; char *dst; - size_t size; + socklen_t size; { static const char fmt[] = "%u.%u.%u.%u"; char tmp[sizeof "255.255.255.255"]; + int l; - if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) { + l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); + if (l <= 0 || (socklen_t) l >= size) { errno = ENOSPC; return (NULL); } - strcpy(dst, tmp); + strlcpy(dst, tmp, size); return (dst); } @@ -114,7 +110,7 @@ static const char * inet_ntop6(src, dst, size) const u_char *src; char *dst; - size_t size; + socklen_t size; { /* * Note that int32_t and int16_t need only be "at least" large enough @@ -185,7 +181,7 @@ inet_ntop6(src, dst, size) tp += strlen(tp); break; } - tp += SPRINTF((tp, "%x", words[i])); + tp += sprintf(tp, "%x", words[i]); } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == @@ -196,10 +192,19 @@ inet_ntop6(src, dst, size) /* * Check for overflow, copy, and we're done. */ - if ((size_t)(tp - tmp) > size) { + if ((socklen_t)(tp - tmp) > size) { errno = ENOSPC; return (NULL); } strcpy(dst, tmp); return (dst); } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_net_ntop +__weak_reference(__inet_net_ntop, inet_net_ntop); +#endif diff --git a/contrib/bind-9.3/lib/bind/inet/inet_pton.c b/contrib/bind-9.3/lib/bind/inet/inet_pton.c index f18a7b64fd..c1aa9b2cd7 100644 --- a/contrib/bind-9.3/lib/bind/inet/inet_pton.c +++ b/contrib/bind-9.3/lib/bind/inet/inet_pton.c @@ -52,8 +52,8 @@ static int inet_pton6 __P((const char *src, u_char *dst)); int inet_pton(af, src, dst) int af; - const char *src; - void *dst; + const char * __restrict src; + void * __restrict dst; { switch (af) { case AF_INET: @@ -219,3 +219,12 @@ inet_pton6(src, dst) memcpy(dst, tmp, NS_IN6ADDRSZ); return (1); } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_pton +__weak_reference(__inet_pton, inet_pton); +#endif diff --git a/contrib/bind-9.3/lib/bind/inet/nsap_addr.c b/contrib/bind-9.3/lib/bind/inet/nsap_addr.c index a4b98e7c4a..eacd733269 100644 --- a/contrib/bind-9.3/lib/bind/inet/nsap_addr.c +++ b/contrib/bind-9.3/lib/bind/inet/nsap_addr.c @@ -107,3 +107,14 @@ inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) { *ascii = '\0'; return (start); } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef inet_nsap_addr +__weak_reference(__inet_nsap_addr, inet_nsap_addr); +#undef inet_nsap_ntoa +__weak_reference(__inet_nsap_ntoa, inet_nsap_ntoa); +#endif diff --git a/contrib/bind-9.3/lib/bind/isc/ev_streams.c b/contrib/bind-9.3/lib/bind/isc/ev_streams.c index 64e88b0c00..fdac9b8979 100644 --- a/contrib/bind-9.3/lib/bind/isc/ev_streams.c +++ b/contrib/bind-9.3/lib/bind/isc/ev_streams.c @@ -24,24 +24,30 @@ static const char rcsid[] = "$Id: ev_streams.c,v 1.2.206.2 2004/03/17 00:29:51 m #endif #include "port_before.h" +#ifndef _LIBC #include "fd_setsize.h" +#endif #include #include #include -#include +#include "isc/eventlib.h" +#ifndef _LIBC #include +#endif #include "eventlib_p.h" #include "port_after.h" +#ifndef _LIBC static int copyvec(evStream *str, const struct iovec *iov, int iocnt); static void consume(evStream *str, size_t bytes); static void done(evContext opaqueCtx, evStream *str); static void writable(evContext opaqueCtx, void *uap, int fd, int evmask); static void readable(evContext opaqueCtx, void *uap, int fd, int evmask); +#endif struct iovec evConsIovec(void *buf, size_t cnt) { @@ -53,6 +59,7 @@ evConsIovec(void *buf, size_t cnt) { return (ret); } +#ifndef _LIBC int evWrite(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, evStreamFunc func, void *uap, evStreamID *id) @@ -304,3 +311,4 @@ readable(evContext opaqueCtx, void *uap, int fd, int evmask) { if (str->ioDone <= 0 || str->ioDone == str->ioTotal) done(opaqueCtx, str); } +#endif /* !_LIBC */ diff --git a/contrib/bind-9.3/lib/bind/isc/ev_timers.c b/contrib/bind-9.3/lib/bind/isc/ev_timers.c index 11433fbffa..b6df4e3758 100644 --- a/contrib/bind-9.3/lib/bind/isc/ev_timers.c +++ b/contrib/bind-9.3/lib/bind/isc/ev_timers.c @@ -26,12 +26,16 @@ static const char rcsid[] = "$Id: ev_timers.c,v 1.2.2.1.4.5 2004/03/17 02:39:13 /* Import. */ #include "port_before.h" +#ifndef _LIBC #include "fd_setsize.h" +#endif #include +#ifndef _LIBC #include -#include +#endif +#include "isc/eventlib.h" #include "eventlib_p.h" #include "port_after.h" @@ -43,6 +47,9 @@ static const char rcsid[] = "$Id: ev_timers.c,v 1.2.2.1.4.5 2004/03/17 02:39:13 /* Forward. */ +#ifdef _LIBC +static int __evOptMonoTime; +#else static int due_sooner(void *, void *); static void set_index(void *, int); static void free_timer(void *, void *); @@ -58,7 +65,7 @@ typedef struct { struct timespec max_idle; evTimer * timer; } idle_timer; - +#endif /* Public. */ struct timespec @@ -138,12 +145,14 @@ evUTCTime() { return (evTimeSpec(now)); } +#ifndef _LIBC struct timespec evLastEventTime(evContext opaqueCtx) { evContext_p *ctx = opaqueCtx.opaque; return (ctx->lastEventTime); } +#endif struct timespec evTimeSpec(struct timeval tv) { @@ -154,6 +163,7 @@ evTimeSpec(struct timeval tv) { return (ts); } +#if !defined(USE_KQUEUE) || !defined(_LIBC) struct timeval evTimeVal(struct timespec ts) { struct timeval tv; @@ -162,7 +172,9 @@ evTimeVal(struct timespec ts) { tv.tv_usec = ts.tv_nsec / 1000; return (tv); } +#endif +#ifndef _LIBC int evSetTimer(evContext opaqueCtx, evTimerFunc func, @@ -495,3 +507,4 @@ idle_timeout(evContext opaqueCtx, this->timer->inter = evSubTime(this->max_idle, idle); } } +#endif /* !_LIBC */ diff --git a/contrib/bind-9.3/lib/bind/isc/eventlib_p.h b/contrib/bind-9.3/lib/bind/isc/eventlib_p.h index 5c45ab83f6..bf47784a6e 100644 --- a/contrib/bind-9.3/lib/bind/isc/eventlib_p.h +++ b/contrib/bind-9.3/lib/bind/isc/eventlib_p.h @@ -38,9 +38,11 @@ #include #include +#ifndef _LIBC #include #include #include +#endif #define EV_MASK_ALL (EV_READ | EV_WRITE | EV_EXCEPT) #define EV_ERR(e) return (errno = (e), -1) @@ -85,6 +87,7 @@ typedef struct evConn { struct evConn * next; } evConn; +#ifndef _LIBC typedef struct evAccept { int fd; union { @@ -174,6 +177,7 @@ typedef struct evEvent_p { struct { const void *placeholder; } null; } u; } evEvent_p; +#endif /* !_LIBC */ #ifdef USE_POLL typedef struct { @@ -209,6 +213,7 @@ extern void __fd_set(int fd, __evEmulMask *maskp); #endif /* USE_POLL */ +#ifndef _LIBC typedef struct { /* Global. */ const evEvent_p *cur; @@ -273,8 +278,11 @@ void evDestroyTimers(const evContext_p *); /* ev_waits.c */ #define evFreeWait __evFreeWait evWait *evFreeWait(evContext_p *ctx, evWait *old); +#endif /* !_LIBC */ /* Global options */ +#ifndef _LIBC extern int __evOptMonoTime; +#endif /* !_LIBC */ #endif /*_EVENTLIB_P_H*/ diff --git a/contrib/bind-9.3/lib/bind/nameser/ns_print.c b/contrib/bind-9.3/lib/bind/nameser/ns_print.c index cb61cb1add..0ee3a2d70e 100644 --- a/contrib/bind-9.3/lib/bind/nameser/ns_print.c +++ b/contrib/bind-9.3/lib/bind/nameser/ns_print.c @@ -30,8 +30,13 @@ static const char rcsid[] = "$Id: ns_print.c,v 1.3.2.1.4.7 2004/09/16 07:01:12 m #include #include +#ifdef _LIBC +#include +#define INSIST(cond) assert(cond) +#else #include #include +#endif #include #include #include @@ -457,7 +462,11 @@ ns_sprintrrf(const u_char *msg, size_t msglen, goto formerr; /* Key flags, Protocol, Algorithm. */ +#ifndef _LIBC key_id = dst_s_dns_key_id(rdata, edata-rdata); +#else + key_id = 0; +#endif keyflags = ns_get16(rdata); rdata += NS_INT16SZ; protocol = *rdata++; algorithm = *rdata++; diff --git a/contrib/bind-9.3/lib/bind/nameser/ns_samedomain.c b/contrib/bind-9.3/lib/bind/nameser/ns_samedomain.c index d4ca550a7a..a5d039eb2d 100644 --- a/contrib/bind-9.3/lib/bind/nameser/ns_samedomain.c +++ b/contrib/bind-9.3/lib/bind/nameser/ns_samedomain.c @@ -140,6 +140,7 @@ ns_samedomain(const char *a, const char *b) { return (strncasecmp(cp, b, lb) == 0); } +#ifndef _LIBC /* * int * ns_subdomain(a, b) @@ -149,6 +150,7 @@ int ns_subdomain(const char *a, const char *b) { return (ns_samename(a, b) != 1 && ns_samedomain(a, b)); } +#endif /* * int diff --git a/contrib/bind-9.3/lib/bind/resolv/herror.c b/contrib/bind-9.3/lib/bind/resolv/herror.c index 58807e9678..c5266b08cd 100644 --- a/contrib/bind-9.3/lib/bind/resolv/herror.c +++ b/contrib/bind-9.3/lib/bind/resolv/herror.c @@ -55,6 +55,10 @@ static const char rcsid[] = "$Id: herror.c,v 1.2.206.1 2004/03/09 08:33:54 marka #include "port_before.h" +#ifdef _LIBC +#include "namespace.h" +#endif + #include #include #include @@ -66,7 +70,11 @@ static const char rcsid[] = "$Id: herror.c,v 1.2.206.1 2004/03/09 08:33:54 marka #include #include #include +#ifndef _LIBC #include +#else +#include "un-namespace.h" +#endif #include "port_after.h" @@ -110,7 +118,11 @@ herror(const char *s) { DE_CONST("\n", t); v->iov_base = t; v->iov_len = 1; +#ifndef _LIBC writev(STDERR_FILENO, iov, (v - iov) + 1); +#else + _writev(STDERR_FILENO, iov, (v - iov) + 1); +#endif } /* diff --git a/contrib/bind-9.3/lib/bind/resolv/mtctxres.c b/contrib/bind-9.3/lib/bind/resolv/mtctxres.c index 635bbd4400..e9dd65d57a 100644 --- a/contrib/bind-9.3/lib/bind/resolv/mtctxres.c +++ b/contrib/bind-9.3/lib/bind/resolv/mtctxres.c @@ -1,13 +1,18 @@ #include #ifdef DO_PTHREADS #include +#ifdef _LIBC +#include +#endif #endif #include #include #include #include -#include +#include "resolv_mt.h" +#ifndef _LIBC #include +#endif #include #ifdef DO_PTHREADS @@ -40,6 +45,7 @@ _mtctxres_init(void) { } #endif +#ifndef _LIBC /* * To support binaries that used the private MT-safe interface in * Solaris 8, we still need to provide the __res_enable_mt() @@ -49,6 +55,7 @@ int __res_enable_mt(void) { return (-1); } +#endif int __res_disable_mt(void) { @@ -99,6 +106,11 @@ ___mtctxres(void) { #ifdef DO_PTHREADS mtctxres_t *mt; +#ifdef _LIBC + if (pthread_main_np() != 0) + return (&sharedctx); +#endif + /* * This if clause should only be executed if we are linking * statically. When linked dynamically _mtctxres_init() should diff --git a/contrib/bind-9.3/lib/bind/resolv/res_comp.c b/contrib/bind-9.3/lib/bind/resolv/res_comp.c index 8cc99a7628..9daed6f6e6 100644 --- a/contrib/bind-9.3/lib/bind/resolv/res_comp.c +++ b/contrib/bind-9.3/lib/bind/resolv/res_comp.c @@ -261,3 +261,14 @@ u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); } u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); } #endif /*__ultrix__*/ #endif /*BIND_4_COMPAT*/ + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef dn_comp +__weak_reference(__dn_comp, dn_comp); +#undef dn_expand +__weak_reference(__dn_expand, dn_expand); +#endif diff --git a/contrib/bind-9.3/lib/bind/resolv/res_data.c b/contrib/bind-9.3/lib/bind/resolv/res_data.c index 204e03d685..1917dd0c0d 100644 --- a/contrib/bind-9.3/lib/bind/resolv/res_data.c +++ b/contrib/bind-9.3/lib/bind/resolv/res_data.c @@ -40,7 +40,9 @@ static const char rcsid[] = "$Id: res_data.c,v 1.1.206.2 2004/03/16 12:34:18 mar #include #include "port_after.h" +#ifndef _LIBC #undef _res +#endif const char *_res_opcodes[] = { "QUERY", @@ -71,11 +73,13 @@ const char *_res_sectioncodes[] = { #endif #ifndef __BIND_NOSTATIC +#ifndef _LIBC struct __res_state _res # if defined(__BIND_RES_TEXT) = { RES_TIMEOUT, } /* Motorola, et al. */ # endif ; +#endif /* !_LIBC */ /* Proto. */ @@ -107,7 +111,11 @@ res_init(void) { if (!_res.retrans) _res.retrans = RES_TIMEOUT; if (!_res.retry) +#ifndef _LIBC _res.retry = 4; +#else + _res.retry = RES_DFLRETRY; +#endif if (!(_res.options & RES_INIT)) _res.options = RES_DEFAULT; @@ -181,6 +189,7 @@ res_query(const char *name, /* domain name */ return (res_nquery(&_res, name, class, type, answer, anslen)); } +#ifndef _LIBC void res_send_setqhook(res_send_qhook hook) { _res.qhook = hook; @@ -190,6 +199,7 @@ void res_send_setrhook(res_send_rhook hook) { _res.rhook = hook; } +#endif int res_isourserver(const struct sockaddr_in *inp) { @@ -206,6 +216,7 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { return (res_nsend(&_res, buf, buflen, ans, anssiz)); } +#ifndef _LIBC int res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, u_char *ans, int anssiz) @@ -217,6 +228,7 @@ res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz)); } +#endif void res_close(void) { @@ -264,6 +276,14 @@ res_querydomain(const char *name, answer, anslen)); } +#ifdef _LIBC +int +res_opt(int n0, u_char *buf, int buflen, int anslen) +{ + return (res_nopt(&_res, n0, buf, buflen, anslen)); +} +#endif + const char * hostalias(const char *name) { static char abuf[MAXDNAME]; @@ -288,4 +308,27 @@ local_hostname_length(const char *hostname) { } #endif /*ultrix*/ +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef res_init +__weak_reference(__res_init, res_init); +#undef p_query +__weak_reference(__p_query, p_query); +#undef res_mkquery +__weak_reference(__res_mkquery, res_mkquery); +#undef res_query +__weak_reference(__res_query, res_query); +#undef res_send +__weak_reference(__res_send, res_send); +#undef res_close +__weak_reference(__res_close, _res_close); +#undef res_search +__weak_reference(__res_search, res_search); +#undef res_querydomain +__weak_reference(__res_querydomain, res_querydomain); +#endif + #endif diff --git a/contrib/bind-9.3/lib/bind/resolv/res_debug.c b/contrib/bind-9.3/lib/bind/resolv/res_debug.c index 8dda12c5e8..eaae7a27d8 100644 --- a/contrib/bind-9.3/lib/bind/resolv/res_debug.c +++ b/contrib/bind-9.3/lib/bind/resolv/res_debug.c @@ -113,7 +113,7 @@ static const char rcsid[] = "$Id: res_debug.c,v 1.3.2.5.4.6 2005/07/28 07:43:22 #include #include #include -#include +#include "resolv_mt.h" #include #include #include @@ -375,7 +375,7 @@ const struct res_sym __p_class_syms[] = { /* * Names of message sections. */ -const struct res_sym __p_default_section_syms[] = { +static const struct res_sym __p_default_section_syms[] = { {ns_s_qd, "QUERY", (char *)0}, {ns_s_an, "ANSWER", (char *)0}, {ns_s_ns, "AUTHORITY", (char *)0}, @@ -383,7 +383,7 @@ const struct res_sym __p_default_section_syms[] = { {0, (char *)0, (char *)0} }; -const struct res_sym __p_update_section_syms[] = { +static const struct res_sym __p_update_section_syms[] = { {S_ZONE, "ZONE", (char *)0}, {S_PREREQ, "PREREQUISITE", (char *)0}, {S_UPDATE, "UPDATE", (char *)0}, @@ -1161,3 +1161,24 @@ res_nametotype(const char *buf, int *successp) { *successp = success; return (result); } + +#ifdef _LIBC +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include . + */ +#undef fp_resstat +__weak_reference(__fp_resstat, fp_resstat); +#undef p_fqnname +__weak_reference(__p_fqnname, p_fqnname); +#undef sym_ston +__weak_reference(__sym_ston, sym_ston); +#undef sym_ntos +__weak_reference(__sym_ntos, sym_ntos); +#undef sym_ntop +__weak_reference(__sym_ntop, sym_ntop); +#undef dn_count_labels +__weak_reference(__dn_count_labels, dn_count_labels); +#undef p_secstodate +__weak_reference(__p_secstodate, p_secstodate); +#endif diff --git a/contrib/bind-9.3/lib/bind/resolv/res_findzonecut.c b/contrib/bind-9.3/lib/bind/resolv/res_findzonecut.c index 804beb6474..e8c18f9a66 100644 --- a/contrib/bind-9.3/lib/bind/resolv/res_findzonecut.c +++ b/contrib/bind-9.3/lib/bind/resolv/res_findzonecut.c @@ -39,7 +39,7 @@ static const char rcsid[] = "$Id: res_findzonecut.c,v 1.2.2.3.4.4 2005/10/11 00: #include #include -#include +#include "isc/list.h" #include "port_after.h" @@ -149,6 +149,7 @@ static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2); * keep going. for the NS and A queries this means we just give up. */ +#ifndef _LIBC int res_findzonecut(res_state statp, const char *dname, ns_class class, int opts, char *zname, size_t zsize, struct in_addr *addrs, int naddrs) @@ -173,6 +174,7 @@ res_findzonecut(res_state statp, const char *dname, ns_class class, int opts, free(u); return (result); } +#endif int res_findzonecut2(res_state statp, const char *dname, ns_class class, int opts, diff --git a/contrib/bind-9.3/lib/bind/resolv/res_init.c b/contrib/bind-9.3/lib/bind/resolv/res_init.c index fd82e87203..004d459fbb 100644 --- a/contrib/bind-9.3/lib/bind/resolv/res_init.c +++ b/contrib/bind-9.3/lib/bind/resolv/res_init.c @@ -75,6 +75,9 @@ static const char rcsid[] = "$Id: res_init.c,v 1.9.2.5.4.6 2006/08/30 23:23:01 m #include "port_before.h" +#ifdef _LIBC +#include "namespace.h" +#endif #include #include #include @@ -90,7 +93,9 @@ static const char rcsid[] = "$Id: res_init.c,v 1.9.2.5.4.6 2006/08/30 23:23:01 m #include #include #include - +#ifdef _LIBC +#include "un-namespace.h" +#endif #include "port_after.h" /* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */ @@ -246,7 +251,7 @@ __res_vinit(res_state statp, int preinit) { #endif /* SOLARIS2 */ /* Allow user to override the local domain definition */ - if ((cp = getenv("LOCALDOMAIN")) != NULL) { + if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) { (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); statp->defdname[sizeof(statp->defdname) - 1] = '\0'; haveenv++; @@ -383,6 +388,10 @@ __res_vinit(res_state statp, int preinit) { #ifdef RESOLVSORT if (MATCH(buf, "sortlist")) { struct in_addr a; + struct in6_addr a6; + int m, i; + u_char *u; + struct __res_state_ext *ext = statp->_u._ext.ext; cp = buf + sizeof("sortlist") - 1; while (nsort < MAXRESOLVSORT) { @@ -417,6 +426,57 @@ __res_vinit(res_state statp, int preinit) { statp->sort_list[nsort].mask = net_mask(statp->sort_list[nsort].addr); } + ext->sort_list[nsort].af = AF_INET; + ext->sort_list[nsort].addr.ina = + statp->sort_list[nsort].addr; + ext->sort_list[nsort].mask.ina.s_addr = + statp->sort_list[nsort].mask; + nsort++; + } + else if (inet_pton(AF_INET6, net, &a6) == 1) { + + ext->sort_list[nsort].af = AF_INET6; + ext->sort_list[nsort].addr.in6a = a6; + u = (u_char *)&ext->sort_list[nsort].mask.in6a; + *cp++ = n; + net = cp; + while (*cp && *cp != ';' && + isascii(*cp) && !isspace(*cp)) + cp++; + m = n; + n = *cp; + *cp = 0; + switch (m) { + case '/': + m = atoi(net); + break; + case '&': + if (inet_pton(AF_INET6, net, u) == 1) { + m = -1; + break; + } + /*FALLTHROUGH*/ + default: + m = sizeof(struct in6_addr) * CHAR_BIT; + break; + } + if (m >= 0) { + for (i = 0; i < sizeof(struct in6_addr); i++) { + if (m <= 0) { + *u = 0; + } else { + m -= CHAR_BIT; + *u = (u_char)~0; + if (m < 0) + *u <<= -m; + } + u++; + } + } + statp->sort_list[nsort].addr.s_addr = + (u_int32_t)0xffffffff; + statp->sort_list[nsort].mask = + (u_int32_t)0xffffffff; nsort++; } *cp = n; @@ -479,7 +539,9 @@ __res_vinit(res_state statp, int preinit) { #endif } - if ((cp = getenv("RES_OPTIONS")) != NULL) + if (issetugid()) + statp->options |= RES_NOALIASES; + else if ((cp = getenv("RES_OPTIONS")) != NULL) res_setoptions(statp, cp, "env"); statp->options |= RES_INIT; return (0); @@ -499,7 +561,9 @@ res_setoptions(res_state statp, const char *options, const char *source) { const char *cp = options; int i; +#ifndef _LIBC struct __res_state_ext *ext = statp->_u._ext.ext; +#endif #ifdef DEBUG if (statp->options & RES_DEBUG) @@ -573,6 +637,10 @@ res_setoptions(res_state statp, const char *options, const char *source) statp->options |= RES_NOTLDQUERY; } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { statp->options |= RES_USE_INET6; + } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) { + statp->options |= RES_INSECURE1; + } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) { + statp->options |= RES_INSECURE2; } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { statp->options |= RES_ROTATE; } else if (!strncmp(cp, "no-check-names", @@ -584,6 +652,7 @@ res_setoptions(res_state statp, const char *options, const char *source) statp->options |= RES_USE_EDNS0; } #endif +#ifndef _LIBC else if (!strncmp(cp, "dname", sizeof("dname") - 1)) { statp->options |= RES_USE_DNAME; } @@ -613,10 +682,13 @@ res_setoptions(res_state statp, const char *options, const char *source) ~RES_NO_NIBBLE2; } } +#endif else { /* XXX - print a warning here? */ } +#ifndef _LIBC skip: +#endif /* skip to next run of spaces */ while (*cp && *cp != ' ' && *cp != '\t') cp++; @@ -659,13 +731,21 @@ res_nclose(res_state statp) { int ns; if (statp->_vcsock >= 0) { +#ifndef _LIBC (void) close(statp->_vcsock); +#else + _close(statp->_vcsock); +#endif statp->_vcsock = -1; statp->_flags &= ~(RES_F_VC | RES_F_CONN); } for (ns = 0; ns < statp->_u._ext.nscount; ns++) { if (statp->_u._ext.nssocks[ns] != -1) { +#ifndef _LIBC (void) close(statp->_u._ext.nssocks[ns]); +#else + _close(statp->_u._ext.nssocks[ns]); +#endif statp->_u._ext.nssocks[ns] = -1; } } @@ -680,6 +760,7 @@ res_ndestroy(res_state statp) { statp->_u._ext.ext = NULL; } +#ifndef _LIBC const char * res_get_nibblesuffix(res_state statp) { if (statp->_u._ext.ext) @@ -693,6 +774,7 @@ res_get_nibblesuffix2(res_state statp) { return (statp->_u._ext.ext->nsuffix2); return ("ip6.int"); } +#endif void res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) { diff --git a/contrib/bind-9.3/lib/bind/resolv/res_mkquery.c b/contrib/bind-9.3/lib/bind/resolv/res_mkquery.c index 89000edf6a..8d888e7555 100644 --- a/contrib/bind-9.3/lib/bind/resolv/res_mkquery.c +++ b/contrib/bind-9.3/lib/bind/resolv/res_mkquery.c @@ -234,6 +234,8 @@ res_nopt(res_state statp, ns_put16(T_OPT, cp); /* TYPE */ cp += INT16SZ; + if (anslen > 0xffff) + anslen = 0xffff; /* limit to 16bit value */ ns_put16(anslen & 0xffff, cp); /* CLASS = UDP payload size */ cp += INT16SZ; *cp++ = NOERROR; /* extended RCODE */ diff --git a/contrib/bind-9.3/lib/bind/resolv/res_mkupdate.c b/contrib/bind-9.3/lib/bind/resolv/res_mkupdate.c index 01078f1a51..a135bf0547 100644 --- a/contrib/bind-9.3/lib/bind/resolv/res_mkupdate.c +++ b/contrib/bind-9.3/lib/bind/resolv/res_mkupdate.c @@ -44,6 +44,9 @@ static const char rcsid[] = "$Id: res_mkupdate.c,v 1.1.2.1.4.5 2005/10/14 05:43: #include #include +#ifdef _LIBC +#include "isc/list.h" +#endif #include "port_after.h" /* Options. Leave them on. */ @@ -58,8 +61,13 @@ static int getstr_str(char *, int, u_char **, u_char *); #define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2); /* Forward. */ - +#ifdef _LIBC +static +#endif int res_protocolnumber(const char *); +#ifdef _LIBC +static +#endif int res_servicenumber(const char *); /* @@ -89,7 +97,10 @@ res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) { u_int16_t rtype, rclass; u_int32_t n1, rttl; u_char *dnptrs[20], **dpp, **lastdnptr; - int siglen, keylen, certlen; +#ifndef _LIBC + int siglen; +#endif + int keylen, certlen; /* * Initialize header fields. @@ -445,6 +456,9 @@ res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) { return (-1); break; case ns_t_sig: +#ifdef _LIBC + return (-1); +#else { int sig_type, success, dateerror; u_int32_t exptime, timesigned; @@ -535,6 +549,7 @@ res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) { cp += siglen; break; } +#endif case ns_t_key: /* flags */ n = gethexnum_str(&startp, endp); @@ -980,6 +995,7 @@ res_buildservicelist() { endservent(); } +#ifndef _LIBC void res_destroyservicelist() { struct valuelist *slp, *slp_next; @@ -992,6 +1008,7 @@ res_destroyservicelist() { } servicelist = (struct valuelist *)0; } +#endif void res_buildprotolist(void) { @@ -1022,6 +1039,7 @@ res_buildprotolist(void) { endprotoent(); } +#ifndef _LIBC void res_destroyprotolist(void) { struct valuelist *plp, *plp_next; @@ -1033,6 +1051,7 @@ res_destroyprotolist(void) { } protolist = (struct valuelist *)0; } +#endif static int findservice(const char *s, struct valuelist **list) { @@ -1059,6 +1078,9 @@ findservice(const char *s, struct valuelist **list) { /* * Convert service name or (ascii) number to int. */ +#ifdef _LIBC +static +#endif int res_servicenumber(const char *p) { if (servicelist == (struct valuelist *)0) @@ -1069,6 +1091,9 @@ res_servicenumber(const char *p) { /* * Convert protocol name or (ascii) number to int. */ +#ifdef _LIBC +static +#endif int res_protocolnumber(const char *p) { if (protolist == (struct valuelist *)0) @@ -1076,6 +1101,7 @@ res_protocolnumber(const char *p) { return (findservice(p, &protolist)); } +#ifndef _LIBC static struct servent * cgetservbyport(u_int16_t port, const char *proto) { /* Host byte order. */ struct valuelist **list = &servicelist; @@ -1156,3 +1182,4 @@ res_servicename(u_int16_t port, const char *proto) { /* Host byte order. */ } return (ss->s_name); } +#endif diff --git a/contrib/bind-9.3/lib/bind/resolv/res_query.c b/contrib/bind-9.3/lib/bind/resolv/res_query.c index 5156ce84c0..62e953e4ab 100644 --- a/contrib/bind-9.3/lib/bind/resolv/res_query.c +++ b/contrib/bind-9.3/lib/bind/resolv/res_query.c @@ -86,6 +86,7 @@ static const char rcsid[] = "$Id: res_query.c,v 1.2.2.3.4.2 2004/03/16 12:34:19 #include #include #include +#include #include "port_after.h" /* Options. Leave them on. */ @@ -242,6 +243,21 @@ res_nsearch(res_state statp, answer, anslen); if (ret > 0 || trailing_dot) return (ret); + if (errno == ECONNREFUSED) { + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (-1); + } + switch (statp->res_h_errno) { + case NO_DATA: + case HOST_NOT_FOUND: + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) + break; + /* FALLTHROUGH */ + default: + return (-1); + } saved_herrno = statp->res_h_errno; tried_as_is++; } @@ -265,6 +281,9 @@ res_nsearch(res_state statp, (domain[0][0] == '.' && domain[0][1] == '\0')) root_on_list++; + if (root_on_list && tried_as_is) + continue; + ret = res_nquerydomain(statp, name, *domain, class, type, answer, anslen); @@ -297,9 +316,26 @@ res_nsearch(res_state statp, /* keep trying */ break; case TRY_AGAIN: + /* + * This can occur due to a server failure + * (that is, all listed servers have failed), + * or all listed servers have timed out. + * ((HEADER *)answer)->rcode may not be set + * to SERVFAIL in the case of a timeout. + * + * Either way we must return TRY_AGAIN in + * order to avoid non-deterministic + * return codes. + * For example, loaded name servers or races + * against network startup/validation (dhcp, + * ppp, etc) can cause the search to timeout + * on one search element, e.g. 'fu.bar.com', + * and return a definitive failure on the + * next search element, e.g. 'fu.'. + */ + got_servfail++; if (hp->rcode == SERVFAIL) { /* try next search element, if any */ - got_servfail++; break; } /* FALLTHROUGH */ @@ -316,6 +352,18 @@ res_nsearch(res_state statp, } } + switch (statp->res_h_errno) { + case NO_DATA: + case HOST_NOT_FOUND: + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) + break; + /* FALLTHROUGH */ + default: + goto giveup; + } + /* * If the query has not already been tried as is then try it * unless RES_NOTLDQUERY is set and there were no dots. @@ -335,6 +383,7 @@ res_nsearch(res_state statp, * else send back meaningless H_ERRNO, that being the one from * the last DNSRCH we did. */ +giveup: if (saved_herrno != -1) RES_SET_H_ERRNO(statp, saved_herrno); else if (got_nodata) @@ -401,6 +450,8 @@ res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { if (statp->options & RES_NOALIASES) return (NULL); + if (issetugid()) + return (NULL); file = getenv("HOSTALIASES"); if (file == NULL || (fp = fopen(file, "r")) == NULL) return (NULL); diff --git a/contrib/bind-9.3/lib/bind/resolv/res_send.c b/contrib/bind-9.3/lib/bind/resolv/res_send.c index c47dd49bc6..08abfe0cfe 100644 --- a/contrib/bind-9.3/lib/bind/resolv/res_send.c +++ b/contrib/bind-9.3/lib/bind/resolv/res_send.c @@ -78,8 +78,13 @@ static const char rcsid[] = "$Id: res_send.c,v 1.5.2.2.4.9 2006/10/16 23:00:50 m */ #include "port_before.h" +#ifndef USE_KQUEUE #include "fd_setsize.h" +#endif +#ifdef _LIBC +#include "namespace.h" +#endif #include #include #include @@ -99,16 +104,23 @@ static const char rcsid[] = "$Id: res_send.c,v 1.5.2.2.4.9 2006/10/16 23:00:50 m #include #include -#include +#include "isc/eventlib.h" #include "port_after.h" - +#ifdef USE_KQUEUE +#include +#else #ifdef USE_POLL #ifdef HAVE_STROPTS_H #include #endif #include #endif /* USE_POLL */ +#endif + +#ifdef _LIBC +#include "un-namespace.h" +#endif /* Options. Leave them on. */ #define DEBUG @@ -117,10 +129,8 @@ static const char rcsid[] = "$Id: res_send.c,v 1.5.2.2.4.9 2006/10/16 23:00:50 m #define EXT(res) ((res)->_u._ext) -#ifndef USE_POLL +#if !defined(USE_POLL) && !defined(USE_KQUEUE) static const int highestFD = FD_SETSIZE - 1; -#else -static int highestFD = 0; #endif /* Forward. */ @@ -129,14 +139,18 @@ static int get_salen __P((const struct sockaddr *)); static struct sockaddr * get_nsaddr __P((res_state, size_t)); static int send_vc(res_state, const u_char *, int, u_char *, int, int *, int); -static int send_dg(res_state, const u_char *, int, +static int send_dg(res_state, +#ifdef USE_KQUEUE + int, +#endif + const u_char *, int, u_char *, int, int *, int, int, int *, int *); static void Aerror(const res_state, FILE *, const char *, int, const struct sockaddr *, int); static void Perror(const res_state, FILE *, const char *, int); static int sock_eq(struct sockaddr *, struct sockaddr *); -#if defined(NEED_PSELECT) && !defined(USE_POLL) +#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE) static int pselect(int, void *, void *, void *, struct timespec *, const sigset_t *); @@ -289,11 +303,10 @@ res_nsend(res_state statp, const u_char *buf, int buflen, u_char *ans, int anssiz) { int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; - char abuf[NI_MAXHOST]; - -#ifdef USE_POLL - highestFD = sysconf(_SC_OPEN_MAX) - 1; +#ifdef USE_KQUEUE + int kq; #endif + char abuf[NI_MAXHOST]; /* No name servers or res_init() failure */ if (statp->nscount == 0 || EXT(statp).ext == NULL) { @@ -310,6 +323,13 @@ res_nsend(res_state statp, gotsomewhere = 0; terrno = ETIMEDOUT; +#ifdef USE_KQUEUE + if ((kq = kqueue()) < 0) { + Perror(statp, stderr, "kqueue", errno); + return (-1); + } +#endif + /* * If the ns_addr_list in the resolver context has changed, then * invalidate our cached copy and the associated timing data. @@ -333,7 +353,11 @@ res_nsend(res_state statp, if (EXT(statp).nssocks[ns] == -1) continue; peerlen = sizeof(peer); +#ifndef _LIBC if (getsockname(EXT(statp).nssocks[ns], +#else + if (_getsockname(EXT(statp).nssocks[ns], +#endif (struct sockaddr *)&peer, &peerlen) < 0) { needclose++; break; @@ -425,6 +449,9 @@ res_nsend(res_state statp, res_nclose(statp); goto next_ns; case res_done: +#ifdef USE_KQUEUE + _close(kq); +#endif return (resplen); case res_modified: /* give the hook another try */ @@ -458,7 +485,11 @@ res_nsend(res_state statp, resplen = n; } else { /* Use datagrams. */ - n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, + n = send_dg(statp, +#ifdef USE_KQUEUE + kq, +#endif + buf, buflen, ans, anssiz, &terrno, ns, try, &v_circuit, &gotsomewhere); if (n < 0) goto fail; @@ -517,11 +548,17 @@ res_nsend(res_state statp, } while (!done); } +#ifdef USE_KQUEUE + _close(kq); +#endif return (resplen); next_ns: ; } /*foreach ns*/ } /*foreach retry*/ res_nclose(statp); +#ifdef USE_KQUEUE + _close(kq); +#endif if (!v_circuit) { if (!gotsomewhere) errno = ECONNREFUSED; /* no nameservers found */ @@ -609,7 +646,11 @@ send_vc(res_state statp, struct sockaddr_storage peer; ISC_SOCKLEN_T size = sizeof peer; +#ifndef _LIBC if (getpeername(statp->_vcsock, +#else + if (_getpeername(statp->_vcsock, +#endif (struct sockaddr *)&peer, &size) < 0 || !sock_eq((struct sockaddr *)&peer, nsap)) { res_nclose(statp); @@ -621,11 +662,17 @@ send_vc(res_state statp, if (statp->_vcsock >= 0) res_nclose(statp); +#ifndef _LIBC statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); +#else + statp->_vcsock = _socket(nsap->sa_family, SOCK_STREAM, 0); +#endif +#if !defined(USE_POLL) && !defined(USE_KQUEUE) if (statp->_vcsock > highestFD) { res_nclose(statp); errno = ENOTSOCK; } +#endif if (statp->_vcsock < 0) { switch (errno) { case EPROTONOSUPPORT: @@ -642,7 +689,11 @@ send_vc(res_state statp, } } errno = 0; +#ifndef _LIBC if (connect(statp->_vcsock, nsap, nsaplen) < 0) { +#else + if (_connect(statp->_vcsock, nsap, nsaplen) < 0) { +#endif *terrno = errno; Aerror(statp, stderr, "connect/vc", errno, nsap, nsaplen); @@ -659,7 +710,11 @@ send_vc(res_state statp, iov[0] = evConsIovec(&len, INT16SZ); DE_CONST(buf, tmp); iov[1] = evConsIovec(tmp, buflen); +#ifndef _LIBC if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { +#else + if (_writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { +#endif *terrno = errno; Perror(statp, stderr, "write failed", errno); res_nclose(statp); @@ -671,7 +726,11 @@ send_vc(res_state statp, read_len: cp = ans; len = INT16SZ; +#ifndef _LIBC while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) { +#else + while ((n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) { +#endif cp += n; if ((len -= n) == 0) break; @@ -717,7 +776,11 @@ send_vc(res_state statp, return (0); } cp = ans; +#ifndef _LIBC while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){ +#else + while (len != 0 && (n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0){ +#endif cp += n; len -= n; } @@ -736,7 +799,11 @@ send_vc(res_state statp, while (len != 0) { char junk[PACKETSZ]; +#ifndef _LIBC n = read(statp->_vcsock, junk, +#else + n = _read(statp->_vcsock, junk, +#endif (len > sizeof junk) ? sizeof junk : len); if (n > 0) len -= n; @@ -767,7 +834,11 @@ send_vc(res_state statp, } static int -send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, +send_dg(res_state statp, +#ifdef USE_KQUEUE + int kq, +#endif + const u_char *buf, int buflen, u_char *ans, int anssiz, int *terrno, int ns, int try, int *v_circuit, int *gotsomewhere) { @@ -779,21 +850,31 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, struct sockaddr_storage from; ISC_SOCKLEN_T fromlen; int resplen, seconds, n, s; +#ifdef USE_KQUEUE + struct kevent kv; +#else #ifdef USE_POLL int polltimeout; struct pollfd pollfd; #else fd_set dsmask; +#endif #endif nsap = get_nsaddr(statp, ns); nsaplen = get_salen(nsap); if (EXT(statp).nssocks[ns] == -1) { +#ifndef _LIBC EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); +#else + EXT(statp).nssocks[ns] = _socket(nsap->sa_family, SOCK_DGRAM, 0); +#endif +#if !defined(USE_POLL) && !defined(USE_KQUEUE) if (EXT(statp).nssocks[ns] > highestFD) { res_nclose(statp); errno = ENOTSOCK; } +#endif if (EXT(statp).nssocks[ns] < 0) { switch (errno) { case EPROTONOSUPPORT: @@ -820,8 +901,21 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, * socket operation, and select returns if the * error message is received. We can thus detect * the absence of a nameserver without timing out. + * + * + * When the option "insecure1" is specified, we'd + * rather expect to see responses from an "unknown" + * address. In order to let the kernel accept such + * responses, do not connect the socket here. + * XXX: or do we need an explicit option to disable + * connecting? */ - if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { + if (!(statp->options & RES_INSECURE1) && +#ifndef _LIBC + connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { +#else + _connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { +#endif Aerror(statp, stderr, "connect(dg)", errno, nsap, nsaplen); res_nclose(statp); @@ -833,13 +927,28 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, } s = EXT(statp).nssocks[ns]; #ifndef CANNOT_CONNECT_DGRAM - if (send(s, (const char*)buf, buflen, 0) != buflen) { + if (statp->options & RES_INSECURE1) { +#ifndef _LIBC + if (sendto(s, +#else + if (_sendto(s, +#endif + (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) { + Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); + res_nclose(statp); + return (0); + } + } else if (send(s, (const char*)buf, buflen, 0) != buflen) { Perror(statp, stderr, "send", errno); res_nclose(statp); return (0); } #else /* !CANNOT_CONNECT_DGRAM */ +#ifndef _LIBC if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) +#else + if (_sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) +#endif { Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); res_nclose(statp); @@ -863,13 +972,18 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, now = evNowTime(); nonow: #ifndef USE_POLL - FD_ZERO(&dsmask); - FD_SET(s, &dsmask); if (evCmpTime(finish, now) > 0) timeout = evSubTime(finish, now); else timeout = evConsTime(0, 0); +#ifdef USE_KQUEUE + EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0); + n = _kevent(kq, &kv, 1, &kv, 1, &timeout); +#else + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); +#endif #else timeout = evSubTime(finish, now); if (timeout.tv_sec < 0) @@ -889,17 +1003,29 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, if (n < 0) { if (errno == EINTR) goto wait; +#ifdef USE_KQUEUE + Perror(statp, stderr, "kevent", errno); +#else #ifndef USE_POLL Perror(statp, stderr, "select", errno); #else Perror(statp, stderr, "poll", errno); #endif /* USE_POLL */ +#endif res_nclose(statp); return (0); } +#ifdef USE_KQUEUE + if (kv.ident != s) + goto wait; +#endif errno = 0; fromlen = sizeof(from); +#ifndef _LIBC resplen = recvfrom(s, (char*)ans, anssiz,0, +#else + resplen = _recvfrom(s, (char*)ans, anssiz,0, +#endif (struct sockaddr *)&from, &fromlen); if (resplen <= 0) { Perror(statp, stderr, "recvfrom", errno); @@ -1062,7 +1188,7 @@ sock_eq(struct sockaddr *a, struct sockaddr *b) { } } -#if defined(NEED_PSELECT) && !defined(USE_POLL) +#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE) /* XXX needs to move to the porting library. */ static int pselect(int nfds, void *rfds, void *wfds, void *efds, diff --git a/contrib/bind-9.3/lib/bind/resolv/res_update.c b/contrib/bind-9.3/lib/bind/resolv/res_update.c index 8783d8a764..d8ed05fe8a 100644 --- a/contrib/bind-9.3/lib/bind/resolv/res_update.c +++ b/contrib/bind-9.3/lib/bind/resolv/res_update.c @@ -43,7 +43,7 @@ static const char rcsid[] = "$Id: res_update.c,v 1.6.2.4.4.2 2004/03/16 12:34:20 #include #include -#include +#include "isc/list.h" #include #include "port_after.h" @@ -167,8 +167,16 @@ res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) { /* Send the update and remember the result. */ if (key != NULL) +#ifdef _LIBC + { + DPRINTF(("TSIG is not supported\n")); + RES_SET_H_ERRNO(statp, NO_RECOVERY); + goto done; + } +#else n = res_nsendsigned(statp, packet, n, key, answer, sizeof answer); +#endif else n = res_nsend(statp, packet, n, answer, sizeof answer); if (n < 0) { diff --git a/include/Makefile b/include/Makefile index 0ad7d7d801..5747d939b8 100644 --- a/include/Makefile +++ b/include/Makefile @@ -18,7 +18,8 @@ INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h ctype.h db.h \ mpool.h monetary.h ndbm.h netconfig.h \ netdb.h nl_types.h nlist.h nss.h nsswitch.h objformat.h \ paths.h pthread.h pthread_np.h pwd.h \ - ranlib.h readpassphrase.h regex.h regexp.h resolv.h re_comp.h rmd160.h \ + ranlib.h readpassphrase.h regex.h regexp.h \ + res_update.h resolv.h re_comp.h rmd160.h \ search.h setjmp.h sgtty.h \ signal.h stab.h stdarg.h stdbool.h stddef.h stdint.h stdio.h stdlib.h \ string.h stringlist.h strings.h struct.h sysexits.h tar.h time.h \ diff --git a/include/arpa/inet.h b/include/arpa/inet.h index 57f224f465..163f9106f5 100644 --- a/include/arpa/inet.h +++ b/include/arpa/inet.h @@ -2,7 +2,7 @@ * Copyright (c) 2004 The DragonFly Project. All rights reserved. * * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -14,8 +14,8 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. + * This product includes software developed by the University of + * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -40,7 +40,7 @@ * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT @@ -53,8 +53,8 @@ /* * @(#)inet.h 8.1 (Berkeley) 6/2/93 - * From: Id: inet.h,v 8.5 1997/01/29 08:48:09 vixie Exp $ - * $FreeBSD: src/include/arpa/inet.h,v 1.11.2.1 2001/04/21 14:53:03 ume Exp $ + * $Id: inet.h,v 1.2.18.1 2005/04/27 05:00:50 sra Exp $ + * $FreeBSD: src/include/arpa/inet.h,v 1.30 2007/08/24 20:25:52 bms Exp $ * $DragonFly: src/include/arpa/inet.h,v 1.5 2005/07/13 12:49:56 joerg Exp $ */ @@ -66,17 +66,30 @@ #include #include -#ifndef _STRUCT_IN_ADDR_DECLARED -#define _STRUCT_IN_ADDR_DECLARED +/* Required for byteorder(3) functions. */ +#include + +#define INET_ADDRSTRLEN 16 +#define INET6_ADDRSTRLEN 46 + /* - * Internet address (a structure for historical reasons) + * XXX socklen_t is used by a POSIX.1-2001 interface, but not required by + * POSIX.1-2001. */ +#ifndef _SOCKLEN_T_DECLARED +typedef __socklen_t socklen_t; +#define _SOCKLEN_T_DECLARED +#endif + +#ifndef _STRUCT_IN_ADDR_DECLARED struct in_addr { in_addr_t s_addr; }; +#define _STRUCT_IN_ADDR_DECLARED #endif /* XXX all new diversions!! argh!! */ +#if __BSD_VISIBLE #define inet_addr __inet_addr #define inet_aton __inet_aton #define inet_lnaof __inet_lnaof @@ -86,42 +99,46 @@ struct in_addr { #define inet_network __inet_network #define inet_net_ntop __inet_net_ntop #define inet_net_pton __inet_net_pton +#define inet_cidr_ntop __inet_cidr_ntop +#define inet_cidr_pton __inet_cidr_pton #define inet_ntoa __inet_ntoa +#define inet_ntoa_r __inet_ntoa_r #define inet_pton __inet_pton #define inet_ntop __inet_ntop #define inet_nsap_addr __inet_nsap_addr #define inet_nsap_ntoa __inet_nsap_ntoa +#endif /* __BSD_VISIBLE */ + +__BEGIN_DECLS +in_addr_t inet_addr(const char *); +/*const*/ char *inet_ntoa(struct in_addr); +char *inet_ntoa_r(struct in_addr, char *buf, socklen_t size); +const char *inet_ntop(int, const void * __restrict, char * __restrict, + socklen_t); +int inet_pton(int, const char * __restrict, void * __restrict); -#ifndef htonl +#if __BSD_VISIBLE +int inet_aton(const char *, struct in_addr *); +in_addr_t inet_lnaof(struct in_addr); +struct in_addr inet_makeaddr(in_addr_t, in_addr_t); +char *inet_neta(in_addr_t, char *, size_t); +in_addr_t inet_netof(struct in_addr); +in_addr_t inet_network(const char *); +char *inet_net_ntop(int, const void *, int, char *, size_t); +int inet_net_pton(int, const char *, void *, size_t); +char *inet_cidr_ntop(int, const void *, int, char *, size_t); +int inet_cidr_pton(int, const char *, void *, int *); +unsigned inet_nsap_addr(const char *, unsigned char *, int); +char *inet_nsap_ntoa(int, const unsigned char *, char *); +#endif /* __BSD_VISIBLE */ +__END_DECLS + +#ifndef _BYTEORDER_FUNC_DEFINED +#define _BYTEORDER_FUNC_DEFINED #define htonl(x) __htonl(x) -#endif -#ifndef htons #define htons(x) __htons(x) -#endif -#ifndef ntohl #define ntohl(x) __ntohl(x) -#endif -#ifndef ntohs #define ntohs(x) __ntohs(x) #endif -__BEGIN_DECLS -int ascii2addr (int, const char *, void *); -char *addr2ascii (int, const void *, int, char *); -in_addr_t inet_addr (const char *); -int inet_aton (const char *, struct in_addr *); -in_addr_t inet_lnaof (struct in_addr); -struct in_addr inet_makeaddr (in_addr_t, in_addr_t); -char * inet_neta (in_addr_t, char *, size_t); -in_addr_t inet_netof (struct in_addr); -in_addr_t inet_network (const char *); -char *inet_net_ntop (int, const void *, int, char *, size_t); -int inet_net_pton (int, const char *, void *, size_t); -char *inet_ntoa (struct in_addr); -int inet_pton (int, const char *, void *); -const char *inet_ntop (int, const void *, char *, size_t); -u_int inet_nsap_addr (const char *, u_char *, int); -char *inet_nsap_ntoa (int, const u_char *, char *); -__END_DECLS - -#endif /* !_INET_H_ */ +#endif /* !_ARPA_INET_H_ */ diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h index 70ff02f7ff..db4bd8ac9f 100644 --- a/include/arpa/nameser.h +++ b/include/arpa/nameser.h @@ -32,25 +32,25 @@ */ /* - * Copyright (c) 1996 by Internet Software Consortium. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 by 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. */ /* - * From: Id: nameser.h,v 8.16 1998/02/06 00:35:58 halley Exp - * $FreeBSD: src/include/arpa/nameser.h,v 1.14.2.1 2001/06/15 22:08:27 ume Exp $ + * $Id: nameser.h,v 1.7.18.2 2008/04/03 23:15:15 marka Exp $ + * $FreeBSD: src/include/arpa/nameser.h,v 1.21 2008/12/14 19:39:53 ume Exp $ * $DragonFly: src/include/arpa/nameser.h,v 1.5 2007/04/18 18:39:11 swildner Exp $ */ @@ -59,25 +59,25 @@ #define BIND_4_COMPAT +#include #include #include /* - * revision information. this is the release date in YYYYMMDD format. - * it can change every day so the right thing to do with it is use it - * in preprocessor commands such as "#if (__NAMESER > 19931104)". do not - * compare for equality; rather, use it to determine whether your libnameser.a - * is new enough to contain a certain feature. + * Revision information. This is the release date in YYYYMMDD format. + * It can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not + * compare for equality; rather, use it to determine whether your libbind.a + * contains a new enough lib/nameser/ to support the feature you need. */ -/* XXXRTH I made this bigger than __BIND in 4.9.5 T6B */ -#define __NAMESER 19961001 /* New interface version stamp. */ - +#define __NAMESER 19991006 /* New interface version stamp. */ /* * Define constants based on RFC 883, RFC 1034, RFC 1035 */ -#define NS_PACKETSZ 512 /* maximum packet size */ +#define NS_PACKETSZ 512 /* default UDP packet size */ #define NS_MAXDNAME 1025 /* maximum domain name */ +#define NS_MAXMSG 65535 /* maximum message size */ #define NS_MAXCDNAME 255 /* maximum compressed domain name */ #define NS_MAXLABEL 63 /* maximum length of domain label */ #define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */ @@ -90,7 +90,6 @@ #define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */ #define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */ #define NS_DEFAULTPORT 53 /* For both TCP and UDP. */ - /* * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord() * in synch with it. @@ -117,7 +116,7 @@ typedef struct __ns_msg { const u_char *_sections[ns_s_max]; ns_sect _sect; int _rrnum; - const u_char *_ptr; + const u_char *_msg_ptr; } ns_msg; /* Private data structure - do not use from outside library. */ @@ -125,10 +124,7 @@ struct _ns_flagdata { int mask, shift; }; extern struct _ns_flagdata _ns_flagdata[]; /* Accessor macros - this is part of the public interface. */ -#define ns_msg_getflag(handle, flag) ( \ - ((handle)._flags & _ns_flagdata[flag].mask) \ - >> _ns_flagdata[flag].shift \ - ) + #define ns_msg_id(handle) ((handle)._id + 0) #define ns_msg_base(handle) ((handle)._msg + 0) #define ns_msg_end(handle) ((handle)._eom + 0) @@ -139,7 +135,7 @@ extern struct _ns_flagdata _ns_flagdata[]; * This is a parsed record. It is caller allocated and has no dynamic data. */ typedef struct __ns_rr { - char name[NS_MAXDNAME]; /* XXX need to malloc */ + char name[NS_MAXDNAME]; u_int16_t type; u_int16_t rr_class; u_int32_t ttl; @@ -149,8 +145,8 @@ typedef struct __ns_rr { /* Accessor macros - this is part of the public interface. */ #define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".") -#define ns_rr_type(rr) ((rr).type + 0) -#define ns_rr_class(rr) ((rr).rr_class + 0) +#define ns_rr_type(rr) ((ns_type)((rr).type + 0)) +#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0)) #define ns_rr_ttl(rr) ((rr).ttl + 0) #define ns_rr_rdlen(rr) ((rr).rdlength + 0) #define ns_rr_rdata(rr) ((rr).rdata + 0) @@ -203,7 +199,13 @@ typedef enum __ns_rcode { ns_r_nxrrset = 8, /* RRset does not exist */ ns_r_notauth = 9, /* Not authoritative for zone */ ns_r_notzone = 10, /* Zone of record different from zone section */ - ns_r_max = 11 + ns_r_max = 11, + /* The following are EDNS extended rcodes */ + ns_r_badvers = 16, + /* The following are TSIG errors */ + ns_r_badsig = 16, + ns_r_badkey = 17, + ns_r_badtime = 18 } ns_rcode; /* BIND_UPDATE */ @@ -214,31 +216,40 @@ typedef enum __ns_update_operation { } ns_update_operation; /* - * This RR-like structure is particular to UPDATE. + * This structure is used for TSIG authenticated messages + */ +struct ns_tsig_key { + char name[NS_MAXDNAME], alg[NS_MAXDNAME]; + unsigned char *data; + int len; +}; +typedef struct ns_tsig_key ns_tsig_key; + +/* + * This structure is used for TSIG authenticated TCP messages */ -struct ns_updrec { - struct ns_updrec *r_prev; /* prev record */ - struct ns_updrec *r_next; /* next record */ - u_int8_t r_section; /* ZONE/PREREQUISITE/UPDATE */ - char * r_dname; /* owner of the RR */ - u_int16_t r_class; /* class number */ - u_int16_t r_type; /* type number */ - u_int32_t r_ttl; /* time to live */ - u_char * r_data; /* rdata fields as text string */ - u_int16_t r_size; /* size of r_data field */ - int r_opcode; /* type of operation */ - /* following fields for private use by the resolver/server routines */ - struct ns_updrec *r_grpnext; /* next record when grouped */ - struct databuf *r_dp; /* databuf to process */ - struct databuf *r_deldp; /* databuf's deleted/overwritten */ - u_int16_t r_zone; /* zone number on server */ +struct ns_tcp_tsig_state { + int counter; + struct dst_key *key; + void *ctx; + unsigned char sig[NS_PACKETSZ]; + int siglen; }; -typedef struct ns_updrec ns_updrec; +typedef struct ns_tcp_tsig_state ns_tcp_tsig_state; + +#define NS_TSIG_FUDGE 300 +#define NS_TSIG_TCP_COUNT 100 +#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT" + +#define NS_TSIG_ERROR_NO_TSIG -10 +#define NS_TSIG_ERROR_NO_SPACE -11 +#define NS_TSIG_ERROR_FORMERR -12 /* * Currently defined type values for resources and queries. */ typedef enum __ns_type { + ns_t_invalid = 0, /* Cookie. */ ns_t_a = 1, /* Host address. */ ns_t_ns = 2, /* Authoritative server. */ ns_t_md = 3, /* Mail destination. */ @@ -274,22 +285,42 @@ typedef enum __ns_type { ns_t_srv = 33, /* Server Selection. */ ns_t_atma = 34, /* ATM Address */ ns_t_naptr = 35, /* Naming Authority PoinTeR */ - ns_t_opt = 41, /* OPT pseudo-RR, RFC2761 */ - /* Query type values which do not appear in resource records. */ + ns_t_kx = 36, /* Key Exchange */ + ns_t_cert = 37, /* Certification record */ + ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */ + ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */ + ns_t_sink = 40, /* Kitchen sink (experimentatl) */ + ns_t_opt = 41, /* EDNS0 option (meta-RR) */ + ns_t_apl = 42, /* Address prefix list (RFC3123) */ + ns_t_tkey = 249, /* Transaction key */ + ns_t_tsig = 250, /* Transaction signature. */ ns_t_ixfr = 251, /* Incremental zone transfer. */ ns_t_axfr = 252, /* Transfer zone of authority. */ ns_t_mailb = 253, /* Transfer mailbox records. */ ns_t_maila = 254, /* Transfer mail agent records. */ ns_t_any = 255, /* Wildcard match. */ + ns_t_zxfr = 256, /* BIND-specific, nonstandard. */ ns_t_max = 65536 } ns_type; +/* Exclusively a QTYPE? (not also an RTYPE) */ +#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \ + (t) == ns_t_mailb || (t) == ns_t_maila) +/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */ +#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt) +/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */ +#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t)) +#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr) +#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \ + (t) == ns_t_zxfr) + /* * Values for class field */ typedef enum __ns_class { + ns_c_invalid = 0, /* Cookie. */ ns_c_in = 1, /* Internet. */ - /* Class 2 unallocated/unsupported. */ + ns_c_2 = 2, /* unallocated/unsupported. */ ns_c_chaos = 3, /* MIT Chaos-net. */ ns_c_hs = 4, /* MIT Hesiod. */ /* Query class values which do not appear in resource records */ @@ -298,9 +329,24 @@ typedef enum __ns_class { ns_c_max = 65536 } ns_class; -/* - * Flags field of the KEY RR rdata - */ +/* DNSSEC constants. */ + +typedef enum __ns_key_types { + ns_kt_rsa = 1, /* key type RSA/MD5 */ + ns_kt_dh = 2, /* Diffie Hellman */ + ns_kt_dsa = 3, /* Digital Signature Standard (MANDATORY) */ + ns_kt_private = 254 /* Private key type starts with OID */ +} ns_key_types; + +typedef enum __ns_cert_types { + cert_t_pkix = 1, /* PKIX (X.509v3) */ + cert_t_spki = 2, /* SPKI */ + cert_t_pgp = 3, /* PGP */ + cert_t_url = 253, /* URL private type */ + cert_t_oid = 254 /* OID private type */ +} ns_cert_types; + +/* Flags field of the KEY RR rdata. */ #define NS_KEY_TYPEMASK 0xC000 /* Mask for "type" bits */ #define NS_KEY_TYPE_AUTH_CONF 0x0000 /* Key usable for both */ #define NS_KEY_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */ @@ -309,35 +355,56 @@ typedef enum __ns_class { /* The type bits can also be interpreted independently, as single bits: */ #define NS_KEY_NO_AUTH 0x8000 /* Key unusable for authentication */ #define NS_KEY_NO_CONF 0x4000 /* Key unusable for confidentiality */ -#define NS_KEY_EXPERIMENTAL 0x2000 /* Security is *mandatory* if bit=0 */ -#define NS_KEY_RESERVED3 0x1000 /* reserved - must be zero */ +#define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */ +#define NS_KEY_EXTENDED_FLAGS 0x1000 /* reserved - must be zero */ #define NS_KEY_RESERVED4 0x0800 /* reserved - must be zero */ -#define NS_KEY_USERACCOUNT 0x0400 /* key is assoc. with a user acct */ -#define NS_KEY_ENTITY 0x0200 /* key is assoc. with entity eg host */ -#define NS_KEY_ZONEKEY 0x0100 /* key is zone key */ -#define NS_KEY_IPSEC 0x0080 /* key is for IPSEC (host or user)*/ -#define NS_KEY_EMAIL 0x0040 /* key is for email (MIME security) */ +#define NS_KEY_RESERVED5 0x0400 /* reserved - must be zero */ +#define NS_KEY_NAME_TYPE 0x0300 /* these bits determine the type */ +#define NS_KEY_NAME_USER 0x0000 /* key is assoc. with user */ +#define NS_KEY_NAME_ENTITY 0x0200 /* key is assoc. with entity eg host */ +#define NS_KEY_NAME_ZONE 0x0100 /* key is zone key */ +#define NS_KEY_NAME_RESERVED 0x0300 /* reserved meaning */ +#define NS_KEY_RESERVED8 0x0080 /* reserved - must be zero */ +#define NS_KEY_RESERVED9 0x0040 /* reserved - must be zero */ #define NS_KEY_RESERVED10 0x0020 /* reserved - must be zero */ #define NS_KEY_RESERVED11 0x0010 /* reserved - must be zero */ #define NS_KEY_SIGNATORYMASK 0x000F /* key can sign RR's of same name */ - -#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED3 | \ +#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \ NS_KEY_RESERVED4 | \ + NS_KEY_RESERVED5 | \ + NS_KEY_RESERVED8 | \ + NS_KEY_RESERVED9 | \ NS_KEY_RESERVED10 | \ NS_KEY_RESERVED11 ) - +#define NS_KEY_RESERVED_BITMASK2 0xFFFF /* no bits defined here */ /* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */ #define NS_ALG_MD5RSA 1 /* MD5 with RSA */ +#define NS_ALG_DH 2 /* Diffie Hellman KEY */ +#define NS_ALG_DSA 3 /* DSA KEY */ +#define NS_ALG_DSS NS_ALG_DSA #define NS_ALG_EXPIRE_ONLY 253 /* No alg, no security */ #define NS_ALG_PRIVATE_OID 254 /* Key begins with OID giving alg */ +/* Protocol values */ +/* value 0 is reserved */ +#define NS_KEY_PROT_TLS 1 +#define NS_KEY_PROT_EMAIL 2 +#define NS_KEY_PROT_DNSSEC 3 +#define NS_KEY_PROT_IPSEC 4 +#define NS_KEY_PROT_ANY 255 /* Signatures */ #define NS_MD5RSA_MIN_BITS 512 /* Size of a mod or exp in bits */ -#define NS_MD5RSA_MAX_BITS 2552 +#define NS_MD5RSA_MAX_BITS 4096 /* Total of binary mod and exp */ #define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3) /* Max length of text sig block */ #define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4) +#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8) +#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8) + +#define NS_DSA_SIG_SIZE 41 +#define NS_DSA_MIN_SIZE 213 +#define NS_DSA_MAX_BYTES 405 /* Offsets into SIG record rdata to find various values */ #define NS_SIG_TYPE 0 /* Type flags */ @@ -348,26 +415,31 @@ typedef enum __ns_class { #define NS_SIG_SIGNED 12 /* Signature time */ #define NS_SIG_FOOT 16 /* Key footprint */ #define NS_SIG_SIGNER 18 /* Domain name of who signed it */ - /* How RR types are represented as bit-flags in NXT records */ #define NS_NXT_BITS 8 #define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS))) #define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS))) #define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_MAX 127 +/* + * EDNS0 extended flags and option codes, host order. + */ +#define NS_OPT_DNSSEC_OK 0x8000U +#define NS_OPT_NSID 3 /* * Inline versions of get/put short/long. Pointer is advanced. */ -#define NS_GET16(s, cp) { \ +#define NS_GET16(s, cp) do { \ const u_char *t_cp = (const u_char *)(cp); \ (s) = ((u_int16_t)t_cp[0] << 8) \ | ((u_int16_t)t_cp[1]) \ ; \ (cp) += NS_INT16SZ; \ -} +} while (0) -#define NS_GET32(l, cp) { \ +#define NS_GET32(l, cp) do { \ const u_char *t_cp = (const u_char *)(cp); \ (l) = ((u_int32_t)t_cp[0] << 24) \ | ((u_int32_t)t_cp[1] << 16) \ @@ -375,17 +447,17 @@ typedef enum __ns_class { | ((u_int32_t)t_cp[3]) \ ; \ (cp) += NS_INT32SZ; \ -} +} while (0) -#define NS_PUT16(s, cp) { \ +#define NS_PUT16(s, cp) do { \ u_int16_t t_s = (u_int16_t)(s); \ u_char *t_cp = (u_char *)(cp); \ *t_cp++ = t_s >> 8; \ *t_cp = t_s; \ (cp) += NS_INT16SZ; \ -} +} while (0) -#define NS_PUT32(l, cp) { \ +#define NS_PUT32(l, cp) do { \ u_int32_t t_l = (u_int32_t)(l); \ u_char *t_cp = (u_char *)(cp); \ *t_cp++ = t_l >> 24; \ @@ -393,54 +465,114 @@ typedef enum __ns_class { *t_cp++ = t_l >> 8; \ *t_cp = t_l; \ (cp) += NS_INT32SZ; \ -} +} while (0) /* - * ANSI C identifier hiding. + * ANSI C identifier hiding for bind's lib/nameser. */ +#define ns_msg_getflag __ns_msg_getflag #define ns_get16 __ns_get16 #define ns_get32 __ns_get32 #define ns_put16 __ns_put16 #define ns_put32 __ns_put32 #define ns_initparse __ns_initparse +#define ns_skiprr __ns_skiprr #define ns_parserr __ns_parserr #define ns_sprintrr __ns_sprintrr #define ns_sprintrrf __ns_sprintrrf #define ns_format_ttl __ns_format_ttl #define ns_parse_ttl __ns_parse_ttl +#if 0 +#define ns_datetosecs __ns_datetosecs +#endif +#define ns_name_ntol __ns_name_ntol #define ns_name_ntop __ns_name_ntop #define ns_name_pton __ns_name_pton #define ns_name_unpack __ns_name_unpack #define ns_name_pack __ns_name_pack #define ns_name_compress __ns_name_compress #define ns_name_uncompress __ns_name_uncompress +#define ns_name_skip __ns_name_skip +#define ns_name_rollback __ns_name_rollback +#if 0 +#define ns_sign __ns_sign +#define ns_sign2 __ns_sign2 +#define ns_sign_tcp __ns_sign_tcp +#define ns_sign_tcp2 __ns_sign_tcp2 +#define ns_sign_tcp_init __ns_sign_tcp_init +#define ns_find_tsig __ns_find_tsig +#define ns_verify __ns_verify +#define ns_verify_tcp __ns_verify_tcp +#define ns_verify_tcp_init __ns_verify_tcp_init +#endif +#define ns_samedomain __ns_samedomain +#if 0 +#define ns_subdomain __ns_subdomain +#endif +#define ns_makecanon __ns_makecanon +#define ns_samename __ns_samename __BEGIN_DECLS -u_int ns_get16 (const u_char *); -u_long ns_get32 (const u_char *); -void ns_put16 (u_int, u_char *); -void ns_put32 (u_long, u_char *); -int ns_initparse (const u_char *, int, ns_msg *); -int ns_parserr (ns_msg *, ns_sect, int, ns_rr *); -int ns_sprintrr (const ns_msg *, const ns_rr *, - const char *, const char *, char *, size_t); -int ns_sprintrrf (const u_char *, size_t, const char *, - ns_class, ns_type, u_long, const u_char *, - size_t, const char *, const char *, - char *, size_t); -int ns_format_ttl (u_long, char *, size_t); -int ns_parse_ttl (const char *, u_long *); -int ns_name_ntop (const u_char *, char *, size_t); -int ns_name_pton (const char *, u_char *, size_t); -int ns_name_unpack (const u_char *, const u_char *, - const u_char *, u_char *, size_t); -int ns_name_pack (const u_char *, u_char *, int, - const u_char **, const u_char **); -int ns_name_uncompress (const u_char *, const u_char *, - const u_char *, char *, size_t); -int ns_name_compress (const char *, u_char *, size_t, - const u_char **, const u_char **); -int ns_name_skip (const u_char **, const u_char *); +int ns_msg_getflag(ns_msg, int); +u_int ns_get16(const u_char *); +u_long ns_get32(const u_char *); +void ns_put16(u_int, u_char *); +void ns_put32(u_long, u_char *); +int ns_initparse(const u_char *, int, ns_msg *); +int ns_skiprr(const u_char *, const u_char *, ns_sect, int); +int ns_parserr(ns_msg *, ns_sect, int, ns_rr *); +int ns_sprintrr(const ns_msg *, const ns_rr *, + const char *, const char *, char *, size_t); +int ns_sprintrrf(const u_char *, size_t, const char *, + ns_class, ns_type, u_long, const u_char *, + size_t, const char *, const char *, + char *, size_t); +int ns_format_ttl(u_long, char *, size_t); +int ns_parse_ttl(const char *, u_long *); +#if 0 +u_int32_t ns_datetosecs(const char *cp, int *errp); +#endif +int ns_name_ntol(const u_char *, u_char *, size_t); +int ns_name_ntop(const u_char *, char *, size_t); +int ns_name_pton(const char *, u_char *, size_t); +int ns_name_unpack(const u_char *, const u_char *, + const u_char *, u_char *, size_t); +int ns_name_pack(const u_char *, u_char *, int, + const u_char **, const u_char **); +int ns_name_uncompress(const u_char *, const u_char *, + const u_char *, char *, size_t); +int ns_name_compress(const char *, u_char *, size_t, + const u_char **, const u_char **); +int ns_name_skip(const u_char **, const u_char *); +void ns_name_rollback(const u_char *, const u_char **, + const u_char **); +#if 0 +int ns_sign(u_char *, int *, int, int, void *, + const u_char *, int, u_char *, int *, time_t); +int ns_sign2(u_char *, int *, int, int, void *, + const u_char *, int, u_char *, int *, time_t, + u_char **, u_char **); +int ns_sign_tcp(u_char *, int *, int, int, + ns_tcp_tsig_state *, int); +int ns_sign_tcp2(u_char *, int *, int, int, + ns_tcp_tsig_state *, int, + u_char **, u_char **); +int ns_sign_tcp_init(void *, const u_char *, int, + ns_tcp_tsig_state *); +u_char *ns_find_tsig(u_char *, u_char *); +int ns_verify(u_char *, int *, void *, + const u_char *, int, u_char *, int *, + time_t *, int); +int ns_verify_tcp(u_char *, int *, ns_tcp_tsig_state *, int); +int ns_verify_tcp_init(void *, const u_char *, int, + ns_tcp_tsig_state *); +#endif +int ns_samedomain(const char *, const char *); +#if 0 +int ns_subdomain(const char *, const char *); +#endif +int ns_makecanon(const char *, char *, size_t); +int ns_samename(const char *, const char *); __END_DECLS #ifdef BIND_4_COMPAT diff --git a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h index da6734e0c5..1b84a226ba 100644 --- a/include/arpa/nameser_compat.h +++ b/include/arpa/nameser_compat.h @@ -32,8 +32,8 @@ /* * from nameser.h 8.1 (Berkeley) 6/2/93 - * From: Id: nameser_compat.h,v 8.9 1998/03/20 23:25:10 halley Exp - * $FreeBSD: src/include/arpa/nameser_compat.h,v 1.2.2.1 2001/06/15 22:08:27 ume Exp $ + * $Id: nameser_compat.h,v 1.5.18.3 2006/05/19 02:36:00 marka Exp $ + * $FreeBSD: src/include/arpa/nameser_compat.h,v 1.7 2007/06/03 17:20:25 ume Exp $ * $DragonFly: src/include/arpa/nameser_compat.h,v 1.2 2003/06/17 04:25:58 dillon Exp $ */ @@ -44,15 +44,15 @@ #include -#if !defined(BYTE_ORDER) || \ - (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \ - BYTE_ORDER != PDP_ENDIAN) +#if !defined(_BYTE_ORDER) || \ + (_BYTE_ORDER != _BIG_ENDIAN && _BYTE_ORDER != _LITTLE_ENDIAN && \ + _BYTE_ORDER != _PDP_ENDIAN) /* you must determine what the correct bit order is for * your compiler - the next line is an intentional error * which will force your compiles to bomb until you fix * the above macros. */ - error "Undefined or invalid BYTE_ORDER"; +#error "Undefined or invalid _BYTE_ORDER"; #endif /* @@ -64,7 +64,7 @@ typedef struct { unsigned id :16; /* query identification number */ -#if BYTE_ORDER == BIG_ENDIAN +#if _BYTE_ORDER == _BIG_ENDIAN /* fields in third byte */ unsigned qr: 1; /* response flag */ unsigned opcode: 4; /* purpose of message */ @@ -78,7 +78,7 @@ typedef struct { unsigned cd: 1; /* checking disabled by resolver */ unsigned rcode :4; /* response code */ #endif -#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN +#if _BYTE_ORDER == _LITTLE_ENDIAN || _BYTE_ORDER == _PDP_ENDIAN /* fields in third byte */ unsigned rd :1; /* recursion desired */ unsigned tc :1; /* truncated message */ @@ -108,6 +108,7 @@ typedef struct { #define RRFIXEDSZ NS_RRFIXEDSZ #define INT32SZ NS_INT32SZ #define INT16SZ NS_INT16SZ +#define INT8SZ NS_INT8SZ #define INADDRSZ NS_INADDRSZ #define IN6ADDRSZ NS_IN6ADDRSZ #define INDIR_MASK NS_CMPRSFLGS @@ -135,6 +136,10 @@ typedef struct { #define NXRRSET ns_r_nxrrset #define NOTAUTH ns_r_notauth #define NOTZONE ns_r_notzone +/*#define BADSIG ns_r_badsig*/ +/*#define BADKEY ns_r_badkey*/ +/*#define BADTIME ns_r_badtime*/ + #define DELETE ns_uop_delete #define ADD ns_uop_add @@ -174,7 +179,9 @@ typedef struct { #define T_SRV ns_t_srv #define T_ATMA ns_t_atma #define T_NAPTR ns_t_naptr +#define T_A6 ns_t_a6 #define T_OPT ns_t_opt +#define T_TSIG ns_t_tsig #define T_IXFR ns_t_ixfr #define T_AXFR ns_t_axfr #define T_MAILB ns_t_mailb diff --git a/include/netdb.h b/include/netdb.h index 3d8b1e0c60..5cd521f3a7 100644 --- a/include/netdb.h +++ b/include/netdb.h @@ -55,26 +55,24 @@ /* * @(#)netdb.h 8.1 (Berkeley) 6/2/93 * From: Id: netdb.h,v 8.9 1996/11/19 08:39:29 vixie Exp $ - * $FreeBSD: src/include/netdb.h,v 1.14.2.5 2001/08/29 08:46:51 alfred Exp $ + * $FreeBSD: src/include/netdb.h,v 1.44 2006/05/21 11:27:28 ume Exp $ * $DragonFly: src/include/netdb.h,v 1.7 2008/10/04 22:09:16 swildner Exp $ */ #ifndef _NETDB_H_ #define _NETDB_H_ -#ifndef _MACHINE_STDINT_H_ -#include -#endif #include +#include #ifndef _SIZE_T_DECLARED -#define _SIZE_T_DECLARED -typedef __size_t size_t; +typedef __size_t size_t; +#define _SIZE_T_DECLARED #endif #ifndef _SOCKLEN_T_DECLARED -#define _SOCKLEN_T_DECLARED -typedef __socklen_t socklen_t; +typedef __socklen_t socklen_t; +#define _SOCKLEN_T_DECLARED #endif #ifndef _PATH_HEQUIV @@ -85,14 +83,14 @@ typedef __socklen_t socklen_t; #define _PATH_PROTOCOLS "/etc/protocols" #define _PATH_SERVICES "/etc/services" -extern int h_errno; +#define h_errno (*__h_errno()) /* * Structures returned by network data base library. All addresses are * supplied in host order, and returned in network order (suitable for * use in system calls). */ -struct hostent { +struct hostent { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address type */ @@ -101,25 +99,21 @@ struct hostent { #define h_addr h_addr_list[0] /* address, for backward compatibility */ }; -/* - * Assumption here is that a network number - * fits in an unsigned long -- probably a poor one. - */ -struct netent { +struct netent { char *n_name; /* official name of net */ char **n_aliases; /* alias list */ int n_addrtype; /* net address type */ - unsigned long n_net; /* network # */ + uint32_t n_net; /* network # */ }; -struct servent { +struct servent { char *s_name; /* official service name */ char **s_aliases; /* alias list */ int s_port; /* port # */ char *s_proto; /* protocol to use */ }; -struct protoent { +struct protoent { char *p_name; /* official protocol name */ char **p_aliases; /* alias list */ int p_proto; /* protocol # */ @@ -130,7 +124,7 @@ struct addrinfo { int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ - size_t ai_addrlen; /* length of ai_addr */ + socklen_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for hostname */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ @@ -138,7 +132,7 @@ struct addrinfo { /* * Error return codes from gethostbyname() and gethostbyaddr() - * (left in extern int h_errno). + * (left in h_errno). */ #define NETDB_INTERNAL -1 /* see errno */ @@ -178,7 +172,7 @@ struct addrinfo { /* valid flags for addrinfo (not a standard def, apps should not use it) */ #define AI_MASK \ (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | \ - AI_ADDRCONFIG) + AI_ADDRCONFIG) #define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */ #define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */ @@ -208,67 +202,77 @@ struct addrinfo { */ #define SCOPE_DELIMITER '%' -/* - * data types - basically forward decl for getnameinfo() - */ - __BEGIN_DECLS -void endhostent (void); -void endnetent (void); -void endnetgrent (void); -void endprotoent (void); -void endservent (void); -void freehostent (struct hostent *); -struct hostent *gethostbyaddr (const void *, socklen_t, int); -struct hostent *gethostbyname (const char *); -struct hostent *gethostbyname2 (const char *, int); -struct hostent *gethostent (void); -struct hostent *getipnodebyaddr (const void *, size_t, int, int *); -struct hostent *getipnodebyname (const char *, int, int, int *); -struct netent *getnetbyaddr (unsigned long, int); -struct netent *getnetbyname (const char *); -struct netent *getnetent (void); -int getnetgrent (char **, char **, char **); -struct protoent *getprotobyname (const char *); -struct protoent *getprotobynumber (int); -struct protoent *getprotoent (void); -struct servent *getservbyname (const char *, const char *); -struct servent *getservbyport (int, const char *); -struct servent *getservent (void); -void herror (const char *); -__const char *hstrerror (int); -int innetgr (const char *, const char *, const char *, - const char *); -void sethostent (int); -/* void sethostfile (const char *); */ -void setnetent (int); -void setprotoent (int); -int getaddrinfo (const char *, const char *, - const struct addrinfo *, struct addrinfo **); -int getnameinfo (const struct sockaddr *, socklen_t, char *, - size_t, char *, size_t, int); -void freeaddrinfo (struct addrinfo *); -const char *gai_strerror (int); -void setnetgrent (const char *); -void setservent (int); +void endhostent(void); +void endnetent(void); +void endnetgrent(void); +void endprotoent(void); +void endservent(void); +void freehostent(struct hostent *); +struct hostent *gethostbyaddr(const void *, socklen_t, int); +int gethostbyaddr_r(const void *, socklen_t, int, struct hostent *, + char *, size_t, struct hostent **, int *); +struct hostent *gethostbyname(const char *); +int gethostbyname_r(const char *, struct hostent *, char *, size_t, + struct hostent **, int *); +struct hostent *gethostbyname2(const char *, int); +int gethostbyname2_r(const char *, int, struct hostent *, char *, + size_t, struct hostent **, int *); +struct hostent *gethostent(void); +int gethostent_r(struct hostent *, char *, size_t, + struct hostent **, int *); +struct hostent *getipnodebyaddr(const void *, size_t, int, int *); +struct hostent *getipnodebyname(const char *, int, int, int *); +struct netent *getnetbyaddr(uint32_t, int); +int getnetbyaddr_r(uint32_t, int, struct netent *, char *, size_t, + struct netent**, int *); +struct netent *getnetbyname(const char *); +int getnetbyname_r(const char *, struct netent *, char *, size_t, + struct netent **, int *); +struct netent *getnetent(void); +int getnetent_r(struct netent *, char *, size_t, struct netent **, + int *); +int getnetgrent(char **, char **, char **); +struct protoent *getprotobyname(const char *); +int getprotobyname_r(const char *, struct protoent *, char *, + size_t, struct protoent **); +struct protoent *getprotobynumber(int); +int getprotobynumber_r(int, struct protoent *, char *, size_t, + struct protoent **); +struct protoent *getprotoent(void); +int getprotoent_r(struct protoent *, char *, size_t, + struct protoent **); +struct servent *getservbyname(const char *, const char *); +int getservbyname_r(const char *, const char *, struct servent *, + char *, size_t, struct servent **); +struct servent *getservbyport(int, const char *); +int getservbyport_r(int, const char *, struct servent *, char *, + size_t, struct servent **); +struct servent *getservent(void); +int getservent_r(struct servent *, char *, size_t, + struct servent **); +void herror(const char *); +__const char *hstrerror(int); +int innetgr(const char *, const char *, const char *, const char *); +void sethostent(int); +/* void sethostfile(const char *); */ +void setnetent(int); +void setprotoent(int); +int getaddrinfo(const char *, const char *, + const struct addrinfo *, struct addrinfo **); +int getnameinfo(const struct sockaddr *, socklen_t, char *, + size_t, char *, size_t, int); +void freeaddrinfo(struct addrinfo *); +const char *gai_strerror(int); +void setnetgrent(const char *); +void setservent(int); /* * PRIVATE functions specific to the FreeBSD implementation */ /* DO NOT USE THESE, THEY ARE SUBJECT TO CHANGE AND ARE NOT PORTABLE!!! */ -void _sethosthtent (int); -void _endhosthtent (void); -void _sethostdnsent (int); -void _endhostdnsent (void); -void _setnethtent (int); -void _endnethtent (void); -void _setnetdnsent (int); -void _endnetdnsent (void); -struct hostent * _gethostbynisname (const char *, int); -struct hostent * _gethostbynisaddr (const char *, int, int); -void _map_v4v6_address (const char *, char *); -void _map_v4v6_hostent (struct hostent *, char **, int *); +int * __h_errno(void); __END_DECLS #endif /* !_NETDB_H_ */ diff --git a/include/res_update.h b/include/res_update.h new file mode 100644 index 0000000000..dfcadcd0dc --- /dev/null +++ b/include/res_update.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999 by Internet Software Consortium, Inc. + * + * 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: res_update.h,v 1.2.18.1 2005/04/27 05:00:49 sra Exp $ + * $FreeBSD: src/include/res_update.h,v 1.3 2007/06/03 17:20:25 ume Exp $ + */ + +#ifndef __RES_UPDATE_H +#define __RES_UPDATE_H + +/*! \file */ + +#include +#include +#include + +/*% + * This RR-like structure is particular to UPDATE. + */ +struct ns_updrec { + struct { + struct ns_updrec *prev; + struct ns_updrec *next; + } r_link, r_glink; + ns_sect r_section; /*%< ZONE/PREREQUISITE/UPDATE */ + char * r_dname; /*%< owner of the RR */ + ns_class r_class; /*%< class number */ + ns_type r_type; /*%< type number */ + u_int32_t r_ttl; /*%< time to live */ + u_char * r_data; /*%< rdata fields as text string */ + u_int r_size; /*%< size of r_data field */ + int r_opcode; /*%< type of operation */ + /* following fields for private use by the resolver/server routines */ + struct databuf *r_dp; /*%< databuf to process */ + struct databuf *r_deldp; /*%< databuf's deleted/overwritten */ + u_int r_zone; /*%< zone number on server */ +}; +typedef struct ns_updrec ns_updrec; +typedef struct { + ns_updrec *head; + ns_updrec *tail; +} ns_updque; + +#define res_mkupdate __res_mkupdate +#define res_update __res_update +#define res_mkupdrec __res_mkupdrec +#define res_freeupdrec __res_freeupdrec +#define res_nmkupdate __res_nmkupdate +#define res_nupdate __res_nupdate + +int res_mkupdate(ns_updrec *, u_char *, int); +int res_update(ns_updrec *); +ns_updrec * res_mkupdrec(int, const char *, u_int, u_int, u_long); +void res_freeupdrec(ns_updrec *); +int res_nmkupdate(res_state, ns_updrec *, u_char *, int); +int res_nupdate(res_state, ns_updrec *, ns_tsig_key *); + +#endif /*__RES_UPDATE_H*/ diff --git a/include/resolv.h b/include/resolv.h index 4e74d16352..ca97b5b804 100644 --- a/include/resolv.h +++ b/include/resolv.h @@ -1,6 +1,6 @@ -/*- - * Copyright (c) 1983, 1987, 1989, 1993 - * The Regents of the University of California. All rights reserved. +/* + * Copyright (c) 1983, 1987, 1989 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,26 +32,26 @@ */ /* - * Portions Copyright (c) 1996 by Internet Software Consortium. + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996-1999 by 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. */ /* * @(#)resolv.h 8.1 (Berkeley) 6/2/93 - * From Id: resolv.h,v 8.12 1998/04/28 19:36:46 halley Exp $ - * $FreeBSD: src/include/resolv.h,v 1.19.2.1 2001/06/15 22:08:26 ume Exp $ + * $Id: resolv.h,v 1.19.18.4 2008/04/03 23:15:15 marka Exp $ + * $FreeBSD: src/include/resolv.h,v 1.33 2008/12/14 19:39:53 ume Exp $ * $DragonFly: src/include/resolv.h,v 1.4 2004/02/26 13:58:25 joerg Exp $ */ @@ -63,6 +63,7 @@ #include #include #include +#include /* * Revision information. This is the release date in YYYYMMDD format. @@ -72,18 +73,60 @@ * is new enough to contain a certain feature. */ -#define __RES 19960801 +#define __RES 20030124 /* + * This used to be defined in res_query.c, now it's in herror.c. + * [XXX no it's not. It's in irs/irs_data.c] + * It was + * never extern'd by any *.h file before it was placed here. For thread + * aware programs, the last h_errno value set is stored in res->h_errno. + * + * XXX: There doesn't seem to be a good reason for exposing RES_SET_H_ERRNO + * (and __h_errno_set) to the public via . + * XXX: __h_errno_set is really part of IRS, not part of the resolver. + * If somebody wants to build and use a resolver that doesn't use IRS, + * what do they do? Perhaps something like + * #ifdef WANT_IRS + * # define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x) + * #else + * # define RES_SET_H_ERRNO(r,x) (h_errno = (r)->res_h_errno = (x)) + * #endif + */ + +#define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x) +struct __res_state; /*%< forward */ +__BEGIN_DECLS +void __h_errno_set(struct __res_state *, int); +__END_DECLS + +/*% * Resolver configuration file. * Normally not present, but may contain the address of the - * inital name server(s) to query and the domain search list. + * initial name server(s) to query and the domain search list. */ #ifndef _PATH_RESCONF #define _PATH_RESCONF "/etc/resolv.conf" #endif +typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } + res_sendhookact; + +typedef res_sendhookact (*res_send_qhook)(struct sockaddr * const *, + const u_char **, int *, + u_char *, int, int *); + +typedef res_sendhookact (*res_send_rhook)(const struct sockaddr *, + const u_char *, int, u_char *, + int, int *); + +struct res_sym { + int number; /* Identifying number, like T_MX */ + const char *name; /* Its symbolic name, like "MX" */ + const char *humanname; /* Its fun name, like "mail exchanger" */ +}; + /* * Global defines and variables for resolver stub. */ @@ -91,13 +134,17 @@ #define MAXDFLSRCH 3 /* # default domain levels to try */ #define MAXDNSRCH 6 /* max # domains in search path */ #define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ - #define RES_TIMEOUT 5 /* min. seconds between retries */ #define MAXRESOLVSORT 10 /* number of net to sort on */ #define RES_MAXNDOTS 15 /* should reflect bit field size */ +#define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */ +#define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */ +#define RES_DFLRETRY 2 /* Default #/tries. */ +#define RES_MAXTIME 65535 /* Infinity, in milliseconds. */ +struct __res_state_ext; struct __res_state { - int retrans; /* retransmition time interval */ + int retrans; /* retransmission time interval */ int retry; /* number of times to retransmit */ u_long options; /* option flags - see below. */ int nscount; /* number of name servers */ @@ -115,23 +162,54 @@ struct __res_state { struct in_addr addr; u_int32_t mask; } sort_list[MAXRESOLVSORT]; - char pad[72]; /* on an i386 this means 512b total */ + res_send_qhook qhook; /* query hook */ + res_send_rhook rhook; /* response hook */ + int res_h_errno; /* last one set for this context */ + int _vcsock; /* PRIVATE: for res_send VC i/o */ + u_int _flags; /* PRIVATE: see below */ + u_int _pad; /* make _u 64 bit aligned */ + union { + /* On an 32-bit arch this means 512b total. */ + char pad[72 - 4*sizeof (int) - 2*sizeof (void *)]; + struct { + u_int16_t nscount; + u_int16_t nstimes[MAXNS]; /* ms. */ + int nssocks[MAXNS]; + struct __res_state_ext *ext; /* extention for IPv6 */ + } _ext; + } _u; +}; + +typedef struct __res_state *res_state; + +union res_sockaddr_union { + struct sockaddr_in sin; +#ifdef IN6ADDR_ANY_INIT + struct sockaddr_in6 sin6; +#endif +#ifdef ISC_ALIGN64 + int64_t __align64; /* 64bit alignment */ +#else + int32_t __align32; /* 32bit alignment */ +#endif + char __space[128]; /* max size */ }; -/* for INET6 */ /* - * replacement of __res_state, separated to keep binary compatibility. + * Resolver flags (used to be discrete per-module statics ints). */ -struct __res_state_ext { - struct sockaddr_storage nsaddr_list[MAXNS]; - struct { - int af; /* address family for addr, mask */ - union { - struct in_addr ina; - struct in6_addr in6a; - } addr, mask; - } sort_list[MAXRESOLVSORT]; -}; +#define RES_F_VC 0x00000001 /* socket is TCP */ +#define RES_F_CONN 0x00000002 /* socket is connected */ +#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors */ +#define RES_F__UNUSED 0x00000008 /* (unused) */ +#define RES_F_LASTMASK 0x000000F0 /* ordinal server of last res_nsend */ +#define RES_F_LASTSHIFT 4 /* bit position of LASTMASK "flag" */ +#define RES_GETLAST(res) (((res)._flags & RES_F_LASTMASK) >> RES_F_LASTSHIFT) + +/* res_findzonecut2() options */ +#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */ +#define RES_IPV4ONLY 0x00000002 /* IPv4 only */ +#define RES_IPV6ONLY 0x00000004 /* IPv6 only */ /* * Resolver options (keep these in synch with res_debug.c, please) @@ -150,11 +228,21 @@ struct __res_state_ext { #define RES_INSECURE2 0x00000800 /* type 2 security disabled */ #define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ #define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */ -#define RES_NOTLDQUERY 0x00004000 /* Don't query TLD names */ +#define RES_ROTATE 0x00004000 /* rotate ns list after each query */ +#define RES_NOCHECKNAME 0x00008000 /* do not check names for sanity. */ +#define RES_KEEPTSIG 0x00010000 /* do not strip TSIG records */ +#define RES_BLAST 0x00020000 /* blast all recursive servers */ +#define RES_NSID 0x00040000 /* request name server ID */ +#define RES_NOTLDQUERY 0x00100000 /* don't unqualified name as a tld */ +#define RES_USE_DNSSEC 0x00200000 /* use DNSSEC using OK bit in OPT */ +/* #define RES_DEBUG2 0x00400000 */ /* nslookup internal */ /* KAME extensions: use higher bit to avoid conflict with ISC use */ -#define RES_USE_EDNS0 0x40000000 /* use EDNS0 */ +#define RES_USE_DNAME 0x10000000 /* use DNAME */ +#define RES_USE_EDNS0 0x40000000 /* use EDNS0 if configured */ +#define RES_NO_NIBBLE2 0x80000000 /* disable alternate nibble lookup */ -#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH) +#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | \ + RES_DNSRCH | RES_NO_NIBBLE2) /* * Resolver "pfcode" values. Used by dig. @@ -173,84 +261,143 @@ struct __res_state_ext { #define RES_PRF_HEADX 0x00000800 #define RES_PRF_QUERY 0x00001000 #define RES_PRF_REPLY 0x00002000 -#define RES_PRF_INIT 0x00004000 -/* 0x00008000 */ +#define RES_PRF_INIT 0x00004000 +#define RES_PRF_TRUNC 0x00008000 +/* 0x00010000 */ -typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } - res_sendhookact; - -typedef res_sendhookact (*res_send_qhook)(struct sockaddr_in * const *, - const u_char **, int *, - u_char *, int, int *); - -typedef res_sendhookact (*res_send_rhook)(const struct sockaddr_in *, - const u_char *, int, - u_char *, int, int *); +/* Things involving an internal (static) resolver context. */ +__BEGIN_DECLS +extern struct __res_state *__res_state(void); +__END_DECLS +#define _res (*__res_state()) -struct res_sym { - int number; /* Identifying number, like T_MX */ - char * name; /* Its symbolic name, like "MX" */ - char * humanname; /* Its fun name, like "mail exchanger" */ -}; +#ifndef __BIND_NOSTATIC +#define fp_nquery __fp_nquery +#define fp_query __fp_query +#define hostalias __hostalias +#define p_query __p_query +#define res_close __res_close +#define res_init __res_init +#define res_isourserver __res_isourserver +#define res_mkquery __res_mkquery +#define res_opt __res_opt +#define res_query __res_query +#define res_querydomain __res_querydomain +#define res_search __res_search +#define res_send __res_send +#define res_sendsigned __res_sendsigned -extern struct __res_state _res; -/* for INET6 */ -extern struct __res_state_ext _res_ext; +__BEGIN_DECLS +void fp_nquery(const u_char *, int, FILE *); +void fp_query(const u_char *, FILE *); +const char *hostalias(const char *); +void p_query(const u_char *); +void res_close(void); +int res_init(void); +int res_isourserver(const struct sockaddr_in *); +int res_mkquery(int, const char *, int, int, const u_char *, + int, const u_char *, u_char *, int); +int res_opt(int, u_char *, int, int); +int res_query(const char *, int, int, u_char *, int); +int res_querydomain(const char *, const char *, int, int, + u_char *, int); +int res_search(const char *, int, int, u_char *, int); +int res_send(const u_char *, int, u_char *, int); +int res_sendsigned(const u_char *, int, ns_tsig_key *, + u_char *, int); +__END_DECLS +#endif +#if !defined(SHARED_LIBBIND) || defined(LIB) +/* + * If libbind is a shared object (well, DLL anyway) + * these externs break the linker when resolv.h is + * included by a lib client (like named) + * Make them go away if a client is including this + * + */ +extern const struct res_sym __p_key_syms[]; +extern const struct res_sym __p_cert_syms[]; extern const struct res_sym __p_class_syms[]; extern const struct res_sym __p_type_syms[]; +extern const struct res_sym __p_rcode_syms[]; +#endif /* SHARED_LIBBIND */ -/* Private routines shared between libc/net, named, nslookup and others. */ -#define res_hnok __res_hnok -#define res_ownok __res_ownok -#define res_mailok __res_mailok -#define res_dnok __res_dnok -#define sym_ston __sym_ston -#define sym_ntos __sym_ntos -#define sym_ntop __sym_ntop -#define b64_ntop __b64_ntop -#define b64_pton __b64_pton -#define loc_ntoa __loc_ntoa -#define loc_aton __loc_aton -#define fp_resstat __fp_resstat -#define p_query __p_query -#define dn_skipname __dn_skipname -#define fp_resstat __fp_resstat -#define fp_query __fp_query -#define fp_nquery __fp_nquery -#define hostalias __hostalias -#define putlong __putlong -#define putshort __putshort -#define p_class __p_class -#define p_time __p_time -#define p_type __p_type -#define p_query __p_query -#define p_cdnname __p_cdnname -#define p_section __p_section -#define p_cdname __p_cdname -#define p_fqnname __p_fqnname -#define p_fqname __p_fqname -#define p_option __p_option -#define p_secstodate __p_secstodate -#define dn_count_labels __dn_count_labels -#define dn_comp __dn_comp -#define dn_expand __dn_expand -#define res_init __res_init -#define res_randomid __res_randomid -#define res_query __res_query -#define res_search __res_search -#define res_querydomain __res_querydomain -#define res_mkquery __res_mkquery -#define res_send __res_send -#define res_isourserver __res_isourserver -#define res_nameinquery __res_nameinquery -#define res_queriesmatch __res_queriesmatch -#define res_close __res_close -#define res_opt __res_opt -#define res_mkupdate __res_mkupdate -#define res_mkupdrec __res_mkupdrec -#define res_freeupdrec __res_freeupdrec - +#define b64_ntop __b64_ntop +#define b64_pton __b64_pton +#define dn_comp __dn_comp +#define dn_count_labels __dn_count_labels +#define dn_expand __dn_expand +#define dn_skipname __dn_skipname +#define fp_resstat __fp_resstat +#define loc_aton __loc_aton +#define loc_ntoa __loc_ntoa +#define p_cdname __p_cdname +#define p_cdnname __p_cdnname +#define p_class __p_class +#define p_fqname __p_fqname +#define p_fqnname __p_fqnname +#define p_option __p_option +#define p_secstodate __p_secstodate +#define p_section __p_section +#define p_time __p_time +#define p_type __p_type +#define p_rcode __p_rcode +#define p_sockun __p_sockun +#define putlong __putlong +#define putshort __putshort +#define res_dnok __res_dnok +#if 0 +#define res_findzonecut __res_findzonecut +#endif +#define res_findzonecut2 __res_findzonecut2 +#define res_hnok __res_hnok +#define res_hostalias __res_hostalias +#define res_mailok __res_mailok +#define res_nameinquery __res_nameinquery +#define res_nclose __res_nclose +#define res_ninit __res_ninit +#define res_nmkquery __res_nmkquery +#define res_pquery __res_pquery +#define res_nquery __res_nquery +#define res_nquerydomain __res_nquerydomain +#define res_nsearch __res_nsearch +#define res_nsend __res_nsend +#if 0 +#define res_nsendsigned __res_nsendsigned +#endif +#define res_nisourserver __res_nisourserver +#define res_ownok __res_ownok +#define res_queriesmatch __res_queriesmatch +#define res_randomid __res_randomid +#define sym_ntop __sym_ntop +#define sym_ntos __sym_ntos +#define sym_ston __sym_ston +#define res_nopt __res_nopt +#define res_nopt_rdata __res_nopt_rdata +#define res_ndestroy __res_ndestroy +#define res_nametoclass __res_nametoclass +#define res_nametotype __res_nametotype +#define res_setservers __res_setservers +#define res_getservers __res_getservers +#if 0 +#define res_buildprotolist __res_buildprotolist +#define res_destroyprotolist __res_destroyprotolist +#define res_destroyservicelist __res_destroyservicelist +#define res_get_nibblesuffix __res_get_nibblesuffix +#define res_get_nibblesuffix2 __res_get_nibblesuffix2 +#endif +#define res_ourserver_p __res_ourserver_p +#if 0 +#define res_protocolname __res_protocolname +#define res_protocolnumber __res_protocolnumber +#endif +#define res_send_setqhook __res_send_setqhook +#define res_send_setrhook __res_send_setrhook +#if 0 +#define res_servicename __res_servicename +#define res_servicenumber __res_servicenumber +#endif __BEGIN_DECLS int res_hnok(const char *); int res_ownok(const char *); @@ -264,52 +411,76 @@ int b64_pton(char const *, u_char *, size_t); int loc_aton(const char *, u_char *); const char *loc_ntoa(const u_char *, char *); int dn_skipname(const u_char *, const u_char *); -void fp_resstat(struct __res_state *, FILE *); -void fp_query(const u_char *, FILE *); -void fp_nquery(const u_char *, int, FILE *); -const char *hostalias(const char *); void putlong(u_int32_t, u_char *); void putshort(u_int16_t, u_char *); +u_int16_t _getshort(const u_char *); +u_int32_t _getlong(const u_char *); const char *p_class(int); const char *p_time(u_int32_t); const char *p_type(int); -void p_query(const u_char *); +const char *p_rcode(int); +const char *p_sockun(union res_sockaddr_union, char *, size_t); const u_char *p_cdnname(const u_char *, const u_char *, int, FILE *); const u_char *p_cdname(const u_char *, const u_char *, FILE *); -const u_char *p_fqnname(const u_char *, const u_char *, - int, char *, int); +const u_char *p_fqnname(const u_char *, const u_char *, int, char *, int); const u_char *p_fqname(const u_char *, const u_char *, FILE *); const char *p_option(u_long); char *p_secstodate(u_long); int dn_count_labels(const char *); -int dn_comp(const char *, u_char *, int, - u_char **, u_char **); +int dn_comp(const char *, u_char *, int, u_char **, u_char **); int dn_expand(const u_char *, const u_char *, const u_char *, char *, int); -int res_init(void); u_int res_randomid(void); -int res_query(const char *, int, int, u_char *, int); -int res_search(const char *, int, int, u_char *, int); -int res_querydomain(const char *, const char *, int, int, - u_char *, int); -int res_mkquery(int, const char *, int, int, const u_char *, - int, const u_char *, u_char *, int); -int res_send(const u_char *, int, u_char *, int); -int res_isourserver(const struct sockaddr_in *); -int res_nameinquery(const char *, int, int, - const u_char *, const u_char *); +int res_nameinquery(const char *, int, int, const u_char *, + const u_char *); int res_queriesmatch(const u_char *, const u_char *, const u_char *, const u_char *); -void res_close(void); -int res_opt(int, u_char *, int, int); const char *p_section(int, int); -/* XXX The following depend on the ns_updrec typedef in arpa/nameser.h */ -#ifdef _ARPA_NAMESER_H_ -int res_update(ns_updrec *); -int res_mkupdate(ns_updrec *, u_char *, int); -ns_updrec *res_mkupdrec(int, const char *, u_int, u_int, u_long); -void res_freeupdrec(ns_updrec *); +/* Things involving a resolver context. */ +int res_ninit(res_state); +int res_nisourserver(const res_state, const struct sockaddr_in *); +void fp_resstat(const res_state, FILE *); +void res_pquery(const res_state, const u_char *, int, FILE *); +const char *res_hostalias(const res_state, const char *, char *, size_t); +int res_nquery(res_state, const char *, int, int, u_char *, int); +int res_nsearch(res_state, const char *, int, int, u_char *, int); +int res_nquerydomain(res_state, const char *, const char *, + int, int, u_char *, int); +int res_nmkquery(res_state, int, const char *, int, int, + const u_char *, int, const u_char *, + u_char *, int); +int res_nsend(res_state, const u_char *, int, u_char *, int); +#if 0 +int res_nsendsigned(res_state, const u_char *, int, + ns_tsig_key *, u_char *, int); +int res_findzonecut(res_state, const char *, ns_class, int, + char *, size_t, struct in_addr *, int); +#endif +int res_findzonecut2(res_state, const char *, ns_class, int, + char *, size_t, + union res_sockaddr_union *, int); +void res_nclose(res_state); +int res_nopt(res_state, int, u_char *, int, int); +int res_nopt_rdata(res_state, int, u_char *, int, u_char *, + u_short, u_short, u_char *); +void res_send_setqhook(res_send_qhook); +void res_send_setrhook(res_send_rhook); +int __res_vinit(res_state, int); +#if 0 +void res_destroyservicelist(void); +const char *res_servicename(u_int16_t, const char *); +const char *res_protocolname(int); +void res_destroyprotolist(void); +void res_buildprotolist(void); +const char *res_get_nibblesuffix(res_state); +const char *res_get_nibblesuffix2(res_state); #endif +void res_ndestroy(res_state); +u_int16_t res_nametoclass(const char *, int *); +u_int16_t res_nametotype(const char *, int *); +void res_setservers(res_state, const union res_sockaddr_union *, + int); +int res_getservers(res_state, union res_sockaddr_union *, int); __END_DECLS #endif /* !_RESOLV_H_ */ diff --git a/lib/libc/Makefile.inc b/lib/libc/Makefile.inc index 1e6f019757..bfc7ade651 100644 --- a/lib/libc/Makefile.inc +++ b/lib/libc/Makefile.inc @@ -33,6 +33,7 @@ NOASM= .include "${.CURDIR}/../libc/quad/Makefile.inc" .endif .include "${.CURDIR}/../libc/regex/Makefile.inc" +.include "${.CURDIR}/../libc/resolv/Makefile.inc" .include "${.CURDIR}/../libc/stdio/Makefile.inc" .include "${.CURDIR}/../libc/stdlib/Makefile.inc" .include "${.CURDIR}/../libc/stdtime/Makefile.inc" diff --git a/lib/libc/include/isc/platform.h b/lib/libc/include/isc/platform.h new file mode 100644 index 0000000000..1c9f63404e --- /dev/null +++ b/lib/libc/include/isc/platform.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: platform.h.in,v 1.2.6.2 2008/01/23 02:15:02 tbox Exp $ */ +/* $FreeBSD: src/lib/libc/include/isc/platform.h,v 1.1 2008/12/14 19:39:53 ume Exp $ */ + +/*! \file */ + +#ifndef ISC_PLATFORM_H +#define ISC_PLATFORM_H + +/* + * Define if the OS does not define struct timespec. + */ +#undef ISC_PLATFORM_NEEDTIMESPEC +#ifdef ISC_PLATFORM_NEEDTIMESPEC +#include /* For time_t */ +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; +#endif + +#endif diff --git a/lib/libc/include/port_after.h b/lib/libc/include/port_after.h new file mode 100644 index 0000000000..068916be66 --- /dev/null +++ b/lib/libc/include/port_after.h @@ -0,0 +1,11 @@ +/* $FreeBSD: src/lib/libc/include/port_after.h,v 1.2 2006/03/21 18:31:24 ume Exp $ */ + +#ifndef _PORT_AFTER_H_ +#define _PORT_AFTER_H_ + +#define HAVE_SA_LEN 1 +#define HAS_INET6_STRUCTS 1 +#define HAVE_SIN6_SCOPE_ID 1 +#define HAVE_TIME_R 1 + +#endif /* _PORT_AFTER_H_ */ diff --git a/lib/libc/include/port_before.h b/lib/libc/include/port_before.h new file mode 100644 index 0000000000..9bd12899d3 --- /dev/null +++ b/lib/libc/include/port_before.h @@ -0,0 +1,22 @@ +/* $FreeBSD: src/lib/libc/include/port_before.h,v 1.1 2006/03/21 15:37:15 ume Exp $ */ + +#ifndef _PORT_BEFORE_H_ +#define _PORT_BEFORE_H_ + +#define _LIBC 1 +#define DO_PTHREADS 1 +#define USE_KQUEUE 1 + +#define ISC_SOCKLEN_T socklen_t +#define ISC_FORMAT_PRINTF(fmt, args) \ + __attribute__((__format__(__printf__, fmt, args))) +#define DE_CONST(konst, var) \ + do { \ + union { const void *k; void *v; } _u; \ + _u.k = konst; \ + var = _u.v; \ + } while (0) + +#define UNUSED(x) (x) = (x) + +#endif /* _PORT_BEFORE_H_ */ diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc index 7b883781b0..fa1f3a8ba2 100644 --- a/lib/libc/net/Makefile.inc +++ b/lib/libc/net/Makefile.inc @@ -5,22 +5,21 @@ # machine-independent net sources .PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/net ${.CURDIR}/../libc/net -SRCS+= addr2ascii.c ascii2addr.c base64.c ether_addr.c eui64.c getaddrinfo.c \ +SRCS+= addr2ascii.c ascii2addr.c base64.c ether_addr.c eui64.c \ + gai_strerror.c getaddrinfo.c \ gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \ getifaddrs.c getnameinfo.c \ getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \ getproto.c getprotoent.c getprotoname.c \ - getservent.c herror.c inet_addr.c \ - if_indextoname.c if_nameindex.c if_nametoindex.c inet_lnaof.c \ - inet_makeaddr.c inet_net_ntop.c inet_net_pton.c inet_neta.c \ - inet_netof.c inet_network.c inet_ntoa.c inet_ntop.c \ - inet_pton.c ip6opt.c linkaddr.c map_v4v6.c name6.c ns_addr.c \ + getservent.c \ + if_indextoname.c if_nameindex.c if_nametoindex.c \ + ip6opt.c linkaddr.c map_v4v6.c name6.c ns_addr.c \ ns_name.c ns_netint.c \ ns_ntoa.c ns_parse.c ns_print.c ns_ttl.c nsap_addr.c \ nsdispatch.c nslexer.c nsparser.y nss_compat.c \ rcmd.c rcmdsh.c recv.c res_comp.c res_data.c res_debug.c \ - res_init.c res_mkquery.c res_mkupdate.c res_query.c res_send.c \ - res_update.c rthdr.c send.c vars.c + res_init.c res_mkquery.c res_query.c res_send.c \ + rthdr.c send.c vars.c # not supported: iso_addr.c # This isn't ready yet. diff --git a/lib/libc/net/gai_strerror.c b/lib/libc/net/gai_strerror.c new file mode 100644 index 0000000000..cced0918c8 --- /dev/null +++ b/lib/libc/net/gai_strerror.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc/net/gai_strerror.c,v 1.2 2006/05/21 11:22:31 ume Exp $ + */ + +#include + +/* Entries EAI_ADDRFAMILY (1) and EAI_NODATA (7) are obsoleted, but left */ +/* for backward compatibility with userland code prior to 2553bis-02 */ +static const char *ai_errlist[] = { + "Success", /* 0 */ + "Address family for hostname not supported", /* 1 */ + "Temporary failure in name resolution", /* EAI_AGAIN */ + "Invalid value for ai_flags", /* EAI_BADFLAGS */ + "Non-recoverable failure in name resolution", /* EAI_FAIL */ + "ai_family not supported", /* EAI_FAMILY */ + "Memory allocation failure", /* EAI_MEMORY */ + "No address associated with hostname", /* 7 */ + "hostname nor servname provided, or not known", /* EAI_NONAME */ + "servname not supported for ai_socktype", /* EAI_SERVICE */ + "ai_socktype not supported", /* EAI_SOCKTYPE */ + "System error returned in errno", /* EAI_SYSTEM */ + "Invalid value for hints", /* EAI_BADHINTS */ + "Resolved protocol is unknown", /* EAI_PROTOCOL */ + "Argument buffer overflow" /* EAI_OVERFLOW */ +}; + +const char * +gai_strerror(int ecode) +{ + if (ecode >= 0 && ecode < EAI_MAX) + return ai_errlist[ecode]; + return "Unknown error"; +} diff --git a/lib/libc/net/getaddrinfo.3 b/lib/libc/net/getaddrinfo.3 index 9732e2c0d9..b7ada3b5c0 100644 --- a/lib/libc/net/getaddrinfo.3 +++ b/lib/libc/net/getaddrinfo.3 @@ -1,7 +1,5 @@ .\" $KAME: getaddrinfo.3,v 1.36 2005/01/05 03:23:05 itojun Exp $ .\" $OpenBSD: getaddrinfo.3,v 1.35 2004/12/21 03:40:31 jaredy Exp $ -.\" $FreeBSD: src/lib/libc/net/getaddrinfo.3,v 1.29 2005/01/23 16:02:48 gnn Exp $ -.\" $DragonFly: src/lib/libc/net/getaddrinfo.3,v 1.7 2008/05/22 06:50:14 hasso Exp $ .\" .\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000, 2001 Internet Software Consortium. @@ -18,7 +16,10 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.Dd May 22, 2008 +.\" $FreeBSD: src/lib/libc/net/getaddrinfo.3,v 1.34 2008/07/01 22:59:20 danger Exp $ +.\" $DragonFly: src/lib/libc/net/getaddrinfo.3,v 1.7 2008/05/22 06:50:14 hasso Exp $ +.\" +.Dd July 1, 2008 .Dt GETADDRINFO 3 .Os .Sh NAME @@ -32,8 +33,10 @@ .In sys/socket.h .In netdb.h .Ft int -.Fn getaddrinfo "const char *hostname" "const char *servname" \ - "const struct addrinfo *hints" "struct addrinfo **res" +.Fo getaddrinfo +.Fa "const char *hostname" "const char *servname" +.Fa "const struct addrinfo *hints" "struct addrinfo **res" +.Fc .Ft void .Fn freeaddrinfo "struct addrinfo *ai" .Sh DESCRIPTION @@ -119,10 +122,20 @@ If .Fa ai_protocol is zero the caller will accept any protocol. .It Fa ai_flags +The .Fa ai_flags -is formed by -.Tn OR Ns 'ing -the following values: +field to which the +.Fa hints +parameter points shall be set to zero +or be the bitwise-inclusive OR of one or more of the values +.Dv AI_ADDRCONFIG , +.Dv AI_ALL , +.Dv AI_CANONNAME , +.Dv AI_NUMERICHOST , +.Dv AI_NUMERICSERV , +.Dv AI_PASSIVE , +and +.Dv AI_V4MAPPED . .Bl -tag -width "AI_CANONNAMEXX" .It Dv AI_ADDRCONFIG If the @@ -227,6 +240,11 @@ flag shall be ignored unless .Fa ai_family equals .Dv AF_INET6 . +Note: this flag is currently +.Em not +supported, see the +.Sx BUGS +section. .El .El .Pp @@ -475,15 +493,23 @@ freeaddrinfo(res0); .%B "Proceedings of the freenix track: 2000 USENIX annual technical conference" .%D June 2000 .Re +.Sh BUGS +The +.Nm +function as implemented in +.Dx +currently does not support +.Dv AI_ALL +and +.Dv AI_V4MAPPED +flags and returns +.Dv EAI_BADFLAGS +if one of them is specified. .Sh STANDARDS The .Fn getaddrinfo function is defined by the -.St -p1003.1g-2000 -draft specification and documented in +.St -p1003.1-2004 +specification and documented in .Dv "RFC 3493" , .Dq Basic Socket Interface Extensions for IPv6 . -.Sh BUGS -The implementation of -.Fn getaddrinfo -is not thread-safe. diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c index cde711cf97..7b64c10bbd 100644 --- a/lib/libc/net/getaddrinfo.c +++ b/lib/libc/net/getaddrinfo.c @@ -1,4 +1,4 @@ -/* $FreeBSD: src/lib/libc/net/getaddrinfo.c,v 1.9.2.14 2002/11/08 17:49:31 ume Exp $ */ +/* $FreeBSD: src/lib/libc/net/getaddrinfo.c,v 1.87 2008/02/03 19:07:55 ume Exp $ */ /* $DragonFly: src/lib/libc/net/getaddrinfo.c,v 1.9 2008/10/04 22:38:42 swildner Exp $ */ /* $KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 itojun Exp $ */ @@ -35,7 +35,6 @@ * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator. * * Issues to be discussed: - * - Thread safe-ness must be checked. * - Return values. There are nonstandard return values defined and used * in the source code. This is because RFC2553 is silent about which error * code must be returned for which situation. @@ -52,16 +51,8 @@ * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? * non-loopback address configured? global address configured? * - * OS specific notes for netbsd/openbsd/freebsd4/bsdi4: - * - To avoid search order issue, we have a big amount of code duplicate - * from gethnamaddr.c and some other places. The issues that there's no - * lower layer function to lookup "IPv4 or IPv6" record. Calling - * gethostbyname2 from getaddrinfo will end up in wrong search order, as - * presented above. - * * OS specific notes for freebsd4: * - FreeBSD supported $GAI. The code does not. - * - FreeBSD allowed classful IPv4 numeric (127.1), the code does not. */ #include "namespace.h" @@ -70,8 +61,18 @@ #include #include #include +#include +#ifdef INET6 +#include +#include +#include +#include /* XXX */ +#endif #include #include +#include +#include +#include #include #include #include @@ -116,10 +117,18 @@ static const char in6_loopback[] = { }; #endif +struct policyqueue { + TAILQ_ENTRY(policyqueue) pc_entry; +#ifdef INET6 + struct in6_addrpolicy pc_policy; +#endif +}; +TAILQ_HEAD(policyhead, policyqueue); + static const struct afd { int a_af; int a_addrlen; - int a_socklen; + socklen_t a_socklen; int a_off; const char *a_addrany; const char *a_loopback; @@ -177,19 +186,29 @@ static const struct explore explore[] = { #define PTON_MAX 4 #endif +#define AIO_SRCFLAG_DEPRECATED 0x1 + +struct ai_order { + union { + struct sockaddr_storage aiou_ss; + struct sockaddr aiou_sa; + } aio_src_un; +#define aio_srcsa aio_src_un.aiou_sa + u_int32_t aio_srcflag; + int aio_srcscope; + int aio_dstscope; + struct policyqueue *aio_srcpolicy; + struct policyqueue *aio_dstpolicy; + struct addrinfo *aio_ai; + int aio_matchlen; +}; + static const ns_src default_dns_files[] = { { NSSRC_FILES, NS_SUCCESS }, { NSSRC_DNS, NS_SUCCESS }, { 0 } }; -#define MAXPACKET (64*1024) - -typedef union { - HEADER hdr; - u_char buf[MAXPACKET]; -} querybuf; - struct res_target { struct res_target *next; const char *name; /* domain name */ @@ -199,81 +218,72 @@ struct res_target { int n; /* result length */ }; -static int str2number (const char *); -static int explore_fqdn (const struct addrinfo *, const char *, - const char *, struct addrinfo **); -static int explore_null (const struct addrinfo *, - const char *, struct addrinfo **); -static int explore_numeric (const struct addrinfo *, const char *, - const char *, struct addrinfo **); -static int explore_numeric_scope (const struct addrinfo *, const char *, - const char *, struct addrinfo **); -static int get_canonname (const struct addrinfo *, - struct addrinfo *, const char *); -static struct addrinfo *get_ai (const struct addrinfo *, - const struct afd *, const char *); -static int get_portmatch (const struct addrinfo *, const char *); -static int get_port (struct addrinfo *, const char *, int); -static const struct afd *find_afd (int); -static int addrconfig (struct addrinfo *); +#define MAXPACKET (64*1024) + +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +static int str2number(const char *, int *); +static int explore_null(const struct addrinfo *, + const char *, struct addrinfo **); +static int explore_numeric(const struct addrinfo *, const char *, + const char *, struct addrinfo **, const char *); +static int explore_numeric_scope(const struct addrinfo *, const char *, + const char *, struct addrinfo **); +static int get_canonname(const struct addrinfo *, + struct addrinfo *, const char *); +static struct addrinfo *get_ai(const struct addrinfo *, + const struct afd *, const char *); +static int get_portmatch(const struct addrinfo *, const char *); +static int get_port(struct addrinfo *, const char *, int); +static const struct afd *find_afd(int); +static int addrconfig(struct addrinfo *); +static void set_source(struct ai_order *, struct policyhead *); +static int comp_dst(const void *, const void *); #ifdef INET6 -static int ip6_str2scopeid (char *, struct sockaddr_in6 *, u_int32_t *); +static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *); #endif +static int gai_addr2scopetype(struct sockaddr *); + +static int explore_fqdn(const struct addrinfo *, const char *, + const char *, struct addrinfo **); -static struct addrinfo *getanswer (const querybuf *, int, const char *, - int, const struct addrinfo *); -static int _dns_getaddrinfo (void *, void *, va_list); -static void _sethtent (void); -static void _endhtent (void); -static struct addrinfo *_gethtent (const char *, const struct addrinfo *); -static int _files_getaddrinfo (void *, void *, va_list); +static int reorder(struct addrinfo *); +static int get_addrselectpolicy(struct policyhead *); +static void free_addrselectpolicy(struct policyhead *); +static struct policyqueue *match_addrselectpolicy(struct sockaddr *, + struct policyhead *); +static int matchlen(struct sockaddr *, struct sockaddr *); + +static struct addrinfo *getanswer(const querybuf *, int, const char *, int, + const struct addrinfo *, res_state); +#if defined(RESOLVSORT) +static int addr4sort(struct addrinfo *, res_state); +#endif +static int _dns_getaddrinfo(void *, void *, va_list); +static void _sethtent(FILE **); +static void _endhtent(FILE **); +static struct addrinfo *_gethtent(FILE **, const char *, + const struct addrinfo *); +static int _files_getaddrinfo(void *, void *, va_list); #ifdef YP -static struct addrinfo *_yphostent (char *, const struct addrinfo *); -static int _yp_getaddrinfo (void *, void *, va_list); +static struct addrinfo *_yphostent(char *, const struct addrinfo *); +static int _yp_getaddrinfo(void *, void *, va_list); #endif #ifdef NS_CACHING -static int addrinfo_id_func(char *, size_t *, va_list, void *); -static int addrinfo_marshal_func(char *, size_t *, void *, va_list, void *); -static int addrinfo_unmarshal_func(char *, size_t, void *, va_list, void *); +static int addrinfo_id_func(char *, size_t *, va_list, void *); +static int addrinfo_marshal_func(char *, size_t *, void *, va_list, + void *); +static int addrinfo_unmarshal_func(char *, size_t, void *, va_list, + void *); #endif -static int res_queryN (const char *, struct res_target *); -static int res_searchN (const char *, struct res_target *); -static int res_querydomainN (const char *, const char *, - struct res_target *); - -static const char *ai_errlist[] = { - "Success", - "Address family for hostname not supported", /* EAI_ADDRFAMILY */ - "Temporary failure in name resolution", /* EAI_AGAIN */ - "Invalid value for ai_flags", /* EAI_BADFLAGS */ - "Non-recoverable failure in name resolution", /* EAI_FAIL */ - "ai_family not supported", /* EAI_FAMILY */ - "Memory allocation failure", /* EAI_MEMORY */ - "No address associated with hostname", /* EAI_NODATA */ - "hostname nor servname provided, or not known", /* EAI_NONAME */ - "servname not supported for ai_socktype", /* EAI_SERVICE */ - "ai_socktype not supported", /* EAI_SOCKTYPE */ - "System error returned in errno", /* EAI_SYSTEM */ - "Invalid value for hints", /* EAI_BADHINTS */ - "Resolved protocol is unknown", /* EAI_PROTOCOL */ - "Argument buffer overflow", /* EAI_OVERFLOW */ - "Unknown error", /* EAI_MAX */ -}; - -/* Make getaddrinfo() thread-safe in libc for use with kernel threads. */ -#include "spinlock.h" -/* - * XXX: Our res_*() is not thread-safe. So, we share lock between - * getaddrinfo() and getipnodeby*(). Still, we cannot use - * getaddrinfo() and getipnodeby*() in conjunction with other - * functions which call res_*(). - */ -spinlock_t __getaddrinfo_thread_lock = _SPINLOCK_INITIALIZER; -#define THREAD_LOCK() \ - if (__isthreaded) _SPINLOCK(&__getaddrinfo_thread_lock); -#define THREAD_UNLOCK() \ - if (__isthreaded) _SPINUNLOCK(&__getaddrinfo_thread_lock); +static int res_queryN(const char *, struct res_target *, res_state); +static int res_searchN(const char *, struct res_target *, res_state); +static int res_querydomainN(const char *, const char *, + struct res_target *, res_state); /* XXX macros that make external reference is BAD. */ @@ -316,14 +326,6 @@ do { \ #define MATCH(x, y, w) \ ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) -const char * -gai_strerror(int ecode) -{ - if (ecode < 0 || ecode > EAI_MAX) - ecode = EAI_MAX; - return ai_errlist[ecode]; -} - void freeaddrinfo(struct addrinfo *ai) { @@ -340,7 +342,7 @@ freeaddrinfo(struct addrinfo *ai) } static int -str2number(const char *p) +str2number(const char *p, int *portp) { char *ep; unsigned long v; @@ -350,9 +352,10 @@ str2number(const char *p) ep = NULL; errno = 0; v = strtoul(p, &ep, 10); - if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) - return v; - else + if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) { + *portp = v; + return 0; + } else return -1; } @@ -367,6 +370,7 @@ getaddrinfo(const char *hostname, const char *servname, struct addrinfo ai0; struct addrinfo *pai; const struct explore *ex; + int numeric = 0; memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; @@ -421,27 +425,6 @@ getaddrinfo(const char *hostname, const char *servname, } } - /* - * post-2553: AI_ALL and AI_V4MAPPED are effective only against - * AF_INET6 query. They need to be ignored if specified in other - * occassions. - */ - switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) { - case AI_V4MAPPED: - case AI_ALL | AI_V4MAPPED: - if (pai->ai_family != AF_INET6) - pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); - break; - case AI_ALL: -#if 1 - /* illegal */ - ERR(EAI_BADFLAGS); -#else - pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); -#endif - break; - } - /* * check for special cases. (1) numeric servname is disallowed if * socktype/protocol are left unspecified. (2) servname is disallowed @@ -480,11 +463,9 @@ getaddrinfo(const char *hostname, const char *servname, if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) continue; - if (!MATCH(pai->ai_socktype, ex->e_socktype, - WILD_SOCKTYPE(ex))) + if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) continue; - if (!MATCH(pai->ai_protocol, ex->e_protocol, - WILD_PROTOCOL(ex))) + if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) continue; if (pai->ai_family == PF_UNSPEC) @@ -498,7 +479,7 @@ getaddrinfo(const char *hostname, const char *servname, error = explore_null(pai, servname, &cur->ai_next); else error = explore_numeric_scope(pai, hostname, servname, - &cur->ai_next); + &cur->ai_next); if (error) goto free; @@ -512,13 +493,15 @@ getaddrinfo(const char *hostname, const char *servname, * If numreic representation of AF1 can be interpreted as FQDN * representation of AF2, we need to think again about the code below. */ - if (sentinel.ai_next) + if (sentinel.ai_next) { + numeric = 1; goto good; + } + if (hostname == NULL) + ERR(EAI_NONAME); /* used to be EAI_NODATA */ if (pai->ai_flags & AI_NUMERICHOST) ERR(EAI_NONAME); - if (hostname == NULL) - ERR(EAI_NODATA); if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(&ai0)) ERR(EAI_FAIL); @@ -535,10 +518,12 @@ getaddrinfo(const char *hostname, const char *servname, if (pai->ai_family != ex->e_af) continue; - if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) { + if (!MATCH(pai->ai_socktype, ex->e_socktype, + WILD_SOCKTYPE(ex))) { continue; } - if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) { + if (!MATCH(pai->ai_protocol, ex->e_protocol, + WILD_PROTOCOL(ex))) { continue; } @@ -553,97 +538,505 @@ getaddrinfo(const char *hostname, const char *servname, cur = cur->ai_next; } - /* XXX */ + /* XXX inhibit errors if we have the result */ if (sentinel.ai_next) error = 0; - if (error) - goto free; +good: + /* + * ensure we return either: + * - error == 0, non-NULL *res + * - error != 0, NULL *res + */ if (error == 0) { if (sentinel.ai_next) { - good: + /* + * If the returned entry is for an active connection, + * and the given name is not numeric, reorder the + * list, so that the application would try the list + * in the most efficient order. Since the head entry + * of the original list may contain ai_canonname and + * that entry may be moved elsewhere in the new list, + * we keep the pointer and will restore it in the new + * head entry. (Note that RFC3493 requires the head + * entry store it when requested by the caller). + */ + if (hints == NULL || !(hints->ai_flags & AI_PASSIVE)) { + if (!numeric) { + char *canonname; + + canonname = + sentinel.ai_next->ai_canonname; + sentinel.ai_next->ai_canonname = NULL; + reorder(&sentinel); + if (sentinel.ai_next->ai_canonname == + NULL) { + sentinel.ai_next->ai_canonname + = canonname; + } else if (canonname != NULL) + free(canonname); + } + } *res = sentinel.ai_next; return SUCCESS; } else error = EAI_FAIL; } - free: - bad: +free: +bad: if (sentinel.ai_next) freeaddrinfo(sentinel.ai_next); *res = NULL; return error; } -/* - * FQDN hostname, DNS lookup - */ static int -explore_fqdn(const struct addrinfo *pai, const char *hostname, - const char *servname, struct addrinfo **res) +reorder(struct addrinfo *sentinel) { - struct addrinfo *result; - struct addrinfo *cur; - int error = 0; + struct addrinfo *ai, **aip; + struct ai_order *aio; + int i, n; + struct policyhead policyhead; -#ifdef NS_CACHING - static const nss_cache_info cache_info = - NS_COMMON_CACHE_INFO_INITIALIZER( - hosts, NULL, addrinfo_id_func, addrinfo_marshal_func, - addrinfo_unmarshal_func); + /* count the number of addrinfo elements for sorting. */ + for (n = 0, ai = sentinel->ai_next; ai != NULL; ai = ai->ai_next, n++) + ; + + /* + * If the number is small enough, we can skip the reordering process. + */ + if (n <= 1) + return(n); + + /* allocate a temporary array for sort and initialization of it. */ + if ((aio = malloc(sizeof(*aio) * n)) == NULL) + return(n); /* give up reordering */ + memset(aio, 0, sizeof(*aio) * n); + + /* retrieve address selection policy from the kernel */ + TAILQ_INIT(&policyhead); + if (!get_addrselectpolicy(&policyhead)) { + /* no policy is installed into kernel, we don't sort. */ + free(aio); + return (n); + } + + for (i = 0, ai = sentinel->ai_next; i < n; ai = ai->ai_next, i++) { + aio[i].aio_ai = ai; + aio[i].aio_dstscope = gai_addr2scopetype(ai->ai_addr); + aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr, + &policyhead); + set_source(&aio[i], &policyhead); + } + + /* perform sorting. */ + qsort(aio, n, sizeof(*aio), comp_dst); + + /* reorder the addrinfo chain. */ + for (i = 0, aip = &sentinel->ai_next; i < n; i++) { + *aip = aio[i].aio_ai; + aip = &aio[i].aio_ai->ai_next; + } + *aip = NULL; + + /* cleanup and return */ + free(aio); + free_addrselectpolicy(&policyhead); + return(n); +} + +static int +get_addrselectpolicy(struct policyhead *head) +{ +#ifdef INET6 + int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY }; + size_t l; + char *buf; + struct in6_addrpolicy *pol, *ep; + + if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) + return (0); + if ((buf = malloc(l)) == NULL) + return (0); + if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) { + free(buf); + return (0); + } + + ep = (struct in6_addrpolicy *)(buf + l); + for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) { + struct policyqueue *new; + + if ((new = malloc(sizeof(*new))) == NULL) { + free_addrselectpolicy(head); /* make the list empty */ + break; + } + new->pc_policy = *pol; + TAILQ_INSERT_TAIL(head, new, pc_entry); + } + + free(buf); + return (1); +#else + return (0); #endif - static const ns_dtab dtab[] = { - NS_FILES_CB(_files_getaddrinfo, NULL) - { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ - NS_NIS_CB(_yp_getaddrinfo, NULL) -#ifdef NS_CACHING - NS_CACHE_CB(&cache_info) +} + +static void +free_addrselectpolicy(struct policyhead *head) +{ + struct policyqueue *ent, *nent; + + for (ent = TAILQ_FIRST(head); ent; ent = nent) { + nent = TAILQ_NEXT(ent, pc_entry); + TAILQ_REMOVE(head, ent, pc_entry); + free(ent); + } +} + +static struct policyqueue * +match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head) +{ +#ifdef INET6 + struct policyqueue *ent, *bestent = NULL; + struct in6_addrpolicy *pol; + int matchlen, bestmatchlen = -1; + u_char *mp, *ep, *k, *p, m; + struct sockaddr_in6 key; + + switch(addr->sa_family) { + case AF_INET6: + key = *(struct sockaddr_in6 *)addr; + break; + case AF_INET: + /* convert the address into IPv4-mapped IPv6 address. */ + memset(&key, 0, sizeof(key)); + key.sin6_family = AF_INET6; + key.sin6_len = sizeof(key); + key.sin6_addr.s6_addr[10] = 0xff; + key.sin6_addr.s6_addr[11] = 0xff; + memcpy(&key.sin6_addr.s6_addr[12], + &((struct sockaddr_in *)addr)->sin_addr, 4); + break; + default: + return(NULL); + } + + for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) { + pol = &ent->pc_policy; + matchlen = 0; + + mp = (u_char *)&pol->addrmask.sin6_addr; + ep = mp + 16; /* XXX: scope field? */ + k = (u_char *)&key.sin6_addr; + p = (u_char *)&pol->addr.sin6_addr; + for (; mp < ep && *mp; mp++, k++, p++) { + m = *mp; + if ((*k & m) != *p) + goto next; /* not match */ + if (m == 0xff) /* short cut for a typical case */ + matchlen += 8; + else { + while (m >= 0x80) { + matchlen++; + m <<= 1; + } + } + } + + /* matched. check if this is better than the current best. */ + if (matchlen > bestmatchlen) { + bestent = ent; + bestmatchlen = matchlen; + } + + next: + continue; + } + + return(bestent); +#else + return(NULL); #endif - { 0 } - }; - result = NULL; +} + +static void +set_source(struct ai_order *aio, struct policyhead *ph) +{ + struct addrinfo ai = *aio->aio_ai; + struct sockaddr_storage ss; + socklen_t srclen; + int s; + + /* set unspec ("no source is available"), just in case */ + aio->aio_srcsa.sa_family = AF_UNSPEC; + aio->aio_srcscope = -1; + + switch(ai.ai_family) { + case AF_INET: +#ifdef INET6 + case AF_INET6: +#endif + break; + default: /* ignore unsupported AFs explicitly */ + return; + } + + /* XXX: make a dummy addrinfo to call connect() */ + ai.ai_socktype = SOCK_DGRAM; + ai.ai_protocol = IPPROTO_UDP; /* is UDP too specific? */ + ai.ai_next = NULL; + memset(&ss, 0, sizeof(ss)); + memcpy(&ss, ai.ai_addr, ai.ai_addrlen); + ai.ai_addr = (struct sockaddr *)&ss; + get_port(&ai, "1", 0); + + /* open a socket to get the source address for the given dst */ + if ((s = _socket(ai.ai_family, ai.ai_socktype, ai.ai_protocol)) < 0) + return; /* give up */ + if (_connect(s, ai.ai_addr, ai.ai_addrlen) < 0) + goto cleanup; + srclen = ai.ai_addrlen; + if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) { + aio->aio_srcsa.sa_family = AF_UNSPEC; + goto cleanup; + } + aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa); + aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph); + aio->aio_matchlen = matchlen(&aio->aio_srcsa, aio->aio_ai->ai_addr); +#ifdef INET6 + if (ai.ai_family == AF_INET6) { + struct in6_ifreq ifr6; + u_int32_t flags6; + + /* XXX: interface name should not be hardcoded */ + strncpy(ifr6.ifr_name, "lo0", sizeof(ifr6.ifr_name)); + memset(&ifr6, 0, sizeof(ifr6)); + memcpy(&ifr6.ifr_addr, ai.ai_addr, ai.ai_addrlen); + if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) { + flags6 = ifr6.ifr_ifru.ifru_flags6; + if ((flags6 & IN6_IFF_DEPRECATED)) + aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED; + } + } +#endif + + cleanup: + _close(s); + return; +} + +static int +matchlen(struct sockaddr *src, struct sockaddr *dst) +{ + int match = 0; + u_char *s, *d; + u_char *lim, r; + int addrlen; + + switch (src->sa_family) { +#ifdef INET6 + case AF_INET6: + s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr; + d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr; + addrlen = sizeof(struct in6_addr); + lim = s + addrlen; + break; +#endif + case AF_INET: + s = (u_char *)&((struct sockaddr_in *)src)->sin_addr; + d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr; + addrlen = sizeof(struct in_addr); + lim = s + addrlen; + break; + default: + return(0); + } + + while (s < lim) + if ((r = (*d++ ^ *s++)) != 0) { + while (r < addrlen * 8) { + match++; + r <<= 1; + } + break; + } else + match += 8; + return(match); +} - THREAD_LOCK(); +static int +comp_dst(const void *arg1, const void *arg2) +{ + const struct ai_order *dst1 = arg1, *dst2 = arg2; /* - * if the servname does not match socktype/protocol, ignore it. + * Rule 1: Avoid unusable destinations. + * XXX: we currently do not consider if an appropriate route exists. */ - if (get_portmatch(pai, servname) != 0) { - THREAD_UNLOCK(); - return 0; + if (dst1->aio_srcsa.sa_family != AF_UNSPEC && + dst2->aio_srcsa.sa_family == AF_UNSPEC) { + return(-1); + } + if (dst1->aio_srcsa.sa_family == AF_UNSPEC && + dst2->aio_srcsa.sa_family != AF_UNSPEC) { + return(1); } - switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", - default_dns_files, hostname, pai)) { - case NS_TRYAGAIN: - error = EAI_AGAIN; - goto free; - case NS_UNAVAIL: - error = EAI_FAIL; - goto free; - case NS_NOTFOUND: - error = EAI_NODATA; - goto free; - case NS_SUCCESS: - error = 0; - for (cur = result; cur; cur = cur->ai_next) { - GET_PORT(cur, servname); - /* canonname should be filled already */ + /* Rule 2: Prefer matching scope. */ + if (dst1->aio_dstscope == dst1->aio_srcscope && + dst2->aio_dstscope != dst2->aio_srcscope) { + return(-1); + } + if (dst1->aio_dstscope != dst1->aio_srcscope && + dst2->aio_dstscope == dst2->aio_srcscope) { + return(1); + } + + /* Rule 3: Avoid deprecated addresses. */ + if (dst1->aio_srcsa.sa_family != AF_UNSPEC && + dst2->aio_srcsa.sa_family != AF_UNSPEC) { + if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) && + (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) { + return(-1); + } + if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) && + !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) { + return(1); } - THREAD_UNLOCK(); - break; } - *res = result; + /* Rule 4: Prefer home addresses. */ + /* XXX: not implemented yet */ - return 0; + /* Rule 5: Prefer matching label. */ +#ifdef INET6 + if (dst1->aio_srcpolicy && dst1->aio_dstpolicy && + dst1->aio_srcpolicy->pc_policy.label == + dst1->aio_dstpolicy->pc_policy.label && + (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL || + dst2->aio_srcpolicy->pc_policy.label != + dst2->aio_dstpolicy->pc_policy.label)) { + return(-1); + } + if (dst2->aio_srcpolicy && dst2->aio_dstpolicy && + dst2->aio_srcpolicy->pc_policy.label == + dst2->aio_dstpolicy->pc_policy.label && + (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL || + dst1->aio_srcpolicy->pc_policy.label != + dst1->aio_dstpolicy->pc_policy.label)) { + return(1); + } +#endif -free: - THREAD_UNLOCK(); - if (result) - freeaddrinfo(result); - return error; + /* Rule 6: Prefer higher precedence. */ +#ifdef INET6 + if (dst1->aio_dstpolicy && + (dst2->aio_dstpolicy == NULL || + dst1->aio_dstpolicy->pc_policy.preced > + dst2->aio_dstpolicy->pc_policy.preced)) { + return(-1); + } + if (dst2->aio_dstpolicy && + (dst1->aio_dstpolicy == NULL || + dst2->aio_dstpolicy->pc_policy.preced > + dst1->aio_dstpolicy->pc_policy.preced)) { + return(1); + } +#endif + + /* Rule 7: Prefer native transport. */ + /* XXX: not implemented yet */ + + /* Rule 8: Prefer smaller scope. */ + if (dst1->aio_dstscope >= 0 && + dst1->aio_dstscope < dst2->aio_dstscope) { + return(-1); + } + if (dst2->aio_dstscope >= 0 && + dst2->aio_dstscope < dst1->aio_dstscope) { + return(1); + } + + /* + * Rule 9: Use longest matching prefix. + * We compare the match length in a same AF only. + */ + if (dst1->aio_ai->ai_addr->sa_family == + dst2->aio_ai->ai_addr->sa_family) { + if (dst1->aio_matchlen > dst2->aio_matchlen) { + return(-1); + } + if (dst1->aio_matchlen < dst2->aio_matchlen) { + return(1); + } + } + + /* Rule 10: Otherwise, leave the order unchanged. */ + return(-1); +} + +/* + * Copy from scope.c. + * XXX: we should standardize the functions and link them as standard + * library. + */ +static int +gai_addr2scopetype(struct sockaddr *sa) +{ +#ifdef INET6 + struct sockaddr_in6 *sa6; +#endif + struct sockaddr_in *sa4; + + switch(sa->sa_family) { +#ifdef INET6 + case AF_INET6: + sa6 = (struct sockaddr_in6 *)sa; + if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) { + /* just use the scope field of the multicast address */ + return(sa6->sin6_addr.s6_addr[2] & 0x0f); + } + /* + * Unicast addresses: map scope type to corresponding scope + * value defined for multcast addresses. + * XXX: hardcoded scope type values are bad... + */ + if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr)) + return(1); /* node local scope */ + if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) + return(2); /* link-local scope */ + if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr)) + return(5); /* site-local scope */ + return(14); /* global scope */ + break; +#endif + case AF_INET: + /* + * IPv4 pseudo scoping according to RFC 3484. + */ + sa4 = (struct sockaddr_in *)sa; + /* IPv4 autoconfiguration addresses have link-local scope. */ + if (((u_char *)&sa4->sin_addr)[0] == 169 && + ((u_char *)&sa4->sin_addr)[1] == 254) + return(2); + /* Private addresses have site-local scope. */ + if (((u_char *)&sa4->sin_addr)[0] == 10 || + (((u_char *)&sa4->sin_addr)[0] == 172 && + (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) || + (((u_char *)&sa4->sin_addr)[0] == 192 && + ((u_char *)&sa4->sin_addr)[1] == 168)) + return(14); /* XXX: It should be 5 unless NAT */ + /* Loopback addresses have link-local scope. */ + if (((u_char *)&sa4->sin_addr)[0] == 127) + return(2); + return(14); + break; + default: + errno = EAFNOSUPPORT; /* is this a good error? */ + return(-1); + } } /* @@ -657,13 +1050,11 @@ explore_null(const struct addrinfo *pai, const char *servname, { int s; const struct afd *afd; - struct addrinfo *cur; - struct addrinfo sentinel; + struct addrinfo *ai; int error; *res = NULL; - sentinel.ai_next = NULL; - cur = &sentinel; + ai = NULL; /* * filter out AFs that are not supported by the kernel @@ -687,26 +1078,19 @@ explore_null(const struct addrinfo *pai, const char *servname, return 0; if (pai->ai_flags & AI_PASSIVE) { - GET_AI(cur->ai_next, afd, afd->a_addrany); - /* xxx meaningless? - * GET_CANONNAME(cur->ai_next, "anyaddr"); - */ - GET_PORT(cur->ai_next, servname); + GET_AI(ai, afd, afd->a_addrany); + GET_PORT(ai, servname); } else { - GET_AI(cur->ai_next, afd, afd->a_loopback); - /* xxx meaningless? - * GET_CANONNAME(cur->ai_next, "localhost"); - */ - GET_PORT(cur->ai_next, servname); + GET_AI(ai, afd, afd->a_loopback); + GET_PORT(ai, servname); } - cur = cur->ai_next; - *res = sentinel.ai_next; + *res = ai; return 0; free: - if (sentinel.ai_next) - freeaddrinfo(sentinel.ai_next); + if (ai != NULL) + freeaddrinfo(ai); return error; } @@ -715,17 +1099,16 @@ free: */ static int explore_numeric(const struct addrinfo *pai, const char *hostname, - const char *servname, struct addrinfo **res) + const char *servname, struct addrinfo **res, + const char *canonname) { const struct afd *afd; - struct addrinfo *cur; - struct addrinfo sentinel; + struct addrinfo *ai; int error; char pton[PTON_MAX]; *res = NULL; - sentinel.ai_next = NULL; - cur = &sentinel; + ai = NULL; /* * if the servname does not match socktype/protocol, ignore it. @@ -738,41 +1121,48 @@ explore_numeric(const struct addrinfo *pai, const char *hostname, return 0; switch (afd->a_af) { -#if 1 /*X/Open spec*/ case AF_INET: - if (inet_aton(hostname, (struct in_addr *)pton) == 1) { - if (pai->ai_family == afd->a_af || - pai->ai_family == PF_UNSPEC /*?*/) { - GET_AI(cur->ai_next, afd, pton); - GET_PORT(cur->ai_next, servname); - while (cur && cur->ai_next) - cur = cur->ai_next; - } else - ERR(EAI_FAMILY); /*xxx*/ - } + /* + * RFC3493 requires getaddrinfo() to accept AF_INET formats + * that are accepted by inet_addr() and its family. The + * accepted forms includes the "classful" one, which inet_pton + * does not accept. So we need to separate the case for + * AF_INET. + */ + if (inet_aton(hostname, (struct in_addr *)pton) != 1) + return 0; break; -#endif default: - if (inet_pton(afd->a_af, hostname, pton) == 1) { - if (pai->ai_family == afd->a_af || - pai->ai_family == PF_UNSPEC /*?*/) { - GET_AI(cur->ai_next, afd, pton); - GET_PORT(cur->ai_next, servname); - while (cur && cur->ai_next) - cur = cur->ai_next; - } else - ERR(EAI_FAMILY); /* XXX */ - } + if (inet_pton(afd->a_af, hostname, pton) != 1) + return 0; break; } - *res = sentinel.ai_next; + if (pai->ai_family == afd->a_af) { + GET_AI(ai, afd, pton); + GET_PORT(ai, servname); + if ((pai->ai_flags & AI_CANONNAME)) { + /* + * Set the numeric address itself as the canonical + * name, based on a clarification in RFC3493. + */ + GET_CANONNAME(ai, canonname); + } + } else { + /* + * XXX: This should not happen since we already matched the AF + * by find_afd. + */ + ERR(EAI_FAMILY); + } + + *res = ai; return 0; free: bad: - if (sentinel.ai_next) - freeaddrinfo(sentinel.ai_next); + if (ai != NULL) + freeaddrinfo(ai); return error; } @@ -784,7 +1174,7 @@ explore_numeric_scope(const struct addrinfo *pai, const char *hostname, const char *servname, struct addrinfo **res) { #if !defined(SCOPE_DELIMITER) || !defined(INET6) - return explore_numeric(pai, hostname, servname, res); + return explore_numeric(pai, hostname, servname, res, hostname); #else const struct afd *afd; struct addrinfo *cur; @@ -801,12 +1191,13 @@ explore_numeric_scope(const struct addrinfo *pai, const char *hostname, afd = find_afd(pai->ai_family); if (afd == NULL) return 0; + if (!afd->a_scoped) - return explore_numeric(pai, hostname, servname, res); + return explore_numeric(pai, hostname, servname, res, hostname); cp = strchr(hostname, SCOPE_DELIMITER); if (cp == NULL) - return explore_numeric(pai, hostname, servname, res); + return explore_numeric(pai, hostname, servname, res, hostname); /* * Handle special case of @@ -819,7 +1210,7 @@ explore_numeric_scope(const struct addrinfo *pai, const char *hostname, addr = hostname2; scope = cp + 1; - error = explore_numeric(pai, addr, servname, res); + error = explore_numeric(pai, addr, servname, res, hostname); if (error == 0) { u_int32_t scopeid; @@ -829,7 +1220,7 @@ explore_numeric_scope(const struct addrinfo *pai, const char *hostname, sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) { free(hostname2); - return(EAI_NODATA); /* XXX: is return OK? */ + return(EAI_NONAME); /* XXX: is return OK? */ } sin6->sin6_scope_id = scopeid; } @@ -845,10 +1236,9 @@ static int get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str) { if ((pai->ai_flags & AI_CANONNAME) != 0) { - ai->ai_canonname = (char *)malloc(strlen(str) + 1); + ai->ai_canonname = strdup(str); if (ai->ai_canonname == NULL) return EAI_MEMORY; - strlcpy(ai->ai_canonname, str, strlen(str) + 1); } return 0; } @@ -918,7 +1308,6 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) else #endif memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); - return ai; } @@ -926,7 +1315,7 @@ static int get_portmatch(const struct addrinfo *ai, const char *servname) { - /* get_port does not touch first argument. when matchonly == 1. */ + /* get_port does not touch first argument when matchonly == 1. */ /* LINTED const cast */ return get_port((struct addrinfo *)ai, servname, 1); } @@ -936,7 +1325,7 @@ get_port(struct addrinfo *ai, const char *servname, int matchonly) { const char *proto; struct servent *sp; - int port; + int port, error; int allownumeric; if (servname == NULL) @@ -965,8 +1354,8 @@ get_port(struct addrinfo *ai, const char *servname, int matchonly) return EAI_SOCKTYPE; } - port = str2number(servname); - if (port >= 0) { + error = str2number(servname, &port); + if (error == 0) { if (!allownumeric) return EAI_SERVICE; if (port < 0 || port > 65535) @@ -1056,7 +1445,6 @@ addrconfig(struct addrinfo *pai) else _close(s); } - } if (af != AF_UNSPEC) { if ((s = _socket(af, SOCK_DGRAM, 0)) < 0) @@ -1114,81 +1502,258 @@ ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) } #endif -#ifdef RESOLVSORT -struct addr_ptr { - struct addrinfo *ai; - int aval; -}; +#ifdef NS_CACHING static int -addr4sort(struct addrinfo *sentinel) +addrinfo_id_func(char *buffer, size_t *buffer_size, va_list ap, + void *cache_mdata) { - struct addrinfo *ai; - struct addr_ptr *addrs, addr; - struct sockaddr_in *sin; - int naddrs, i, j; - int needsort = 0; + res_state statp; + u_long res_options; - if (!sentinel) - return -1; - naddrs = 0; - for (ai = sentinel->ai_next; ai; ai = ai->ai_next) - naddrs++; - if (naddrs < 2) - return 0; /* We don't need sorting. */ - if ((addrs = malloc(sizeof(struct addr_ptr) * naddrs)) == NULL) - return -1; - i = 0; - for (ai = sentinel->ai_next; ai; ai = ai->ai_next) { - sin = (struct sockaddr_in *)ai->ai_addr; - for (j = 0; (unsigned)j < _res.nsort; j++) { - if (_res.sort_list[j].addr.s_addr == - (sin->sin_addr.s_addr & _res.sort_list[j].mask)) - break; - } - addrs[i].ai = ai; - addrs[i].aval = j; - if (needsort == 0 && i > 0 && j < addrs[i - 1].aval) - needsort = i; - i++; + const int op_id = 0; /* identifies the getaddrinfo for the cache */ + char *hostname; + struct addrinfo *hints; + + char *p; + int ai_flags, ai_family, ai_socktype, ai_protocol; + size_t desired_size, size; + + statp = __res_state(); + res_options = statp->options & (RES_RECURSE | RES_DEFNAMES | + RES_DNSRCH | RES_NOALIASES | RES_USE_INET6); + + hostname = va_arg(ap, char *); + hints = va_arg(ap, struct addrinfo *); + + desired_size = sizeof(res_options) + sizeof(int) + sizeof(int) * 4; + if (hostname != NULL) { + size = strlen(hostname); + desired_size += size + 1; + } else + size = 0; + + if (desired_size > *buffer_size) { + *buffer_size = desired_size; + return (NS_RETURN); } - if (!needsort) { - free(addrs); - return 0; + + if (hints == NULL) + ai_flags = ai_family = ai_socktype = ai_protocol = 0; + else { + ai_flags = hints->ai_flags; + ai_family = hints->ai_family; + ai_socktype = hints->ai_socktype; + ai_protocol = hints->ai_protocol; } - while (needsort < naddrs) { - for (j = needsort - 1; j >= 0; j--) { - if (addrs[j].aval > addrs[j+1].aval) { - addr = addrs[j]; - addrs[j] = addrs[j + 1]; - addrs[j + 1] = addr; - } else - break; - } - needsort++; + p = buffer; + memcpy(p, &res_options, sizeof(res_options)); + p += sizeof(res_options); + + memcpy(p, &op_id, sizeof(int)); + p += sizeof(int); + + memcpy(p, &ai_flags, sizeof(int)); + p += sizeof(int); + + memcpy(p, &ai_family, sizeof(int)); + p += sizeof(int); + + memcpy(p, &ai_socktype, sizeof(int)); + p += sizeof(int); + + memcpy(p, &ai_protocol, sizeof(int)); + p += sizeof(int); + + if (hostname != NULL) + memcpy(p, hostname, size); + + *buffer_size = desired_size; + return (NS_SUCCESS); +} + +static int +addrinfo_marshal_func(char *buffer, size_t *buffer_size, void *retval, + va_list ap, void *cache_mdata) +{ + struct addrinfo *ai, *cai; + char *p; + size_t desired_size, size, ai_size; + + ai = *((struct addrinfo **)retval); + + desired_size = sizeof(size_t); + ai_size = 0; + for (cai = ai; cai != NULL; cai = cai->ai_next) { + desired_size += sizeof(struct addrinfo) + cai->ai_addrlen; + if (cai->ai_canonname != NULL) + desired_size += sizeof(size_t) + + strlen(cai->ai_canonname); + ++ai_size; } - ai = sentinel; - for (i = 0; i < naddrs; ++i) { - ai->ai_next = addrs[i].ai; - ai = ai->ai_next; + if (desired_size > *buffer_size) { + /* this assignment is here for future use */ + errno = ERANGE; + *buffer_size = desired_size; + return (NS_RETURN); } - ai->ai_next = NULL; - free(addrs); + + memset(buffer, 0, desired_size); + p = buffer; + + memcpy(p, &ai_size, sizeof(size_t)); + p += sizeof(size_t); + for (cai = ai; cai != NULL; cai = cai->ai_next) { + memcpy(p, cai, sizeof(struct addrinfo)); + p += sizeof(struct addrinfo); + + memcpy(p, cai->ai_addr, cai->ai_addrlen); + p += cai->ai_addrlen; + + if (cai->ai_canonname != NULL) { + size = strlen(cai->ai_canonname); + memcpy(p, &size, sizeof(size_t)); + p += sizeof(size_t); + + memcpy(p, cai->ai_canonname, size); + p += size; + } + } + + return (NS_SUCCESS); +} + +static int +addrinfo_unmarshal_func(char *buffer, size_t buffer_size, void *retval, + va_list ap, void *cache_mdata) +{ + struct addrinfo new_ai, *result, *sentinel, *lasts; + + char *p; + size_t ai_size, ai_i, size; + + p = buffer; + memcpy(&ai_size, p, sizeof(size_t)); + p += sizeof(size_t); + + result = NULL; + lasts = NULL; + for (ai_i = 0; ai_i < ai_size; ++ai_i) { + memcpy(&new_ai, p, sizeof(struct addrinfo)); + p += sizeof(struct addrinfo); + size = new_ai.ai_addrlen + sizeof(struct addrinfo) + + _ALIGNBYTES; + + sentinel = (struct addrinfo *)malloc(size); + memset(sentinel, 0, size); + + memcpy(sentinel, &new_ai, sizeof(struct addrinfo)); + sentinel->ai_addr = (struct sockaddr *)_ALIGN((char *)sentinel + + sizeof(struct addrinfo)); + + memcpy(sentinel->ai_addr, p, new_ai.ai_addrlen); + p += new_ai.ai_addrlen; + + if (new_ai.ai_canonname != NULL) { + memcpy(&size, p, sizeof(size_t)); + p += sizeof(size_t); + + sentinel->ai_canonname = (char *)malloc(size + 1); + memset(sentinel->ai_canonname, 0, size + 1); + + memcpy(sentinel->ai_canonname, p, size); + p += size; + } + + if (result == NULL) { + result = sentinel; + lasts = sentinel; + } else { + lasts->ai_next = sentinel; + lasts = sentinel; + } + } + + *((struct addrinfo **)retval) = result; + return (NS_SUCCESS); +} +#endif /* NS_CACHING */ + +/* + * FQDN hostname, DNS lookup + */ +static int +explore_fqdn(const struct addrinfo *pai, const char *hostname, + const char *servname, struct addrinfo **res) +{ + struct addrinfo *result; + struct addrinfo *cur; + int error = 0; + +#ifdef NS_CACHING + static const nss_cache_info cache_info = + NS_COMMON_CACHE_INFO_INITIALIZER( + hosts, NULL, addrinfo_id_func, addrinfo_marshal_func, + addrinfo_unmarshal_func); +#endif + static const ns_dtab dtab[] = { + NS_FILES_CB(_files_getaddrinfo, NULL) + { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ + NS_NIS_CB(_yp_getaddrinfo, NULL) +#ifdef NS_CACHING + NS_CACHE_CB(&cache_info) +#endif + { 0 } + }; + + result = NULL; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + return 0; + + switch (_nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", + default_dns_files, hostname, pai)) { + case NS_TRYAGAIN: + error = EAI_AGAIN; + goto free; + case NS_UNAVAIL: + error = EAI_FAIL; + goto free; + case NS_NOTFOUND: + error = EAI_NONAME; + goto free; + case NS_SUCCESS: + error = 0; + for (cur = result; cur; cur = cur->ai_next) { + GET_PORT(cur, servname); + /* canonname should be filled already */ + } + break; + } + + *res = result; + return 0; + +free: + if (result) + freeaddrinfo(result); + return error; } -#endif /*RESOLVSORT*/ #ifdef DEBUG static const char AskedForGot[] = "gethostby*.getanswer: asked for \"%s\", got \"%s\""; #endif -static FILE *hostf = NULL; static struct addrinfo * getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, - const struct addrinfo *pai) + const struct addrinfo *pai, res_state res) { struct addrinfo sentinel, *cur; struct addrinfo ai; @@ -1202,7 +1767,7 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, int type, class, ancount, qdcount; int haveanswer, had_error; char tbuf[MAXDNAME]; - int (*name_ok) (const char *); + int (*name_ok)(const char *); char hostbuf[8*1024]; memset(&sentinel, 0, sizeof(sentinel)); @@ -1229,12 +1794,12 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, ep = hostbuf + sizeof hostbuf; cp = answer->buf + HFIXEDSZ; if (qdcount != 1) { - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(res, NO_RECOVERY); return (NULL); } n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(res, NO_RECOVERY); return (NULL); } cp += n + QFIXEDSZ; @@ -1245,7 +1810,7 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, */ n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(res, NO_RECOVERY); return (NULL); } canonname = bp; @@ -1263,9 +1828,9 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, } cp += n; /* name */ type = _getshort(cp); - cp += INT16SZ; /* type */ + cp += INT16SZ; /* type */ class = _getshort(cp); - cp += INT16SZ + INT32SZ; /* class, TTL */ + cp += INT16SZ + INT32SZ; /* class, TTL */ n = _getshort(cp); cp += INT16SZ; /* len */ if (class != C_IN) { @@ -1372,10 +1937,10 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, * We support only IPv4 address for backward * compatibility against gethostbyname(3). */ - if (_res.nsort && qtype == T_A) { - if (addr4sort(&sentinel) < 0) { + if (res->nsort && qtype == T_A) { + if (addr4sort(&sentinel, res) < 0) { freeaddrinfo(sentinel.ai_next); - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(res, NO_RECOVERY); return NULL; } } @@ -1384,13 +1949,79 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, get_canonname(pai, sentinel.ai_next, qname); else get_canonname(pai, sentinel.ai_next, canonname); - h_errno = NETDB_SUCCESS; + RES_SET_H_ERRNO(res, NETDB_SUCCESS); return sentinel.ai_next; } - h_errno = NO_RECOVERY; - return NULL; + RES_SET_H_ERRNO(res, NO_RECOVERY); + return NULL; +} + +#ifdef RESOLVSORT +struct addr_ptr { + struct addrinfo *ai; + int aval; +}; + +static int +addr4sort(struct addrinfo *sentinel, res_state res) +{ + struct addrinfo *ai; + struct addr_ptr *addrs, addr; + struct sockaddr_in *sin; + int naddrs, i, j; + int needsort = 0; + + if (!sentinel) + return -1; + naddrs = 0; + for (ai = sentinel->ai_next; ai; ai = ai->ai_next) + naddrs++; + if (naddrs < 2) + return 0; /* We don't need sorting. */ + if ((addrs = malloc(sizeof(struct addr_ptr) * naddrs)) == NULL) + return -1; + i = 0; + for (ai = sentinel->ai_next; ai; ai = ai->ai_next) { + sin = (struct sockaddr_in *)ai->ai_addr; + for (j = 0; (unsigned)j < res->nsort; j++) { + if (res->sort_list[j].addr.s_addr == + (sin->sin_addr.s_addr & res->sort_list[j].mask)) + break; + } + addrs[i].ai = ai; + addrs[i].aval = j; + if (needsort == 0 && i > 0 && j < addrs[i - 1].aval) + needsort = i; + i++; + } + if (!needsort) { + free(addrs); + return 0; + } + + while (needsort < naddrs) { + for (j = needsort - 1; j >= 0; j--) { + if (addrs[j].aval > addrs[j+1].aval) { + addr = addrs[j]; + addrs[j] = addrs[j + 1]; + addrs[j + 1] = addr; + } else + break; + } + needsort++; + } + + ai = sentinel; + for (i = 0; i < naddrs; ++i) { + ai->ai_next = addrs[i].ai; + ai = ai->ai_next; + } + ai->ai_next = NULL; + free(addrs); + return 0; } +#endif /*RESOLVSORT*/ /*ARGSUSED*/ static int @@ -1398,54 +2029,55 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) { struct addrinfo *ai; querybuf *buf, *buf2; - const char *name; + const char *hostname; const struct addrinfo *pai; struct addrinfo sentinel, *cur; struct res_target q, q2; + res_state res; - name = va_arg(ap, char *); + hostname = va_arg(ap, char *); pai = va_arg(ap, const struct addrinfo *); - memset(&q, 0, sizeof(q2)); + memset(&q, 0, sizeof(q)); memset(&q2, 0, sizeof(q2)); memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; buf = malloc(sizeof(*buf)); if (!buf) { - h_errno = NETDB_INTERNAL; - return EAI_MEMORY; + RES_SET_H_ERRNO(res, NETDB_INTERNAL); + return NS_NOTFOUND; } buf2 = malloc(sizeof(*buf2)); if (!buf2) { free(buf); - h_errno = NETDB_INTERNAL; - return EAI_MEMORY; + RES_SET_H_ERRNO(res, NETDB_INTERNAL); + return NS_NOTFOUND; } switch (pai->ai_family) { case AF_UNSPEC: - q.name = name; + q.name = hostname; q.qclass = C_IN; q.qtype = T_A; q.answer = buf->buf; q.anslen = sizeof(buf->buf); q.next = &q2; - q2.name = name; + q2.name = hostname; q2.qclass = C_IN; q2.qtype = T_AAAA; q2.answer = buf2->buf; q2.anslen = sizeof(buf2->buf); break; case AF_INET: - q.name = name; + q.name = hostname; q.qclass = C_IN; q.qtype = T_A; q.answer = buf->buf; q.anslen = sizeof(buf->buf); break; case AF_INET6: - q.name = name; + q.name = hostname; q.qclass = C_IN; q.qtype = T_AAAA; q.answer = buf->buf; @@ -1456,28 +2088,36 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) free(buf2); return NS_UNAVAIL; } - if (res_searchN(name, &q) < 0) { + + res = __res_state(); + if ((res->options & RES_INIT) == 0 && res_ninit(res) == -1) { + RES_SET_H_ERRNO(res, NETDB_INTERNAL); + free(buf); + free(buf2); + return NS_NOTFOUND; + } + + if (res_searchN(hostname, &q, res) < 0) { free(buf); free(buf2); return NS_NOTFOUND; } /* prefer IPv6 */ if (q.next) { - ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai); + ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai, res); if (ai) { cur->ai_next = ai; while (cur && cur->ai_next) cur = cur->ai_next; } } - - ai = getanswer(buf, q.n, q.name, q.qtype, pai); + ai = getanswer(buf, q.n, q.name, q.qtype, pai, res); if (ai) cur->ai_next = ai; free(buf); free(buf2); if (sentinel.ai_next == NULL) - switch (h_errno) { + switch (res->res_h_errno) { case HOST_NOT_FOUND: return NS_NOTFOUND; case TRY_AGAIN: @@ -1490,25 +2130,25 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) } static void -_sethtent(void) +_sethtent(FILE **hostf) { - if (!hostf) - hostf = fopen(_PATH_HOSTS, "r" ); + if (!*hostf) + *hostf = fopen(_PATH_HOSTS, "r"); else - rewind(hostf); + rewind(*hostf); } static void -_endhtent(void) +_endhtent(FILE **hostf) { - if (hostf) { - fclose(hostf); - hostf = NULL; + if (*hostf) { + fclose(*hostf); + *hostf = NULL; } } static struct addrinfo * -_gethtent(const char *name, const struct addrinfo *pai) +_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai) { char *p; char *cp, *tname, *cname; @@ -1517,16 +2157,16 @@ _gethtent(const char *name, const struct addrinfo *pai) const char *addr; char hostbuf[8*1024]; - if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) + if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r"))) return (NULL); again: - if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) + if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf))) return (NULL); if (*p == '#') goto again; - if (!(cp = strpbrk(p, "#\n"))) - goto again; - *cp = '\0'; + cp = strpbrk(p, "#\n"); + if (cp != NULL) + *cp = '\0'; if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; @@ -1590,6 +2230,7 @@ _files_getaddrinfo(void *rv, void *cb_data, va_list ap) const struct addrinfo *pai; struct addrinfo sentinel, *cur; struct addrinfo *p; + FILE *hostf = NULL; name = va_arg(ap, char *); pai = va_arg(ap, struct addrinfo *); @@ -1597,13 +2238,13 @@ _files_getaddrinfo(void *rv, void *cb_data, va_list ap) memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; - _sethtent(); - while ((p = _gethtent(name, pai)) != NULL) { + _sethtent(&hostf); + while ((p = _gethtent(&hostf, name, pai)) != NULL) { cur->ai_next = p; while (cur && cur->ai_next) cur = cur->ai_next; } - _endhtent(); + _endhtent(&hostf); *((struct addrinfo **)rv) = sentinel.ai_next; if (sentinel.ai_next == NULL) @@ -1612,8 +2253,6 @@ _files_getaddrinfo(void *rv, void *cb_data, va_list ap) } #ifdef YP -static char *__ypdomain; - /*ARGSUSED*/ static struct addrinfo * _yphostent(char *line, const struct addrinfo *pai) @@ -1696,10 +2335,14 @@ _yp_getaddrinfo(void *rv, void *cb_data, va_list ap) { struct addrinfo sentinel, *cur; struct addrinfo *ai = NULL; - static char *__ypcurrent; - int __ypcurrentlen, r; + char *ypbuf; + int ypbuflen, r; const char *name; const struct addrinfo *pai; + char *ypdomain; + + if (_yp_check(&ypdomain) == 0) + return NS_UNAVAIL; name = va_arg(ap, char *); pai = va_arg(ap, const struct addrinfo *); @@ -1707,46 +2350,37 @@ _yp_getaddrinfo(void *rv, void *cb_data, va_list ap) memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; - if (!__ypdomain) { - if (_yp_check(&__ypdomain) == 0) - return NS_UNAVAIL; - } - if (__ypcurrent) - free(__ypcurrent); - __ypcurrent = NULL; - /* hosts.byname is only for IPv4 (Solaris8) */ if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) { - r = yp_match(__ypdomain, "hosts.byname", name, - (int)strlen(name), &__ypcurrent, &__ypcurrentlen); + r = yp_match(ypdomain, "hosts.byname", name, + (int)strlen(name), &ypbuf, &ypbuflen); if (r == 0) { struct addrinfo ai4; ai4 = *pai; ai4.ai_family = AF_INET; - ai = _yphostent(__ypcurrent, &ai4); + ai = _yphostent(ypbuf, &ai4); if (ai) { cur->ai_next = ai; while (cur && cur->ai_next) cur = cur->ai_next; } + free(ypbuf); } } /* ipnodes.byname can hold both IPv4/v6 */ - r = yp_match(__ypdomain, "ipnodes.byname", name, - (int)strlen(name), &__ypcurrent, &__ypcurrentlen); + r = yp_match(ypdomain, "ipnodes.byname", name, + (int)strlen(name), &ypbuf, &ypbuflen); if (r == 0) { - ai = _yphostent(__ypcurrent, pai); - if (ai) { + ai = _yphostent(ypbuf, pai); + if (ai) cur->ai_next = ai; - while (cur && cur->ai_next) - cur = cur->ai_next; - } + free(ypbuf); } if (sentinel.ai_next == NULL) { - h_errno = HOST_NOT_FOUND; + RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND); return NS_NOTFOUND; } *((struct addrinfo **)rv) = sentinel.ai_next; @@ -1756,188 +2390,6 @@ _yp_getaddrinfo(void *rv, void *cb_data, va_list ap) /* resolver logic */ -extern const char *__hostalias (const char *); -extern int h_errno; - - -#ifdef NS_CACHING -static int -addrinfo_id_func(char *buffer, size_t *buffer_size, va_list ap, - void *cache_mdata) -{ - res_state statp; - u_long res_options; - - const int op_id = 0; /* identifies the getaddrinfo for the cache */ - char *hostname; - struct addrinfo *hints; - - char *p; - int ai_flags, ai_family, ai_socktype, ai_protocol; - size_t desired_size, size; - - statp = __res_state(); - res_options = statp->options & (RES_RECURSE | RES_DEFNAMES | - RES_DNSRCH | RES_NOALIASES | RES_USE_INET6); - - hostname = va_arg(ap, char *); - hints = va_arg(ap, struct addrinfo *); - - desired_size = sizeof(res_options) + sizeof(int) + sizeof(int) * 4; - if (hostname != NULL) { - size = strlen(hostname); - desired_size += size + 1; - } else - size = 0; - - if (desired_size > *buffer_size) { - *buffer_size = desired_size; - return (NS_RETURN); - } - - if (hints == NULL) - ai_flags = ai_family = ai_socktype = ai_protocol = 0; - else { - ai_flags = hints->ai_flags; - ai_family = hints->ai_family; - ai_socktype = hints->ai_socktype; - ai_protocol = hints->ai_protocol; - } - - p = buffer; - memcpy(p, &res_options, sizeof(res_options)); - p += sizeof(res_options); - - memcpy(p, &op_id, sizeof(int)); - p += sizeof(int); - - memcpy(p, &ai_flags, sizeof(int)); - p += sizeof(int); - - memcpy(p, &ai_family, sizeof(int)); - p += sizeof(int); - - memcpy(p, &ai_socktype, sizeof(int)); - p += sizeof(int); - - memcpy(p, &ai_protocol, sizeof(int)); - p += sizeof(int); - - if (hostname != NULL) - memcpy(p, hostname, size); - - *buffer_size = desired_size; - return (NS_SUCCESS); -} - -static int -addrinfo_marshal_func(char *buffer, size_t *buffer_size, void *retval, - va_list ap, void *cache_mdata) -{ - struct addrinfo *ai, *cai; - char *p; - size_t desired_size, size, ai_size; - - ai = *((struct addrinfo **)retval); - - desired_size = sizeof(size_t); - ai_size = 0; - for (cai = ai; cai != NULL; cai = cai->ai_next) { - desired_size += sizeof(struct addrinfo) + cai->ai_addrlen; - if (cai->ai_canonname != NULL) - desired_size += sizeof(size_t) + - strlen(cai->ai_canonname); - ++ai_size; - } - - if (desired_size > *buffer_size) { - /* this assignment is here for future use */ - errno = ERANGE; - *buffer_size = desired_size; - return (NS_RETURN); - } - - memset(buffer, 0, desired_size); - p = buffer; - - memcpy(p, &ai_size, sizeof(size_t)); - p += sizeof(size_t); - for (cai = ai; cai != NULL; cai = cai->ai_next) { - memcpy(p, cai, sizeof(struct addrinfo)); - p += sizeof(struct addrinfo); - - memcpy(p, cai->ai_addr, cai->ai_addrlen); - p += cai->ai_addrlen; - - if (cai->ai_canonname != NULL) { - size = strlen(cai->ai_canonname); - memcpy(p, &size, sizeof(size_t)); - p += sizeof(size_t); - - memcpy(p, cai->ai_canonname, size); - p += size; - } - } - - return (NS_SUCCESS); -} - -static int -addrinfo_unmarshal_func(char *buffer, size_t buffer_size, void *retval, - va_list ap, void *cache_mdata) -{ - struct addrinfo new_ai, *result, *sentinel, *lasts; - - char *p; - size_t ai_size, ai_i, size; - - p = buffer; - memcpy(&ai_size, p, sizeof(size_t)); - p += sizeof(size_t); - - result = NULL; - lasts = NULL; - for (ai_i = 0; ai_i < ai_size; ++ai_i) { - memcpy(&new_ai, p, sizeof(struct addrinfo)); - p += sizeof(struct addrinfo); - size = new_ai.ai_addrlen + sizeof(struct addrinfo) + - _ALIGNBYTES; - - sentinel = (struct addrinfo *)malloc(size); - memset(sentinel, 0, size); - - memcpy(sentinel, &new_ai, sizeof(struct addrinfo)); - sentinel->ai_addr = (struct sockaddr *)_ALIGN((char *)sentinel + - sizeof(struct addrinfo)); - - memcpy(sentinel->ai_addr, p, new_ai.ai_addrlen); - p += new_ai.ai_addrlen; - - if (new_ai.ai_canonname != NULL) { - memcpy(&size, p, sizeof(size_t)); - p += sizeof(size_t); - - sentinel->ai_canonname = (char *)malloc(size + 1); - memset(sentinel->ai_canonname, 0, size + 1); - - memcpy(sentinel->ai_canonname, p, size); - p += size; - } - - if (result == NULL) { - result = sentinel; - lasts = sentinel; - } else { - lasts->ai_next = sentinel; - lasts = sentinel; - } - } - - *((struct addrinfo **)retval) = result; - return (NS_SUCCESS); -} -#endif /* NS_CACHING */ - /* * Formulate a normal query, send, and await answer. * Returned answer is placed in supplied buffer "answer". @@ -1949,12 +2401,12 @@ addrinfo_unmarshal_func(char *buffer, size_t buffer_size, void *retval, * Caller must parse answer and determine whether it answers the question. */ static int -res_queryN(const char *name, /* domain name */ - struct res_target *target) +res_queryN(const char *name, struct res_target *target, res_state res) { u_char *buf; HEADER *hp; int n; + u_int oflags; struct res_target *t; int rcode; int ancount; @@ -1962,15 +2414,10 @@ res_queryN(const char *name, /* domain name */ rcode = NOERROR; ancount = 0; - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - h_errno = NETDB_INTERNAL; - return (-1); - } - buf = malloc(MAXPACKET); if (!buf) { - h_errno = NETDB_INTERNAL; - return (-1); + RES_SET_H_ERRNO(res, NETDB_INTERNAL); + return -1; } for (t = target; t; t = t->next) { @@ -1979,50 +2426,65 @@ res_queryN(const char *name, /* domain name */ int anslen; hp = (HEADER *)(void *)t->answer; - hp->rcode = NOERROR; /* default */ /* make it easier... */ class = t->qclass; type = t->qtype; answer = t->answer; anslen = t->anslen; + + oflags = res->_flags; + +again: + hp->rcode = NOERROR; /* default */ + #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (res->options & RES_DEBUG) printf(";; res_query(%s, %d, %d)\n", name, class, type); #endif - n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL, + n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL, buf, MAXPACKET); - if (n > 0 && (_res.options & RES_USE_EDNS0) != 0) - n = res_opt(n, buf, MAXPACKET, anslen); + if (n > 0 && (res->_flags & RES_F_EDNS0ERR) == 0 && + (res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U) + n = res_nopt(res, n, buf, MAXPACKET, anslen); if (n <= 0) { #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (res->options & RES_DEBUG) printf(";; res_query: mkquery failed\n"); #endif free(buf); - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(res, NO_RECOVERY); return (n); } - n = res_send(buf, n, answer, anslen); -#if 0 + n = res_nsend(res, buf, n, answer, anslen); if (n < 0) { + /* + * if the query choked with EDNS0, retry + * without EDNS0 + */ + if ((res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) + != 0U && + ((oflags ^ res->_flags) & RES_F_EDNS0ERR) != 0) { + res->_flags |= RES_F_EDNS0ERR; + if (res->options & RES_DEBUG) + printf(";; res_nquery: retry without EDNS0\n"); + goto again; + } + rcode = hp->rcode; /* record most recent error */ #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (res->options & RES_DEBUG) printf(";; res_query: send error\n"); #endif - free(buf); - h_errno = TRY_AGAIN; - return (n); + continue; } -#endif - if (n < 0 || n > anslen) + if (n > anslen) hp->rcode = FORMERR; /* XXX not very informative */ if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { rcode = hp->rcode; /* record most recent error */ #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (res->options & RES_DEBUG) printf(";; rcode = %u, ancount=%u\n", hp->rcode, ntohs(hp->ancount)); #endif @@ -2039,19 +2501,19 @@ res_queryN(const char *name, /* domain name */ if (ancount == 0) { switch (rcode) { case NXDOMAIN: - h_errno = HOST_NOT_FOUND; + RES_SET_H_ERRNO(res, HOST_NOT_FOUND); break; case SERVFAIL: - h_errno = TRY_AGAIN; + RES_SET_H_ERRNO(res, TRY_AGAIN); break; case NOERROR: - h_errno = NO_DATA; + RES_SET_H_ERRNO(res, NO_DATA); break; case FORMERR: case NOTIMP: case REFUSED: default: - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(res, NO_RECOVERY); break; } return (-1); @@ -2066,22 +2528,19 @@ res_queryN(const char *name, /* domain name */ * is detected. Error code, if any, is left in h_errno. */ static int -res_searchN(const char *name, /* domain name */ - struct res_target *target) +res_searchN(const char *name, struct res_target *target, res_state res) { const char *cp, * const *domain; HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/ u_int dots; int trailing_dot, ret, saved_herrno; - int got_nodata = 0, got_servfail = 0, tried_as_is = 0; - - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - h_errno = NETDB_INTERNAL; - return (-1); - } + int got_nodata = 0, got_servfail = 0, root_on_list = 0; + int tried_as_is = 0; + int searched = 0; + char abuf[MAXDNAME]; errno = 0; - h_errno = HOST_NOT_FOUND; /* default, if we never query */ + RES_SET_H_ERRNO(res, HOST_NOT_FOUND); /* default, if we never query */ dots = 0; for (cp = name; *cp; cp++) dots += (*cp == '.'); @@ -2092,19 +2551,36 @@ res_searchN(const char *name, /* domain name */ /* * if there aren't any dots, it could be a user-level alias */ - if (!dots && (cp = __hostalias(name)) != NULL) - return (res_queryN(cp, target)); + if (!dots && + (cp = res_hostalias(res, name, abuf, sizeof(abuf))) != NULL) + return (res_queryN(cp, target, res)); /* - * If there are dots in the name already, let's just give it a try - * 'as is'. The threshold can be set with the "ndots" option. + * If there are enough dots in the name, let's just give it a + * try 'as is'. The threshold can be set with the "ndots" option. + * Also, query 'as is', if there is a trailing dot in the name. */ saved_herrno = -1; - if (dots >= _res.ndots) { - ret = res_querydomainN(name, NULL, target); - if (ret > 0) + if (dots >= res->ndots || trailing_dot) { + ret = res_querydomainN(name, NULL, target, res); + if (ret > 0 || trailing_dot) return (ret); - saved_herrno = h_errno; + if (errno == ECONNREFUSED) { + RES_SET_H_ERRNO(res, TRY_AGAIN); + return (-1); + } + switch (res->res_h_errno) { + case NO_DATA: + case HOST_NOT_FOUND: + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) + break; + /* FALLTHROUGH */ + default: + return (-1); + } + saved_herrno = res->res_h_errno; tried_as_is++; } @@ -2114,15 +2590,23 @@ res_searchN(const char *name, /* domain name */ * - there is at least one dot, there is no trailing dot, * and RES_DNSRCH is set. */ - if ((!dots && (_res.options & RES_DEFNAMES)) || - (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { + if ((!dots && (res->options & RES_DEFNAMES)) || + (dots && !trailing_dot && (res->options & RES_DNSRCH))) { int done = 0; - for (domain = (const char * const *)_res.dnsrch; + for (domain = (const char * const *)res->dnsrch; *domain && !done; domain++) { + searched = 1; + + if (domain[0][0] == '\0' || + (domain[0][0] == '.' && domain[0][1] == '\0')) + root_on_list++; + + if (root_on_list && tried_as_is) + continue; - ret = res_querydomainN(name, *domain, target); + ret = res_querydomainN(name, *domain, target, res); if (ret > 0) return (ret); @@ -2140,11 +2624,11 @@ res_searchN(const char *name, /* domain name */ * fully-qualified. */ if (errno == ECONNREFUSED) { - h_errno = TRY_AGAIN; + RES_SET_H_ERRNO(res, TRY_AGAIN); return (-1); } - switch (h_errno) { + switch (res->res_h_errno) { case NO_DATA: got_nodata++; /* FALLTHROUGH */ @@ -2152,9 +2636,9 @@ res_searchN(const char *name, /* domain name */ /* keep trying */ break; case TRY_AGAIN: + got_servfail++; if (hp->rcode == SERVFAIL) { /* try next search element, if any */ - got_servfail++; break; } /* FALLTHROUGH */ @@ -2166,18 +2650,30 @@ res_searchN(const char *name, /* domain name */ * if we got here for some reason other than DNSRCH, * we only wanted one iteration of the loop, so stop. */ - if (!(_res.options & RES_DNSRCH)) + if (!(res->options & RES_DNSRCH)) done++; } } + switch (res->res_h_errno) { + case NO_DATA: + case HOST_NOT_FOUND: + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) + break; + /* FALLTHROUGH */ + default: + goto giveup; + } + /* - * if we have not already tried the name "as is", do that now. - * note that we do this regardless of how many dots were in the - * name or whether it ends with a dot. + * If the query has not already been tried as is then try it + * unless RES_NOTLDQUERY is set and there were no dots. */ - if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) { - ret = res_querydomainN(name, NULL, target); + if ((dots || !searched || !(res->options & RES_NOTLDQUERY)) && + !(tried_as_is || root_on_list)) { + ret = res_querydomainN(name, NULL, target, res); if (ret > 0) return (ret); } @@ -2190,12 +2686,13 @@ res_searchN(const char *name, /* domain name */ * else send back meaningless h_errno, that being the one from * the last DNSRCH we did. */ +giveup: if (saved_herrno != -1) - h_errno = saved_herrno; + RES_SET_H_ERRNO(res, saved_herrno); else if (got_nodata) - h_errno = NO_DATA; + RES_SET_H_ERRNO(res, NO_DATA); else if (got_servfail) - h_errno = TRY_AGAIN; + RES_SET_H_ERRNO(res, TRY_AGAIN); return (-1); } @@ -2205,18 +2702,14 @@ res_searchN(const char *name, /* domain name */ */ static int res_querydomainN(const char *name, const char *domain, - struct res_target *target) + struct res_target *target, res_state res) { char nbuf[MAXDNAME]; const char *longname = nbuf; size_t n, d; - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - h_errno = NETDB_INTERNAL; - return (-1); - } #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (res->options & RES_DEBUG) printf(";; res_querydomain(%s, %s)\n", name, domain?domain:""); #endif @@ -2227,7 +2720,7 @@ res_querydomainN(const char *name, const char *domain, */ n = strlen(name); if (n >= MAXDNAME) { - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(res, NO_RECOVERY); return (-1); } if (n > 0 && name[--n] == '.') { @@ -2239,10 +2732,10 @@ res_querydomainN(const char *name, const char *domain, n = strlen(name); d = strlen(domain); if (n + d + 1 >= MAXDNAME) { - h_errno = NO_RECOVERY; + RES_SET_H_ERRNO(res, NO_RECOVERY); return (-1); } snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); } - return (res_queryN(longname, target)); + return (res_queryN(longname, target, res)); } diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c index 528a2971a6..19ae1d23d6 100644 --- a/lib/libc/net/gethostbydns.c +++ b/lib/libc/net/gethostbydns.c @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -49,8 +49,8 @@ * --Copyright-- * * @(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93 - * $From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $ - * $FreeBSD: src/lib/libc/net/gethostbydns.c,v 1.27.2.5 2002/11/02 18:54:57 ume Exp $ + * From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $ + * $FreeBSD: src/lib/libc/net/gethostbydns.c,v 1.58 2007/01/09 00:28:02 imp Exp $ * $DragonFly: src/lib/libc/net/gethostbydns.c,v 1.6 2005/11/13 02:04:47 swildner Exp $ */ @@ -73,25 +73,20 @@ #include #include +#include "netdb_private.h" #include "res_config.h" #define SPRINTF(x) ((size_t)sprintf x) -#define MAXALIASES 35 -#define MAXADDRS 35 - static const char AskedForGot[] = "gethostby*.gethostanswer: asked for \"%s\", got \"%s\""; -static char *h_addr_ptrs[MAXADDRS + 1]; - -static struct hostent host; -static char *host_aliases[MAXALIASES]; -static char hostbuf[8*1024]; -static u_char host_addr[16]; /* IPv4 or IPv6 */ - #ifdef RESOLVSORT -static void addrsort (char **, int); +static void addrsort(char **, int, res_state); +#endif + +#ifdef DEBUG +static void dprintf(char *, int, res_state) __printflike(1, 0); #endif #define MAXPACKET (64*1024) @@ -106,14 +101,13 @@ typedef union { char ac; } align; -extern int h_errno; int _dns_ttl_; #ifdef DEBUG static void -dprintf(char *msg, int num) +dprintf(char *msg, int num, res_state res) { - if (_res.options & RES_DEBUG) { + if (res->options & RES_DEBUG) { int save = errno; printf(msg, num); @@ -121,43 +115,44 @@ dprintf(char *msg, int num) } } #else -# define dprintf(msg, num) /*nada*/ +# define dprintf(msg, num, res) /*nada*/ #endif #define BOUNDED_INCR(x) \ do { \ cp += x; \ if (cp > eom) { \ - h_errno = NO_RECOVERY; \ - return (NULL); \ + RES_SET_H_ERRNO(statp, NO_RECOVERY); \ + return (-1); \ } \ } while (0) #define BOUNDS_CHECK(ptr, count) \ do { \ if ((ptr) + (count) > eom) { \ - h_errno = NO_RECOVERY; \ - return (NULL); \ + RES_SET_H_ERRNO(statp, NO_RECOVERY); \ + return (-1); \ } \ } while (0) -static struct hostent * -gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) +static int +gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, + struct hostent *he, struct hostent_data *hed, res_state statp) { const HEADER *hp; const u_char *cp; int n; const u_char *eom, *erdata; - char *bp, **ap, **hap; - int type, class, buflen, ancount, qdcount; + char *bp, *ep, **ap, **hap; + int type, class, ancount, qdcount; int haveanswer, had_error; int toobig = 0; char tbuf[MAXDNAME]; const char *tname; - int (*name_ok) (const char *); + int (*name_ok)(const char *); tname = qname; - host.h_name = NULL; + he->h_name = NULL; eom = answer->buf + anslen; switch (qtype) { case T_A: @@ -168,8 +163,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) name_ok = res_dnok; break; default: - h_errno = NO_RECOVERY; - return (NULL); /* XXX should be abort(); */ + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); /* XXX should be abort(); */ } /* * find first satisfactory answer @@ -177,18 +172,18 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) hp = &answer->hdr; ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); - bp = hostbuf; - buflen = sizeof hostbuf; + bp = hed->hostbuf; + ep = hed->hostbuf + sizeof hed->hostbuf; cp = answer->buf; BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { - h_errno = NO_RECOVERY; - return (NULL); + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { - h_errno = NO_RECOVERY; - return (NULL); + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } BOUNDED_INCR(n + QFIXEDSZ); if (qtype == T_A || qtype == T_AAAA) { @@ -198,26 +193,25 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) */ n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { - h_errno = NO_RECOVERY; - return (NULL); + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } - host.h_name = bp; + he->h_name = bp; bp += n; - buflen -= n; /* The qname can be abbreviated, but h_name is now absolute. */ - qname = host.h_name; + qname = he->h_name; } - ap = host_aliases; + ap = hed->host_aliases; *ap = NULL; - host.h_aliases = host_aliases; - hap = h_addr_ptrs; + he->h_aliases = hed->host_aliases; + hap = hed->h_addr_ptrs; *hap = NULL; - host.h_addr_list = h_addr_ptrs; + he->h_addr_list = hed->h_addr_ptrs; haveanswer = 0; had_error = 0; _dns_ttl_ = -1; while (ancount-- > 0 && cp < eom && !had_error) { - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !(*name_ok)(bp)) { had_error++; continue; @@ -225,9 +219,9 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) cp += n; /* name */ BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); type = _getshort(cp); - cp += INT16SZ; /* type */ + cp += INT16SZ; /* type */ class = _getshort(cp); - cp += INT16SZ; /* class */ + cp += INT16SZ; /* class */ if (qtype == T_A && type == T_A) _dns_ttl_ = _getlong(cp); cp += INT32SZ; /* TTL */ @@ -241,7 +235,7 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) continue; /* XXX - had_error++ ? */ } if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { - if (ap >= &host_aliases[MAXALIASES-1]) + if (ap >= &hed->host_aliases[_MAXALIASES-1]) continue; n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); if ((n < 0) || !(*name_ok)(tbuf)) { @@ -250,8 +244,8 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) } cp += n; if (cp != erdata) { - h_errno = NO_RECOVERY; - return (NULL); + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } /* Store alias. */ *ap++ = bp; @@ -261,17 +255,15 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) continue; } bp += n; - buflen -= n; /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) { + if (n > ep - bp || n >= MAXHOSTNAMELEN) { had_error++; continue; } strcpy(bp, tbuf); - host.h_name = bp; + he->h_name = bp; bp += n; - buflen -= n; continue; } if (qtype == T_PTR && type == T_CNAME) { @@ -282,19 +274,18 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) } cp += n; if (cp != erdata) { - h_errno = NO_RECOVERY; - return (NULL); + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) { + if (n > ep - bp || n >= MAXHOSTNAMELEN) { had_error++; continue; } strcpy(bp, tbuf); tname = bp; bp += n; - buflen -= n; continue; } if (type != qtype) { @@ -314,7 +305,7 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) cp += n; continue; /* XXX - had_error++ ? */ } - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !res_hnok(bp)) { had_error++; break; @@ -322,12 +313,12 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) #if MULTI_PTRS_ARE_ALIASES cp += n; if (cp != erdata) { - h_errno = NO_RECOVERY; - return (NULL); + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } if (!haveanswer) - host.h_name = bp; - else if (ap < &host_aliases[MAXALIASES-1]) + he->h_name = bp; + else if (ap < &hed->host_aliases[_MAXALIASES-1]) *ap++ = bp; else n = -1; @@ -338,73 +329,69 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) break; } bp += n; - buflen -= n; } break; #else - host.h_name = bp; - if (_res.options & RES_USE_INET6) { + he->h_name = bp; + if (statp->options & RES_USE_INET6) { n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { had_error++; break; } bp += n; - buflen -= n; - _map_v4v6_hostent(&host, &bp, &buflen); + _map_v4v6_hostent(he, &bp, ep); } - h_errno = NETDB_SUCCESS; - return (&host); + RES_SET_H_ERRNO(statp, NETDB_SUCCESS); + return (0); #endif case T_A: case T_AAAA: - if (strcasecmp(host.h_name, bp) != 0) { + if (strcasecmp(he->h_name, bp) != 0) { syslog(LOG_NOTICE|LOG_AUTH, - AskedForGot, host.h_name, bp); + AskedForGot, he->h_name, bp); cp += n; continue; /* XXX - had_error++ ? */ } - if (n != host.h_length) { + if (n != he->h_length) { cp += n; continue; } if (!haveanswer) { int nn; - host.h_name = bp; + he->h_name = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; - buflen -= nn; } - buflen -= sizeof(align) - ((u_long)bp % sizeof(align)); bp += sizeof(align) - ((u_long)bp % sizeof(align)); - if (bp + n >= &hostbuf[sizeof hostbuf]) { - dprintf("size (%d) too big\n", n); + if (bp + n >= ep) { + dprintf("size (%d) too big\n", n, statp); had_error++; continue; } - if (hap >= &h_addr_ptrs[MAXADDRS-1]) { + if (hap >= &hed->h_addr_ptrs[_MAXADDRS-1]) { if (!toobig++) dprintf("Too many addresses (%d)\n", - MAXADDRS); + _MAXADDRS, statp); cp += n; continue; } - bcopy(cp, *hap++ = bp, n); + memcpy(*hap++ = bp, cp, n); bp += n; - buflen -= n; cp += n; if (cp != erdata) { - h_errno = NO_RECOVERY; - return (NULL); + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } break; default: - dprintf("Impossible condition (type=%d)\n", type); - h_errno = NO_RECOVERY; - return (NULL); + dprintf("Impossible condition (type=%d)\n", type, + statp); + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); /* BIND has abort() here, too risky on bad data */ } if (!had_error) @@ -419,236 +406,182 @@ gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype) * in its return structures - should give it the "best" * address in that case, not some random one */ - if (_res.nsort && haveanswer > 1 && qtype == T_A) - addrsort(h_addr_ptrs, haveanswer); + if (statp->nsort && haveanswer > 1 && qtype == T_A) + addrsort(hed->h_addr_ptrs, haveanswer, statp); # endif /*RESOLVSORT*/ - if (!host.h_name) { + if (!he->h_name) { n = strlen(qname) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) + if (n > ep - bp || n >= MAXHOSTNAMELEN) goto no_recovery; strcpy(bp, qname); - host.h_name = bp; + he->h_name = bp; bp += n; - buflen -= n; } - if (_res.options & RES_USE_INET6) - _map_v4v6_hostent(&host, &bp, &buflen); - h_errno = NETDB_SUCCESS; - return (&host); + if (statp->options & RES_USE_INET6) + _map_v4v6_hostent(he, &bp, ep); + RES_SET_H_ERRNO(statp, NETDB_SUCCESS); + return (0); } no_recovery: - h_errno = NO_RECOVERY; - return (NULL); + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); } +/* XXX: for async DNS resolver in ypserv */ struct hostent * __dns_getanswer(const char *answer, int anslen, const char *qname, int qtype) { - switch(qtype) { + struct hostent *he; + struct hostent_data *hed; + int error; + res_state statp; + + statp = __res_state(); + if ((he = __hostent_init()) == NULL || + (hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (NULL); + } + switch (qtype) { case T_AAAA: - host.h_addrtype = AF_INET6; - host.h_length = IN6ADDRSZ; + he->h_addrtype = AF_INET6; + he->h_length = NS_IN6ADDRSZ; break; case T_A: default: - host.h_addrtype = AF_INET; - host.h_length = INADDRSZ; + he->h_addrtype = AF_INET; + he->h_length = NS_INADDRSZ; break; } - return(gethostanswer((const querybuf *)answer, anslen, qname, qtype)); + error = gethostanswer((const querybuf *)answer, anslen, qname, qtype, + he, hed, statp); + return (error == 0) ? he : NULL; } int _dns_gethostbyname(void *rval, void *cb_data, va_list ap) { + const char *name; + int af; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct hostent *hptr, he; + struct hostent_data *hed; querybuf *buf; - const char *cp, *name; - char *bp; - int af, n, size, type, len; - struct hostent *hp; + int n, type, error; + res_state statp; name = va_arg(ap, const char *); af = va_arg(ap, int); - *(struct hostent **)rval = NULL; - - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - h_errno = NETDB_INTERNAL; - return NS_UNAVAIL; + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + *((struct hostent **)rval) = NULL; + + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } + he.h_addrtype = af; switch (af) { case AF_INET: - size = INADDRSZ; + he.h_length = NS_INADDRSZ; type = T_A; break; case AF_INET6: - size = IN6ADDRSZ; + he.h_length = NS_IN6ADDRSZ; type = T_AAAA; break; default: - h_errno = NETDB_INTERNAL; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; errno = EAFNOSUPPORT; - return NS_UNAVAIL; + return (NS_UNAVAIL); } - host.h_addrtype = af; - host.h_length = size; - - /* - * if there aren't any dots, it could be a user-level alias. - * this is also done in res_query() since we are not the only - * function that looks up host names. - */ - if (!strchr(name, '.') && (cp = __hostalias(name))) - name = cp; - - /* - * disallow names consisting only of digits/dots, unless - * they end in a dot. - */ - if (isdigit((unsigned char)name[0])) - for (cp = name;; ++cp) { - if (!*cp) { - if (*--cp == '.') - break; - /* - * All-numeric, no dot at the end. - * Fake up a hostent as if we'd actually - * done a lookup. - */ - if (inet_pton(af, name, host_addr) <= 0) { - h_errno = HOST_NOT_FOUND; - return NS_NOTFOUND; - } - strncpy(hostbuf, name, MAXDNAME); - hostbuf[MAXDNAME] = '\0'; - bp = hostbuf + MAXDNAME; - len = sizeof hostbuf - MAXDNAME; - host.h_name = hostbuf; - host.h_aliases = host_aliases; - host_aliases[0] = NULL; - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; - if (_res.options & RES_USE_INET6) - _map_v4v6_hostent(&host, &bp, &len); - h_errno = NETDB_SUCCESS; - *(struct hostent **)rval = &host; - return NS_SUCCESS; - } - if (!isdigit((unsigned char)*cp) && *cp != '.') - break; - } - if ((isxdigit((unsigned char)name[0]) && strchr(name, ':') != NULL) || - name[0] == ':') - for (cp = name;; ++cp) { - if (!*cp) { - if (*--cp == '.') - break; - /* - * All-IPv6-legal, no dot at the end. - * Fake up a hostent as if we'd actually - * done a lookup. - */ - if (inet_pton(af, name, host_addr) <= 0) { - h_errno = HOST_NOT_FOUND; - return NS_NOTFOUND; - } - strncpy(hostbuf, name, MAXDNAME); - hostbuf[MAXDNAME] = '\0'; - bp = hostbuf + MAXDNAME; - len = sizeof hostbuf - MAXDNAME; - host.h_name = hostbuf; - host.h_aliases = host_aliases; - host_aliases[0] = NULL; - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; - h_errno = NETDB_SUCCESS; - *(struct hostent **)rval = &host; - return NS_SUCCESS; - } - if (!isxdigit((unsigned char)*cp) && *cp != ':' && *cp != '.') - break; - } - if ((buf = malloc(sizeof(*buf))) == NULL) { - h_errno = NETDB_INTERNAL; - return (NULL); + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } - n = res_search(name, C_IN, type, buf->buf, sizeof(buf->buf)); + n = res_nsearch(statp, name, C_IN, type, buf->buf, sizeof(buf->buf)); if (n < 0) { free(buf); - dprintf("res_search failed (%d)\n", n); - return (NULL); + dprintf("res_nsearch failed (%d)\n", n, statp); + *h_errnop = statp->res_h_errno; + return (0); } else if (n > sizeof(buf->buf)) { free(buf); - dprintf("static buffer is too small (%d)\n", n); - return (NULL); + dprintf("static buffer is too small (%d)\n", n, statp); + *h_errnop = statp->res_h_errno; + return (0); } - *(struct hostent **)rval = gethostanswer(buf, n, name, type); + error = gethostanswer(buf, n, name, type, &he, hed, statp); free(buf); - return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; + if (error != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); } int _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) { - const char *addr; /* XXX should have been def'd as u_char! */ - int len, af; - + const void *addr; + socklen_t len; + int af; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; const u_char *uaddr; - static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; - static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; - int n, size; + struct hostent *hptr, he; + struct hostent_data *hed; + int n; querybuf *buf; - struct hostent *hp; char qbuf[MAXDNAME+1], *qp; + res_state statp; #ifdef SUNSECURITY - struct hostent *rhp; + struct hostdata rhd; + struct hostent *rhe; char **haddr; u_long old_options; - char hname2[MAXDNAME+1]; + char hname2[MAXDNAME+1], numaddr[46]; + int ret_h_error; #endif /*SUNSECURITY*/ - addr = va_arg(ap, const char *); - uaddr = (const u_char *)addr; - len = va_arg(ap, int); + addr = va_arg(ap, const void *); + len = va_arg(ap, socklen_t); af = va_arg(ap, int); + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + uaddr = (const u_char *)addr; - *(struct hostent **)rval = NULL; - - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - h_errno = NETDB_INTERNAL; - return NS_UNAVAIL; - } - if (af == AF_INET6 && len == IN6ADDRSZ && - (!bcmp(uaddr, mapped, sizeof mapped) || - !bcmp(uaddr, tunnelled, sizeof tunnelled))) { - /* Unmap. */ - addr += sizeof mapped; - uaddr += sizeof mapped; - af = AF_INET; - len = INADDRSZ; - } - switch (af) { - case AF_INET: - size = INADDRSZ; - break; - case AF_INET6: - size = IN6ADDRSZ; - break; - default: - errno = EAFNOSUPPORT; - h_errno = NETDB_INTERNAL; - return NS_UNAVAIL; - } - if (size != len) { - errno = EINVAL; - h_errno = NETDB_INTERNAL; - return NS_UNAVAIL; + *((struct hostent **)rval) = NULL; + + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } + switch (af) { case AF_INET: sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", @@ -659,7 +592,7 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) break; case AF_INET6: qp = qbuf; - for (n = IN6ADDRSZ - 1; n >= 0; n--) { + for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) { qp += SPRINTF((qp, "%x.%x.", uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf)); @@ -670,29 +603,28 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) abort(); } if ((buf = malloc(sizeof(*buf))) == NULL) { - h_errno = NETDB_INTERNAL; - return (NULL); - } - n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf->buf, sizeof buf->buf); - if (n < 0 && af == AF_INET6) { - *qp = '\0'; - strlcat(qbuf, "ip6.int", sizeof(qbuf)); - n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf->buf, - sizeof buf->buf); + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return NS_NOTFOUND; } + n = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf->buf, + sizeof buf->buf); if (n < 0) { free(buf); - dprintf("res_query failed (%d)\n", n); - return NS_UNAVAIL; + dprintf("res_nquery failed (%d)\n", n, statp); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); } if (n > sizeof buf->buf) { free(buf); - dprintf("static buffer is too small (%d)\n", n); - return NS_UNAVAIL; + dprintf("static buffer is too small (%d)\n", n, statp); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); } - if (!(hp = gethostanswer(buf, n, qbuf, T_PTR))) { + if (gethostanswer(buf, n, qbuf, T_PTR, &he, hed, statp) != 0) { free(buf); - return NS_NOTFOUND; /* h_errno was set by gethostanswer() */ + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); /* h_errno was set by gethostanswer() */ } free(buf); #ifdef SUNSECURITY @@ -701,61 +633,74 @@ _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) * turn off search as the name should be absolute, * 'localhost' should be matched by defnames */ - strncpy(hname2, hp->h_name, MAXDNAME); + strncpy(hname2, he.h_name, MAXDNAME); hname2[MAXDNAME] = '\0'; - old_options = _res.options; - _res.options &= ~RES_DNSRCH; - _res.options |= RES_DEFNAMES; - if (!(rhp = gethostbyname(hname2))) { + old_options = statp->options; + statp->options &= ~RES_DNSRCH; + statp->options |= RES_DEFNAMES; + memset(&rhd, 0, sizeof rhd); + rhe = gethostbyname_r(hname2, &rhd.host, &rhd.data, + sizeof(rhd.data), &ret_h_error); + if (rhe == NULL) { + if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) + strlcpy(numaddr, "UNKNOWN", sizeof(numaddr)); syslog(LOG_NOTICE|LOG_AUTH, "gethostbyaddr: No A record for %s (verifying [%s])", - hname2, inet_ntoa(*((struct in_addr *)addr))); - _res.options = old_options; - h_errno = HOST_NOT_FOUND; - return NS_NOTFOUND; + hname2, numaddr); + statp->options = old_options; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } - _res.options = old_options; - for (haddr = rhp->h_addr_list; *haddr; haddr++) - if (!memcmp(*haddr, addr, INADDRSZ)) + statp->options = old_options; + for (haddr = rhe->h_addr_list; *haddr; haddr++) + if (!memcmp(*haddr, addr, NS_INADDRSZ)) break; if (!*haddr) { + if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) + strlcpy(numaddr, "UNKNOWN", sizeof(numaddr)); syslog(LOG_NOTICE|LOG_AUTH, "gethostbyaddr: A record of %s != PTR record [%s]", - hname2, inet_ntoa(*((struct in_addr *)addr))); - h_errno = HOST_NOT_FOUND; - return NS_NOTFOUND; + hname2, numaddr); + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } } #endif /*SUNSECURITY*/ - hp->h_addrtype = af; - hp->h_length = len; - bcopy(addr, host_addr, len); - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; - if (af == AF_INET && (_res.options & RES_USE_INET6)) { - _map_v4v6_address((char*)host_addr, (char*)host_addr); - hp->h_addrtype = AF_INET6; - hp->h_length = IN6ADDRSZ; + he.h_addrtype = af; + he.h_length = len; + memcpy(hed->host_addr, uaddr, len); + hed->h_addr_ptrs[0] = (char *)hed->host_addr; + hed->h_addr_ptrs[1] = NULL; + if (af == AF_INET && (statp->options & RES_USE_INET6)) { + _map_v4v6_address((char*)hed->host_addr, (char*)hed->host_addr); + he.h_addrtype = AF_INET6; + he.h_length = NS_IN6ADDRSZ; + } + RES_SET_H_ERRNO(statp, NETDB_SUCCESS); + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } - h_errno = NETDB_SUCCESS; - *(struct hostent **)rval = hp; - return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND; + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); } #ifdef RESOLVSORT static void -addrsort(char **ap, int num) +addrsort(char **ap, int num, res_state res) { int i, j; char **p; - short aval[MAXADDRS]; + short aval[_MAXADDRS]; int needsort = 0; p = ap; for (i = 0; i < num; i++, p++) { - for (j = 0 ; (unsigned)j < _res.nsort; j++) - if (_res.sort_list[j].addr.s_addr == - (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) + for (j = 0 ; (unsigned)j < res->nsort; j++) + if (res->sort_list[j].addr.s_addr == + (((struct in_addr *)(*p))->s_addr & res->sort_list[j].mask)) break; aval[i] = j; if (needsort == 0 && i > 0 && j < aval[i-1]) @@ -784,18 +729,25 @@ addrsort(char **ap, int num) } } #endif + void _sethostdnsent(int stayopen) { - if ((_res.options & RES_INIT) == 0 && res_init() == -1) + res_state statp; + + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) return; if (stayopen) - _res.options |= RES_STAYOPEN | RES_USEVC; + statp->options |= RES_STAYOPEN | RES_USEVC; } void _endhostdnsent(void) { - _res.options &= ~(RES_STAYOPEN | RES_USEVC); - res_close(); + res_state statp; + + statp = __res_state(); + statp->options &= ~(RES_STAYOPEN | RES_USEVC); + res_nclose(statp); } diff --git a/lib/libc/net/gethostbyht.c b/lib/libc/net/gethostbyht.c index f87c568bf8..ead6f12839 100644 --- a/lib/libc/net/gethostbyht.c +++ b/lib/libc/net/gethostbyht.c @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -47,7 +47,7 @@ * --Copyright-- * * @(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93 - * $FreeBSD: src/lib/libc/net/gethostbyht.c,v 1.12 1999/08/28 00:00:05 peter Exp $ + * $FreeBSD: src/lib/libc/net/gethostbyht.c,v 1.27 2007/01/09 00:28:02 imp Exp $ * $DragonFly: src/lib/libc/net/gethostbyht.c,v 1.6 2005/11/13 02:04:47 swildner Exp $ */ @@ -63,66 +63,60 @@ #include #include /* XXX */ #include /* XXX */ - -#define MAXALIASES 35 - -static struct hostent host; -static char *host_aliases[MAXALIASES]; -static char hostbuf[BUFSIZ+1]; -static FILE *hostf = NULL; -static u_int32_t host_addr[4]; /* IPv4 or IPv6 */ -static char *h_addr_ptrs[2]; -static int stayopen = 0; +#include "netdb_private.h" void -_sethosthtent(int f) +_sethosthtent(int f, struct hostent_data *hed) { - if (!hostf) - hostf = fopen(_PATH_HOSTS, "r" ); + if (!hed->hostf) + hed->hostf = fopen(_PATH_HOSTS, "r"); else - rewind(hostf); - stayopen = f; + rewind(hed->hostf); + hed->stayopen = f; } void -_endhosthtent(void) +_endhosthtent(struct hostent_data *hed) { - if (hostf && !stayopen) { - fclose(hostf); - hostf = NULL; + if (hed->hostf && !hed->stayopen) { + fclose(hed->hostf); + hed->hostf = NULL; } } -struct hostent * -gethostent(void) +static int +gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped, + res_state statp) { - char *p; + char *p, *bp, *ep; char *cp, **q; int af, len; + char hostbuf[BUFSIZ + 1]; - if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { - h_errno = NETDB_INTERNAL; - return (NULL); + if (!hed->hostf && !(hed->hostf = fopen(_PATH_HOSTS, "r"))) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); } again: - if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { - h_errno = HOST_NOT_FOUND; - return (NULL); + if (!(p = fgets(hostbuf, sizeof hostbuf, hed->hostf))) { + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + return (-1); } if (*p == '#') goto again; - if (!(cp = strpbrk(p, "#\n"))) - goto again; - *cp = '\0'; + cp = strpbrk(p, "#\n"); + if (cp != NULL) + *cp = '\0'; if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; - if (inet_pton(AF_INET6, p, host_addr) > 0) { + if (inet_pton(AF_INET6, p, hed->host_addr) > 0) { af = AF_INET6; len = IN6ADDRSZ; - } else if (inet_pton(AF_INET, p, host_addr) > 0) { - if (_res.options & RES_USE_INET6) { - _map_v4v6_address((char*)host_addr, (char*)host_addr); + } else if (inet_pton(AF_INET, p, hed->host_addr) > 0) { + if (mapped) { + _map_v4v6_address((char *)hed->host_addr, + (char *)hed->host_addr); af = AF_INET6; len = IN6ADDRSZ; } else { @@ -132,30 +126,89 @@ gethostent(void) } else { goto again; } - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; - host.h_length = len; - host.h_addrtype = af; + hed->h_addr_ptrs[0] = (char *)hed->host_addr; + hed->h_addr_ptrs[1] = NULL; + he->h_addr_list = hed->h_addr_ptrs; + he->h_length = len; + he->h_addrtype = af; while (*cp == ' ' || *cp == '\t') cp++; - host.h_name = cp; - q = host.h_aliases = host_aliases; - if ((cp = strpbrk(cp, " \t")) != NULL) - *cp++ = '\0'; + bp = hed->hostbuf; + ep = hed->hostbuf + sizeof hed->hostbuf; + he->h_name = bp; + q = he->h_aliases = hed->host_aliases; + if ((p = strpbrk(cp, " \t")) != NULL) + *p++ = '\0'; + len = strlen(cp) + 1; + if (ep - bp < len) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + strlcpy(bp, cp, ep - bp); + bp += len; + cp = p; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } - if (q < &host_aliases[MAXALIASES - 1]) - *q++ = cp; - if ((cp = strpbrk(cp, " \t")) != NULL) - *cp++ = '\0'; + if (q >= &hed->host_aliases[_MAXALIASES - 1]) + break; + if ((p = strpbrk(cp, " \t")) != NULL) + *p++ = '\0'; + len = strlen(cp) + 1; + if (ep - bp < len) + break; + strlcpy(bp, cp, ep - bp); + *q++ = bp; + bp += len; + cp = p; } *q = NULL; - h_errno = NETDB_SUCCESS; - return (&host); + RES_SET_H_ERRNO(statp, NETDB_SUCCESS); + return (0); +} + +int +gethostent_r(struct hostent *hptr, char *buffer, size_t buflen, + struct hostent **result, int *h_errnop) +{ + struct hostent_data *hed; + struct hostent he; + res_state statp; + + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); + } + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); + } + if (gethostent_p(&he, hed, statp->options & RES_USE_INET6, statp) != 0) + return (-1); + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) + return (-1); + *result = hptr; + return (0); +} + +struct hostent * +gethostent(void) +{ + struct hostdata *hd; + struct hostent *rval; + int ret_h_errno; + + if ((hd = __hostdata_init()) == NULL) + return (NULL); + if (gethostent_r(&hd->host, hd->data, sizeof(hd->data), &rval, + &ret_h_errno) != 0) + return (NULL); + return (rval); } int @@ -163,46 +216,114 @@ _ht_gethostbyname(void *rval, void *cb_data, va_list ap) { const char *name; int af; - struct hostent *p; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct hostent *hptr, he; + struct hostent_data *hed; char **cp; + res_state statp; + int error; name = va_arg(ap, const char *); af = va_arg(ap, int); + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + *((struct hostent **)rval) = NULL; + + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } - sethostent(0); - while ((p = gethostent()) != NULL) { - if (p->h_addrtype != af) + _sethosthtent(0, hed); + while ((error = gethostent_p(&he, hed, 0, statp)) == 0) { + if (he.h_addrtype != af) continue; - if (strcasecmp(p->h_name, name) == 0) + if (he.h_addrtype == AF_INET && + statp->options & RES_USE_INET6) { + _map_v4v6_address(he.h_addr, he.h_addr); + he.h_length = IN6ADDRSZ; + he.h_addrtype = AF_INET6; + } + if (strcasecmp(he.h_name, name) == 0) break; - for (cp = p->h_aliases; *cp != 0; cp++) + for (cp = he.h_aliases; *cp != 0; cp++) if (strcasecmp(*cp, name) == 0) goto found; } found: - endhostent(); - *(struct hostent **)rval = p; + _endhosthtent(hed); - return (p != NULL) ? NS_SUCCESS : NS_NOTFOUND; + if (error != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); } int _ht_gethostbyaddr(void *rval, void *cb_data, va_list ap) { - const char *addr; - int len, af; - struct hostent *p; + const void *addr; + socklen_t len; + int af; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct hostent *hptr, he; + struct hostent_data *hed; + res_state statp; + int error; - addr = va_arg(ap, const char *); - len = va_arg(ap, int); + addr = va_arg(ap, const void *); + len = va_arg(ap, socklen_t); af = va_arg(ap, int); + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + *((struct hostent **)rval) = NULL; - sethostent(0); - while ((p = gethostent()) != NULL) - if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len)) + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + + _sethosthtent(0, hed); + while ((error = gethostent_p(&he, hed, 0, statp)) == 0) + if (he.h_addrtype == af && !bcmp(he.h_addr, addr, len)) { + if (he.h_addrtype == AF_INET && + statp->options & RES_USE_INET6) { + _map_v4v6_address(he.h_addr, he.h_addr); + he.h_length = IN6ADDRSZ; + he.h_addrtype = AF_INET6; + } break; - endhostent(); + } + _endhosthtent(hed); - *(struct hostent **)rval = p; - return (p != NULL) ? NS_SUCCESS : NS_NOTFOUND; + if (error != 0) + return (NS_NOTFOUND); + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); } diff --git a/lib/libc/net/gethostbyname.3 b/lib/libc/net/gethostbyname.3 index 93d764d059..6344d48e95 100644 --- a/lib/libc/net/gethostbyname.3 +++ b/lib/libc/net/gethostbyname.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,10 +26,10 @@ .\" SUCH DAMAGE. .\" .\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95 -.\" $FreeBSD: src/lib/libc/net/gethostbyname.3,v 1.12.2.7 2001/12/14 18:33:55 ru Exp $ +.\" $FreeBSD: src/lib/libc/net/gethostbyname.3,v 1.38 2007/01/09 00:28:02 imp Exp $ .\" $DragonFly: src/lib/libc/net/gethostbyname.3,v 1.3 2006/11/17 23:01:21 swildner Exp $ .\" -.Dd May 25, 1995 +.Dd May 12, 2006 .Dt GETHOSTBYNAME 3 .Os .Sh NAME @@ -50,7 +46,7 @@ .Lb libc .Sh SYNOPSIS .In netdb.h -.Vt extern int h_errno ; +.Vt int h_errno ; .Ft struct hostent * .Fn gethostbyname "const char *name" .Ft struct hostent * @@ -68,6 +64,19 @@ .Ft const char * .Fn hstrerror "int err" .Sh DESCRIPTION +.Bf -symbolic +The +.Xr getaddrinfo 3 +and +.Xr getnameinfo 3 +functions are preferred over the +.Fn gethostbyname , +.Fn gethostbyname2 , +and +.Fn gethostbyaddr +functions. +.Ef +.Pp The .Fn gethostbyname , .Fn gethostbyname2 @@ -77,12 +86,41 @@ functions each return a pointer to an object with the following structure describing an internet host referenced by name or by address, respectively. -This structure contains either the information obtained from the name server, +.Pp +The +.Fa name +argument passed to +.Fn gethostbyname +or +.Fn gethostbyname2 +should point to a +.Dv NUL Ns -terminated +hostname. +The +.Fa addr +argument passed to +.Fn gethostbyaddr +should point to an address which is +.Fa len +bytes long, +in binary form +(i.e., not an IP address in human readable +.Tn ASCII +form). +The +.Fa type +argument specifies the address family +(e.g.\& +.Dv AF_INET , AF_INET6 , +etc.) of this address. +.Pp +The structure returned contains either the information obtained from the name +server, .Xr named 8 , broken-out fields from a line in .Pa /etc/hosts , or database entries supplied by the -.Xr yp 4 +.Xr yp 8 system. The order of the lookups is controlled by the .Sq hosts @@ -145,16 +183,6 @@ which is intended to allow lookups in address families other than .Dv AF_INET , for example .Dv AF_INET6 . -Currently the -.Fa af -argument must be specified as -.Dv AF_INET -else the function will return -.Dv NULL -after having set -.Va h_errno -to -.Dv NETDB_INTERNAL .Pp The .Fn sethostent @@ -186,8 +214,8 @@ connection. The .Fn herror function writes a message to the diagnostic output consisting of the -string parameter -.Fa s , +string argument +.Fa string , the constant string .Qq Li ":\ " , and a message corresponding to the value of @@ -198,13 +226,29 @@ The function returns a string which is the message text corresponding to the value of the .Fa err -parameter. +argument. .Sh FILES .Bl -tag -width /etc/nsswitch.conf -compact .It Pa /etc/hosts .It Pa /etc/nsswitch.conf .It Pa /etc/resolv.conf .El +.Sh EXAMPLES +Print out the hostname associated with a specific IP address: +.Bd -literal -offset indent +const char *ipstr = "127.0.0.1"; +struct in_addr ip; +struct hostent *hp; + +if (!inet_aton(ipstr, &ip)) + errx(1, "can't parse IP address %s", ipstr); + +if ((hp = gethostbyaddr((const void *)&ip, + sizeof ip, AF_INET)) == NULL) + errx(1, "no name associated with %s", ipstr); + +printf("name associated with %s is %s\en", ipstr, hp->h_name); +.Ed .Sh DIAGNOSTICS Error return status from .Fn gethostbyname , @@ -214,7 +258,7 @@ and is indicated by return of a .Dv NULL pointer. -The external integer +The integer .Va h_errno may then be checked to see whether this is a temporary failure or an invalid or unknown host. @@ -253,6 +297,8 @@ for example, a mail-forwarder may be registered for this domain. .El .Sh SEE ALSO .Xr getaddrinfo 3 , +.Xr getnameinfo 3 , +.Xr inet_aton 3 , .Xr resolver 3 , .Xr hosts 5 , .Xr hostname 7 , @@ -267,7 +313,7 @@ and .Fn endhostent are redefined, when -.Em libc +.Lb libc is built to use only the routines to lookup in .Pa /etc/hosts and not the name server. @@ -317,8 +363,14 @@ function first appeared in .Tn BIND version 4.9.4. .Sh BUGS -These functions use static data storage; +These functions use a thread-specific data storage; if the data is needed for future use, it should be copied before any subsequent calls overwrite it. +.Pp +Though these functions are thread-safe, +still it is recommended to use the +.Xr getaddrinfo 3 +family of functions, instead. +.Pp Only the Internet address format is currently understood. diff --git a/lib/libc/net/gethostbynis.c b/lib/libc/net/gethostbynis.c index 59d3247375..768a4c5c1c 100644 --- a/lib/libc/net/gethostbynis.c +++ b/lib/libc/net/gethostbynis.c @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/net/gethostbynis.c,v 1.16 2003/01/05 14:05:24 fenner Exp $ + * $FreeBSD: src/lib/libc/net/gethostbynis.c,v 1.28 2006/05/12 15:37:23 ume Exp $ * $DragonFly: src/lib/libc/net/gethostbynis.c,v 1.4 2005/11/13 02:04:47 swildner Exp $ */ @@ -39,54 +39,50 @@ #include #include #include +#include /* XXX */ #ifdef YP #include #include #include #endif - -#define MAXALIASES 35 -#define MAXADDRS 35 - -extern int h_errno; +#include "netdb_private.h" #ifdef YP -static char *host_aliases[MAXALIASES]; -static char hostaddr[MAXADDRS]; -static char *host_addrs[2]; - -static struct hostent * -_gethostbynis(const char *name, char *map, int af) +static int +_gethostbynis(const char *name, char *map, int af, struct hostent *he, + struct hostent_data *hed) { + char *p, *bp, *ep; char *cp, **q; char *result; - int resultlen,size; - static struct hostent h; - static char *domain = (char *)NULL; - static char ypbuf[YPMAXRECORD + 2]; - in_addr_t addr; + int resultlen, size, addrok = 0; + char ypbuf[YPMAXRECORD + 2]; + res_state statp; + statp = __res_state(); switch(af) { case AF_INET: size = NS_INADDRSZ; break; - default: case AF_INET6: size = NS_IN6ADDRSZ; + break; + default: errno = EAFNOSUPPORT; - h_errno = NETDB_INTERNAL; - return NULL; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); } - if (domain == (char *)NULL) - if (yp_get_default_domain (&domain)) { - h_errno = NETDB_INTERNAL; - return ((struct hostent *)NULL); + if (hed->yp_domain == (char *)NULL) + if (yp_get_default_domain (&hed->yp_domain)) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); } - if (yp_match(domain, map, name, strlen(name), &result, &resultlen)) { - h_errno = HOST_NOT_FOUND; - return ((struct hostent *)NULL); + if (yp_match(hed->yp_domain, map, name, strlen(name), &result, + &resultlen)) { + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + return (-1); } /* avoid potential memory leak */ @@ -100,72 +96,206 @@ _gethostbynis(const char *name, char *map, int af) cp = strpbrk(result, " \t"); *cp++ = '\0'; - h.h_addr_list = host_addrs; - h.h_addr = hostaddr; - addr = inet_addr(result); - bcopy((char *)&addr, h.h_addr, size); - h.h_length = size; - h.h_addrtype = AF_INET; + he->h_addr_list = hed->h_addr_ptrs; + he->h_addr = (char *)hed->host_addr; + switch (af) { + case AF_INET: + addrok = inet_aton(result, (struct in_addr *)hed->host_addr); + if (addrok != 1) + break; + if (statp->options & RES_USE_INET6) { + _map_v4v6_address((char *)hed->host_addr, + (char *)hed->host_addr); + af = AF_INET6; + size = NS_IN6ADDRSZ; + } + break; + case AF_INET6: + addrok = inet_pton(af, result, hed->host_addr); + break; + } + if (addrok != 1) { + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + return (-1); + } + he->h_addr_list[1] = NULL; + he->h_length = size; + he->h_addrtype = af; while (*cp == ' ' || *cp == '\t') cp++; - h.h_name = cp; - q = h.h_aliases = host_aliases; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; + bp = hed->hostbuf; + ep = hed->hostbuf + sizeof hed->hostbuf; + he->h_name = bp; + q = he->h_aliases = hed->host_aliases; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + size = strlen(cp) + 1; + if (ep - bp < size) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + strlcpy(bp, cp, ep - bp); + bp += size; + cp = p; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } - if (q < &host_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; + if (q >= &hed->host_aliases[_MAXALIASES - 1]) + break; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + size = strlen(cp) + 1; + if (ep - bp < size) + break; + strlcpy(bp, cp, ep - bp); + *q++ = bp; + bp += size; + cp = p; } *q = NULL; - return (&h); + return (0); +} + +static int +_gethostbynisname_r(const char *name, int af, struct hostent *he, + struct hostent_data *hed) +{ + char *map; + + switch (af) { + case AF_INET: + map = "hosts.byname"; + break; + default: + map = "ipnodes.byname"; + break; + } + return (_gethostbynis(name, map, af, he, hed)); +} + +static int +_gethostbynisaddr_r(const void *addr, socklen_t len, int af, + struct hostent *he, struct hostent_data *hed) +{ + char *map; + char numaddr[46]; + + switch (af) { + case AF_INET: + map = "hosts.byaddr"; + break; + default: + map = "ipnodes.byaddr"; + break; + } + if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) + return (-1); + return (_gethostbynis(numaddr, map, af, he, hed)); } #endif /* YP */ -/* XXX _gethostbynisname/_gethostbynisaddr only used by getaddrinfo */ +/* XXX _gethostbynisname/_gethostbynisaddr only used by getipnodeby*() */ struct hostent * _gethostbynisname(const char *name, int af) { #ifdef YP - return _gethostbynis(name, "hosts.byname", af); + struct hostent *he; + struct hostent_data *hed; + u_long oresopt; + int error; + res_state statp; + + statp = __res_state(); + if ((he = __hostent_init()) == NULL || + (hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (NULL); + } + + oresopt = statp->options; + statp->options &= ~RES_USE_INET6; + error = _gethostbynisname_r(name, af, he, hed); + statp->options = oresopt; + return (error == 0) ? he : NULL; #else - return NULL; + return (NULL); #endif } struct hostent * -_gethostbynisaddr(const char *addr, int len, int af) +_gethostbynisaddr(const void *addr, socklen_t len, int af) { #ifdef YP - return _gethostbynis(inet_ntoa(*(struct in_addr *)addr), - "hosts.byaddr", af); + struct hostent *he; + struct hostent_data *hed; + u_long oresopt; + int error; + res_state statp; + + statp = __res_state(); + if ((he = __hostent_init()) == NULL || + (hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (NULL); + } + + oresopt = statp->options; + statp->options &= ~RES_USE_INET6; + error = _gethostbynisaddr_r(addr, len, af, he, hed); + statp->options = oresopt; + return (error == 0) ? he : NULL; #else - return NULL; + return (NULL); #endif } - int _nis_gethostbyname(void *rval, void *cb_data, va_list ap) { #ifdef YP const char *name; int af; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct hostent *hptr, he; + struct hostent_data *hed; + res_state statp; name = va_arg(ap, const char *); af = va_arg(ap, int); + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + *((struct hostent **)rval) = NULL; - *(struct hostent **)rval = _gethostbynis(name, "hosts.byname", af); - return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + + if (_gethostbynisname_r(name, af, &he, hed) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); #else - return NS_UNAVAIL; + *((struct hostent **)rval) = NULL; + return (NS_UNAVAIL); #endif } @@ -173,17 +303,46 @@ int _nis_gethostbyaddr(void *rval, void *cb_data, va_list ap) { #ifdef YP - const char *addr; - int len; + const void *addr; + socklen_t len; int af; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct hostent *hptr, he; + struct hostent_data *hed; + res_state statp; - addr = va_arg(ap, const char *); - len = va_arg(ap, int); + addr = va_arg(ap, const void *); + len = va_arg(ap, socklen_t); af = va_arg(ap, int); + hptr = va_arg(ap, struct hostent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + *((struct hostent **)rval) = NULL; + + statp = __res_state(); + if ((hed = __hostent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } - *(struct hostent **)rval =_gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr", af); - return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; + if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct hostent **)rval) = hptr; + return (NS_SUCCESS); #else - return NS_UNAVAIL; + *((struct hostent **)rval) = NULL; + return (NS_UNAVAIL); #endif } diff --git a/lib/libc/net/gethostnamadr.c b/lib/libc/net/gethostnamadr.c index ae4060e10b..3fa0ddd9bf 100644 --- a/lib/libc/net/gethostnamadr.c +++ b/lib/libc/net/gethostnamadr.c @@ -22,10 +22,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/net/gethostnamadr.c,v 1.15.2.2 2001/03/05 10:40:42 obrien Exp $ + * $FreeBSD: src/lib/libc/net/gethostnamadr.c,v 1.33 2006/05/21 11:27:28 ume Exp $ * $DragonFly: src/lib/libc/net/gethostnamadr.c,v 1.6 2007/12/29 22:55:29 matthias Exp $ */ +#include "namespace.h" +#include "reentrant.h" #include #include #include @@ -33,11 +35,15 @@ #include #include #include +#include +#include #include #include #include #include /* XXX hack for _res */ #include /* XXX hack for _res */ +#include "un-namespace.h" +#include "netdb_private.h" #ifdef NS_CACHING #include "nscache.h" #endif @@ -49,6 +55,9 @@ extern int _ht_gethostbyaddr(void *, void *, va_list); extern int _dns_gethostbyaddr(void *, void *, va_list); extern int _nis_gethostbyaddr(void *, void *, va_list); +static int gethostbyname_internal(const char *, int, struct hostent *, char *, + size_t, struct hostent **, int *, res_state); + /* Host lookup order if nsswitch.conf is broken or nonexistant */ static const ns_src default_src[] = { { NSSRC_FILES, NS_SUCCESS }, @@ -61,83 +70,94 @@ static int host_marshal_func(char *, size_t *, void *, va_list, void *); static int host_unmarshal_func(char *, size_t, void *, va_list, void *); #endif -struct hostent * -gethostbyname(const char *name) -{ - struct hostent *hp; +NETDB_THREAD_ALLOC(hostent) +NETDB_THREAD_ALLOC(hostent_data) +NETDB_THREAD_ALLOC(hostdata) - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - h_errno = NETDB_INTERNAL; - return (NULL); - } - if (_res.options & RES_USE_INET6) { /* XXX */ - hp = gethostbyname2(name, AF_INET6); /* XXX */ - if (hp) /* XXX */ - return (hp); /* XXX */ - } /* XXX */ - return (gethostbyname2(name, AF_INET)); +static void +hostent_free(void *ptr) +{ + free(ptr); } -struct hostent * -gethostbyname2(const char *name, int type) +static void +hostent_data_free(void *ptr) { - struct hostent *hp = 0; - int rval; - -#ifdef NS_CACHING - static const nss_cache_info cache_info = - NS_COMMON_CACHE_INFO_INITIALIZER( - hosts, (void *)nss_lt_name, - host_id_func, host_marshal_func, host_unmarshal_func); -#endif - static const ns_dtab dtab[] = { - NS_FILES_CB(_ht_gethostbyname, NULL) - { NSSRC_DNS, _dns_gethostbyname, NULL }, - NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */ -#ifdef NS_CACHING - NS_CACHE_CB(&cache_info) -#endif - { 0 } - }; + struct hostent_data *hed = ptr; - rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyname", - default_src, name, type); + if (hed == NULL) + return; + hed->stayopen = 0; + _endhosthtent(hed); + free(hed); +} - if (rval != NS_SUCCESS) - return NULL; - else - return hp; +static void +hostdata_free(void *ptr) +{ + free(ptr); } -struct hostent * -gethostbyaddr(const void *addr, socklen_t len, int type) +int +__copy_hostent(struct hostent *he, struct hostent *hptr, char *buf, + size_t buflen) { - struct hostent *hp = 0; - int rval; + char *cp; + char **ptr; + int i, n; + int nptr, len; + + /* Find out the amount of space required to store the answer. */ + nptr = 2; /* NULL ptrs */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; he->h_addr_list[i]; i++, nptr++) { + len += he->h_length; + } + for (i = 0; he->h_aliases[i]; i++, nptr++) { + len += strlen(he->h_aliases[i]) + 1; + } + len += strlen(he->h_name) + 1; + len += nptr * sizeof(char*); -#ifdef NS_CACHING - static const nss_cache_info cache_info = - NS_COMMON_CACHE_INFO_INITIALIZER( - hosts, (void *)nss_lt_id, - host_id_func, host_marshal_func, host_unmarshal_func); -#endif - static const ns_dtab dtab[] = { - NS_FILES_CB(_ht_gethostbyaddr, NULL) - { NSSRC_DNS, _dns_gethostbyaddr, NULL }, - NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */ -#ifdef NS_CACHING - NS_CACHE_CB(&cache_info) -#endif - { 0 } - }; + if (len > buflen) { + errno = ERANGE; + return (-1); + } + + /* copy address size and type */ + hptr->h_addrtype = he->h_addrtype; + n = hptr->h_length = he->h_length; - rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyaddr", - default_src, addr, len, type); + ptr = (char **)ALIGN(buf); + cp = (char *)ALIGN(buf) + nptr * sizeof(char *); - if (rval != NS_SUCCESS) - return NULL; - else - return hp; + /* copy address list */ + hptr->h_addr_list = ptr; + for (i = 0; he->h_addr_list[i]; i++ , ptr++) { + memcpy(cp, he->h_addr_list[i], n); + hptr->h_addr_list[i] = cp; + cp += n; + } + hptr->h_addr_list[i] = NULL; + ptr++; + + /* copy official name */ + n = strlen(he->h_name) + 1; + strcpy(cp, he->h_name); + hptr->h_name = cp; + cp += n; + + /* copy aliases */ + hptr->h_aliases = ptr; + for (i = 0 ; he->h_aliases[i]; i++) { + n = strlen(he->h_aliases[i]) + 1; + strcpy(cp, he->h_aliases[i]); + hptr->h_aliases[i] = cp; + cp += n; + } + hptr->h_aliases[i] = NULL; + + return (0); } #ifdef NS_CACHING @@ -149,7 +169,9 @@ host_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) const int op_id = 1; char *str; - int len, type; + void *addr; + socklen_t len; + int type; size_t desired_size, size; enum nss_lookup_type lookup_type; @@ -194,12 +216,13 @@ host_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) res = NS_SUCCESS; break; case nss_lt_id: - str = va_arg(ap, char *); - len = va_arg(ap, int); + addr = va_arg(ap, void *); + len = va_arg(ap, socklen_t); type = va_arg(ap, int); desired_size = sizeof(res_options) + sizeof(int) + - sizeof(enum nss_lookup_type) + sizeof(int) * 2 + len; + sizeof(enum nss_lookup_type) + sizeof(int) + + sizeof(socklen_t) + len; if (desired_size > *buffer_size) { res = NS_RETURN; @@ -219,10 +242,10 @@ host_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) memcpy(p, &type, sizeof(int)); p += sizeof(int); - memcpy(p, &len, sizeof(int)); - p += sizeof(int); + memcpy(p, &len, sizeof(socklen_t)); + p += sizeof(socklen_t); - memcpy(p, str, len); + memcpy(p, addr, len); res = NS_SUCCESS; break; @@ -238,10 +261,12 @@ fin: static int host_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, - void *cache_mdata) + void *cache_mdata) { char *str; - int len, type; + void *addr; + socklen_t len; + int type; struct hostent *ht; struct hostent new_ht; @@ -254,8 +279,8 @@ host_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, type = va_arg(ap, int); break; case nss_lt_id: - str = va_arg(ap, char *); - len = va_arg(ap, int); + addr = va_arg(ap, void *); + len = va_arg(ap, socklen_t); type = va_arg(ap, int); break; default: @@ -342,10 +367,12 @@ host_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, static int host_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, - void *cache_mdata) + void *cache_mdata) { char *str; - int len, type; + void *addr; + socklen_t len; + int type; struct hostent *ht; char *p; @@ -359,8 +386,8 @@ host_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, type = va_arg(ap, int); break; case nss_lt_id: - str = va_arg(ap, char *); - len = va_arg(ap, int); + addr = va_arg(ap, void *); + len = va_arg(ap, socklen_t); type = va_arg(ap, int); break; default: @@ -408,16 +435,290 @@ host_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, } #endif /* NS_CACHING */ +static int +fakeaddr(const char *name, int af, struct hostent *hp, char *buf, + size_t buflen, res_state statp) +{ + struct hostent_data *hed; + struct hostent he; + + if ((hed = __hostent_data_init()) == NULL) { + errno = ENOMEM; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); + } + + if ((af != AF_INET || + inet_aton(name, (struct in_addr *)hed->host_addr) != 1) && + inet_pton(af, name, hed->host_addr) != 1) { + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + return (-1); + } + strncpy(hed->hostbuf, name, MAXDNAME); + hed->hostbuf[MAXDNAME] = '\0'; + if (af == AF_INET && (statp->options & RES_USE_INET6) != 0U) { + _map_v4v6_address((char *)hed->host_addr, + (char *)hed->host_addr); + af = AF_INET6; + } + he.h_addrtype = af; + switch(af) { + case AF_INET: + he.h_length = NS_INADDRSZ; + break; + case AF_INET6: + he.h_length = NS_IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); + } + he.h_name = hed->hostbuf; + he.h_aliases = hed->host_aliases; + hed->host_aliases[0] = NULL; + hed->h_addr_ptrs[0] = (char *)hed->host_addr; + hed->h_addr_ptrs[1] = NULL; + he.h_addr_list = hed->h_addr_ptrs; + RES_SET_H_ERRNO(statp, NETDB_SUCCESS); + return (__copy_hostent(&he, hp, buf, buflen)); +} + +int +gethostbyname_r(const char *name, struct hostent *he, char *buffer, + size_t buflen, struct hostent **result, int *h_errnop) +{ + res_state statp; + + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); + } + if (statp->options & RES_USE_INET6) { + if (fakeaddr(name, AF_INET, he, buffer, buflen, statp) == 0) { + *result = he; + return (0); + } + if (gethostbyname_internal(name, AF_INET6, he, buffer, buflen, + result, h_errnop, statp) == 0) + return (0); + } + return (gethostbyname_internal(name, AF_INET, he, buffer, buflen, + result, h_errnop, statp)); +} + +int +gethostbyname2_r(const char *name, int af, struct hostent *he, char *buffer, + size_t buflen, struct hostent **result, int *h_errnop) +{ + res_state statp; + + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return (-1); + } + return (gethostbyname_internal(name, af, he, buffer, buflen, result, + h_errnop, statp)); +} + +int +gethostbyname_internal(const char *name, int af, struct hostent *hp, char *buf, + size_t buflen, struct hostent **result, int *h_errnop, + res_state statp) +{ + const char *cp; + int rval, ret_errno; + char abuf[MAXDNAME]; + +#ifdef NS_CACHING + static const nss_cache_info cache_info = + NS_COMMON_CACHE_INFO_INITIALIZER( + hosts, (void *)nss_lt_name, + host_id_func, host_marshal_func, host_unmarshal_func); +#endif + static const ns_dtab dtab[] = { + NS_FILES_CB(_ht_gethostbyname, NULL) + { NSSRC_DNS, _dns_gethostbyname, NULL }, + NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */ +#ifdef NS_CACHING + NS_CACHE_CB(&cache_info) +#endif + { 0 } + }; + + switch (af) { + case AF_INET: + case AF_INET6: + break; + default: + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + errno = EAFNOSUPPORT; + return (-1); + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_query() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && + (cp = res_hostalias(statp, name, abuf, sizeof abuf))) + name = cp; + + if (fakeaddr(name, af, hp, buf, buflen, statp) == 0) { + *result = hp; + return (0); + } + + rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS, + "gethostbyname2_r", default_src, name, af, hp, buf, buflen, + &ret_errno, h_errnop); + + return ((rval == NS_SUCCESS) ? 0 : -1); +} + +int +gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, + char *buf, size_t buflen, struct hostent **result, + int *h_errnop) +{ + const u_char *uaddr = (const u_char *)addr; + const struct in6_addr *addr6; + socklen_t size; + int rval, ret_errno; + res_state statp; + +#ifdef NS_CACHING + static const nss_cache_info cache_info = + NS_COMMON_CACHE_INFO_INITIALIZER( + hosts, (void *)nss_lt_id, + host_id_func, host_marshal_func, host_unmarshal_func); +#endif + static const ns_dtab dtab[] = { + NS_FILES_CB(_ht_gethostbyaddr, NULL) + { NSSRC_DNS, _dns_gethostbyaddr, NULL }, + NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */ +#ifdef NS_CACHING + NS_CACHE_CB(&cache_info) +#endif + { 0 } + }; + + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); + } + + if (af == AF_INET6 && len == NS_IN6ADDRSZ) { + addr6 = (const struct in6_addr *)addr; + if (IN6_IS_ADDR_LINKLOCAL(addr6)) { + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + *h_errnop = statp->res_h_errno; + return (-1); + } + if (IN6_IS_ADDR_V4MAPPED(addr6) || + IN6_IS_ADDR_V4COMPAT(addr6)) { + /* Unmap. */ + uaddr += NS_IN6ADDRSZ - NS_INADDRSZ; + af = AF_INET; + len = NS_INADDRSZ; + } + } + switch (af) { + case AF_INET: + size = NS_INADDRSZ; + break; + case AF_INET6: + size = NS_IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); + } + if (size != len) { + errno = EINVAL; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); + } + + rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS, + "gethostbyaddr_r", default_src, uaddr, len, af, hp, buf, buflen, + &ret_errno, h_errnop); + + return ((rval == NS_SUCCESS) ? 0 : -1); +} + +struct hostent * +gethostbyname(const char *name) +{ + struct hostdata *hd; + struct hostent *rval; + int ret_h_errno; + + if ((hd = __hostdata_init()) == NULL) + return (NULL); + if (gethostbyname_r(name, &hd->host, hd->data, sizeof(hd->data), &rval, + &ret_h_errno) != 0) + return (NULL); + return (rval); +} + +struct hostent * +gethostbyname2(const char *name, int af) +{ + struct hostdata *hd; + struct hostent *rval; + int ret_h_errno; + + if ((hd = __hostdata_init()) == NULL) + return (NULL); + if (gethostbyname2_r(name, af, &hd->host, hd->data, sizeof(hd->data), + &rval, &ret_h_errno) != 0) + return (NULL); + return (rval); +} + +struct hostent * +gethostbyaddr(const void *addr, socklen_t len, int af) +{ + struct hostdata *hd; + struct hostent *rval; + int ret_h_errno; + + if ((hd = __hostdata_init()) == NULL) + return (NULL); + if (gethostbyaddr_r(addr, len, af, &hd->host, hd->data, + sizeof(hd->data), &rval, &ret_h_errno) != 0) + return (NULL); + return (rval); +} + void sethostent(int stayopen) { - _sethosthtent(stayopen); + struct hostent_data *hed; + + if ((hed = __hostent_data_init()) == NULL) + return; + _sethosthtent(stayopen, hed); _sethostdnsent(stayopen); } void endhostent(void) { - _endhosthtent(); + struct hostent_data *hed; + + if ((hed = __hostent_data_init()) == NULL) + return; + _endhosthtent(hed); _endhostdnsent(); } diff --git a/lib/libc/net/getnameinfo.3 b/lib/libc/net/getnameinfo.3 index 1d73345bf4..5dc987dea9 100644 --- a/lib/libc/net/getnameinfo.3 +++ b/lib/libc/net/getnameinfo.3 @@ -1,7 +1,5 @@ .\" $KAME: getnameinfo.3,v 1.37 2005/01/05 03:23:05 itojun Exp $ .\" $OpenBSD: getnameinfo.3,v 1.36 2004/12/21 09:48:20 jmc Exp $ -.\" $FreeBSD: src/lib/libc/net/getnameinfo.3,v 1.21 2005/01/23 16:02:48 gnn Exp $ -.\" $DragonFly: src/lib/libc/net/getnameinfo.3,v 1.5 2007/08/18 20:48:47 swildner Exp $ .\" .\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000, 2001 Internet Software Consortium. @@ -18,7 +16,10 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.Dd December 20, 2004 +.\" $FreeBSD: src/lib/libc/net/getnameinfo.3,v 1.25 2007/02/28 21:28:33 bms Exp $ +.\" $DragonFly: src/lib/libc/net/getnameinfo.3,v 1.5 2007/08/18 20:48:47 swildner Exp $ +.\" +.Dd February 28, 2007 .Dt GETNAMEINFO 3 .Os .Sh NAME @@ -31,8 +32,10 @@ .In sys/socket.h .In netdb.h .Ft int -.Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" "char *host" \ - "size_t hostlen" "char *serv" "size_t servlen" "int flags" +.Fo getnameinfo +.Fa "const struct sockaddr *sa" "socklen_t salen" "char *host" +.Fa "size_t hostlen" "char *serv" "size_t servlen" "int flags" +.Fc .Sh DESCRIPTION The .Fn getnameinfo @@ -47,15 +50,29 @@ functions and is the converse of the .Xr getaddrinfo 3 function. .Pp +If a link-layer address is passed to +.Fn getnameinfo , +its ASCII representation will be stored in +.Fa host . +The string pointed to by +.Fa serv +will be set to the empty string if non-NULL; +.Fa flags +will always be ignored. +This is intended as a replacement for the legacy +.Xr link_ntoa 3 +function. +.Pp The .Li sockaddr structure .Fa sa should point to either a -.Li sockaddr_in -or +.Li sockaddr_in , .Li sockaddr_in6 -structure (for IPv4 or IPv6 respectively) that is +or +.Li sockaddr_dl +structure (for IPv4, IPv6 or link-layer respectively) that is .Fa salen bytes long. .Pp @@ -166,6 +183,7 @@ printf("host=%s\en", hbuf); .Xr gethostbyaddr 3 , .Xr getservbyport 3 , .Xr inet_ntop 3 , +.Xr link_ntoa 3 , .Xr resolver 3 , .Xr hosts 5 , .Xr resolv.conf 5 , @@ -261,10 +279,6 @@ if (error == 0) { NULL, 0, NI_NUMERICHOST); } .Ed -.Sh BUGS -The implementation of -.Fn getnameinfo -is not thread-safe. .\".Pp .\".Ox .\"intentionally uses a different diff --git a/lib/libc/net/getnameinfo.c b/lib/libc/net/getnameinfo.c index f4b2c47d3d..69b35c9b73 100644 --- a/lib/libc/net/getnameinfo.c +++ b/lib/libc/net/getnameinfo.c @@ -1,9 +1,10 @@ -/* $FreeBSD: src/lib/libc/net/getnameinfo.c,v 1.4.2.5 2002/07/31 10:11:09 ume Exp $ */ +/* $FreeBSD: src/lib/libc/net/getnameinfo.c,v 1.20 2007/02/28 21:18:38 bms Exp $ */ /* $DragonFly: src/lib/libc/net/getnameinfo.c,v 1.5 2008/10/04 22:09:17 swildner Exp $ */ /* $KAME: getnameinfo.c,v 1.61 2002/06/27 09:25:47 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * Copyright (c) 2000 Ben Harris. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,6 +49,8 @@ #include #include #include +#include +#include #include #include #include @@ -57,10 +60,41 @@ #include #include +static int getnameinfo_inet(const struct sockaddr *, socklen_t, char *, + size_t, char *, size_t, int); +#ifdef INET6 +static int ip6_parsenumeric(const struct sockaddr *, const char *, char *, + size_t, int); +static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int); +#endif +static int getnameinfo_link(const struct sockaddr *, socklen_t, char *, + size_t, char *, size_t, int); +static int hexname(const u_int8_t *, size_t, char *, size_t); + +int +getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags) +{ + + switch (sa->sa_family) { + case AF_INET: +#ifdef INET6 + case AF_INET6: +#endif + return getnameinfo_inet(sa, salen, host, hostlen, serv, + servlen, flags); + case AF_LINK: + return getnameinfo_link(sa, salen, host, hostlen, serv, + servlen, flags); + default: + return EAI_FAMILY; + } +} + static const struct afd { int a_af; - int a_addrlen; - int a_socklen; + size_t a_addrlen; + socklen_t a_socklen; int a_off; } afdl [] = { #ifdef INET6 @@ -78,15 +112,9 @@ struct sockinet { u_short si_port; }; -#ifdef INET6 -static int ip6_parsenumeric (const struct sockaddr *, const char *, char *, - size_t, int); -static int ip6_sa2str (const struct sockaddr_in6 *, char *, size_t, int); -#endif - -int -getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, - size_t hostlen, char *serv, size_t servlen, int flags) +static int +getnameinfo_inet(const struct sockaddr *sa, socklen_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags) { const struct afd *afd; struct servent *sp; @@ -102,9 +130,6 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, if (sa == NULL) return EAI_FAIL; - if (sa->sa_len != salen) - return EAI_FAIL; - family = sa->sa_family; for (i = 0; afdl[i].a_af; i++) if (afdl[i].a_af == family) { @@ -155,7 +180,7 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, flags |= NI_NUMERICHOST; v4a >>= IN_CLASSA_NSHIFT; if (v4a == 0) - flags |= NI_NUMERICHOST; + flags |= NI_NUMERICHOST; break; #ifdef INET6 case AF_INET6: @@ -191,7 +216,7 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, * hostlen == 0 means that the caller does not want the result. */ } else if (flags & NI_NUMERICHOST) { - int numaddrlen; + size_t numaddrlen; /* NUMERICHOST and NAMEREQD conflicts with each other */ if (flags & NI_NAMEREQD) @@ -273,7 +298,7 @@ static int ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host, size_t hostlen, int flags) { - int numaddrlen; + size_t numaddrlen; char numaddr[512]; if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL) @@ -338,9 +363,85 @@ ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags) /* last resort */ n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id); - if (n < 0 || n >= bufsiz) + if (n < 0 || (size_t)n >= bufsiz) return -1; else return n; } #endif /* INET6 */ + +/* + * getnameinfo_link(): + * Format a link-layer address into a printable format, paying attention to + * the interface type. + */ +/* ARGSUSED */ +static int +getnameinfo_link(const struct sockaddr *sa, socklen_t salen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags) +{ + const struct sockaddr_dl *sdl = + (const struct sockaddr_dl *)(const void *)sa; + int n; + + if (serv != NULL && servlen > 0) + *serv = '\0'; + + if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) { + n = snprintf(host, hostlen, "link#%d", sdl->sdl_index); + if (n > hostlen) { + *host = '\0'; + return EAI_MEMORY; + } + return 0; + } + + switch (sdl->sdl_type) { + /* + * The following have zero-length addresses. + * IFT_ATM (net/if_atmsubr.c) + * IFT_FAITH (net/if_faith.c) + * IFT_GIF (net/if_gif.c) + * IFT_LOOP (net/if_loop.c) + * IFT_PPP (net/if_ppp.c, net/if_spppsubr.c) + * IFT_SLIP (net/if_sl.c, net/if_strip.c) + * IFT_STF (net/if_stf.c) + * IFT_L2VLAN (net/if_vlan.c) + * IFT_BRIDGE (net/if_bridge.h> + */ + /* + * The following use IPv4 addresses as link-layer addresses: + * IFT_OTHER (net/if_gre.c) + * IFT_OTHER (netinet/ip_ipip.c) + */ + /* default below is believed correct for all these. */ + case IFT_ARCNET: + case IFT_ETHER: + case IFT_FDDI: + case IFT_HIPPI: + case IFT_ISO88025: + default: + return hexname((u_int8_t *)LLADDR(sdl), (size_t)sdl->sdl_alen, + host, hostlen); + } +} + +static int +hexname(const u_int8_t *cp, size_t len, char *host, size_t hostlen) +{ + int i, n; + char *outp = host; + + *outp = '\0'; + for (i = 0; i < len; i++) { + n = snprintf(outp, hostlen, "%s%02x", + i ? ":" : "", cp[i]); + if (n < 0 || n >= hostlen) { + *host = '\0'; + return EAI_MEMORY; + } + outp += n; + hostlen -= n; + } + return 0; +} diff --git a/lib/libc/net/getnetbydns.c b/lib/libc/net/getnetbydns.c index b238414553..d90f00708a 100644 --- a/lib/libc/net/getnetbydns.c +++ b/lib/libc/net/getnetbydns.c @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -47,7 +47,7 @@ * --Copyright-- * * @(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93 - * $FreeBSD: src/lib/libc/net/getnetbydns.c,v 1.13.2.4 2002/10/11 11:07:13 ume Exp $ + * $FreeBSD: src/lib/libc/net/getnetbydns.c,v 1.34 2007/01/09 00:28:02 imp Exp $ * $DragonFly: src/lib/libc/net/getnetbydns.c,v 1.5 2005/11/13 02:04:47 swildner Exp $ */ /* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro @@ -64,6 +64,7 @@ #include #include +#include #include #include #include @@ -75,13 +76,11 @@ #include #include +#include "netdb_private.h" #include "res_config.h" -extern int h_errno; - #define BYADDR 0 #define BYNAME 1 -#define MAXALIASES 35 #define MAXPACKET (64*1024) @@ -95,20 +94,75 @@ typedef union { char ac; } align; -static struct netent * -getnetanswer(querybuf *answer, int anslen, int net_i) +/* + * Reverse the order of first four dotted entries of in. + * Out must contain space for at least strlen(in) characters. + * The result does not include any leading 0s of in. + */ +static void +ipreverse(char *in, char *out) +{ + char *pos[4]; + int len[4]; + char *p, *start; + int i = 0; + int leading = 1; + + /* Fill-in element positions and lengths: pos[], len[]. */ + start = p = in; + for (;;) { + if (*p == '.' || *p == '\0') { + /* Leading 0? */ + if (leading && p - start == 1 && *start == '0') + len[i] = 0; + else { + len[i] = p - start; + leading = 0; + } + pos[i] = start; + start = p + 1; + i++; + } + if (i == 4) + break; + if (*p == 0) { + for (; i < 4; i++) { + pos[i] = p; + len[i] = 0; + } + break; + } + p++; + } + + /* Copy the entries in reverse order */ + p = out; + leading = 1; + for (i = 3; i >= 0; i--) { + memcpy(p, pos[i], len[i]); + if (len[i]) + leading = 0; + p += len[i]; + /* Need a . separator? */ + if (!leading && i > 0 && len[i - 1]) + *p++ = '.'; + } + *p = '\0'; +} + +static int +getnetanswer(querybuf *answer, int anslen, int net_i, struct netent *ne, + struct netent_data *ned, res_state statp) { HEADER *hp; u_char *cp; int n; u_char *eom; - int type, class, buflen, ancount, qdcount, haveanswer, i, nchar; - char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN]; - char *in, *st, *pauxt, *bp, **ap; - char *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0; -static struct netent net_entry; -static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; + int type, class, ancount, qdcount, haveanswer; + char aux[MAXHOSTNAMELEN]; + char ans[MAXHOSTNAMELEN]; + char *in, *bp, *ep, **ap; /* * find first satisfactory answer @@ -128,24 +182,24 @@ static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; hp = &answer->hdr; ancount = ntohs(hp->ancount); /* #/records in the answer section */ qdcount = ntohs(hp->qdcount); /* #/entries in the question section */ - bp = netbuf; - buflen = sizeof(netbuf); + bp = ned->netbuf; + ep = ned->netbuf + sizeof(ned->netbuf); cp = answer->buf + HFIXEDSZ; if (!qdcount) { if (hp->aa) - h_errno = HOST_NOT_FOUND; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); else - h_errno = TRY_AGAIN; - return (NULL); + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (-1); } while (qdcount-- > 0) cp += __dn_skipname(cp, eom) + QFIXEDSZ; - ap = net_aliases; + ap = ned->net_aliases; *ap = NULL; - net_entry.n_aliases = net_aliases; + ne->n_aliases = ned->net_aliases; haveanswer = 0; while (--ancount >= 0 && cp < eom) { - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !res_dnok(bp)) break; cp += n; @@ -157,18 +211,16 @@ static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; cp += INT32SZ; /* TTL */ GETSHORT(n, cp); if (class == C_IN && type == T_PTR) { - n = dn_expand(answer->buf, eom, cp, bp, buflen); + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); if ((n < 0) || !res_hnok(bp)) { cp += n; - return (NULL); + return (-1); } - cp += n; + cp += n; *ap++ = bp; n = strlen(bp) + 1; bp += n; - buflen -= n; - net_entry.n_addrtype = - (class == C_IN) ? AF_INET : AF_UNSPEC; + ne->n_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; haveanswer++; } } @@ -176,56 +228,80 @@ static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; *ap = NULL; switch (net_i) { case BYADDR: - net_entry.n_name = *net_entry.n_aliases; - net_entry.n_net = 0L; + ne->n_name = *ne->n_aliases; + ne->n_net = 0L; break; case BYNAME: - in = *net_entry.n_aliases; - net_entry.n_name = &ans[0]; - aux2[0] = '\0'; - for (i = 0; i < 4; i++) { - for (st = in, nchar = 0; - *st != '.'; - st++, nchar++) - ; - if (nchar != 1 || *in != '0' || flag) { - flag = 1; - strncpy(paux1, (i==0) ? in : in-1, - (i==0) ? nchar : nchar+1); - paux1[(i==0) ? nchar : nchar+1] = '\0'; - pauxt = paux2; - paux2 = strcat(paux1, paux2); - paux1 = pauxt; - } - in = ++st; - } - net_entry.n_net = inet_network(paux2); + in = *ne->n_aliases; + n = strlen(ans) + 1; + if (ep - bp < n) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + errno = ENOBUFS; + return (-1); + } + strlcpy(bp, ans, ep - bp); + ne->n_name = bp; + if (strlen(in) + 1 > sizeof(aux)) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + errno = ENOBUFS; + return (-1); + } + ipreverse(in, aux); + ne->n_net = inet_network(aux); break; } - net_entry.n_aliases++; - return (&net_entry); + ne->n_aliases++; + return (0); } - h_errno = TRY_AGAIN; - return (NULL); + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (-1); } int _dns_getnetbyaddr(void *rval, void *cb_data, va_list ap) { + uint32_t net; + int net_type; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; + struct netent_data *ned; unsigned int netbr[4]; - int nn, anslen, net_type; + int nn, anslen, error; querybuf *buf; char qbuf[MAXDNAME]; - unsigned long net, net2; - struct netent *net_entry; + uint32_t net2; + res_state statp; - net = va_arg(ap, unsigned long); + net = va_arg(ap, uint32_t); net_type = va_arg(ap, int); + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); - *(struct netent **)rval = NULL; + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } + + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } + + *((struct netent **)rval) = NULL; - if (net_type != AF_INET) - return NS_UNAVAIL; + if (net_type != AF_INET) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } for (nn = 4, net2 = net; net2; net2 >>= 8) netbr[--nn] = net2 & 0xff; @@ -246,94 +322,138 @@ _dns_getnetbyaddr(void *rval, void *cb_data, va_list ap) break; } if ((buf = malloc(sizeof(*buf))) == NULL) { - h_errno = NETDB_INTERNAL; - return NS_NOTFOUND; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } - anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)buf, sizeof(*buf)); + anslen = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf, + sizeof(*buf)); if (anslen < 0) { free(buf); #ifdef DEBUG - if (_res.options & RES_DEBUG) - printf("res_search failed\n"); + if (statp->options & RES_DEBUG) + printf("res_nsearch failed\n"); #endif - return NS_UNAVAIL; + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); } else if (anslen > sizeof(*buf)) { free(buf); #ifdef DEBUG - if (_res.options & RES_DEBUG) - printf("res_search static buffer too small\n"); + if (statp->options & RES_DEBUG) + printf("res_nsearch static buffer too small\n"); #endif - return NS_UNAVAIL; + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); } - net_entry = getnetanswer(buf, anslen, BYADDR); + error = getnetanswer(buf, anslen, BYADDR, &ne, ned, statp); free(buf); - if (net_entry) { - unsigned u_net = net; /* maybe net should be unsigned ? */ - + if (error == 0) { /* Strip trailing zeros */ - while ((u_net & 0xff) == 0 && u_net != 0) - u_net >>= 8; - net_entry->n_net = u_net; - *(struct netent **)rval = net_entry; - return NS_SUCCESS; + while ((net & 0xff) == 0 && net != 0) + net >>= 8; + ne.n_net = net; + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); } - return NS_NOTFOUND; + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } int _dns_getnetbyname(void *rval, void *cb_data, va_list ap) { const char *net; - int anslen; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; + struct netent_data *ned; + int anslen, error; querybuf *buf; char qbuf[MAXDNAME]; - struct netent *net_entry; + res_state statp; net = va_arg(ap, const char *); + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); - *(struct netent**)rval = NULL; - - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - h_errno = NETDB_INTERNAL; - return NS_UNAVAIL; + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); } if ((buf = malloc(sizeof(*buf))) == NULL) { - h_errno = NETDB_INTERNAL; - return NS_NOTFOUND; + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); } + + *((struct netent **)rval) = NULL; + strncpy(qbuf, net, sizeof(qbuf) - 1); qbuf[sizeof(qbuf) - 1] = '\0'; - anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)buf, sizeof(*buf)); + anslen = res_nsearch(statp, qbuf, C_IN, T_PTR, (u_char *)buf, + sizeof(*buf)); if (anslen < 0) { free(buf); #ifdef DEBUG - if (_res.options & RES_DEBUG) - printf("res_search failed\n"); + if (statp->options & RES_DEBUG) + printf("res_nsearch failed\n"); #endif - return NS_UNAVAIL; + return (NS_UNAVAIL); } else if (anslen > sizeof(*buf)) { free(buf); #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (statp->options & RES_DEBUG) printf("res_search static buffer too small\n"); #endif - return NS_UNAVAIL; + return (NS_UNAVAIL); } - *(struct netent**)rval = getnetanswer(buf, anslen, BYNAME); + error = getnetanswer(buf, anslen, BYNAME, &ne, ned, statp); free(buf); - return (*(struct netent**)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; + if (error != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); } void _setnetdnsent(int stayopen) { + res_state statp; + + statp = __res_state(); + if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) + return; if (stayopen) - _res.options |= RES_STAYOPEN | RES_USEVC; + statp->options |= RES_STAYOPEN | RES_USEVC; } void _endnetdnsent(void) { - _res.options &= ~(RES_STAYOPEN | RES_USEVC); - res_close(); + res_state statp; + + statp = __res_state(); + statp->options &= ~(RES_STAYOPEN | RES_USEVC); + res_nclose(statp); } diff --git a/lib/libc/net/getnetbyht.c b/lib/libc/net/getnetbyht.c index 0e5f26e597..541e54c45a 100644 --- a/lib/libc/net/getnetbyht.c +++ b/lib/libc/net/getnetbyht.c @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -27,7 +27,8 @@ * SUCH DAMAGE. * * @(#)getnetent.c 8.1 (Berkeley) 6/4/93 - * $FreeBSD: src/lib/libc/net/getnetbyht.c,v 1.7.2.1 2002/07/07 11:34:42 robert Exp $ + * From: Id: getnetent.c,v 8.4 1997/06/01 20:34:37 vixie Exp + * $FreeBSD: src/lib/libc/net/getnetbyht.c,v 1.19 2007/01/09 00:28:02 imp Exp $ * $DragonFly: src/lib/libc/net/getnetbyht.c,v 1.5 2005/11/13 02:04:47 swildner Exp $ */ @@ -47,129 +48,231 @@ #include #include #include +#include #include #include #include #include - -#define MAXALIASES 35 - -static FILE *netf; -static char line[BUFSIZ+1]; -static struct netent net; -static char *net_aliases[MAXALIASES]; -static int _net_stayopen; +#include "netdb_private.h" void -_setnethtent(int f) +_setnethtent(int f, struct netent_data *ned) { - if (netf == NULL) - netf = fopen(_PATH_NETWORKS, "r" ); + if (ned->netf == NULL) + ned->netf = fopen(_PATH_NETWORKS, "r"); else - rewind(netf); - _net_stayopen |= f; + rewind(ned->netf); + ned->stayopen |= f; } void -_endnethtent(void) +_endnethtent(struct netent_data *ned) { - if (netf) { - fclose(netf); - netf = NULL; + if (ned->netf) { + fclose(ned->netf); + ned->netf = NULL; } - _net_stayopen = 0; + ned->stayopen = 0; } -struct netent * -getnetent(void) +static int +getnetent_p(struct netent *ne, struct netent_data *ned) { - char *p; + char *p, *bp, *ep; char *cp, **q; + int len; + char line[BUFSIZ + 1]; - if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL) - return (NULL); + if (ned->netf == NULL && + (ned->netf = fopen(_PATH_NETWORKS, "r")) == NULL) + return (-1); again: - p = fgets(line, sizeof line, netf); + p = fgets(line, sizeof line, ned->netf); if (p == NULL) - return (NULL); + return (-1); if (*p == '#') goto again; cp = strpbrk(p, "#\n"); - if (cp == NULL) - goto again; - *cp = '\0'; - net.n_name = p; + if (cp != NULL) + *cp = '\0'; + bp = ned->netbuf; + ep = ned->netbuf + sizeof ned->netbuf; + ne->n_name = bp; cp = strpbrk(p, " \t"); if (cp == NULL) goto again; *cp++ = '\0'; + len = strlen(p) + 1; + if (ep - bp < len) { + RES_SET_H_ERRNO(__res_state(), NO_RECOVERY); + return (-1); + } + strlcpy(bp, p, ep - bp); + bp += len; while (*cp == ' ' || *cp == '\t') cp++; p = strpbrk(cp, " \t"); if (p != NULL) *p++ = '\0'; - net.n_net = inet_network(cp); - net.n_addrtype = AF_INET; - q = net.n_aliases = net_aliases; - if (p != NULL) + ne->n_net = inet_network(cp); + ne->n_addrtype = AF_INET; + q = ne->n_aliases = ned->net_aliases; + if (p != NULL) { cp = p; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q >= &ned->net_aliases[_MAXALIASES - 1]) + break; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + len = strlen(cp) + 1; + if (ep - bp < len) + break; + strlcpy(bp, cp, ep - bp); + *q++ = bp; + bp += len; + cp = p; } - if (q < &net_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; } *q = NULL; - return (&net); + return (0); +} + +int +getnetent_r(struct netent *nptr, char *buffer, size_t buflen, + struct netent **result, int *h_errnop) +{ + struct netent_data *ned; + struct netent ne; + res_state statp; + + statp = __res_state(); + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (-1); + } + if (getnetent_p(&ne, ned) != 0) + return (-1); + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) + return (-1); + *result = nptr; + return (0); +} + +struct netent * +getnetent(void) +{ + struct netdata *nd; + struct netent *rval; + int ret_h_errno; + + if ((nd = __netdata_init()) == NULL) + return (NULL); + if (getnetent_r(&nd->net, nd->data, sizeof(nd->data), &rval, + &ret_h_errno) != 0) + return (NULL); + return (rval); } int _ht_getnetbyname(void *rval, void *cb_data, va_list ap) { const char *name; - struct netent *p; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; + struct netent_data *ned; char **cp; + res_state statp; + int error; name = va_arg(ap, const char *); + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); - setnetent(_net_stayopen); - while ( (p = getnetent()) ) { - if (strcasecmp(p->n_name, name) == 0) + statp = __res_state(); + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } + + _setnethtent(ned->stayopen, ned); + while ((error = getnetent_p(&ne, ned)) == 0) { + if (strcasecmp(ne.n_name, name) == 0) break; - for (cp = p->n_aliases; *cp != 0; cp++) + for (cp = ne.n_aliases; *cp != 0; cp++) if (strcasecmp(*cp, name) == 0) goto found; } found: - if (!_net_stayopen) - endnetent(); - *(struct netent **)rval = p; - return (p != NULL) ? NS_SUCCESS : NS_NOTFOUND; + if (!ned->stayopen) + _endnethtent(ned); + if (error != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); } int _ht_getnetbyaddr(void *rval, void *cb_data, va_list ap) { - unsigned long net; + uint32_t net; int type; - struct netent *p; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; + struct netent_data *ned; + res_state statp; + int error; - net = va_arg(ap, unsigned long); + net = va_arg(ap, uint32_t); type = va_arg(ap, int); + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); - setnetent(_net_stayopen); - while ( (p = getnetent()) ) - if (p->n_addrtype == type && p->n_net == net) + statp = __res_state(); + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } + + _setnethtent(ned->stayopen, ned); + while ((error = getnetent_p(&ne, ned)) == 0) + if (ne.n_addrtype == type && ne.n_net == net) break; - if (!_net_stayopen) - endnetent(); - *(struct netent **)rval = p; - return (p != NULL) ? NS_SUCCESS : NS_NOTFOUND; + if (!ned->stayopen) + _endnethtent(ned); + if (error != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); } diff --git a/lib/libc/net/getnetbynis.c b/lib/libc/net/getnetbynis.c index e7009ee015..c6d61397a7 100644 --- a/lib/libc/net/getnetbynis.c +++ b/lib/libc/net/getnetbynis.c @@ -22,7 +22,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/net/getnetbynis.c,v 1.11 1999/08/28 00:00:07 peter Exp $ + * $FreeBSD: src/lib/libc/net/getnetbynis.c,v 1.21 2006/04/15 16:20:27 ume Exp $ * $DragonFly: src/lib/libc/net/getnetbynis.c,v 1.4 2005/11/13 02:04:47 swildner Exp $ */ @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -44,22 +45,18 @@ #include #include #endif - -#define MAXALIASES 35 -#define MAXADDRS 35 +#include "netdb_private.h" #ifdef YP -static char *host_aliases[MAXALIASES]; - -static struct netent * -_getnetbynis(const char *name, char *map, int af) +static int +_getnetbynis(const char *name, char *map, int af, struct netent *ne, + struct netent_data *ned) { + char *p, *bp, *ep; char *cp, **q; - static char *result; - int resultlen; - static struct netent h; - static char *domain = NULL; - static char ypbuf[YPMAXRECORD + 2]; + char *result; + int resultlen, len; + char ypbuf[YPMAXRECORD + 2]; switch(af) { case AF_INET: @@ -67,15 +64,16 @@ _getnetbynis(const char *name, char *map, int af) default: case AF_INET6: errno = EAFNOSUPPORT; - return NULL; + return (-1); } - if (domain == NULL) - if (yp_get_default_domain (&domain)) - return (NULL); + if (ned->yp_domain == (char *)NULL) + if (yp_get_default_domain (&ned->yp_domain)) + return (-1); - if (yp_match(domain, map, name, strlen(name), &result, &resultlen)) - return (NULL); + if (yp_match(ned->yp_domain, map, name, strlen(name), &result, + &resultlen)) + return (-1); bcopy((char *)result, (char *)&ypbuf, resultlen); ypbuf[resultlen] = '\0'; @@ -87,15 +85,24 @@ _getnetbynis(const char *name, char *map, int af) cp = strpbrk(result, " \t"); *cp++ = '\0'; - h.n_name = result; + bp = ned->netbuf; + ep = ned->netbuf + sizeof ned->netbuf; + len = strlen(result) + 1; + if (ep - bp < len) { + RES_SET_H_ERRNO(__res_state(), NO_RECOVERY); + return (-1); + } + strlcpy(bp, result, ep - bp); + ne->n_name = bp; + bp += len; while (*cp == ' ' || *cp == '\t') cp++; - h.n_net = inet_network(cp); - h.n_addrtype = AF_INET; + ne->n_net = inet_network(cp); + ne->n_addrtype = AF_INET; - q = h.n_aliases = host_aliases; + q = ne->n_aliases = ned->net_aliases; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; @@ -104,14 +111,21 @@ _getnetbynis(const char *name, char *map, int af) cp++; continue; } - if (q < &host_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; + if (q > &ned->net_aliases[_MAXALIASES - 1]) + break; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + len = strlen(cp) + 1; + if (ep - bp < len) + break; + strlcpy(bp, cp, ep - bp); + *q++ = bp; + bp += len; + cp = p; } *q = NULL; - return (&h); + return (0); } #endif /* YP */ @@ -120,13 +134,39 @@ _nis_getnetbyname(void *rval, void *cb_data, va_list ap) { #ifdef YP const char *name; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; + struct netent_data *ned; + res_state statp; name = va_arg(ap, const char *); + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + statp = __res_state(); + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } - *(struct netent **)rval = _getnetbynis(name, "networks.byname", AF_INET); - return (*(struct netent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; + if (_getnetbynis(name, "networks.byname", AF_INET, &ne, ned) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); #else - return NS_UNAVAIL; + return (NS_UNAVAIL); #endif } @@ -135,20 +175,40 @@ int _nis_getnetbyaddr(void *rval, void *cb_data, va_list ap) { #ifdef YP + uint32_t addr; + int af; + char *buffer; + size_t buflen; + int *errnop, *h_errnop; + struct netent *nptr, ne; + struct netent_data *ned; char *str, *cp; - unsigned long addr, net2; - int af, nn; + uint32_t net2; + int nn; unsigned int netbr[4]; char buf[MAXDNAME]; + res_state statp; - addr = va_arg(ap, unsigned long); + addr = va_arg(ap, uint32_t); af = va_arg(ap, int); - - *(struct netent **)rval = NULL; + nptr = va_arg(ap, struct netent *); + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + h_errnop = va_arg(ap, int *); + + statp = __res_state(); + if ((ned = __netent_data_init()) == NULL) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; + return (NS_UNAVAIL); + } if (af != AF_INET) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + *h_errnop = statp->res_h_errno; errno = EAFNOSUPPORT; - return NS_UNAVAIL; + return (NS_UNAVAIL); } for (nn = 4, net2 = addr; net2; net2 >>= 8) { @@ -179,9 +239,17 @@ _nis_getnetbyaddr(void *rval, void *cb_data, va_list ap) cp = str + (strlen(str) - 2); } - *(struct netent **)rval = _getnetbynis(str, "networks.byaddr", af); - return (*(struct netent**)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; + if (_getnetbynis(str, "networks.byaddr", af, &ne, ned) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + if (__copy_netent(&ne, nptr, buffer, buflen) != 0) { + *h_errnop = statp->res_h_errno; + return (NS_NOTFOUND); + } + *((struct netent **)rval) = nptr; + return (NS_SUCCESS); #else - return NS_UNAVAIL; + return (NS_UNAVAIL); #endif /* YP */ } diff --git a/lib/libc/net/getnetnamadr.c b/lib/libc/net/getnetnamadr.c index 3803e7fd72..1b03b48cd1 100644 --- a/lib/libc/net/getnetnamadr.c +++ b/lib/libc/net/getnetnamadr.c @@ -22,10 +22,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/lib/libc/net/getnetnamadr.c,v 1.12.2.1 2001/03/05 10:47:08 obrien Exp $ + * $FreeBSD: src/lib/libc/net/getnetnamadr.c,v 1.23 2006/04/28 12:03:35 ume Exp $ * $DragonFly: src/lib/libc/net/getnetnamadr.c,v 1.4 2005/11/13 02:04:47 swildner Exp $ */ +#include "namespace.h" +#include "reentrant.h" #include #include #include @@ -33,9 +35,16 @@ #include #include #include +#include +#include #include #include #include +#include "un-namespace.h" +#include "netdb_private.h" +#ifdef NS_CACHING +#include "nscache.h" +#endif extern int _ht_getnetbyname(void *, void *, va_list); extern int _dns_getnetbyname(void *, void *, va_list); @@ -51,60 +60,391 @@ static const ns_src default_src[] = { { 0 } }; -struct netent * -getnetbyname(const char *name) +NETDB_THREAD_ALLOC(netent_data) +NETDB_THREAD_ALLOC(netdata) + +#ifdef NS_CACHING +static int +net_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) +{ + char *name; + uint32_t net; + int type; + + size_t desired_size, size; + enum nss_lookup_type lookup_type; + int res = NS_UNAVAIL; + + lookup_type = (enum nss_lookup_type)cache_mdata; + switch (lookup_type) { + case nss_lt_name: + name = va_arg(ap, char *); + + size = strlen(name); + desired_size = sizeof(enum nss_lookup_type) + size + 1; + if (desired_size > *buffer_size) { + res = NS_RETURN; + goto fin; + } + + memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); + memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1); + + res = NS_SUCCESS; + break; + case nss_lt_id: + net = va_arg(ap, uint32_t); + type = va_arg(ap, int); + + desired_size = sizeof(enum nss_lookup_type) + + sizeof(uint32_t) + sizeof(int); + if (desired_size > *buffer_size) { + res = NS_RETURN; + goto fin; + } + + memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); + memcpy(buffer + sizeof(enum nss_lookup_type), &net, + sizeof(uint32_t)); + memcpy(buffer + sizeof(enum nss_lookup_type) + sizeof(uint32_t), + &type, sizeof(int)); + + res = NS_SUCCESS; + break; + default: + /* should be unreachable */ + return (NS_UNAVAIL); + } + +fin: + *buffer_size = desired_size; + return (res); +} + + +static int +net_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, + void *cache_mdata) +{ + char *name; + uint32_t net; + int type; + struct netent *ne; + char *orig_buf; + size_t orig_buf_size; + + struct netent new_ne; + size_t desired_size, size, aliases_size; + char *p; + char **alias; + + switch ((enum nss_lookup_type)cache_mdata) { + case nss_lt_name: + name = va_arg(ap, char *); + break; + case nss_lt_id: + net = va_arg(ap, uint32_t); + type = va_arg(ap, int); + break; + case nss_lt_all: + break; + default: + /* should be unreachable */ + return (NS_UNAVAIL); + } + + ne = va_arg(ap, struct netent *); + orig_buf = va_arg(ap, char *); + orig_buf_size = va_arg(ap, size_t); + + desired_size = _ALIGNBYTES + sizeof(struct netent) + sizeof(char *); + if (ne->n_name != NULL) + desired_size += strlen(ne->n_name) + 1; + + if (ne->n_aliases != NULL) { + aliases_size = 0; + for (alias = ne->n_aliases; *alias; ++alias) { + desired_size += strlen(*alias) + 1; + ++aliases_size; + } + + desired_size += _ALIGNBYTES + + (aliases_size + 1) * sizeof(char *); + } + + if (*buffer_size < desired_size) { + /* this assignment is here for future use */ + *buffer_size = desired_size; + return (NS_RETURN); + } + + memcpy(&new_ne, ne, sizeof(struct netent)); + + *buffer_size = desired_size; + memset(buffer, 0, desired_size); + p = buffer + sizeof(struct netent) + sizeof(char *); + memcpy(buffer + sizeof(struct netent), &p, sizeof(char *)); + p = (char *)_ALIGN(p); + + if (new_ne.n_name != NULL) { + size = strlen(new_ne.n_name); + memcpy(p, new_ne.n_name, size); + new_ne.n_name = p; + p += size + 1; + } + + if (new_ne.n_aliases != NULL) { + p = (char *)_ALIGN(p); + memcpy(p, new_ne.n_aliases, sizeof(char *) * aliases_size); + new_ne.n_aliases = (char **)p; + p += sizeof(char *) * (aliases_size + 1); + + for (alias = new_ne.n_aliases; *alias; ++alias) { + size = strlen(*alias); + memcpy(p, *alias, size); + *alias = p; + p += size + 1; + } + } + + memcpy(buffer, &new_ne, sizeof(struct netent)); + return (NS_SUCCESS); +} + +static int +net_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, + void *cache_mdata) +{ + char *name; + uint32_t net; + int type; + struct netent *ne; + char *orig_buf; + size_t orig_buf_size; + int *ret_errno; + + char *p; + char **alias; + + switch ((enum nss_lookup_type)cache_mdata) { + case nss_lt_name: + name = va_arg(ap, char *); + break; + case nss_lt_id: + net = va_arg(ap, uint32_t); + type = va_arg(ap, int); + break; + case nss_lt_all: + break; + default: + /* should be unreachable */ + return (NS_UNAVAIL); + } + + ne = va_arg(ap, struct netent *); + orig_buf = va_arg(ap, char *); + orig_buf_size = va_arg(ap, size_t); + ret_errno = va_arg(ap, int *); + + if (orig_buf_size < + buffer_size - sizeof(struct netent) - sizeof(char *)) { + *ret_errno = ERANGE; + return (NS_RETURN); + } + + memcpy(ne, buffer, sizeof(struct netent)); + memcpy(&p, buffer + sizeof(struct netent), sizeof(char *)); + + orig_buf = (char *)_ALIGN(orig_buf); + memcpy(orig_buf, buffer + sizeof(struct netent) + sizeof(char *) + + _ALIGN(p) - (size_t)p, + buffer_size - sizeof(struct netent) - sizeof(char *) - + _ALIGN(p) + (size_t)p); + p = (char *)_ALIGN(p); + + NS_APPLY_OFFSET(ne->n_name, orig_buf, p, char *); + if (ne->n_aliases != NULL) { + NS_APPLY_OFFSET(ne->n_aliases, orig_buf, p, char **); + + for (alias = ne->n_aliases; *alias; ++alias) + NS_APPLY_OFFSET(*alias, orig_buf, p, char *); + } + + if (retval != NULL) + *((struct netent **)retval) = ne; + + return (NS_SUCCESS); +} +#endif /* NS_CACHING */ + +static void +netent_data_free(void *ptr) { - struct netent *hp = 0; - int rval; + struct netent_data *ned = ptr; + + if (ned == NULL) + return; + ned->stayopen = 0; + _endnethtent(ned); + free(ned); +} + +static void +netdata_free(void *ptr) +{ + free(ptr); +} + +int +__copy_netent(struct netent *ne, struct netent *nptr, char *buf, size_t buflen) +{ + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /* NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; ne->n_aliases[i]; i++, numptr++) { + len += strlen(ne->n_aliases[i]) + 1; + } + len += strlen(ne->n_name) + 1; + len += numptr * sizeof(char*); + + if (len > (int)buflen) { + errno = ERANGE; + return (-1); + } + + /* copy net value and type */ + nptr->n_addrtype = ne->n_addrtype; + nptr->n_net = ne->n_net; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(ne->n_name) + 1; + strcpy(cp, ne->n_name); + nptr->n_name = cp; + cp += n; + /* copy aliases */ + nptr->n_aliases = (char **)ALIGN(buf); + for (i = 0 ; ne->n_aliases[i]; i++) { + n = strlen(ne->n_aliases[i]) + 1; + strcpy(cp, ne->n_aliases[i]); + nptr->n_aliases[i] = cp; + cp += n; + } + nptr->n_aliases[i] = NULL; + + return (0); +} + +int +getnetbyname_r(const char *name, struct netent *ne, char *buffer, + size_t buflen, struct netent **result, int *h_errorp) +{ +#ifdef NS_CACHING + static const nss_cache_info cache_info = + NS_COMMON_CACHE_INFO_INITIALIZER( + networks, (void *)nss_lt_name, + net_id_func, net_marshal_func, net_unmarshal_func); +#endif static const ns_dtab dtab[] = { NS_FILES_CB(_ht_getnetbyname, NULL) { NSSRC_DNS, _dns_getnetbyname, NULL }, NS_NIS_CB(_nis_getnetbyname, NULL) /* force -DHESIOD */ +#ifdef NS_CACHING + NS_CACHE_CB(&cache_info) +#endif { 0 } }; + int rval, ret_errno; - rval = nsdispatch((void *)&hp, dtab, NSDB_NETWORKS, "getnetbyname", - default_src, name); + rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS, + "getnetbyname_r", default_src, name, ne, buffer, buflen, + &ret_errno, h_errorp); - if (rval != NS_SUCCESS) - return NULL; - else - return hp; + return ((rval == NS_SUCCESS) ? 0 : -1); } -struct netent * -getnetbyaddr(u_long addr, int af) +int +getnetbyaddr_r(uint32_t addr, int af, struct netent *ne, char *buffer, + size_t buflen, struct netent **result, int *h_errorp) { - struct netent *hp = 0; - int rval; - +#ifdef NS_CACHING + static const nss_cache_info cache_info = + NS_COMMON_CACHE_INFO_INITIALIZER( + networks, (void *)nss_lt_id, + net_id_func, net_marshal_func, net_unmarshal_func); +#endif static const ns_dtab dtab[] = { NS_FILES_CB(_ht_getnetbyaddr, NULL) { NSSRC_DNS, _dns_getnetbyaddr, NULL }, NS_NIS_CB(_nis_getnetbyaddr, NULL) /* force -DHESIOD */ +#ifdef NS_CACHING + NS_CACHE_CB(&cache_info) +#endif { 0 } }; + int rval, ret_errno; - rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "getnetbyaddr", - default_src, addr, af); + rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS, + "getnetbyaddr_r", default_src, addr, af, ne, buffer, buflen, + &ret_errno, h_errorp); - if (rval != NS_SUCCESS) - return NULL; - else - return hp; + return ((rval == NS_SUCCESS) ? 0 : -1); +} + +struct netent * +getnetbyname(const char *name) +{ + struct netdata *nd; + struct netent *rval; + int ret_h_errno; + + if ((nd = __netdata_init()) == NULL) + return (NULL); + if (getnetbyname_r(name, &nd->net, nd->data, sizeof(nd->data), &rval, + &ret_h_errno) != 0) + return (NULL); + return (rval); +} + +struct netent * +getnetbyaddr(uint32_t addr, int af) +{ + struct netdata *nd; + struct netent *rval; + int ret_h_errno; + + if ((nd = __netdata_init()) == NULL) + return (NULL); + if (getnetbyaddr_r(addr, af, &nd->net, nd->data, sizeof(nd->data), + &rval, &ret_h_errno) != 0) + return (NULL); + return (rval); } void setnetent(int stayopen) { - _setnethtent(stayopen); + struct netent_data *ned; + + if ((ned = __netent_data_init()) == NULL) + return; + _setnethtent(stayopen, ned); _setnetdnsent(stayopen); } void endnetent(void) { - _endnethtent(); + struct netent_data *ned; + + if ((ned = __netent_data_init()) == NULL) + return; + _endnethtent(ned); _endnetdnsent(); } diff --git a/lib/libc/net/herror.c b/lib/libc/net/herror.c deleted file mode 100644 index c11bcd81f3..0000000000 --- a/lib/libc/net/herror.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)herror.c 8.1 (Berkeley) 6/4/93 - * $FreeBSD: src/lib/libc/net/herror.c,v 1.8 1999/08/28 00:00:09 peter Exp $ - * $DragonFly: src/lib/libc/net/herror.c,v 1.6 2005/11/13 02:04:47 swildner Exp $ - */ - -/* - * Portions Copyright (c) 1996 by 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 "namespace.h" -#include -#include -#include -#include -#include -#include "un-namespace.h" - -const char *h_errlist[] = { - "Resolver Error 0 (no error)", - "Unknown host", /* 1 HOST_NOT_FOUND */ - "Host name lookup failure", /* 2 TRY_AGAIN */ - "Unknown server error", /* 3 NO_RECOVERY */ - "No address associated with name", /* 4 NO_ADDRESS */ -}; -int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; - -int h_errno; - -/* - * herror -- - * print the error indicated by the h_errno value. - */ -void -herror(const char *s) -{ - struct iovec iov[4]; - struct iovec *v = iov; - - if (s && *s) { - v->iov_base = (char *)s; - v->iov_len = strlen(s); - v++; - v->iov_base = ": "; - v->iov_len = 2; - v++; - } - v->iov_base = (char *)hstrerror(h_errno); - v->iov_len = strlen(v->iov_base); - v++; - v->iov_base = "\n"; - v->iov_len = 1; - _writev(STDERR_FILENO, iov, (v - iov) + 1); -} - -const char * -hstrerror(int err) -{ - if (err < 0) - return ("Resolver internal error"); - else if (err < h_nerr) - return (h_errlist[err]); - return ("Unknown resolver error"); -} diff --git a/lib/libc/net/inet_addr.c b/lib/libc/net/inet_addr.c deleted file mode 100644 index 14bb654a27..0000000000 --- a/lib/libc/net/inet_addr.c +++ /dev/null @@ -1,191 +0,0 @@ -/* $KAME: inet_addr.c,v 1.5 2001/08/20 02:32:40 itojun Exp $ */ - -/* - * ++Copyright++ 1983, 1990, 1993 - * - - * Copyright (c) 1983, 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * 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, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION 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. - * - - * --Copyright-- - * - * @(#)inet_addr.c 8.1 (Berkeley) 6/17/93 - * $FreeBSD: src/lib/libc/net/inet_addr.c,v 1.12.2.2 2002/04/28 05:40:24 suz Exp $ - * $DragonFly: src/lib/libc/net/inet_addr.c,v 1.5 2005/11/13 02:04:47 swildner Exp $ - */ - -#include - -#include -#include - -#include -#include -#include -#include - -/* - * ASCII internet address interpretation routine. - * The value returned is in network order. - */ -in_addr_t /* XXX should be struct in_addr :( */ -inet_addr(const char *cp) -{ - struct in_addr val; - - if (inet_aton(cp, &val)) - return (val.s_addr); - return (INADDR_NONE); -} - -/* - * Check whether "cp" is a valid ASCII representation - * of an Internet address and convert to a binary address. - * Returns 1 if the address is valid, 0 if not. - * This replaces inet_addr, the return value from which - * cannot distinguish between failure and a local broadcast address. - */ -int -inet_aton(const char *cp, struct in_addr *addr) -{ - u_long parts[4]; - in_addr_t val; - char *c; - char *endptr; - int gotend, n; - - c = (char *)cp; - n = 0; - /* - * Run through the string, grabbing numbers until - * the end of the string, or some error - */ - gotend = 0; - while (!gotend) { - errno = 0; - val = strtoul(c, &endptr, 0); - - if (errno == ERANGE) /* Fail completely if it overflowed. */ - return (0); - - /* - * If the whole string is invalid, endptr will equal - * c.. this way we can make sure someone hasn't - * gone '.12' or something which would get past - * the next check. - */ - if (endptr == c) - return (0); - parts[n] = val; - c = endptr; - - /* Check the next character past the previous number's end */ - switch (*c) { - case '.' : - /* Make sure we only do 3 dots .. */ - if (n == 3) /* Whoops. Quit. */ - return (0); - n++; - c++; - break; - - case '\0': - gotend = 1; - break; - - default: - if (isspace((unsigned char)*c)) { - gotend = 1; - break; - } else - return (0); /* Invalid character, so fail */ - } - - } - - /* - * Concoct the address according to - * the number of parts specified. - */ - - switch (n) { - case 0: /* a -- 32 bits */ - /* - * Nothing is necessary here. Overflow checking was - * already done in strtoul(). - */ - break; - case 1: /* a.b -- 8.24 bits */ - if (val > 0xffffff || parts[0] > 0xff) - return (0); - val |= parts[0] << 24; - break; - - case 2: /* a.b.c -- 8.8.16 bits */ - if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16); - break; - - case 3: /* a.b.c.d -- 8.8.8.8 bits */ - if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff || - parts[2] > 0xff) - return (0); - val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); - break; - } - - if (addr != NULL) - addr->s_addr = htonl(val); - return (1); -} - -/* - * Weak aliases for applications that use certain private entry points, - * and fail to include . - */ -#undef inet_addr -__weak_reference(__inet_addr, inet_addr); -#undef inet_aton -__weak_reference(__inet_aton, inet_aton); diff --git a/lib/libc/net/inet_lnaof.c b/lib/libc/net/inet_lnaof.c deleted file mode 100644 index 615b9a6af9..0000000000 --- a/lib/libc/net/inet_lnaof.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/lib/libc/net/inet_lnaof.c,v 1.2.6.1 2001/04/21 14:53:04 ume Exp $ - * $DragonFly: src/lib/libc/net/inet_lnaof.c,v 1.5 2005/11/13 02:04:47 swildner Exp $ - * - * @(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93 - */ - -#include -#include -#include - -/* - * Return the local network address portion of an - * internet address; handles class a/b/c network - * number formats. - */ -in_addr_t -inet_lnaof(struct in_addr in) -{ - in_addr_t i = ntohl(in.s_addr); - - if (IN_CLASSA(i)) - return ((i)&IN_CLASSA_HOST); - else if (IN_CLASSB(i)) - return ((i)&IN_CLASSB_HOST); - else - return ((i)&IN_CLASSC_HOST); -} - -/* - * Weak aliases for applications that use certain private entry points, - * and fail to include . - */ -#undef inet_lnaof -__weak_reference(__inet_lnaof, inet_lnaof); diff --git a/lib/libc/net/inet_makeaddr.c b/lib/libc/net/inet_makeaddr.c deleted file mode 100644 index ca41fda6b7..0000000000 --- a/lib/libc/net/inet_makeaddr.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/lib/libc/net/inet_makeaddr.c,v 1.2.6.1 2001/04/21 14:53:04 ume Exp $ - * $DragonFly: src/lib/libc/net/inet_makeaddr.c,v 1.4 2005/11/13 02:04:47 swildner Exp $ - * - * @(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93 - */ - -#include -#include -#include - -/* - * Formulate an Internet address from network + host. Used in - * building addresses stored in the ifnet structure. - */ -struct in_addr -inet_makeaddr(in_addr_t net, in_addr_t host) -{ - in_addr_t addr; - - if (net < 128) - addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); - else if (net < 65536) - addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); - else if (net < 16777216L) - addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); - else - addr = net | host; - addr = htonl(addr); - return (*(struct in_addr *)&addr); -} - -/* - * Weak aliases for applications that use certain private entry points, - * and fail to include . - */ -#undef inet_makeaddr -__weak_reference(__inet_makeaddr, inet_makeaddr); diff --git a/lib/libc/net/inet_net_ntop.c b/lib/libc/net/inet_net_ntop.c deleted file mode 100644 index 2798df4257..0000000000 --- a/lib/libc/net/inet_net_ntop.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 1996 by 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. - * - * $FreeBSD: src/lib/libc/net/inet_net_ntop.c,v 1.5 1999/08/28 00:00:10 peter Exp $ - * $DragonFly: src/lib/libc/net/inet_net_ntop.c,v 1.4 2005/11/13 02:04:47 swildner Exp $ - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef SPRINTF_CHAR -# define SPRINTF(x) strlen(sprintf/**/x) -#else -# define SPRINTF(x) ((size_t)sprintf x) -#endif - -static char * inet_net_ntop_ipv4 (const u_char *src, int bits, - char *dst, size_t size); - -/* - * char * - * inet_net_ntop(af, src, bits, dst, size) - * convert network number from network to presentation format. - * generates CIDR style result always. - * return: - * pointer to dst, or NULL if an error occurred (check errno). - * author: - * Paul Vixie (ISC), July 1996 - */ -char * -inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size) -{ - switch (af) { - case AF_INET: - return (inet_net_ntop_ipv4(src, bits, dst, size)); - default: - errno = EAFNOSUPPORT; - return (NULL); - } -} - -/* - * static char * - * inet_net_ntop_ipv4(src, bits, dst, size) - * convert IPv4 network number from network to presentation format. - * generates CIDR style result always. - * return: - * pointer to dst, or NULL if an error occurred (check errno). - * note: - * network byte order assumed. this means 192.5.5.240/28 has - * 0x11110000 in its fourth octet. - * author: - * Paul Vixie (ISC), July 1996 - */ -static char * -inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) -{ - char *odst = dst; - char *t; - u_int m; - int b; - - if (bits < 0 || bits > 32) { - errno = EINVAL; - return (NULL); - } - if (bits == 0) { - if (size < sizeof "0") - goto emsgsize; - *dst++ = '0'; - *dst = '\0'; - } - - /* Format whole octets. */ - for (b = bits / 8; b > 0; b--) { - if (size < sizeof "255.") - goto emsgsize; - t = dst; - dst += SPRINTF((dst, "%u", *src++)); - if (b > 1) { - *dst++ = '.'; - *dst = '\0'; - } - size -= (size_t)(dst - t); - } - - /* Format partial octet. */ - b = bits % 8; - if (b > 0) { - if (size < sizeof ".255") - goto emsgsize; - t = dst; - if (dst != odst) - *dst++ = '.'; - m = ((1 << b) - 1) << (8 - b); - dst += SPRINTF((dst, "%u", *src & m)); - size -= (size_t)(dst - t); - } - - /* Format CIDR /width. */ - if (size < sizeof "/32") - goto emsgsize; - dst += SPRINTF((dst, "/%u", bits)); - return (odst); - - emsgsize: - errno = EMSGSIZE; - return (NULL); -} - -/* - * Weak aliases for applications that use certain private entry points, - * and fail to include . - */ -#undef inet_net_ntop -__weak_reference(__inet_net_ntop, inet_net_ntop); diff --git a/lib/libc/net/inet_net_pton.c b/lib/libc/net/inet_net_pton.c deleted file mode 100644 index ea1d050ffe..0000000000 --- a/lib/libc/net/inet_net_pton.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 1996 by 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. - * - * $From Id: inet_net_pton.c,v 1.8 1996/11/21 10:28:12 vixie Exp $ - * $FreeBSD: src/lib/libc/net/inet_net_pton.c,v 1.6 1999/08/28 00:00:10 peter Exp $ - * $DragonFly: src/lib/libc/net/inet_net_pton.c,v 1.4 2005/11/13 02:04:47 swildner Exp $ - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef SPRINTF_CHAR -# define SPRINTF(x) strlen(sprintf/**/x) -#else -# define SPRINTF(x) ((size_t)sprintf x) -#endif - -static int inet_net_pton_ipv4 (const char *src, u_char *dst, - size_t size); - -/* - * static int - * inet_net_pton(af, src, dst, size) - * convert network number from presentation to network format. - * accepts hex octets, hex strings, decimal octets, and /CIDR. - * "size" is in bytes and describes "dst". - * return: - * number of bits, either imputed classfully or specified with /CIDR, - * or -1 if some failure occurred (check errno). ENOENT means it was - * not a valid network specification. - * author: - * Paul Vixie (ISC), June 1996 - */ -int -inet_net_pton(int af, const char *src, void *dst, size_t size) -{ - switch (af) { - case AF_INET: - return (inet_net_pton_ipv4(src, dst, size)); - default: - errno = EAFNOSUPPORT; - return (-1); - } -} - -/* - * static int - * inet_net_pton_ipv4(src, dst, size) - * convert IPv4 network number from presentation to network format. - * accepts hex octets, hex strings, decimal octets, and /CIDR. - * "size" is in bytes and describes "dst". - * return: - * number of bits, either imputed classfully or specified with /CIDR, - * or -1 if some failure occurred (check errno). ENOENT means it was - * not an IPv4 network specification. - * note: - * network byte order assumed. this means 192.5.5.240/28 has - * 0x11110000 in its fourth octet. - * author: - * Paul Vixie (ISC), June 1996 - */ -static int -inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) -{ - static const char - xdigits[] = "0123456789abcdef", - digits[] = "0123456789"; - int n, ch, tmp, dirty, bits; - const u_char *odst = dst; - - ch = *src++; - if (ch == '0' && (src[0] == 'x' || src[0] == 'X') - && isascii(src[1]) && isxdigit(src[1])) { - /* Hexadecimal: Eat nybble string. */ - if (size <= 0) - goto emsgsize; - *dst = 0, dirty = 0; - src++; /* skip x or X. */ - while ((ch = *src++) != '\0' && - isascii(ch) && isxdigit(ch)) { - if (isupper(ch)) - ch = tolower(ch); - n = strchr(xdigits, ch) - xdigits; - assert(n >= 0 && n <= 15); - *dst |= n; - if (!dirty++) - *dst <<= 4; - else if (size-- > 0) - *++dst = 0, dirty = 0; - else - goto emsgsize; - } - if (dirty) - size--; - } else if (isascii(ch) && isdigit(ch)) { - /* Decimal: eat dotted digit string. */ - for (;;) { - tmp = 0; - do { - n = strchr(digits, ch) - digits; - assert(n >= 0 && n <= 9); - tmp *= 10; - tmp += n; - if (tmp > 255) - goto enoent; - } while ((ch = *src++) != '\0' && - isascii(ch) && isdigit(ch)); - if (size-- <= 0) - goto emsgsize; - *dst++ = (u_char) tmp; - if (ch == '\0' || ch == '/') - break; - if (ch != '.') - goto enoent; - ch = *src++; - if (!isascii(ch) || !isdigit(ch)) - goto enoent; - } - } else - goto enoent; - - bits = -1; - if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) { - /* CIDR width specifier. Nothing can follow it. */ - ch = *src++; /* Skip over the /. */ - bits = 0; - do { - n = strchr(digits, ch) - digits; - assert(n >= 0 && n <= 9); - bits *= 10; - bits += n; - } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); - if (ch != '\0') - goto enoent; - if (bits > 32) - goto emsgsize; - } - - /* Firey death and destruction unless we prefetched EOS. */ - if (ch != '\0') - goto enoent; - - /* If nothing was written to the destination, we found no address. */ - if (dst == odst) - goto enoent; - /* If no CIDR spec was given, infer width from net class. */ - if (bits == -1) { - if (*odst >= 240) /* Class E */ - bits = 32; - else if (*odst >= 224) /* Class D */ - bits = 4; - else if (*odst >= 192) /* Class C */ - bits = 24; - else if (*odst >= 128) /* Class B */ - bits = 16; - else /* Class A */ - bits = 8; - /* If imputed mask is narrower than specified octets, widen. */ - if (bits >= 8 && bits < ((dst - odst) * 8)) - bits = (dst - odst) * 8; - } - /* Extend network to cover the actual mask. */ - while (bits > ((dst - odst) * 8)) { - if (size-- <= 0) - goto emsgsize; - *dst++ = '\0'; - } - return (bits); - - enoent: - errno = ENOENT; - return (-1); - - emsgsize: - errno = EMSGSIZE; - return (-1); -} - -/* - * Weak aliases for applications that use certain private entry points, - * and fail to include . - */ -#undef inet_net_pton -__weak_reference(__inet_net_pton, inet_net_pton); diff --git a/lib/libc/net/inet_neta.c b/lib/libc/net/inet_neta.c deleted file mode 100644 index fd92565aac..0000000000 --- a/lib/libc/net/inet_neta.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 1996 by 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. - * - * $FreeBSD: src/lib/libc/net/inet_neta.c,v 1.6.2.1 2001/04/21 14:53:04 ume Exp $ - * $DragonFly: src/lib/libc/net/inet_neta.c,v 1.3 2005/11/13 02:04:47 swildner Exp $ - */ - -#include -#include -#include -#include - -#include -#include -#include - -#ifdef SPRINTF_CHAR -# define SPRINTF(x) strlen(sprintf/**/x) -#else -# define SPRINTF(x) ((size_t)sprintf x) -#endif - -/* - * char * - * inet_neta(src, dst, size) - * format a in_addr_t network number into presentation format. - * return: - * pointer to dst, or NULL if an error occurred (check errno). - * note: - * format of ``src'' is as for inet_network(). - * author: - * Paul Vixie (ISC), July 1996 - */ -char * -inet_neta(in_addr_t src, char *dst, size_t size) -{ - char *odst = dst; - char *tp; - - while (src & 0xffffffff) { - u_char b = (src & 0xff000000) >> 24; - - src <<= 8; - if (b) { - if (size < sizeof "255.") - goto emsgsize; - tp = dst; - dst += SPRINTF((dst, "%u", b)); - if (src != 0L) { - *dst++ = '.'; - *dst = '\0'; - } - size -= (size_t)(dst - tp); - } - } - if (dst == odst) { - if (size < sizeof "0.0.0.0") - goto emsgsize; - strcpy(dst, "0.0.0.0"); - } - return (odst); - - emsgsize: - errno = EMSGSIZE; - return (NULL); -} - -/* - * Weak aliases for applications that use certain private entry points, - * and fail to include . - */ -#undef inet_neta -__weak_reference(__inet_neta, inet_neta); diff --git a/lib/libc/net/inet_netof.c b/lib/libc/net/inet_netof.c deleted file mode 100644 index c0c979c111..0000000000 --- a/lib/libc/net/inet_netof.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/lib/libc/net/inet_netof.c,v 1.2.6.1 2001/04/21 14:53:04 ume Exp $ - * $DragonFly: src/lib/libc/net/inet_netof.c,v 1.5 2005/11/13 02:04:47 swildner Exp $ - * - * @(#)inet_netof.c 8.1 (Berkeley) 6/4/93 - */ - -#include -#include -#include - -/* - * Return the network number from an internet - * address; handles class a/b/c network #'s. - */ -in_addr_t -inet_netof(struct in_addr in) -{ - in_addr_t i = ntohl(in.s_addr); - - if (IN_CLASSA(i)) - return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); - else if (IN_CLASSB(i)) - return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); - else - return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); -} - -/* - * Weak aliases for applications that use certain private entry points, - * and fail to include . - */ -#undef inet_netof -__weak_reference(__inet_netof, inet_netof); diff --git a/lib/libc/net/inet_network.c b/lib/libc/net/inet_network.c deleted file mode 100644 index e8dd5f5d37..0000000000 --- a/lib/libc/net/inet_network.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/lib/libc/net/inet_network.c,v 1.6.2.1 2001/04/21 14:53:04 ume Exp $ - * $DragonFly: src/lib/libc/net/inet_network.c,v 1.6 2005/11/13 02:04:47 swildner Exp $ - * - * @(#)inet_network.c 8.1 (Berkeley) 6/4/93 - */ - -#include -#include -#include -#include - -/* - * Internet network address interpretation routine. - * The library routines call this routine to interpret - * network numbers. - */ -in_addr_t -inet_network(const char *cp) -{ - in_addr_t val, base, i, n; - char c; - in_addr_t parts[4], *pp = parts; - -again: - val = 0; base = 10; - if (*cp == '0') - base = 8, cp++; - if (*cp == 'x' || *cp == 'X') - base = 16, cp++; - while ((c = *cp) != 0) { - if (isdigit((unsigned char)c)) { - val = (val * base) + (c - '0'); - cp++; - continue; - } - if (base == 16 && isxdigit((unsigned char)c)) { - val = (val << 4) + (c + 10 - (islower((unsigned char)c) ? 'a' : 'A')); - cp++; - continue; - } - break; - } - if (*cp == '.') { - if (pp >= parts + 3) - return (INADDR_NONE); - *pp++ = val, cp++; - goto again; - } - if (*cp && !isspace((unsigned char)*cp)) - return (INADDR_NONE); - *pp++ = val; - n = pp - parts; - for (val = 0, i = 0; i < n; i++) { - val <<= 8; - val |= parts[i] & 0xff; - } - return (val); -} - -/* - * Weak aliases for applications that use certain private entry points, - * and fail to include . - */ -#undef inet_network -__weak_reference(__inet_network, inet_network); diff --git a/lib/libc/net/inet_ntop.c b/lib/libc/net/inet_ntop.c deleted file mode 100644 index 6901867a25..0000000000 --- a/lib/libc/net/inet_ntop.c +++ /dev/null @@ -1,184 +0,0 @@ -/* Copyright (c) 1996 by 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. - * - * $FreeBSD: src/lib/libc/net/inet_ntop.c,v 1.6.2.2 2002/12/16 15:19:35 robert Exp $ - * $DragonFly: src/lib/libc/net/inet_ntop.c,v 1.4 2005/11/13 02:04:47 swildner Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * WARNING: Don't even consider trying to compile this on a system where - * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. - */ - -static const char *inet_ntop4 (const u_char *src, char *dst, size_t size); -static const char *inet_ntop6 (const u_char *src, char *dst, size_t size); - -/* char * - * inet_ntop(af, src, dst, size) - * convert a network format address to presentation format. - * return: - * pointer to presentation format address (`dst'), or NULL (see errno). - * author: - * Paul Vixie, 1996. - */ -const char * -inet_ntop(int af, const void *src, char *dst, size_t size) -{ - switch (af) { - case AF_INET: - return (inet_ntop4(src, dst, size)); - case AF_INET6: - return (inet_ntop6(src, dst, size)); - default: - errno = EAFNOSUPPORT; - return (NULL); - } - /* NOTREACHED */ -} - -/* const char * - * inet_ntop4(src, dst, size) - * format an IPv4 address, more or less like inet_ntoa() - * return: - * `dst' (as a const) - * notes: - * (1) uses no statics - * (2) takes a u_char* not an in_addr as input - * author: - * Paul Vixie, 1996. - */ -static const char * -inet_ntop4(const u_char *src, char *dst, size_t size) -{ - static const char fmt[] = "%u.%u.%u.%u"; - - if ((size_t)snprintf(dst, size, fmt, src[0], src[1], src[2], src[3]) - >= size) { - errno = ENOSPC; - return (NULL); - } - return (dst); -} - -/* const char * - * inet_ntop6(src, dst, size) - * convert IPv6 binary address into presentation (printable) format - * author: - * Paul Vixie, 1996. - */ -static const char * -inet_ntop6(const u_char *src, char *dst, size_t size) -{ - /* - * Note that int32_t and int16_t need only be "at least" large enough - * to contain a value of the specified size. On some systems, like - * Crays, there is no such thing as an integer variable with 16 bits. - * Keep this in mind if you think this function should have been coded - * to use pointer overlays. All the world's not a VAX. - */ - char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; - struct { int base, len; } best, cur; - u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; - int i; - - /* - * Preprocess: - * Copy the input (bytewise) array into a wordwise array. - * Find the longest run of 0x00's in src[] for :: shorthanding. - */ - memset(words, '\0', sizeof words); - for (i = 0; i < NS_IN6ADDRSZ; i++) - words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); - best.base = -1; - cur.base = -1; - for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { - if (words[i] == 0) { - if (cur.base == -1) - cur.base = i, cur.len = 1; - else - cur.len++; - } else { - if (cur.base != -1) { - if (best.base == -1 || cur.len > best.len) - best = cur; - cur.base = -1; - } - } - } - if (cur.base != -1) { - if (best.base == -1 || cur.len > best.len) - best = cur; - } - if (best.base != -1 && best.len < 2) - best.base = -1; - - /* - * Format the result. - */ - tp = tmp; - for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { - /* Are we inside the best run of 0x00's? */ - if (best.base != -1 && i >= best.base && - i < (best.base + best.len)) { - if (i == best.base) - *tp++ = ':'; - continue; - } - /* Are we following an initial run of 0x00s or any real hex? */ - if (i != 0) - *tp++ = ':'; - /* Is this address an encapsulated IPv4? */ - if (i == 6 && best.base == 0 && - (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { - if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) - return (NULL); - tp += strlen(tp); - break; - } - tp += sprintf(tp, "%x", words[i]); - } - /* Was it a trailing run of 0x00's? */ - if (best.base != -1 && (best.base + best.len) == - (NS_IN6ADDRSZ / NS_INT16SZ)) - *tp++ = ':'; - *tp++ = '\0'; - - /* - * Check for overflow, copy, and we're done. - */ - if ((size_t)(tp - tmp) > size) { - errno = ENOSPC; - return (NULL); - } - strcpy(dst, tmp); - return (dst); -} - -/* - * Weak aliases for applications that use certain private entry points, - * and fail to include . - */ -#undef inet_ntop -__weak_reference(__inet_ntop, inet_ntop); diff --git a/lib/libc/net/inet_pton.c b/lib/libc/net/inet_pton.c deleted file mode 100644 index 190246d7f4..0000000000 --- a/lib/libc/net/inet_pton.c +++ /dev/null @@ -1,220 +0,0 @@ -/* $KAME: inet_pton.c,v 1.5 2001/08/20 02:32:40 itojun Exp $ */ - -/* Copyright (c) 1996 by 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. - * - * $FreeBSD: src/lib/libc/net/inet_pton.c,v 1.6.2.1 2002/04/28 05:40:24 suz Exp $ - * $DragonFly: src/lib/libc/net/inet_pton.c,v 1.5 2007/04/19 12:52:29 corecode Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * WARNING: Don't even consider trying to compile this on a system where - * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. - */ - -static int inet_pton4 (const char *src, u_char *dst); -static int inet_pton6 (const char *src, u_char *dst); - -/* int - * inet_pton(af, src, dst) - * convert from presentation format (which usually means ASCII printable) - * to network format (which is usually some kind of binary format). - * return: - * 1 if the address was valid for the specified address family - * 0 if the address wasn't valid (`dst' is untouched in this case) - * -1 if some other error occurred (`dst' is untouched in this case, too) - * author: - * Paul Vixie, 1996. - */ -int -inet_pton(int af, const char *src, void *dst) -{ - switch (af) { - case AF_INET: - return (inet_pton4(src, dst)); - case AF_INET6: - return (inet_pton6(src, dst)); - default: - errno = EAFNOSUPPORT; - return (-1); - } - /* NOTREACHED */ -} - -/* int - * inet_pton4(src, dst) - * like inet_aton() but without all the hexadecimal and shorthand. - * return: - * 1 if `src' is a valid dotted quad, else 0. - * notice: - * does not touch `dst' unless it's returning 1. - * author: - * Paul Vixie, 1996. - */ -static int -inet_pton4(const char *src, u_char *dst) -{ - static const char digits[] = "0123456789"; - int saw_digit, octets, ch; - u_char tmp[NS_INADDRSZ], *tp; - - saw_digit = 0; - octets = 0; - *(tp = tmp) = 0; - while ((ch = *src++) != '\0') { - const char *pch; - - if ((pch = strchr(digits, ch)) != NULL) { - u_int new = *tp * 10 + (pch - digits); - - if (saw_digit && *tp == 0) - return (0); - if (new > 255) - return (0); - *tp = new; - if (! saw_digit) { - if (++octets > 4) - return (0); - saw_digit = 1; - } - } else if (ch == '.' && saw_digit) { - if (octets == 4) - return (0); - *++tp = 0; - saw_digit = 0; - } else - return (0); - } - if (octets < 4) - return (0); - - memcpy(dst, tmp, NS_INADDRSZ); - return (1); -} - -/* int - * inet_pton6(src, dst) - * convert presentation level address to network order binary form. - * return: - * 1 if `src' is a valid [RFC1884 2.2] address, else 0. - * notice: - * (1) does not touch `dst' unless it's returning 1. - * (2) :: in a full address is silently ignored. - * credit: - * inspired by Mark Andrews. - * author: - * Paul Vixie, 1996. - */ -static int -inet_pton6(const char *src, u_char *dst) -{ - static const char xdigits_l[] = "0123456789abcdef", - xdigits_u[] = "0123456789ABCDEF"; - u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; - const char *xdigits, *curtok; - int ch, saw_xdigit; - u_int val; - - memset((tp = tmp), '\0', NS_IN6ADDRSZ); - endp = tp + NS_IN6ADDRSZ; - colonp = NULL; - /* Leading :: requires some special handling. */ - if (*src == ':') - if (*++src != ':') - return (0); - curtok = src; - saw_xdigit = 0; - val = 0; - while ((ch = *src++) != '\0') { - const char *pch; - - if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) - pch = strchr((xdigits = xdigits_u), ch); - if (pch != NULL) { - val <<= 4; - val |= (pch - xdigits); - if (val > 0xffff) - return (0); - saw_xdigit = 1; - continue; - } - if (ch == ':') { - curtok = src; - if (!saw_xdigit) { - if (colonp) - return (0); - colonp = tp; - continue; - } else if (*src == '\0') - return (0); - if (tp + NS_INT16SZ > endp) - return (0); - *tp++ = (u_char) (val >> 8) & 0xff; - *tp++ = (u_char) val & 0xff; - saw_xdigit = 0; - val = 0; - continue; - } - if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && - inet_pton4(curtok, tp) > 0) { - tp += NS_INADDRSZ; - saw_xdigit = 0; - break; /* '\0' was seen by inet_pton4(). */ - } - return (0); - } - if (saw_xdigit) { - if (tp + NS_INT16SZ > endp) - return (0); - *tp++ = (u_char) (val >> 8) & 0xff; - *tp++ = (u_char) val & 0xff; - } - if (colonp != NULL) { - /* - * Since some memmove()'s erroneously fail to handle - * overlapping regions, we'll do the shift by hand. - */ - const int n = tp - colonp; - int i; - - if (tp == endp) - return (0); - for (i = 1; i <= n; i++) { - endp[- i] = colonp[n - i]; - colonp[n - i] = 0; - } - tp = endp; - } - if (tp != endp) - return (0); - memcpy(dst, tmp, NS_IN6ADDRSZ); - return (1); -} - -/* - * Weak aliases for applications that use certain private entry points, - * and fail to include . - */ -#undef inet_pton -__weak_reference(__inet_pton, inet_pton); diff --git a/lib/libc/net/name6.c b/lib/libc/net/name6.c index 4f80727e7d..6173a3dbd5 100644 --- a/lib/libc/net/name6.c +++ b/lib/libc/net/name6.c @@ -1,4 +1,3 @@ -/* $FreeBSD: src/lib/libc/net/name6.c,v 1.6.2.9 2002/11/02 18:54:57 ume Exp $ */ /* $KAME: name6.c,v 1.25 2000/06/26 16:44:40 itojun Exp $ */ /* @@ -43,7 +42,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -78,24 +81,27 @@ * SOFTWARE. * - * --Copyright-- + * + * $FreeBSD: src/lib/libc/net/name6.c,v 1.62 2007/07/31 16:09:41 bushman Exp $ */ /* * Atsushi Onoe */ -/* - * TODO for thread safe - * use mutex for _hostconf, _hostconf_init. - * rewrite resolvers to be thread safe - */ - #include "namespace.h" #include #include #include #include #include +#ifdef INET6 +#include +#include +#include +#include +#include /* XXX */ +#endif #include #include @@ -110,13 +116,8 @@ #include #include #include "un-namespace.h" -#ifdef NS_CACHING -#include "nscache.h" -#endif - -#ifndef _PATH_HOSTS -#define _PATH_HOSTS "/etc/hosts" -#endif +#include "netdb_private.h" +#include "res_private.h" #ifndef MAXALIASES #define MAXALIASES 10 @@ -143,7 +144,7 @@ do { \ } while (0) #define MAPADDRENABLED(flags) \ (((flags) & AI_V4MAPPED) || \ - (((flags) & AI_V4MAPPED_CFG) && _mapped_addr_enabled())) + (((flags) & AI_V4MAPPED_CFG))) union inx_addr { struct in_addr in_addr; @@ -160,353 +161,83 @@ union inx_addr { #define map_inaddr map_addr_un.mau_inaddr }; -static struct hostent *_hpcopy(struct hostent *hp, int *errp); -static struct hostent *_hpaddr(int af, const char *name, void *addr, int *errp); -static struct hostent *_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp); +struct policyqueue { + TAILQ_ENTRY(policyqueue) pc_entry; #ifdef INET6 -static struct hostent *_hpmapv6(struct hostent *hp, int *errp); -#endif -static struct hostent *_hpsort(struct hostent *hp); -static struct hostent *_ghbyname(const char *name, int af, int flags, int *errp); -static char *_hgetword(char **pp); -static int _mapped_addr_enabled(void); - -static FILE *_files_open(int *errp); -static int _files_ghbyname(void *, void *, va_list); -static int _files_ghbyaddr(void *, void *, va_list); -#ifdef YP -static int _nis_ghbyname(void *, void *, va_list); -static int _nis_ghbyaddr(void *, void *, va_list); -#endif -static int _dns_ghbyname(void *, void *, va_list); -static int _dns_ghbyaddr(void *, void *, va_list); -#ifdef ICMPNL -static int _icmp_ghbyaddr(void *, void *, va_list); -#endif /* ICMPNL */ -#ifdef NS_CACHING -static int ipnode_id_func(char *, size_t *, va_list, void *); -static int ipnode_marshal_func(char *, size_t *, void *, va_list, void *); -static int ipnode_unmarshal_func(char *, size_t, void *, va_list, void *); -#endif - -/* Make getipnodeby*() thread-safe in libc for use with kernel threads. */ -#include "libc_private.h" -#include "spinlock.h" -/* - * XXX: Our res_*() is not thread-safe. So, we share lock between - * getaddrinfo() and getipnodeby*(). Still, we cannot use - * getaddrinfo() and getipnodeby*() in conjunction with other - * functions which call res_*(). - */ -extern spinlock_t __getaddrinfo_thread_lock; -#define THREAD_LOCK() \ - if (__isthreaded) _SPINLOCK(&__getaddrinfo_thread_lock); -#define THREAD_UNLOCK() \ - if (__isthreaded) _SPINUNLOCK(&__getaddrinfo_thread_lock); - -/* Host lookup order if nsswitch.conf is broken or nonexistant */ -static const ns_src default_src[] = { - { NSSRC_FILES, NS_SUCCESS }, - { NSSRC_DNS, NS_SUCCESS }, -#ifdef ICMPNL -#define NSSRC_ICMP "icmp" - { NSSRC_ICMP, NS_SUCCESS }, + struct in6_addrpolicy pc_policy; #endif - { 0 } +}; +TAILQ_HEAD(policyhead, policyqueue); + +#define AIO_SRCFLAG_DEPRECATED 0x1 + +struct hp_order { + union { + struct sockaddr_storage aiou_ss; + struct sockaddr aiou_sa; + } aio_src_un; +#define aio_srcsa aio_src_un.aiou_sa + u_int32_t aio_srcflag; + int aio_srcscope; + int aio_dstscope; + struct policyqueue *aio_srcpolicy; + struct policyqueue *aio_dstpolicy; + union { + struct sockaddr_storage aiou_ss; + struct sockaddr aiou_sa; + } aio_un; +#define aio_sa aio_un.aiou_sa + int aio_matchlen; + char *aio_h_addr; }; -/* - * Check if kernel supports mapped address. - * implementation dependent - */ -#ifdef __KAME__ -#include -#endif /* __KAME__ */ - -static int -_mapped_addr_enabled(void) -{ - /* implementation dependent check */ -#if defined(__KAME__) && defined(IPV6CTL_MAPPED_ADDR) - int mib[4]; - size_t len; - int val; - - mib[0] = CTL_NET; - mib[1] = PF_INET6; - mib[2] = IPPROTO_IPV6; - mib[3] = IPV6CTL_MAPPED_ADDR; - len = sizeof(val); - if (sysctl(mib, 4, &val, &len, 0, 0) == 0 && val != 0) - return 1; -#endif /* __KAME__ && IPV6CTL_MAPPED_ADDR */ - return 0; -} - -#ifdef NS_CACHING -static int -ipnode_id_func(char *buffer, size_t *buffer_size, va_list ap, - void *cache_mdata) -{ - res_state statp; - u_long res_options; - - const int op_id = 2; - char *name; - int af; - size_t len; - void *src; - - char *p; - size_t desired_size, size; - enum nss_lookup_type lookup_type; - int res = NS_UNAVAIL; - - statp = __res_state(); - res_options = statp->options & (RES_RECURSE | RES_DEFNAMES | - RES_DNSRCH | RES_NOALIASES | RES_USE_INET6); - - lookup_type = (enum nss_lookup_type)cache_mdata; - switch (lookup_type) { - case nss_lt_name: - name = va_arg(ap, char *); - af = va_arg(ap, int); - - size = strlen(name); - desired_size = sizeof(res_options) + sizeof(int) + - sizeof(enum nss_lookup_type) + sizeof(int) + size + 1; - - if (desired_size > *buffer_size) { - res = NS_RETURN; - goto fin; - } - - p = buffer; - memcpy(p, &res_options, sizeof(res_options)); - p += sizeof(res_options); - - memcpy(p, &op_id, sizeof(int)); - p += sizeof(int); - - memcpy(p, &lookup_type, sizeof(enum nss_lookup_type)); - p += sizeof(enum nss_lookup_type); - - memcpy(p, &af, sizeof(int)); - p += sizeof(int); - - memcpy(p, name, size + 1); - - res = NS_SUCCESS; - break; - case nss_lt_id: - src = va_arg(ap, void *); - len = va_arg(ap, size_t); - af = va_arg(ap, int); - - desired_size = sizeof(res_options) + sizeof(int) + - sizeof(enum nss_lookup_type) + sizeof(int) + - sizeof(size_t) + len; - - if (desired_size > *buffer_size) { - res = NS_RETURN; - goto fin; - } - - p = buffer; - memcpy(p, &res_options, sizeof(res_options)); - p += sizeof(res_options); - - memcpy(p, &op_id, sizeof(int)); - p += sizeof(int); - - memcpy(p, &lookup_type, sizeof(enum nss_lookup_type)); - p += sizeof(enum nss_lookup_type); - - memcpy(p, &af, sizeof(int)); - p += sizeof(int); - - memcpy(p, &len, sizeof(size_t)); - p += sizeof(size_t); - - memcpy(p, src, len); - - res = NS_SUCCESS; - break; - default: - /* should be unreachable */ - return (NS_UNAVAIL); - } - -fin: - *buffer_size = desired_size; - return (res); -} - -static int -ipnode_marshal_func(char *buffer, size_t *buffer_size, void *retval, - va_list ap, void *cache_mdata) -{ - struct hostent *ht; - - struct hostent new_ht; - size_t desired_size, aliases_size, addr_size, size; - char *p, **iter; - - ht = *((struct hostent **)retval); - - desired_size = _ALIGNBYTES + sizeof(struct hostent) + sizeof(char *); - if (ht->h_name != NULL) - desired_size += strlen(ht->h_name) + 1; - - if (ht->h_aliases != NULL) { - aliases_size = 0; - for (iter = ht->h_aliases; *iter; ++iter) { - desired_size += strlen(*iter) + 1; - ++aliases_size; - } - - desired_size += _ALIGNBYTES + - (aliases_size + 1) * sizeof(char *); - } - - if (ht->h_addr_list != NULL) { - addr_size = 0; - for (iter = ht->h_addr_list; *iter; ++iter) - ++addr_size; - - desired_size += addr_size * _ALIGN(ht->h_length); - desired_size += _ALIGNBYTES + (addr_size + 1) * sizeof(char *); - } - - if (desired_size > *buffer_size) { - /* this assignment is here for future use */ - *buffer_size = desired_size; - return (NS_RETURN); - } - - memcpy(&new_ht, ht, sizeof(struct hostent)); - memset(buffer, 0, desired_size); - - *buffer_size = desired_size; - p = buffer + sizeof(struct hostent) + sizeof(char *); - memcpy(buffer + sizeof(struct hostent), &p, sizeof(char *)); - p = (char *)_ALIGN(p); - - if (new_ht.h_name != NULL) { - size = strlen(new_ht.h_name); - memcpy(p, new_ht.h_name, size); - new_ht.h_name = p; - p += size + 1; - } - - if (new_ht.h_aliases != NULL) { - p = (char *)_ALIGN(p); - memcpy(p, new_ht.h_aliases, sizeof(char *) * aliases_size); - new_ht.h_aliases = (char **)p; - p += sizeof(char *) * (aliases_size + 1); - - for (iter = new_ht.h_aliases; *iter; ++iter) { - size = strlen(*iter); - memcpy(p, *iter, size); - *iter = p; - p += size + 1; - } - } - - if (new_ht.h_addr_list != NULL) { - p = (char *)_ALIGN(p); - memcpy(p, new_ht.h_addr_list, sizeof(char *) * addr_size); - new_ht.h_addr_list = (char **)p; - p += sizeof(char *) * (addr_size + 1); - - size = _ALIGN(new_ht.h_length); - for (iter = new_ht.h_addr_list; *iter; ++iter) { - memcpy(p, *iter, size); - *iter = p; - p += size + 1; - } - } - memcpy(buffer, &new_ht, sizeof(struct hostent)); - return (NS_SUCCESS); -} - -static int -ipnode_unmarshal_func(char *buffer, size_t buffer_size, void *retval, - va_list ap, void *cache_mdata) -{ - struct hostent new_ht; - struct hostent *ht; - - char *p; - char **iter; - char *orig_buf; - int err; - - ht = &new_ht; - - memcpy(ht, buffer, sizeof(struct hostent)); - memcpy(&p, buffer + sizeof(struct hostent), sizeof(char *)); - - orig_buf = buffer + sizeof(struct hostent) + sizeof(char *) + - _ALIGN(p) - (size_t)p; - p = (char *)_ALIGN(p); - - - NS_APPLY_OFFSET(ht->h_name, orig_buf, p, char *); - if (ht->h_aliases != NULL) { - NS_APPLY_OFFSET(ht->h_aliases, orig_buf, p, char **); - - for (iter = ht->h_aliases; *iter; ++iter) - NS_APPLY_OFFSET(*iter, orig_buf, p, char *); - } - - if (ht->h_addr_list != NULL) { - NS_APPLY_OFFSET(ht->h_addr_list, orig_buf, p, char **); - - for (iter = ht->h_addr_list; *iter; ++iter) - NS_APPLY_OFFSET(*iter, orig_buf, p, char *); - } - - ht = _hpcopy(ht, &err); - if (ht == NULL) - return (NS_UNAVAIL); - - *((struct hostent **)retval) = ht; - return (NS_SUCCESS); -} +static struct hostent *_hpcopy(struct hostent *, int *); +static struct hostent *_hpaddr(int, const char *, void *, int *); +#ifdef INET6 +static struct hostent *_hpmerge(struct hostent *, struct hostent *, int *); +static struct hostent *_hpmapv6(struct hostent *, int *); #endif +static struct hostent *_hpsort(struct hostent *, res_state); + +static struct hostent *_hpreorder(struct hostent *); +static int get_addrselectpolicy(struct policyhead *); +static void free_addrselectpolicy(struct policyhead *); +static struct policyqueue *match_addrselectpolicy(struct sockaddr *, + struct policyhead *); +static void set_source(struct hp_order *, struct policyhead *); +static int matchlen(struct sockaddr *, struct sockaddr *); +static int comp_dst(const void *, const void *); +static int gai_addr2scopetype(struct sockaddr *); /* * Functions defined in RFC2553 * getipnodebyname, getipnodebyaddr, freehostent */ -static struct hostent * -_ghbyname(const char *name, int af, int flags, int *errp) +struct hostent * +getipnodebyname(const char *name, int af, int flags, int *errp) { struct hostent *hp; - int i, rval; - -#ifdef NS_CACHING - static const nss_cache_info cache_info = - NS_COMMON_CACHE_INFO_INITIALIZER( - hosts, (void *)nss_lt_name, - ipnode_id_func, ipnode_marshal_func, ipnode_unmarshal_func); -#endif + union inx_addr addrbuf; + res_state statp; + u_long options; - static const ns_dtab dtab[] = { - NS_FILES_CB(_files_ghbyname, NULL) - { NSSRC_DNS, _dns_ghbyname, NULL }, - NS_NIS_CB(_nis_ghbyname, NULL) -#ifdef NS_CACHING - NS_CACHE_CB(&cache_info) + switch (af) { + case AF_INET: +#ifdef INET6 + case AF_INET6: #endif - { 0 } - }; + break; + default: + *errp = NO_RECOVERY; + return NULL; + } if (flags & AI_ADDRCONFIG) { int s; + if ((s = _socket(af, SOCK_DGRAM, 0)) < 0) + return NULL; /* * TODO: * Note that implementation dependent test for address @@ -514,47 +245,7 @@ _ghbyname(const char *name, int af, int flags, int *errp) * (or apropriate interval), * because addresses will be dynamically assigned or deleted. */ - if (af == AF_UNSPEC) { - if ((s = _socket(AF_INET6, SOCK_DGRAM, 0)) < 0) - af = AF_INET; - else { - _close(s); - if ((s = _socket(AF_INET, SOCK_DGRAM, 0)) < 0) - af = AF_INET6; - else - _close(s); - } - - } - if (af != AF_UNSPEC) { - if ((s = _socket(af, SOCK_DGRAM, 0)) < 0) - return NULL; - _close(s); - } - } - - rval = nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyname", default_src, - name, af, errp); - return (rval == NS_SUCCESS) ? hp : NULL; -} - -/* getipnodebyname() internal routine for multiple query(PF_UNSPEC) support. */ -static struct hostent * -_getipnodebyname_multi(const char *name, int af, int flags, int *errp) -{ - struct hostent *hp; - union inx_addr addrbuf; - - /* XXX: PF_UNSPEC is only supposed to be passed from getaddrinfo() */ - if (af != AF_INET -#ifdef INET6 - && af != AF_INET6 -#endif - && af != PF_UNSPEC - ) - { - *errp = NO_RECOVERY; - return NULL; + _close(s); } #ifdef INET6 @@ -579,75 +270,60 @@ _getipnodebyname_multi(const char *name, int af, int flags, int *errp) return _hpaddr(af, name, &addrbuf, errp); } - *errp = HOST_NOT_FOUND; - hp = _ghbyname(name, af, flags, errp); + + statp = __res_state(); + if ((statp->options & RES_INIT) == 0) { + if (res_ninit(statp) < 0) { + *errp = NETDB_INTERNAL; + return NULL; + } + } + + options = statp->options; + statp->options &= ~RES_USE_INET6; + + hp = gethostbyname2(name, af); + hp = _hpcopy(hp, errp); #ifdef INET6 - if (af == AF_INET6 - && ((flags & AI_ALL) || hp == NULL) - && (MAPADDRENABLED(flags))) { - struct hostent *hp2 = _ghbyname(name, AF_INET, flags, errp); + if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) && + MAPADDRENABLED(flags)) { + struct hostent *hp2 = gethostbyname2(name, AF_INET); if (hp == NULL) - hp = _hpmapv6(hp2, errp); + if (hp2 == NULL) + *errp = statp->res_h_errno; + else + hp = _hpmapv6(hp2, errp); else { - if (hp2 && strcmp(hp->h_name, hp2->h_name) != 0) { - freehostent(hp2); - hp2 = NULL; + if (hp2 && strcmp(hp->h_name, hp2->h_name) == 0) { + struct hostent *hpb = hp; + hp = _hpmerge(hpb, hp2, errp); + freehostent(hpb); } - hp = _hpmerge(hp, hp2, errp); } } #endif - return _hpsort(hp); -} -struct hostent * -getipnodebyname(const char *name, int af, int flags, int *errp) -{ - if (af != AF_INET -#ifdef INET6 - && af != AF_INET6 -#endif - ) - { - *errp = NO_RECOVERY; - return NULL; - } - return(_getipnodebyname_multi(name, af ,flags, errp)); + if (hp == NULL) + *errp = statp->res_h_errno; + + statp->options = options; + return _hpreorder(_hpsort(hp, statp)); } struct hostent * getipnodebyaddr(const void *src, size_t len, int af, int *errp) { struct hostent *hp; - int i, rval; + res_state statp; + u_long options; + #ifdef INET6 struct in6_addr addrbuf; #else struct in_addr addrbuf; #endif -#ifdef NS_CACHING - static const nss_cache_info cache_info = - NS_COMMON_CACHE_INFO_INITIALIZER( - hosts, (void *)nss_lt_id, - ipnode_id_func, ipnode_marshal_func, ipnode_unmarshal_func); -#endif - static const ns_dtab dtab[] = { - NS_FILES_CB(_files_ghbyaddr, NULL) - { NSSRC_DNS, _dns_ghbyaddr, NULL }, - NS_NIS_CB(_nis_ghbyaddr, NULL) -#ifdef ICMPNL - { NSSRC_ICMP, _icmp_ghbyaddr, NULL }, -#endif -#ifdef NS_CACHING - NS_CACHE_CB(&cache_info) -#endif - { 0 } - }; - - *errp = HOST_NOT_FOUND; - switch (af) { case AF_INET: if (len != sizeof(struct in_addr)) { @@ -658,7 +334,7 @@ getipnodebyaddr(const void *src, size_t len, int af, int *errp) memcpy(&addrbuf, src, len); src = &addrbuf; } - if (((const struct in_addr *)src)->s_addr == 0) + if (((struct in_addr *)src)->s_addr == 0) return NULL; break; #ifdef INET6 @@ -671,11 +347,11 @@ getipnodebyaddr(const void *src, size_t len, int af, int *errp) memcpy(&addrbuf, src, len); src = &addrbuf; } - if (IN6_IS_ADDR_UNSPECIFIED((const struct in6_addr *)src)) + if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src)) return NULL; - if (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src) - || IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) { - src = (const char *)src + + if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src) + || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) { + src = (char *)src + (sizeof(struct in6_addr) - sizeof(struct in_addr)); af = AF_INET; len = sizeof(struct in_addr); @@ -687,46 +363,31 @@ getipnodebyaddr(const void *src, size_t len, int af, int *errp) return NULL; } - rval = nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyaddr", default_src, - src, len, af, errp); - return (rval == NS_SUCCESS) ? hp : NULL; -} + statp = __res_state(); + if ((statp->options & RES_INIT) == 0) { + if (res_ninit(statp) < 0) { + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + return NULL; + } + } -void -freehostent(struct hostent *ptr) -{ - free(ptr); -} + options = statp->options; + statp->options &= ~RES_USE_INET6; -#if 0 + hp = gethostbyaddr(src, len, af); + if (hp == NULL) + *errp = statp->res_h_errno; -/* XXX: should be deprecated */ -struct hostent * -getnodebyname(const char *name, int af, int flags) -{ - return getipnodebyname(name, af, flags, &h_errno); + statp->options = options; + return (_hpcopy(hp, errp)); } -#ifdef __warn_references -__warn_references(getnodebyname, - "warning: getnodebyname() deprecated, " - "should use getaddrinfo() or getipnodebyname()"); -#endif - -struct hostent * -getnodebyaddr(const void *src, size_t len, int af) +void +freehostent(struct hostent *ptr) { - return getipnodebyaddr(src, len, af, &h_errno); + free(ptr); } -#ifdef __warn_references -__warn_references(getnodebyaddr, - "warning: getnodebyaddr() deprecated, " - "should use getnameinfo() or getipnodebyaddr()"); -#endif - -#endif - /* * Private utility functions */ @@ -820,16 +481,17 @@ _hpaddr(int af, const char *name, void *addr, int *errp) char *addrs[2]; hp = &hpbuf; - hp->h_name = name; + hp->h_name = (char *)name; hp->h_aliases = NULL; hp->h_addrtype = af; hp->h_length = ADDRLEN(af); hp->h_addr_list = addrs; - addrs[0] = addr; + addrs[0] = (char *)addr; addrs[1] = NULL; - return _hpcopy(hp, errp); + return (_hpcopy(hp, errp)); } +#ifdef INET6 /* * _hpmerge: merge 2 hostent structure, arguments will be freed */ @@ -844,9 +506,9 @@ _hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp) union inx_addr addrbuf[MAXADDRS]; if (hp1 == NULL) - return hp2; + return _hpcopy(hp2, errp); if (hp2 == NULL) - return hp1; + return _hpcopy(hp1, errp); #define HP(i) (i == 1 ? hp1 : hp2) hp = &hpbuf; @@ -866,17 +528,14 @@ _hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp) } } aliases[nalias] = NULL; -#ifdef INET6 if (hp1->h_length != hp2->h_length) { hp->h_addrtype = AF_INET6; hp->h_length = sizeof(struct in6_addr); } else { -#endif hp->h_addrtype = hp1->h_addrtype; hp->h_length = hp1->h_length; -#ifdef INET6 } -#endif + hp->h_addr_list = addrs; naddr = 0; for (i = 1; i <= 2; i++) { @@ -895,11 +554,9 @@ _hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp) } } addrs[naddr] = NULL; - hp = _hpcopy(hp, errp); - freehostent(hp1); - freehostent(hp2); - return hp; + return (_hpcopy(hp, errp)); } +#endif /* * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses @@ -908,24 +565,17 @@ _hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp) static struct hostent * _hpmapv6(struct hostent *hp, int *errp) { - struct hostent *hp6; + struct hostent hp6; if (hp == NULL) return NULL; if (hp->h_addrtype == AF_INET6) - return hp; + return _hpcopy(hp, errp); - /* make dummy hostent to convert IPv6 address */ - if ((hp6 = (struct hostent *)malloc(sizeof(struct hostent))) == NULL) { - *errp = TRY_AGAIN; - return NULL; - } - hp6->h_name = NULL; - hp6->h_aliases = NULL; - hp6->h_addrtype = AF_INET6; - hp6->h_length = sizeof(struct in6_addr); - hp6->h_addr_list = NULL; - return _hpmerge(hp6, hp, errp); + memset(&hp6, 0, sizeof(struct hostent)); + hp6.h_addrtype = AF_INET6; + hp6.h_length = sizeof(struct in6_addr); + return _hpmerge(&hp6, hp, errp); } #endif @@ -933,26 +583,27 @@ _hpmapv6(struct hostent *hp, int *errp) * _hpsort: sort address by sortlist */ static struct hostent * -_hpsort(struct hostent *hp) +_hpsort(struct hostent *hp, res_state statp) { int i, j, n; u_char *ap, *sp, *mp, **pp; char t; char order[MAXADDRS]; - int nsort = _res.nsort; + int nsort = statp->nsort; if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0) return hp; for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) { for (j = 0; j < nsort; j++) { #ifdef INET6 - if (_res_ext.sort_list[j].af != hp->h_addrtype) + if (statp->_u._ext.ext->sort_list[j].af != + hp->h_addrtype) continue; - sp = (u_char *)&_res_ext.sort_list[j].addr; - mp = (u_char *)&_res_ext.sort_list[j].mask; + sp = (u_char *)&statp->_u._ext.ext->sort_list[j].addr; + mp = (u_char *)&statp->_u._ext.ext->sort_list[j].mask; #else - sp = (u_char *)&_res.sort_list[j].addr; - mp = (u_char *)&_res.sort_list[j].mask; + sp = (u_char *)&statp->sort_list[j].addr; + mp = (u_char *)&statp->sort_list[j].mask; #endif for (n = 0; n < hp->h_length; n++) { if ((ap[n] & mp[n]) != sp[n]) @@ -980,1103 +631,482 @@ _hpsort(struct hostent *hp) return hp; } -static char * -_hgetword(char **pp) -{ - char c, *p, *ret; - const char *sp; - static const char sep[] = "# \t\n"; - - ret = NULL; - for (p = *pp; (c = *p) != '\0'; p++) { - for (sp = sep; *sp != '\0'; sp++) { - if (c == *sp) - break; - } - if (c == '#') - p[1] = '\0'; /* ignore rest of line */ - if (ret == NULL) { - if (*sp == '\0') - ret = p; - } else { - if (*sp != '\0') { - *p++ = '\0'; - break; - } - } - } - *pp = p; - if (ret == NULL || *ret == '\0') - return NULL; - return ret; -} - /* - * FILES (/etc/hosts) + * _hpreorder: sort address by default address selection */ - -static FILE * -_files_open(int *errp) +static struct hostent * +_hpreorder(struct hostent *hp) { - FILE *fp; - fp = fopen(_PATH_HOSTS, "r"); - if (fp == NULL) - *errp = NO_RECOVERY; - return fp; -} + struct hp_order *aio; + int i, n; + char *ap; + struct sockaddr *sa; + struct policyhead policyhead; -static int -_files_ghbyname(void *rval, void *cb_data, va_list ap) -{ - const char *name; - int af; - int *errp; - int match, nalias; - char *p, *line, *addrstr, *cname; - FILE *fp; - struct hostent *rethp, *hp, hpbuf; - char *aliases[MAXALIASES + 1], *addrs[2]; - union inx_addr addrbuf; - char buf[BUFSIZ]; - int af0 = af; + if (hp == NULL) + return hp; + + switch (hp->h_addrtype) { + case AF_INET: +#ifdef INET6 + case AF_INET6: +#endif + break; + default: + free_addrselectpolicy(&policyhead); + return hp; + } - name = va_arg(ap, const char *); - af = va_arg(ap, int); - errp = va_arg(ap, int *); + /* count the number of addrinfo elements for sorting. */ + for (n = 0; hp->h_addr_list[n] != NULL; n++) + ; - *(struct hostent **)rval = NULL; + /* + * If the number is small enough, we can skip the reordering process. + */ + if (n <= 1) + return hp; - if ((fp = _files_open(errp)) == NULL) - return NS_UNAVAIL; - rethp = hp = NULL; + /* allocate a temporary array for sort and initialization of it. */ + if ((aio = malloc(sizeof(*aio) * n)) == NULL) + return hp; /* give up reordering */ + memset(aio, 0, sizeof(*aio) * n); - while (fgets(buf, sizeof(buf), fp)) { - line = buf; - if ((addrstr = _hgetword(&line)) == NULL - || (cname = _hgetword(&line)) == NULL) - continue; - match = (strcasecmp(cname, name) == 0); - nalias = 0; - while ((p = _hgetword(&line)) != NULL) { - if (!match) - match = (strcasecmp(p, name) == 0); - if (nalias < MAXALIASES) - aliases[nalias++] = p; - } - if (!match) - continue; - switch (af0) { + /* retrieve address selection policy from the kernel */ + TAILQ_INIT(&policyhead); + if (!get_addrselectpolicy(&policyhead)) { + /* no policy is installed into kernel, we don't sort. */ + free(aio); + return hp; + } + + for (i = 0; i < n; i++) { + ap = hp->h_addr_list[i]; + aio[i].aio_h_addr = ap; + sa = &aio[i].aio_sa; + switch (hp->h_addrtype) { case AF_INET: - if (inet_aton(addrstr, (struct in_addr *)&addrbuf) - != 1) { - *errp = NO_DATA; /* name found */ - continue; - } - af = af0; + sa->sa_family = AF_INET; + sa->sa_len = sizeof(struct sockaddr_in); + memcpy(&((struct sockaddr_in *)sa)->sin_addr, ap, + sizeof(struct in_addr)); break; #ifdef INET6 case AF_INET6: - if (inet_pton(af, addrstr, &addrbuf) != 1) { - *errp = NO_DATA; /* name found */ - continue; + if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { + sa->sa_family = AF_INET; + sa->sa_len = sizeof(struct sockaddr_in); + memcpy(&((struct sockaddr_in *)sa)->sin_addr, + &ap[12], sizeof(struct in_addr)); + } else { + sa->sa_family = AF_INET6; + sa->sa_len = sizeof(struct sockaddr_in6); + memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr, + ap, sizeof(struct in6_addr)); } - af = af0; break; #endif - case AF_UNSPEC: - if (inet_aton(addrstr, (struct in_addr *)&addrbuf) - == 1) { - af = AF_INET; - break; - } -#ifdef INET6 - if (inet_pton(AF_INET6, addrstr, &addrbuf) == 1) { - af = AF_INET6; - break; - } -#endif - *errp = NO_DATA; /* name found */ - continue; - /* NOTREACHED */ } - hp = &hpbuf; - hp->h_name = cname; - hp->h_aliases = aliases; - aliases[nalias] = NULL; - hp->h_addrtype = af; - hp->h_length = ADDRLEN(af); - hp->h_addr_list = addrs; - addrs[0] = (char *)&addrbuf; - addrs[1] = NULL; - hp = _hpcopy(hp, errp); - rethp = _hpmerge(rethp, hp, errp); + aio[i].aio_dstscope = gai_addr2scopetype(sa); + aio[i].aio_dstpolicy = match_addrselectpolicy(sa, &policyhead); + set_source(&aio[i], &policyhead); } - fclose(fp); - *(struct hostent **)rval = rethp; - return (rethp != NULL) ? NS_SUCCESS : NS_NOTFOUND; -} -static int -_files_ghbyaddr(void *rval, void *cb_data, va_list ap) -{ - const void *addr; - int addrlen; - int af; - int *errp; - int nalias; - char *p, *line; - FILE *fp; - struct hostent *hp, hpbuf; - char *aliases[MAXALIASES + 1], *addrs[2]; - union inx_addr addrbuf; - char buf[BUFSIZ]; - - addr = va_arg(ap, const void *); - addrlen = va_arg(ap, int); - af = va_arg(ap, int); - errp = va_arg(ap, int *); - - *(struct hostent**)rval = NULL; - - if ((fp = _files_open(errp)) == NULL) - return NS_UNAVAIL; - hp = NULL; - while (fgets(buf, sizeof(buf), fp)) { - line = buf; - if ((p = _hgetword(&line)) == NULL - || (af == AF_INET - ? inet_aton(p, (struct in_addr *)&addrbuf) - : inet_pton(af, p, &addrbuf)) != 1 - || memcmp(addr, &addrbuf, addrlen) != 0 - || (p = _hgetword(&line)) == NULL) - continue; - hp = &hpbuf; - hp->h_name = p; - hp->h_aliases = aliases; - nalias = 0; - while ((p = _hgetword(&line)) != NULL) { - if (nalias < MAXALIASES) - aliases[nalias++] = p; - } - aliases[nalias] = NULL; - hp->h_addrtype = af; - hp->h_length = addrlen; - hp->h_addr_list = addrs; - addrs[0] = (char *)&addrbuf; - addrs[1] = NULL; - hp = _hpcopy(hp, errp); - break; - } - fclose(fp); - *(struct hostent **)rval = hp; - return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND; -} + /* perform sorting. */ + qsort(aio, n, sizeof(*aio), comp_dst); -#ifdef YP -/* - * NIS - * - * XXX actually a hack, these are INET4 specific. - */ -static int -_nis_ghbyname(void *rval, void *cb_data, va_list ap) -{ - const char *name; - int af; - int *errp; - struct hostent *hp = NULL; - - name = va_arg(ap, const char *); - af = va_arg(ap, int); - errp = va_arg(ap, int *); - - if (af == AF_UNSPEC) - af = AF_INET; - if (af == AF_INET) { - hp = _gethostbynisname(name, af); - if (hp != NULL) - hp = _hpcopy(hp, errp); - } + /* reorder the h_addr_list. */ + for (i = 0; i < n; i++) + hp->h_addr_list[i] = aio[i].aio_h_addr; - *(struct hostent **)rval = hp; - return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND; + /* cleanup and return */ + free(aio); + free_addrselectpolicy(&policyhead); + return hp; } static int -_nis_ghbyaddr(void *rval, void *cb_data, va_list ap) -{ - const void *addr; - int addrlen; - int af; - int *errp; - struct hostent *hp = NULL; - - addr = va_arg(ap, const void *); - addrlen = va_arg(ap, int); - af = va_arg(ap, int); - - if (af == AF_INET) { - hp = _gethostbynisaddr(addr, addrlen, af); - if (hp != NULL) - hp = _hpcopy(hp, errp); - } - *(struct hostent **)rval = hp; - return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND; -} -#endif - -struct __res_type_list { - SLIST_ENTRY(__res_type_list) rtl_entry; - int rtl_type; -}; - -#define MAXPACKET (64*1024) - -typedef union { - HEADER hdr; - u_char buf[MAXPACKET]; -} querybuf; - -static struct hostent *getanswer (const querybuf *, int, const char *, - int, struct hostent *, int *); - -/* - * we don't need to take care about sorting, nor IPv4 mapped address here. - */ -static struct hostent * -getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, - struct hostent *template, int *errp) +get_addrselectpolicy(struct policyhead *head) { - const HEADER *hp; - const u_char *cp; - int n; - const u_char *eom, *erdata; - char *bp, **ap, **hap, *obp; - int type, class, buflen, ancount, qdcount; - int haveanswer, had_error; - char tbuf[MAXDNAME]; - const char *tname; - int (*name_ok) (const char *); - static char *h_addr_ptrs[MAXADDRS + 1]; - static char *host_aliases[MAXALIASES]; - static char hostbuf[8*1024]; - -#define BOUNDED_INCR(x) \ - do { \ - cp += x; \ - if (cp > eom) { \ - *errp = NO_RECOVERY; \ - return (NULL); \ - } \ - } while (0) - -#define BOUNDS_CHECK(ptr, count) \ - do { \ - if ((ptr) + (count) > eom) { \ - *errp = NO_RECOVERY; \ - return (NULL); \ - } \ - } while (0) - -/* XXX do {} while (0) cannot be put here */ -#define DNS_ASSERT(x) \ - { \ - if (!(x)) { \ - cp += n; \ - continue; \ - } \ +#ifdef INET6 + int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY }; + size_t l; + char *buf; + struct in6_addrpolicy *pol, *ep; + + if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0) + return (0); + if ((buf = malloc(l)) == NULL) + return (0); + if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) { + free(buf); + return (0); } -/* XXX do {} while (0) cannot be put here */ -#define DNS_FATAL(x) \ - { \ - if (!(x)) { \ - had_error++; \ - continue; \ - } \ - } + ep = (struct in6_addrpolicy *)(buf + l); + for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) { + struct policyqueue *new; - tname = qname; - template->h_name = NULL; - eom = answer->buf + anslen; - switch (qtype) { - case T_A: - case T_AAAA: - name_ok = res_hnok; - break; - case T_PTR: - name_ok = res_dnok; - break; - default: - return (NULL); /* XXX should be abort(); */ - } - /* - * find first satisfactory answer - */ - hp = &answer->hdr; - ancount = ntohs(hp->ancount); - qdcount = ntohs(hp->qdcount); - bp = hostbuf; - buflen = sizeof hostbuf; - cp = answer->buf; - BOUNDED_INCR(HFIXEDSZ); - if (qdcount != 1) { - *errp = NO_RECOVERY; - return (NULL); - } - n = dn_expand(answer->buf, eom, cp, bp, buflen); - if ((n < 0) || !(*name_ok)(bp)) { - *errp = NO_RECOVERY; - return (NULL); - } - BOUNDED_INCR(n + QFIXEDSZ); - if (qtype == T_A || qtype == T_AAAA) { - /* res_send() has already verified that the query name is the - * same as the one we sent; this just gets the expanded name - * (i.e., with the succeeding search-domain tacked on). - */ - n = strlen(bp) + 1; /* for the \0 */ - if (n >= MAXHOSTNAMELEN) { - *errp = NO_RECOVERY; - return (NULL); + if ((new = malloc(sizeof(*new))) == NULL) { + free_addrselectpolicy(head); /* make the list empty */ + break; } - template->h_name = bp; - bp += n; - buflen -= n; - /* The qname can be abbreviated, but h_name is now absolute. */ - qname = template->h_name; + new->pc_policy = *pol; + TAILQ_INSERT_TAIL(head, new, pc_entry); } - ap = host_aliases; - *ap = NULL; - template->h_aliases = host_aliases; - hap = h_addr_ptrs; - *hap = NULL; - template->h_addr_list = h_addr_ptrs; - haveanswer = 0; - had_error = 0; - while (ancount-- > 0 && cp < eom && !had_error) { - n = dn_expand(answer->buf, eom, cp, bp, buflen); - DNS_FATAL(n >= 0); - DNS_FATAL((*name_ok)(bp)); - cp += n; /* name */ - BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); - NS_GET16(type, cp); /* type */ - NS_GET16(class, cp); /* class */ - cp += INT32SZ; /* skip TTL */ - NS_GET16(n, cp); /* len */ - BOUNDS_CHECK(cp, n); - erdata = cp + n; - DNS_ASSERT(class == C_IN); - if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { - if (ap >= &host_aliases[MAXALIASES-1]) - continue; - n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); - DNS_FATAL(n >= 0); - DNS_FATAL((*name_ok)(tbuf)); - cp += n; - if (cp != erdata) { - *errp = NO_RECOVERY; - return (NULL); - } - /* Store alias. */ - *ap++ = bp; - n = strlen(bp) + 1; /* for the \0 */ - DNS_FATAL(n < MAXHOSTNAMELEN); - bp += n; - buflen -= n; - /* Get canonical name. */ - n = strlen(tbuf) + 1; /* for the \0 */ - DNS_FATAL(n <= buflen); - DNS_FATAL(n < MAXHOSTNAMELEN); - strcpy(bp, tbuf); - template->h_name = bp; - bp += n; - buflen -= n; - continue; - } - if (qtype == T_PTR && type == T_CNAME) { - n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); - if (n < 0 || !res_dnok(tbuf)) { - had_error++; - continue; - } - cp += n; - if (cp != erdata) { - *errp = NO_RECOVERY; - return (NULL); - } - /* Get canonical name. */ - n = strlen(tbuf) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) { - had_error++; - continue; - } - strcpy(bp, tbuf); - tname = bp; - bp += n; - buflen -= n; - continue; - } - DNS_ASSERT(type == qtype); - switch (type) { - case T_PTR: - DNS_ASSERT(strcasecmp(tname, bp) == 0); - n = dn_expand(answer->buf, eom, cp, bp, buflen); - DNS_FATAL(n >= 0); - DNS_FATAL(res_hnok(bp)); -#if MULTI_PTRS_ARE_ALIASES - cp += n; - if (cp != erdata) { - *errp = NO_RECOVERY; - return (NULL); - } - if (!haveanswer) - template->h_name = bp; - else if (ap < &host_aliases[MAXALIASES-1]) - *ap++ = bp; - else - n = -1; - if (n != -1) { - n = strlen(bp) + 1; /* for the \0 */ - if (n >= MAXHOSTNAMELEN) { - had_error++; - break; - } - bp += n; - buflen -= n; - } - break; + + free(buf); + return (1); #else - template->h_name = bp; - *errp = NETDB_SUCCESS; - return (template); -#endif - case T_A: - case T_AAAA: - DNS_ASSERT(strcasecmp(template->h_name, bp) == 0); - DNS_ASSERT(n == template->h_length); - if (!haveanswer) { - int nn; - - template->h_name = bp; - nn = strlen(bp) + 1; /* for the \0 */ - bp += nn; - buflen -= nn; - } - obp = bp; /* ALIGN rounds up */ - bp = (char *)ALIGN(bp); - buflen -= (bp - obp); - - DNS_FATAL(bp + n < &hostbuf[sizeof hostbuf]); - DNS_ASSERT(hap < &h_addr_ptrs[MAXADDRS-1]); -#ifdef FILTER_V4MAPPED - if (type == T_AAAA) { - struct in6_addr in6; - memcpy(&in6, cp, sizeof(in6)); - DNS_ASSERT(IN6_IS_ADDR_V4MAPPED(&in6) == 0); - } + return (0); #endif - bcopy(cp, *hap++ = bp, n); - bp += n; - buflen -= n; - cp += n; - if (cp != erdata) { - *errp = NO_RECOVERY; - return (NULL); - } - break; - default: - abort(); - } - if (!had_error) - haveanswer++; - } - if (haveanswer) { - *ap = NULL; - *hap = NULL; - if (!template->h_name) { - n = strlen(qname) + 1; /* for the \0 */ - if (n > buflen || n >= MAXHOSTNAMELEN) - goto no_recovery; - strcpy(bp, qname); - template->h_name = bp; - bp += n; - buflen -= n; - } - *errp = NETDB_SUCCESS; - return (template); - } - no_recovery: - *errp = NO_RECOVERY; - return (NULL); - -#undef BOUNDED_INCR -#undef BOUNDS_CHECK -#undef DNS_ASSERT -#undef DNS_FATAL } -/* res_search() variant with multiple query support. */ -static struct hostent * -_res_search_multi(const char *name, struct __res_type_list *rtl, int *errp) +static void +free_addrselectpolicy(struct policyhead *head) { - const char *cp, * const *domain; - struct hostent *hp0 = NULL, *hp; - struct hostent hpbuf; - u_int dots; - int trailing_dot, ret, saved_herrno; - int got_nodata = 0, got_servfail = 0, tried_as_is = 0; - struct __res_type_list *rtl0 = rtl; - querybuf *buf; - - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - *errp = NETDB_INTERNAL; - return (NULL); - } - dots = 0; - for (cp = name; *cp; cp++) - dots += (*cp == '.'); - trailing_dot = 0; - if (cp > name && *--cp == '.') - trailing_dot++; - - buf = malloc(sizeof(*buf)); - if (buf == NULL) { - *errp = NETDB_INTERNAL; - return NULL; - } - - /* If there aren't any dots, it could be a user-level alias */ - if (!dots && (cp = hostalias(name)) != NULL) { - for(rtl = rtl0; rtl != NULL; - rtl = SLIST_NEXT(rtl, rtl_entry)) { - ret = res_query(cp, C_IN, rtl->rtl_type, buf->buf, - sizeof(buf->buf)); - if (ret > 0 && (size_t)ret < sizeof(buf->buf)) { - hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) - ? AF_INET6 : AF_INET; - hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); - hp = getanswer(buf, ret, name, rtl->rtl_type, - &hpbuf, errp); - if (!hp) - continue; - hp = _hpcopy(&hpbuf, errp); - hp0 = _hpmerge(hp0, hp, errp); - } else - *errp = h_errno; - } - free(buf); - return (hp0); - } + struct policyqueue *ent, *nent; - /* - * If there are dots in the name already, let's just give it a try - * 'as is'. The threshold can be set with the "ndots" option. - */ - saved_herrno = -1; - if (dots >= _res.ndots) { - for(rtl = rtl0; rtl != NULL; - rtl = SLIST_NEXT(rtl, rtl_entry)) { - ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type, - buf->buf, sizeof(buf->buf)); - if (ret > 0 && (size_t)ret < sizeof(buf->buf)) { - hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) - ? AF_INET6 : AF_INET; - hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); - hp = getanswer(buf, ret, name, rtl->rtl_type, - &hpbuf, errp); - if (!hp) - continue; - hp = _hpcopy(&hpbuf, errp); - hp0 = _hpmerge(hp0, hp, errp); - } else - *errp = h_errno; - } - if (hp0 != NULL) { - free(buf); - return (hp0); - } - saved_herrno = *errp; - tried_as_is++; + for (ent = TAILQ_FIRST(head); ent; ent = nent) { + nent = TAILQ_NEXT(ent, pc_entry); + TAILQ_REMOVE(head, ent, pc_entry); + free(ent); } +} - /* - * We do at least one level of search if - * - there is no dot and RES_DEFNAME is set, or - * - there is at least one dot, there is no trailing dot, - * and RES_DNSRCH is set. - */ - if ((!dots && (_res.options & RES_DEFNAMES)) || - (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { - int done = 0; - - for (domain = (const char * const *)_res.dnsrch; - *domain && !done; - domain++) { - - for(rtl = rtl0; rtl != NULL; - rtl = SLIST_NEXT(rtl, rtl_entry)) { - ret = res_querydomain(name, *domain, C_IN, - rtl->rtl_type, - buf->buf, sizeof(buf->buf)); - if (ret > 0 && (size_t)ret < sizeof(buf->buf)) { - hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) - ? AF_INET6 : AF_INET; - hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); - hp = getanswer(buf, ret, name, - rtl->rtl_type, &hpbuf, errp); - if (!hp) - continue; - hp = _hpcopy(&hpbuf, errp); - hp0 = _hpmerge(hp0, hp, errp); - } else - *errp = h_errno; - } - if (hp0 != NULL) { - free(buf); - return (hp0); - } +static struct policyqueue * +match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head) +{ +#ifdef INET6 + struct policyqueue *ent, *bestent = NULL; + struct in6_addrpolicy *pol; + int matchlen, bestmatchlen = -1; + u_char *mp, *ep, *k, *p, m; + struct sockaddr_in6 key; - /* - * If no server present, give up. - * If name isn't found in this domain, - * keep trying higher domains in the search list - * (if that's enabled). - * On a NO_DATA error, keep trying, otherwise - * a wildcard entry of another type could keep us - * from finding this entry higher in the domain. - * If we get some other error (negative answer or - * server failure), then stop searching up, - * but try the input name below in case it's - * fully-qualified. - */ - if (errno == ECONNREFUSED) { - free(buf); - *errp = TRY_AGAIN; - return (NULL); - } + switch(addr->sa_family) { + case AF_INET6: + key = *(struct sockaddr_in6 *)addr; + break; + case AF_INET: + /* convert the address into IPv4-mapped IPv6 address. */ + memset(&key, 0, sizeof(key)); + key.sin6_family = AF_INET6; + key.sin6_len = sizeof(key); + key.sin6_addr.s6_addr[10] = 0xff; + key.sin6_addr.s6_addr[11] = 0xff; + memcpy(&key.sin6_addr.s6_addr[12], + &((struct sockaddr_in *)addr)->sin_addr, 4); + break; + default: + return(NULL); + } - switch (*errp) { - case NO_DATA: - got_nodata++; - /* FALLTHROUGH */ - case HOST_NOT_FOUND: - /* keep trying */ - break; - case TRY_AGAIN: - if (buf->hdr.rcode == SERVFAIL) { - /* try next search element, if any */ - got_servfail++; - break; + for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) { + pol = &ent->pc_policy; + matchlen = 0; + + mp = (u_char *)&pol->addrmask.sin6_addr; + ep = mp + 16; /* XXX: scope field? */ + k = (u_char *)&key.sin6_addr; + p = (u_char *)&pol->addr.sin6_addr; + for (; mp < ep && *mp; mp++, k++, p++) { + m = *mp; + if ((*k & m) != *p) + goto next; /* not match */ + if (m == 0xff) /* short cut for a typical case */ + matchlen += 8; + else { + while (m >= 0x80) { + matchlen++; + m <<= 1; } - /* FALLTHROUGH */ - default: - /* anything else implies that we're done */ - done++; } - - /* if we got here for some reason other than DNSRCH, - * we only wanted one iteration of the loop, so stop. - */ - if (!(_res.options & RES_DNSRCH)) - done++; } - } - /* - * If we have not already tried the name "as is", do that now. - * note that we do this regardless of how many dots were in the - * name or whether it ends with a dot unless NOTLDQUERY is set. - */ - if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) { - for(rtl = rtl0; rtl != NULL; - rtl = SLIST_NEXT(rtl, rtl_entry)) { - ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type, - buf->buf, sizeof(buf->buf)); - if (ret > 0 && (size_t)ret < sizeof(buf->buf)) { - hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) - ? AF_INET6 : AF_INET; - hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); - hp = getanswer(buf, ret, name, rtl->rtl_type, - &hpbuf, errp); - if (!hp) - continue; - hp = _hpcopy(&hpbuf, errp); - hp0 = _hpmerge(hp0, hp, errp); - } else - *errp = h_errno; - } - if (hp0 != NULL) { - free(buf); - return (hp0); + /* matched. check if this is better than the current best. */ + if (matchlen > bestmatchlen) { + bestent = ent; + bestmatchlen = matchlen; } + + next: + continue; } - free(buf); + return(bestent); +#else + return(NULL); +#endif - /* if we got here, we didn't satisfy the search. - * if we did an initial full query, return that query's h_errno - * (note that we wouldn't be here if that query had succeeded). - * else if we ever got a nodata, send that back as the reason. - * else send back meaningless h_errno, that being the one from - * the last DNSRCH we did. - */ - if (saved_herrno != -1) - *errp = saved_herrno; - else if (got_nodata) - *errp = NO_DATA; - else if (got_servfail) - *errp = TRY_AGAIN; - return (NULL); } -static int -_dns_ghbyname(void *rval, void *cb_data, va_list ap) +static void +set_source(struct hp_order *aio, struct policyhead *ph) { - const char *name; - int af; - int *errp; - struct __res_type_list *rtl, rtl4; -#ifdef INET6 - struct __res_type_list rtl6; -#endif + struct sockaddr_storage ss = aio->aio_un.aiou_ss; + socklen_t srclen; + int s; - name = va_arg(ap, const char *); - af = va_arg(ap, int); - errp = va_arg(ap, int *); + /* set unspec ("no source is available"), just in case */ + aio->aio_srcsa.sa_family = AF_UNSPEC; + aio->aio_srcscope = -1; -#ifdef INET6 - switch (af) { - case AF_UNSPEC: - SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; - SLIST_NEXT(&rtl6, rtl_entry) = &rtl4; rtl6.rtl_type = T_AAAA; - rtl = &rtl6; + switch(ss.ss_family) { + case AF_INET: + ((struct sockaddr_in *)&ss)->sin_port = htons(1); break; +#ifdef INET6 case AF_INET6: - SLIST_NEXT(&rtl6, rtl_entry) = NULL; rtl6.rtl_type = T_AAAA; - rtl = &rtl6; + ((struct sockaddr_in6 *)&ss)->sin6_port = htons(1); break; - case AF_INET: - SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; - rtl = &rtl4; - break; - default: - return(NULL); +#endif + default: /* ignore unsupported AFs explicitly */ + return; + } + + /* open a socket to get the source address for the given dst */ + if ((s = _socket(ss.ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) + return; /* give up */ + if (_connect(s, (struct sockaddr *)&ss, ss.ss_len) < 0) + goto cleanup; + srclen = ss.ss_len; + if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) { + aio->aio_srcsa.sa_family = AF_UNSPEC; + goto cleanup; + } + aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa); + aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph); + aio->aio_matchlen = matchlen(&aio->aio_srcsa, (struct sockaddr *)&ss); +#ifdef INET6 + if (ss.ss_family == AF_INET6) { + struct in6_ifreq ifr6; + u_int32_t flags6; + + /* XXX: interface name should not be hardcoded */ + strncpy(ifr6.ifr_name, "lo0", sizeof(ifr6.ifr_name)); + memset(&ifr6, 0, sizeof(ifr6)); + memcpy(&ifr6.ifr_addr, &ss, ss.ss_len); + if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) { + flags6 = ifr6.ifr_ifru.ifru_flags6; + if ((flags6 & IN6_IFF_DEPRECATED)) + aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED; + } } -#else - SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; - rtl = &rtl4; #endif - *(struct hostent **)rval = _res_search_multi(name, rtl, errp); - if (*(struct hostent **)rval != NULL) - return NS_SUCCESS; - else if (*errp == TRY_AGAIN) - return NS_TRYAGAIN; - else - return NS_NOTFOUND; + + cleanup: + _close(s); + return; } static int -_dns_ghbyaddr(void *rval, void *cb_data, va_list ap) +matchlen(struct sockaddr *src, struct sockaddr *dst) { - const void *addr; + int match = 0; + u_char *s, *d; + u_char *lim, r; int addrlen; - int af; - int *errp; - int n; - struct hostent *hp; - u_char c; - const u_char *cp; - char *bp; - struct hostent hbuf; - int na; -#ifdef INET6 - static const char hex[] = "0123456789abcdef"; -#endif - querybuf *buf; - char qbuf[MAXDNAME+1]; - char *hlist[2]; - const char *tld6[] = { "ip6.arpa", "ip6.int", NULL }; - const char *tld4[] = { "in-addr.arpa", NULL }; - const char **tld; - - addr = va_arg(ap, const void *); - addrlen = va_arg(ap, int); - af = va_arg(ap, int); - errp = va_arg(ap, int *); - - *(struct hostent **)rval = NULL; - -#ifdef INET6 - /* XXX */ - if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr)) - return NS_NOTFOUND; -#endif - switch (af) { + switch (src->sa_family) { #ifdef INET6 case AF_INET6: - tld = tld6; + s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr; + d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr; + addrlen = sizeof(struct in6_addr); + lim = s + addrlen; break; #endif case AF_INET: - tld = tld4; + s = (u_char *)&((struct sockaddr_in *)src)->sin_addr; + d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr; + addrlen = sizeof(struct in_addr); + lim = s + addrlen; break; default: - return NULL; + return(0); } - if ((_res.options & RES_INIT) == 0) { - if (res_init() < 0) { - *errp = h_errno; - return NS_UNAVAIL; - } - } - memset(&hbuf, 0, sizeof(hbuf)); - hbuf.h_name = NULL; - hbuf.h_addrtype = af; - hbuf.h_length = addrlen; - na = 0; - - buf = malloc(sizeof(*buf)); - if (buf == NULL) { - *errp = NETDB_INTERNAL; - return NULL; - } - for (/* nothing */; *tld; tld++) { - /* - * XXX assumes that MAXDNAME is big enough - error checks - * has been made by callers - */ - n = 0; - bp = qbuf; - cp = (const uint8_t *)addr+addrlen-1; - switch (af) { -#ifdef INET6 - case AF_INET6: - for (; n < addrlen; n++, cp--) { - c = *cp; - *bp++ = hex[c & 0xf]; - *bp++ = '.'; - *bp++ = hex[c >> 4]; - *bp++ = '.'; - } - strcpy(bp, *tld); - break; -#endif - case AF_INET: - for (; n < addrlen; n++, cp--) { - c = *cp; - if (c >= 100) - *bp++ = '0' + c / 100; - if (c >= 10) - *bp++ = '0' + (c % 100) / 10; - *bp++ = '0' + c % 10; - *bp++ = '.'; + while (s < lim) + if ((r = (*d++ ^ *s++)) != 0) { + while (r < addrlen * 8) { + match++; + r <<= 1; } - strcpy(bp, *tld); break; - } + } else + match += 8; + return(match); +} - n = res_query(qbuf, C_IN, T_PTR, buf->buf, sizeof buf->buf); - if (n < 0) { - *errp = h_errno; - continue; - } else if ((size_t)n > sizeof(buf->buf)) { - *errp = NETDB_INTERNAL; -#if 0 - errno = ERANGE; /* XXX is it OK to set errno here? */ -#endif - continue; - } - hp = getanswer(buf, n, qbuf, T_PTR, &hbuf, errp); - if (!hp) - continue; - free(buf); - hbuf.h_addrtype = af; - hbuf.h_length = addrlen; - hbuf.h_addr_list = hlist; - hlist[0] = addr; - hlist[1] = NULL; - return _hpcopy(&hbuf, errp); +static int +comp_dst(const void *arg1, const void *arg2) +{ + const struct hp_order *dst1 = arg1, *dst2 = arg2; + + /* + * Rule 1: Avoid unusable destinations. + * XXX: we currently do not consider if an appropriate route exists. + */ + if (dst1->aio_srcsa.sa_family != AF_UNSPEC && + dst2->aio_srcsa.sa_family == AF_UNSPEC) { + return(-1); + } + if (dst1->aio_srcsa.sa_family == AF_UNSPEC && + dst2->aio_srcsa.sa_family != AF_UNSPEC) { + return(1); } - free(buf); - return NULL; -} -#ifdef ICMPNL + /* Rule 2: Prefer matching scope. */ + if (dst1->aio_dstscope == dst1->aio_srcscope && + dst2->aio_dstscope != dst2->aio_srcscope) { + return(-1); + } + if (dst1->aio_dstscope != dst1->aio_srcscope && + dst2->aio_dstscope == dst2->aio_srcscope) { + return(1); + } -/* - * experimental: - * draft-ietf-ipngwg-icmp-namelookups-02.txt - * ifindex is assumed to be encoded in addr. - */ -#include -#include -#include - -struct _icmp_host_cache { - struct _icmp_host_cache *hc_next; - int hc_ifindex; - struct in6_addr hc_addr; - char *hc_name; -}; + /* Rule 3: Avoid deprecated addresses. */ + if (dst1->aio_srcsa.sa_family != AF_UNSPEC && + dst2->aio_srcsa.sa_family != AF_UNSPEC) { + if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) && + (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) { + return(-1); + } + if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) && + !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) { + return(1); + } + } -static char * -_icmp_fqdn_query(const struct in6_addr *addr, int ifindex) -{ - int s; - struct icmp6_filter filter; - struct msghdr msg; - struct cmsghdr *cmsg; - struct in6_pktinfo *pkt; - char cbuf[256]; - char buf[1024]; - int cc; - struct icmp6_fqdn_query *fq; - struct icmp6_fqdn_reply *fr; - struct _icmp_host_cache *hc; - struct sockaddr_in6 sin6; - struct iovec iov; - fd_set s_fds, fds; - struct timeval tout; - int len; - char *name; - static int pid; - static struct _icmp_host_cache *hc_head; - - for (hc = hc_head; hc; hc = hc->hc_next) { - if (hc->hc_ifindex == ifindex - && IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr)) - return hc->hc_name; + /* Rule 4: Prefer home addresses. */ + /* XXX: not implemented yet */ + + /* Rule 5: Prefer matching label. */ +#ifdef INET6 + if (dst1->aio_srcpolicy && dst1->aio_dstpolicy && + dst1->aio_srcpolicy->pc_policy.label == + dst1->aio_dstpolicy->pc_policy.label && + (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL || + dst2->aio_srcpolicy->pc_policy.label != + dst2->aio_dstpolicy->pc_policy.label)) { + return(-1); } + if (dst2->aio_srcpolicy && dst2->aio_dstpolicy && + dst2->aio_srcpolicy->pc_policy.label == + dst2->aio_dstpolicy->pc_policy.label && + (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL || + dst1->aio_srcpolicy->pc_policy.label != + dst1->aio_dstpolicy->pc_policy.label)) { + return(1); + } +#endif - if (pid == 0) - pid = getpid(); - - ICMP6_FILTER_SETBLOCKALL(&filter); - ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter); - - FD_ZERO(&s_fds); - tout.tv_sec = 0; - tout.tv_usec = 200000; /*XXX: 200ms*/ - - fq = (struct icmp6_fqdn_query *)buf; - fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY; - fq->icmp6_fqdn_code = 0; - fq->icmp6_fqdn_cksum = 0; - fq->icmp6_fqdn_id = (u_short)pid; - fq->icmp6_fqdn_unused = 0; - fq->icmp6_fqdn_cookie[0] = 0; - fq->icmp6_fqdn_cookie[1] = 0; - - memset(&sin6, 0, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_addr = *addr; - - memset(&msg, 0, sizeof(msg)); - msg.msg_name = (caddr_t)&sin6; - msg.msg_namelen = sizeof(sin6); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - iov.iov_base = (caddr_t)buf; - iov.iov_len = sizeof(struct icmp6_fqdn_query); - - if (ifindex) { - msg.msg_control = cbuf; - msg.msg_controllen = sizeof(cbuf); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); - cmsg->cmsg_level = IPPROTO_IPV6; - cmsg->cmsg_type = IPV6_PKTINFO; - pkt = (struct in6_pktinfo *)&cmsg[1]; - memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr)); - pkt->ipi6_ifindex = ifindex; - cmsg = CMSG_NXTHDR(&msg, cmsg); - msg.msg_controllen = (char *)cmsg - cbuf; + /* Rule 6: Prefer higher precedence. */ +#ifdef INET6 + if (dst1->aio_dstpolicy && + (dst2->aio_dstpolicy == NULL || + dst1->aio_dstpolicy->pc_policy.preced > + dst2->aio_dstpolicy->pc_policy.preced)) { + return(-1); + } + if (dst2->aio_dstpolicy && + (dst1->aio_dstpolicy == NULL || + dst2->aio_dstpolicy->pc_policy.preced > + dst1->aio_dstpolicy->pc_policy.preced)) { + return(1); } +#endif - if ((s = _socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) - return NULL; - _setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, - (char *)&filter, sizeof(filter)); - cc = _sendmsg(s, &msg, 0); - if (cc < 0) { - _close(s); - return NULL; + /* Rule 7: Prefer native transport. */ + /* XXX: not implemented yet */ + + /* Rule 8: Prefer smaller scope. */ + if (dst1->aio_dstscope >= 0 && + dst1->aio_dstscope < dst2->aio_dstscope) { + return(-1); } - FD_SET(s, &s_fds); - for (;;) { - fds = s_fds; - if (select(s + 1, &fds, NULL, NULL, &tout) <= 0) { - _close(s); - return NULL; + if (dst2->aio_dstscope >= 0 && + dst2->aio_dstscope < dst1->aio_dstscope) { + return(1); + } + + /* + * Rule 9: Use longest matching prefix. + * We compare the match length in a same AF only. + */ + if (dst1->aio_sa.sa_family == dst2->aio_sa.sa_family) { + if (dst1->aio_matchlen > dst2->aio_matchlen) { + return(-1); } - len = sizeof(sin6); - cc = _recvfrom(s, buf, sizeof(buf), 0, - (struct sockaddr *)&sin6, &len); - if (cc <= 0) { - _close(s); - return NULL; + if (dst1->aio_matchlen < dst2->aio_matchlen) { + return(1); } - if (cc < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) - continue; - if (!IN6_ARE_ADDR_EQUAL(addr, &sin6.sin6_addr)) - continue; - fr = (struct icmp6_fqdn_reply *)(buf + sizeof(struct ip6_hdr)); - if (fr->icmp6_fqdn_type == ICMP6_FQDN_REPLY) - break; - } - _close(s); - if (fr->icmp6_fqdn_cookie[1] != 0) { - /* rfc1788 type */ - name = buf + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4; - len = (buf + cc) - name; - } else { - len = fr->icmp6_fqdn_namelen; - name = fr->icmp6_fqdn_name; } - if (len <= 0) - return NULL; - name[len] = 0; - if ((hc = (struct _icmp_host_cache *)malloc(sizeof(*hc))) == NULL) - return NULL; - /* XXX: limit number of cached entries */ - hc->hc_ifindex = ifindex; - hc->hc_addr = *addr; - hc->hc_name = strdup(name); - hc->hc_next = hc_head; - hc_head = hc; - return hc->hc_name; + /* Rule 10: Otherwise, leave the order unchanged. */ + return(-1); } -static struct hostent * -_icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp) +/* + * Copy from scope.c. + * XXX: we should standardize the functions and link them as standard + * library. + */ +static int +gai_addr2scopetype(struct sockaddr *sa) { - char *hname; - int ifindex; - struct in6_addr addr6; +#ifdef INET6 + struct sockaddr_in6 *sa6; +#endif + struct sockaddr_in *sa4; - if (af != AF_INET6) { + switch(sa->sa_family) { +#ifdef INET6 + case AF_INET6: + sa6 = (struct sockaddr_in6 *)sa; + if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) { + /* just use the scope field of the multicast address */ + return(sa6->sin6_addr.s6_addr[2] & 0x0f); + } /* - * Note: rfc1788 defines Who Are You for IPv4, - * but no one implements it. + * Unicast addresses: map scope type to corresponding scope + * value defined for multcast addresses. + * XXX: hardcoded scope type values are bad... */ - return NULL; + if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr)) + return(1); /* node local scope */ + if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) + return(2); /* link-local scope */ + if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr)) + return(5); /* site-local scope */ + return(14); /* global scope */ + break; +#endif + case AF_INET: + /* + * IPv4 pseudo scoping according to RFC 3484. + */ + sa4 = (struct sockaddr_in *)sa; + /* IPv4 autoconfiguration addresses have link-local scope. */ + if (((u_char *)&sa4->sin_addr)[0] == 169 && + ((u_char *)&sa4->sin_addr)[1] == 254) + return(2); + /* Private addresses have site-local scope. */ + if (((u_char *)&sa4->sin_addr)[0] == 10 || + (((u_char *)&sa4->sin_addr)[0] == 172 && + (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) || + (((u_char *)&sa4->sin_addr)[0] == 192 && + ((u_char *)&sa4->sin_addr)[1] == 168)) + return(14); /* XXX: It should be 5 unless NAT */ + /* Loopback addresses have link-local scope. */ + if (((u_char *)&sa4->sin_addr)[0] == 127) + return(2); + return(14); + break; + default: + errno = EAFNOSUPPORT; /* is this a good error? */ + return(-1); } - - memcpy(&addr6, addr, addrlen); - ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3]; - addr6.s6_addr[2] = addr6.s6_addr[3] = 0; - - if (!IN6_IS_ADDR_LINKLOCAL(&addr6)) - return NULL; /*XXX*/ - - if ((hname = _icmp_fqdn_query(&addr6, ifindex)) == NULL) - return NULL; - return _hpaddr(af, hname, &addr6, errp); } -#endif /* ICMPNL */ diff --git a/lib/libc/net/netdb_private.h b/lib/libc/net/netdb_private.h index cef0b7ce1c..51ec8c4950 100644 --- a/lib/libc/net/netdb_private.h +++ b/lib/libc/net/netdb_private.h @@ -130,16 +130,16 @@ void __endprotoent_p(struct protoent_data *); int __getprotoent_p(struct protoent *, struct protoent_data *); void __setprotoent_p(int, struct protoent_data *); void _endhostdnsent(void); -void _endhosthtent(void); +void _endhosthtent(struct hostent_data *); void _endnetdnsent(void); -void _endnethtent(void); -struct hostent *_gethostbynisaddr(const char *, int, int); +void _endnethtent(struct netent_data *); +struct hostent *_gethostbynisaddr(const void *, socklen_t, int); struct hostent *_gethostbynisname(const char *, int); void _map_v4v6_address(const char *, char *); -void _map_v4v6_hostent(struct hostent *, char **, int *); +void _map_v4v6_hostent(struct hostent *, char **, char *); void _sethostdnsent(int); -void _sethosthtent(int); +void _sethosthtent(int, struct hostent_data *); void _setnetdnsent(int); -void _setnethtent(int); +void _setnethtent(int, struct netent_data *); #endif /* _NETDB_PRIVATE_H_ */ diff --git a/lib/libc/net/ns_name.c b/lib/libc/net/ns_name.c deleted file mode 100644 index 18ddc18a02..0000000000 --- a/lib/libc/net/ns_name.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - * Copyright (c) 1996 by 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. - * - * $FreeBSD: src/lib/libc/net/ns_name.c,v 1.2 1999/08/28 00:00:14 peter Exp $ - * $DragonFly: src/lib/libc/net/ns_name.c,v 1.3 2005/11/13 02:04:47 swildner Exp $ - */ - -#include - -#include -#include - -#include -#include -#include - -/* Data. */ - -static char digits[] = "0123456789"; - -/* Forward. */ - -static int special(int); -static int printable(int); -static int dn_find(const u_char *, const u_char *, - const u_char * const *, - const u_char * const *); - -/* Public. */ - -/* - * ns_name_ntop(src, dst, dstsiz) - * Convert an encoded domain name to printable ascii as per RFC1035. - * return: - * Number of bytes written to buffer, or -1 (with errno set) - * notes: - * The root is returned as "." - * All other domains are returned in non absolute form - */ -int -ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) { - const u_char *cp; - char *dn, *eom; - u_char c; - u_int n; - - cp = src; - dn = dst; - eom = dst + dstsiz; - - while ((n = *cp++) != 0) { - if ((n & NS_CMPRSFLGS) != 0) { - /* Some kind of compression pointer. */ - errno = EMSGSIZE; - return (-1); - } - if (dn != dst) { - if (dn >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = '.'; - } - if (dn + n >= eom) { - errno = EMSGSIZE; - return (-1); - } - for (; n > 0; n--) { - c = *cp++; - if (special(c)) { - if (dn + 1 >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = '\\'; - *dn++ = (char)c; - } else if (!printable(c)) { - if (dn + 3 >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = '\\'; - *dn++ = digits[c / 100]; - *dn++ = digits[(c % 100) / 10]; - *dn++ = digits[c % 10]; - } else { - if (dn >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = (char)c; - } - } - } - if (dn == dst) { - if (dn >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = '.'; - } - if (dn >= eom) { - errno = EMSGSIZE; - return (-1); - } - *dn++ = '\0'; - return (dn - dst); -} - -/* - * ns_name_pton(src, dst, dstsiz) - * Convert a ascii string into an encoded domain name as per RFC1035. - * return: - * -1 if it fails - * 1 if string was fully qualified - * 0 is string was not fully qualified - * notes: - * Enforces label and domain length limits. - */ - -int -ns_name_pton(const char *src, u_char *dst, size_t dstsiz) { - u_char *label, *bp, *eom; - int c, n, escaped; - char *cp; - - escaped = 0; - bp = dst; - eom = dst + dstsiz; - label = bp++; - - while ((c = *src++) != 0) { - if (escaped) { - if ((cp = strchr(digits, c)) != NULL) { - n = (cp - digits) * 100; - if ((c = *src++) == 0 || - (cp = strchr(digits, c)) == NULL) { - errno = EMSGSIZE; - return (-1); - } - n += (cp - digits) * 10; - if ((c = *src++) == 0 || - (cp = strchr(digits, c)) == NULL) { - errno = EMSGSIZE; - return (-1); - } - n += (cp - digits); - if (n > 255) { - errno = EMSGSIZE; - return (-1); - } - c = n; - } - escaped = 0; - } else if (c == '\\') { - escaped = 1; - continue; - } else if (c == '.') { - c = (bp - label - 1); - if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ - errno = EMSGSIZE; - return (-1); - } - if (label >= eom) { - errno = EMSGSIZE; - return (-1); - } - *label = c; - /* Fully qualified ? */ - if (*src == '\0') { - if (c != 0) { - if (bp >= eom) { - errno = EMSGSIZE; - return (-1); - } - *bp++ = '\0'; - } - if ((bp - dst) > MAXCDNAME) { - errno = EMSGSIZE; - return (-1); - } - return (1); - } - if (c == 0) { - errno = EMSGSIZE; - return (-1); - } - label = bp++; - continue; - } - if (bp >= eom) { - errno = EMSGSIZE; - return (-1); - } - *bp++ = (u_char)c; - } - c = (bp - label - 1); - if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */ - errno = EMSGSIZE; - return (-1); - } - if (label >= eom) { - errno = EMSGSIZE; - return (-1); - } - *label = c; - if (c != 0) { - if (bp >= eom) { - errno = EMSGSIZE; - return (-1); - } - *bp++ = 0; - } - if ((bp - dst) > MAXCDNAME) { /* src too big */ - errno = EMSGSIZE; - return (-1); - } - return (0); -} - -/* - * ns_name_unpack(msg, eom, src, dst, dstsiz) - * Unpack a domain name from a message, source may be compressed. - * return: - * -1 if it fails, or consumed octets if it succeeds. - */ -int -ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, - u_char *dst, size_t dstsiz) -{ - const u_char *srcp, *dstlim; - u_char *dstp; - int n, len, checked; - - len = -1; - checked = 0; - dstp = dst; - srcp = src; - dstlim = dst + dstsiz; - if (srcp < msg || srcp >= eom) { - errno = EMSGSIZE; - return (-1); - } - /* Fetch next label in domain name. */ - while ((n = *srcp++) != 0) { - /* Check for indirection. */ - switch (n & NS_CMPRSFLGS) { - case 0: - /* Limit checks. */ - if (dstp + n + 1 >= dstlim || srcp + n >= eom) { - errno = EMSGSIZE; - return (-1); - } - checked += n + 1; - *dstp++ = n; - memcpy(dstp, srcp, n); - dstp += n; - srcp += n; - break; - - case NS_CMPRSFLGS: - if (srcp >= eom) { - errno = EMSGSIZE; - return (-1); - } - if (len < 0) - len = srcp - src + 1; - srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); - if (srcp < msg || srcp >= eom) { /* Out of range. */ - errno = EMSGSIZE; - return (-1); - } - checked += 2; - /* - * Check for loops in the compressed name; - * if we've looked at the whole message, - * there must be a loop. - */ - if (checked >= eom - msg) { - errno = EMSGSIZE; - return (-1); - } - break; - - default: - errno = EMSGSIZE; - return (-1); /* flag error */ - } - } - *dstp = '\0'; - if (len < 0) - len = srcp - src; - return (len); -} - -/* - * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr) - * Pack domain name 'domain' into 'comp_dn'. - * return: - * Size of the compressed name, or -1. - * notes: - * 'dnptrs' is an array of pointers to previous compressed names. - * dnptrs[0] is a pointer to the beginning of the message. The array - * ends with NULL. - * 'lastdnptr' is a pointer to the end of the array pointed to - * by 'dnptrs'. - * Side effects: - * The list of pointers in dnptrs is updated for labels inserted into - * the message as we compress the name. If 'dnptr' is NULL, we don't - * try to compress names. If 'lastdnptr' is NULL, we don't update the - * list. - */ -int -ns_name_pack(const u_char *src, u_char *dst, int dstsiz, - const u_char **dnptrs, const u_char **lastdnptr) -{ - u_char *dstp; - const u_char **cpp, **lpp, *eob, *msg; - const u_char *srcp; - int n, l; - - srcp = src; - dstp = dst; - eob = dstp + dstsiz; - lpp = cpp = NULL; - if (dnptrs != NULL) { - if ((msg = *dnptrs++) != NULL) { - for (cpp = dnptrs; *cpp != NULL; cpp++) - ; - lpp = cpp; /* end of list to search */ - } - } else - msg = NULL; - - /* make sure the domain we are about to add is legal */ - l = 0; - do { - n = *srcp; - if ((n & NS_CMPRSFLGS) != 0) { - errno = EMSGSIZE; - return (-1); - } - l += n + 1; - if (l > MAXCDNAME) { - errno = EMSGSIZE; - return (-1); - } - srcp += n + 1; - } while (n != 0); - - srcp = src; - do { - /* Look to see if we can use pointers. */ - n = *srcp; - if (n != 0 && msg != NULL) { - l = dn_find(srcp, msg, (const u_char * const *)dnptrs, - (const u_char * const *)lpp); - if (l >= 0) { - if (dstp + 1 >= eob) { - errno = EMSGSIZE; - return (-1); - } - *dstp++ = (l >> 8) | NS_CMPRSFLGS; - *dstp++ = l % 256; - return (dstp - dst); - } - /* Not found, save it. */ - if (lastdnptr != NULL && cpp < lastdnptr - 1 && - (dstp - msg) < 0x4000) { - *cpp++ = dstp; - *cpp = NULL; - } - } - /* copy label to buffer */ - if (n & NS_CMPRSFLGS) { /* Should not happen. */ - errno = EMSGSIZE; - return (-1); - } - if (dstp + 1 + n >= eob) { - errno = EMSGSIZE; - return (-1); - } - memcpy(dstp, srcp, n + 1); - srcp += n + 1; - dstp += n + 1; - } while (n != 0); - - if (dstp > eob) { - if (msg != NULL) - *lpp = NULL; - errno = EMSGSIZE; - return (-1); - } - return (dstp - dst); -} - -/* - * ns_name_uncompress(msg, eom, src, dst, dstsiz) - * Expand compressed domain name to presentation format. - * return: - * Number of bytes read out of `src', or -1 (with errno set). - * note: - * Root domain returns as "." not "". - */ -int -ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, - char *dst, size_t dstsiz) -{ - u_char tmp[NS_MAXCDNAME]; - int n; - - if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) - return (-1); - if (ns_name_ntop(tmp, dst, dstsiz) == -1) - return (-1); - return (n); -} - -/* - * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr) - * Compress a domain name into wire format, using compression pointers. - * return: - * Number of bytes consumed in `dst' or -1 (with errno set). - * notes: - * 'dnptrs' is an array of pointers to previous compressed names. - * dnptrs[0] is a pointer to the beginning of the message. - * The list ends with NULL. 'lastdnptr' is a pointer to the end of the - * array pointed to by 'dnptrs'. Side effect is to update the list of - * pointers for labels inserted into the message as we compress the name. - * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' - * is NULL, we don't update the list. - */ -int -ns_name_compress(const char *src, u_char *dst, size_t dstsiz, - const u_char **dnptrs, const u_char **lastdnptr) -{ - u_char tmp[NS_MAXCDNAME]; - - if (ns_name_pton(src, tmp, sizeof tmp) == -1) - return (-1); - return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); -} - -/* - * ns_name_skip(ptrptr, eom) - * Advance *ptrptr to skip over the compressed name it points at. - * return: - * 0 on success, -1 (with errno set) on failure. - */ -int -ns_name_skip(const u_char **ptrptr, const u_char *eom) { - const u_char *cp; - u_int n; - - cp = *ptrptr; - while (cp < eom && (n = *cp++) != 0) { - /* Check for indirection. */ - switch (n & NS_CMPRSFLGS) { - case 0: /* normal case, n == len */ - cp += n; - continue; - case NS_CMPRSFLGS: /* indirection */ - cp++; - break; - default: /* illegal type */ - errno = EMSGSIZE; - return (-1); - } - break; - } - if (cp > eom) { - errno = EMSGSIZE; - return (-1); - } - *ptrptr = cp; - return (0); -} - -/* Private. */ - -/* - * special(ch) - * Thinking in noninternationalized USASCII (per the DNS spec), - * is this characted special ("in need of quoting") ? - * return: - * boolean. - */ -static int -special(int ch) { - switch (ch) { - case 0x22: /* '"' */ - case 0x2E: /* '.' */ - case 0x3B: /* ';' */ - case 0x5C: /* '\\' */ - /* Special modifiers in zone files. */ - case 0x40: /* '@' */ - case 0x24: /* '$' */ - return (1); - default: - return (0); - } -} - -/* - * printable(ch) - * Thinking in noninternationalized USASCII (per the DNS spec), - * is this character visible and not a space when printed ? - * return: - * boolean. - */ -static int -printable(int ch) { - return (ch > 0x20 && ch < 0x7f); -} - -/* - * Thinking in noninternationalized USASCII (per the DNS spec), - * convert this character to lower case if it's upper case. - */ -static int -mklower(int ch) { - if (ch >= 0x41 && ch <= 0x5A) - return (ch + 0x20); - return (ch); -} - -/* - * dn_find(domain, msg, dnptrs, lastdnptr) - * Search for the counted-label name in an array of compressed names. - * return: - * offset from msg if found, or -1. - * notes: - * dnptrs is the pointer to the first name on the list, - * not the pointer to the start of the message. - */ -static int -dn_find(const u_char *domain, const u_char *msg, - const u_char * const *dnptrs, - const u_char * const *lastdnptr) -{ - const u_char *dn, *cp, *sp; - const u_char * const *cpp; - u_int n; - - for (cpp = dnptrs; cpp < lastdnptr; cpp++) { - dn = domain; - sp = cp = *cpp; - while ((n = *cp++) != 0) { - /* - * check for indirection - */ - switch (n & NS_CMPRSFLGS) { - case 0: /* normal case, n == len */ - if (n != *dn++) - goto next; - for (; n > 0; n--) - if (mklower(*dn++) != mklower(*cp++)) - goto next; - /* Is next root for both ? */ - if (*dn == '\0' && *cp == '\0') - return (sp - msg); - if (*dn) - continue; - goto next; - - case NS_CMPRSFLGS: /* indirection */ - cp = msg + (((n & 0x3f) << 8) | *cp); - break; - - default: /* illegal type */ - errno = EMSGSIZE; - return (-1); - } - } - next: ; - } - errno = ENOENT; - return (-1); -} diff --git a/lib/libc/net/ns_netint.c b/lib/libc/net/ns_netint.c deleted file mode 100644 index 8264bc6d06..0000000000 --- a/lib/libc/net/ns_netint.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 1996 by 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. - * - * $FreeBSD: src/lib/libc/net/ns_netint.c,v 1.2 1999/08/28 00:00:14 peter Exp $ - * $DragonFly: src/lib/libc/net/ns_netint.c,v 1.2 2003/06/17 04:26:44 dillon Exp $ - */ - -/* Import. */ - -#include -#include - -#include -#include - -u_int -ns_get16(const u_char *src) { - u_int dst; - - NS_GET16(dst, src); - return (dst); -} - -u_long -ns_get32(const u_char *src) { - u_long dst; - - NS_GET32(dst, src); - return (dst); -} - -void -ns_put16(u_int src, u_char *dst) { - NS_PUT16(src, dst); -} - -void -ns_put32(u_long src, u_char *dst) { - NS_PUT32(src, dst); -} diff --git a/lib/libc/net/ns_parse.c b/lib/libc/net/ns_parse.c deleted file mode 100644 index 006078098c..0000000000 --- a/lib/libc/net/ns_parse.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 1996 by 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. - * - * $FreeBSD: src/lib/libc/net/ns_parse.c,v 1.3 1999/08/28 00:00:14 peter Exp $ - * $DragonFly: src/lib/libc/net/ns_parse.c,v 1.2 2003/06/17 04:26:44 dillon Exp $ - */ - -#include - -#include -#include - -#include -#include -#include - -/* These need to be in the same order as the nres.h:ns_flag enum. */ -struct _ns_flagdata _ns_flagdata[16] = { - { 0x8000, 15 }, /* qr. */ - { 0x7800, 11 }, /* opcode. */ - { 0x0400, 10 }, /* aa. */ - { 0x0200, 9 }, /* tc. */ - { 0x0100, 8 }, /* rd. */ - { 0x0080, 7 }, /* ra. */ - { 0x0040, 6 }, /* z. */ - { 0x0020, 5 }, /* ad. */ - { 0x0010, 4 }, /* cd. */ - { 0x000f, 0 }, /* rcode. */ - { 0x0000, 0 }, /* expansion (1/6). */ - { 0x0000, 0 }, /* expansion (2/6). */ - { 0x0000, 0 }, /* expansion (3/6). */ - { 0x0000, 0 }, /* expansion (4/6). */ - { 0x0000, 0 }, /* expansion (5/6). */ - { 0x0000, 0 }, /* expansion (6/6). */ -}; - -static int -skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) { - const u_char *optr = ptr; - - for ((void)NULL; count > 0; count--) { - int b, rdlength; - - b = dn_skipname(ptr, eom); - if (b < 0) - goto emsgsize; - ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; - if (section != ns_s_qd) { - if (ptr + NS_INT32SZ > eom) - goto emsgsize; - ptr += NS_INT32SZ/*TTL*/; - if (ptr + NS_INT16SZ > eom) - goto emsgsize; - NS_GET16(rdlength, ptr); - ptr += rdlength/*RData*/; - } - } - if (ptr > eom) - goto emsgsize; - return (ptr - optr); - emsgsize: - errno = EMSGSIZE; - return (-1); -} - -int -ns_initparse(const u_char *msg, int msglen, ns_msg *handle) { - const u_char *eom = msg + msglen; - int i; - - memset(handle, 0x5e, sizeof *handle); - handle->_msg = msg; - handle->_eom = eom; - if (msg + NS_INT16SZ > eom) - goto emsgsize; - NS_GET16(handle->_id, msg); - if (msg + NS_INT16SZ > eom) - goto emsgsize; - NS_GET16(handle->_flags, msg); - for (i = 0; i < ns_s_max; i++) { - if (msg + NS_INT16SZ > eom) - goto emsgsize; - NS_GET16(handle->_counts[i], msg); - } - for (i = 0; i < ns_s_max; i++) - if (handle->_counts[i] == 0) - handle->_sections[i] = NULL; - else { - int b = skiprr(msg, eom, (ns_sect)i, - handle->_counts[i]); - - if (b < 0) - return (-1); - handle->_sections[i] = msg; - msg += b; - } - if (msg != eom) - goto emsgsize; - handle->_sect = ns_s_max; - handle->_rrnum = -1; - handle->_ptr = NULL; - return (0); - emsgsize: - errno = EMSGSIZE; - return (-1); -} - -int -ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { - int b; - - /* Make section right. */ - if (section < 0 || section >= ns_s_max) - goto enodev; - if ((int)section != (int)handle->_sect) { - handle->_sect = section; - handle->_rrnum = 0; - handle->_ptr = handle->_sections[(int)section]; - } - - /* Make rrnum right. */ - if (rrnum == -1) - rrnum = handle->_rrnum; - if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) - goto enodev; - if (rrnum < handle->_rrnum) { - handle->_rrnum = 0; - handle->_ptr = handle->_sections[(int)section]; - } - - b = skiprr(handle->_msg, handle->_eom, section, - rrnum - handle->_rrnum); - if (b < 0) - return (-1); - handle->_ptr += b; - handle->_rrnum = rrnum; - - /* Do the parse. */ - b = dn_expand(handle->_msg, handle->_eom, - handle->_ptr, rr->name, NS_MAXDNAME); - if (b < 0) - return (-1); - handle->_ptr += b; - if (handle->_ptr + NS_INT16SZ > handle->_eom) - goto emsgsize; - NS_GET16(rr->type, handle->_ptr); - if (handle->_ptr + NS_INT16SZ > handle->_eom) - goto emsgsize; - NS_GET16(rr->rr_class, handle->_ptr); - if (section == ns_s_qd) { - rr->ttl = 0; - rr->rdlength = 0; - rr->rdata = NULL; - } else { - if (handle->_ptr + NS_INT32SZ > handle->_eom) - goto emsgsize; - NS_GET32(rr->ttl, handle->_ptr); - if (handle->_ptr + NS_INT16SZ > handle->_eom) - goto emsgsize; - NS_GET16(rr->rdlength, handle->_ptr); - if (handle->_ptr + rr->rdlength > handle->_eom) - goto emsgsize; - rr->rdata = handle->_ptr; - handle->_ptr += rr->rdlength; - } - handle->_rrnum++; - - /* All done. */ - return (0); - enodev: - errno = ENODEV; - return (-1); - emsgsize: - errno = EMSGSIZE; - return (-1); -} diff --git a/lib/libc/net/ns_print.c b/lib/libc/net/ns_print.c deleted file mode 100644 index 5289be6f45..0000000000 --- a/lib/libc/net/ns_print.c +++ /dev/null @@ -1,742 +0,0 @@ -/* - * Copyright (c) 1996, 1998 by 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. - * - * $FreeBSD: src/lib/libc/net/ns_print.c,v 1.2 1999/08/28 00:00:15 peter Exp $ - * $DragonFly: src/lib/libc/net/ns_print.c,v 1.3 2005/11/13 02:04:47 swildner Exp $ - */ - -/* Import. */ - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#define SPRINTF(x) ((size_t)sprintf x) - -/* Forward. */ - -static size_t prune_origin(const char *name, const char *origin); -static int charstr(const u_char *rdata, const u_char *edata, - char **buf, size_t *buflen); -static int addname(const u_char *msg, size_t msglen, - const u_char **p, const char *origin, - char **buf, size_t *buflen); -static void addlen(size_t len, char **buf, size_t *buflen); -static int addstr(const char *src, size_t len, - char **buf, size_t *buflen); -static int addtab(size_t len, size_t target, int spaced, - char **buf, size_t *buflen); - -/* Macros. */ - -#define T(x) \ - do { \ - if ((x) < 0) \ - return (-1); \ - } while (0) - -/* Public. */ - -/* - * int - * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen) - * Convert an RR to presentation format. - * return: - * Number of characters written to buf, or -1 (check errno). - */ -int -ns_sprintrr(const ns_msg *handle, const ns_rr *rr, - const char *name_ctx, const char *origin, - char *buf, size_t buflen) -{ - int n; - - n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), - ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), - ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), - name_ctx, origin, buf, buflen); - return (n); -} - -/* - * int - * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen, - * name_ctx, origin, buf, buflen) - * Convert the fields of an RR into presentation format. - * return: - * Number of characters written to buf, or -1 (check errno). - */ -int -ns_sprintrrf(const u_char *msg, size_t msglen, - const char *name, ns_class class, ns_type type, - u_long ttl, const u_char *rdata, size_t rdlen, - const char *name_ctx, const char *origin, - char *buf, size_t buflen) -{ - const char *obuf = buf; - const u_char *edata = rdata + rdlen; - int spaced = 0; - - const char *comment; - char tmp[100]; - int len, x; - - /* - * Owner. - */ - if (name_ctx != NULL && strcasecmp(name_ctx, name) == 0) { - T(addstr("\t\t\t", 3, &buf, &buflen)); - } else { - len = prune_origin(name, origin); - if (len == 0) { - T(addstr("@\t\t\t", 4, &buf, &buflen)); - } else { - T(addstr(name, len, &buf, &buflen)); - /* Origin not used and no trailing dot? */ - if ((!origin || !origin[0] || name[len] == '\0') && - name[len - 1] != '.') { - T(addstr(".", 1, &buf, &buflen)); - len++; - } - T(spaced = addtab(len, 24, spaced, &buf, &buflen)); - } - } - - /* - * TTL, Class, Type. - */ - T(x = ns_format_ttl(ttl, buf, buflen)); - addlen(x, &buf, &buflen); - len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); - T(addstr(tmp, len, &buf, &buflen)); - T(spaced = addtab(x + len, 16, spaced, &buf, &buflen)); - - /* - * RData. - */ - switch (type) { - case ns_t_a: - if (rdlen != NS_INADDRSZ) - goto formerr; - inet_ntop(AF_INET, rdata, buf, buflen); - addlen(strlen(buf), &buf, &buflen); - break; - - case ns_t_cname: - case ns_t_mb: - case ns_t_mg: - case ns_t_mr: - case ns_t_ns: - case ns_t_ptr: - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - break; - - case ns_t_hinfo: - case ns_t_isdn: - /* First word. */ - T(len = charstr(rdata, edata, &buf, &buflen)); - if (len == 0) - goto formerr; - rdata += len; - T(addstr(" ", 1, &buf, &buflen)); - - /* Second word. */ - T(len = charstr(rdata, edata, &buf, &buflen)); - if (len == 0) - goto formerr; - rdata += len; - break; - - case ns_t_soa: { - u_long t; - - /* Server name. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - T(addstr(" ", 1, &buf, &buflen)); - - /* Administrator name. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - T(addstr(" (\n", 3, &buf, &buflen)); - spaced = 0; - - if ((edata - rdata) != 5*NS_INT32SZ) - goto formerr; - - /* Serial number. */ - t = ns_get32(rdata); rdata += NS_INT32SZ; - T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); - len = SPRINTF((tmp, "%lu", t)); - T(addstr(tmp, len, &buf, &buflen)); - T(spaced = addtab(len, 16, spaced, &buf, &buflen)); - T(addstr("; serial\n", 9, &buf, &buflen)); - spaced = 0; - - /* Refresh interval. */ - t = ns_get32(rdata); rdata += NS_INT32SZ; - T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); - T(len = ns_format_ttl(t, buf, buflen)); - addlen(len, &buf, &buflen); - T(spaced = addtab(len, 16, spaced, &buf, &buflen)); - T(addstr("; refresh\n", 10, &buf, &buflen)); - spaced = 0; - - /* Retry interval. */ - t = ns_get32(rdata); rdata += NS_INT32SZ; - T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); - T(len = ns_format_ttl(t, buf, buflen)); - addlen(len, &buf, &buflen); - T(spaced = addtab(len, 16, spaced, &buf, &buflen)); - T(addstr("; retry\n", 8, &buf, &buflen)); - spaced = 0; - - /* Expiry. */ - t = ns_get32(rdata); rdata += NS_INT32SZ; - T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); - T(len = ns_format_ttl(t, buf, buflen)); - addlen(len, &buf, &buflen); - T(spaced = addtab(len, 16, spaced, &buf, &buflen)); - T(addstr("; expiry\n", 9, &buf, &buflen)); - spaced = 0; - - /* Minimum TTL. */ - t = ns_get32(rdata); rdata += NS_INT32SZ; - T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); - T(len = ns_format_ttl(t, buf, buflen)); - addlen(len, &buf, &buflen); - T(addstr(" )", 2, &buf, &buflen)); - T(spaced = addtab(len, 16, spaced, &buf, &buflen)); - T(addstr("; minimum\n", 10, &buf, &buflen)); - - break; - } - - case ns_t_mx: - case ns_t_afsdb: - case ns_t_rt: { - u_int t; - - if (rdlen < NS_INT16SZ) - goto formerr; - - /* Priority. */ - t = ns_get16(rdata); - rdata += NS_INT16SZ; - len = SPRINTF((tmp, "%u ", t)); - T(addstr(tmp, len, &buf, &buflen)); - - /* Target. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - - break; - } - - case ns_t_px: { - u_int t; - - if (rdlen < NS_INT16SZ) - goto formerr; - - /* Priority. */ - t = ns_get16(rdata); - rdata += NS_INT16SZ; - len = SPRINTF((tmp, "%u ", t)); - T(addstr(tmp, len, &buf, &buflen)); - - /* Name1. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - T(addstr(" ", 1, &buf, &buflen)); - - /* Name2. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - - break; - } - - case ns_t_x25: - T(len = charstr(rdata, edata, &buf, &buflen)); - if (len == 0) - goto formerr; - rdata += len; - break; - - case ns_t_txt: - while (rdata < edata) { - T(len = charstr(rdata, edata, &buf, &buflen)); - if (len == 0) - goto formerr; - rdata += len; - if (rdata < edata) - T(addstr(" ", 1, &buf, &buflen)); - } - break; - - case ns_t_nsap: { - char t[255*3]; - - inet_nsap_ntoa(rdlen, rdata, t); - T(addstr(t, strlen(t), &buf, &buflen)); - break; - } - - case ns_t_aaaa: - if (rdlen != NS_IN6ADDRSZ) - goto formerr; - inet_ntop(AF_INET6, rdata, buf, buflen); - addlen(strlen(buf), &buf, &buflen); - break; - - case ns_t_loc: { - char t[255]; - - /* XXX protocol format checking? */ - loc_ntoa(rdata, t); - T(addstr(t, strlen(t), &buf, &buflen)); - break; - } - - case ns_t_naptr: { - u_int order, preference; - char t[50]; - - if (rdlen < 2*NS_INT16SZ) - goto formerr; - - /* Order, Precedence. */ - order = ns_get16(rdata); rdata += NS_INT16SZ; - preference = ns_get16(rdata); rdata += NS_INT16SZ; - len = SPRINTF((t, "%u %u ", order, preference)); - T(addstr(t, len, &buf, &buflen)); - - /* Flags. */ - T(len = charstr(rdata, edata, &buf, &buflen)); - if (len == 0) - goto formerr; - rdata += len; - T(addstr(" ", 1, &buf, &buflen)); - - /* Service. */ - T(len = charstr(rdata, edata, &buf, &buflen)); - if (len == 0) - goto formerr; - rdata += len; - T(addstr(" ", 1, &buf, &buflen)); - - /* Regexp. */ - T(len = charstr(rdata, edata, &buf, &buflen)); - if (len < 0) - return (-1); - if (len == 0) - goto formerr; - rdata += len; - T(addstr(" ", 1, &buf, &buflen)); - - /* Server. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - break; - } - - case ns_t_srv: { - u_int priority, weight, port; - char t[50]; - - if (rdlen < NS_INT16SZ*3) - goto formerr; - - /* Priority, Weight, Port. */ - priority = ns_get16(rdata); rdata += NS_INT16SZ; - weight = ns_get16(rdata); rdata += NS_INT16SZ; - port = ns_get16(rdata); rdata += NS_INT16SZ; - len = SPRINTF((t, "%u %u %u ", priority, weight, port)); - T(addstr(t, len, &buf, &buflen)); - - /* Server. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - break; - } - - case ns_t_minfo: - case ns_t_rp: - /* Name1. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - T(addstr(" ", 1, &buf, &buflen)); - - /* Name2. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - - break; - - case ns_t_wks: { - int n, lcnt; - - if (rdlen < NS_INT32SZ + 1) - goto formerr; - - /* Address. */ - inet_ntop(AF_INET, rdata, buf, buflen); - addlen(strlen(buf), &buf, &buflen); - rdata += NS_INADDRSZ; - - /* Protocol. */ - len = SPRINTF((tmp, " %u ( ", *rdata)); - T(addstr(tmp, len, &buf, &buflen)); - rdata += NS_INT8SZ; - - /* Bit map. */ - n = 0; - lcnt = 0; - while (rdata < edata) { - u_int c = *rdata++; - do { - if (c & 0200) { - if (lcnt == 0) { - T(addstr("\n\t\t\t\t", 5, - &buf, &buflen)); - lcnt = 10; - spaced = 0; - } - len = SPRINTF((tmp, "%d ", n)); - T(addstr(tmp, len, &buf, &buflen)); - lcnt--; - } - c <<= 1; - } while (++n & 07); - } - T(addstr(")", 1, &buf, &buflen)); - - break; - } - - case ns_t_key: { - char base64_key[NS_MD5RSA_MAX_BASE64]; - u_int keyflags, protocol, algorithm; - const char *leader; - int n; - - if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) - goto formerr; - - /* Key flags, Protocol, Algorithm. */ - keyflags = ns_get16(rdata); rdata += NS_INT16SZ; - protocol = *rdata++; - algorithm = *rdata++; - len = SPRINTF((tmp, "0x%04x %u %u", - keyflags, protocol, algorithm)); - T(addstr(tmp, len, &buf, &buflen)); - - /* Public key data. */ - len = b64_ntop(rdata, edata - rdata, - base64_key, sizeof base64_key); - if (len < 0) - goto formerr; - if (len > 15) { - T(addstr(" (", 2, &buf, &buflen)); - leader = "\n\t\t"; - spaced = 0; - } else - leader = " "; - for (n = 0; n < len; n += 48) { - T(addstr(leader, strlen(leader), &buf, &buflen)); - T(addstr(base64_key + n, MIN(len - n, 48), - &buf, &buflen)); - } - if (len > 15) - T(addstr(" )", 2, &buf, &buflen)); - - break; - } - - case ns_t_sig: { - char base64_key[NS_MD5RSA_MAX_BASE64]; - u_int type, algorithm, labels, footprint; - const char *leader; - u_long t; - int n; - - if (rdlen < 22) - goto formerr; - - /* Type covered, Algorithm, Label count, Original TTL. */ - type = ns_get16(rdata); rdata += NS_INT16SZ; - algorithm = *rdata++; - labels = *rdata++; - t = ns_get32(rdata); rdata += NS_INT32SZ; - len = SPRINTF((tmp, " %s %d %lu ", - p_type(type), algorithm, t)); - T(addstr(tmp, len, &buf, &buflen)); - if (labels != (u_int)dn_count_labels(name)) - goto formerr; - - /* Signature expiry. */ - t = ns_get32(rdata); rdata += NS_INT32SZ; - len = SPRINTF((tmp, "%s ", p_secstodate(t))); - T(addstr(tmp, len, &buf, &buflen)); - - /* Time signed. */ - t = ns_get32(rdata); rdata += NS_INT32SZ; - len = SPRINTF((tmp, "%s ", p_secstodate(t))); - T(addstr(tmp, len, &buf, &buflen)); - - /* Signature Footprint. */ - footprint = ns_get16(rdata); rdata += NS_INT16SZ; - len = SPRINTF((tmp, "%u ", footprint)); - T(addstr(tmp, len, &buf, &buflen)); - - /* Signer's name. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - - /* Signature. */ - len = b64_ntop(rdata, edata - rdata, - base64_key, sizeof base64_key); - if (len > 15) { - T(addstr(" (", 2, &buf, &buflen)); - leader = "\n\t\t"; - spaced = 0; - } else - leader = " "; - if (len < 0) - goto formerr; - for (n = 0; n < len; n += 48) { - T(addstr(leader, strlen(leader), &buf, &buflen)); - T(addstr(base64_key + n, MIN(len - n, 48), - &buf, &buflen)); - } - if (len > 15) - T(addstr(" )", 2, &buf, &buflen)); - - break; - } - - case ns_t_nxt: { - int n, c; - - /* Next domain name. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - - /* Type bit map. */ - n = edata - rdata; - for (c = 0; c < n*8; c++) - if (NS_NXT_BIT_ISSET(c, rdata)) { - len = SPRINTF((tmp, " %s", p_type(c))); - T(addstr(tmp, len, &buf, &buflen)); - } - break; - } - - default: - comment = "unknown RR type"; - goto hexify; - } - return (buf - obuf); - formerr: - comment = "RR format error"; - hexify: { - int n, m; - char *p; - - len = SPRINTF((tmp, "\\#(\t\t; %s", comment)); - T(addstr(tmp, len, &buf, &buflen)); - while (rdata < edata) { - p = tmp; - p += SPRINTF((p, "\n\t")); - spaced = 0; - n = MIN(16, edata - rdata); - for (m = 0; m < n; m++) - p += SPRINTF((p, "%02x ", rdata[m])); - T(addstr(tmp, p - tmp, &buf, &buflen)); - if (n < 16) { - T(addstr(")", 1, &buf, &buflen)); - T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); - } - p = tmp; - p += SPRINTF((p, "; ")); - for (m = 0; m < n; m++) - *p++ = (isascii(rdata[m]) && isprint(rdata[m])) - ? rdata[m] - : '.'; - T(addstr(tmp, p - tmp, &buf, &buflen)); - rdata += n; - } - return (buf - obuf); - } -} - -/* Private. */ - -/* - * size_t - * prune_origin(name, origin) - * Find out if the name is at or under the current origin. - * return: - * Number of characters in name before start of origin, - * or length of name if origin does not match. - * notes: - * This function should share code with samedomain(). - */ -static size_t -prune_origin(const char *name, const char *origin) { - const char *oname = name; - - while (*name != '\0') { - if (origin != NULL && strcasecmp(name, origin) == 0) - return (name - oname - (name > oname)); - while (*name != '\0') { - if (*name == '\\') { - name++; - /* XXX need to handle \nnn form. */ - if (*name == '\0') - break; - } else if (*name == '.') { - name++; - break; - } - name++; - } - } - return (name - oname); -} - -/* - * int - * charstr(rdata, edata, buf, buflen) - * Format a into the presentation buffer. - * return: - * Number of rdata octets consumed - * 0 for protocol format error - * -1 for output buffer error - * side effects: - * buffer is advanced on success. - */ -static int -charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { - const u_char *odata = rdata; - size_t save_buflen = *buflen; - char *save_buf = *buf; - - if (addstr("\"", 1, buf, buflen) < 0) - goto enospc; - if (rdata < edata) { - int n = *rdata; - - if (rdata + 1 + n <= edata) { - rdata++; - while (n-- > 0) { - if (strchr("\n\"\\", *rdata) != NULL) - if (addstr("\\", 1, buf, buflen) < 0) - goto enospc; - if (addstr((const char *)rdata, 1, - buf, buflen) < 0) - goto enospc; - rdata++; - } - } - } - if (addstr("\"", 1, buf, buflen) < 0) - goto enospc; - return (rdata - odata); - enospc: - errno = ENOSPC; - *buf = save_buf; - *buflen = save_buflen; - return (-1); -} - -static int -addname(const u_char *msg, size_t msglen, - const u_char **pp, const char *origin, - char **buf, size_t *buflen) -{ - size_t newlen, save_buflen = *buflen; - char *save_buf = *buf; - int n; - - n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); - if (n < 0) - goto enospc; /* Guess. */ - newlen = prune_origin(*buf, origin); - if ((origin == NULL || origin[0] == '\0' || (*buf)[newlen] == '\0') && - (newlen == 0 || (*buf)[newlen - 1] != '.')) { - /* No trailing dot. */ - if (newlen + 2 > *buflen) - goto enospc; /* No room for ".\0". */ - (*buf)[newlen++] = '.'; - (*buf)[newlen] = '\0'; - } - if (newlen == 0) { - /* Use "@" instead of name. */ - if (newlen + 2 > *buflen) - goto enospc; /* No room for "@\0". */ - (*buf)[newlen++] = '@'; - (*buf)[newlen] = '\0'; - } - *pp += n; - addlen(newlen, buf, buflen); - **buf = '\0'; - return (newlen); - enospc: - errno = ENOSPC; - *buf = save_buf; - *buflen = save_buflen; - return (-1); -} - -static void -addlen(size_t len, char **buf, size_t *buflen) { - assert(len <= *buflen); - *buf += len; - *buflen -= len; -} - -static int -addstr(const char *src, size_t len, char **buf, size_t *buflen) { - if (len > *buflen) { - errno = ENOSPC; - return (-1); - } - memcpy(*buf, src, len); - addlen(len, buf, buflen); - **buf = '\0'; - return (0); -} - -static int -addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { - size_t save_buflen = *buflen; - char *save_buf = *buf; - int t; - - if (spaced || len >= target - 1) { - T(addstr(" ", 2, buf, buflen)); - spaced = 1; - } else { - for (t = (target - len - 1) / 8; t >= 0; t--) - if (addstr("\t", 1, buf, buflen) < 0) { - *buflen = save_buflen; - *buf = save_buf; - return (-1); - } - spaced = 0; - } - return (spaced); -} diff --git a/lib/libc/net/ns_ttl.c b/lib/libc/net/ns_ttl.c deleted file mode 100644 index 3d6ffcd6b6..0000000000 --- a/lib/libc/net/ns_ttl.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 1996 by 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. - * - * $FreeBSD: src/lib/libc/net/ns_ttl.c,v 1.2 1999/08/28 00:00:15 peter Exp $ - * $DragonFly: src/lib/libc/net/ns_ttl.c,v 1.3 2005/11/13 02:04:47 swildner Exp $ - */ - -/* Import. */ - -#include - -#include -#include -#include -#include - -#define SPRINTF(x) ((size_t)sprintf x) - -/* Forward. */ - -static int fmt1(int t, char s, char **buf, size_t *buflen); - -/* Macros. */ - -#define T(x) if ((x) < 0) return (-1); else (void)NULL - -/* Public. */ - -int -ns_format_ttl(u_long src, char *dst, size_t dstlen) { - char *odst = dst; - int secs, mins, hours, days, weeks, x; - char *p; - - secs = src % 60; src /= 60; - mins = src % 60; src /= 60; - hours = src % 24; src /= 24; - days = src % 7; src /= 7; - weeks = src; src = 0; - - x = 0; - if (weeks) { - T(fmt1(weeks, 'W', &dst, &dstlen)); - x++; - } - if (days) { - T(fmt1(days, 'D', &dst, &dstlen)); - x++; - } - if (hours) { - T(fmt1(hours, 'H', &dst, &dstlen)); - x++; - } - if (mins) { - T(fmt1(mins, 'M', &dst, &dstlen)); - x++; - } - if (secs || !(weeks || days || hours || mins)) { - T(fmt1(secs, 'S', &dst, &dstlen)); - x++; - } - - if (x > 1) { - int ch; - - for (p = odst; (ch = *p) != '\0'; p++) - if (isascii(ch) && isupper(ch)) - *p = tolower(ch); - } - - return (dst - odst); -} - -int -ns_parse_ttl(const char *src, u_long *dst) { - u_long ttl, tmp; - int ch, digits, dirty; - - ttl = 0; - tmp = 0; - digits = 0; - dirty = 0; - while ((ch = *src++) != '\0') { - if (!isascii(ch) || !isprint(ch)) - goto einval; - if (isdigit(ch)) { - tmp *= 10; - tmp += (ch - '0'); - digits++; - continue; - } - if (digits == 0) - goto einval; - if (islower(ch)) - ch = toupper(ch); - switch (ch) { - case 'W': tmp *= 7; - case 'D': tmp *= 24; - case 'H': tmp *= 60; - case 'M': tmp *= 60; - case 'S': break; - default: goto einval; - } - ttl += tmp; - tmp = 0; - digits = 0; - dirty = 1; - } - if (digits > 0) { - if (dirty) - goto einval; - else - ttl += tmp; - } - *dst = ttl; - return (0); - - einval: - errno = EINVAL; - return (-1); -} - -/* Private. */ - -static int -fmt1(int t, char s, char **buf, size_t *buflen) { - char tmp[50]; - size_t len; - - len = SPRINTF((tmp, "%d%c", t, s)); - if (len + 1 > *buflen) - return (-1); - strcpy(*buf, tmp); - *buf += len; - *buflen -= len; - return (0); -} diff --git a/lib/libc/net/res_comp.c b/lib/libc/net/res_comp.c deleted file mode 100644 index 2cf07a5c75..0000000000 --- a/lib/libc/net/res_comp.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 1985, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)res_comp.c 8.1 (Berkeley) 6/4/93 - * $From: Id: res_comp.c,v 8.11 1997/05/21 19:31:04 halley Exp $ - * $FreeBSD: src/lib/libc/net/res_comp.c,v 1.16 1999/08/28 00:00:16 peter Exp $ - * $DragonFly: src/lib/libc/net/res_comp.c,v 1.4 2005/11/13 02:04:47 swildner Exp $ - */ - -/* - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * 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, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION 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. - */ - -/* - * Portions Copyright (c) 1996 by 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 - -#define BIND_4_COMPAT - -/* - * Expand compressed domain name 'comp_dn' to full domain name. - * 'msg' is a pointer to the begining of the message, - * 'eomorig' points to the first location after the message, - * 'exp_dn' is a pointer to a buffer of size 'length' for the result. - * Return size of compressed name or -1 if there was an error. - */ -int -dn_expand(const u_char *msg, const u_char *eom, const u_char *src, - char *dst, int dstsiz) -{ - int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); - - if (n > 0 && dst[0] == '.') - dst[0] = '\0'; - return (n); -} - -/* - * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. - * Return the size of the compressed name or -1. - * 'length' is the size of the array pointed to by 'comp_dn'. - */ -int -dn_comp(const char *src, u_char *dst, int dstsiz, - u_char **dnptrs, u_char **lastdnptr) -{ - return (ns_name_compress(src, dst, (size_t)dstsiz, - (const u_char **)dnptrs, - (const u_char **)lastdnptr)); -} - -/* - * Skip over a compressed domain name. Return the size or -1. - */ -int -dn_skipname(const u_char *ptr, const u_char *eom) -{ - const u_char *saveptr = ptr; - - if (ns_name_skip(&ptr, eom) == -1) - return (-1); - return (ptr - saveptr); -} - -/* - * Verify that a domain name uses an acceptable character set. - */ - -/* - * Note the conspicuous absence of ctype macros in these definitions. On - * non-ASCII hosts, we can't depend on string literals or ctype macros to - * tell us anything about network-format data. The rest of the BIND system - * is not careful about this, but for some reason, we're doing it right here. - */ -#define PERIOD 0x2e -#define hyphenchar(c) ((c) == 0x2d) -#define bslashchar(c) ((c) == 0x5c) -#define periodchar(c) ((c) == PERIOD) -#define asterchar(c) ((c) == 0x2a) -#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ - || ((c) >= 0x61 && (c) <= 0x7a)) -#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) - -#define borderchar(c) (alphachar(c) || digitchar(c)) -#define middlechar(c) (borderchar(c) || hyphenchar(c)) -#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) - -int -res_hnok(const char *dn) -{ - int ppch = '\0', pch = PERIOD, ch = *dn++; - - while (ch != '\0') { - int nch = *dn++; - - if (periodchar(ch)) { - ; - } else if (periodchar(pch)) { - if (!borderchar(ch)) - return (0); - } else if (periodchar(nch) || nch == '\0') { - if (!borderchar(ch)) - return (0); - } else { - if (!middlechar(ch)) - return (0); - } - ppch = pch, pch = ch, ch = nch; - } - return (1); -} - -/* - * hostname-like (A, MX, WKS) owners can have "*" as their first label - * but must otherwise be as a host name. - */ -int -res_ownok(const char *dn) -{ - if (asterchar(dn[0])) { - if (periodchar(dn[1])) - return (res_hnok(dn+2)); - if (dn[1] == '\0') - return (1); - } - return (res_hnok(dn)); -} - -/* - * SOA RNAMEs and RP RNAMEs can have any printable character in their first - * label, but the rest of the name has to look like a host name. - */ -int -res_mailok(const char *dn) -{ - int ch, escaped = 0; - - /* "." is a valid missing representation */ - if (*dn == '\0') - return (1); - - /* otherwise