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