From: Danny Mayer Date: Thu, 23 Dec 2004 05:16:06 +0000 (-0500) Subject: ports from BIND 9.3.0 and reintegrated into ntp libisc xode X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3723a4239b3f53233be09d8780c4476f5da82bf1;p=thirdparty%2Fntp.git ports from BIND 9.3.0 and reintegrated into ntp libisc xode bk: 41ca54963FEQg_32ZWhdjI8VrB2kaw --- diff --git a/include/isc/buffer.h b/include/isc/buffer.h new file mode 100644 index 0000000000..02b82bcbac --- /dev/null +++ b/include/isc/buffer.h @@ -0,0 +1,800 @@ +/* + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1998-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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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: buffer.h,v 1.39.12.2 2004/03/08 09:04:51 marka Exp $ */ + +#ifndef ISC_BUFFER_H +#define ISC_BUFFER_H 1 + +/***** + ***** Module Info + *****/ + +/* + * Buffers + * + * A buffer is a region of memory, together with a set of related subregions. + * Buffers are used for parsing and I/O operations. + * + * The 'used region' and the 'available' region are disjoint, and their + * union is the buffer's region. The used region extends from the beginning + * of the buffer region to the last used byte. The available region + * extends from one byte greater than the last used byte to the end of the + * buffer's region. The size of the used region can be changed using various + * buffer commands. Initially, the used region is empty. + * + * The used region is further subdivided into two disjoint regions: the + * 'consumed region' and the 'remaining region'. The union of these two + * regions is the used region. The consumed region extends from the beginning + * of the used region to the byte before the 'current' offset (if any). The + * 'remaining' region the current pointer to the end of the used + * region. The size of the consumed region can be changed using various + * buffer commands. Initially, the consumed region is empty. + * + * The 'active region' is an (optional) subregion of the remaining region. + * It extends from the current offset to an offset in the remaining region + * that is selected with isc_buffer_setactive(). Initially, the active region + * is empty. If the current offset advances beyond the chosen offset, the + * active region will also be empty. + * + * /------------entire length---------------\ + * /----- used region -----\/-- available --\ + * +----------------------------------------+ + * | consumed | remaining | | + * +----------------------------------------+ + * a b c d e + * + * a == base of buffer. + * b == current pointer. Can be anywhere between a and d. + * c == active pointer. Meaningful between b and d. + * d == used pointer. + * e == length of buffer. + * + * a-e == entire length of buffer. + * a-d == used region. + * a-b == consumed region. + * b-d == remaining region. + * b-c == optional active region. + * + * The following invariants are maintained by all routines: + * + * length > 0 + * + * base is a valid pointer to length bytes of memory + * + * 0 <= used <= length + * + * 0 <= current <= used + * + * 0 <= active <= used + * (although active < current implies empty active region) + * + * MP: + * Buffers have no synchronization. Clients must ensure exclusive + * access. + * + * Reliability: + * No anticipated impact. + * + * Resources: + * Memory: 1 pointer + 6 unsigned integers per buffer. + * + * Security: + * No anticipated impact. + * + * Standards: + * None. + */ + +/*** + *** Imports + ***/ + +#include +#include +#include + +/* + * To make many functions be inline macros (via #define) define this. + * If it is undefined, a function will be used. + */ +/* #define ISC_BUFFER_USEINLINE */ + +ISC_LANG_BEGINDECLS + +/*** + *** Magic numbers + ***/ +#define ISC_BUFFER_MAGIC 0x42756621U /* Buf!. */ +#define ISC_BUFFER_VALID(b) ISC_MAGIC_VALID(b, ISC_BUFFER_MAGIC) + +/* + * The following macros MUST be used only on valid buffers. It is the + * caller's responsibility to ensure this by using the ISC_BUFFER_VALID + * check above, or by calling another isc_buffer_*() function (rather than + * another macro.) + */ + +/* + * Fundamental buffer elements. (A through E in the introductory comment.) + */ +#define isc_buffer_base(b) ((void *)(b)->base) /*a*/ +#define isc_buffer_current(b) \ + ((void *)((unsigned char *)(b)->base + (b)->current)) /*b*/ +#define isc_buffer_active(b) \ + ((void *)((unsigned char *)(b)->base + (b)->active)) /*c*/ +#define isc_buffer_used(b) \ + ((void *)((unsigned char *)(b)->base + (b)->used)) /*d*/ +#define isc_buffer_length(b) ((b)->length) /*e*/ + +/* + * Derived lengths. (Described in the introductory comment.) + */ +#define isc_buffer_usedlength(b) ((b)->used) /* d-a */ +#define isc_buffer_consumedlength(b) ((b)->current) /* b-a */ +#define isc_buffer_remaininglength(b) ((b)->used - (b)->current) /* d-b */ +#define isc_buffer_activelength(b) ((b)->active - (b)->current) /* c-b */ +#define isc_buffer_availablelength(b) ((b)->length - (b)->used) /* e-d */ + +/* + * Note that the buffer structure is public. This is principally so buffer + * operations can be implemented using macros. Applications are strongly + * discouraged from directly manipulating the structure. + */ + +struct isc_buffer { + unsigned int magic; + void *base; + /* The following integers are byte offsets from 'base'. */ + unsigned int length; + unsigned int used; + unsigned int current; + unsigned int active; + /* linkable */ + ISC_LINK(isc_buffer_t) link; + /* private internal elements */ + isc_mem_t *mctx; +}; + +/*** + *** Functions + ***/ + +isc_result_t +isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer, + unsigned int length); +/* + * Allocate a dynamic linkable buffer which has "length" bytes in the + * data region. + * + * Requires: + * "mctx" is valid. + * + * "dynbuffer" is non-NULL, and "*dynbuffer" is NULL. + * + * Returns: + * ISC_R_SUCCESS - success + * ISC_R_NOMEMORY - no memory available + * + * Note: + * Changing the buffer's length field is not permitted. + */ + +void +isc_buffer_free(isc_buffer_t **dynbuffer); +/* + * Release resources allocated for a dynamic buffer. + * + * Requires: + * "dynbuffer" is not NULL. + * + * "*dynbuffer" is a valid dynamic buffer. + * + * Ensures: + * "*dynbuffer" will be NULL on return, and all memory associated with + * the dynamic buffer is returned to the memory context used in + * isc_buffer_allocate(). + */ + +void +isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length); +/* + * Make 'b' refer to the 'length'-byte region starting at base. + * + * Requires: + * + * 'length' > 0 + * + * 'base' is a pointer to a sequence of 'length' bytes. + * + */ + +void +isc__buffer_invalidate(isc_buffer_t *b); +/* + * Make 'b' an invalid buffer. + * + * Requires: + * 'b' is a valid buffer. + * + * Ensures: + * If assertion checking is enabled, future attempts to use 'b' without + * calling isc_buffer_init() on it will cause an assertion failure. + */ + +void +isc__buffer_region(isc_buffer_t *b, isc_region_t *r); +/* + * Make 'r' refer to the region of 'b'. + * + * Requires: + * + * 'b' is a valid buffer. + * + * 'r' points to a region structure. + */ + +void +isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r); +/* + * Make 'r' refer to the used region of 'b'. + * + * Requires: + * + * 'b' is a valid buffer. + * + * 'r' points to a region structure. + */ + +void +isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r); +/* + * Make 'r' refer to the available region of 'b'. + * + * Requires: + * + * 'b' is a valid buffer. + * + * 'r' points to a region structure. + */ + +void +isc__buffer_add(isc_buffer_t *b, unsigned int n); +/* + * Increase the 'used' region of 'b' by 'n' bytes. + * + * Requires: + * + * 'b' is a valid buffer + * + * used + n <= length + * + */ + +void +isc__buffer_subtract(isc_buffer_t *b, unsigned int n); +/* + * Decrease the 'used' region of 'b' by 'n' bytes. + * + * Requires: + * + * 'b' is a valid buffer + * + * used >= n + * + */ + +void +isc__buffer_clear(isc_buffer_t *b); +/* + * Make the used region empty. + * + * Requires: + * + * 'b' is a valid buffer + * + * Ensures: + * + * used = 0 + * + */ + +void +isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r); +/* + * Make 'r' refer to the consumed region of 'b'. + * + * Requires: + * + * 'b' is a valid buffer. + * + * 'r' points to a region structure. + */ + +void +isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r); +/* + * Make 'r' refer to the remaining region of 'b'. + * + * Requires: + * + * 'b' is a valid buffer. + * + * 'r' points to a region structure. + */ + +void +isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r); +/* + * Make 'r' refer to the active region of 'b'. + * + * Requires: + * + * 'b' is a valid buffer. + * + * 'r' points to a region structure. + */ + +void +isc__buffer_setactive(isc_buffer_t *b, unsigned int n); +/* + * Sets the end of the active region 'n' bytes after current. + * + * Requires: + * + * 'b' is a valid buffer. + * + * current + n <= used + */ + +void +isc__buffer_first(isc_buffer_t *b); +/* + * Make the consumed region empty. + * + * Requires: + * + * 'b' is a valid buffer + * + * Ensures: + * + * current == 0 + * + */ + +void +isc__buffer_forward(isc_buffer_t *b, unsigned int n); +/* + * Increase the 'consumed' region of 'b' by 'n' bytes. + * + * Requires: + * + * 'b' is a valid buffer + * + * current + n <= used + * + */ + +void +isc__buffer_back(isc_buffer_t *b, unsigned int n); +/* + * Decrease the 'consumed' region of 'b' by 'n' bytes. + * + * Requires: + * + * 'b' is a valid buffer + * + * n <= current + * + */ + +void +isc_buffer_compact(isc_buffer_t *b); +/* + * Compact the used region by moving the remaining region so it occurs + * at the start of the buffer. The used region is shrunk by the size of + * the consumed region, and the consumed region is then made empty. + * + * Requires: + * + * 'b' is a valid buffer + * + * Ensures: + * + * current == 0 + * + * The size of the used region is now equal to the size of the remaining + * region (as it was before the call). The contents of the used region + * are those of the remaining region (as it was before the call). + */ + +isc_uint8_t +isc_buffer_getuint8(isc_buffer_t *b); +/* + * Read an unsigned 8-bit integer from 'b' and return it. + * + * Requires: + * + * 'b' is a valid buffer. + * + * The length of the available region of 'b' is at least 1. + * + * Ensures: + * + * The current pointer in 'b' is advanced by 1. + * + * Returns: + * + * A 8-bit unsigned integer. + */ + +void +isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val); +/* + * Store an unsigned 8-bit integer from 'val' into 'b'. + * + * Requires: + * 'b' is a valid buffer. + * + * The length of the unused region of 'b' is at least 1. + * + * Ensures: + * The used pointer in 'b' is advanced by 1. + */ + +isc_uint16_t +isc_buffer_getuint16(isc_buffer_t *b); +/* + * Read an unsigned 16-bit integer in network byte order from 'b', convert + * it to host byte order, and return it. + * + * Requires: + * + * 'b' is a valid buffer. + * + * The length of the available region of 'b' is at least 2. + * + * Ensures: + * + * The current pointer in 'b' is advanced by 2. + * + * Returns: + * + * A 16-bit unsigned integer. + */ + +void +isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val); +/* + * Store an unsigned 16-bit integer in host byte order from 'val' + * into 'b' in network byte order. + * + * Requires: + * 'b' is a valid buffer. + * + * The length of the unused region of 'b' is at least 2. + * + * Ensures: + * The used pointer in 'b' is advanced by 2. + */ + +isc_uint32_t +isc_buffer_getuint32(isc_buffer_t *b); +/* + * Read an unsigned 32-bit integer in network byte order from 'b', convert + * it to host byte order, and return it. + * + * Requires: + * + * 'b' is a valid buffer. + * + * The length of the available region of 'b' is at least 4. + * + * Ensures: + * + * The current pointer in 'b' is advanced by 4. + * + * Returns: + * + * A 32-bit unsigned integer. + */ + +void +isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val); +/* + * Store an unsigned 32-bit integer in host byte order from 'val' + * into 'b' in network byte order. + * + * Requires: + * 'b' is a valid buffer. + * + * The length of the unused region of 'b' is at least 4. + * + * Ensures: + * The used pointer in 'b' is advanced by 4. + */ + +void +isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base, + unsigned int length); +/* + * Copy 'length' bytes of memory at 'base' into 'b'. + * + * Requires: + * 'b' is a valid buffer. + * + * 'base' points to 'length' bytes of valid memory. + * + */ + +void +isc__buffer_putstr(isc_buffer_t *b, const char *source); +/* + * Copy 'source' into 'b', not including terminating NUL. + * + * Requires: + * 'b' is a valid buffer. + * + * 'source' to be a valid NULL terminated string. + * + * strlen(source) <= isc_buffer_available(b) + */ + +isc_result_t +isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r); +/* + * Copy the contents of 'r' into 'b'. + * + * Requires: + * 'b' is a valid buffer. + * + * 'r' is a valid region. + * + * Returns: + * + * ISC_R_SUCCESS + * ISC_R_NOSPACE The available region of 'b' is not + * big enough. + */ + +ISC_LANG_ENDDECLS + +/* + * Inline macro versions of the functions. These should never be called + * directly by an application, but will be used by the functions within + * buffer.c. The callers should always use "isc_buffer_*()" names, never + * ones beginning with "isc__" + */ + +/* + * XXXDCL Something more could be done with initializing buffers that + * point to const data. For example, a new function, isc_buffer_initconst, + * could be used, and a new boolean flag in the buffer structure could + * indicate whether the buffer was initialized with that function. + * (isc_bufer_init itself would be reprototyped to *not* have its "base" + * parameter be const.) Then if the boolean were true, the isc_buffer_put* + * functions could assert a contractual requirement for a non-const buffer. + * One drawback is that the isc_buffer_* functions (macros) that return + * pointers would still need to return non-const pointers to avoid compiler + * warnings, so it would be up to code that uses them to have to deal + * with the possibility that the buffer was initialized as const -- + * a problem that they *already* have to deal with but have absolutely + * no ability to. With a new isc_buffer_isconst() function returning + * true/false, they could at least assert a contractual requirement for + * non-const buffers when needed. + */ +#define ISC__BUFFER_INIT(_b, _base, _length) \ + do { \ + union { \ + const void * konst; \ + void * var; \ + } _u; \ + _u.konst = (_base); \ + (_b)->base = _u.var; \ + (_b)->length = (_length); \ + (_b)->used = 0; \ + (_b)->current = 0; \ + (_b)->active = 0; \ + (_b)->mctx = NULL; \ + ISC_LINK_INIT(_b, link); \ + (_b)->magic = ISC_BUFFER_MAGIC; \ + } while (0) + +#define ISC__BUFFER_INVALIDATE(_b) \ + do { \ + (_b)->magic = 0; \ + (_b)->base = NULL; \ + (_b)->length = 0; \ + (_b)->used = 0; \ + (_b)->current = 0; \ + (_b)->active = 0; \ + } while (0) + +#define ISC__BUFFER_REGION(_b, _r) \ + do { \ + (_r)->base = (_b)->base; \ + (_r)->length = (_b)->length; \ + } while (0) + +#define ISC__BUFFER_USEDREGION(_b, _r) \ + do { \ + (_r)->base = (_b)->base; \ + (_r)->length = (_b)->used; \ + } while (0) + +#define ISC__BUFFER_AVAILABLEREGION(_b, _r) \ + do { \ + (_r)->base = isc_buffer_used(_b); \ + (_r)->length = isc_buffer_availablelength(_b); \ + } while (0) + +#define ISC__BUFFER_ADD(_b, _n) \ + do { \ + (_b)->used += (_n); \ + } while (0) + +#define ISC__BUFFER_SUBTRACT(_b, _n) \ + do { \ + (_b)->used -= (_n); \ + if ((_b)->current > (_b)->used) \ + (_b)->current = (_b)->used; \ + if ((_b)->active > (_b)->used) \ + (_b)->active = (_b)->used; \ + } while (0) + +#define ISC__BUFFER_CLEAR(_b) \ + do { \ + (_b)->used = 0; \ + (_b)->current = 0; \ + (_b)->active = 0; \ + } while (0) + +#define ISC__BUFFER_CONSUMEDREGION(_b, _r) \ + do { \ + (_r)->base = (_b)->base; \ + (_r)->length = (_b)->current; \ + } while (0) + +#define ISC__BUFFER_REMAININGREGION(_b, _r) \ + do { \ + (_r)->base = isc_buffer_current(_b); \ + (_r)->length = isc_buffer_remaininglength(_b); \ + } while (0) + +#define ISC__BUFFER_ACTIVEREGION(_b, _r) \ + do { \ + if ((_b)->current < (_b)->active) { \ + (_r)->base = isc_buffer_current(_b); \ + (_r)->length = isc_buffer_activelength(_b); \ + } else { \ + (_r)->base = NULL; \ + (_r)->length = 0; \ + } \ + } while (0) + +#define ISC__BUFFER_SETACTIVE(_b, _n) \ + do { \ + (_b)->active = (_b)->current + (_n); \ + } while (0) + +#define ISC__BUFFER_FIRST(_b) \ + do { \ + (_b)->current = 0; \ + } while (0) + +#define ISC__BUFFER_FORWARD(_b, _n) \ + do { \ + (_b)->current += (_n); \ + } while (0) + +#define ISC__BUFFER_BACK(_b, _n) \ + do { \ + (_b)->current -= (_n); \ + } while (0) + +#define ISC__BUFFER_PUTMEM(_b, _base, _length) \ + do { \ + memcpy(isc_buffer_used(_b), (_base), (_length)); \ + (_b)->used += (_length); \ + } while (0) + +#define ISC__BUFFER_PUTSTR(_b, _source) \ + do { \ + unsigned int _length; \ + unsigned char *_cp; \ + _length = strlen(_source); \ + _cp = isc_buffer_used(_b); \ + memcpy(_cp, (_source), _length); \ + (_b)->used += (_length); \ + } while (0) + +#define ISC__BUFFER_PUTUINT8(_b, _val) \ + do { \ + unsigned char *_cp; \ + isc_uint8_t _val2 = (_val); \ + _cp = isc_buffer_used(_b); \ + (_b)->used++; \ + _cp[0] = _val2 & 0x00ff; \ + } while (0) + +#define ISC__BUFFER_PUTUINT16(_b, _val) \ + do { \ + unsigned char *_cp; \ + isc_uint16_t _val2 = (_val); \ + _cp = isc_buffer_used(_b); \ + (_b)->used += 2; \ + _cp[0] = (unsigned char)((_val2 & 0xff00U) >> 8); \ + _cp[1] = (unsigned char)(_val2 & 0x00ffU); \ + } while (0) + +#define ISC__BUFFER_PUTUINT32(_b, _val) \ + do { \ + unsigned char *_cp; \ + isc_uint32_t _val2 = (_val); \ + _cp = isc_buffer_used(_b); \ + (_b)->used += 4; \ + _cp[0] = (unsigned char)((_val2 & 0xff000000) >> 24); \ + _cp[1] = (unsigned char)((_val2 & 0x00ff0000) >> 16); \ + _cp[2] = (unsigned char)((_val2 & 0x0000ff00) >> 8); \ + _cp[3] = (unsigned char)((_val2 & 0x000000ff)); \ + } while (0) + +#if defined(ISC_BUFFER_USEINLINE) +#define isc_buffer_init ISC__BUFFER_INIT +#define isc_buffer_invalidate ISC__BUFFER_INVALIDATE +#define isc_buffer_region ISC__BUFFER_REGION +#define isc_buffer_usedregion ISC__BUFFER_USEDREGION +#define isc_buffer_availableregion ISC__BUFFER_AVAILABLEREGION +#define isc_buffer_add ISC__BUFFER_ADD +#define isc_buffer_subtract ISC__BUFFER_SUBTRACT +#define isc_buffer_clear ISC__BUFFER_CLEAR +#define isc_buffer_consumedregion ISC__BUFFER_CONSUMEDREGION +#define isc_buffer_remainingregion ISC__BUFFER_REMAININGREGION +#define isc_buffer_activeregion ISC__BUFFER_ACTIVEREGION +#define isc_buffer_setactive ISC__BUFFER_SETACTIVE +#define isc_buffer_first ISC__BUFFER_FIRST +#define isc_buffer_forward ISC__BUFFER_FORWARD +#define isc_buffer_back ISC__BUFFER_BACK +#define isc_buffer_putmem ISC__BUFFER_PUTMEM +#define isc_buffer_putstr ISC__BUFFER_PUTSTR +#define isc_buffer_putuint8 ISC__BUFFER_PUTUINT8 +#define isc_buffer_putuint16 ISC__BUFFER_PUTUINT16 +#define isc_buffer_putuint32 ISC__BUFFER_PUTUINT32 +#else +#define isc_buffer_init isc__buffer_init +#define isc_buffer_invalidate isc__buffer_invalidate +#define isc_buffer_region isc__buffer_region +#define isc_buffer_usedregion isc__buffer_usedregion +#define isc_buffer_availableregion isc__buffer_availableregion +#define isc_buffer_add isc__buffer_add +#define isc_buffer_subtract isc__buffer_subtract +#define isc_buffer_clear isc__buffer_clear +#define isc_buffer_consumedregion isc__buffer_consumedregion +#define isc_buffer_remainingregion isc__buffer_remainingregion +#define isc_buffer_activeregion isc__buffer_activeregion +#define isc_buffer_setactive isc__buffer_setactive +#define isc_buffer_first isc__buffer_first +#define isc_buffer_forward isc__buffer_forward +#define isc_buffer_back isc__buffer_back +#define isc_buffer_putmem isc__buffer_putmem +#define isc_buffer_putstr isc__buffer_putstr +#define isc_buffer_putuint8 isc__buffer_putuint8 +#define isc_buffer_putuint16 isc__buffer_putuint16 +#define isc_buffer_putuint32 isc__buffer_putuint32 +#endif + +#endif /* ISC_BUFFER_H */ diff --git a/include/isc/net.h b/include/isc/net.h index 25924febca..a5d9859f15 100644 --- a/include/isc/net.h +++ b/include/isc/net.h @@ -1,21 +1,21 @@ /* - * Copyright (C) 1999-2001 Internet Software Consortium. + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2003 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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.h,v 1.34 2002/04/03 06:38:38 marka Exp $ */ +/* $Id: net.h,v 1.31.2.2.10.8 2004/04/29 01:31:23 marka Exp $ */ #ifndef ISC_NET_H #define ISC_NET_H 1 @@ -75,6 +75,8 @@ #include #include /* Contractual promise. */ +#include + #include /* Contractual promise. */ #include /* Contractual promise. */ #ifdef ISC_PLATFORM_NEEDNETINETIN6H @@ -230,6 +232,10 @@ typedef isc_uint16_t in_port_t; (((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \ == ISC__IPADDR(0xe0000000)) +#define ISC_IPADDR_ISEXPERIMENTAL(i) \ + (((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \ + == ISC__IPADDR(0xf0000000)) + /*** *** Functions. ***/ @@ -245,6 +251,7 @@ isc_net_probeipv4(void); * * ISC_R_SUCCESS IPv4 is supported. * ISC_R_NOTFOUND IPv4 is not supported. + * ISC_R_DISABLED IPv4 is disabled. * ISC_R_UNEXPECTED */ @@ -257,9 +264,48 @@ isc_net_probeipv6(void); * * ISC_R_SUCCESS IPv6 is supported. * ISC_R_NOTFOUND IPv6 is not supported. + * ISC_R_DISABLED IPv6 is disabled. + * ISC_R_UNEXPECTED + */ + +isc_result_t +isc_net_probe_ipv6only(void); +/* + * Check if the system's kernel supports the IPV6_V6ONLY socket option. + * + * Returns: + * + * ISC_R_SUCCESS the option is supported for both TCP and UDP. + * ISC_R_NOTFOUND IPv6 itself or the option is not supported. + * ISC_R_UNEXPECTED + */ + +isc_result_t +isc_net_probe_ipv6pktinfo(void); +/* + * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option + * for UDP sockets. + * + * Returns: + * + * ISC_R_SUCCESS the option is supported. + * ISC_R_NOTFOUND IPv6 itself or the option is not supported. * ISC_R_UNEXPECTED */ +void +isc_net_disableipv4(void); + +void +isc_net_disableipv6(void); + +void +isc_net_enableipv4(void); + +void +isc_net_enableipv6(void); + +#ifdef ISC_PLATFORM_NEEDNTOP const char * isc_net_ntop(int af, const void *src, char *dst, size_t size); #ifdef ISC_PLATFORM_NEEDNTOP diff --git a/include/isc/netaddr.h b/include/isc/netaddr.h index 811e8dd48e..e209a9fa77 100644 --- a/include/isc/netaddr.h +++ b/include/isc/netaddr.h @@ -1,21 +1,21 @@ /* + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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: netaddr.h,v 1.21 2002/04/03 06:38:35 marka Exp $ */ +/* $Id: netaddr.h,v 1.18.12.7 2004/03/08 09:04:52 marka Exp $ */ #ifndef ISC_NETADDR_H #define ISC_NETADDR_H 1 @@ -23,9 +23,6 @@ #include #include #include -#include "ntp_rfc2553.h" - - ISC_LANG_BEGINDECLS @@ -35,6 +32,7 @@ struct isc_netaddr { struct in_addr in; struct in6_addr in6; } type; + isc_uint32_t zone; }; isc_boolean_t @@ -97,6 +95,12 @@ isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina); void isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6); +void +isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone); + +isc_uint32_t +isc_netaddr_getzone(const isc_netaddr_t *netaddr); + void isc_netaddr_any(isc_netaddr_t *netaddr); /* @@ -115,6 +119,12 @@ isc_netaddr_ismulticast(isc_netaddr_t *na); * Returns ISC_TRUE if the address is a multicast address. */ +isc_boolean_t +isc_netaddr_isexperimental(isc_netaddr_t *na); +/* + * Returns ISC_TRUE if the address is a experimental (CLASS E) address. + */ + isc_boolean_t isc_netaddr_islinklocal(isc_netaddr_t *na); /* diff --git a/include/isc/netscope.h b/include/isc/netscope.h new file mode 100644 index 0000000000..7cc0f182d7 --- /dev/null +++ b/include/isc/netscope.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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: netscope.h,v 1.4.142.5 2004/03/08 09:04:52 marka Exp $ */ + +#ifndef ISC_NETSCOPE_H +#define ISC_NETSCOPE_H 1 + +ISC_LANG_BEGINDECLS + +/* + * Convert a string of an IPv6 scope zone to zone index. If the conversion + * succeeds, 'zoneid' will store the index value. + * XXXJT: when a standard interface for this purpose is defined, + * we should use it. + * + * Returns: + * ISC_R_SUCCESS: conversion succeeds + * ISC_R_FAILURE: conversion fails + */ +isc_result_t +isc_netscope_pton(int af, char *scopename, void *addr, isc_uint32_t *zoneid); + +ISC_LANG_ENDDECLS + +#endif /* ISC_NETADDR_H */ diff --git a/include/isc/region.h b/include/isc/region.h new file mode 100644 index 0000000000..5622394aaf --- /dev/null +++ b/include/isc/region.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1998-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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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: region.h,v 1.16.12.3 2004/03/08 09:04:53 marka Exp $ */ + +#ifndef ISC_REGION_H +#define ISC_REGION_H 1 + +#include + +struct isc_region { + unsigned char * base; + unsigned int length; +}; + +struct isc_textregion { + char * base; + unsigned int length; +}; + +/* XXXDCL questionable ... bears discussion. we have been putting off + * discussing the region api. + */ +struct isc_constregion { + const void * base; + unsigned int length; +}; + +struct isc_consttextregion { + const char * base; + unsigned int length; +}; + +/* + * The region structure is not opaque, and is usually directly manipulated. + * Some macros are defined below for convenience. + */ + +#define isc_region_consume(r,l) \ + do { \ + isc_region_t *_r = (r); \ + unsigned int _l = (l); \ + INSIST(_r->length >= _l); \ + _r->base += _l; \ + _r->length -= _l; \ + } while (0) + +#define isc_textregion_consume(r,l) \ + do { \ + isc_textregion_t *_r = (r); \ + unsigned int _l = (l); \ + INSIST(_r->length >= _l); \ + _r->base += _l; \ + _r->length -= _l; \ + } while (0) + +#define isc_constregion_consume(r,l) \ + do { \ + isc_constregion_t *_r = (r); \ + unsigned int _l = (l); \ + INSIST(_r->length >= _l); \ + _r->base += _l; \ + _r->length -= _l; \ + } while (0) + +int +isc_region_compare(isc_region_t *r1, isc_region_t *r2); +/* + * Compares the contents of two regions + * + * Requires: + * 'r1' is a valid region + * 'r2' is a valid region + * + * Returns: + * < 0 if r1 is lexicographically less than r2 + * = 0 if r1 is lexicographically identical to r2 + * > 0 if r1 is lexicographically greater than r2 + */ + +#endif /* ISC_REGION_H */ diff --git a/include/isc/result.h b/include/isc/result.h index bf6b992587..93f7cefbd6 100644 --- a/include/isc/result.h +++ b/include/isc/result.h @@ -1,21 +1,21 @@ /* - * Copyright (C) 1998-2001 Internet Software Consortium. + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1998-2001, 2003 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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: result.h,v 1.59 2001/11/30 01:02:17 gson Exp $ */ +/* $Id: result.h,v 1.57.2.2.8.5 2004/05/15 03:46:13 jinmei Exp $ */ #ifndef ISC_RESULT_H #define ISC_RESULT_H 1 @@ -80,11 +80,14 @@ #define ISC_R_CONNECTIONRESET 54 /* connection reset */ #define ISC_R_SOFTQUOTA 55 /* soft quota reached */ #define ISC_R_BADNUMBER 56 /* not a valid number */ +#define ISC_R_DISABLED 57 /* disabled */ +#define ISC_R_MAXSIZE 58 /* max size */ +#define ISC_R_BADADDRESSFORM 59 /* invalid address format */ /* * Not a result code: the number of results. */ -#define ISC_R_NRESULTS 57 +#define ISC_R_NRESULTS 60 ISC_LANG_BEGINDECLS diff --git a/include/isc/sockaddr.h b/include/isc/sockaddr.h index 5257b059de..635af38117 100644 --- a/include/isc/sockaddr.h +++ b/include/isc/sockaddr.h @@ -173,6 +173,12 @@ isc_sockaddr_ismulticast(isc_sockaddr_t *sa); * Returns ISC_TRUE if the address is a multicast address. */ +isc_boolean_t +isc_sockaddr_isexperimental(isc_sockaddr_t *sa); +/* + * Returns ISC_TRUE if the address is a experimental (CLASS E) address. + */ + isc_boolean_t isc_sockaddr_islinklocal(isc_sockaddr_t *sa); /* diff --git a/libisc/net.c b/libisc/net.c index 6c51f1c973..db832667f1 100644 --- a/libisc/net.c +++ b/libisc/net.c @@ -1,21 +1,21 @@ /* - * Copyright (C) 1999-2001 Internet Software Consortium. + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2003 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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 $ */ +/* $Id: net.c,v 1.22.2.2.10.7 2004/04/29 01:31:22 marka Exp $ */ #include @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -31,9 +32,17 @@ const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT; #endif +#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRLOOPBACK) +const struct in6_addr isc_net_in6addrloop = IN6ADDR_LOOPBACK_INIT; +#endif + static isc_boolean_t once = ISC_FALSE; +static isc_once_t once_ipv6only = ISC_ONCE_INIT; +static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT; static isc_result_t ipv4_result = ISC_R_NOTFOUND; static isc_result_t ipv6_result = ISC_R_NOTFOUND; +static isc_result_t ipv6only_result = ISC_R_NOTFOUND; +static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND; static isc_result_t try_proto(int domain) { @@ -64,6 +73,7 @@ try_proto(int domain) { } #ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 #ifdef ISC_PLATFORM_HAVEIN6PKTINFO if (domain == PF_INET6) { struct sockaddr_in6 sin6; @@ -85,6 +95,7 @@ try_proto(int domain) { } } #endif +#endif #endif (void)close(s); @@ -96,10 +107,12 @@ static void initialize_action(void) { ipv4_result = try_proto(PF_INET); #ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 #ifdef ISC_PLATFORM_HAVEIN6PKTINFO ipv6_result = try_proto(PF_INET6); #endif #endif +#endif } static void @@ -121,3 +134,190 @@ isc_net_probeipv6(void) { initialize(); return (ipv6_result); } + +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 +static void +try_ipv6only(void) { +#ifdef IPV6_V6ONLY + int s, on; + char strbuf[ISC_STRERRORSIZE]; +#endif + isc_result_t result; + + result = isc_net_probeipv6(); + if (result != ISC_R_SUCCESS) { + ipv6only_result = result; + return; + } + +#ifndef IPV6_V6ONLY + ipv6only_result = ISC_R_NOTFOUND; + return; +#else + /* check for TCP sockets */ + s = socket(PF_INET6, SOCK_STREAM, 0); + if (s == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + ipv6only_result = ISC_R_UNEXPECTED; + return; + } + + on = 1; + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { + ipv6only_result = ISC_R_NOTFOUND; + goto close; + } + + close(s); + + /* check for UDP sockets */ + s = socket(PF_INET6, SOCK_DGRAM, 0); + if (s == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + ipv6only_result = ISC_R_UNEXPECTED; + return; + } + + on = 1; + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { + ipv6only_result = ISC_R_NOTFOUND; + goto close; + } + + close(s); + + ipv6only_result = ISC_R_SUCCESS; + +close: + close(s); + return; +#endif /* IPV6_V6ONLY */ +} + +static void +initialize_ipv6only(void) { + RUNTIME_CHECK(isc_once_do(&once_ipv6only, + try_ipv6only) == ISC_R_SUCCESS); +} +#endif /* IPV6_V6ONLY */ + +static void +try_ipv6pktinfo(void) { + int s, on; + char strbuf[ISC_STRERRORSIZE]; + isc_result_t result; + int optname; + + result = isc_net_probeipv6(); + if (result != ISC_R_SUCCESS) { + ipv6pktinfo_result = result; + return; + } + + /* we only use this for UDP sockets */ + s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if (s == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + ipv6pktinfo_result = ISC_R_UNEXPECTED; + return; + } + +#ifdef IPV6_RECVPKTINFO + optname = IPV6_RECVPKTINFO; +#else + optname = IPV6_PKTINFO; +#endif + on = 1; + if (setsockopt(s, IPPROTO_IPV6, optname, &on, sizeof(on)) < 0) { + ipv6pktinfo_result = ISC_R_NOTFOUND; + goto close; + } + + close(s); + ipv6pktinfo_result = ISC_R_SUCCESS; + +close: + close(s); + return; +} + +static void +initialize_ipv6pktinfo(void) { + RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo, + try_ipv6pktinfo) == ISC_R_SUCCESS); +} +#endif /* WANT_IPV6 */ + +isc_result_t +isc_net_probe_ipv6only(void) { +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 + initialize_ipv6only(); +#else + ipv6only_result = ISC_R_NOTFOUND; +#endif +#endif + return (ipv6only_result); +} + +isc_result_t +isc_net_probe_ipv6pktinfo(void) { +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 + initialize_ipv6pktinfo(); +#else + ipv6pktinfo_result = ISC_R_NOTFOUND; +#endif +#endif + return (ipv6pktinfo_result); +} + +void +isc_net_disableipv4(void) { + initialize(); + if (ipv4_result == ISC_R_SUCCESS) + ipv4_result = ISC_R_DISABLED; +} + +void +isc_net_disableipv6(void) { + initialize(); + if (ipv6_result == ISC_R_SUCCESS) + ipv6_result = ISC_R_DISABLED; +} + +void +isc_net_enableipv4(void) { + initialize(); + if (ipv4_result == ISC_R_DISABLED) + ipv4_result = ISC_R_SUCCESS; +} + +void +isc_net_enableipv6(void) { + initialize(); + if (ipv6_result == ISC_R_DISABLED) + ipv6_result = ISC_R_SUCCESS; +} diff --git a/libisc/netaddr.c b/libisc/netaddr.c new file mode 100644 index 0000000000..712ad2c134 --- /dev/null +++ b/libisc/netaddr.c @@ -0,0 +1,357 @@ +/* + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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: netaddr.c,v 1.18.12.9 2004/05/15 03:46:12 jinmei Exp $ */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +isc_boolean_t +isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) { + REQUIRE(a != NULL && b != NULL); + + if (a->family != b->family) + return (ISC_FALSE); + + if (a->zone != b->zone) + return (ISC_FALSE); + + switch (a->family) { + case AF_INET: + if (a->type.in.s_addr != b->type.in.s_addr) + return (ISC_FALSE); + break; + case AF_INET6: + if (memcmp(&a->type.in6, &b->type.in6, + sizeof(a->type.in6)) != 0 || + a->zone != b->zone) + return (ISC_FALSE); + break; + default: + return (ISC_FALSE); + } + return (ISC_TRUE); +} + +isc_boolean_t +isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b, + unsigned int prefixlen) +{ + const unsigned char *pa, *pb; + unsigned int ipabytes; /* Length of whole IP address in bytes */ + unsigned int nbytes; /* Number of significant whole bytes */ + unsigned int nbits; /* Number of significant leftover bits */ + + REQUIRE(a != NULL && b != NULL); + + if (a->family != b->family) + return (ISC_FALSE); + + if (a->zone != b->zone) + return (ISC_FALSE); + + switch (a->family) { + case AF_INET: + pa = (const unsigned char *) &a->type.in; + pb = (const unsigned char *) &b->type.in; + ipabytes = 4; + break; + case AF_INET6: + pa = (const unsigned char *) &a->type.in6; + pb = (const unsigned char *) &b->type.in6; + ipabytes = 16; + break; + default: + pa = pb = NULL; /* Avoid silly compiler warning. */ + ipabytes = 0; /* Ditto. */ + return (ISC_FALSE); + } + + /* + * Don't crash if we get a pattern like 10.0.0.1/9999999. + */ + if (prefixlen > ipabytes * 8) + prefixlen = ipabytes * 8; + + nbytes = prefixlen / 8; + nbits = prefixlen % 8; + + if (nbytes > 0) { + if (memcmp(pa, pb, nbytes) != 0) + return (ISC_FALSE); + } + if (nbits > 0) { + unsigned int bytea, byteb, mask; + INSIST(nbytes < ipabytes); + INSIST(nbits < 8); + bytea = pa[nbytes]; + byteb = pb[nbytes]; + mask = (0xFF << (8-nbits)) & 0xFF; + if ((bytea & mask) != (byteb & mask)) + return (ISC_FALSE); + } + return (ISC_TRUE); +} + +isc_result_t +isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) { + char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; + char zbuf[sizeof("%4294967295")]; + unsigned int alen; + int zlen; + const char *r; + const void *type; + + REQUIRE(netaddr != NULL); + + switch (netaddr->family) { + case AF_INET: + type = &netaddr->type.in; + break; + case AF_INET6: + type = &netaddr->type.in6; + break; + default: + return (ISC_R_FAILURE); + } + r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf)); + if (r == NULL) + return (ISC_R_FAILURE); + + alen = strlen(abuf); + INSIST(alen < sizeof(abuf)); + + zlen = 0; + if (netaddr->family == AF_INET6 && netaddr->zone != 0) { + zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone); + if (zlen < 0) + return (ISC_R_FAILURE); + INSIST((unsigned int)zlen < sizeof(zbuf)); + } + + if (alen + zlen > isc_buffer_availablelength(target)) + return (ISC_R_NOSPACE); + + isc_buffer_putmem(target, (unsigned char *)abuf, alen); + isc_buffer_putmem(target, (unsigned char *)zbuf, zlen); + + return (ISC_R_SUCCESS); +} + +void +isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) { + isc_result_t result; + isc_buffer_t buf; + + isc_buffer_init(&buf, array, size); + result = isc_netaddr_totext(na, &buf); + + /* + * Null terminate. + */ + if (result == ISC_R_SUCCESS) { + if (isc_buffer_availablelength(&buf) >= 1) + isc_buffer_putuint8(&buf, 0); + else + result = ISC_R_NOSPACE; + } + + if (result != ISC_R_SUCCESS) { + snprintf(array, size, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR, + ISC_MSG_UNKNOWNADDR, + ""), + na->family); + array[size - 1] = '\0'; + } +} + +isc_result_t +isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) { + unsigned int nbits, nbytes, ipbytes, i; + const unsigned char *p; + + switch (s->family) { + case AF_INET: + p = (const unsigned char *) &s->type.in; + ipbytes = 4; + break; + case AF_INET6: + p = (const unsigned char *) &s->type.in6; + ipbytes = 16; + break; + default: + ipbytes = 0; + return (ISC_R_NOTIMPLEMENTED); + } + nbytes = nbits = 0; + for (i = 0; i < ipbytes; i++) { + if (p[i] != 0xFF) + break; + } + nbytes = i; + if (i < ipbytes) { + unsigned int c = p[nbytes]; + while ((c & 0x80) != 0 && nbits < 8) { + c <<= 1; nbits++; + } + if ((c & 0xFF) != 0) + return (ISC_R_MASKNONCONTIG); + i++; + } + for (; i < ipbytes; i++) { + if (p[i] != 0) + return (ISC_R_MASKNONCONTIG); + i++; + } + *lenp = nbytes * 8 + nbits; + return (ISC_R_SUCCESS); +} + +void +isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) { + memset(netaddr, 0, sizeof(*netaddr)); + netaddr->family = AF_INET; + netaddr->type.in = *ina; +} + +void +isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) { + memset(netaddr, 0, sizeof(*netaddr)); + netaddr->family = AF_INET6; + netaddr->type.in6 = *ina6; +} + +void +isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone) { + /* we currently only support AF_INET6. */ + REQUIRE(netaddr->family == AF_INET6); + + netaddr->zone = zone; +} + +isc_uint32_t +isc_netaddr_getzone(const isc_netaddr_t *netaddr) { + return (netaddr->zone); +} + +void +isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) { + int family = s->type.sa.sa_family; + t->family = family; + switch (family) { + case AF_INET: + t->type.in = s->type.sin.sin_addr; + t->zone = 0; + break; + case AF_INET6: + memcpy(&t->type.in6, &s->type.sin6.sin6_addr, 16); +#ifdef ISC_PLATFORM_HAVESCOPEID + t->zone = s->type.sin6.sin6_scope_id; +#else + t->zone = 0; +#endif + break; + default: + INSIST(0); + } +} + +void +isc_netaddr_any(isc_netaddr_t *netaddr) { + memset(netaddr, 0, sizeof(*netaddr)); + netaddr->family = AF_INET; + netaddr->type.in.s_addr = INADDR_ANY; +} + +void +isc_netaddr_any6(isc_netaddr_t *netaddr) { + memset(netaddr, 0, sizeof(*netaddr)); + netaddr->family = AF_INET6; + netaddr->type.in6 = in6addr_any; +} + +isc_boolean_t +isc_netaddr_ismulticast(isc_netaddr_t *na) { + switch (na->family) { + case AF_INET: + return (ISC_TF(ISC_IPADDR_ISMULTICAST(na->type.in.s_addr))); + case AF_INET6: + return (ISC_TF(IN6_IS_ADDR_MULTICAST(&na->type.in6))); + default: + return (ISC_FALSE); /* XXXMLG ? */ + } +} + +isc_boolean_t +isc_netaddr_isexperimental(isc_netaddr_t *na) { + switch (na->family) { + case AF_INET: + return (ISC_TF(ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr))); + default: + return (ISC_FALSE); /* XXXMLG ? */ + } +} + +isc_boolean_t +isc_netaddr_islinklocal(isc_netaddr_t *na) { + switch (na->family) { + case AF_INET: + return (ISC_FALSE); + case AF_INET6: + return (ISC_TF(IN6_IS_ADDR_LINKLOCAL(&na->type.in6))); + default: + return (ISC_FALSE); + } +} + +isc_boolean_t +isc_netaddr_issitelocal(isc_netaddr_t *na) { + switch (na->family) { + case AF_INET: + return (ISC_FALSE); + case AF_INET6: + return (ISC_TF(IN6_IS_ADDR_SITELOCAL(&na->type.in6))); + default: + return (ISC_FALSE); + } +} + +void +isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) { + isc_netaddr_t *src; + + DE_CONST(s, src); /* Must come before IN6_IS_ADDR_V4MAPPED. */ + + REQUIRE(s->family == AF_INET6); + REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6)); + + memset(t, 0, sizeof(*t)); + t->family = AF_INET; + memcpy(&t->type.in, (char *)&src->type.in6 + 12, 4); + return; +} diff --git a/libisc/netscope.c b/libisc/netscope.c new file mode 100644 index 0000000000..f0bffc44a4 --- /dev/null +++ b/libisc/netscope.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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: netscope.c,v 1.5.142.7 2004/03/12 10:31:26 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include + +isc_result_t +isc_netscope_pton(int af, char *scopename, void *addr, isc_uint32_t *zoneid) { + char *ep; +#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX + unsigned int ifid; +#endif + struct in6_addr *in6; + isc_uint32_t zone; + isc_uint64_t llz; + + /* at this moment, we only support AF_INET6 */ + if (af != AF_INET6) + return (ISC_R_FAILURE); + + in6 = (struct in6_addr *)addr; + + /* + * Basically, "names" are more stable than numeric IDs in terms of + * renumbering, and are more preferred. However, since there is no + * standard naming convention and APIs to deal with the names. Thus, + * we only handle the case of link-local addresses, for which we use + * interface names as link names, assuming one to one mapping between + * interfaces and links. + */ +#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX + if (IN6_IS_ADDR_LINKLOCAL(in6) && + (ifid = if_nametoindex((const char *)scopename)) != 0) + zone = (isc_uint32_t)ifid; + else { +#endif + llz = isc_string_touint64(scopename, &ep, 10); + if (ep == scopename) + return (ISC_R_FAILURE); + + /* check overflow */ + zone = (isc_uint32_t)(llz & 0xffffffffUL); + if (zone != llz) + return (ISC_R_FAILURE); +#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX + } +#endif + + *zoneid = zone; + return (ISC_R_SUCCESS); +} diff --git a/libisc/sockaddr.c b/libisc/sockaddr.c new file mode 100644 index 0000000000..28558853cf --- /dev/null +++ b/libisc/sockaddr.c @@ -0,0 +1,474 @@ +/* + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2003 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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: sockaddr.c,v 1.48.2.1.2.10 2004/05/15 03:46:12 jinmei Exp $ */ + +#include + +#include + +#include +/* + * We currently don't need hashing here + */ +#if 0 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +isc_boolean_t +isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { + REQUIRE(a != NULL && b != NULL); + + if (a->length != b->length) + return (ISC_FALSE); + + /* + * We don't just memcmp because the sin_zero field isn't always + * zero. + */ + + if (a->type.sa.sa_family != b->type.sa.sa_family) + return (ISC_FALSE); + switch (a->type.sa.sa_family) { + case AF_INET: + if (memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr, + sizeof(a->type.sin.sin_addr)) != 0) + return (ISC_FALSE); + if (a->type.sin.sin_port != b->type.sin.sin_port) + return (ISC_FALSE); + break; + case AF_INET6: + if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, + sizeof(a->type.sin6.sin6_addr)) != 0) + return (ISC_FALSE); +#ifdef ISC_PLATFORM_HAVESCOPEID + if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id) + return (ISC_FALSE); +#endif + if (a->type.sin6.sin6_port != b->type.sin6.sin6_port) + return (ISC_FALSE); + break; + default: + if (memcmp(&a->type, &b->type, a->length) != 0) + return (ISC_FALSE); + } + return (ISC_TRUE); +} + +isc_boolean_t +isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { + REQUIRE(a != NULL && b != NULL); + + if (a->length != b->length) + return (ISC_FALSE); + + if (a->type.sa.sa_family != b->type.sa.sa_family) + return (ISC_FALSE); + switch (a->type.sa.sa_family) { + case AF_INET: + if (memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr, + sizeof(a->type.sin.sin_addr)) != 0) + return (ISC_FALSE); + break; + case AF_INET6: + if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, + sizeof(a->type.sin6.sin6_addr)) != 0) + return (ISC_FALSE); +#ifdef ISC_PLATFORM_HAVESCOPEID + if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id) + return (ISC_FALSE); +#endif + break; + default: + if (memcmp(&a->type, &b->type, a->length) != 0) + return (ISC_FALSE); + } + return (ISC_TRUE); +} + +isc_boolean_t +isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b, + unsigned int prefixlen) +{ + isc_netaddr_t na, nb; + isc_netaddr_fromsockaddr(&na, a); + isc_netaddr_fromsockaddr(&nb, b); + return (isc_netaddr_eqprefix(&na, &nb, prefixlen)); +} + +isc_result_t +isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) { + isc_result_t result; + isc_netaddr_t netaddr; + char pbuf[sizeof("65000")]; + unsigned int plen; + isc_region_t avail; + + REQUIRE(sockaddr != NULL); + + /* + * Do the port first, giving us the opportunity to check for + * unsupported address families before calling + * isc_netaddr_fromsockaddr(). + */ + switch (sockaddr->type.sa.sa_family) { + case AF_INET: + snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port)); + break; + case AF_INET6: + snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port)); + break; + default: + return (ISC_R_FAILURE); + } + + plen = strlen(pbuf); + INSIST(plen < sizeof(pbuf)); + + isc_netaddr_fromsockaddr(&netaddr, sockaddr); + result = isc_netaddr_totext(&netaddr, target); + if (result != ISC_R_SUCCESS) + return (result); + + if (1 + plen + 1 > isc_buffer_availablelength(target)) + return (ISC_R_NOSPACE); + + isc_buffer_putmem(target, (const unsigned char *)"#", 1); + isc_buffer_putmem(target, (const unsigned char *)pbuf, plen); + + /* + * Null terminate after used region. + */ + isc_buffer_availableregion(target, &avail); + INSIST(avail.length >= 1); + avail.base[0] = '\0'; + + return (ISC_R_SUCCESS); +} + +void +isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) { + isc_result_t result; + isc_buffer_t buf; + + isc_buffer_init(&buf, array, size); + result = isc_sockaddr_totext(sa, &buf); + if (result != ISC_R_SUCCESS) { + /* + * The message is the same as in netaddr.c. + */ + snprintf(array, size, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR, + ISC_MSG_UNKNOWNADDR, + ""), + sa->type.sa.sa_family); + array[size - 1] = '\0'; + } +} + +#if 0 +/* + * We currently don't need hashing here + */ +unsigned int +isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) { + unsigned int length = 0; + const unsigned char *s = NULL; + unsigned int h = 0; + unsigned int g; + unsigned int p = 0; + const struct in6_addr *in6; + + REQUIRE(sockaddr != NULL); + + switch (sockaddr->type.sa.sa_family) { + case AF_INET: + s = (const unsigned char *)&sockaddr->type.sin.sin_addr; + p = ntohs(sockaddr->type.sin.sin_port); + length = sizeof(sockaddr->type.sin.sin_addr.s_addr); + break; + case AF_INET6: + in6 = &sockaddr->type.sin6.sin6_addr; + if (IN6_IS_ADDR_V4MAPPED(in6)) { + s = (const unsigned char *)&in6[12]; + length = sizeof(sockaddr->type.sin.sin_addr.s_addr); + } else { + s = (const unsigned char *)in6; + length = sizeof(sockaddr->type.sin6.sin6_addr); + } + p = ntohs(sockaddr->type.sin6.sin6_port); + break; + default: + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_SOCKADDR, + ISC_MSG_UNKNOWNFAMILY, + "unknown address family: %d"), + (int)sockaddr->type.sa.sa_family); + s = (const unsigned char *)&sockaddr->type; + length = sockaddr->length; + p = 0; + } + + h = isc_hash_calc(s, length, ISC_TRUE); + if (!address_only) { + g = isc_hash_calc((const unsigned char *)&p, sizeof(p), + ISC_TRUE); + h = h ^ g; /* XXX: we should concatenate h and p first */ + } + + return (h); +} +#endif + +void +isc_sockaddr_any(isc_sockaddr_t *sockaddr) +{ + memset(sockaddr, 0, sizeof(*sockaddr)); + sockaddr->type.sin.sin_family = AF_INET; +#ifdef ISC_PLATFORM_HAVESALEN + sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); +#endif + sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY; + sockaddr->type.sin.sin_port = 0; + sockaddr->length = sizeof(sockaddr->type.sin); + ISC_LINK_INIT(sockaddr, link); +} + +void +isc_sockaddr_any6(isc_sockaddr_t *sockaddr) +{ + memset(sockaddr, 0, sizeof(*sockaddr)); + sockaddr->type.sin6.sin6_family = AF_INET6; +#ifdef ISC_PLATFORM_HAVESALEN + sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); +#endif + sockaddr->type.sin6.sin6_addr = in6addr_any; + sockaddr->type.sin6.sin6_port = 0; + sockaddr->length = sizeof(sockaddr->type.sin6); + ISC_LINK_INIT(sockaddr, link); +} + +void +isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina, + in_port_t port) +{ + memset(sockaddr, 0, sizeof(*sockaddr)); + sockaddr->type.sin.sin_family = AF_INET; +#ifdef ISC_PLATFORM_HAVESALEN + sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); +#endif + sockaddr->type.sin.sin_addr = *ina; + sockaddr->type.sin.sin_port = htons(port); + sockaddr->length = sizeof(sockaddr->type.sin); + ISC_LINK_INIT(sockaddr, link); +} + +void +isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) { + switch (pf) { + case AF_INET: + isc_sockaddr_any(sockaddr); + break; + case AF_INET6: + isc_sockaddr_any6(sockaddr); + break; + default: + INSIST(0); + } +} + +void +isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6, + in_port_t port) +{ + memset(sockaddr, 0, sizeof(*sockaddr)); + sockaddr->type.sin6.sin6_family = AF_INET6; +#ifdef ISC_PLATFORM_HAVESALEN + sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); +#endif + sockaddr->type.sin6.sin6_addr = *ina6; + sockaddr->type.sin6.sin6_port = htons(port); + sockaddr->length = sizeof(sockaddr->type.sin6); + ISC_LINK_INIT(sockaddr, link); +} + +void +isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina, + in_port_t port) +{ + memset(sockaddr, 0, sizeof(*sockaddr)); + sockaddr->type.sin6.sin6_family = AF_INET6; +#ifdef ISC_PLATFORM_HAVESALEN + sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); +#endif + sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff; + sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff; + memcpy(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4); + sockaddr->type.sin6.sin6_port = htons(port); + sockaddr->length = sizeof(sockaddr->type.sin6); + ISC_LINK_INIT(sockaddr, link); +} + +int +isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) { + + /* + * Get the protocol family of 'sockaddr'. + */ + +#if (AF_INET == PF_INET && AF_INET6 == PF_INET6) + /* + * Assume that PF_xxx == AF_xxx for all AF and PF. + */ + return (sockaddr->type.sa.sa_family); +#else + switch (sockaddr->type.sa.sa_family) { + case AF_INET: + return (PF_INET); + case AF_INET6: + return (PF_INET6); + default: + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, + ISC_MSG_UNKNOWNFAMILY, + "unknown address family: %d"), + (int)sockaddr->type.sa.sa_family); + } +#endif +} + +void +isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na, + in_port_t port) +{ + memset(sockaddr, 0, sizeof(*sockaddr)); + sockaddr->type.sin.sin_family = na->family; + switch (na->family) { + case AF_INET: + sockaddr->length = sizeof(sockaddr->type.sin); +#ifdef ISC_PLATFORM_HAVESALEN + sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin); +#endif + sockaddr->type.sin.sin_addr = na->type.in; + sockaddr->type.sin.sin_port = htons(port); + break; + case AF_INET6: + sockaddr->length = sizeof(sockaddr->type.sin6); +#ifdef ISC_PLATFORM_HAVESALEN + sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6); +#endif + memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16); +#ifdef ISC_PLATFORM_HAVESCOPEID + sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na); +#endif + sockaddr->type.sin6.sin6_port = htons(port); + break; + default: + INSIST(0); + } + ISC_LINK_INIT(sockaddr, link); +} + +void +isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) { + switch (sockaddr->type.sa.sa_family) { + case AF_INET: + sockaddr->type.sin.sin_port = htons(port); + break; + case AF_INET6: + sockaddr->type.sin6.sin6_port = htons(port); + break; + default: + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, + ISC_MSG_UNKNOWNFAMILY, + "unknown address family: %d"), + (int)sockaddr->type.sa.sa_family); + } +} + +in_port_t +isc_sockaddr_getport(isc_sockaddr_t *sockaddr) { + in_port_t port = 0; + + switch (sockaddr->type.sa.sa_family) { + case AF_INET: + port = ntohs(sockaddr->type.sin.sin_port); + break; + case AF_INET6: + port = ntohs(sockaddr->type.sin6.sin6_port); + break; + default: + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR, + ISC_MSG_UNKNOWNFAMILY, + "unknown address family: %d"), + (int)sockaddr->type.sa.sa_family); + } + + return (port); +} + +isc_boolean_t +isc_sockaddr_ismulticast(isc_sockaddr_t *sockaddr) { + isc_netaddr_t netaddr; + + isc_netaddr_fromsockaddr(&netaddr, sockaddr); + return (isc_netaddr_ismulticast(&netaddr)); +} + +isc_boolean_t +isc_sockaddr_isexperimental(isc_sockaddr_t *sockaddr) { + isc_netaddr_t netaddr; + + if (sockaddr->type.sa.sa_family == AF_INET) { + isc_netaddr_fromsockaddr(&netaddr, sockaddr); + return (isc_netaddr_isexperimental(&netaddr)); + } + return (ISC_FALSE); +} + +isc_boolean_t +isc_sockaddr_issitelocal(isc_sockaddr_t *sockaddr) { + isc_netaddr_t netaddr; + + if (sockaddr->type.sa.sa_family == AF_INET6) { + isc_netaddr_fromsockaddr(&netaddr, sockaddr); + return (isc_netaddr_issitelocal(&netaddr)); + } + return (ISC_FALSE); +} + +isc_boolean_t +isc_sockaddr_islinklocal(isc_sockaddr_t *sockaddr) { + isc_netaddr_t netaddr; + + if (sockaddr->type.sa.sa_family == AF_INET6) { + isc_netaddr_fromsockaddr(&netaddr, sockaddr); + return (isc_netaddr_islinklocal(&netaddr)); + } + return (ISC_FALSE); +} diff --git a/ports/winnt/include/isc/ipv6.h b/ports/winnt/include/isc/ipv6.h index daaadb2338..c8c76e6d98 100644 --- a/ports/winnt/include/isc/ipv6.h +++ b/ports/winnt/include/isc/ipv6.h @@ -1,21 +1,21 @@ /* - * Copyright (C) 2000, 2001 Internet Software Consortium. + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2000-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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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: ipv6.h,v 1.10 2002/08/01 03:56:08 mayer Exp $ */ +/* $Id: ipv6.h,v 1.9.2.2.2.5 2004/04/19 06:39:55 marka Exp $ */ #ifndef ISC_IPV6_H #define ISC_IPV6_H 1 @@ -43,8 +43,9 @@ * RFC 2553. */ -#define s6_addr8 s6_addr +#if _MSC_VER < 1300 #define in6_addr in_addr6 +#endif #ifndef IN6ADDR_ANY_INIT #define IN6ADDR_ANY_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }} @@ -53,6 +54,9 @@ #define IN6ADDR_LOOPBACK_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }} #endif +extern const struct in6_addr isc_in6addr_any; +extern const struct in6_addr isc_in6addr_loopback; + /* * Unspecified */ @@ -105,7 +109,7 @@ */ #ifndef IN6_IS_ADDR_MULTICAST #define IN6_IS_ADDR_MULTICAST(a) \ - ((a)->s6_addr8[0] == 0xffU) + ((a)->s6_addr[0] == 0xffU) #endif /* * Unicast link / site local. diff --git a/ports/winnt/include/isc/net.h b/ports/winnt/include/isc/net.h index df7ff066b1..8f068d9a70 100644 --- a/ports/winnt/include/isc/net.h +++ b/ports/winnt/include/isc/net.h @@ -1,21 +1,21 @@ /* - * Copyright (C) 1999-2001 Internet Software Consortium. + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2003 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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.h,v 1.17 2002/08/01 03:56:08 mayer Exp $ */ +/* $Id: net.h,v 1.15.12.10 2004/04/29 01:31:23 marka Exp $ */ #ifndef ISC_NET_H #define ISC_NET_H 1 @@ -97,8 +97,8 @@ #include #include -//#include -//#include +#include +#include /* * This is here because named client, interfacemgr.c, etc. use the name as @@ -119,6 +119,11 @@ struct in6_pktinfo { #endif #endif +#if _MSC_VER < 1300 +#define in6addr_any isc_in6addr_any +#define in6addr_loopback isc_in6addr_loopback +#endif + /* * Ensure type in_port_t is defined. */ @@ -141,6 +146,10 @@ typedef isc_uint16_t in_port_t; (((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \ == ISC__IPADDR(0xe0000000)) +#define ISC_IPADDR_ISEXPERIMENTAL(i) \ + (((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \ + == ISC__IPADDR(0xf0000000)) + /* * Fix the FD_SET and FD_CLR Macros to properly cast */ @@ -234,6 +243,7 @@ isc_net_probeipv4(void); * * ISC_R_SUCCESS IPv4 is supported. * ISC_R_NOTFOUND IPv4 is not supported. + * ISC_R_DISABLED IPv4 is disabled. * ISC_R_UNEXPECTED */ @@ -246,9 +256,47 @@ isc_net_probeipv6(void); * * ISC_R_SUCCESS IPv6 is supported. * ISC_R_NOTFOUND IPv6 is not supported. + * ISC_R_DISABLED IPv6 is disabled. + * ISC_R_UNEXPECTED + */ + +isc_result_t +isc_net_probe_ipv6only(void); +/* + * Check if the system's kernel supports the IPV6_V6ONLY socket option. + * + * Returns: + * + * ISC_R_SUCCESS the option is supported for both TCP and UDP. + * ISC_R_NOTFOUND IPv6 itself or the option is not supported. * ISC_R_UNEXPECTED */ +isc_result_t +isc_net_probe_ipv6pktinfo(void); +/* + * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option + * for UDP sockets. + * + * Returns: + * + * ISC_R_SUCCESS the option is supported. + * ISC_R_NOTFOUND IPv6 itself or the option is not supported. + * ISC_R_UNEXPECTED + */ + +void +isc_net_disableipv4(void); + +void +isc_net_disableipv6(void); + +void +isc_net_enableipv4(void); + +void +isc_net_enableipv6(void); + #ifdef ISC_PLATFORM_NEEDNTOP const char * isc_net_ntop(int af, const void *src, char *dst, size_t size); diff --git a/ports/winnt/libisc/net.c b/ports/winnt/libisc/net.c index ea48cd2bd5..1b43f3008e 100644 --- a/ports/winnt/libisc/net.c +++ b/ports/winnt/libisc/net.c @@ -1,21 +1,21 @@ /* - * Copyright (C) 1999-2001 Internet Software Consortium. + * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2003 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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.4 2001/11/21 05:07:25 mayer Exp $ */ +/* $Id: net.c,v 1.3.2.2.4.7 2004/04/29 01:31:23 marka Exp $ */ #include @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -34,8 +35,12 @@ const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT; #endif static isc_boolean_t once = ISC_FALSE; +static isc_once_t once_ipv6only = ISC_ONCE_INIT; +static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT; static isc_result_t ipv4_result = ISC_R_NOTFOUND; static isc_result_t ipv6_result = ISC_R_NOTFOUND; +static isc_result_t ipv6only_result = ISC_R_NOTFOUND; +static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND; static isc_result_t try_proto(int domain) { @@ -62,6 +67,7 @@ try_proto(int domain) { } #ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 #ifdef ISC_PLATFORM_HAVEIN6PKTINFO if (domain == PF_INET6) { struct sockaddr_in6 sin6; @@ -83,6 +89,7 @@ try_proto(int domain) { } } #endif +#endif #endif closesocket(s); @@ -94,10 +101,12 @@ static void initialize_action(void) { ipv4_result = try_proto(PF_INET); #ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 #ifdef ISC_PLATFORM_HAVEIN6PKTINFO ipv6_result = try_proto(PF_INET6); #endif #endif +#endif } static void @@ -119,6 +128,193 @@ isc_net_probeipv6(void) { initialize(); return (ipv6_result); } +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 +static void +try_ipv6only(void) { +#ifdef IPV6_V6ONLY + SOCKET s; + int on; + char strbuf[ISC_STRERRORSIZE]; +#endif + isc_result_t result; + + result = isc_net_probeipv6(); + if (result != ISC_R_SUCCESS) { + ipv6only_result = result; + return; + } + +#ifndef IPV6_V6ONLY + ipv6only_result = ISC_R_NOTFOUND; + return; +#else + /* check for TCP sockets */ + s = socket(PF_INET6, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + ipv6only_result = ISC_R_UNEXPECTED; + return; + } + + on = 1; + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { + ipv6only_result = ISC_R_NOTFOUND; + goto close; + } + + close(s); + + /* check for UDP sockets */ + s = socket(PF_INET6, SOCK_DGRAM, 0); + if (s == INVALID_SOCKET) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + ipv6only_result = ISC_R_UNEXPECTED; + return; + } + + on = 1; + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { + ipv6only_result = ISC_R_NOTFOUND; + goto close; + } + + close(s); + + ipv6only_result = ISC_R_SUCCESS; + +close: + close(s); + return; +#endif /* IPV6_V6ONLY */ +} + +static void +initialize_ipv6only(void) { + RUNTIME_CHECK(isc_once_do(&once_ipv6only, + try_ipv6only) == ISC_R_SUCCESS); +} + +static void +try_ipv6pktinfo(void) { + int s, on; + char strbuf[ISC_STRERRORSIZE]; + isc_result_t result; + int optname; + + result = isc_net_probeipv6(); + if (result != ISC_R_SUCCESS) { + ipv6pktinfo_result = result; + return; + } + + /* we only use this for UDP sockets */ + s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if (s == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + ipv6pktinfo_result = ISC_R_UNEXPECTED; + return; + } + +#ifdef IPV6_RECVPKTINFO + optname = IPV6_RECVPKTINFO; +#else + optname = IPV6_PKTINFO; +#endif + on = 1; + if (setsockopt(s, IPPROTO_IPV6, optname, &on, sizeof(on)) < 0) { + ipv6pktinfo_result = ISC_R_NOTFOUND; + goto close; + } + + close(s); + ipv6pktinfo_result = ISC_R_SUCCESS; + +close: + close(s); + return; +} + +static void +initialize_ipv6pktinfo(void) { + RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo, + try_ipv6pktinfo) == ISC_R_SUCCESS); +} +#endif /* WANT_IPV6 */ +#endif /* ISC_PLATFORM_HAVEIPV6 */ + +isc_result_t +isc_net_probe_ipv6only(void) { +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 + initialize_ipv6only(); +#else + ipv6only_result = ISC_R_NOTFOUND; +#endif +#endif + return (ipv6only_result); +} + +isc_result_t +isc_net_probe_ipv6pktinfo(void) { +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 + initialize_ipv6pktinfo(); +#else + ipv6pktinfo_result = ISC_R_NOTFOUND; +#endif +#endif + return (ipv6pktinfo_result); +} + +void +isc_net_disableipv4(void) { + initialize(); + if (ipv4_result == ISC_R_SUCCESS) + ipv4_result = ISC_R_DISABLED; +} + +void +isc_net_disableipv6(void) { + initialize(); + if (ipv6_result == ISC_R_SUCCESS) + ipv6_result = ISC_R_DISABLED; +} + +void +isc_net_enableipv4(void) { + initialize(); + if (ipv4_result == ISC_R_DISABLED) + ipv4_result = ISC_R_SUCCESS; +} + +void +isc_net_enableipv6(void) { + initialize(); + if (ipv6_result == ISC_R_DISABLED) + ipv6_result = ISC_R_SUCCESS; +} /* * Initialize socket services */