]> git.proxmox.com Git - mirror_edk2.git/blob - StdLib/BsdSocketLib/inet_net_pton.c
Add Socket Libraries.
[mirror_edk2.git] / StdLib / BsdSocketLib / inet_net_pton.c
1 /*
2 * Copyright (c) 1996 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 /*
19 * Portions copyright (c) 1999, 2000
20 * Intel Corporation.
21 * All rights reserved.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 *
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
29 *
30 * 2. Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in the
32 * documentation and/or other materials provided with the distribution.
33 *
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 *
37 * This product includes software developed by Intel Corporation and
38 * its contributors.
39 *
40 * 4. Neither the name of Intel Corporation or its contributors may be
41 * used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
45 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
48 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
54 * THE POSSIBILITY OF SUCH DAMAGE.
55 *
56 */
57
58 #if defined(LIBC_SCCS) && !defined(lint)
59 static const char orig_rcsid[] = "From Id: inet_net_pton.c,v 1.8 1996/11/21 10:28:12 vixie Exp $";
60 static const char rcsid[] = "$Id: inet_net_pton.c,v 1.1.1.1 2003/11/19 01:51:29 kyu3 Exp $";
61 #endif
62
63 #include <sys/types.h>
64 #include <sys/socket.h>
65 #include <netinet/in.h>
66 #include <arpa/inet.h>
67
68 #include <assert.h>
69 #include <ctype.h>
70 #include <errno.h>
71 #include <stdio.h>
72 #include <string.h>
73 #include <stdlib.h>
74
75 #ifdef SPRINTF_CHAR
76 # define SPRINTF(x) strlen(sprintf/**/x)
77 #else
78 # define SPRINTF(x) ((size_t)sprintf x)
79 #endif
80
81 static int inet_net_pton_ipv4 (const char *src, u_char *dst,
82 size_t size);
83
84 /*
85 * static int
86 * inet_net_pton(af, src, dst, size)
87 * convert network number from presentation to network format.
88 * accepts hex octets, hex strings, decimal octets, and /CIDR.
89 * "size" is in bytes and describes "dst".
90 * return:
91 * number of bits, either imputed classfully or specified with /CIDR,
92 * or -1 if some failure occurred (check errno). ENOENT means it was
93 * not a valid network specification.
94 * author:
95 * Paul Vixie (ISC), June 1996
96 */
97 int
98 inet_net_pton(
99 int af,
100 const char *src,
101 void *dst,
102 size_t size
103 )
104 {
105 switch (af) {
106 case AF_INET:
107 return (inet_net_pton_ipv4(src, dst, size));
108 default:
109 errno = EAFNOSUPPORT;
110 return (-1);
111 }
112 }
113
114 /*
115 * static int
116 * inet_net_pton_ipv4(src, dst, size)
117 * convert IPv4 network number from presentation to network format.
118 * accepts hex octets, hex strings, decimal octets, and /CIDR.
119 * "size" is in bytes and describes "dst".
120 * return:
121 * number of bits, either imputed classfully or specified with /CIDR,
122 * or -1 if some failure occurred (check errno). ENOENT means it was
123 * not an IPv4 network specification.
124 * note:
125 * network byte order assumed. this means 192.5.5.240/28 has
126 * 0x11110000 in its fourth octet.
127 * author:
128 * Paul Vixie (ISC), June 1996
129 */
130 static int
131 inet_net_pton_ipv4(
132 const char *src,
133 u_char *dst,
134 size_t size
135 )
136 {
137 static const char xdigits[] = "0123456789abcdef";
138 static const char digits[] = "0123456789";
139 int n;
140 int ch;
141 int tmp;
142 int dirty;
143 int bits;
144 const u_char *odst = dst;
145
146 ch = *src++;
147 if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
148 && isascii(src[1]) && isxdigit(src[1])) {
149 /* Hexadecimal: Eat nybble string. */
150 if (size <= 0)
151 goto emsgsize;
152 *dst = 0, dirty = 0;
153 src++; /* skip x or X. */
154 while ((ch = *src++) != '\0' &&
155 isascii(ch) && isxdigit(ch)) {
156 if (isupper(ch))
157 ch = tolower(ch);
158 n = (int)(strchr(xdigits, ch) - xdigits);
159 assert(n >= 0 && n <= 15);
160 *dst |= n;
161 if (!dirty++)
162 *dst <<= 4;
163 else if (size-- > 0)
164 *++dst = 0, dirty = 0;
165 else
166 goto emsgsize;
167 }
168 if (dirty)
169 size--;
170 } else if (isascii(ch) && isdigit(ch)) {
171 /* Decimal: eat dotted digit string. */
172 for (;;) {
173 tmp = 0;
174 do {
175 n = (int)(strchr(digits, ch) - digits);
176 assert(n >= 0 && n <= 9);
177 tmp *= 10;
178 tmp += n;
179 if (tmp > 255)
180 goto enoent;
181 } while ((ch = *src++) != '\0' &&
182 isascii(ch) && isdigit(ch));
183 if (size-- <= 0)
184 goto emsgsize;
185 *dst++ = (u_char) tmp;
186 if (ch == '\0' || ch == '/')
187 break;
188 if (ch != '.')
189 goto enoent;
190 ch = *src++;
191 if (!isascii(ch) || !isdigit(ch))
192 goto enoent;
193 }
194 } else
195 goto enoent;
196
197 bits = -1;
198 if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
199 /* CIDR width specifier. Nothing can follow it. */
200 ch = *src++; /* Skip over the /. */
201 bits = 0;
202 do {
203 n = (int)(strchr(digits, ch) - digits);
204 assert(n >= 0 && n <= 9);
205 bits *= 10;
206 bits += n;
207 } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
208 if (ch != '\0')
209 goto enoent;
210 if (bits > 32)
211 goto emsgsize;
212 }
213
214 /* Firey death and destruction unless we prefetched EOS. */
215 if (ch != '\0')
216 goto enoent;
217
218 /* If nothing was written to the destination, we found no address. */
219 if (dst == odst)
220 goto enoent;
221 /* If no CIDR spec was given, infer width from net class. */
222 if (bits == -1) {
223 if (*odst >= 240) /* Class E */
224 bits = 32;
225 else if (*odst >= 224) /* Class D */
226 bits = 4;
227 else if (*odst >= 192) /* Class C */
228 bits = 24;
229 else if (*odst >= 128) /* Class B */
230 bits = 16;
231 else /* Class A */
232 bits = 8;
233 /* If imputed mask is narrower than specified octets, widen. */
234 if (bits >= 8 && bits < ((dst - odst) * 8))
235 bits = (int)(dst - odst) * 8;
236 }
237 /* Extend network to cover the actual mask. */
238 while (bits > ((dst - odst) * 8)) {
239 if (size-- <= 0)
240 goto emsgsize;
241 *dst++ = '\0';
242 }
243 return (bits);
244
245 enoent:
246 errno = ENOENT;
247 return (-1);
248
249 emsgsize:
250 errno = EMSGSIZE;
251 return (-1);
252 }