diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-07-03 21:45:45 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-07-03 21:45:45 +0000 |
commit | 2f8f3b7a6a1290e44c382d78b704c8252ae4bc8c (patch) | |
tree | 14aedacad0d5cc685966c0a402eb2c3d3d5ba0e5 /lib/libc/net/getnameinfo.c | |
parent | ba605c59cbfc40d91c9b393f345009157272731e (diff) |
cleaned up
Diffstat (limited to 'lib/libc/net/getnameinfo.c')
-rw-r--r-- | lib/libc/net/getnameinfo.c | 388 |
1 files changed, 210 insertions, 178 deletions
diff --git a/lib/libc/net/getnameinfo.c b/lib/libc/net/getnameinfo.c index 1ae197c15aa..62c4b9d9287 100644 --- a/lib/libc/net/getnameinfo.c +++ b/lib/libc/net/getnameinfo.c @@ -1,7 +1,7 @@ /* * %%% copyright-cmetz-96-bsd * Copyright (c) 1996-1999, Craig Metz, All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -17,7 +17,7 @@ * 4. Neither the name of the author nor the names of 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 @@ -36,197 +36,229 @@ #include <sys/types.h> #include <sys/socket.h> - #include <netinet/in.h> #include <sys/un.h> #include <sys/utsname.h> #include <netdb.h> +#include <arpa/inet.h> #include <errno.h> #include <string.h> #include <resolv.h> -#ifndef AF_LOCAL -#define AF_LOCAL AF_UNIX -#endif /* AF_LOCAL */ - -#ifndef min +#ifndef min #define min(x,y) (((x) > (y)) ? (y) : (x)) -#endif /* min */ +#endif /* min */ -#define RETURN_ERROR(x) do { \ - rval = (x); \ - goto ret; \ - } while(0) - -static int netdb_lookup_name(int family, void *addr, int addrlen, char *name, - int namelen, int flags) +static int +netdb_lookup_name(int family, void *addr, int addrlen, char *name, + int namelen, int flags) { - struct hostent *hostent; - char *c, *c2; - int rval, i; - - if (!(hostent = gethostbyaddr(addr, addrlen, family))) { - switch(h_errno) { - case NETDB_INTERNAL: - RETURN_ERROR(EAI_SYSTEM); - case HOST_NOT_FOUND: - RETURN_ERROR(1); - case TRY_AGAIN: - RETURN_ERROR(EAI_AGAIN); - case NO_RECOVERY: - RETURN_ERROR(EAI_FAIL); - case NO_DATA: - RETURN_ERROR(1); - default: - RETURN_ERROR(EAI_FAIL); - }; - }; - - endhostent(); - - c = hostent->h_name; - if ((flags & NI_NOFQDN) && (_res.options & RES_INIT) && _res.defdname[0] && - (c2 = strstr(c + 1, _res.defdname)) && (*(--c2) == '.')) { - *c2 = 0; - i = min(c2 - c, namelen) - 1; - strncpy(name, c, i); - } else - strncpy(name, c, namelen - 1); - - rval = 0; + struct hostent *hostent; + char *c, *c2; + int i; -ret: - return rval; + if (!(hostent = gethostbyaddr(addr, addrlen, family))) { + switch (h_errno) { + case NETDB_INTERNAL: + return(EAI_SYSTEM); + case HOST_NOT_FOUND: + return(1); + case TRY_AGAIN: + return(EAI_AGAIN); + case NO_RECOVERY: + return(EAI_FAIL); + case NO_DATA: + return(1); + default: + return(EAI_FAIL); + } + } + + endhostent(); + + c = hostent->h_name; + if ((flags & NI_NOFQDN) && (_res.options & RES_INIT) && _res.defdname[0] && + (c2 = strstr(c + 1, _res.defdname)) && (*(--c2) == '.')) { + *c2 = 0; + i = min(c2 - c, namelen); + strlcpy(name, c, i); + } else + strlcpy(name, c, namelen); + return 0; } -int getnameinfo(const struct sockaddr *sa, size_t addrlen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) +int +getnameinfo(const struct sockaddr *sa, size_t addrlen, char *host, + size_t hostlen, char *serv, size_t servlen, int flags) { - int rval; - int serrno = errno; - - if (!sa || (addrlen != SA_LEN(sa))) - RETURN_ERROR(EAI_FAIL); - - if (host && (hostlen > 0)) - switch(sa->sa_family) { - case AF_INET6: - if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)sa)->sin6_addr)) { - if (flags & NI_NUMERICHOST) - goto inet6_noname; - else - strncpy(host, "*", hostlen - 1); - break; - }; - - if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr)) { - struct sockaddr_in sin; - memset(&sin, 0, sizeof(struct sockaddr_in)); - sin.sin_len = sizeof(struct sockaddr_in); - sin.sin_family = AF_INET; - sin.sin_port = ((struct sockaddr_in6 *)sa)->sin6_port; - sin.sin_addr.s_addr = ((u_int32_t *)&((struct sockaddr_in6 *)sa)->sin6_addr)[3]; - if (!(rval = getnameinfo((struct sockaddr *)&sin, sizeof(struct sockaddr_in), host, hostlen, serv, servlen, flags | NI_NAMEREQD))) - goto ret; - if (rval != EAI_NONAME) - goto ret; - goto inet6_noname; - }; - - if (flags & NI_NUMERICHOST) - goto inet6_noname; - - if ((rval = netdb_lookup_name(AF_INET6, - &((struct sockaddr_in6 *)sa)->sin6_addr, sizeof(struct in6_addr), - host, hostlen, flags)) < 0) - goto ret; - - if (!rval) - break; - -inet6_noname: - if (flags & NI_NAMEREQD) - RETURN_ERROR(EAI_NONAME); - - if (!inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr, host, hostlen)) - RETURN_ERROR(EAI_NONAME); - - break; - case AF_INET: - if (flags & NI_NUMERICHOST) - goto inet_noname; - - if (!((struct sockaddr_in *)sa)->sin_addr.s_addr) { - strncpy(host, "*", hostlen - 1); - break; - }; - - if ((rval = netdb_lookup_name(AF_INET, - &((struct sockaddr_in *)sa)->sin_addr, sizeof(struct in_addr), - host, hostlen, flags)) < 0) - goto ret; - - if (!rval) - break; -inet_noname: - if (flags & NI_NAMEREQD) - RETURN_ERROR(EAI_NONAME); - - if (!inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr, host, hostlen)) - RETURN_ERROR(EAI_NONAME); - - break; - case AF_LOCAL: - if (!(flags & NI_NUMERICHOST)) { - struct utsname utsname; - - if (!uname(&utsname)) { - strncpy(host, utsname.nodename, hostlen - 1); - break; - }; - }; - - if (flags & NI_NAMEREQD) - RETURN_ERROR(EAI_NONAME); - - strncpy(host, "localhost", hostlen - 1); - break; - default: - RETURN_ERROR(EAI_FAMILY); - }; - - if (serv && (servlen > 0)) - switch(sa->sa_family) { - case AF_INET: - case AF_INET6: - if (!(flags & NI_NUMERICSERV)) { - struct servent *s; - if (s = getservbyport(((struct sockaddr_in *)sa)->sin_port, (flags & NI_DGRAM) ? "udp" : "tcp")) { - strncpy(serv, s->s_name, servlen - 1); - break; - }; - if (!((struct sockaddr_in *)sa)->sin_port) { - strncpy(serv, "*", servlen - 1); - break; - }; - }; - snprintf(serv, servlen - 1, "%d", ntohs(((struct sockaddr_in *)sa)->sin_port)); - break; - case AF_LOCAL: - strncpy(serv, ((struct sockaddr_un *)sa)->sun_path, servlen - 1); - break; - }; - - if (host && (hostlen > 0)) - host[hostlen-1] = 0; - if (serv && (servlen > 0)) - serv[servlen-1] = 0; - rval = 0; + int rval; + int saved_errno; -ret: - if (rval == 1) - rval = EAI_FAIL; + if (sa == NULL || addrlen != sa->sa_len) + return EAI_FAIL; + saved_errno = errno; + + if (host && hostlen > 0) { + switch (sa->sa_family) { + case AF_INET6: + { + struct sockaddr_in6 *sin6 = (void *)sa; + + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + if (flags & NI_NUMERICHOST) + goto inet6_noname; + strlcpy(host, "*", hostlen); + break; + } + + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { + struct sockaddr_in sin; + + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_len = sizeof(struct sockaddr_in); + sin.sin_family = AF_INET; + sin.sin_port = sin6->sin6_port; + sin.sin_addr.s_addr = + ((u_int32_t *)&sin6->sin6_addr)[3]; + if (!(rval = getnameinfo((struct sockaddr *)&sin, + sizeof(struct sockaddr_in), host, hostlen, + serv, servlen, flags | NI_NAMEREQD))) + goto ret; + if (rval != EAI_NONAME) + goto ret; + goto inet6_noname; + } + + if (flags & NI_NUMERICHOST) + goto inet6_noname; + if ((rval = netdb_lookup_name(AF_INET6, + &sin6->sin6_addr, sizeof(struct in6_addr), + host, hostlen, flags)) < 0) + goto ret; - errno = serrno; + if (!rval) + break; + inet6_noname: + if (flags & NI_NAMEREQD) { + rval = EAI_NONAME; + goto ret; + } + if (!inet_ntop(AF_INET6, &sin6->sin6_addr, host, hostlen)) { + rval = EAI_NONAME; + goto ret; + } + break; + } + case AF_INET: + { + struct sockaddr_in *sin = (void *)sa; - return rval; -}; + if (flags & NI_NUMERICHOST) + goto inet_noname; + + if (sin->sin_addr.s_addr == 0) { + strlcpy(host, "*", hostlen); + break; + } + + if ((rval = netdb_lookup_name(AF_INET, + &sin->sin_addr, sizeof(struct in_addr), + host, hostlen, flags)) < 0) + goto ret; + + if (!rval) + break; + inet_noname: + if (flags & NI_NAMEREQD) { + rval = EAI_NONAME; + goto ret; + } + if (!inet_ntop(AF_INET, &sin->sin_addr, host, hostlen)) { + rval = EAI_NONAME; + goto ret; + } + break; + } + case AF_LOCAL: + if (!(flags & NI_NUMERICHOST)) { + struct utsname utsname; + + if (!uname(&utsname)) { + strlcpy(host, utsname.nodename, hostlen); + break; + } + } + + if (flags & NI_NAMEREQD) { + rval = EAI_NONAME; + goto ret; + } + + strlcpy(host, "localhost", hostlen); + break; + default: + rval = EAI_FAMILY; + goto ret; + } + } + + if (serv && servlen > 0) { + switch (sa->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin = (void *)sa; + struct servent *s; + + if ((flags & NI_NUMERICSERV) == 0) { + s = getservbyport(sin->sin_port, + (flags & NI_DGRAM) ? "udp" : "tcp"); + if (s) { + strlcpy(serv, s->s_name, servlen); + break; + } + if (sin->sin_port == 0) { + strlcpy(serv, "*", servlen); + break; + } + } + snprintf(serv, servlen, "%d", ntohs(sin->sin_port)); + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6 = (void *)sa; + struct servent *s; + + if ((flags & NI_NUMERICSERV) == 0) { + + s = getservbyport(sin6->sin6_port, + (flags & NI_DGRAM) ? "udp" : "tcp"); + if (s) { + strlcpy(serv, s->s_name, servlen); + break; + } + if (sin6->sin6_port == 0) { + strlcpy(serv, "*", servlen); + break; + } + } + snprintf(serv, servlen, "%d", ntohs(sin6->sin6_port)); + break; + } + case AF_LOCAL: + { + struct sockaddr_un *sun = (void *)sa; + + strlcpy(serv, sun->sun_path, servlen); + break; + } + } + } + rval = 0; + +ret: + if (rval == 1) + rval = EAI_FAIL; + errno = saved_errno; + return (rval); +} |