From a72b0131c9cba3bb6f537ccc4720de87bb151c6e Mon Sep 17 00:00:00 2001 From: Hajimu UMEMOTO Date: Mon, 25 Apr 2005 17:36:28 +0000 Subject: [PATCH] ensure parsing numeric address before any host query. Inspired by: NetBSD --- lib/libc/net/gethostbydns.c | 87 --------------------- lib/libc/net/gethostnamadr.c | 141 +++++++++++++++++++++++++++++++---- 2 files changed, 127 insertions(+), 101 deletions(-) diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c index 33a07491e60a..84912075ded9 100644 --- a/lib/libc/net/gethostbydns.c +++ b/lib/libc/net/gethostbydns.c @@ -96,8 +96,6 @@ static char *host_aliases[MAXALIASES]; static char hostbuf[8*1024]; static u_char host_addr[16]; /* IPv4 or IPv6 */ -extern const char *_res_hostalias(const char *, char *, size_t); - #ifdef RESOLVSORT static void addrsort(char **, int); #endif @@ -476,20 +474,12 @@ _dns_gethostbyname(void *rval, void *cb_data, va_list ap) const char *name; int af; querybuf *buf; - const char *cp; - char *bp, *ep; int n, size, type; - char abuf[MAXDNAME]; 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; - } - switch (af) { case AF_INET: size = INADDRSZ; @@ -508,83 +498,6 @@ _dns_gethostbyname(void *rval, void *cb_data, va_list ap) 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 = _res_hostalias(name, abuf, sizeof abuf))) - 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; - ep = hostbuf + sizeof hostbuf; - 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, &ep); - 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'; - 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 NS_NOTFOUND; diff --git a/lib/libc/net/gethostnamadr.c b/lib/libc/net/gethostnamadr.c index f5c3382ffc8f..2409502f3c67 100644 --- a/lib/libc/net/gethostnamadr.c +++ b/lib/libc/net/gethostnamadr.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -47,9 +48,12 @@ extern int _nis_gethostbyname(void *, void *, va_list); extern int _ht_gethostbyaddr(void *, void *, va_list); extern int _dns_gethostbyaddr(void *, void *, va_list); extern int _nis_gethostbyaddr(void *, void *, va_list); +extern const char *_res_hostalias(const char *, char *, size_t); + +static struct hostent *gethostbyname_internal(const char *, int); /* Host lookup order if nsswitch.conf is broken or nonexistant */ -static const ns_src default_src[] = { +static const ns_src default_src[] = { { NSSRC_FILES, NS_SUCCESS }, { NSSRC_DNS, NS_SUCCESS }, { 0 } @@ -62,31 +66,140 @@ gethostbyname(const char *name) if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; - return (NULL); + 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)); + if (_res.options & RES_USE_INET6) { + hp = gethostbyname_internal(name, AF_INET6); + if (hp) + return hp; + } + return gethostbyname_internal(name, AF_INET); } struct hostent * -gethostbyname2(const char *name, int type) +gethostbyname2(const char *name, int af) { - struct hostent *hp = 0; - int rval; + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return NULL; + } + return gethostbyname_internal(name, af); +} +static struct hostent * +gethostbyname_internal(const char *name, int af) +{ + const char *cp; + char *bp, *ep; + struct hostent *hp = 0; + int size, rval; + char abuf[MAXDNAME]; + + static struct hostent host; + static char *h_addr_ptrs[2]; + static char *host_aliases[1]; + static char hostbuf[MAXDNAME + IN6ADDRSZ + sizeof(uint32_t)]; + static uint32_t host_addr[4]; /* IPv4 or IPv6 */ static const ns_dtab dtab[] = { NS_FILES_CB(_ht_gethostbyname, NULL) { NSSRC_DNS, _dns_gethostbyname, NULL }, NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */ { 0 } - }; - + }; + + switch (af) { + case AF_INET: + size = INADDRSZ; + break; + case AF_INET6: + size = IN6ADDRSZ; + break; + default: + h_errno = NETDB_INTERNAL; + errno = EAFNOSUPPORT; + return NULL; + } + + 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 = _res_hostalias(name, abuf, sizeof abuf))) + name = cp; + + /* + * disallow names consisting only of digits/dots, unless + * they end in a dot. + */ + if (isdigit((u_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 NULL; + } + strncpy(hostbuf, name, MAXDNAME); + hostbuf[MAXDNAME] = '\0'; + bp = hostbuf + MAXDNAME; + ep = hostbuf + sizeof hostbuf; + 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, &ep); + h_errno = NETDB_SUCCESS; + return &host; + } + if (!isdigit((u_char)*cp) && *cp != '.') + break; + } + if ((isxdigit((u_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 NULL; + } + strncpy(hostbuf, name, MAXDNAME); + hostbuf[MAXDNAME] = '\0'; + 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; + return &host; + } + if (!isxdigit((u_char)*cp) && *cp != ':' && *cp != '.') + break; + } + rval = _nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyname", - default_src, name, type); + default_src, name, af); if (rval != NS_SUCCESS) return NULL;