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