]> git.stg.codes - ssmd.git/blob - 3rdparty/snmp++/src/IPv6Utility.cpp
Initial adding
[ssmd.git] / 3rdparty / snmp++ / src / IPv6Utility.cpp
1 /*_############################################################################
2   _## 
3   _##  IPv6Utility.cpp  
4   _##
5   _##  SNMP++v3.2.25
6   _##  -----------------------------------------------
7   _##  Copyright (c) 2001-2010 Jochen Katz, Frank Fock
8   _##
9   _##  This software is based on SNMP++2.6 from Hewlett Packard:
10   _##  
11   _##    Copyright (c) 1996
12   _##    Hewlett-Packard Company
13   _##  
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. 
25   _##  
26   _##  Stuttgart, Germany, Thu Sep  2 00:07:47 CEST 2010 
27   _##  
28   _##########################################################################*/
29 /*
30  * Copyright (C) 2004, 2005  Internet Systems Consortium, Inc. ("ISC")
31  * Copyright (C) 1996-2001  Internet Software Consortium.
32  *
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.
36  *
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.
44  */
45 /*===================================================================
46
47   SNMP++ IPv6Utility.h
48
49   DESCRIPTION:
50   This module contains the Utility functions for IPV6 support functions 
51   required for WIN32 environment
52
53   Adapted and integrated into snmp++ by Ragavan Tetchinamourty
54
55 =====================================================================*/
56 //XXX char ipv6utility_cpp_version[] = "@(#) SNMP++ $Id: $";
57
58 #include <stdio.h>  //use vsnprintf
59 #include "snmp_pp/IPv6Utility.h"
60
61 //FIXME #if defined(_MSC_VER) && defined(SNMP_PP_IPv6)
62 #if defined(WIN32) && defined(SNMP_PP_IPv6)
63
64 #define NS_INT16SZ      2
65 #define NS_INADDRSZ     4
66 #define NS_IN6ADDRSZ    16
67 #define EAFNOSUPPORT    WSAEAFNOSUPPORT
68 #define ENOSPC          28
69
70 /*
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.
73  */
74
75
76 static const char *inet_ntop4(const unsigned char *src, char *dst, size_t size);
77
78 #ifdef AF_INET6
79 static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size);
80 #endif
81
82 static int inet_pton4(const char *src, unsigned char *dst);
83 #ifdef AF_INET6
84 static int inet_pton6(const char *src, unsigned char *dst);
85 #endif
86
87
88
89 /* char *
90  * isc_net_ntop(af, src, dst, size)
91  *      convert a network format address to presentation format.
92  * return:
93  *      pointer to presentation format address (`dst'), or NULL (see errno).
94  * author:
95  *      Paul Vixie, 1996.
96  */
97 const char *
98 inet_ntop(int af, const void *src, char *dst, size_t size)
99 {
100         switch (af) {
101         case AF_INET:
102                 return (inet_ntop4((const unsigned char*)src, dst, size));
103 #ifdef AF_INET6
104         case AF_INET6:
105                 return (inet_ntop6((const unsigned char*)src, dst, size));
106 #endif
107         default:
108                 errno = EAFNOSUPPORT;
109                 return (NULL);
110         }
111         /* NOTREACHED */
112 }
113
114 #if defined(_MSC_VER)
115 static int
116 snprintf (char *str, int n, char *fmt, ...)
117 {
118 va_list a;
119 va_start (a, fmt);
120 int ret = vsnprintf (str, n, fmt, a);
121 va_end (a);
122 return ret;
123 }
124 #endif
125
126 /* const char *
127  * inet_ntop4(src, dst, size)
128  *      format an IPv4 address
129  * return:
130  *      `dst' (as a const)
131  * notes:
132  *      (1) uses no statics
133  *      (2) takes a unsigned char* not an in_addr as input
134  * author:
135  *      Paul Vixie, 1996.
136  */
137 static const char *
138 inet_ntop4(const unsigned char *src, char *dst, size_t size)
139 {
140         /*static const */char *fmt = "%u.%u.%u.%u";
141         char tmp[sizeof "255.255.255.255"];
142         size_t len;
143
144         len = snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]);   
145         
146         if (len >= size) {
147                 errno = ENOSPC;
148                 return (NULL);
149         }
150         memcpy(dst, tmp, len + 1);
151
152         return (dst);
153 }
154
155 /* const char *
156  * isc_inet_ntop6(src, dst, size)
157  *      convert IPv6 binary address into presentation (printable) format
158  * author:
159  *      Paul Vixie, 1996.
160  */
161 #ifdef AF_INET6
162 static const char *
163 inet_ntop6(const unsigned char *src, char *dst, size_t size)
164 {
165         /*
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.
171          */
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];
175         int i, inc;
176
177         /*
178          * Preprocess:
179          *      Copy the input (bytewise) array into a wordwise array.
180          *      Find the longest run of 0x00's in src[] for :: shorthanding.
181          */
182         memset(words, '\0', sizeof words);
183         for (i = 0; i < NS_IN6ADDRSZ; i++)
184                 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
185         best.base = -1;
186         cur.base = -1;
187         for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
188                 if (words[i] == 0) {
189                         if (cur.base == -1)
190                                 cur.base = i, cur.len = 1;
191                         else
192                                 cur.len++;
193                 } else {
194                         if (cur.base != -1) {
195                                 if (best.base == -1 || cur.len > best.len)
196                                         best = cur;
197                                 cur.base = -1;
198                         }
199                 }
200         }
201         if (cur.base != -1) {
202                 if (best.base == -1 || cur.len > best.len)
203                         best = cur;
204         }
205         if (best.base != -1 && best.len < 2)
206                 best.base = -1;
207
208         /*
209          * Format the result.
210          */
211         tp = tmp;
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)) {
216                         if (i == best.base)
217                                 *tp++ = ':';
218                         continue;
219                 }
220                 /* Are we following an initial run of 0x00s or any real hex? */
221                 if (i != 0)
222                         *tp++ = ':';
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)))
227                                 return (NULL);
228                         tp += strlen(tp);
229                         break;
230                 }
231                 inc = snprintf(tp, 5, "%x", words[i]);
232                 // Ragavan Commented
233                 //assert(inc < 5);
234                 tp += inc;
235         }
236         /* Was it a trailing run of 0x00's? */
237         if (best.base != -1 && (best.base + best.len) ==
238             (NS_IN6ADDRSZ / NS_INT16SZ))
239                 *tp++ = ':';
240         *tp++ = '\0';
241
242         /*
243          * Check for overflow, copy, and we're done.
244          */
245         if ((size_t)(tp - tmp) > size) {
246                 errno = ENOSPC;
247                 return (NULL);
248         }
249         memcpy(dst, tmp, tp - tmp);
250         return (dst);
251 }
252 #endif /* AF_INET6 */
253
254
255
256 /* int
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).
260  * return:
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)
264  * author:
265  *      Paul Vixie, 1996.
266  */
267 int
268 inet_pton(int af,
269           const char *src,
270           void *dst)
271 {
272         switch (af) {
273         case AF_INET:
274                 return (inet_pton4(src, (unsigned char *)dst));
275 #ifdef AF_INET6
276         case AF_INET6:
277                 return (inet_pton6(src, (unsigned char *)dst));
278 #endif
279         default:
280                 errno = EAFNOSUPPORT;
281                 return (-1);
282         }
283         /* NOTREACHED */
284 }
285
286 /* int
287  * inet_pton4(src, dst)
288  *      like inet_aton() but without all the hexadecimal and shorthand.
289  * return:
290  *      1 if `src' is a valid dotted quad, else 0.
291  * notice:
292  *      does not touch `dst' unless it's returning 1.
293  * author:
294  *      Paul Vixie, 1996.
295  */
296 static int
297 inet_pton4(const char *src, unsigned char *dst) 
298 {
299         static const char digits[] = "0123456789";
300         int saw_digit, octets, ch;
301         unsigned char tmp[NS_INADDRSZ], *tp;
302
303         saw_digit = 0;
304         octets = 0;
305         *(tp = tmp) = 0;
306         while ((ch = *src++) != '\0') {
307                 const char *pch;
308
309                 if ((pch = strchr(digits, ch)) != NULL) {
310                         unsigned int newstr = *tp * 10 + (pch - digits);
311
312                         if (newstr > 255)
313                                 return (0);
314                         *tp = newstr;
315                         if (! saw_digit) {
316                                 if (++octets > 4)
317                                         return (0);
318                                 saw_digit = 1;
319                         }
320                 } else if (ch == '.' && saw_digit) {
321                         if (octets == 4)
322                                 return (0);
323                         *++tp = 0;
324                         saw_digit = 0;
325                 } else
326                         return (0);
327         }
328         if (octets < 4)
329                 return (0);
330         memcpy(dst, tmp, NS_INADDRSZ);
331         return (1);
332 }
333
334 /* int
335  * inet_pton6(src, dst)
336  *      convert presentation level address to network order binary form.
337  * return:
338  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
339  * notice:
340  *      (1) does not touch `dst' unless it's returning 1.
341  *      (2) :: in a full address is silently ignored.
342  * credit:
343  *      inspired by Mark Andrews.
344  * author:
345  *      Paul Vixie, 1996.
346  */
347 #ifdef AF_INET6
348 static int
349 inet_pton6(const char *src, unsigned char *dst)
350 {
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;
355         int ch, saw_xdigit;
356         unsigned int val;
357
358         memset((tp = tmp), '\0', NS_IN6ADDRSZ);
359         endp = tp + NS_IN6ADDRSZ;
360         colonp = NULL;
361         /* Leading :: requires some special handling. */
362         if (*src == ':')
363                 if (*++src != ':')
364                         return (0);
365         curtok = src;
366         saw_xdigit = 0;
367         val = 0;
368         while ((ch = *src++) != '\0') {
369                 const char *pch;
370
371                 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
372                         pch = strchr((xdigits = xdigits_u), ch);
373                 if (pch != NULL) {
374                         val <<= 4;
375                         val |= (pch - xdigits);
376                         if (val > 0xffff)
377                                 return (0);
378                         saw_xdigit = 1;
379                         continue;
380                 }
381                 if (ch == ':') {
382                         curtok = src;
383                         if (!saw_xdigit) {
384                                 if (colonp)
385                                         return (0);
386                                 colonp = tp;
387                                 continue;
388                         }
389                         if (tp + NS_INT16SZ > endp)
390                                 return (0);
391                         *tp++ = (unsigned char) (val >> 8) & 0xff;
392                         *tp++ = (unsigned char) val & 0xff;
393                         saw_xdigit = 0;
394                         val = 0;
395                         continue;
396                 }
397                 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
398                     inet_pton4(curtok, tp) > 0) {
399                         tp += NS_INADDRSZ;
400                         saw_xdigit = 0;
401                         break;  /* '\0' was seen by inet_pton4(). */
402                 }
403                 return (0);
404         }
405         if (saw_xdigit) {
406                 if (tp + NS_INT16SZ > endp)
407                         return (0);
408                 *tp++ = (unsigned char) (val >> 8) & 0xff;
409                 *tp++ = (unsigned char) val & 0xff;
410         }
411         if (colonp != NULL) {
412                 /*
413                  * Since some memmove()'s erroneously fail to handle
414                  * overlapping regions, we'll do the shift by hand.
415                  */
416                 const int n = tp - colonp;
417                 int i;
418
419                 for (i = 1; i <= n; i++) {
420                         endp[- i] = colonp[n - i];
421                         colonp[n - i] = 0;
422                 }
423                 tp = endp;
424         }
425         if (tp != endp)
426                 return (0);
427         memcpy(dst, tmp, NS_IN6ADDRSZ);
428         return (1);
429 }
430 #endif // AF_INET6
431
432 #endif // defined(_MSC_VER) && defined(SNMP_PP_IPv6)