1 /*_############################################################################
6 _## -----------------------------------------------
7 _## Copyright (c) 2001-2010 Jochen Katz, Frank Fock
9 _## This software is based on SNMP++2.6 from Hewlett Packard:
11 _## Copyright (c) 1996
12 _## Hewlett-Packard Company
14 _## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
15 _## Permission to use, copy, modify, distribute and/or sell this software
16 _## and/or its documentation is hereby granted without fee. User agrees
17 _## to display the above copyright notice and this license notice in all
18 _## copies of the software and any documentation of the software. User
19 _## agrees to assume all liability for the use of the software;
20 _## Hewlett-Packard and Jochen Katz make no representations about the
21 _## suitability of this software for any purpose. It is provided
22 _## "AS-IS" without warranty of any kind, either express or implied. User
23 _## hereby grants a royalty-free license to any and all derivatives based
24 _## upon this software code base.
26 _## Stuttgart, Germany, Thu Sep 2 00:07:47 CEST 2010
28 _##########################################################################*/
30 * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
31 * Copyright (C) 1996-2001 Internet Software Consortium.
33 * Permission to use, copy, modify, and distribute this software for any
34 * purpose with or without fee is hereby granted, provided that the above
35 * copyright notice and this permission notice appear in all copies.
37 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
38 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
39 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
40 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
41 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
42 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
43 * PERFORMANCE OF THIS SOFTWARE.
45 /*===================================================================
50 This module contains the Utility functions for IPV6 support functions
51 required for WIN32 environment
53 Adapted and integrated into snmp++ by Ragavan Tetchinamourty
55 =====================================================================*/
56 //XXX char ipv6utility_cpp_version[] = "@(#) SNMP++ $Id: $";
58 #include <stdio.h> //use vsnprintf
59 #include "snmp_pp/IPv6Utility.h"
61 //FIXME #if defined(_MSC_VER) && defined(SNMP_PP_IPv6)
62 #if defined(WIN32) && defined(SNMP_PP_IPv6)
66 #define NS_IN6ADDRSZ 16
67 #define EAFNOSUPPORT WSAEAFNOSUPPORT
71 * WARNING: Don't even consider trying to compile this on a system where
72 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
76 static const char *inet_ntop4(const unsigned char *src, char *dst, size_t size);
79 static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size);
82 static int inet_pton4(const char *src, unsigned char *dst);
84 static int inet_pton6(const char *src, unsigned char *dst);
90 * isc_net_ntop(af, src, dst, size)
91 * convert a network format address to presentation format.
93 * pointer to presentation format address (`dst'), or NULL (see errno).
98 inet_ntop(int af, const void *src, char *dst, size_t size)
102 return (inet_ntop4((const unsigned char*)src, dst, size));
105 return (inet_ntop6((const unsigned char*)src, dst, size));
108 errno = EAFNOSUPPORT;
114 #if defined(_MSC_VER)
116 snprintf (char *str, int n, char *fmt, ...)
120 int ret = vsnprintf (str, n, fmt, a);
127 * inet_ntop4(src, dst, size)
128 * format an IPv4 address
132 * (1) uses no statics
133 * (2) takes a unsigned char* not an in_addr as input
138 inet_ntop4(const unsigned char *src, char *dst, size_t size)
140 /*static const */char *fmt = "%u.%u.%u.%u";
141 char tmp[sizeof "255.255.255.255"];
144 len = snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]);
150 memcpy(dst, tmp, len + 1);
156 * isc_inet_ntop6(src, dst, size)
157 * convert IPv6 binary address into presentation (printable) format
163 inet_ntop6(const unsigned char *src, char *dst, size_t size)
166 * Note that int32_t and int16_t need only be "at least" large enough
167 * to contain a value of the specified size. On some systems, like
168 * Crays, there is no such thing as an integer variable with 16 bits.
169 * Keep this in mind if you think this function should have been coded
170 * to use pointer overlays. All the world's not a VAX.
172 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
173 struct { int base, len; } best, cur;
174 unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
179 * Copy the input (bytewise) array into a wordwise array.
180 * Find the longest run of 0x00's in src[] for :: shorthanding.
182 memset(words, '\0', sizeof words);
183 for (i = 0; i < NS_IN6ADDRSZ; i++)
184 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
187 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
190 cur.base = i, cur.len = 1;
194 if (cur.base != -1) {
195 if (best.base == -1 || cur.len > best.len)
201 if (cur.base != -1) {
202 if (best.base == -1 || cur.len > best.len)
205 if (best.base != -1 && best.len < 2)
212 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
213 /* Are we inside the best run of 0x00's? */
214 if (best.base != -1 && i >= best.base &&
215 i < (best.base + best.len)) {
220 /* Are we following an initial run of 0x00s or any real hex? */
223 /* Is this address an encapsulated IPv4? */
224 if (i == 6 && best.base == 0 &&
225 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
226 if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
231 inc = snprintf(tp, 5, "%x", words[i]);
236 /* Was it a trailing run of 0x00's? */
237 if (best.base != -1 && (best.base + best.len) ==
238 (NS_IN6ADDRSZ / NS_INT16SZ))
243 * Check for overflow, copy, and we're done.
245 if ((size_t)(tp - tmp) > size) {
249 memcpy(dst, tmp, tp - tmp);
252 #endif /* AF_INET6 */
257 * inet_pton(af, src, dst)
258 * convert from presentation format (which usually means ASCII printable)
259 * to network format (which is usually some kind of binary format).
261 * 1 if the address was valid for the specified address family
262 * 0 if the address wasn't valid (`dst' is untouched in this case)
263 * -1 if some other error occurred (`dst' is untouched in this case, too)
274 return (inet_pton4(src, (unsigned char *)dst));
277 return (inet_pton6(src, (unsigned char *)dst));
280 errno = EAFNOSUPPORT;
287 * inet_pton4(src, dst)
288 * like inet_aton() but without all the hexadecimal and shorthand.
290 * 1 if `src' is a valid dotted quad, else 0.
292 * does not touch `dst' unless it's returning 1.
297 inet_pton4(const char *src, unsigned char *dst)
299 static const char digits[] = "0123456789";
300 int saw_digit, octets, ch;
301 unsigned char tmp[NS_INADDRSZ], *tp;
306 while ((ch = *src++) != '\0') {
309 if ((pch = strchr(digits, ch)) != NULL) {
310 unsigned int newstr = *tp * 10 + (pch - digits);
320 } else if (ch == '.' && saw_digit) {
330 memcpy(dst, tmp, NS_INADDRSZ);
335 * inet_pton6(src, dst)
336 * convert presentation level address to network order binary form.
338 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
340 * (1) does not touch `dst' unless it's returning 1.
341 * (2) :: in a full address is silently ignored.
343 * inspired by Mark Andrews.
349 inet_pton6(const char *src, unsigned char *dst)
351 static const char xdigits_l[] = "0123456789abcdef",
352 xdigits_u[] = "0123456789ABCDEF";
353 unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
354 const char *xdigits, *curtok;
358 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
359 endp = tp + NS_IN6ADDRSZ;
361 /* Leading :: requires some special handling. */
368 while ((ch = *src++) != '\0') {
371 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
372 pch = strchr((xdigits = xdigits_u), ch);
375 val |= (pch - xdigits);
389 if (tp + NS_INT16SZ > endp)
391 *tp++ = (unsigned char) (val >> 8) & 0xff;
392 *tp++ = (unsigned char) val & 0xff;
397 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
398 inet_pton4(curtok, tp) > 0) {
401 break; /* '\0' was seen by inet_pton4(). */
406 if (tp + NS_INT16SZ > endp)
408 *tp++ = (unsigned char) (val >> 8) & 0xff;
409 *tp++ = (unsigned char) val & 0xff;
411 if (colonp != NULL) {
413 * Since some memmove()'s erroneously fail to handle
414 * overlapping regions, we'll do the shift by hand.
416 const int n = tp - colonp;
419 for (i = 1; i <= n; i++) {
420 endp[- i] = colonp[n - i];
427 memcpy(dst, tmp, NS_IN6ADDRSZ);
432 #endif // defined(_MSC_VER) && defined(SNMP_PP_IPv6)