Replace the types from sys/types.h and netinet/in.h by their glib.h
[obnox/wireshark/wip.git] / epan / inet_pton.c
1 /*
2  * Copyright (c) 1996,1999 by Internet Software Consortium.
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15  * SOFTWARE.
16  */
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #if defined(LIBC_SCCS) && !defined(lint)
23 static char rcsid[] = "$Id: inet_pton.c,v 1.3 2002/08/02 21:29:39 jmayer Exp $";
24 #endif /* LIBC_SCCS and not lint */
25
26 #ifdef HAVE_SYS_PARAM_H
27 #include <sys/param.h>
28 #endif
29
30 #ifdef HAVE_WINSOCK2_H
31 #include <winsock2.h>
32 #define EAFNOSUPPORT    WSAEAFNOSUPPORT
33 #endif
34
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h>
37 #endif
38
39 #ifdef HAVE_ARPA_INET_H
40 #include <arpa/inet.h>
41 #endif
42
43 #ifdef HAVE_ARPA_NAMESER_H
44 #include <arpa/nameser.h>
45 #endif
46
47 #include <string.h>
48 #include <errno.h>
49
50 #include "inet_v6defs.h"
51
52 #ifndef NS_INADDRSZ
53 #define NS_INADDRSZ     4
54 #endif
55 #ifndef NS_IN6ADDRSZ
56 #define NS_IN6ADDRSZ    16
57 #endif
58 #ifndef NS_INT16SZ
59 #define NS_INT16SZ      2
60 #endif
61
62 /*
63  * WARNING: Don't even consider trying to compile this on a system where
64  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
65  */
66
67 #ifdef AF_INET
68 static int      inet_pton4 __P((const char *src, guchar *dst));
69 #endif
70 #ifdef AF_INET6
71 static int      inet_pton6 __P((const char *src, guchar *dst));
72 #endif
73
74 /* int
75  * inet_pton(af, src, dst)
76  *      convert from presentation format (which usually means ASCII printable)
77  *      to network format (which is usually some kind of binary format).
78  * return:
79  *      1 if the address was valid for the specified address family
80  *      0 if the address wasn't valid (`dst' is untouched in this case)
81  *      -1 if some other error occurred (`dst' is untouched in this case, too)
82  * author:
83  *      Paul Vixie, 1996.
84  */
85 int
86 inet_pton(af, src, dst)
87         int af;
88         const char *src;
89         void *dst;
90 {
91         switch (af) {
92 #ifdef AF_INET
93         case AF_INET:
94                 return (inet_pton4(src, dst));
95 #endif
96 #ifdef AF_INET6
97         case AF_INET6:
98                 return (inet_pton6(src, dst));
99 #endif
100         default:
101                 errno = EAFNOSUPPORT;
102                 return (-1);
103         }
104         /* NOTREACHED */
105 }
106
107 #ifdef AF_INET
108 /* int
109  * inet_pton4(src, dst)
110  *      like inet_aton() but without all the hexadecimal and shorthand.
111  * return:
112  *      1 if `src' is a valid dotted quad, else 0.
113  * notice:
114  *      does not touch `dst' unless it's returning 1.
115  * author:
116  *      Paul Vixie, 1996.
117  */
118 static int
119 inet_pton4(src, dst)
120         const char *src;
121         guchar *dst;
122 {
123         static const char digits[] = "0123456789";
124         int saw_digit, octets, ch;
125         guchar tmp[NS_INADDRSZ], *tp;
126
127         saw_digit = 0;
128         octets = 0;
129         *(tp = tmp) = 0;
130         while ((ch = *src++) != '\0') {
131                 const char *pch;
132
133                 if ((pch = strchr(digits, ch)) != NULL) {
134                         guint new = *tp * 10 + (pch - digits);
135
136                         if (new > 255)
137                                 return (0);
138                         *tp = new;
139                         if (! saw_digit) {
140                                 if (++octets > 4)
141                                         return (0);
142                                 saw_digit = 1;
143                         }
144                 } else if (ch == '.' && saw_digit) {
145                         if (octets == 4)
146                                 return (0);
147                         *++tp = 0;
148                         saw_digit = 0;
149                 } else
150                         return (0);
151         }
152         if (octets < 4)
153                 return (0);
154         memcpy(dst, tmp, NS_INADDRSZ);
155         return (1);
156 }
157 #endif
158
159 #ifdef AF_INET6
160 /* int
161  * inet_pton6(src, dst)
162  *      convert presentation level address to network order binary form.
163  * return:
164  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
165  * notice:
166  *      (1) does not touch `dst' unless it's returning 1.
167  *      (2) :: in a full address is silently ignored.
168  * credit:
169  *      inspired by Mark Andrews.
170  * author:
171  *      Paul Vixie, 1996.
172  */
173 static int
174 inet_pton6(src, dst)
175         const char *src;
176         guchar *dst;
177 {
178         static const char xdigits_l[] = "0123456789abcdef",
179                           xdigits_u[] = "0123456789ABCDEF";
180         guchar tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
181         const char *xdigits, *curtok;
182         int ch, saw_xdigit;
183         guint val;
184
185         memset((tp = tmp), '\0', NS_IN6ADDRSZ);
186         endp = tp + NS_IN6ADDRSZ;
187         colonp = NULL;
188         /* Leading :: requires some special handling. */
189         if (*src == ':')
190                 if (*++src != ':')
191                         return (0);
192         curtok = src;
193         saw_xdigit = 0;
194         val = 0;
195         while ((ch = *src++) != '\0') {
196                 const char *pch;
197
198                 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
199                         pch = strchr((xdigits = xdigits_u), ch);
200                 if (pch != NULL) {
201                         val <<= 4;
202                         val |= (pch - xdigits);
203                         if (val > 0xffff)
204                                 return (0);
205                         saw_xdigit = 1;
206                         continue;
207                 }
208                 if (ch == ':') {
209                         curtok = src;
210                         if (!saw_xdigit) {
211                                 if (colonp)
212                                         return (0);
213                                 colonp = tp;
214                                 continue;
215                         } else if (*src == '\0') {
216                                 return (0);
217                         }
218                         if (tp + NS_INT16SZ > endp)
219                                 return (0);
220                         *tp++ = (guchar) (val >> 8) & 0xff;
221                         *tp++ = (guchar) val & 0xff;
222                         saw_xdigit = 0;
223                         val = 0;
224                         continue;
225                 }
226                 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
227                     inet_pton4(curtok, tp) > 0) {
228                         tp += NS_INADDRSZ;
229                         saw_xdigit = 0;
230                         break;  /* '\0' was seen by inet_pton4(). */
231                 }
232                 return (0);
233         }
234         if (saw_xdigit) {
235                 if (tp + NS_INT16SZ > endp)
236                         return (0);
237                 *tp++ = (guchar) (val >> 8) & 0xff;
238                 *tp++ = (guchar) val & 0xff;
239         }
240         if (colonp != NULL) {
241                 /*
242                  * Since some memmove()'s erroneously fail to handle
243                  * overlapping regions, we'll do the shift by hand.
244                  */
245                 const int n = tp - colonp;
246                 int i;
247
248                 if (tp == endp)
249                         return (0);
250                 for (i = 1; i <= n; i++) {
251                         endp[- i] = colonp[n - i];
252                         colonp[n - i] = 0;
253                 }
254                 tp = endp;
255         }
256         if (tp != endp)
257                 return (0);
258         memcpy(dst, tmp, NS_IN6ADDRSZ);
259         return (1);
260 }
261 #endif