summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/inet_net_pton.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net/inet_net_pton.c')
-rw-r--r--src/lib/libc/net/inet_net_pton.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/src/lib/libc/net/inet_net_pton.c b/src/lib/libc/net/inet_net_pton.c
new file mode 100644
index 0000000000..3c72efac6b
--- /dev/null
+++ b/src/lib/libc/net/inet_net_pton.c
@@ -0,0 +1,206 @@
1/* $OpenBSD: inet_net_pton.c,v 1.3 2003/04/25 19:40:25 henning Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static const char rcsid[] = "$From: inet_net_pton.c,v 8.3 1996/11/11 06:36:52 vixie Exp $";
23#else
24static const char rcsid[] = "$OpenBSD: inet_net_pton.c,v 1.3 2003/04/25 19:40:25 henning Exp $";
25#endif
26#endif
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <assert.h>
34#include <ctype.h>
35#include <errno.h>
36#include <stdio.h>
37#include <string.h>
38#include <stdlib.h>
39
40static int inet_net_pton_ipv4(const char *, u_char *, size_t);
41
42/*
43 * static int
44 * inet_net_pton(af, src, dst, size)
45 * convert network number from presentation to network format.
46 * accepts hex octets, hex strings, decimal octets, and /CIDR.
47 * "size" is in bytes and describes "dst".
48 * return:
49 * number of bits, either imputed classfully or specified with /CIDR,
50 * or -1 if some failure occurred (check errno). ENOENT means it was
51 * not a valid network specification.
52 * author:
53 * Paul Vixie (ISC), June 1996
54 */
55int
56inet_net_pton(af, src, dst, size)
57 int af;
58 const char *src;
59 void *dst;
60 size_t size;
61{
62 switch (af) {
63 case AF_INET:
64 return (inet_net_pton_ipv4(src, dst, size));
65 default:
66 errno = EAFNOSUPPORT;
67 return (-1);
68 }
69}
70
71/*
72 * static int
73 * inet_net_pton_ipv4(src, dst, size)
74 * convert IPv4 network number from presentation to network format.
75 * accepts hex octets, hex strings, decimal octets, and /CIDR.
76 * "size" is in bytes and describes "dst".
77 * return:
78 * number of bits, either imputed classfully or specified with /CIDR,
79 * or -1 if some failure occurred (check errno). ENOENT means it was
80 * not an IPv4 network specification.
81 * note:
82 * network byte order assumed. this means 192.5.5.240/28 has
83 * 0x11110000 in its fourth octet.
84 * author:
85 * Paul Vixie (ISC), June 1996
86 */
87static int
88inet_net_pton_ipv4(src, dst, size)
89 const char *src;
90 u_char *dst;
91 size_t size;
92{
93 static const char
94 xdigits[] = "0123456789abcdef",
95 digits[] = "0123456789";
96 int n, ch, tmp, dirty, bits;
97 const u_char *odst = dst;
98
99 ch = *src++;
100 if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
101 && isascii(src[1]) && isxdigit(src[1])) {
102 /* Hexadecimal: Eat nybble string. */
103 if (size <= 0)
104 goto emsgsize;
105 *dst = 0, dirty = 0;
106 src++; /* skip x or X. */
107 while ((ch = *src++) != '\0' &&
108 isascii(ch) && isxdigit(ch)) {
109 if (isupper(ch))
110 ch = tolower(ch);
111 n = strchr(xdigits, ch) - xdigits;
112 assert(n >= 0 && n <= 15);
113 *dst |= n;
114 if (!dirty++)
115 *dst <<= 4;
116 else if (size-- > 0)
117 *++dst = 0, dirty = 0;
118 else
119 goto emsgsize;
120 }
121 if (dirty)
122 size--;
123 } else if (isascii(ch) && isdigit(ch)) {
124 /* Decimal: eat dotted digit string. */
125 for (;;) {
126 tmp = 0;
127 do {
128 n = strchr(digits, ch) - digits;
129 assert(n >= 0 && n <= 9);
130 tmp *= 10;
131 tmp += n;
132 if (tmp > 255)
133 goto enoent;
134 } while ((ch = *src++) != '\0' &&
135 isascii(ch) && isdigit(ch));
136 if (size-- <= 0)
137 goto emsgsize;
138 *dst++ = (u_char) tmp;
139 if (ch == '\0' || ch == '/')
140 break;
141 if (ch != '.')
142 goto enoent;
143 ch = *src++;
144 if (!isascii(ch) || !isdigit(ch))
145 goto enoent;
146 }
147 } else
148 goto enoent;
149
150 bits = -1;
151 if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
152 /* CIDR width specifier. Nothing can follow it. */
153 ch = *src++; /* Skip over the /. */
154 bits = 0;
155 do {
156 n = strchr(digits, ch) - digits;
157 assert(n >= 0 && n <= 9);
158 bits *= 10;
159 bits += n;
160 } while ((ch = *src++) != '\0' &&
161 isascii(ch) && isdigit(ch));
162 if (ch != '\0')
163 goto enoent;
164 if (bits > 32)
165 goto emsgsize;
166 }
167
168 /* Firey death and destruction unless we prefetched EOS. */
169 if (ch != '\0')
170 goto enoent;
171
172 /* If nothing was written to the destination, we found no address. */
173 if (dst == odst)
174 goto enoent;
175 /* If no CIDR spec was given, infer width from net class. */
176 if (bits == -1) {
177 if (*odst >= 240) /* Class E */
178 bits = 32;
179 else if (*odst >= 224) /* Class D */
180 bits = 4;
181 else if (*odst >= 192) /* Class C */
182 bits = 24;
183 else if (*odst >= 128) /* Class B */
184 bits = 16;
185 else /* Class A */
186 bits = 8;
187 /* If imputed mask is narrower than specified octets, widen. */
188 if (bits < ((dst - odst) * 8))
189 bits = (dst - odst) * 8;
190 }
191 /* Extend network to cover the actual mask. */
192 while (bits > ((dst - odst) * 8)) {
193 if (size-- <= 0)
194 goto emsgsize;
195 *dst++ = '\0';
196 }
197 return (bits);
198
199 enoent:
200 errno = ENOENT;
201 return (-1);
202
203 emsgsize:
204 errno = EMSGSIZE;
205 return (-1);
206}