diff options
Diffstat (limited to 'contrib/ntp/libisc')
-rw-r--r-- | contrib/ntp/libisc/assertions.c | 93 | ||||
-rw-r--r-- | contrib/ntp/libisc/error.c | 101 | ||||
-rw-r--r-- | contrib/ntp/libisc/ifiter_ioctl.c | 820 | ||||
-rw-r--r-- | contrib/ntp/libisc/ifiter_sysctl.c | 305 | ||||
-rw-r--r-- | contrib/ntp/libisc/inet_ntop.c | 198 | ||||
-rw-r--r-- | contrib/ntp/libisc/interfaceiter.c | 159 | ||||
-rw-r--r-- | contrib/ntp/libisc/isc_strerror.c | 74 | ||||
-rw-r--r-- | contrib/ntp/libisc/lib.c | 77 | ||||
-rw-r--r-- | contrib/ntp/libisc/mem.c | 42 | ||||
-rw-r--r-- | contrib/ntp/libisc/msgcat.c | 130 | ||||
-rw-r--r-- | contrib/ntp/libisc/net.c | 123 | ||||
-rw-r--r-- | contrib/ntp/libisc/strerror.c | 72 |
12 files changed, 2194 insertions, 0 deletions
diff --git a/contrib/ntp/libisc/assertions.c b/contrib/ntp/libisc/assertions.c new file mode 100644 index 0000000..08dd5f3 --- /dev/null +++ b/contrib/ntp/libisc/assertions.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 1997-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: assertions.c,v 1.16 2001/07/16 03:52:05 mayer Exp $ */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> + +#include <isc/assertions.h> +#include <isc/msgs.h> + +/* + * Forward. + */ + +static void +default_callback(const char *, int, isc_assertiontype_t, const char *); + +/* + * Public. + */ + +LIBISC_EXTERNAL_DATA isc_assertioncallback_t isc_assertion_failed = + default_callback; + +void +isc_assertion_setcallback(isc_assertioncallback_t cb) { + if (cb == NULL) + isc_assertion_failed = default_callback; + else + isc_assertion_failed = cb; +} + +const char * +isc_assertion_typetotext(isc_assertiontype_t type) { + const char *result; + + /* + * These strings have purposefully not been internationalized + * because they are considered to essentially be keywords of + * the ISC development environment. + */ + switch (type) { + case isc_assertiontype_require: + result = "REQUIRE"; + break; + case isc_assertiontype_ensure: + result = "ENSURE"; + break; + case isc_assertiontype_insist: + result = "INSIST"; + break; + case isc_assertiontype_invariant: + result = "INVARIANT"; + break; + default: + result = NULL; + } + return (result); +} + +/* + * Private. + */ + +static void +default_callback(const char *file, int line, isc_assertiontype_t type, + const char *cond) +{ + fprintf(stderr, "%s:%d: %s(%s) %s.\n", + file, line, isc_assertion_typetotext(type), cond, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); + fflush(stderr); + abort(); + /* NOTREACHED */ +} diff --git a/contrib/ntp/libisc/error.c b/contrib/ntp/libisc/error.c new file mode 100644 index 0000000..ed0469d --- /dev/null +++ b/contrib/ntp/libisc/error.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 1998-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: error.c,v 1.16 2001/08/08 22:54:49 gson Exp $ */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> + +#include <isc/error.h> +#include <isc/msgs.h> + +static void +default_unexpected_callback(const char *, int, const char *, va_list) + ISC_FORMAT_PRINTF(3, 0); + +static void +default_fatal_callback(const char *, int, const char *, va_list) + ISC_FORMAT_PRINTF(3, 0); + +static isc_errorcallback_t unexpected_callback = default_unexpected_callback; +static isc_errorcallback_t fatal_callback = default_fatal_callback; + +void +isc_error_setunexpected(isc_errorcallback_t cb) { + if (cb == NULL) + unexpected_callback = default_unexpected_callback; + else + unexpected_callback = cb; +} + +void +isc_error_setfatal(isc_errorcallback_t cb) { + if (cb == NULL) + fatal_callback = default_fatal_callback; + else + fatal_callback = cb; +} + +void +isc_error_unexpected(const char *file, int line, const char *format, ...) { + va_list args; + + va_start(args, format); + (unexpected_callback)(file, line, format, args); + va_end(args); +} + +void +isc_error_fatal(const char *file, int line, const char *format, ...) { + va_list args; + + va_start(args, format); + (fatal_callback)(file, line, format, args); + va_end(args); + abort(); +} + +void +isc_error_runtimecheck(const char *file, int line, const char *expression) { + isc_error_fatal(file, line, "RUNTIME_CHECK(%s) %s", expression, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); +} + +static void +default_unexpected_callback(const char *file, int line, const char *format, + va_list args) +{ + fprintf(stderr, "%s:%d: ", file, line); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + fflush(stderr); +} + +static void +default_fatal_callback(const char *file, int line, const char *format, + va_list args) +{ + fprintf(stderr, "%s:%d: %s: ", file, line, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FATALERROR, "fatal error")); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + fflush(stderr); +} diff --git a/contrib/ntp/libisc/ifiter_ioctl.c b/contrib/ntp/libisc/ifiter_ioctl.c new file mode 100644 index 0000000..bf731e7 --- /dev/null +++ b/contrib/ntp/libisc/ifiter_ioctl.c @@ -0,0 +1,820 @@ +/* + * Copyright (C) 1999-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: ifiter_ioctl.c,v 1.34 2002/08/16 00:05:57 marka Exp $ */ + +/* + * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl. + * See netintro(4). + */ + +#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) +#ifdef ISC_PLATFORM_HAVEIF_LADDRCONF +#define lifc_len iflc_len +#define lifc_buf iflc_buf +#define lifc_req iflc_req +#define LIFCONF if_laddrconf +#else +#define ISC_HAVE_LIFC_FAMILY 1 +#define ISC_HAVE_LIFC_FLAGS 1 +#define LIFCONF lifconf +#endif + +#ifdef ISC_PLATFORM_HAVEIF_LADDRREQ +#define lifr_addr iflr_addr +#define lifr_name iflr_name +#define lifr_dstaddr iflr_dstaddr +#define lifr_broadaddr iflr_broadaddr +#define lifr_flags iflr_flags +#define ss_family sa_family +#define LIFREQ if_laddrreq +#else +#define LIFREQ lifreq +#endif +#endif + +#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T') +#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) + +struct isc_interfaceiter { + unsigned int magic; /* Magic number. */ + isc_mem_t *mctx; + int socket; + int mode; + struct ifconf ifc; +#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) + struct LIFCONF lifc; +#endif + void *buf; /* Buffer for sysctl data. */ + unsigned int bufsize; /* Bytes allocated. */ +#ifdef HAVE_TRUCLUSTER + int clua_context; /* Cluster alias context */ +#endif + unsigned int pos; /* Current offset in + SIOCGLIFCONF data */ + isc_interface_t current; /* Current interface data. */ + isc_result_t result; /* Last result code. */ +}; + +#ifdef HAVE_TRUCLUSTER +#include <clua/clua.h> +#include <sys/socket.h> +#endif + + +/* + * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system + * will have more than a megabyte of interface configuration data. + */ +#define IFCONF_BUFSIZE_INITIAL 4096 +#define IFCONF_BUFSIZE_MAX 1048576 + +static isc_result_t +getbuf4(isc_interfaceiter_t *iter) { + char strbuf[ISC_STRERRORSIZE]; + + iter->bufsize = IFCONF_BUFSIZE_INITIAL; + + for (;;) { + iter->buf = isc_mem_get(iter->mctx, iter->bufsize); + if (iter->buf == NULL) + return (ISC_R_NOMEMORY); + + memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len)); + iter->ifc.ifc_len = iter->bufsize; + iter->ifc.ifc_buf = iter->buf; + /* + * Ignore the HP/UX warning about "integer overflow during + * conversion". It comes from its own macro definition, + * and is really hard to shut up. + */ + if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc) + == -1) { + if (errno != EINVAL) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERIOCTL, + ISC_MSG_GETIFCONFIG, + "get interface " + "configuration: %s"), + strbuf); + goto unexpected; + } + /* + * EINVAL. Retry with a bigger buffer. + */ + } else { + /* + * The ioctl succeeded. + * Some OS's just return what will fit rather + * than set EINVAL if the buffer is too small + * to fit all the interfaces in. If + * ifc.lifc_len is too near to the end of the + * buffer we will grow it just in case and + * retry. + */ + if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq) + < iter->bufsize) + break; + } + if (iter->bufsize >= IFCONF_BUFSIZE_MAX) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERIOCTL, + ISC_MSG_BUFFERMAX, + "get interface " + "configuration: " + "maximum buffer " + "size exceeded")); + goto unexpected; + } + isc_mem_put(iter->mctx, iter->buf, iter->bufsize); + + iter->bufsize *= 2; + } + iter->mode = 4; + return (ISC_R_SUCCESS); + + unexpected: + isc_mem_put(iter->mctx, iter->buf, iter->bufsize); + iter->buf = NULL; + return (ISC_R_UNEXPECTED); +} + +static isc_result_t +getbuf6(isc_interfaceiter_t *iter) { +#if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR) + UNUSED(iter); + return (ISC_R_NOTIMPLEMENTED); +#else + char strbuf[ISC_STRERRORSIZE]; + isc_result_t result; + + iter->bufsize = IFCONF_BUFSIZE_INITIAL; + + for (;;) { + iter->buf = isc_mem_get(iter->mctx, iter->bufsize); + if (iter->buf == NULL) + return (ISC_R_NOMEMORY); + + memset(&iter->lifc.lifc_len, 0, sizeof(iter->lifc.lifc_len)); +#ifdef ISC_HAVE_LIFC_FAMILY + iter->lifc.lifc_family = AF_UNSPEC; +#endif +#ifdef ISC_HAVE_LIFC_FLAGS + iter->lifc.lifc_flags = 0; +#endif + iter->lifc.lifc_len = iter->bufsize; + iter->lifc.lifc_buf = iter->buf; + /* + * Ignore the HP/UX warning about "integer overflow during + * conversion". It comes from its own macro definition, + * and is really hard to shut up. + */ + if (ioctl(iter->socket, SIOCGLIFCONF, (char *)&iter->lifc) + == -1) { +#ifdef __hpux + /* + * IPv6 interface scanning is not available on all + * kernels w/ IPv6 sockets. + */ + if (errno == ENOENT) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERIOCTL, + ISC_MSG_GETIFCONFIG, + "get interface " + "configuration: %s"), + strbuf); + result = ISC_R_FAILURE; + goto cleanup; + } +#endif + if (errno != EINVAL) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERIOCTL, + ISC_MSG_GETIFCONFIG, + "get interface " + "configuration: %s"), + strbuf); + result = ISC_R_UNEXPECTED; + goto cleanup; + } + /* + * EINVAL. Retry with a bigger buffer. + */ + } else { + /* + * The ioctl succeeded. + * Some OS's just return what will fit rather + * than set EINVAL if the buffer is too small + * to fit all the interfaces in. If + * ifc.ifc_len is too near to the end of the + * buffer we will grow it just in case and + * retry. + */ + if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ) + < iter->bufsize) + break; + } + if (iter->bufsize >= IFCONF_BUFSIZE_MAX) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERIOCTL, + ISC_MSG_BUFFERMAX, + "get interface " + "configuration: " + "maximum buffer " + "size exceeded")); + result = ISC_R_UNEXPECTED; + goto cleanup; + } + isc_mem_put(iter->mctx, iter->buf, iter->bufsize); + + iter->bufsize *= 2; + } + + iter->mode = 6; + return (ISC_R_SUCCESS); + + cleanup: + isc_mem_put(iter->mctx, iter->buf, iter->bufsize); + iter->buf = NULL; + return (result); +#endif +} + +isc_result_t +isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { + isc_interfaceiter_t *iter; + isc_result_t result; + char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(iterp != NULL); + REQUIRE(*iterp == NULL); + + iter = isc_mem_get(mctx, sizeof(*iter)); + if (iter == NULL) + return (ISC_R_NOMEMORY); + + iter->mctx = mctx; + iter->buf = NULL; + iter->mode = 0; + + /* + * Create an unbound datagram socket to do the SIOCGLIFADDR ioctl on. + */ + if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERIOCTL, + ISC_MSG_MAKESCANSOCKET, + "making interface " + "scan socket: %s"), + strbuf); + result = ISC_R_UNEXPECTED; + goto socket_failure; + } + + /* + * Get the interface configuration, allocating more memory if + * necessary. + */ + + result = isc_net_probeipv6(); + if (result == ISC_R_SUCCESS) + result = getbuf6(iter); + if (result != ISC_R_SUCCESS) + result = getbuf4(iter); + if (result != ISC_R_SUCCESS) + goto ioctl_failure; + + /* + * A newly created iterator has an undefined position + * until isc_interfaceiter_first() is called. + */ +#ifdef HAVE_TRUCLUSTER + iter->clua_context = -1; +#endif + iter->pos = (unsigned int) -1; + iter->result = ISC_R_FAILURE; + + iter->magic = IFITER_MAGIC; + *iterp = iter; + return (ISC_R_SUCCESS); + + ioctl_failure: + if (iter->buf != NULL) + isc_mem_put(mctx, iter->buf, iter->bufsize); + (void) close(iter->socket); + + socket_failure: + isc_mem_put(mctx, iter, sizeof(*iter)); + return (result); +} + +#ifdef HAVE_TRUCLUSTER +static void +get_inaddr(isc_netaddr_t *dst, struct in_addr *src) { + dst->family = AF_INET; + memcpy(&dst->type.in, src, sizeof(struct in_addr)); +} + +static isc_result_t +internal_current_clusteralias(isc_interfaceiter_t *iter) { + struct sockaddr sa; + struct clua_info ci; + while (clua_getaliasaddress(&sa, &iter->clua_context) == CLUA_SUCCESS) { + if (clua_getaliasinfo(&sa, &ci) != CLUA_SUCCESS) + continue; + memset(&iter->current, 0, sizeof(iter->current)); + iter->current.af = sa.sa_family; + memset(iter->current.name, 0, sizeof(iter->current.name)); + sprintf(iter->current.name, "clua%d", ci.aliasid); + iter->current.flags = INTERFACE_F_UP; + get_inaddr(&iter->current.address, &ci.addr); + get_inaddr(&iter->current.netmask, &ci.netmask); + return (ISC_R_SUCCESS); + } + return (ISC_R_NOMORE); +} +#endif + +/* + * Get information about the current interface to iter->current. + * If successful, return ISC_R_SUCCESS. + * If the interface has an unsupported address family, or if + * some operation on it fails, return ISC_R_IGNORE to make + * the higher-level iterator code ignore it. + */ + +static isc_result_t +internal_current4(isc_interfaceiter_t *iter) { + struct ifreq *ifrp; + struct ifreq ifreq; + int family; + char strbuf[ISC_STRERRORSIZE]; +#if !defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) + struct if_laddrreq if_laddrreq; + int i, bits; +#endif + + REQUIRE(VALID_IFITER(iter)); + REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len); + + ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos); + + memset(&ifreq, 0, sizeof(ifreq)); + memcpy(&ifreq, ifrp, sizeof(ifreq)); + + family = ifreq.ifr_addr.sa_family; +#if !defined (SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \ + defined(ISC_PLATFORM_HAVEIPV6) + if (family != AF_INET && family != AF_INET6) +#else + if (family != AF_INET) +#endif + return (ISC_R_IGNORE); + + memset(&iter->current, 0, sizeof(iter->current)); + iter->current.af = family; + + INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name)); + memset(iter->current.name, 0, sizeof(iter->current.name)); + memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name)); + + get_addr(family, &iter->current.address, + (struct sockaddr *)&ifrp->ifr_addr); + + /* + * If the interface does not have a address ignore it. + */ + switch (family) { + case AF_INET: + if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) + return (ISC_R_IGNORE); + break; + case AF_INET6: + if (memcmp(&iter->current.address.type.in6, &in6addr_any, + sizeof(in6addr_any)) == 0) + return (ISC_R_IGNORE); + break; + } + + /* + * Get interface flags. + */ + + iter->current.flags = 0; + + /* + * Ignore the HP/UX warning about "integer overflow during + * conversion. It comes from its own macro definition, + * and is really hard to shut up. + */ + if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "%s: getting interface flags: %s", + ifreq.ifr_name, strbuf); + return (ISC_R_IGNORE); + } + + if ((ifreq.ifr_flags & IFF_UP) != 0) + iter->current.flags |= INTERFACE_F_UP; + + if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0) + iter->current.flags |= INTERFACE_F_POINTTOPOINT; + + if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0) + iter->current.flags |= INTERFACE_F_LOOPBACK; + + if ((ifreq.ifr_flags & IFF_BROADCAST) != 0) { + iter->current.flags |= INTERFACE_F_BROADCAST; + } + +#ifdef IFF_MULTICAST + if ((ifreq.ifr_flags & IFF_MULTICAST) != 0) { + iter->current.flags |= INTERFACE_F_MULTICAST; + } +#endif + +#if !defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) + if (family == AF_INET) + goto inet; + + memset(&if_laddrreq, 0, sizeof(if_laddrreq)); + memcpy(if_laddrreq.iflr_name, iter->current.name, + sizeof(if_laddrreq.iflr_name)); + memcpy(&if_laddrreq.addr, &iter->current.address.type.in6, + sizeof(iter->current.address.type.in6)); + + if (ioctl(iter->socket, SIOCGLIFADDR, &if_laddrreq) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "%s: getting interface address: %s", + ifreq.ifr_name, strbuf); + return (ISC_R_IGNORE); + } + + /* + * Netmask already zeroed. + */ + iter->current.netmask.family = family; + for (i = 0; i < 16; i++) { + if (if_laddrreq.prefixlen > 8) { + bits = 0; + if_laddrreq.prefixlen -= 8; + } else { + bits = 8 - if_laddrreq.prefixlen; + if_laddrreq.prefixlen = 0; + } + iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff; + } + return (ISC_R_SUCCESS); + + inet: +#endif + if (family != AF_INET) + return (ISC_R_IGNORE); + /* + * If the interface is point-to-point, get the destination address. + */ + if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { + /* + * Ignore the HP/UX warning about "integer overflow during + * conversion. It comes from its own macro definition, + * and is really hard to shut up. + */ + if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq) + < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERIOCTL, + ISC_MSG_GETDESTADDR, + "%s: getting " + "destination address: %s"), + ifreq.ifr_name, strbuf); + return (ISC_R_IGNORE); + } + get_addr(family, &iter->current.dstaddress, + (struct sockaddr *)&ifreq.ifr_dstaddr); + } + + if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) { + /* + * Ignore the HP/UX warning about "integer overflow during + * conversion. It comes from its own macro definition, + * and is really hard to shut up. + */ + if (ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq) + < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERIOCTL, + ISC_MSG_GETDESTADDR, + "%s: getting " + "broadcast address: %s"), + ifreq.ifr_name, strbuf); + return (ISC_R_IGNORE); + } + get_addr(family, &iter->current.broadcast, + (struct sockaddr *)&ifreq.ifr_broadaddr); + } + /* + * Get the network mask. + */ + memset(&ifreq, 0, sizeof(ifreq)); + memcpy(&ifreq, ifrp, sizeof(ifreq)); + /* + * Ignore the HP/UX warning about "integer overflow during + * conversion. It comes from its own macro definition, + * and is really hard to shut up. + */ + if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) + < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERIOCTL, + ISC_MSG_GETNETMASK, + "%s: getting netmask: %s"), + ifreq.ifr_name, strbuf); + return (ISC_R_IGNORE); + } + get_addr(family, &iter->current.netmask, + (struct sockaddr *)&ifreq.ifr_addr); + return (ISC_R_SUCCESS); +} + +static isc_result_t +internal_current6(isc_interfaceiter_t *iter) { +#if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR) + UNUSED(iter); + return (ISC_R_NOTIMPLEMENTED); +#else + struct LIFREQ *ifrp; + struct LIFREQ lifreq; + int family; + char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(VALID_IFITER(iter)); + REQUIRE (iter->pos < (unsigned int) iter->lifc.lifc_len); + + ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos); + + memset(&lifreq, 0, sizeof(lifreq)); + memcpy(&lifreq, ifrp, sizeof(lifreq)); + + family = lifreq.lifr_addr.ss_family; +#ifdef ISC_PLATFORM_HAVEIPV6 + if (family != AF_INET && family != AF_INET6) +#else + if (family != AF_INET) +#endif + return (ISC_R_IGNORE); + + memset(&iter->current, 0, sizeof(iter->current)); + iter->current.af = family; + + INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name)); + memset(iter->current.name, 0, sizeof(iter->current.name)); + memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name)); + + get_addr(family, &iter->current.address, + (struct sockaddr *)&lifreq.lifr_addr); + + /* + * If the interface does not have a address ignore it. + */ + switch (family) { + case AF_INET: + if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) + return (ISC_R_IGNORE); + break; + case AF_INET6: + if (memcmp(&iter->current.address.type.in6, &in6addr_any, + sizeof(in6addr_any)) == 0) + return (ISC_R_IGNORE); + break; + } + + /* + * Get interface flags. + */ + + iter->current.flags = 0; + + /* + * Ignore the HP/UX warning about "integer overflow during + * conversion. It comes from its own macro definition, + * and is really hard to shut up. + */ + if (ioctl(iter->socket, SIOCGLIFFLAGS, (char *) &lifreq) < 0) { + + /* + * XXX This should be looked at further since it looks strange. + * If we get an ENXIO then we ignore the error and not worry + * about the flags. + */ + if (errno != ENXIO) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "%s: getting interface flags: %s", + lifreq.lifr_name, strbuf); + return (ISC_R_IGNORE); + } + } + + if ((lifreq.lifr_flags & IFF_UP) != 0) + iter->current.flags |= INTERFACE_F_UP; + + if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0) + iter->current.flags |= INTERFACE_F_POINTTOPOINT; + + if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0) + iter->current.flags |= INTERFACE_F_LOOPBACK; + + /* + * Note that IPv6 broadcast does not exist + * so don't check for IPv6 broadcast flag + */ + +#ifdef IFF_MULTICAST + if ((lifreq.lifr_flags & IFF_MULTICAST) != 0) { + iter->current.flags |= INTERFACE_F_MULTICAST; + } +#endif + + /* + * If the interface is point-to-point, get the destination address. + */ + if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { + /* + * Ignore the HP/UX warning about "interger overflow during + * conversion. It comes from its own macro definition, + * and is really hard to shut up. + */ + if (ioctl(iter->socket, SIOCGLIFDSTADDR, (char *)&lifreq) + < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERIOCTL, + ISC_MSG_GETDESTADDR, + "%s: getting " + "destination address: %s"), + lifreq.lifr_name, strbuf); + return (ISC_R_IGNORE); + } + get_addr(family, &iter->current.dstaddress, + (struct sockaddr *)&lifreq.lifr_dstaddr); + } + + + /* + * Get the network mask. + */ + memset(&lifreq, 0, sizeof(lifreq)); + memcpy(&lifreq, ifrp, sizeof(lifreq)); + switch (family) { + case AF_INET: + /* + * Ignore the HP/UX warning about "integer overflow during + * conversion. It comes from its own macro definition, + * and is really hard to shut up. + */ + if (ioctl(iter->socket, SIOCGLIFNETMASK, (char *)&lifreq) + < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERIOCTL, + ISC_MSG_GETNETMASK, + "%s: getting netmask: %s"), + lifreq.lifr_name, strbuf); + return (ISC_R_IGNORE); + } + get_addr(family, &iter->current.netmask, + (struct sockaddr *)&lifreq.lifr_addr); + break; + case AF_INET6: { +#ifdef lifr_addrlen + int i, bits; + + /* + * Netmask already zeroed. + */ + iter->current.netmask.family = family; + for (i = 0; i < lifreq.lifr_addrlen; i += 8) { + bits = lifreq.lifr_addrlen - i; + bits = (bits < 8) ? (8 - bits) : 0; + iter->current.netmask.type.in6.s6_addr[i / 8] = + (~0 << bits) & 0xff; + } +#endif + break; + } + } + + return (ISC_R_SUCCESS); +#endif +} + +static isc_result_t +internal_current(isc_interfaceiter_t *iter) { + if (iter->mode == 6) + return (internal_current6(iter)); + return (internal_current4(iter)); +} + +/* + * Step the iterator to the next interface. Unlike + * isc_interfaceiter_next(), this may leave the iterator + * positioned on an interface that will ultimately + * be ignored. Return ISC_R_NOMORE if there are no more + * interfaces, otherwise ISC_R_SUCCESS. + */ +static isc_result_t +internal_next4(isc_interfaceiter_t *iter) { + struct ifreq *ifrp; + + REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len); + +#ifdef HAVE_TRUCLUSTER + if (internal_current_clusteralias(iter) == ISC_R_SUCCESS) + return (ISC_R_SUCCESS); +#endif + ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos); + +#ifdef ISC_PLATFORM_HAVESALEN + if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr)) + iter->pos += sizeof(ifrp->ifr_name) + ifrp->ifr_addr.sa_len; + else +#endif + iter->pos += sizeof(*ifrp); + + if (iter->pos >= (unsigned int) iter->ifc.ifc_len) + return (ISC_R_NOMORE); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +internal_next6(isc_interfaceiter_t *iter) { +#if !defined(SIOCGLIFCONF) || !defined(SIOCGLIFADDR) + UNUSED(iter); + return (ISC_R_NOTIMPLEMENTED); +#else + struct LIFREQ *ifrp; + + REQUIRE (iter->pos < (unsigned int) iter->lifc.lifc_len); + + ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos); + +#ifdef ISC_PLATFORM_HAVESALEN + if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr)) + iter->pos += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len; + else +#endif + iter->pos += sizeof(*ifrp); + + if (iter->pos >= (unsigned int) iter->lifc.lifc_len) + return (ISC_R_NOMORE); + + return (ISC_R_SUCCESS); +#endif +} + +static isc_result_t +internal_next(isc_interfaceiter_t *iter) { + if (iter->mode == 6) + return (internal_next6(iter)); + return (internal_next4(iter)); +} + +static void +internal_destroy(isc_interfaceiter_t *iter) { + (void) close(iter->socket); +} diff --git a/contrib/ntp/libisc/ifiter_sysctl.c b/contrib/ntp/libisc/ifiter_sysctl.c new file mode 100644 index 0000000..74440fa --- /dev/null +++ b/contrib/ntp/libisc/ifiter_sysctl.c @@ -0,0 +1,305 @@ +/* + * Copyright (C) 1999-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: ifiter_sysctl.c,v 1.17 2002/05/30 01:24:12 marka Exp $ */ + +/* + * Obtain the list of network interfaces using sysctl. + * See TCP/IP Illustrated Volume 2, sections 19.8, 19.14, + * and 19.16. + */ + +#include <sys/param.h> +#include <sys/sysctl.h> + +#include <net/route.h> +#include <net/if_dl.h> + +/* XXX what about Alpha? */ +#ifdef sgi +#define ROUNDUP(a) ((a) > 0 ? \ + (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) : \ + sizeof(__uint64_t)) +#else +#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \ + : sizeof(long)) +#endif + +#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'S') +#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) + +struct isc_interfaceiter { + unsigned int magic; /* Magic number. */ + isc_mem_t *mctx; + void *buf; /* Buffer for sysctl data. */ + unsigned int bufsize; /* Bytes allocated. */ + unsigned int bufused; /* Bytes used. */ + unsigned int pos; /* Current offset in + sysctl data. */ + isc_interface_t current; /* Current interface data. */ + isc_result_t result; /* Last result code. */ +}; + +static int mib[6] = { + CTL_NET, + PF_ROUTE, + 0, + 0, /* Any address family. */ + NET_RT_IFLIST, + 0 /* Flags. */ +}; + +isc_result_t +isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { + isc_interfaceiter_t *iter; + isc_result_t result; + size_t bufsize; + size_t bufused; + char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(iterp != NULL); + REQUIRE(*iterp == NULL); + + iter = isc_mem_get(mctx, sizeof(*iter)); + if (iter == NULL) + return (ISC_R_NOMEMORY); + + iter->mctx = mctx; + iter->buf = 0; + + /* + * Determine the amount of memory needed. + */ + bufsize = 0; + if (sysctl(mib, 6, NULL, &bufsize, NULL, (size_t) 0) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERSYSCTL, + ISC_MSG_GETIFLISTSIZE, + "getting interface " + "list size: sysctl: %s"), + strbuf); + result = ISC_R_UNEXPECTED; + goto failure; + } + iter->bufsize = bufsize; + + iter->buf = isc_mem_get(iter->mctx, iter->bufsize); + if (iter->buf == NULL) { + result = ISC_R_NOMEMORY; + goto failure; + } + + bufused = bufsize; + if (sysctl(mib, 6, iter->buf, &bufused, NULL, (size_t) 0) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_IFITERSYSCTL, + ISC_MSG_GETIFLIST, + "getting interface list: " + "sysctl: %s"), + strbuf); + result = ISC_R_UNEXPECTED; + goto failure; + } + iter->bufused = bufused; + INSIST(iter->bufused <= iter->bufsize); + + /* + * A newly created iterator has an undefined position + * until isc_interfaceiter_first() is called. + */ + iter->pos = (unsigned int) -1; + iter->result = ISC_R_FAILURE; + + iter->magic = IFITER_MAGIC; + *iterp = iter; + return (ISC_R_SUCCESS); + + failure: + if (iter->buf != NULL) + isc_mem_put(mctx, iter->buf, iter->bufsize); + isc_mem_put(mctx, iter, sizeof(*iter)); + return (result); +} + +/* + * Get information about the current interface to iter->current. + * If successful, return ISC_R_SUCCESS. + * If the interface has an unsupported address family, + * return ISC_R_IGNORE. In case of other failure, + * return ISC_R_UNEXPECTED. + */ + +static isc_result_t +internal_current(isc_interfaceiter_t *iter) { + struct ifa_msghdr *ifam, *ifam_end; + + REQUIRE(VALID_IFITER(iter)); + REQUIRE (iter->pos < (unsigned int) iter->bufused); + + ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos); + ifam_end = (struct ifa_msghdr *) ((char *) iter->buf + iter->bufused); + + if (ifam->ifam_type == RTM_IFINFO) { + struct if_msghdr *ifm = (struct if_msghdr *) ifam; + struct sockaddr_dl *sdl = (struct sockaddr_dl *) (ifm + 1); + unsigned int namelen; + + memset(&iter->current, 0, sizeof(iter->current)); + + namelen = sdl->sdl_nlen; + if (namelen > sizeof(iter->current.name) - 1) + namelen = sizeof(iter->current.name) - 1; + + memset(iter->current.name, 0, sizeof(iter->current.name)); + memcpy(iter->current.name, sdl->sdl_data, namelen); + + iter->current.flags = 0; + + if ((ifam->ifam_flags & IFF_UP) != 0) + iter->current.flags |= INTERFACE_F_UP; + + if ((ifam->ifam_flags & IFF_POINTOPOINT) != 0) + iter->current.flags |= INTERFACE_F_POINTTOPOINT; + + if ((ifam->ifam_flags & IFF_LOOPBACK) != 0) + iter->current.flags |= INTERFACE_F_LOOPBACK; + + if ((ifam->ifam_flags & IFF_BROADCAST) != 0) { + iter->current.flags |= INTERFACE_F_BROADCAST; + } +#ifdef IFF_MULTICAST + if ((ifam->ifam_flags & IFF_MULTICAST) != 0) { + iter->current.flags |= INTERFACE_F_MULTICAST; + } +#endif + + /* + * This is not an interface address. + * Force another iteration. + */ + return (ISC_R_IGNORE); + } else if (ifam->ifam_type == RTM_NEWADDR) { + int i; + int family; + struct sockaddr *mask_sa = NULL; + struct sockaddr *addr_sa = NULL; + struct sockaddr *dst_sa = NULL; + + struct sockaddr *sa = (struct sockaddr *)(ifam + 1); + family = sa->sa_family; + + for (i = 0; i < RTAX_MAX; i++) + { + if ((ifam->ifam_addrs & (1 << i)) == 0) + continue; + + INSIST(sa < (struct sockaddr *) ifam_end); + + switch (i) { + case RTAX_NETMASK: /* Netmask */ + mask_sa = sa; + break; + case RTAX_IFA: /* Interface address */ + addr_sa = sa; + break; + case RTAX_BRD: /* Broadcast or destination address */ + dst_sa = sa; + break; + } +#ifdef ISC_PLATFORM_HAVESALEN + sa = (struct sockaddr *)((char*)(sa) + + ROUNDUP(sa->sa_len)); +#else +#ifdef sgi + /* + * Do as the contributed SGI code does. + */ + sa = (struct sockaddr *)((char*)(sa) + + ROUNDUP(_FAKE_SA_LEN_DST(sa))); +#else + /* XXX untested. */ + sa = (struct sockaddr *)((char*)(sa) + + ROUNDUP(sizeof(struct sockaddr))); +#endif +#endif + } + + if (addr_sa == NULL) + return (ISC_R_IGNORE); + + family = addr_sa->sa_family; + if (family != AF_INET && family != AF_INET6) + return (ISC_R_IGNORE); + + iter->current.af = family; + + get_addr(family, &iter->current.address, addr_sa); + + if (mask_sa != NULL) + get_addr(family, &iter->current.netmask, mask_sa); + + if (dst_sa != NULL && + (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) + get_addr(family, &iter->current.dstaddress, dst_sa); + if (dst_sa != NULL && + (iter->current.flags & INTERFACE_F_BROADCAST) != 0) + get_addr(family, &iter->current.broadcast, dst_sa); + + return (ISC_R_SUCCESS); + } else { + printf(isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERSYSCTL, + ISC_MSG_UNEXPECTEDTYPE, + "warning: unexpected interface list " + "message type\n")); + return (ISC_R_IGNORE); + } +} + +/* + * Step the iterator to the next interface. Unlike + * isc_interfaceiter_next(), this may leave the iterator + * positioned on an interface that will ultimately + * be ignored. Return ISC_R_NOMORE if there are no more + * interfaces, otherwise ISC_R_SUCCESS. + */ +static isc_result_t +internal_next(isc_interfaceiter_t *iter) { + struct ifa_msghdr *ifam; + REQUIRE (iter->pos < (unsigned int) iter->bufused); + + ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos); + + iter->pos += ifam->ifam_msglen; + + if (iter->pos >= iter->bufused) + return (ISC_R_NOMORE); + + return (ISC_R_SUCCESS); +} + +static void +internal_destroy(isc_interfaceiter_t *iter) { + UNUSED(iter); /* Unused. */ + /* + * Do nothing. + */ +} + diff --git a/contrib/ntp/libisc/inet_ntop.c b/contrib/ntp/libisc/inet_ntop.c new file mode 100644 index 0000000..395d0e5 --- /dev/null +++ b/contrib/ntp/libisc/inet_ntop.c @@ -0,0 +1,198 @@ +/* + * Copyright (C) 1996-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = + "$Id: inet_ntop.c,v 1.13 2001/11/27 01:56:00 gson Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <config.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include <isc/net.h> + +#include "ntp_sprintf.h" + +#define NS_INT16SZ 2 +#define NS_IN6ADDRSZ 16 + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4(const unsigned char *src, char *dst, + size_t size); + +#ifdef AF_INET6 +static const char *inet_ntop6(const unsigned char *src, char *dst, + size_t size); +#endif + +/* char * + * isc_net_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +isc_net_ntop(int af, const void *src, char *dst, size_t size) +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); +#ifdef AF_INET6 + case AF_INET6: + return (inet_ntop6(src, dst, size)); +#endif + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a unsigned char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const unsigned char *src, char *dst, size_t size) +{ + static const char *fmt = "%u.%u.%u.%u"; + char tmp[sizeof("255.255.255.255")]; + + if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) + { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + + return (dst); +} + +/* const char * + * isc_inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +#ifdef AF_INET6 +static const char * +inet_ntop6(const unsigned char *src, char *dst, size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp; + struct { int base, len; } best, cur; + unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof(words)); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + best.len = 0; + cur.base = -1; + cur.len = 0; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, + sizeof(tmp) - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + tp += SPRINTF((tp, "%x", words[i])); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} +#endif /* AF_INET6 */ diff --git a/contrib/ntp/libisc/interfaceiter.c b/contrib/ntp/libisc/interfaceiter.c new file mode 100644 index 0000000..37af9f3 --- /dev/null +++ b/contrib/ntp/libisc/interfaceiter.c @@ -0,0 +1,159 @@ +/* + * Copyright (C) 1999-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: interfaceiter.c,v 1.27 2002/07/02 05:51:43 marka Exp $ */ + +#include <config.h> + +#include <sys/types.h> +#include <sys/ioctl.h> +#ifdef HAVE_SYS_SOCKIO_H +#include <sys/sockio.h> /* Required for ifiter_ioctl.c. */ +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> + +#include <isc/interfaceiter.h> +#include <isc/magic.h> +#include <isc/mem.h> +#include <isc/msgs.h> +#include <isc/net.h> +#include <isc/result.h> +#include <isc/strerror.h> +#include <isc/string.h> +#include <isc/types.h> +#include <isc/util.h> + +/* Must follow <isc/net.h>. */ +#ifdef HAVE_NET_IF6_H +#include <net/if6.h> +#endif +#include <net/if.h> + +/* Common utility functions */ + +/* + * Extract the network address part from a "struct sockaddr". + * + * The address family is given explicity + * instead of using src->sa_family, because the latter does not work + * for copying a network mask obtained by SIOCGIFNETMASK (it does + * not have a valid address family). + */ + +static void +get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src) { + dst->family = family; + switch (family) { + case AF_INET: + memcpy(&dst->type.in, + &((struct sockaddr_in *) src)->sin_addr, + sizeof(struct in_addr)); + break; + case AF_INET6: + memcpy(&dst->type.in6, + &((struct sockaddr_in6 *) src)->sin6_addr, + sizeof(struct in6_addr)); + break; + default: + INSIST(0); + break; + } +} + +/* + * Include system-dependent code. + */ + +#if HAVE_IFLIST_SYSCTL +#include "ifiter_sysctl.c" +#else +#include "ifiter_ioctl.c" +#endif + +/* + * The remaining code is common to the sysctl and ioctl case. + */ + +isc_result_t +isc_interfaceiter_current(isc_interfaceiter_t *iter, + isc_interface_t *ifdata) +{ + REQUIRE(iter->result == ISC_R_SUCCESS); + memcpy(ifdata, &iter->current, sizeof(*ifdata)); + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_interfaceiter_first(isc_interfaceiter_t *iter) { + isc_result_t result; + + REQUIRE(VALID_IFITER(iter)); + + iter->pos = 0; +#ifdef HAVE_TRUCLUSTER + iter->clua_context = 0; +#endif + for (;;) { + result = internal_current(iter); + if (result != ISC_R_IGNORE) + break; + result = internal_next(iter); + if (result != ISC_R_SUCCESS) + break; + } + iter->result = result; + return (result); +} + +isc_result_t +isc_interfaceiter_next(isc_interfaceiter_t *iter) { + isc_result_t result; + + REQUIRE(VALID_IFITER(iter)); + REQUIRE(iter->result == ISC_R_SUCCESS); + + for (;;) { + result = internal_next(iter); + if (result != ISC_R_SUCCESS) + break; + result = internal_current(iter); + if (result != ISC_R_IGNORE) + break; + } + iter->result = result; + return (result); +} + +void +isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) +{ + isc_interfaceiter_t *iter; + REQUIRE(iterp != NULL); + iter = *iterp; + REQUIRE(VALID_IFITER(iter)); + + internal_destroy(iter); + isc_mem_put(iter->mctx, iter->buf, iter->bufsize); + + iter->magic = 0; + isc_mem_put(iter->mctx, iter, sizeof(*iter)); + *iterp = NULL; +} diff --git a/contrib/ntp/libisc/isc_strerror.c b/contrib/ntp/libisc/isc_strerror.c new file mode 100644 index 0000000..9ec4a2f --- /dev/null +++ b/contrib/ntp/libisc/isc_strerror.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: strerror.c,v 1.3 2001/11/20 01:45:45 gson Exp $ */ + +#include <config.h> + +#include <stdio.h> +#include <string.h> + +#include <isc/mutex.h> +#include <isc/once.h> +#include <isc/print.h> +#include <isc/strerror.h> +#include <isc/util.h> + +#include "l_stdlib.h" + +#ifdef HAVE_STRERROR +/* + * We need to do this this way for profiled locks. + */ +static isc_mutex_t isc_strerror_lock; +static void init_lock(void) { + RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS); +} +#else +extern const char * const sys_errlist[]; +extern const int sys_nerr; +#endif + +void +isc__strerror(int num, char *buf, size_t size) { +#ifdef HAVE_STRERROR + char *msg; + unsigned int unum = num; + static isc_once_t once = ISC_ONCE_INIT; + + REQUIRE(buf != NULL); + + RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS); + + LOCK(&isc_strerror_lock); + msg = strerror(num); + if (msg != NULL) + snprintf(buf, size, "%s", msg); + else + snprintf(buf, size, "Unknown error: %u", unum); + UNLOCK(&isc_strerror_lock); +#else + unsigned int unum = num; + + REQUIRE(buf != NULL); + + if (num >= 0 && num < sys_nerr) + snprintf(buf, size, "%s", sys_errlist[num]); + else + snprintf(buf, size, "Unknown error: %u", unum); +#endif +} diff --git a/contrib/ntp/libisc/lib.c b/contrib/ntp/libisc/lib.c new file mode 100644 index 0000000..95dd479 --- /dev/null +++ b/contrib/ntp/libisc/lib.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 1999-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: lib.c,v 1.9 2001/11/19 03:08:23 mayer Exp $ */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> + +#include <isc/once.h> +#include <isc/msgs.h> +#include <isc/lib.h> + +/*** + *** Globals + ***/ + +LIBISC_EXTERNAL_DATA isc_msgcat_t * isc_msgcat = NULL; + + +/*** + *** Private + ***/ + +static isc_once_t msgcat_once = ISC_ONCE_INIT; + + +/*** + *** Functions + ***/ + +static void +open_msgcat(void) { + isc_msgcat_open("libisc.cat", &isc_msgcat); +} + +void +isc_lib_initmsgcat(void) { + isc_result_t result; + + /* + * Initialize the ISC library's message catalog, isc_msgcat, if it + * has not already been initialized. + */ + + result = isc_once_do(&msgcat_once, open_msgcat); + if (result != ISC_R_SUCCESS) { + /* + * Normally we'd use RUNTIME_CHECK() or FATAL_ERROR(), but + * we can't do that here, since they might call us! + * (Note that the catalog might be open anyway, so we might + * as well try to provide an internationalized message.) + */ + fprintf(stderr, "%s:%d: %s: isc_once_do() %s.\n", + __FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FATALERROR, "fatal error"), + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); + abort(); + } +} diff --git a/contrib/ntp/libisc/mem.c b/contrib/ntp/libisc/mem.c new file mode 100644 index 0000000..39f1e5c --- /dev/null +++ b/contrib/ntp/libisc/mem.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 1997-2002 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: mem.c,v 1.113 2002/05/23 04:32:30 marka Exp $ */ + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> + +#include <isc/mem.h> +#include <isc/util.h> + +void * +isc_mem_get(isc_mem_t *ctx, size_t size) { + UNUSED(ctx); + if(size == 0) + size = 1; + return (malloc(size)); +} + +void +isc_mem_put(isc_mem_t *ctx, void *ptr, size_t size) +{ + UNUSED(ctx); + UNUSED(size); + free(ptr); +} + diff --git a/contrib/ntp/libisc/msgcat.c b/contrib/ntp/libisc/msgcat.c new file mode 100644 index 0000000..8253a06 --- /dev/null +++ b/contrib/ntp/libisc/msgcat.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 1999-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: msgcat.c,v 1.12 2001/11/30 01:59:39 gson Exp $ */ + +/* + * Principal Author: Bob Halley + */ + +#include <config.h> + +#include <stdlib.h> +#include <unistd.h> + +#include <isc/magic.h> +#include <isc/msgcat.h> +#include <isc/util.h> + +#ifdef HAVE_CATGETS +#include <nl_types.h> /* Required for nl_catd. */ +#endif + +/* + * Implementation Notes: + * + * We use malloc() and free() instead of isc_mem_get() and isc_mem_put() + * because we don't want to require a memory context to be specified + * in order to use a message catalog. + */ + +struct isc_msgcat { + unsigned int magic; +#ifdef HAVE_CATGETS + nl_catd catalog; +#endif +}; + +#define MSGCAT_MAGIC ISC_MAGIC('M', 'C', 'a', 't') +#define VALID_MSGCAT(m) ISC_MAGIC_VALID(m, MSGCAT_MAGIC) + +void +isc_msgcat_open(const char *name, isc_msgcat_t **msgcatp) { + isc_msgcat_t *msgcat; + + /* + * Open a message catalog. + */ + + REQUIRE(name != NULL); + REQUIRE(msgcatp != NULL && *msgcatp == NULL); + + msgcat = malloc(sizeof(*msgcat)); + if (msgcat == NULL) { + *msgcatp = NULL; + return; + } + +#ifdef HAVE_CATGETS + /* + * We don't check if catopen() fails because we don't care. + * If it does fail, then when we call catgets(), it will use + * the default string. + */ + msgcat->catalog = catopen(name, 0); +#endif + msgcat->magic = MSGCAT_MAGIC; + + *msgcatp = msgcat; +} + +void +isc_msgcat_close(isc_msgcat_t **msgcatp) { + isc_msgcat_t *msgcat; + + /* + * Close a message catalog. + */ + + REQUIRE(msgcatp != NULL); + msgcat = *msgcatp; + REQUIRE(VALID_MSGCAT(msgcat) || msgcat == NULL); + + if (msgcat != NULL) { +#ifdef HAVE_CATGETS + if (msgcat->catalog != (nl_catd)(-1)) + (void)catclose(msgcat->catalog); +#endif + msgcat->magic = 0; + free(msgcat); + } + + *msgcatp = NULL; +} + +const char * +isc_msgcat_get(isc_msgcat_t *msgcat, int set, int message, + const char *default_text) +{ + /* + * Get message 'message' from message set 'set' in 'msgcat'. If it + * is not available, use 'default'. + */ + + REQUIRE(VALID_MSGCAT(msgcat) || msgcat == NULL); + REQUIRE(set > 0); + REQUIRE(message > 0); + REQUIRE(default_text != NULL); + +#ifdef HAVE_CATGETS + if (msgcat == NULL) + return (default_text); + return (catgets(msgcat->catalog, set, message, default_text)); +#else + return (default_text); +#endif +} diff --git a/contrib/ntp/libisc/net.c b/contrib/ntp/libisc/net.c new file mode 100644 index 0000000..6c51f1c --- /dev/null +++ b/contrib/ntp/libisc/net.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 1999-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: net.c,v 1.25 2001/11/30 01:59:45 gson Exp $ */ + +#include <config.h> + +#include <errno.h> +#include <unistd.h> + +#include <isc/net.h> +#include <isc/strerror.h> +#include <isc/string.h> +#include <isc/util.h> + +#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRANY) +const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT; +#endif + +static isc_boolean_t once = ISC_FALSE; +static isc_result_t ipv4_result = ISC_R_NOTFOUND; +static isc_result_t ipv6_result = ISC_R_NOTFOUND; + +static isc_result_t +try_proto(int domain) { + int s; + isc_result_t result = ISC_R_SUCCESS; + char strbuf[ISC_STRERRORSIZE]; + + s = socket(domain, SOCK_STREAM, 0); + if (s == -1) { + switch (errno) { +#ifdef EAFNOSUPPORT + case EAFNOSUPPORT: +#endif +#ifdef EPROTONOSUPPORT + case EPROTONOSUPPORT: +#endif +#ifdef EINVAL + case EINVAL: +#endif + return (ISC_R_NOTFOUND); + default: + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s failed", + strbuf); + return (ISC_R_UNEXPECTED); + } + } + +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef ISC_PLATFORM_HAVEIN6PKTINFO + if (domain == PF_INET6) { + struct sockaddr_in6 sin6; + unsigned int len; + + /* + * Check to see if IPv6 is broken, as is common on Linux. + */ + len = sizeof(sin6); + if (getsockname(s, (struct sockaddr *)&sin6, (void *)&len) < 0) + { + result = ISC_R_NOTFOUND; + } else { + if (len == sizeof(struct sockaddr_in6)) + result = ISC_R_SUCCESS; + else { + result = ISC_R_NOTFOUND; + } + } + } +#endif +#endif + + (void)close(s); + + return (result); +} + +static void +initialize_action(void) { + ipv4_result = try_proto(PF_INET); +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef ISC_PLATFORM_HAVEIN6PKTINFO + ipv6_result = try_proto(PF_INET6); +#endif +#endif +} + +static void +initialize(void) { + if(once == ISC_FALSE) { + initialize_action(); + once = ISC_TRUE; + } +} + +isc_result_t +isc_net_probeipv4(void) { + initialize(); + return (ipv4_result); +} + +isc_result_t +isc_net_probeipv6(void) { + initialize(); + return (ipv6_result); +} diff --git a/contrib/ntp/libisc/strerror.c b/contrib/ntp/libisc/strerror.c new file mode 100644 index 0000000..4a0f8d8 --- /dev/null +++ b/contrib/ntp/libisc/strerror.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: strerror.c,v 1.3 2001/11/20 01:45:45 gson Exp $ */ + +#include <config.h> + +#include <stdio.h> +#include <string.h> + +#include <isc/mutex.h> +#include <isc/once.h> +#include <isc/print.h> +#include <isc/strerror.h> +#include <isc/util.h> + +#ifdef HAVE_STRERROR +/* + * We need to do this this way for profiled locks. + */ +static isc_mutex_t isc_strerror_lock; +static void init_lock(void) { + RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS); +} +#else +extern const char * const sys_errlist[]; +extern const int sys_nerr; +#endif + +void +isc__strerror(int num, char *buf, size_t size) { +#ifdef HAVE_STRERROR + char *msg; + unsigned int unum = num; + static isc_once_t once = ISC_ONCE_INIT; + + REQUIRE(buf != NULL); + + RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS); + + LOCK(&isc_strerror_lock); + msg = strerror(num); + if (msg != NULL) + snprintf(buf, size, "%s", msg); + else + snprintf(buf, size, "Unknown error: %u", unum); + UNLOCK(&isc_strerror_lock); +#else + unsigned int unum = num; + + REQUIRE(buf != NULL); + + if (num >= 0 && num < sys_nerr) + snprintf(buf, size, "%s", sys_errlist[num]); + else + snprintf(buf, size, "Unknown error: %u", unum); +#endif +} |