From 0b07eb6ed0e25c8391d711146b09187f3a9a033c Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Wed, 29 Aug 2001 20:48:07 +0000 Subject: [PATCH] split fake getaddrinfo implementation off into a separate file git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13687 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/ChangeLog | 7 + src/include/fake-addrinfo.c | 270 +++++++++++++++++++++++++++++++++++ src/include/fake-addrinfo.h | 275 +----------------------------------- 3 files changed, 282 insertions(+), 270 deletions(-) create mode 100644 src/include/fake-addrinfo.c diff --git a/src/include/ChangeLog b/src/include/ChangeLog index f9b6872f9..ffc8ed424 100644 --- a/src/include/ChangeLog +++ b/src/include/ChangeLog @@ -1,3 +1,10 @@ +2001-08-29 Ken Raeburn + + * fake-addrinfo.c: New file, split off from fake-addrinfo.h. + * fake-addrinfo.h: Don't define implementation functions. + (FAI_DEFINED): New macro, used to protect against multiple + inclusions. + 2001-08-03 Ken Raeburn * k5-int.h (ss2sin6): New gcc-specific function and alternative diff --git a/src/include/fake-addrinfo.c b/src/include/fake-addrinfo.c new file mode 100644 index 000000000..74be2cf0a --- /dev/null +++ b/src/include/fake-addrinfo.c @@ -0,0 +1,270 @@ +#include "fake-addrinfo.h" + +#if !defined (HAVE_GETADDRINFO) || defined (BROKEN_GETADDRINFO) + +static int translate_h_errno (int h); + +static int fai_add_entry (struct addrinfo **result, void *addr, int port, + const struct addrinfo *template) +{ + struct addrinfo *n = malloc (sizeof (struct addrinfo)); + struct sockaddr_in *sin4; + if (n == 0) + return EAI_MEMORY; + if (template->ai_family != AF_INET) + return EAI_FAMILY; + *n = *template; + sin4 = malloc (sizeof (struct sockaddr_in)); + if (sin4 == 0) + return EAI_MEMORY; + n->ai_addr = (struct sockaddr *) sin4; + sin4->sin_family = AF_INET; + sin4->sin_addr = *(struct in_addr *)addr; + sin4->sin_port = port; +#ifdef HAVE_SA_LEN + sin4->sin_len = sizeof (struct sockaddr_in); +#endif + n->ai_next = *result; + *result = n; + return 0; +} + +static int fai_add_hosts_by_name (const char *name, int af, + struct addrinfo *template, + int portnum, int flags, + struct addrinfo **result) +{ + struct hostent *hp; + int i, r; + + if (af != AF_INET) + /* For now, real ipv6 support needs real getaddrinfo. */ + return EAI_FAMILY; + hp = gethostbyname (name); + if (hp == 0) + return translate_h_errno (h_errno); + for (i = 0; hp->h_addr_list[i]; i++) { + r = fai_add_entry (result, hp->h_addr_list[i], portnum, template); + if (r) + return r; + } + if (*result && (flags & AI_CANONNAME)) + (*result)->ai_canonname = strdup (hp->h_name); + return 0; +} + +int getaddrinfo (const char *name, const char *serv, + const struct addrinfo *hint, struct addrinfo **result) +{ + struct addrinfo *res = 0; + int ret; + int port = 0, socktype; + int flags; + struct addrinfo template; + + if (hint != 0) { + if (hint->ai_family != 0 && hint->ai_family != AF_INET) + return EAI_NODATA; + socktype = hint->ai_socktype; + flags = hint->ai_flags; + } else { + socktype = 0; + flags = 0; + } + + if (serv) { + size_t numlen = strspn (serv, "0123456789"); + if (serv[numlen] == '\0') { + /* pure numeric */ + unsigned long p = strtoul (serv, 0, 10); + if (p == 0 || p > 65535) + return EAI_NONAME; + port = htons (p); + } else { + struct servent *sp; + int try_dgram_too = 0; + if (socktype == 0) { + try_dgram_too = 1; + socktype = SOCK_STREAM; + } + try_service_lookup: + sp = getservbyname (serv, socktype == SOCK_STREAM ? "tcp" : "udp"); + if (sp == 0) { + if (try_dgram_too) { + socktype = SOCK_DGRAM; + goto try_service_lookup; + } + return EAI_SERVICE; + } + port = sp->s_port; + } + } + + if (name == 0) { + name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1"; + flags |= AI_NUMERICHOST; + } + + template.ai_family = AF_INET; + template.ai_addrlen = sizeof (struct sockaddr_in); + template.ai_socktype = socktype; + template.ai_protocol = 0; + template.ai_flags = 0; + template.ai_canonname = 0; + template.ai_next = 0; + template.ai_addr = 0; + + /* If NUMERICHOST is set, parse a numeric address. + If it's not set, don't accept such names. */ + if (flags & AI_NUMERICHOST) { + struct in_addr addr4; +#if 0 + ret = inet_aton (name, &addr4); + if (ret) + return EAI_NONAME; +#else + addr4.s_addr = inet_addr (name); + if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1) + /* 255.255.255.255 or parse error, both bad */ + return EAI_NONAME; +#endif + ret = fai_add_entry (&res, &addr4, port, &template); + } else { + ret = fai_add_hosts_by_name (name, AF_INET, &template, port, flags, + &res); + } + + if (ret && ret != NO_ADDRESS) { + freeaddrinfo (res); + return ret; + } + if (res == 0) + return NO_ADDRESS; + *result = res; + return 0; +} + +int getnameinfo (const struct sockaddr *sa, socklen_t len, + char *host, size_t hostlen, + char *service, size_t servicelen, + int flags) +{ + struct hostent *hp; + const struct sockaddr_in *sinp; + struct servent *sp; + + if (sa->sa_family != AF_INET) { + return EAI_FAMILY; + } + sinp = (const struct sockaddr_in *) sa; + + if (host) { + if (flags & NI_NUMERICHOST) { + char *p; + numeric_host: + p = inet_ntoa (sinp->sin_addr); + if (strlen (p) < hostlen) + strcpy (host, p); + else + return EAI_FAIL; /* ?? */ + } else { + hp = gethostbyaddr (&sinp->sin_addr, sizeof (struct in_addr), + sa->sa_family); + if (hp == 0) { + if (h_errno == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */ + goto numeric_host; + return translate_h_errno (h_errno); + } + if (strlen (hp->h_name) < hostlen) + strcpy (host, hp->h_name); + else + return EAI_FAIL; /* ?? */ + } + } + + if (service) { + if (flags & NI_NUMERICSERV) { + char numbuf[10]; + int port; + numeric_service: + port = ntohs (sinp->sin_port); + if (port < 0 || port > 65535) + return EAI_FAIL; + sprintf (numbuf, "%d", port); + if (strlen (numbuf) < servicelen) + strcpy (service, numbuf); + else + return EAI_FAIL; + } else { + sp = getservbyport (sinp->sin_port, + (flags & NI_DGRAM) ? "udp" : "tcp"); + if (sp == 0) + goto numeric_service; + if (strlen (sp->s_name) < servicelen) + strcpy (service, sp->s_name); + else + return EAI_FAIL; + } + } + + return 0; +} + +void freeaddrinfo (struct addrinfo *ai) +{ + struct addrinfo *next; + while (ai) { + next = ai->ai_next; + free (ai->ai_canonname); + free (ai->ai_addr); + free (ai); + ai = next; + } +} + +char *gai_strerror (int code) +{ + switch (code) { + case EAI_ADDRFAMILY: return "address family for nodename not supported"; + case EAI_AGAIN: return "temporary failure in name resolution"; + case EAI_BADFLAGS: return "bad flags to getaddrinfo/getnameinfo"; + case EAI_FAIL: return "non-recoverable failure in name resolution"; + case EAI_FAMILY: return "ai_family not supported"; + case EAI_MEMORY: return "out of memory"; + case EAI_NODATA: return "no address associated with hostname"; + case EAI_NONAME: return "name does not exist"; + case EAI_SERVICE: return "service name not supported for specified socket type"; + case EAI_SOCKTYPE: return "ai_socktype not supported"; + case EAI_SYSTEM: return strerror (errno); + default: return "bogus getaddrinfo error?"; + } +} + +static int translate_h_errno (int h) +{ + switch (h) { + case 0: + return 0; +#ifdef NETDB_INTERNAL + case NETDB_INTERNAL: + if (errno == ENOMEM) + return EAI_MEMORY; + return EAI_SYSTEM; +#endif + case HOST_NOT_FOUND: + return EAI_NONAME; + case TRY_AGAIN: + return EAI_AGAIN; + case NO_RECOVERY: + return EAI_FAIL; + case NO_DATA: +#if NO_DATA != NO_ADDRESS + case NO_ADDRESS: +#endif + return EAI_NODATA; + default: + return EAI_SYSTEM; + } +} + +#endif diff --git a/src/include/fake-addrinfo.h b/src/include/fake-addrinfo.h index 08536e9a4..483230d75 100644 --- a/src/include/fake-addrinfo.h +++ b/src/include/fake-addrinfo.h @@ -1,6 +1,8 @@ +#ifndef FAI_DEFINED +#define FAI_DEFINED #include "port-sockets.h" -#ifndef HAVE_GETADDRINFO +#if !defined (HAVE_GETADDRINFO) || defined (BROKEN_GETADDRINFO) #ifndef FAI_PREFIX # error "FAI_PREFIX must be defined when fake-addrinfo.h is included" @@ -100,275 +102,6 @@ void freeaddrinfo (struct addrinfo *ai); char *gai_strerror (int code); -#ifdef FAI_IMPLEMENTATION - -static int translate_h_errno (int h); - -static int fai_add_entry (struct addrinfo **result, void *addr, int port, - const struct addrinfo *template) -{ - struct addrinfo *n = malloc (sizeof (struct addrinfo)); - struct sockaddr_in *sin4; - if (n == 0) - return EAI_MEMORY; - if (template->ai_family != AF_INET) - return EAI_FAMILY; - *n = *template; - sin4 = malloc (sizeof (struct sockaddr_in)); - if (sin4 == 0) - return EAI_MEMORY; - n->ai_addr = (struct sockaddr *) sin4; - sin4->sin_family = AF_INET; - sin4->sin_addr = *(struct in_addr *)addr; - sin4->sin_port = port; -#ifdef HAVE_SA_LEN - sin4->sin_len = sizeof (struct sockaddr_in); -#endif - n->ai_next = *result; - *result = n; - return 0; -} - -static int fai_add_hosts_by_name (const char *name, int af, - struct addrinfo *template, - int portnum, int flags, - struct addrinfo **result) -{ - struct hostent *hp; - int i, r; - - if (af != AF_INET) - /* For now, real ipv6 support needs real getaddrinfo. */ - return EAI_FAMILY; - hp = gethostbyname (name); - if (hp == 0) - return translate_h_errno (h_errno); - for (i = 0; hp->h_addr_list[i]; i++) { - r = fai_add_entry (result, hp->h_addr_list[i], portnum, template); - if (r) - return r; - } - if (*result && (flags & AI_CANONNAME)) - (*result)->ai_canonname = strdup (hp->h_name); - return 0; -} - -int getaddrinfo (const char *name, const char *serv, - const struct addrinfo *hint, struct addrinfo **result) -{ - struct addrinfo *res = 0; - int ret; - int port = 0, socktype; - int flags; - struct addrinfo template; - - if (hint != 0) { - if (hint->ai_family != 0 && hint->ai_family != AF_INET) - return EAI_NODATA; - socktype = hint->ai_socktype; - flags = hint->ai_flags; - } else { - socktype = 0; - flags = 0; - } - - if (serv) { - size_t numlen = strspn (serv, "0123456789"); - if (serv[numlen] == '\0') { - /* pure numeric */ - unsigned long p = strtoul (serv, 0, 10); - if (p == 0 || p > 65535) - return EAI_NONAME; - port = htons (p); - } else { - struct servent *sp; - int try_dgram_too = 0; - if (socktype == 0) { - try_dgram_too = 1; - socktype = SOCK_STREAM; - } - try_service_lookup: - sp = getservbyname (serv, socktype == SOCK_STREAM ? "tcp" : "udp"); - if (sp == 0) { - if (try_dgram_too) { - socktype = SOCK_DGRAM; - goto try_service_lookup; - } - return EAI_SERVICE; - } - port = sp->s_port; - } - } - - if (name == 0) { - name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1"; - flags |= AI_NUMERICHOST; - } - - template.ai_family = AF_INET; - template.ai_addrlen = sizeof (struct sockaddr_in); - template.ai_socktype = socktype; - template.ai_protocol = 0; - template.ai_flags = 0; - template.ai_canonname = 0; - template.ai_next = 0; - template.ai_addr = 0; - - /* If NUMERICHOST is set, parse a numeric address. - If it's not set, don't accept such names. */ - if (flags & AI_NUMERICHOST) { - struct in_addr addr4; -#if 0 - ret = inet_aton (name, &addr4); - if (ret) - return EAI_NONAME; -#else - addr4.s_addr = inet_addr (name); - if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1) - /* 255.255.255.255 or parse error, both bad */ - return EAI_NONAME; -#endif - ret = fai_add_entry (&res, &addr4, port, &template); - } else { - ret = fai_add_hosts_by_name (name, AF_INET, &template, port, flags, - &res); - } - - if (ret && ret != NO_ADDRESS) { - freeaddrinfo (res); - return ret; - } - if (res == 0) - return NO_ADDRESS; - *result = res; - return 0; -} - -int getnameinfo (const struct sockaddr *sa, socklen_t len, - char *host, size_t hostlen, - char *service, size_t servicelen, - int flags) -{ - struct hostent *hp; - const struct sockaddr_in *sinp; - struct servent *sp; - - if (sa->sa_family != AF_INET) { - return EAI_FAMILY; - } - sinp = (const struct sockaddr_in *) sa; - - if (host) { - if (flags & NI_NUMERICHOST) { - char *p; - numeric_host: - p = inet_ntoa (sinp->sin_addr); - if (strlen (p) < hostlen) - strcpy (host, p); - else - return EAI_FAIL; /* ?? */ - } else { - hp = gethostbyaddr (&sinp->sin_addr, sizeof (struct in_addr), - AF_INET); - if (hp == 0) { - if (h_errno == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */ - goto numeric_host; - return translate_h_errno (h_errno); - } - if (strlen (hp->h_name) < hostlen) - strcpy (host, hp->h_name); - else - return EAI_FAIL; /* ?? */ - } - } - - if (service) { - if (flags & NI_NUMERICSERV) { - char numbuf[10]; - int port; - numeric_service: - port = ntohs (sinp->sin_port); - if (port < 0 || port > 65535) - return EAI_FAIL; - sprintf (numbuf, "%d", port); - if (strlen (numbuf) < servicelen) - strcpy (service, numbuf); - else - return EAI_FAIL; - } else { - sp = getservbyport (sinp->sin_port, - (flags & NI_DGRAM) ? "udp" : "tcp"); - if (sp == 0) - goto numeric_service; - if (strlen (sp->s_name) < servicelen) - strcpy (service, sp->s_name); - else - return EAI_FAIL; - } - } - - return 0; -} - -void freeaddrinfo (struct addrinfo *ai) -{ - struct addrinfo *next; - while (ai) { - next = ai->ai_next; - free (ai->ai_canonname); - free (ai->ai_addr); - free (ai); - ai = next; - } -} - -char *gai_strerror (int code) -{ - switch (code) { - case EAI_ADDRFAMILY: return "address family for nodename not supported"; - case EAI_AGAIN: return "temporary failure in name resolution"; - case EAI_BADFLAGS: return "bad flags to getaddrinfo/getnameinfo"; - case EAI_FAIL: return "non-recoverable failure in name resolution"; - case EAI_FAMILY: return "ai_family not supported"; - case EAI_MEMORY: return "out of memory"; - case EAI_NODATA: return "no address associated with hostname"; - case EAI_NONAME: return "name does not exist"; - case EAI_SERVICE: return "service name not supported for specified socket type"; - case EAI_SOCKTYPE: return "ai_socktype not supported"; - case EAI_SYSTEM: return strerror (errno); - default: return "bogus getaddrinfo error?"; - } -} - -static int translate_h_errno (int h) -{ - switch (h) { - case 0: - return 0; -#ifdef NETDB_INTERNAL - case NETDB_INTERNAL: - if (errno == ENOMEM) - return EAI_MEMORY; - return EAI_SYSTEM; -#endif - case HOST_NOT_FOUND: - return EAI_NONAME; - case TRY_AGAIN: - return EAI_AGAIN; - case NO_RECOVERY: - return EAI_FAIL; - case NO_DATA: -#if NO_DATA != NO_ADDRESS - case NO_ADDRESS: -#endif - return EAI_NODATA; - default: - return EAI_SYSTEM; - } -} - -#endif /* FAI_IMPLEMENTATION */ - #define HAVE_GETADDRINFO #undef HAVE_GETNAMEINFO #define HAVE_GETNAMEINFO @@ -383,3 +116,5 @@ static int translate_h_errno (int h) #ifndef AI_NUMERICHOST # define AI_NUMERICHOST 0 #endif + +#endif /* FAI_DEFINED */ -- 2.26.2