]> sjero.net Git - iperf/blob - compat/inet_pton.c
Original 2.0.2 iperf sources
[iperf] / compat / inet_pton.c
1 #include "inet_aton.h"
2 #ifdef __cplusplus
3 extern "C" {
4 #endif
5
6 /*
7  * Copyright (C) 1996-2001  Internet Software Consortium.
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
14  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
16  * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
17  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
18  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
19  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
20  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23 #ifndef HAVE_INET_PTON
24 #define NS_INT16SZ       2
25 #define NS_INADDRSZ     4
26 #define NS_IN6ADDRSZ    16
27
28 /* int
29  * isc_net_pton(af, src, dst)
30  *      convert from presentation format (which usually means ASCII printable)
31  *      to network format (which is usually some kind of binary format).
32  * return:
33  *      1 if the address was valid for the specified address family
34  *      0 if the address wasn't valid (`dst' is untouched in this case)
35  * author:
36  *      Paul Vixie, 1996.
37  */
38 int
39 inet_pton(int af,
40           const char *src,
41           void *dst) {
42     switch ( af ) {
43         case AF_INET:
44             return(inet_pton4(src, dst));
45 #ifdef HAVE_IPV6
46         case AF_INET6:
47             return(inet_pton6(src, dst));
48 #endif
49         default:
50             return 0;
51     }
52     /* NOTREACHED */
53 }
54
55 /* int
56  * inet_pton4(src, dst)
57  *      like inet_aton() but without all the hexadecimal and shorthand.
58  * return:
59  *      1 if `src' is a valid dotted quad, else 0.
60  * notice:
61  *      does not touch `dst' unless it's returning 1.
62  * author:
63  *      Paul Vixie, 1996.
64  */
65 int
66 inet_pton4(src, dst)
67 const char *src;
68 unsigned char *dst;
69 {
70     static const char digits[] = "0123456789";
71     int saw_digit, octets, ch;
72     unsigned char tmp[NS_INADDRSZ], *tp;
73
74     saw_digit = 0;
75     octets = 0;
76     *(tp = tmp) = 0;
77     while ( (ch = *src++) != '\0' ) {
78         const char *pch;
79
80         if ( (pch = strchr(digits, ch)) != NULL ) {
81             unsigned int new = *tp * 10 + (pch - digits);
82
83             if ( new > 255 )
84                 return(0);
85             *tp = new;
86             if ( ! saw_digit ) {
87                 if ( ++octets > 4 )
88                     return(0);
89                 saw_digit = 1;
90             }
91         } else if ( ch == '.' && saw_digit ) {
92             if ( octets == 4 )
93                 return(0);
94             *++tp = 0;
95             saw_digit = 0;
96         } else
97             return(0);
98     }
99     if ( octets < 4 )
100         return(0);
101     memcpy(dst, tmp, NS_INADDRSZ);
102     return(1);
103 }
104
105 /* int
106  * inet_pton6(src, dst)
107  *      convert presentation level address to network order binary form.
108  * return:
109  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
110  * notice:
111  *      (1) does not touch `dst' unless it's returning 1.
112  *      (2) :: in a full address is silently ignored.
113  * credit:
114  *      inspired by Mark Andrews.
115  * author:
116  *      Paul Vixie, 1996.
117  */
118 #ifdef HAVE_IPV6
119 int
120 inet_pton6(src, dst)
121 const char *src;
122 unsigned char *dst;
123 {
124     static const char xdigits_l[] = "0123456789abcdef",
125     xdigits_u[] = "0123456789ABCDEF";
126     unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
127     const char *xdigits, *curtok;
128     int ch, saw_xdigit;
129     unsigned int val;
130
131     memset((tp = tmp), '\0', NS_IN6ADDRSZ);
132     endp = tp + NS_IN6ADDRSZ;
133     colonp = NULL;
134     /* Leading :: requires some special handling. */
135     if ( *src == ':' )
136         if ( *++src != ':' )
137             return(0);
138     curtok = src;
139     saw_xdigit = 0;
140     val = 0;
141     while ( (ch = *src++) != '\0' ) {
142         const char *pch;
143
144         if ( (pch = strchr((xdigits = xdigits_l), ch)) == NULL )
145             pch = strchr((xdigits = xdigits_u), ch);
146         if ( pch != NULL ) {
147             val <<= 4;
148             val |= (pch - xdigits);
149             if ( val > 0xffff )
150                 return(0);
151             saw_xdigit = 1;
152             continue;
153         }
154         if ( ch == ':' ) {
155             curtok = src;
156             if ( !saw_xdigit ) {
157                 if ( colonp )
158                     return(0);
159                 colonp = tp;
160                 continue;
161             }
162             if ( tp + NS_INT16SZ > endp )
163                 return(0);
164             *tp++ = (unsigned char) (val >> 8) & 0xff;
165             *tp++ = (unsigned char) val & 0xff;
166             saw_xdigit = 0;
167             val = 0;
168             continue;
169         }
170         if ( ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
171              inet_pton4(curtok, tp) > 0 ) {
172             tp += NS_INADDRSZ;
173             saw_xdigit = 0;
174             break;  /* '\0' was seen by inet_pton4(). */
175         }
176         return(0);
177     }
178     if ( saw_xdigit ) {
179         if ( tp + NS_INT16SZ > endp )
180             return(0);
181         *tp++ = (unsigned char) (val >> 8) & 0xff;
182         *tp++ = (unsigned char) val & 0xff;
183     }
184     if ( colonp != NULL ) {
185         /*
186          * Since some memmove()'s erroneously fail to handle
187          * overlapping regions, we'll do the shift by hand.
188          */
189         const int n = tp - colonp;
190         int i;
191
192         for ( i = 1; i <= n; i++ ) {
193             endp[- i] = colonp[n - i];
194             colonp[n - i] = 0;
195         }
196         tp = endp;
197     }
198     if ( tp != endp )
199         return(0);
200     memcpy(dst, tmp, NS_IN6ADDRSZ);
201     return(1);
202 }
203 #endif
204
205 #endif /* HAVE_INET_PTON */
206
207 #ifdef __cplusplus
208 } /* end extern "C" */
209 #endif