]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
ports from BIND 9.3.0 and reintegrated into ntp libisc xode
authorDanny Mayer <mayer@ntp.org>
Thu, 23 Dec 2004 05:16:06 +0000 (00:16 -0500)
committerDanny Mayer <mayer@ntp.org>
Thu, 23 Dec 2004 05:16:06 +0000 (00:16 -0500)
bk: 41ca54963FEQg_32ZWhdjI8VrB2kaw

14 files changed:
include/isc/buffer.h [new file with mode: 0644]
include/isc/net.h
include/isc/netaddr.h
include/isc/netscope.h [new file with mode: 0644]
include/isc/region.h [new file with mode: 0644]
include/isc/result.h
include/isc/sockaddr.h
libisc/net.c
libisc/netaddr.c [new file with mode: 0644]
libisc/netscope.c [new file with mode: 0644]
libisc/sockaddr.c [new file with mode: 0644]
ports/winnt/include/isc/ipv6.h
ports/winnt/include/isc/net.h
ports/winnt/libisc/net.c

diff --git a/include/isc/buffer.h b/include/isc/buffer.h
new file mode 100644 (file)
index 0000000..02b82bc
--- /dev/null
@@ -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 <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/types.h>
+
+/*
+ * 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 */
index 25924febca389273f5d5be0bb6a9688dc77a24c3..a5d9859f157ed836d090c496537fc16cf97b5573 100644 (file)
@@ -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 <sys/types.h>
 #include <sys/socket.h>                /* Contractual promise. */
 
+#include <net/if.h>
+
 #include <netinet/in.h>                /* Contractual promise. */
 #include <arpa/inet.h>         /* 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
index 811e8dd48e0c8162c6022b81560a05677e1ee318..e209a9fa77497663ad933e16014e511f23bc8b6c 100644 (file)
@@ -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 <isc/lang.h>
 #include <isc/net.h>
 #include <isc/types.h>
-#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 (file)
index 0000000..7cc0f18
--- /dev/null
@@ -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 (file)
index 0000000..5622394
--- /dev/null
@@ -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 <isc/types.h>
+
+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 */
index bf6b99258732293e22031f753e39d5165bf3f9ae..93f7cefbd658b4272813c122f8beb8d3049d5958 100644 (file)
@@ -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
 #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
 
index 5257b059de01fbe4ed0c4a020ef0d7de0037da6b..635af38117bf5d4061893a03740809bc34a16a01 100644 (file)
@@ -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);
 /*
index 6c51f1c973fdd4f7241813b32f009b45ebe0aa1d..db832667f184e8ce3ce0a40b1cc9cb547155435d 100644 (file)
@@ -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 <config.h>
 
@@ -23,6 +23,7 @@
 #include <unistd.h>
 
 #include <isc/net.h>
+#include <isc/once.h>
 #include <isc/strerror.h>
 #include <isc/string.h>
 #include <isc/util.h>
 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 (file)
index 0000000..712ad2c
--- /dev/null
@@ -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 <config.h>
+
+#include <stdio.h>
+
+#include <isc/buffer.h>
+#include <isc/msgs.h>
+#include <isc/net.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+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,
+                                       "<unknown address, family %u>"),
+                        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 (file)
index 0000000..f0bffc4
--- /dev/null
@@ -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 <config.h>
+
+#include <isc/string.h>
+#include <isc/net.h>
+#include <isc/netscope.h>
+#include <isc/result.h>
+
+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 (file)
index 0000000..2855885
--- /dev/null
@@ -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 <config.h>
+
+#include <stdio.h>
+
+#include <isc/buffer.h>
+/*
+ * We currently don't need hashing here
+ */
+#if 0
+#include <isc/hash.h>
+#endif
+
+#include <isc/msgs.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+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,
+                                       "<unknown address, family %u>"),
+                        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);
+}
index daaadb2338dd4d6812305078493739cb2eb131fe..c8c76e6d98618ec0b2db600f6dd2998c3fd25d32 100644 (file)
@@ -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
  */
  */
 #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.
index df7ff066b160ad513ddf8f8bd15c6f59c53ac8d0..8f068d9a707120fa0138f90c5f1e3fc1161644a8 100644 (file)
@@ -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 <isc/lang.h>
 #include <isc/types.h>
 
-//#include <ws2tcpip.h>
-//#include <isc/ipv6.h>
+#include <ws2tcpip.h>
+#include <isc/ipv6.h>
 
 /*
  * 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);
index ea48cd2bd537ff6f5d42fa5630f4bbcac75ee8df..1b43f3008e5ec7d561f2b013d4807c4e63183908 100644 (file)
@@ -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 <config.h>
 
@@ -25,6 +25,7 @@
 #include <ws2tcpip.h>
 #include <isc/ipv6.h>
 #include <isc/net.h>
+#include <isc/once.h>
 #include <isc/strerror.h>
 #include <isc/string.h>
 #include <isc/util.h>
@@ -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
  */