Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 : : * Copyright (c) 1996,1999 by Internet Software Consortium.
4 : : *
5 : : * Permission to use, copy, modify, and distribute this software for any
6 : : * purpose with or without fee is hereby granted, provided that the above
7 : : * copyright notice and this permission notice appear in all copies.
8 : : *
9 : : * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10 : : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 : : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12 : : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 : : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 : : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 : : * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 : : *
17 : : * src/backend/utils/adt/inet_net_pton.c
18 : : */
19 : :
20 : : #if defined(LIBC_SCCS) && !defined(lint)
21 : : static const char rcsid[] = "Id: inet_net_pton.c,v 1.4.2.3 2004/03/17 00:40:11 marka Exp $";
22 : : #endif
23 : :
24 : : #include "postgres.h"
25 : :
26 : : #include <sys/socket.h>
27 : : #include <netinet/in.h>
28 : : #include <arpa/inet.h>
29 : : #include <assert.h>
30 : : #include <ctype.h>
31 : :
32 : : #include "utils/builtins.h" /* needed on some platforms */
33 : : #include "utils/inet.h"
34 : :
35 : :
36 : : static int inet_net_pton_ipv4(const char *src, u_char *dst);
37 : : static int inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size);
38 : : static int inet_net_pton_ipv6(const char *src, u_char *dst);
39 : : static int inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size);
40 : :
41 : :
42 : : /*
43 : : * int
44 : : * pg_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 : : *
55 : : * Changes:
56 : : * I added the inet_cidr_pton function (also from Paul) and changed
57 : : * the names to reflect their current use.
58 : : *
59 : : */
60 : : int
2452 tgl@sss.pgh.pa.us 61 :CBC 3658 : pg_inet_net_pton(int af, const char *src, void *dst, size_t size)
62 : : {
10076 bruce@momjian.us 63 [ + + - ]: 3658 : switch (af)
64 : : {
8351 65 : 2937 : case PGSQL_AF_INET:
66 : : return size == -1 ?
8958 67 [ + + ]: 3856 : inet_net_pton_ipv4(src, dst) :
68 : 919 : inet_cidr_pton_ipv4(src, dst, size);
8351 69 : 721 : case PGSQL_AF_INET6:
70 : : return size == -1 ?
71 [ + + ]: 987 : inet_net_pton_ipv6(src, dst) :
72 : 266 : inet_cidr_pton_ipv6(src, dst, size);
10076 bruce@momjian.us 73 :UBC 0 : default:
74 : 0 : errno = EAFNOSUPPORT;
3183 peter_e@gmx.net 75 : 0 : return -1;
76 : : }
77 : : }
78 : :
79 : : /*
80 : : * static int
81 : : * inet_cidr_pton_ipv4(src, dst, size)
82 : : * convert IPv4 network number from presentation to network format.
83 : : * accepts hex octets, hex strings, decimal octets, and /CIDR.
84 : : * "size" is in bytes and describes "dst".
85 : : * return:
86 : : * number of bits, either imputed classfully or specified with /CIDR,
87 : : * or -1 if some failure occurred (check errno). ENOENT means it was
88 : : * not an IPv4 network specification.
89 : : * note:
90 : : * network byte order assumed. this means 192.5.5.240/28 has
91 : : * 0b11110000 in its fourth octet.
92 : : * author:
93 : : * Paul Vixie (ISC), June 1996
94 : : */
95 : : static int
10057 bruce@momjian.us 96 :CBC 919 : inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size)
97 : : {
98 : : static const char xdigits[] = "0123456789abcdef";
99 : : static const char digits[] = "0123456789";
100 : : int n,
101 : : ch,
7763 tgl@sss.pgh.pa.us 102 : 919 : tmp = 0,
103 : : dirty,
104 : : bits;
10076 bruce@momjian.us 105 : 919 : const u_char *odst = dst;
106 : :
107 : 919 : ch = *src++;
108 [ + + + - : 919 : if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
- + ]
9284 tgl@sss.pgh.pa.us 109 [ # # ]:UBC 0 : && isxdigit((unsigned char) src[1]))
110 : : {
111 : : /* Hexadecimal: Eat nybble string. */
7763 112 [ # # ]: 0 : if (size <= 0U)
10076 bruce@momjian.us 113 : 0 : goto emsgsize;
10067 114 : 0 : dirty = 0;
9842 115 : 0 : src++; /* skip x or X. */
9284 tgl@sss.pgh.pa.us 116 [ # # # # ]: 0 : while ((ch = *src++) != '\0' && isxdigit((unsigned char) ch))
117 : : {
308 jdavis@postgresql.or 118 :UNC 0 : ch = pg_ascii_tolower((unsigned char) ch);
10076 bruce@momjian.us 119 :UBC 0 : n = strchr(xdigits, ch) - xdigits;
120 [ # # # # ]: 0 : assert(n >= 0 && n <= 15);
10062 121 [ # # ]: 0 : if (dirty == 0)
122 : 0 : tmp = n;
123 : : else
124 : 0 : tmp = (tmp << 4) | n;
9842 125 [ # # ]: 0 : if (++dirty == 2)
126 : : {
7763 tgl@sss.pgh.pa.us 127 [ # # ]: 0 : if (size-- <= 0U)
10067 bruce@momjian.us 128 : 0 : goto emsgsize;
129 : 0 : *dst++ = (u_char) tmp;
10062 130 : 0 : dirty = 0;
131 : : }
132 : : }
9842 133 [ # # ]: 0 : if (dirty)
134 : : { /* Odd trailing nybble? */
7763 tgl@sss.pgh.pa.us 135 [ # # ]: 0 : if (size-- <= 0U)
10076 bruce@momjian.us 136 : 0 : goto emsgsize;
10062 137 : 0 : *dst++ = (u_char) (tmp << 4);
138 : : }
139 : : }
9284 tgl@sss.pgh.pa.us 140 [ + - ]:CBC 919 : else if (isdigit((unsigned char) ch))
141 : : {
142 : : /* Decimal: eat dotted digit string. */
143 : : for (;;)
144 : : {
10076 bruce@momjian.us 145 : 3136 : tmp = 0;
146 : : do
147 : : {
148 : 5746 : n = strchr(digits, ch) - digits;
149 [ + - + - ]: 5746 : assert(n >= 0 && n <= 9);
150 : 5746 : tmp *= 10;
151 : 5746 : tmp += n;
152 [ + + ]: 5746 : if (tmp > 255)
153 : 8 : goto enoent;
154 [ + + ]: 5738 : } while ((ch = *src++) != '\0' &&
9284 tgl@sss.pgh.pa.us 155 [ + + ]: 5410 : isdigit((unsigned char) ch));
7763 156 [ - + ]: 3128 : if (size-- <= 0U)
10076 bruce@momjian.us 157 :UBC 0 : goto emsgsize;
10076 bruce@momjian.us 158 :CBC 3128 : *dst++ = (u_char) tmp;
159 [ + + + + ]: 3128 : if (ch == '\0' || ch == '/')
160 : : break;
161 [ - + ]: 2217 : if (ch != '.')
10076 bruce@momjian.us 162 :UBC 0 : goto enoent;
10076 bruce@momjian.us 163 :CBC 2217 : ch = *src++;
9284 tgl@sss.pgh.pa.us 164 [ - + ]: 2217 : if (!isdigit((unsigned char) ch))
10076 bruce@momjian.us 165 :UBC 0 : goto enoent;
166 : : }
167 : : }
168 : : else
169 : 0 : goto enoent;
170 : :
10076 bruce@momjian.us 171 :CBC 911 : bits = -1;
9284 tgl@sss.pgh.pa.us 172 [ + + + - : 911 : if (ch == '/' && isdigit((unsigned char) src[0]) && dst > odst)
+ - ]
173 : : {
174 : : /* CIDR width specifier. Nothing can follow it. */
10076 bruce@momjian.us 175 : 583 : ch = *src++; /* Skip over the /. */
176 : 583 : bits = 0;
177 : : do
178 : : {
179 : 1034 : n = strchr(digits, ch) - digits;
180 [ + - + - ]: 1034 : assert(n >= 0 && n <= 9);
181 : 1034 : bits *= 10;
182 : 1034 : bits += n;
9284 tgl@sss.pgh.pa.us 183 [ + + + - ]: 1034 : } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
10076 bruce@momjian.us 184 [ - + ]: 583 : if (ch != '\0')
10076 bruce@momjian.us 185 :UBC 0 : goto enoent;
10076 bruce@momjian.us 186 [ - + ]:CBC 583 : if (bits > 32)
10076 bruce@momjian.us 187 :UBC 0 : goto emsgsize;
188 : : }
189 : :
190 : : /* Fiery death and destruction unless we prefetched EOS. */
10076 bruce@momjian.us 191 [ - + ]:CBC 911 : if (ch != '\0')
10076 bruce@momjian.us 192 :UBC 0 : goto enoent;
193 : :
194 : : /* If nothing was written to the destination, we found no address. */
10076 bruce@momjian.us 195 [ - + ]:CBC 911 : if (dst == odst)
10076 bruce@momjian.us 196 :UBC 0 : goto enoent;
197 : : /* If no CIDR spec was given, infer width from net class. */
10076 bruce@momjian.us 198 [ + + ]:CBC 911 : if (bits == -1)
199 : : {
200 [ + + ]: 328 : if (*odst >= 240) /* Class E */
201 : 128 : bits = 32;
202 [ - + ]: 200 : else if (*odst >= 224) /* Class D */
7763 tgl@sss.pgh.pa.us 203 :UBC 0 : bits = 8;
10076 bruce@momjian.us 204 [ + + ]:CBC 200 : else if (*odst >= 192) /* Class C */
205 : 20 : bits = 24;
206 [ - + ]: 180 : else if (*odst >= 128) /* Class B */
10076 bruce@momjian.us 207 :UBC 0 : bits = 16;
208 : : else
209 : : /* Class A */
10076 bruce@momjian.us 210 :CBC 180 : bits = 8;
211 : : /* If imputed mask is narrower than specified octets, widen. */
7763 tgl@sss.pgh.pa.us 212 [ + + ]: 328 : if (bits < ((dst - odst) * 8))
10076 bruce@momjian.us 213 : 160 : bits = (dst - odst) * 8;
214 : :
215 : : /*
216 : : * If there are no additional bits specified for a class D address
217 : : * adjust bits to 4.
218 : : */
7763 tgl@sss.pgh.pa.us 219 [ + + - + ]: 328 : if (bits == 8 && *odst == 224)
7763 tgl@sss.pgh.pa.us 220 :UBC 0 : bits = 4;
221 : : }
222 : : /* Extend network to cover the actual mask. */
10076 bruce@momjian.us 223 [ + + ]:CBC 943 : while (bits > ((dst - odst) * 8))
224 : : {
7763 tgl@sss.pgh.pa.us 225 [ - + ]: 32 : if (size-- <= 0U)
10076 bruce@momjian.us 226 :UBC 0 : goto emsgsize;
10076 bruce@momjian.us 227 :CBC 32 : *dst++ = '\0';
228 : : }
3183 peter_e@gmx.net 229 : 911 : return bits;
230 : :
10076 bruce@momjian.us 231 : 8 : enoent:
232 : 8 : errno = ENOENT;
3183 peter_e@gmx.net 233 : 8 : return -1;
234 : :
10076 bruce@momjian.us 235 :UBC 0 : emsgsize:
236 : 0 : errno = EMSGSIZE;
3183 peter_e@gmx.net 237 : 0 : return -1;
238 : : }
239 : :
240 : : /*
241 : : * int
242 : : * inet_net_pton_ipv4(af, src, dst, *bits)
243 : : * convert network address from presentation to network format.
244 : : * accepts inet_pton()'s input for this "af" plus trailing "/CIDR".
245 : : * "dst" is assumed large enough for its "af". "bits" is set to the
246 : : * /CIDR prefix length, which can have defaults (like /32 for IPv4).
247 : : * return:
248 : : * -1 if an error occurred (inspect errno; ENOENT means bad format).
249 : : * 0 if successful conversion occurred.
250 : : * note:
251 : : * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
252 : : * as called for by inet_cidr_pton() but it can be a host address with
253 : : * an included netmask.
254 : : * author:
255 : : * Paul Vixie (ISC), October 1998
256 : : */
257 : : static int
10057 bruce@momjian.us 258 :CBC 2018 : inet_net_pton_ipv4(const char *src, u_char *dst)
259 : : {
260 : : static const char digits[] = "0123456789";
261 : 2018 : const u_char *odst = dst;
262 : : int n,
263 : : ch,
264 : : tmp,
265 : : bits;
9842 266 : 2018 : size_t size = 4;
267 : :
268 : : /* Get the mantissa. */
9284 tgl@sss.pgh.pa.us 269 [ + - ]: 7808 : while (ch = *src++, isdigit((unsigned char) ch))
270 : : {
10057 bruce@momjian.us 271 : 7808 : tmp = 0;
272 : : do
273 : : {
274 : 16385 : n = strchr(digits, ch) - digits;
275 [ + - + - ]: 16385 : assert(n >= 0 && n <= 9);
276 : 16385 : tmp *= 10;
277 : 16385 : tmp += n;
278 [ + + ]: 16385 : if (tmp > 255)
279 : 8 : goto enoent;
9284 tgl@sss.pgh.pa.us 280 [ + + + + ]: 16377 : } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
10057 bruce@momjian.us 281 [ - + ]: 7800 : if (size-- == 0)
10057 bruce@momjian.us 282 :UBC 0 : goto emsgsize;
10057 bruce@momjian.us 283 :CBC 7800 : *dst++ = (u_char) tmp;
284 [ + + + + ]: 7800 : if (ch == '\0' || ch == '/')
285 : : break;
286 [ - + ]: 5790 : if (ch != '.')
10057 bruce@momjian.us 287 :UBC 0 : goto enoent;
288 : : }
289 : :
290 : : /* Get the prefix length if any. */
10057 bruce@momjian.us 291 :CBC 2010 : bits = -1;
9284 tgl@sss.pgh.pa.us 292 [ + + + - : 2010 : if (ch == '/' && isdigit((unsigned char) src[0]) && dst > odst)
+ - ]
293 : : {
294 : : /* CIDR width specifier. Nothing can follow it. */
9842 bruce@momjian.us 295 : 835 : ch = *src++; /* Skip over the /. */
10057 296 : 835 : bits = 0;
297 : : do
298 : : {
299 : 1402 : n = strchr(digits, ch) - digits;
300 [ + - + - ]: 1402 : assert(n >= 0 && n <= 9);
301 : 1402 : bits *= 10;
302 : 1402 : bits += n;
9284 tgl@sss.pgh.pa.us 303 [ + + + - ]: 1402 : } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
10057 bruce@momjian.us 304 [ - + ]: 835 : if (ch != '\0')
10057 bruce@momjian.us 305 :UBC 0 : goto enoent;
10057 bruce@momjian.us 306 [ - + ]:CBC 835 : if (bits > 32)
10057 bruce@momjian.us 307 :UBC 0 : goto emsgsize;
308 : : }
309 : :
310 : : /* Fiery death and destruction unless we prefetched EOS. */
10057 bruce@momjian.us 311 [ - + ]:CBC 2010 : if (ch != '\0')
10057 bruce@momjian.us 312 :UBC 0 : goto enoent;
313 : :
314 : : /* Prefix length can default to /32 only if all four octets spec'd. */
10057 bruce@momjian.us 315 [ + + ]:CBC 2010 : if (bits == -1)
316 : : {
317 [ + - ]: 1175 : if (dst - odst == 4)
318 : 1175 : bits = 32;
319 : : else
10057 bruce@momjian.us 320 :UBC 0 : goto enoent;
321 : : }
322 : :
323 : : /* If nothing was written to the destination, we found no address. */
10057 bruce@momjian.us 324 [ - + ]:CBC 2010 : if (dst == odst)
10057 bruce@momjian.us 325 :UBC 0 : goto enoent;
326 : :
327 : : /* If prefix length overspecifies mantissa, life is bad. */
10057 bruce@momjian.us 328 [ - + ]:CBC 2010 : if ((bits / 8) > (dst - odst))
10057 bruce@momjian.us 329 :UBC 0 : goto enoent;
330 : :
331 : : /* Extend address to four octets. */
10057 bruce@momjian.us 332 [ + + ]:CBC 2250 : while (size-- > 0)
333 : 240 : *dst++ = 0;
334 : :
335 : 2010 : return bits;
336 : :
9842 337 : 8 : enoent:
10057 338 : 8 : errno = ENOENT;
3183 peter_e@gmx.net 339 : 8 : return -1;
340 : :
9842 bruce@momjian.us 341 :UBC 0 : emsgsize:
10057 342 : 0 : errno = EMSGSIZE;
3183 peter_e@gmx.net 343 : 0 : return -1;
344 : : }
345 : :
346 : : static int
8310 bruce@momjian.us 347 :CBC 403 : getbits(const char *src, int *bitsp)
348 : : {
349 : : static const char digits[] = "0123456789";
350 : : int n;
351 : : int val;
352 : : char ch;
353 : :
8351 354 : 403 : val = 0;
355 : 403 : n = 0;
8310 356 [ + + ]: 1284 : while ((ch = *src++) != '\0')
357 : : {
358 : : const char *pch;
359 : :
8351 360 : 881 : pch = strchr(digits, ch);
8310 361 [ + - ]: 881 : if (pch != NULL)
362 : : {
8351 363 [ + + - + ]: 881 : if (n++ != 0 && val == 0) /* no leading zeros */
3183 peter_e@gmx.net 364 :UBC 0 : return 0;
8351 bruce@momjian.us 365 :CBC 881 : val *= 10;
366 : 881 : val += (pch - digits);
8310 367 [ - + ]: 881 : if (val > 128) /* range */
3183 peter_e@gmx.net 368 :UBC 0 : return 0;
8351 bruce@momjian.us 369 :CBC 881 : continue;
370 : : }
3183 peter_e@gmx.net 371 :UBC 0 : return 0;
372 : : }
8351 bruce@momjian.us 373 [ - + ]:CBC 403 : if (n == 0)
3183 peter_e@gmx.net 374 :UBC 0 : return 0;
8351 bruce@momjian.us 375 :CBC 403 : *bitsp = val;
3183 peter_e@gmx.net 376 : 403 : return 1;
377 : : }
378 : :
379 : : static int
8310 bruce@momjian.us 380 : 24 : getv4(const char *src, u_char *dst, int *bitsp)
381 : : {
382 : : static const char digits[] = "0123456789";
383 : 24 : u_char *odst = dst;
384 : : int n;
385 : : u_int val;
386 : : char ch;
387 : :
8351 388 : 24 : val = 0;
389 : 24 : n = 0;
8310 390 [ + + ]: 192 : while ((ch = *src++) != '\0')
391 : : {
392 : : const char *pch;
393 : :
8351 394 : 188 : pch = strchr(digits, ch);
8310 395 [ + + ]: 188 : if (pch != NULL)
396 : : {
8351 397 [ - + - - ]: 96 : if (n++ != 0 && val == 0) /* no leading zeros */
3183 peter_e@gmx.net 398 :UBC 0 : return 0;
8351 bruce@momjian.us 399 :CBC 96 : val *= 10;
400 : 96 : val += (pch - digits);
8310 401 [ - + ]: 96 : if (val > 255) /* range */
3183 peter_e@gmx.net 402 :UBC 0 : return 0;
8351 bruce@momjian.us 403 :CBC 96 : continue;
404 : : }
8310 405 [ + + + - ]: 92 : if (ch == '.' || ch == '/')
406 : : {
407 [ - + ]: 92 : if (dst - odst > 3) /* too many octets? */
3183 peter_e@gmx.net 408 :UBC 0 : return 0;
8351 bruce@momjian.us 409 :CBC 92 : *dst++ = val;
410 [ + + ]: 92 : if (ch == '/')
3183 peter_e@gmx.net 411 : 20 : return getbits(src, bitsp);
8351 bruce@momjian.us 412 : 72 : val = 0;
413 : 72 : n = 0;
414 : 72 : continue;
415 : : }
3183 peter_e@gmx.net 416 :UBC 0 : return 0;
417 : : }
8351 bruce@momjian.us 418 [ - + ]:CBC 4 : if (n == 0)
3183 peter_e@gmx.net 419 :UBC 0 : return 0;
8310 bruce@momjian.us 420 [ - + ]:CBC 4 : if (dst - odst > 3) /* too many octets? */
3183 peter_e@gmx.net 421 :UBC 0 : return 0;
8351 bruce@momjian.us 422 :CBC 4 : *dst++ = val;
3183 peter_e@gmx.net 423 : 4 : return 1;
424 : : }
425 : :
426 : : static int
8351 bruce@momjian.us 427 : 455 : inet_net_pton_ipv6(const char *src, u_char *dst)
428 : : {
429 : 455 : return inet_cidr_pton_ipv6(src, dst, 16);
430 : : }
431 : :
432 : : #define NS_IN6ADDRSZ 16
433 : : #define NS_INT16SZ 2
434 : : #define NS_INADDRSZ 4
435 : :
436 : : static int
8310 437 : 721 : inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size)
438 : : {
439 : : static const char xdigits_l[] = "0123456789abcdef",
440 : : xdigits_u[] = "0123456789ABCDEF";
441 : : u_char tmp[NS_IN6ADDRSZ],
442 : : *tp,
443 : : *endp,
444 : : *colonp;
445 : : const char *xdigits,
446 : : *curtok;
447 : : int ch,
448 : : saw_xdigit;
449 : : u_int val;
450 : : int digits;
451 : : int bits;
452 : :
8351 453 [ - + ]: 721 : if (size < NS_IN6ADDRSZ)
8351 bruce@momjian.us 454 :UBC 0 : goto emsgsize;
455 : :
8351 bruce@momjian.us 456 :CBC 721 : memset((tp = tmp), '\0', NS_IN6ADDRSZ);
457 : 721 : endp = tp + NS_IN6ADDRSZ;
458 : 721 : colonp = NULL;
459 : : /* Leading :: requires some special handling. */
460 [ + + ]: 721 : if (*src == ':')
461 [ - + ]: 44 : if (*++src != ':')
8351 bruce@momjian.us 462 :UBC 0 : goto enoent;
8351 bruce@momjian.us 463 :CBC 721 : curtok = src;
464 : 721 : saw_xdigit = 0;
465 : 721 : val = 0;
466 : 721 : digits = 0;
467 : 721 : bits = -1;
8310 468 [ + + ]: 15729 : while ((ch = *src++) != '\0')
469 : : {
470 : : const char *pch;
471 : :
8351 472 [ + + ]: 15419 : if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
473 : 3650 : pch = strchr((xdigits = xdigits_u), ch);
8310 474 [ + + ]: 15419 : if (pch != NULL)
475 : : {
8351 476 : 11769 : val <<= 4;
477 : 11769 : val |= (pch - xdigits);
478 [ - + ]: 11769 : if (++digits > 4)
8351 bruce@momjian.us 479 :UBC 0 : goto enoent;
8351 bruce@momjian.us 480 :CBC 11769 : saw_xdigit = 1;
481 : 11769 : continue;
482 : : }
8310 483 [ + + ]: 3650 : if (ch == ':')
484 : : {
8351 485 : 3243 : curtok = src;
8310 486 [ + + ]: 3243 : if (!saw_xdigit)
487 : : {
8351 488 [ + + ]: 604 : if (colonp)
489 : 4 : goto enoent;
490 : 600 : colonp = tp;
491 : 600 : continue;
492 : : }
8310 493 [ - + ]: 2639 : else if (*src == '\0')
8351 bruce@momjian.us 494 :UBC 0 : goto enoent;
8351 bruce@momjian.us 495 [ - + ]:CBC 2639 : if (tp + NS_INT16SZ > endp)
3610 tgl@sss.pgh.pa.us 496 :UBC 0 : goto enoent;
8351 bruce@momjian.us 497 :CBC 2639 : *tp++ = (u_char) (val >> 8) & 0xff;
498 : 2639 : *tp++ = (u_char) val & 0xff;
499 : 2639 : saw_xdigit = 0;
500 : 2639 : digits = 0;
501 : 2639 : val = 0;
502 : 2639 : continue;
503 : : }
504 [ + + + - : 431 : if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ - ]
8310 505 : 24 : getv4(curtok, tp, &bits) > 0)
506 : : {
8351 507 : 24 : tp += NS_INADDRSZ;
508 : 24 : saw_xdigit = 0;
8310 509 : 24 : break; /* '\0' was seen by inet_pton4(). */
510 : : }
8351 511 [ + - + - ]: 383 : if (ch == '/' && getbits(src, &bits) > 0)
512 : 383 : break;
8351 bruce@momjian.us 513 :UBC 0 : goto enoent;
514 : : }
8310 bruce@momjian.us 515 [ + + ]:CBC 717 : if (saw_xdigit)
516 : : {
8351 517 [ - + ]: 613 : if (tp + NS_INT16SZ > endp)
8351 bruce@momjian.us 518 :UBC 0 : goto enoent;
8351 bruce@momjian.us 519 :CBC 613 : *tp++ = (u_char) (val >> 8) & 0xff;
520 : 613 : *tp++ = (u_char) val & 0xff;
521 : : }
522 [ + + ]: 717 : if (bits == -1)
523 : 314 : bits = 128;
524 : :
8310 525 : 717 : endp = tmp + 16;
526 : :
527 [ + + ]: 717 : if (colonp != NULL)
528 : : {
529 : : /*
530 : : * Since some memmove()'s erroneously fail to handle overlapping
531 : : * regions, we'll do the shift by hand.
532 : : */
533 : 596 : const int n = tp - colonp;
534 : : int i;
535 : :
8351 536 [ - + ]: 596 : if (tp == endp)
8351 bruce@momjian.us 537 :UBC 0 : goto enoent;
8310 bruce@momjian.us 538 [ + + ]:CBC 3948 : for (i = 1; i <= n; i++)
539 : : {
540 : 3352 : endp[-i] = colonp[n - i];
8351 541 : 3352 : colonp[n - i] = 0;
542 : : }
543 : 596 : tp = endp;
544 : : }
545 [ - + ]: 717 : if (tp != endp)
8351 bruce@momjian.us 546 :UBC 0 : goto enoent;
547 : :
548 : : /*
549 : : * Copy out the result.
550 : : */
8351 bruce@momjian.us 551 :CBC 717 : memcpy(dst, tmp, NS_IN6ADDRSZ);
552 : :
3183 peter_e@gmx.net 553 : 717 : return bits;
554 : :
8310 bruce@momjian.us 555 : 4 : enoent:
8351 556 : 4 : errno = ENOENT;
3183 peter_e@gmx.net 557 : 4 : return -1;
558 : :
8310 bruce@momjian.us 559 :UBC 0 : emsgsize:
8351 560 : 0 : errno = EMSGSIZE;
3183 peter_e@gmx.net 561 : 0 : return -1;
562 : : }
|