diff options
author | cmetz <cmetz@cvs.openbsd.org> | 1999-06-23 21:55:30 +0000 |
---|---|---|
committer | cmetz <cmetz@cvs.openbsd.org> | 1999-06-23 21:55:30 +0000 |
commit | 0d589ac230ce63eb0d3ce399a31ffa5cb3904614 (patch) | |
tree | 85b14cb3cf4e439e2115cbd059e8c27ca279bc61 /lib | |
parent | b325ac5573bc3c88f13368f8b4a7f1e96de3ae60 (diff) |
Added some protocol independent interfaces (supposedly IPv6 support APIs, but
ones that are useful for all protocols, not just IPv6).
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/net/Makefile.inc | 22 | ||||
-rw-r--r-- | lib/libc/net/__siocgifconf.c | 131 | ||||
-rw-r--r-- | lib/libc/net/freeaddrinfo.c | 45 | ||||
-rw-r--r-- | lib/libc/net/gai_strerror.c | 116 | ||||
-rw-r--r-- | lib/libc/net/getaddrinfo.c | 1127 | ||||
-rw-r--r-- | lib/libc/net/getnameinfo.c | 562 | ||||
-rw-r--r-- | lib/libc/net/if_indextoname.c | 181 | ||||
-rw-r--r-- | lib/libc/net/if_indextoname.o | bin | 0 -> 16022 bytes | |||
-rw-r--r-- | lib/libc/net/if_nameindex.c | 212 | ||||
-rw-r--r-- | lib/libc/net/if_nameindex.o | bin | 0 -> 17733 bytes | |||
-rw-r--r-- | lib/libc/net/if_nametoindex.c | 173 | ||||
-rw-r--r-- | lib/libc/net/if_nametoindex.o | bin | 0 -> 15886 bytes |
12 files changed, 2559 insertions, 10 deletions
diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc index 35a9632a94e..b4b94ad763d 100644 --- a/lib/libc/net/Makefile.inc +++ b/lib/libc/net/Makefile.inc @@ -1,19 +1,21 @@ -# $OpenBSD: Makefile.inc,v 1.17 1998/11/20 11:18:43 d Exp $ +# $OpenBSD: Makefile.inc,v 1.18 1999/06/23 21:55:28 cmetz Exp $ # net sources .PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net CFLAGS+=-DRESOLVSORT -SRCS+= base64.c gethostnamadr.c getnetbyaddr.c getnetbyname.c getnetent.c \ - getnetnamadr.c getproto.c getprotoent.c getprotoname.c getservbyname.c \ - getservbyport.c getservent.c herror.c inet_addr.c inet_lnaof.c \ - inet_makeaddr.c inet_neta.c inet_netof.c inet_network.c \ - inet_net_ntop.c inet_net_pton.c inet_ntoa.c inet_ntop.c \ - inet_pton.c ipx_addr.c ipx_ntoa.c \ - iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c nsap_addr.c rcmd.c recv.c \ - res_comp.c res_data.c res_debug.c res_init.c res_mkquery.c res_query.c \ - res_random.c res_send.c send.c sethostent.c ethers.c rcmdsh.c +SRCS+= __siocgifconf.c base64.c freeaddrinfo.c gai_strerror.c getaddrinfo.c \ + gethostnamadr.c getnameinfo.c getnetbyaddr.c getnetbyname.c \ + getnetent.c getnetnamadr.c getproto.c getprotoent.c getprotoname.c \ + getservbyname.c getservbyport.c getservent.c herror.c \ + if_indextoname.c if_nameindex.c if_nametoindex.c inet_addr.c \ + inet_lnaof.c inet_makeaddr.c inet_neta.c inet_netof.c inet_network.c \ + inet_net_ntop.c inet_net_pton.c inet_ntoa.c inet_ntop.c inet_pton.c \ + ipx_addr.c ipx_ntoa.c iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c \ + nsap_addr.c rcmd.c recv.c res_comp.c res_data.c res_debug.c \ + res_init.c res_mkquery.c res_query.c res_random.c res_send.c send.c \ + sethostent.c ethers.c rcmdsh.c # machine-dependent net sources # m-d Makefile.inc must include sources for: diff --git a/lib/libc/net/__siocgifconf.c b/lib/libc/net/__siocgifconf.c new file mode 100644 index 00000000000..4dac955f56e --- /dev/null +++ b/lib/libc/net/__siocgifconf.c @@ -0,0 +1,131 @@ +/* + * %%% copyright-cmetz-98-bsd + * Copyright (c) 1998-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: + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + */ + +#include <sys/types.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <net/if.h> +#include <sys/ioctl.h> +#include <errno.h> + +int __siocgifconf(int fd, struct ifconf *ifconf) +{ + int i, j; + + ifconf->ifc_len = 0; + ifconf->ifc_buf = 0; + if (!ioctl(fd, SIOCGIFCONF, (void *)ifconf) && ifconf->ifc_len) { + if (!(ifconf->ifc_buf = malloc(ifconf->ifc_len))) { + errno = ENOMEM; + return -1; + }; + if (ioctl(fd, SIOCGIFCONF, (void *)ifconf)) { + free(ifconf->ifc_buf); + return -1; + }; + return 0; + }; + + for (i = 5; i < 12; i++) { + if (!(ifconf->ifc_buf = malloc(ifconf->ifc_len = j = sizeof(struct ifconf) * (1 << i)))) { + errno = ENOMEM; + return -1; + }; + if (ioctl(fd, SIOCGIFCONF, (void *)ifconf)) { + free(ifconf->ifc_buf); + return -1; + }; + if ((ifconf->ifc_len > IFNAMSIZ + sizeof(struct sockaddr)) + && (ifconf->ifc_len < j)) + return 0; + free(ifconf->ifc_buf); + }; + return -1; +}; + diff --git a/lib/libc/net/freeaddrinfo.c b/lib/libc/net/freeaddrinfo.c new file mode 100644 index 00000000000..a327ffb3915 --- /dev/null +++ b/lib/libc/net/freeaddrinfo.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1996, 1997, 1998, 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: + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + */ + +#include <stdlib.h> +#include <netdb.h> + +void freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *p; + + while(ai) { + p = ai; + ai = ai->ai_next; + free((void *)p); + } +} diff --git a/lib/libc/net/gai_strerror.c b/lib/libc/net/gai_strerror.c new file mode 100644 index 00000000000..a758b7449ba --- /dev/null +++ b/lib/libc/net/gai_strerror.c @@ -0,0 +1,116 @@ +/* + * %%% copyright-cmetz-97-bsd + * Copyright (c) 1997-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: + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + */ + +/* gai_strerror() v1.38 */ + +#include <sys/types.h> +#include <netdb.h> +#include <errno.h> + +#define THREAD_SAFE 0 + +#if !THREAD_SAFE +static char buffer[256]; +#endif /* !THREAD_SAFE */ + +char *gai_strerror(int errnum) +{ + switch(errnum) { + case 0: + return "no error"; + case EAI_BADFLAGS: + return "invalid value for ai_flags"; + case EAI_NONAME: + return "name or service is not known"; + case EAI_AGAIN: + return "temporary failure in name resolution"; + case EAI_FAIL: + return "non-recoverable failure in name resolution"; + case EAI_NODATA: + return "no address associated with name"; + case EAI_FAMILY: + return "ai_family not supported"; + case EAI_SOCKTYPE: + return "ai_socktype not supported"; + case EAI_SERVICE: + return "service not supported for ai_socktype"; + case EAI_ADDRFAMILY: + return "address family for name not supported"; + case EAI_MEMORY: + return "memory allocation failure"; + case EAI_SYSTEM: +#if THREAD_SAFE + return "system error"; +#else /* THREAD_SAFE */ + snprintf(buffer, sizeof(buffer)-1, "system error: %s(%d)", strerror(errno), errno); + buffer[sizeof(buffer)-1] = 0; + return buffer; +#endif /* THREAD_SAFE */ + default: +#if THREAD_SAFE + return "unknown/invalid error"; +#else /* THREAD_SAFE */ + snprintf(buffer, sizeof(buffer)-1, "unknown/invalid error %d", errnum); + buffer[sizeof(buffer)-1] = 0; + return buffer; +#endif /* THREAD_SAFE */ + }; +}; diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c new file mode 100644 index 00000000000..a572dbcde09 --- /dev/null +++ b/lib/libc/net/getaddrinfo.c @@ -0,0 +1,1127 @@ +/* + * %%% 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: + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + */ + +/* getaddrinfo() v1.38 */ + +/* + I'd like to thank Matti Aarnio for finding some bugs in this code and + sending me patches, as well as everyone else who has contributed to this + code (by reporting bugs, suggesting improvements, and commented on its + behavior and proposed changes). +*/ + +/* + Someone merged an earlier version of this code into the GNU libc and + added support for getservbyname_r and gethostbyname2_r. The support for + those functions in this version of the code was written using that work + as a reference. I may have improved on it, or I may have broken it. +*/ + +/* To do what POSIX says, even when it's broken, define: */ +/* #define BROKEN_LIKE_POSIX 1 */ +/* Note: real apps will break if you define this, while nothing other than a + conformance test suite should have a problem with it undefined. */ + +/* If your C runtime library provides the POSIX p1003.1g D6.6 bit types + of the form u?int(16|32)_t, define: */ +/* #define HAVE_POSIX1G_TYPES 1 */ +/* Note: this implementation tries to guess what the correct values are for + your compiler+processor combination but might not always get it right. */ + +/* To enable debugging support (REQUIRES NRL support library), define: */ +/* #define DEBUG 1 */ + +#if FOR_GNULIBC +#define HAVE_POSIX1G_TYPES 1 +#define INET6 1 +#define LOCAL 1 +#define NETDB 1 +#undef RESOLVER +#undef HOSTTABLE +#undef DEBUG +#define HAVE_GETSERVBYNAME_R 1 +#define HAVE_GETHOSTBYNAME2_R 1 +#define getservbyname_r __getservbyname_r +#define gethostbyname2_r __gethostbyname2_r +#endif /* FOR_GNULIBC */ + +#ifdef __OpenBSD__ +#define HAVE_POSIX1G_TYPES 1 +#define INET6 1 +#define LOCAL 1 +#define NETDB 1 +#define SALEN 1 +#undef RESOLVER +#undef HOSTTABLE +#undef DEBUG +#undef HAVE_GETSERVBYNAME_R +#undef HAVE_GETHOSTBYNAME2_R +#endif /* __OpenBSD__ */ + +#include <sys/types.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/socket.h> +#include <string.h> +#if LOCAL +#include <stdio.h> +#include <sys/utsname.h> +#include <sys/un.h> +#endif /* LOCAL */ +#include <netinet/in.h> +#include <netdb.h> +#include <errno.h> +#if RESOLVER +#include <arpa/nameser.h> +#include <resolv.h> +#endif /* RESOLVER */ +#if DEBUG +#include <syslog.h> +#endif /* DEBUG */ + +#ifndef AF_LOCAL +#define AF_LOCAL AF_UNIX +#endif /* AF_LOCAL */ +#ifndef PF_LOCAL +#define PF_LOCAL PF_UNIX +#endif /* PF_LOCAL */ +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif /* UNIX_PATH_MAX */ + +#if !HAVE_POSIX1G_TYPES +#if (~0UL) == 0xffffffff +#define uint8_t unsigned char +#define int16_t short +#define uint16_t unsigned short +#define int32_t long +#define uint32_t unsigned long +#else /* (~0UL) == 0xffffffff */ +#if (~0UL) == 0xffffffffffffffff +#define uint8_t unsigned char +#define int16_t short +#define uint16_t unsigned short +#define int32_t int +#define uint32_t unsigned int +#else /* (~0UL) == 0xffffffffffffffff */ +#error Neither 32 bit nor 64 bit word size detected. +#error You need to define the bit types manually. +#endif /* (~0UL) == 0xffffffffffffffff */ +#endif /* (~0UL) == 0xffffffff */ +#endif /* !HAVE_POSIX1G_TYPES */ + +#if defined(INET6) && !defined(AF_INET6) +#error Without a definition of AF_INET6, this system cannot support IPv6 +#error addresses. +#endif /* defined(INET6) && !defined(AF_INET6) */ + +#if INET6 +#ifndef T_AAAA +#define T_AAAA 28 +#endif /* T_AAAA */ +#endif /* INET6 */ + +#if DEBUG +#if RESOLVER +#define DEBUG_MESSAGES (_res.options & RES_DEBUG) +#else /* RESOLVER */ +int __getaddrinfo_debug = 0; +#define DEBUG_MESSAGES (__getaddrinfo_debug) +#endif /* RESOLVER */ +#endif /* DEBUG */ + +#define GAIH_OKIFUNSPEC 0x0100 +#define GAIH_EAI ~(GAIH_OKIFUNSPEC) + +static struct addrinfo nullreq = +{ 0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL }; + +struct gaih_service { + char *name; + int num; +}; + +struct gaih_servtuple { + struct gaih_servtuple *next; + int socktype; + int protocol; + int port; +}; + +static struct gaih_servtuple nullserv = { + NULL, 0, 0, 0 +}; + +struct gaih_addrtuple { + struct gaih_addrtuple *next; + int family; + char addr[16]; + char *cname; +}; + +struct gaih_typeproto { + int socktype; + int protocol; + char *name; +}; + +#if DEBUG +#define RETURN_ERROR(x) do { \ + if (DEBUG_MESSAGES) \ + fprintf(stderr, "%s:%d: returning %s\n", __FILE__, __LINE__, #x); \ + rval = (x); \ + goto ret; \ + } while(0) +#else /* DEBUG */ +#define RETURN_ERROR(x) do { \ + rval = (x); \ + goto ret; \ + } while(0) +#endif /* DEBUG */ + +#if HOSTTABLE +static int hosttable_lookup_addr(const char *name, const struct addrinfo *req, struct gaih_addrtuple **pat) +{ + FILE *f; + char buffer[1024]; + char *c, *c2; + int rval = 1; + char *prevcname = NULL; + struct gaih_addrtuple at; + + if (!(f = fopen("/etc/hosts", "r"))) + RETURN_ERROR(-EAI_SYSTEM); + + while(fgets(buffer, sizeof(buffer), f)) { + if (c = strchr(buffer, '#')) + *c = 0; + + c = buffer; + while(*c && !isspace(*c)) c++; + if (!*c) + continue; + + *(c++) = 0; + + while(*c && isspace(*c)) c++; + if (!*c) + continue; + + if (!(c2 = strstr(c, name))) + continue; + + if (*(c2 - 1) && !isspace(*(c2 - 1))) + continue; + + c2 += strlen(name); + if (*c2 && !isspace(*c2)) + continue; + + c2 = c; + while(*c2 && !isspace(*c2)) c2++; + if (!*c2) + continue; + *c2 = 0; + + memset(&at, 0, sizeof(struct gaih_addrtuple)); + + if (!req->ai_family || (req->ai_family == AF_INET)) + if (inet_pton(AF_INET, buffer, (char *)&at.addr) > 0) { + at.family = AF_INET; + goto build; + }; + +#if INET6 + if (!req->ai_family || (req->ai_family == AF_INET6)) + if (inet_pton(AF_INET6, buffer, (char *)&at.addr) > 0) { + at.family = AF_INET6; + goto build; + }; +#endif /* INET6 */ + + continue; + +build: + if (!(*pat = malloc(sizeof(struct gaih_addrtuple)))) + RETURN_ERROR(-EAI_MEMORY); + + memcpy(*pat, &at, sizeof(struct gaih_addrtuple)); + + if (req->ai_flags & AI_CANONNAME) + if (prevcname && !strcmp(prevcname, c)) + (*pat)->cname = prevcname; + else + prevcname = (*pat)->cname = strdup(c); + + pat = &((*pat)->next); + + rval = 0; + }; + +ret: + if (f) + fclose(f); + return rval; +}; +#endif /* HOSTTABLE */ + +#if NETDB +int netdb_lookup_addr(const char *name, int af, const struct addrinfo *req, struct gaih_addrtuple **pat) +{ + int rval, herrno, i; + char *prevcname = NULL; + struct hostent *h; + +#if HAVE_GETHOSTBYNAME2_R + void *buf; + int buflen = 1024; + struct hostent th; + int herrno, j; + + do { + if (!(buf = malloc(buflen))) + RETURN_ERROR(-EAI_MEMORY); + + if (!gethostbyname2_r(name, af, &th, buf, buflen, &h, &herrno)) + break; + + free(buf); + buf = NULL; + + if ((herrno == NETDB_INTERNAL) && (errno == ERANGE)) { + if (buflen >= 65536) + RETURN_ERROR(-EAI_MEMORY); + + buflen = buflen << 1; + continue; + }; + } while(0); +#else /* HAVE_GETHOSTBYNAME2_R */ + h = gethostbyname2(name, af); + herrno = h_errno; +#endif /* HAVE_GETHOSTBYNAME2_R */ + + if (!h) { +#if DEBUG + if (DEBUG_MESSAGES) + fprintf(stderr, "getaddrinfo: gethostbyname2 failed, h_errno=%d\n", herrno); +#endif /* DEBUG */ + switch(herrno) { + 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); + }; + }; + + for (i = 0; h->h_addr_list[i]; i++) { + while(*pat) + pat = &((*pat)->next); + + if (!(*pat = malloc(sizeof(struct gaih_addrtuple)))) + RETURN_ERROR(-EAI_MEMORY); + + memset(*pat, 0, sizeof(struct gaih_addrtuple)); + + switch((*pat)->family = af) { + case AF_INET: + memcpy((*pat)->addr, h->h_addr_list[i], sizeof(struct in_addr)); + break; +#if INET6 + case AF_INET6: + memcpy((*pat)->addr, h->h_addr_list[i], sizeof(struct in6_addr)); + break; +#endif /* INET6 */ + default: + RETURN_ERROR(-EAI_FAIL); + }; + + if (req->ai_flags & AI_CANONNAME) { + if (prevcname && !strcmp(prevcname, h->h_name)) + (*pat)->cname = prevcname; + else + prevcname = (*pat)->cname = strdup(h->h_name); + }; + + pat = &((*pat)->next); + } + + rval = 0; + +ret: +#if HAVE_GETHOSTBYNAME2_R + free(buf); +#endif /* HAVE_GETHOSTBYNAME2_R */ + return rval; +}; +#endif /* NETDB */ + +#if RESOLVER +#define RRHEADER_SZ 10 + +int resolver_lookup_addr(const char *name, int type, const struct addrinfo *req, struct gaih_addrtuple **pat) +{ + int rval; + char answer[PACKETSZ]; + int answerlen; + char dn[MAXDNAME]; + char *prevcname = NULL; + void *p, *ep; + int answers, i, j; + uint16_t rtype, rclass; + + if ((answerlen = res_search(name, C_IN, type, answer, sizeof(answer))) < 0) { +#if DEBUG + if (DEBUG_MESSAGES) + fprintf(stderr, "getaddrinfo: res_search failed, h_errno=%d\n", h_errno); +#endif /* DEBUG */ + 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); + }; + }; + + p = answer; + ep = answer + answerlen; + + if (answerlen < RRHEADER_SZ) + RETURN_ERROR(-EAI_FAIL); + + { + HEADER *h = (HEADER *)p; + if (!h->qr || (h->opcode != QUERY) || (h->qdcount != htons(1)) || + !h->ancount) + RETURN_ERROR(-EAI_FAIL); + answers = ntohs(h->ancount); + }; + p += sizeof(HEADER); + + if ((i = dn_expand(answer, ep, p, dn, sizeof(dn))) < 0) + RETURN_ERROR(-EAI_FAIL); + p += i; + + if (p + 2*sizeof(uint16_t) >= ep) + RETURN_ERROR(-EAI_FAIL); + + GETSHORT(rtype, p); + GETSHORT(rclass, p); + + if ((rtype != type) || (rclass != C_IN)) + RETURN_ERROR(-EAI_FAIL); + + while(answers--) { + if ((i = dn_expand(answer, ep, p, dn, sizeof(dn))) < 0) + RETURN_ERROR(-EAI_FAIL); + p += i; + + if (p + RRHEADER_SZ >= ep) + RETURN_ERROR(-EAI_FAIL); + + GETSHORT(rtype, p); + GETSHORT(rclass, p); + p += sizeof(uint32_t); + if (rclass != C_IN) + RETURN_ERROR(-EAI_FAIL); + GETSHORT(rclass, p); + i = rclass; + + if (p + i > ep) + RETURN_ERROR(-EAI_FAIL); + + if (rtype == type) { + while(*pat) + pat = &((*pat)->next); + + if (!(*pat = malloc(sizeof(struct gaih_addrtuple)))) + RETURN_ERROR(-EAI_MEMORY); + + memset(*pat, 0, sizeof(struct gaih_addrtuple)); + + switch(type) { + case T_A: + if (i != sizeof(struct in_addr)) + RETURN_ERROR(-EAI_FAIL); + (*pat)->family = AF_INET; + break; +#if INET6 + case T_AAAA: + if (i != sizeof(struct in6_addr)) + RETURN_ERROR(-EAI_FAIL); + (*pat)->family = AF_INET6; + break; +#endif /* INET6 */ + default: + RETURN_ERROR(-EAI_FAIL); + }; + + memcpy((*pat)->addr, p, i); + + if (req->ai_flags & AI_CANONNAME) + if (prevcname && !strcmp(prevcname, dn)) + (*pat)->cname = prevcname; + else + prevcname = (*pat)->cname = strdup(dn); + }; + p += i; + }; + + rval = 0; + +ret: + return rval; +}; +#endif /* RESOLVER */ + +#if LOCAL +static int gaih_local(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai) +{ + int rval; + struct utsname utsname; + + if (name || (req->ai_flags & AI_CANONNAME)) + if (uname(&utsname) < 0) + RETURN_ERROR(-EAI_SYSTEM); + if (name) { + if (strcmp(name, "localhost") && strcmp(name, "local") && strcmp(name, "unix") && strcmp(name, utsname.nodename)) + RETURN_ERROR(GAIH_OKIFUNSPEC | -EAI_NONAME); + }; + + if (!(*pai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_un) + ((req->ai_flags & AI_CANONNAME) ? (strlen(utsname.nodename) + 1): 0)))) + RETURN_ERROR(-EAI_MEMORY); + + (*pai)->ai_next = NULL; + (*pai)->ai_flags = req->ai_flags; + (*pai)->ai_family = AF_LOCAL; + (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM; + (*pai)->ai_protocol = req->ai_protocol; + (*pai)->ai_addrlen = sizeof(struct sockaddr_un); + (*pai)->ai_addr = (void *)(*pai) + sizeof(struct addrinfo); +#if SALEN + ((struct sockaddr_un *)(*pai)->ai_addr)->sun_len = sizeof(struct sockaddr_un); +#endif /* SALEN */ + ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL; + memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX); + if (service) { + char *c; + if (c = strchr(service->name, '/')) { + if (strlen(service->name) >= sizeof(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path)) + RETURN_ERROR(GAIH_OKIFUNSPEC | -EAI_SERVICE); + strcpy(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, service->name); + } else { + if (strlen(P_tmpdir "/") + 1 + strlen(service->name) >= sizeof(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path)) + RETURN_ERROR(GAIH_OKIFUNSPEC | -EAI_SERVICE); + strcpy(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, P_tmpdir "/"); + strcat(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, service->name); + }; + } else { + char *c; + if (!(c = tmpnam(NULL))) + RETURN_ERROR(GAIH_OKIFUNSPEC | -EAI_SYSTEM); + + strncpy((((struct sockaddr_un *)(*pai)->ai_addr)->sun_path), c, sizeof(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path) - 1); + c[sizeof(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path) - 1] = 0; + }; + if (req->ai_flags & AI_CANONNAME) { + strncpy((*pai)->ai_canonname = (char *)(*pai) + sizeof(struct addrinfo) + sizeof(struct sockaddr_un), utsname.nodename, sizeof(utsname.nodename) - 1); + (*pai)->ai_canonname[sizeof(utsname.nodename) - 1] = 0; + } else + (*pai)->ai_canonname = NULL; + + rval = 0; + +ret: + return rval; +}; +#endif /* LOCAL */ + +static struct gaih_typeproto gaih_inet_typeproto[] = { + { 0, 0, NULL }, + { SOCK_STREAM, IPPROTO_TCP, "tcp" }, + { SOCK_DGRAM, IPPROTO_UDP, "udp" }, + { 0, 0, NULL } +}; + +static int gaih_inet_serv(char *servicename, struct gaih_typeproto *tp, struct gaih_servtuple **st) +{ + int rval; + struct servent *s; +#if HAVE_GETSERVBYNAME_R + int i; + void *buf; + int buflen = 1024; + struct servent ts; + + do { + if (!(buf = malloc(buflen))) + RETURN_ERROR(-EAI_MEMORY); + + if (!getservbyname_r(servicename, tp->name, &ts, buf, buflen, &s)) + break; + + free(buf); + buf = NULL; + + if (errno != ERANGE) + RETURN_ERROR(GAIH_OKIFUNSPEC | -EAI_SERVICE); + + if (buflen >= 65536) + RETURN_ERROR(-EAI_MEMORY); + + buflen = buflen << 1; + } while(1); +#else /* HAVE_GETSERVBYNAME_R */ + if (!(s = getservbyname(servicename, tp->name))) + RETURN_ERROR(GAIH_OKIFUNSPEC | -EAI_SERVICE); +#endif /* HAVE_GETSERVBYNAME_R */ + + if (!(*st = malloc(sizeof(struct gaih_servtuple)))) + RETURN_ERROR(-EAI_MEMORY); + + (*st)->next = NULL; + (*st)->socktype = tp->socktype; + (*st)->protocol = tp->protocol; + (*st)->port = s->s_port; + + rval = 0; + +ret: +#if HAVE_GETSERVBYNAME_R + if (buf) + free(buf); +#endif /* HAVE_GETSERVBYNAME_R */ + return rval; +} + +static int gaih_inet(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai) +{ + int rval; + struct hostent *h = NULL; + struct gaih_typeproto *tp = gaih_inet_typeproto; + struct gaih_servtuple *st = &nullserv; + struct gaih_addrtuple *at = NULL; + int i; + + if (req->ai_protocol || req->ai_socktype) { + for (tp++; tp->name && + ((req->ai_socktype != tp->socktype) || !req->ai_socktype) && + ((req->ai_protocol != tp->protocol) || !req->ai_protocol); tp++); + if (!tp->name) + if (req->ai_socktype) + RETURN_ERROR(GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); + else + RETURN_ERROR(GAIH_OKIFUNSPEC | -EAI_SERVICE); + } + + if (service && (service->num < 0)) { + if (tp->name) { + if (rval = gaih_inet_serv(service->name, tp, &st)) + goto ret; + } else { + struct gaih_servtuple **pst = &st; + for (tp++; tp->name; tp++) { + if (rval = gaih_inet_serv(service->name, tp, pst)) { + if (rval & GAIH_OKIFUNSPEC) + continue; + goto ret; + }; + pst = &((*pst)->next); + }; + if (st == &nullserv) + RETURN_ERROR(GAIH_OKIFUNSPEC | -EAI_SERVICE); + }; + } else { + if (!(st = malloc(sizeof(struct gaih_servtuple)))) + RETURN_ERROR(-EAI_MEMORY); + + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = tp->protocol; + if (service) + st->port = htons(service->num); + else + st->port = 0; + }; + + if (!name) { + if (!(at = malloc(sizeof(struct gaih_addrtuple)))) + RETURN_ERROR(-EAI_MEMORY); + + memset(at, 0, sizeof(struct gaih_addrtuple)); + +#if INET6 + if (req->ai_family) + at->family = req->ai_family; + else { + if (!(at->next = malloc(sizeof(struct gaih_addrtuple)))) + RETURN_ERROR(-EAI_MEMORY); + + at->family = AF_INET6; + + memset(at->next, 0, sizeof(struct gaih_addrtuple)); + at->next->family = AF_INET; + }; +#else /* INET6 */ + at->family = AF_INET; +#endif /* INET6 */ + + goto build; + }; + + if (!req->ai_family || (req->ai_family == AF_INET)) { + struct in_addr in_addr; + if (inet_pton(AF_INET, name, &in_addr) > 0) { + if (!(at = malloc(sizeof(struct gaih_addrtuple)))) + RETURN_ERROR(-EAI_MEMORY); + + memset(at, 0, sizeof(struct gaih_addrtuple)); + + at->family = AF_INET; + memcpy(at->addr, &in_addr, sizeof(struct in_addr)); + goto build; + }; + }; + +#if INET6 + if (!req->ai_family || (req->ai_family == AF_INET6)) { + struct in6_addr in6_addr; + if (inet_pton(AF_INET6, name, &in6_addr) > 0) { + if (!(at = malloc(sizeof(struct gaih_addrtuple)))) + RETURN_ERROR(-EAI_MEMORY); + + memset(at, 0, sizeof(struct gaih_addrtuple)); + + at->family = AF_INET6; + memcpy(at->addr, &in6_addr, sizeof(struct in6_addr)); + goto build; + }; + }; +#endif /* INET6 */ + + if (!(req->ai_flags & AI_NUMERICHOST)) { +#if NETDB +#if INET6 + if (!req->ai_family || (req->ai_family == AF_INET6)) + if ((rval = netdb_lookup_addr(name, AF_INET6, req, &at)) < 0) + goto ret; +#endif /* INET6 */ + if (!req->ai_family || (req->ai_family == AF_INET)) + if ((rval = netdb_lookup_addr(name, AF_INET, req, &at)) < 0) + goto ret; + + if (!rval) + goto build; +#else /* NETDB */ +#if HOSTTABLE + if ((rval = hosttable_lookup_addr(name, req, &at)) < 0) + goto ret; + + if (!rval) + goto build; +#endif /* HOSTTABLE */ + +#if RESOLVER +#if INET6 + { + int rval2; + + if (!req->ai_family || (req->ai_family == AF_INET6)) + if ((rval2 = resolver_lookup_addr(name, T_AAAA, req, &at)) < 0) { + rval = rval2; + goto ret; + }; +#endif /* INET6 */ + + if (!req->ai_family || (req->ai_family == AF_INET)) + if ((rval = resolver_lookup_addr(name, T_A, req, &at)) < 0) + goto ret; + +#if INET6 + if (!rval || !rval2) + goto build; + }; +#else /* INET6 */ + if (!rval) + goto build; +#endif /* INET6 */ +#endif /* RESOLVER */ +#endif /* NETDB */ + }; + + if (!at) + RETURN_ERROR(GAIH_OKIFUNSPEC | -EAI_NONAME); + +build: + { + char *prevcname = NULL; + struct gaih_servtuple *st2; + struct gaih_addrtuple *at2 = at; + int j; + + while(at2) { + if (req->ai_flags & AI_CANONNAME) { + if (at2->cname) + j = strlen(at2->cname) + 1; + else + if (name) + j = strlen(name) + 1; + else + j = 2; + } else + j = 0; + +#if INET6 + if (at2->family == AF_INET6) + i = sizeof(struct sockaddr_in6); + else +#endif /* INET6 */ + i = sizeof(struct sockaddr_in); + + st2 = st; + while(st2) { + if (!(*pai = malloc(sizeof(struct addrinfo) + i + j))) + RETURN_ERROR(-EAI_MEMORY); + + memset(*pai, 0, sizeof(struct addrinfo) + i + j); + + (*pai)->ai_flags = req->ai_flags; + (*pai)->ai_family = at2->family; + (*pai)->ai_socktype = st2->socktype; + (*pai)->ai_protocol = st2->protocol; + (*pai)->ai_addrlen = i; + (*pai)->ai_addr = (void *)(*pai) + sizeof(struct addrinfo); +#if SALEN + ((struct sockaddr_in *)(*pai)->ai_addr)->sin_len = i; +#endif /* SALEN */ + ((struct sockaddr_in *)(*pai)->ai_addr)->sin_family = at2->family; + ((struct sockaddr_in *)(*pai)->ai_addr)->sin_port = st2->port; + +#if INET6 + if (at2->family == AF_INET6) + memcpy(&((struct sockaddr_in6 *)(*pai)->ai_addr)->sin6_addr, at2->addr, sizeof(struct in6_addr)); + else +#endif /* INET6 */ + memcpy(&((struct sockaddr_in *)(*pai)->ai_addr)->sin_addr, at2->addr, sizeof(struct in_addr)); + + if (j) { + (*pai)->ai_canonname = (void *)(*pai) + sizeof(struct addrinfo) + i; + if (at2->cname) { + strcpy((*pai)->ai_canonname, at2->cname); + if (prevcname != at2->cname) { + if (prevcname) + free(prevcname); + prevcname = at2->cname; + }; + } else + strcpy((*pai)->ai_canonname, name ? name : "*"); + }; + + pai = &((*pai)->ai_next); + + st2 = st2->next; + }; + at2 = at2->next; + }; + }; + + rval = 0; + +ret: + if (st != &nullserv) { + struct gaih_servtuple *st2 = st; + while(st) { + st2 = st->next; + free(st); + st = st2; + } + } + if (at) { + struct gaih_addrtuple *at2 = at; + while(at) { + at2 = at->next; + free(at); + at = at2; + } + } + + return rval; +} + +struct gaih { + int family; + char *name; + int (*gaih)(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai); +}; + +static struct gaih gaih[] = { +#if INET6 + { PF_INET6, "inet6", gaih_inet }, +#endif /* INET6 */ + { PF_INET, "inet", gaih_inet }, +#if LOCAL + { PF_LOCAL, "local", gaih_local }, +#endif /* LOCAL */ + { -1, NULL, NULL } +}; + +#if DEBUG +static void dump_addrinfo(const struct addrinfo *ai, int follownext) +{ + char *c; + +loop: + fprintf(stderr, "addrinfo at "); + if (!ai) { + fprintf(stderr, "NULL\n"); + return; + }; + fprintf(stderr, "%08x:\n", (unsigned int)ai); + fprintf(stderr, " flags=%x(", ai->ai_flags); + c = ""; + if (ai->ai_flags & AI_PASSIVE) { + fprintf(stderr, "passive"); + c = " "; + }; + if (ai->ai_flags & AI_CANONNAME) { + fprintf(stderr, "%scanonname", c); + c = " "; + }; + if (ai->ai_flags & AI_NUMERICHOST) { + fprintf(stderr, "%snumerichost", c); + c = " "; + }; + if (ai->ai_flags & AI_EXT) { + fprintf(stderr, "%sext", c); + }; + fprintf(stderr, ")\n"); + fprintf(stderr, " family=%x(%s)\n", ai->ai_family, nrl_afnumtoname(ai->ai_family)); + fprintf(stderr, " socktype=%x(%s)\n", ai->ai_socktype, nrl_socktypenumtoname(ai->ai_socktype)); + fprintf(stderr, " protocol=%x\n", ai->ai_protocol); + fprintf(stderr, " addrlen=%x\n", ai->ai_addrlen); + fprintf(stderr, " addr=%08x", (unsigned int)ai->ai_addr); + if (ai->ai_addr) { + fprintf(stderr, ":\n"); +#if SALEN + fprintf(stderr, " len=%x\n", ai->ai_addr->sa_len); +#endif /* SALEN */ + fprintf(stderr, " family=%x(%s)\n", ai->ai_addr->sa_family, nrl_afnumtoname(ai->ai_addr->sa_family)); + fprintf(stderr, " data="); + +#if SALEN + if (ai->ai_addrlen != ai->ai_addr->sa_len) { + fprintf(stderr, " (addrlen != len, skipping)"); + } else +#endif /* SALEN */ + { + uint8_t *p; + int i; + + p = (uint8_t *)ai->ai_addr->sa_data; + i = ai->ai_addrlen - ((void *)ai->ai_addr->sa_data - (void *)ai->ai_addr); + while (i-- > 0) + fprintf(stderr, "%02x", *(p++)); + }; + }; + fprintf(stderr, "\n canonname=%08x", (unsigned int)ai->ai_canonname); + if (ai->ai_canonname) + fprintf(stderr, "(%s)", ai->ai_canonname); + fprintf(stderr, "\n next=%08x\n", (unsigned int)ai->ai_next); + + if (follownext && ai->ai_next) { + ai = ai->ai_next; + goto loop; + }; +}; +#endif /* DEBUG */ + +int getaddrinfo(const char *name, const char *service, + const struct addrinfo *req, struct addrinfo **pai) +{ + int rval = EAI_SYSTEM; /* XXX */ + int i, j = 0; + struct addrinfo *p = NULL, **end; + struct gaih *g = gaih, *pg = NULL; + struct gaih_service gaih_service, *pservice; + +#if DEBUG + if (DEBUG_MESSAGES) { + fprintf(stderr, "getaddrinfo(name=%s, service=%s, req=%p, pai=%p)\n req: ", name ? name : "NULL", service ? service : "NULL", req, pai); + + dump_addrinfo(req, 0); + }; +#endif /* DEBUG */ + + if (name && (name[0] == '*') && !name[1]) + name = NULL; + + if (service && (service[0] == '*') && !service[1]) + service = NULL; + +#if BROKEN_LIKE_POSIX + if (!name && !service && !(req.ai_flags & AI_EXT)) + RETURN_ERROR(EAI_NONAME); +#endif /* BROKEN_LIKE_POSIX */ + + if (!req) + req = &nullreq; + + if (req->ai_flags & ~(AI_CANONNAME | AI_PASSIVE | AI_NUMERICHOST | AI_EXT)) + RETURN_ERROR(EAI_BADFLAGS); + +#if BROKEN_LIKE_POSIX + if ((req->ai_flags & AI_CANONNAME) && !name && !(req.ai_flags & AI_EXT)) + RETURN_ERROR(EAI_BADFLAGS); +#endif /* BROKEN_LIKE_POSIX */ + + if (service && *service) { + char *c; + gaih_service.num = strtoul(gaih_service.name = (void *)service, &c, 10); + if (*c) { + gaih_service.num = -1; + } +#if BROKEN_LIKE_POSIX + else + if (!req->ai_socktype && !(req.ai_flags & AI_EXT)) + RETURN_ERROR(EAI_SERVICE); +#endif /* BROKEN_LIKE_POSIX */ + + pservice = &gaih_service; + } else + pservice = NULL; + + if (pai) + end = &p; + else + end = NULL; + + while(g->gaih) { + if ((req->ai_family == g->family) || !req->ai_family) { + j++; + if (!((pg && (pg->gaih == g->gaih)))) { + pg = g; + if (rval = g->gaih(name, pservice, req, end)) { + if (!req->ai_family && (rval & GAIH_OKIFUNSPEC)) + continue; + + if (p) + freeaddrinfo(p); + + rval = -(rval & GAIH_EAI); + goto ret; + } + if (end) + while(*end) end = &((*end)->ai_next); + } + } + g++; + } + + if (!j) + RETURN_ERROR(EAI_FAMILY); + + if (p) { + *pai = p; +#if DEBUG + if (DEBUG_MESSAGES) { + fprintf(stderr, "getaddrinfo: Success. *pai:\n"); + dump_addrinfo(p, 1); + }; +#endif /* DEBUG */ + rval = 0; + goto ret; + } + + if (!pai && !rval) { + rval = 0; + goto ret; + }; + + RETURN_ERROR(EAI_NONAME); + +ret: +#if DEBUG + if (DEBUG_MESSAGES) + fprintf(stderr, "getaddrinfo=%d\n", rval); +#endif /* DEBUG */ + return rval; +} + diff --git a/lib/libc/net/getnameinfo.c b/lib/libc/net/getnameinfo.c new file mode 100644 index 00000000000..15aa67d4648 --- /dev/null +++ b/lib/libc/net/getnameinfo.c @@ -0,0 +1,562 @@ +/* + * %%% 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: + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + */ + +/* getnameinfo() v1.38 */ + +/* To enable debugging support (REQUIRES NRL support library), define: */ +/* #define DEBUG 1 */ + +#ifdef __OpenBSD__ +#define HAVE_POSIX1G_TYPES 1 +#define INET6 1 +#define LOCAL 1 +#define NETDB 1 +#define SALEN 1 +#undef RESOLVER +#undef HOSTTABLE +#undef DEBUG +#undef HAVE_GETSERVBYNAME_R +#undef HAVE_GETHOSTBYNAME2_R +#endif /* __OpenBSD__ */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#if LOCAL +#include <sys/un.h> +#include <sys/utsname.h> +#endif /* LOCAL */ +#include <netdb.h> +#include <errno.h> +#include <string.h> +#if RESOLVER +#include <arpa/nameser.h> +#include <resolv.h> +#endif /* RESOLVER */ + +#include "support.h" + +#ifndef AF_LOCAL +#define AF_LOCAL AF_UNIX +#endif /* AF_LOCAL */ + +#ifndef min +#define min(x,y) (((x) > (y)) ? (y) : (x)) +#endif /* min */ + +#if DEBUG +#if RESOLVER +#define DEBUG_MESSAGES (_res.options & RES_DEBUG) +#else /* RESOLVER */ +int __getnameinfo_debug = 0; +#define DEBUG_MESSAGES (__getnameinfo_debug) +#endif /* RESOLVER */ +#endif /* DEBUG */ + +#if DEBUG +#define RETURN_ERROR(x) do { \ + if (DEBUG_MESSAGES) \ + fprintf(stderr, "%s:%d: returning %s\n", __FILE__, __LINE__, #x); \ + rval = (x); \ + goto ret; \ + } while(0) +#else /* DEBUG */ +#define RETURN_ERROR(x) do { \ + rval = (x); \ + goto ret; \ + } while(0) +#endif /* DEBUG */ + +#if HOSTTABLE +static int hosttable_lookup_name(int family, void *addr, char *name, int namelen, int flags) +{ + int rval; + FILE *f; + char buffer[1024]; + char addrbuf[16]; + char *c, *c2; + int i; + char *prevcname = NULL; + + if (!(f = fopen("/etc/hosts", "r"))) + RETURN_ERROR(EAI_SYSTEM); + + while(fgets(buffer, sizeof(buffer), f)) { + if (c = strchr(buffer, '#')) + *c = 0; + + c = buffer; + while(*c && !isspace(*c)) c++; + if (!*c) + continue; + + *(c++) = 0; + + if (family == AF_INET) + if (inet_pton(AF_INET, buffer, addrbuf) > 0) + if (!memcmp(addrbuf, addr, sizeof(struct in_addr))) + goto build; + +#if INET6 + if (family == AF_INET6) + if (inet_pton(AF_INET6, buffer, addrbuf) > 0) + if (!memcmp(addrbuf, addr, sizeof(struct in6_addr))) + goto build; +#endif /* INET6 */ + + continue; + +build: + while(*c && isspace(*c)) c++; + if (!*c) + continue; + + c2 = c; + while(*c2 && !isspace(*c2)) c2++; + if (!*c2) + continue; + *c2 = 0; + + 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; + goto ret; + }; + + RETURN_ERROR(1); + +ret: + fclose(f); + return rval; +}; +#endif /* HOSTTABLE */ + +#if RESOLVER +#if INET6 +static char hextab[] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; +#endif /* INET6 */ + +struct rrheader { + int16_t type; + int16_t class; + u_int32_t ttl; + int16_t size; +}; +#define RRHEADER_SZ 10 + +int resolver_lookup_name(const char *ptrname, char *name, int namelen, int flags) +{ + int rval; + char answer[PACKETSZ]; + int answerlen; + char dn[MAXDNAME]; + char *prevcname = NULL; + void *p, *ep; + int answers, i; + uint16_t rtype, rclass; + + if ((answerlen = res_search(ptrname, C_IN, T_PTR, answer, sizeof(answer))) < 0) { + 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); + }; + }; + + p = answer; + ep = answer + answerlen; + + if (answerlen < sizeof(HEADER)) + RETURN_ERROR(EAI_FAIL); + + { + HEADER *h = (HEADER *)p; + if (!h->qr || (h->opcode != QUERY) || (h->qdcount != htons(1)) || !h->ancount) + RETURN_ERROR(EAI_FAIL); + + answers = ntohs(h->ancount); + }; + p += sizeof(HEADER); + + if ((i = dn_expand(answer, ep, p, dn, sizeof(dn))) < 0) + RETURN_ERROR(EAI_FAIL); + + p += i; + + if (p + 2*sizeof(u_int16_t) >= ep) + RETURN_ERROR(EAI_FAIL); + + GETSHORT(rtype, p); + GETSHORT(rclass, p); + + if ((rtype != T_PTR) || (rclass != C_IN)) + RETURN_ERROR(EAI_FAIL); + + while(answers--) { + if ((i = dn_expand(answer, ep, p, dn, sizeof(dn))) < 0) + RETURN_ERROR(EAI_FAIL); + + p += i; + + if (p + RRHEADER_SZ >= ep) + RETURN_ERROR(EAI_FAIL); + + GETSHORT(rtype, p); + GETSHORT(rclass, p); + p += sizeof(uint32_t); + if (rclass != C_IN) + RETURN_ERROR(EAI_FAIL); + GETSHORT(rclass, p); + i = rclass; + + if (p + i > ep) + RETURN_ERROR(EAI_FAIL); + + if (rtype == T_PTR) { + if (dn_expand(answer, ep, p, dn, sizeof(dn)) != i) + RETURN_ERROR(EAI_FAIL); + + { + char *c2; + + if ((flags & NI_NOFQDN) && (_res.options & RES_INIT) && _res.defdname[0] && (c2 = strstr(dn + 1, _res.defdname)) && (*(--c2) == '.')) { + *c2 = 0; + strncpy(name, dn, min(c2 - dn, namelen) - 1); + } else + strncpy(name, dn, namelen - 1); + }; + }; + p += i; + }; + + rval = 0; + +ret: + return rval; +}; +#endif /* RESOLVER */ + +#if NETDB +static int netdb_lookup_name(int family, void *addr, int addrlen, char *name, + int namelen) +{ + 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; + +ret: + return rval; +} +#endif /* NETDB */ + +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) { +#if INET6 + 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)); +#if SALEN + sin.sin_len = sizeof(struct sockaddr_in); +#endif /* SALEN */ + 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 HOSTTABLE + if ((rval = hosttable_lookup_name(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr, host, hostlen, flags)) < 0) + goto ret; + + if (!rval) + break; +#endif /* HOSTTABLE */ +#if RESOLVER + { + char ptrname[sizeof("0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.int.")]; + { + int i; + char *c = ptrname; + u_int8_t *p = (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr + sizeof(struct in6_addr) - 1; + + for (i = sizeof(struct in6_addr) / sizeof(u_int8_t); i > 0; i--, p--) { + *(c++) = hextab[*p & 0x0f]; + *(c++) = '.'; + *(c++) = hextab[(*p & 0xf0) >> 4]; + *(c++) = '.'; + }; + strcpy(c, "ip6.int."); + }; + + if ((rval = resolver_lookup_name(ptrname, host, hostlen, flags)) < 0) + goto ret; + + if (!rval) + break; + }; +#endif /* RESOLVER */ + +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; +#endif /* INET6 */ + 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 HOSTTABLE + if ((rval = hosttable_lookup_name(AF_INET, &((struct sockaddr_in *)sa)->sin_addr, host, hostlen, flags)) < 0) + goto ret; + + if (!rval) + break; +#endif /* HOSTTABLE */ +#if RESOLVER + { + char ptrname[30]; + u_int8_t *p = (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr; + sprintf(ptrname, "%d.%d.%d.%d.in-addr.arpa.", p[3], p[2], p[1], p[0]); + + if ((rval = resolver_lookup_name(ptrname, host, hostlen, flags)) < 0) + goto ret; + + if (!rval) + break; + }; +#endif /* RESOLVER */ + +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; +#if LOCAL + 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; +#endif /* LOCAL */ + default: + RETURN_ERROR(EAI_FAMILY); + }; + + if (serv && (servlen > 0)) + switch(sa->sa_family) { + case AF_INET: +#if INET6 + case AF_INET6: +#endif /* 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; +#if LOCAL + case AF_LOCAL: + strncpy(serv, ((struct sockaddr_un *)sa)->sun_path, servlen - 1); + break; +#endif /* LOCAL */ + }; + + if (host && (hostlen > 0)) + host[hostlen-1] = 0; + if (serv && (servlen > 0)) + serv[servlen-1] = 0; + rval = 0; + +ret: + if (rval == 1) + rval = EAI_FAIL; + + errno = serrno; + + return rval; +}; diff --git a/lib/libc/net/if_indextoname.c b/lib/libc/net/if_indextoname.c new file mode 100644 index 00000000000..ff7fcada915 --- /dev/null +++ b/lib/libc/net/if_indextoname.c @@ -0,0 +1,181 @@ +/* + * %%% copyright-cmetz-98-bsd + * Copyright (c) 1998-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: + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + */ + +#include <sys/types.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <net/if.h> +#ifdef AF_LINK +#include <net/if_dl.h> +#endif /* AF_LINK */ +#include <errno.h> + +static char __name[IFNAMSIZ + 1]; + +char *if_indextoname(unsigned int index, char *name) +{ + int i, fd; +#ifdef SIOCGIFNAME + struct ifreq ifreq; +#else /* SIOCGIFNAME */ + struct ifconf ifconf; + void *p; + int len; + char lastname[IFNAMSIZ + 1]; + char iname[IFNAMSIZ + 1]; + char *retname = NULL; +#endif /* SIOCGIFNAME */ + + if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) + return 0; + + if (!name) + name = __name; + +#ifdef SIOCGIFNAME + ifreq.ifr_ifindex = index; + i = ioctl(fd, SIOCGIFNAME, &ifreq); + close(fd); + if (i) + return NULL; + + strcpy(name, ifreq.ifr_name); + return name; +#else /* SIOCGIFNAME */ + if (__siocgifconf(fd, &ifconf)) { + close(fd); + return NULL; + }; + + i = 0; + p = ifconf.ifc_buf; + len = ifconf.ifc_len; + lastname[0] = 0; + lastname[IFNAMSIZ] = 0; + iname[0] = 0; + + while(len > 0) { + if (len < (IFNAMSIZ + sizeof(struct sockaddr))) + goto ret; + if (strncmp(lastname, p, IFNAMSIZ)) { + if (i == index) + strcpy(iname, lastname); + memcpy(lastname, p, IFNAMSIZ); + i++; + }; + len -= IFNAMSIZ; + p += IFNAMSIZ; + +#ifdef AF_LINK + if (((struct sockaddr *)p)->sa_family == AF_LINK) + if (((struct sockaddr_dl *)p)->sdl_index == index) { + strcpy(retname = name, lastname); + goto ret; + }; +#endif /* AF_LINK */ + + if (len < SA_LEN((struct sockaddr *)p)) + goto ret; + len -= SA_LEN((struct sockaddr *)p); + p += SA_LEN((struct sockaddr *)p); + }; + + if (i == index) + strcpy(iname, lastname); + + if (iname[0]) + strcpy(retname = name, iname); + +ret: + close(fd); + free(ifconf.ifc_buf); + return retname; +#endif /* SIOCGIFNAME */ +}; diff --git a/lib/libc/net/if_indextoname.o b/lib/libc/net/if_indextoname.o Binary files differnew file mode 100644 index 00000000000..332c550d58a --- /dev/null +++ b/lib/libc/net/if_indextoname.o diff --git a/lib/libc/net/if_nameindex.c b/lib/libc/net/if_nameindex.c new file mode 100644 index 00000000000..65bdbde9af7 --- /dev/null +++ b/lib/libc/net/if_nameindex.c @@ -0,0 +1,212 @@ +/* + * %%% copyright-cmetz-98-bsd + * Copyright (c) 1998-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: + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + */ + +#include <stdlib.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <net/if.h> +#ifdef AF_LINK +#include <net/if_dl.h> +#endif /* AF_LINK */ +#include <errno.h> + +struct if_nameindex *if_nameindex(void) +{ + int i, j, fd; + struct if_nameindex *nameindex = NULL; + struct ifconf ifconf; + void *p; + int len; + char lastname[IFNAMSIZ + 1]; + + if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) + return NULL; + + if (__siocgifconf(fd, &ifconf)) { + close(fd); + return NULL; + }; + + i = sizeof(struct if_nameindex); + j = 0; + p = ifconf.ifc_buf; + len = ifconf.ifc_len; + lastname[0] = 0; + lastname[IFNAMSIZ] = 0; + + while(len > 0) { + if (len < (IFNAMSIZ + sizeof(struct sockaddr))) + goto ret; + if (strncmp(lastname, p, IFNAMSIZ)) { + memcpy(lastname, p, IFNAMSIZ); + i += sizeof(struct if_nameindex); + j += strlen(lastname) + 1; + }; + len -= IFNAMSIZ; + p += IFNAMSIZ; + + if (len < SA_LEN((struct sockaddr *)p)) + goto ret; + len -= SA_LEN((struct sockaddr *)p); + p += SA_LEN((struct sockaddr *)p); + }; + + if (!(nameindex = malloc(i + j))) { + errno = ENOMEM; + goto ret; + }; + memset(nameindex, 0, i + j); + + { +#ifdef SIOCGIFINDEX + struct ifreq ifreq; +#endif /* SIOCGIFINDEX */ + struct if_nameindex *n; + char *c; + + n = nameindex; + p = ifconf.ifc_buf; + c = (void *)nameindex + i; + i = 0; + len = ifconf.ifc_len; + lastname[0] = 0; + + while(len > 0) { + if (len < (IFNAMSIZ + sizeof(struct sockaddr))) + goto ret; + if (strncmp(lastname, p, IFNAMSIZ)) { + if (i) { + if (!n->if_index) { +#ifdef SIOCGIFINDEX + strcpy(ifreq.ifr_name, lastname); + if (ioctl(fd, SIOCGIFINDEX, &ifreq)) + goto ret; + n->if_index = ifreq.ifr_ifindex; +#else /* SIOCGIFINDEX */ + n->if_index = i; +#endif /* SIOCGIFINDEX */ + }; + n++; + }; + i++; + memcpy(lastname, p, IFNAMSIZ); + strcpy(n->if_name = c, lastname); + c += strlen(c) + 1; + }; + len -= IFNAMSIZ; + p += IFNAMSIZ; + + if (len < SA_LEN((struct sockaddr *)p)) + goto ret; +#ifdef AF_LINK + if (((struct sockaddr *)p)->sa_family == AF_LINK) + n->if_index = ((struct sockaddr_dl *)p)->sdl_index; +#endif /* AF_LINK */ + len -= SA_LEN((struct sockaddr *)p); + p += SA_LEN((struct sockaddr *)p); + }; + + if (!n->if_index) { +#ifdef SIOCGIFINDEX + strcpy(ifreq.ifr_name, lastname); + if (ioctl(fd, SIOCGIFINDEX, &ifreq)) + goto ret; + n->if_index = ifreq.ifr_ifindex; +#else /* SIOCGIFINDEX */ + n->if_index = i; +#endif /* SIOCGIFINDEX */ + }; + }; + +ret: + close(fd); + free(ifconf.ifc_buf); + return nameindex; +}; diff --git a/lib/libc/net/if_nameindex.o b/lib/libc/net/if_nameindex.o Binary files differnew file mode 100644 index 00000000000..65fba476f2d --- /dev/null +++ b/lib/libc/net/if_nameindex.o diff --git a/lib/libc/net/if_nametoindex.c b/lib/libc/net/if_nametoindex.c new file mode 100644 index 00000000000..8ec2b233d19 --- /dev/null +++ b/lib/libc/net/if_nametoindex.c @@ -0,0 +1,173 @@ +/* + * %%% copyright-cmetz-98-bsd + * Copyright (c) 1998-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: + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Craig Metz and + * by other contributors. + * 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 + * 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. + */ + +#include <sys/types.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <net/if.h> +#ifdef AF_LINK +#include <net/if_dl.h> +#endif /* AF_LINK */ +#include <errno.h> + +unsigned int if_nametoindex(const char *name) +{ + int i, fd; +#ifdef SIOCGIFINDEX + struct ifreq ifreq; +#else /* SIOCGIFINDEX */ + struct ifconf ifconf; + void *p; + int len; + char lastname[IFNAMSIZ + 1], *thisname; + unsigned int index = 0; +#endif /* SIOCGIFINDEX */ + + if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) + return 0; + +#ifdef SIOCGIFINDEX + strcpy(ifreq.ifr_name, name); + i = ioctl(fd, SIOCGIFINDEX, &ifreq); + close(fd); + if (i) + return 0; + + return ifreq.ifr_ifindex; +#else /* SIOCGIFINDEX */ + if (__siocgifconf(fd, &ifconf)) { + close(fd); + return 0; + }; + + i = 0; + p = ifconf.ifc_buf; + len = ifconf.ifc_len; + lastname[0] = 0; + lastname[IFNAMSIZ] = 0; + + while(len > 0) { + if (len < (IFNAMSIZ + sizeof(struct sockaddr))) + goto ret; + + if (strncmp(lastname, thisname = p, IFNAMSIZ)) { + if (!strcmp(lastname, name)) { + index = i; + goto ret; + }; + memcpy(lastname, thisname, IFNAMSIZ); + i++; + }; + + len -= IFNAMSIZ; + p += IFNAMSIZ; + +#ifdef AF_LINK + if (!strncmp(thisname, name, IFNAMSIZ) && (((struct sockaddr *)p)->sa_family == AF_LINK)) { + index = ((struct sockaddr_dl *)p)->sdl_index; + goto ret; + }; +#endif /* AF_LINK */ + + if (len < SA_LEN((struct sockaddr *)p)) + goto ret; + len -= SA_LEN((struct sockaddr *)p); + p += SA_LEN((struct sockaddr *)p); + }; + + if (!strcmp(lastname, name)) + index = i; + +ret: + close(fd); + free(ifconf.ifc_buf); + return index; +#endif /* SIOCGIFINDEX */ +}; diff --git a/lib/libc/net/if_nametoindex.o b/lib/libc/net/if_nametoindex.o Binary files differnew file mode 100644 index 00000000000..910d2b4861a --- /dev/null +++ b/lib/libc/net/if_nametoindex.o |