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" /* pgrminclude ignore */ /* needed on some
33 : : * platforms */
34 : : #include "utils/inet.h"
35 : :
36 : :
37 : : static int inet_net_pton_ipv4(const char *src, u_char *dst);
38 : : static int inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size);
39 : : static int inet_net_pton_ipv6(const char *src, u_char *dst);
40 : : static int inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size);
41 : :
42 : :
43 : : /*
44 : : * int
45 : : * pg_inet_net_pton(af, src, dst, size)
46 : : * convert network number from presentation to network format.
47 : : * accepts hex octets, hex strings, decimal octets, and /CIDR.
48 : : * "size" is in bytes and describes "dst".
49 : : * return:
50 : : * number of bits, either imputed classfully or specified with /CIDR,
51 : : * or -1 if some failure occurred (check errno). ENOENT means it was
52 : : * not a valid network specification.
53 : : * author:
54 : : * Paul Vixie (ISC), June 1996
55 : : *
56 : : * Changes:
57 : : * I added the inet_cidr_pton function (also from Paul) and changed
58 : : * the names to reflect their current use.
59 : : *
60 : : */
61 : : int
1701 tgl@sss.pgh.pa.us 62 :CBC 2874 : pg_inet_net_pton(int af, const char *src, void *dst, size_t size)
63 : : {
9325 bruce@momjian.us 64 [ + + - ]: 2874 : switch (af)
65 : : {
7600 66 : 2426 : case PGSQL_AF_INET:
67 : : return size == -1 ?
8207 68 [ + + ]: 2981 : inet_net_pton_ipv4(src, dst) :
69 : 555 : inet_cidr_pton_ipv4(src, dst, size);
7600 70 : 448 : case PGSQL_AF_INET6:
71 : : return size == -1 ?
72 [ + + ]: 592 : inet_net_pton_ipv6(src, dst) :
73 : 144 : inet_cidr_pton_ipv6(src, dst, size);
9325 bruce@momjian.us 74 :UBC 0 : default:
75 : 0 : errno = EAFNOSUPPORT;
2432 peter_e@gmx.net 76 : 0 : return -1;
77 : : }
78 : : }
79 : :
80 : : /*
81 : : * static int
82 : : * inet_cidr_pton_ipv4(src, dst, size)
83 : : * convert IPv4 network number from presentation to network format.
84 : : * accepts hex octets, hex strings, decimal octets, and /CIDR.
85 : : * "size" is in bytes and describes "dst".
86 : : * return:
87 : : * number of bits, either imputed classfully or specified with /CIDR,
88 : : * or -1 if some failure occurred (check errno). ENOENT means it was
89 : : * not an IPv4 network specification.
90 : : * note:
91 : : * network byte order assumed. this means 192.5.5.240/28 has
92 : : * 0b11110000 in its fourth octet.
93 : : * author:
94 : : * Paul Vixie (ISC), June 1996
95 : : */
96 : : static int
9306 bruce@momjian.us 97 :CBC 555 : inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size)
98 : : {
99 : : static const char xdigits[] = "0123456789abcdef";
100 : : static const char digits[] = "0123456789";
101 : : int n,
102 : : ch,
7012 tgl@sss.pgh.pa.us 103 : 555 : tmp = 0,
104 : : dirty,
105 : : bits;
9325 bruce@momjian.us 106 : 555 : const u_char *odst = dst;
107 : :
108 : 555 : ch = *src++;
109 [ + + + - : 555 : if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
- + ]
8533 tgl@sss.pgh.pa.us 110 [ # # ]:UBC 0 : && isxdigit((unsigned char) src[1]))
111 : : {
112 : : /* Hexadecimal: Eat nybble string. */
7012 113 [ # # ]: 0 : if (size <= 0U)
9325 bruce@momjian.us 114 : 0 : goto emsgsize;
9316 115 : 0 : dirty = 0;
9091 116 : 0 : src++; /* skip x or X. */
8533 tgl@sss.pgh.pa.us 117 [ # # # # ]: 0 : while ((ch = *src++) != '\0' && isxdigit((unsigned char) ch))
118 : : {
119 [ # # ]: 0 : if (isupper((unsigned char) ch))
120 : 0 : ch = tolower((unsigned char) ch);
9325 bruce@momjian.us 121 : 0 : n = strchr(xdigits, ch) - xdigits;
122 [ # # # # ]: 0 : assert(n >= 0 && n <= 15);
9311 123 [ # # ]: 0 : if (dirty == 0)
124 : 0 : tmp = n;
125 : : else
126 : 0 : tmp = (tmp << 4) | n;
9091 127 [ # # ]: 0 : if (++dirty == 2)
128 : : {
7012 tgl@sss.pgh.pa.us 129 [ # # ]: 0 : if (size-- <= 0U)
9316 bruce@momjian.us 130 : 0 : goto emsgsize;
131 : 0 : *dst++ = (u_char) tmp;
9311 132 : 0 : dirty = 0;
133 : : }
134 : : }
9091 135 [ # # ]: 0 : if (dirty)
136 : : { /* Odd trailing nybble? */
7012 tgl@sss.pgh.pa.us 137 [ # # ]: 0 : if (size-- <= 0U)
9325 bruce@momjian.us 138 : 0 : goto emsgsize;
9311 139 : 0 : *dst++ = (u_char) (tmp << 4);
140 : : }
141 : : }
8533 tgl@sss.pgh.pa.us 142 [ + - ]:CBC 555 : else if (isdigit((unsigned char) ch))
143 : : {
144 : : /* Decimal: eat dotted digit string. */
145 : : for (;;)
146 : : {
9325 bruce@momjian.us 147 : 1815 : tmp = 0;
148 : : do
149 : : {
150 : 3490 : n = strchr(digits, ch) - digits;
151 [ + - + - ]: 3490 : assert(n >= 0 && n <= 9);
152 : 3490 : tmp *= 10;
153 : 3490 : tmp += n;
154 [ + + ]: 3490 : if (tmp > 255)
155 : 6 : goto enoent;
156 [ + + ]: 3484 : } while ((ch = *src++) != '\0' &&
8533 tgl@sss.pgh.pa.us 157 [ + + ]: 3234 : isdigit((unsigned char) ch));
7012 158 [ - + ]: 1809 : if (size-- <= 0U)
9325 bruce@momjian.us 159 :UBC 0 : goto emsgsize;
9325 bruce@momjian.us 160 :CBC 1809 : *dst++ = (u_char) tmp;
161 [ + + + + ]: 1809 : if (ch == '\0' || ch == '/')
162 : : break;
163 [ - + ]: 1260 : if (ch != '.')
9325 bruce@momjian.us 164 :UBC 0 : goto enoent;
9325 bruce@momjian.us 165 :CBC 1260 : ch = *src++;
8533 tgl@sss.pgh.pa.us 166 [ - + ]: 1260 : if (!isdigit((unsigned char) ch))
9325 bruce@momjian.us 167 :UBC 0 : goto enoent;
168 : : }
169 : : }
170 : : else
171 : 0 : goto enoent;
172 : :
9325 bruce@momjian.us 173 :CBC 549 : bits = -1;
8533 tgl@sss.pgh.pa.us 174 [ + + + - : 549 : if (ch == '/' && isdigit((unsigned char) src[0]) && dst > odst)
+ - ]
175 : : {
176 : : /* CIDR width specifier. Nothing can follow it. */
9325 bruce@momjian.us 177 : 299 : ch = *src++; /* Skip over the /. */
178 : 299 : bits = 0;
179 : : do
180 : : {
181 : 523 : n = strchr(digits, ch) - digits;
182 [ + - + - ]: 523 : assert(n >= 0 && n <= 9);
183 : 523 : bits *= 10;
184 : 523 : bits += n;
8533 tgl@sss.pgh.pa.us 185 [ + + + - ]: 523 : } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
9325 bruce@momjian.us 186 [ - + ]: 299 : if (ch != '\0')
9325 bruce@momjian.us 187 :UBC 0 : goto enoent;
9325 bruce@momjian.us 188 [ - + ]:CBC 299 : if (bits > 32)
9325 bruce@momjian.us 189 :UBC 0 : goto emsgsize;
190 : : }
191 : :
192 : : /* Fiery death and destruction unless we prefetched EOS. */
9325 bruce@momjian.us 193 [ - + ]:CBC 549 : if (ch != '\0')
9325 bruce@momjian.us 194 :UBC 0 : goto enoent;
195 : :
196 : : /* If nothing was written to the destination, we found no address. */
9325 bruce@momjian.us 197 [ - + ]:CBC 549 : if (dst == odst)
9325 bruce@momjian.us 198 :UBC 0 : goto enoent;
199 : : /* If no CIDR spec was given, infer width from net class. */
9325 bruce@momjian.us 200 [ + + ]:CBC 549 : if (bits == -1)
201 : : {
202 [ + + ]: 250 : if (*odst >= 240) /* Class E */
203 : 96 : bits = 32;
204 [ - + ]: 154 : else if (*odst >= 224) /* Class D */
7012 tgl@sss.pgh.pa.us 205 :UBC 0 : bits = 8;
9325 bruce@momjian.us 206 [ + + ]:CBC 154 : else if (*odst >= 192) /* Class C */
207 : 15 : bits = 24;
208 [ - + ]: 139 : else if (*odst >= 128) /* Class B */
9325 bruce@momjian.us 209 :UBC 0 : bits = 16;
210 : : else
211 : : /* Class A */
9325 bruce@momjian.us 212 :CBC 139 : bits = 8;
213 : : /* If imputed mask is narrower than specified octets, widen. */
7012 tgl@sss.pgh.pa.us 214 [ + + ]: 250 : if (bits < ((dst - odst) * 8))
9325 bruce@momjian.us 215 : 124 : bits = (dst - odst) * 8;
216 : :
217 : : /*
218 : : * If there are no additional bits specified for a class D address
219 : : * adjust bits to 4.
220 : : */
7012 tgl@sss.pgh.pa.us 221 [ + + - + ]: 250 : if (bits == 8 && *odst == 224)
7012 tgl@sss.pgh.pa.us 222 :UBC 0 : bits = 4;
223 : : }
224 : : /* Extend network to cover the actual mask. */
9325 bruce@momjian.us 225 [ + + ]:CBC 573 : while (bits > ((dst - odst) * 8))
226 : : {
7012 tgl@sss.pgh.pa.us 227 [ - + ]: 24 : if (size-- <= 0U)
9325 bruce@momjian.us 228 :UBC 0 : goto emsgsize;
9325 bruce@momjian.us 229 :CBC 24 : *dst++ = '\0';
230 : : }
2432 peter_e@gmx.net 231 : 549 : return bits;
232 : :
9325 bruce@momjian.us 233 : 6 : enoent:
234 : 6 : errno = ENOENT;
2432 peter_e@gmx.net 235 : 6 : return -1;
236 : :
9325 bruce@momjian.us 237 :UBC 0 : emsgsize:
238 : 0 : errno = EMSGSIZE;
2432 peter_e@gmx.net 239 : 0 : return -1;
240 : : }
241 : :
242 : : /*
243 : : * int
244 : : * inet_net_pton_ipv4(af, src, dst, *bits)
245 : : * convert network address from presentation to network format.
246 : : * accepts inet_pton()'s input for this "af" plus trailing "/CIDR".
247 : : * "dst" is assumed large enough for its "af". "bits" is set to the
248 : : * /CIDR prefix length, which can have defaults (like /32 for IPv4).
249 : : * return:
250 : : * -1 if an error occurred (inspect errno; ENOENT means bad format).
251 : : * 0 if successful conversion occurred.
252 : : * note:
253 : : * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
254 : : * as called for by inet_cidr_pton() but it can be a host address with
255 : : * an included netmask.
256 : : * author:
257 : : * Paul Vixie (ISC), October 1998
258 : : */
259 : : static int
9306 bruce@momjian.us 260 :CBC 1871 : inet_net_pton_ipv4(const char *src, u_char *dst)
261 : : {
262 : : static const char digits[] = "0123456789";
263 : 1871 : const u_char *odst = dst;
264 : : int n,
265 : : ch,
266 : : tmp,
267 : : bits;
9091 268 : 1871 : size_t size = 4;
269 : :
270 : : /* Get the mantissa. */
8533 tgl@sss.pgh.pa.us 271 [ + - ]: 7286 : while (ch = *src++, isdigit((unsigned char) ch))
272 : : {
9306 bruce@momjian.us 273 : 7286 : tmp = 0;
274 : : do
275 : : {
276 : 14887 : n = strchr(digits, ch) - digits;
277 [ + - + - ]: 14887 : assert(n >= 0 && n <= 9);
278 : 14887 : tmp *= 10;
279 : 14887 : tmp += n;
280 [ + + ]: 14887 : if (tmp > 255)
281 : 6 : goto enoent;
8533 tgl@sss.pgh.pa.us 282 [ + + + + ]: 14881 : } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
9306 bruce@momjian.us 283 [ - + ]: 7280 : if (size-- == 0)
9306 bruce@momjian.us 284 :UBC 0 : goto emsgsize;
9306 bruce@momjian.us 285 :CBC 7280 : *dst++ = (u_char) tmp;
286 [ + + + + ]: 7280 : if (ch == '\0' || ch == '/')
287 : : break;
288 [ - + ]: 5415 : if (ch != '.')
9306 bruce@momjian.us 289 :UBC 0 : goto enoent;
290 : : }
291 : :
292 : : /* Get the prefix length if any. */
9306 bruce@momjian.us 293 :CBC 1865 : bits = -1;
8533 tgl@sss.pgh.pa.us 294 [ + + + - : 1865 : if (ch == '/' && isdigit((unsigned char) src[0]) && dst > odst)
+ - ]
295 : : {
296 : : /* CIDR width specifier. Nothing can follow it. */
9091 bruce@momjian.us 297 : 469 : ch = *src++; /* Skip over the /. */
9306 298 : 469 : bits = 0;
299 : : do
300 : : {
301 : 750 : n = strchr(digits, ch) - digits;
302 [ + - + - ]: 750 : assert(n >= 0 && n <= 9);
303 : 750 : bits *= 10;
304 : 750 : bits += n;
8533 tgl@sss.pgh.pa.us 305 [ + + + - ]: 750 : } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
9306 bruce@momjian.us 306 [ - + ]: 469 : if (ch != '\0')
9306 bruce@momjian.us 307 :UBC 0 : goto enoent;
9306 bruce@momjian.us 308 [ - + ]:CBC 469 : if (bits > 32)
9306 bruce@momjian.us 309 :UBC 0 : goto emsgsize;
310 : : }
311 : :
312 : : /* Fiery death and destruction unless we prefetched EOS. */
9306 bruce@momjian.us 313 [ - + ]:CBC 1865 : if (ch != '\0')
9306 bruce@momjian.us 314 :UBC 0 : goto enoent;
315 : :
316 : : /* Prefix length can default to /32 only if all four octets spec'd. */
9306 bruce@momjian.us 317 [ + + ]:CBC 1865 : if (bits == -1)
318 : : {
319 [ + - ]: 1396 : if (dst - odst == 4)
320 : 1396 : bits = 32;
321 : : else
9306 bruce@momjian.us 322 :UBC 0 : goto enoent;
323 : : }
324 : :
325 : : /* If nothing was written to the destination, we found no address. */
9306 bruce@momjian.us 326 [ - + ]:CBC 1865 : if (dst == odst)
9306 bruce@momjian.us 327 :UBC 0 : goto enoent;
328 : :
329 : : /* If prefix length overspecifies mantissa, life is bad. */
9306 bruce@momjian.us 330 [ - + ]:CBC 1865 : if ((bits / 8) > (dst - odst))
9306 bruce@momjian.us 331 :UBC 0 : goto enoent;
332 : :
333 : : /* Extend address to four octets. */
9306 bruce@momjian.us 334 [ + + ]:CBC 2045 : while (size-- > 0)
335 : 180 : *dst++ = 0;
336 : :
337 : 1865 : return bits;
338 : :
9091 339 : 6 : enoent:
9306 340 : 6 : errno = ENOENT;
2432 peter_e@gmx.net 341 : 6 : return -1;
342 : :
9091 bruce@momjian.us 343 :UBC 0 : emsgsize:
9306 344 : 0 : errno = EMSGSIZE;
2432 peter_e@gmx.net 345 : 0 : return -1;
346 : : }
347 : :
348 : : static int
7559 bruce@momjian.us 349 :CBC 238 : getbits(const char *src, int *bitsp)
350 : : {
351 : : static const char digits[] = "0123456789";
352 : : int n;
353 : : int val;
354 : : char ch;
355 : :
7600 356 : 238 : val = 0;
357 : 238 : n = 0;
7559 358 [ + + ]: 712 : while ((ch = *src++) != '\0')
359 : : {
360 : : const char *pch;
361 : :
7600 362 : 474 : pch = strchr(digits, ch);
7559 363 [ + - ]: 474 : if (pch != NULL)
364 : : {
7600 365 [ + + - + ]: 474 : if (n++ != 0 && val == 0) /* no leading zeros */
2432 peter_e@gmx.net 366 :UBC 0 : return 0;
7600 bruce@momjian.us 367 :CBC 474 : val *= 10;
368 : 474 : val += (pch - digits);
7559 369 [ - + ]: 474 : if (val > 128) /* range */
2432 peter_e@gmx.net 370 :UBC 0 : return 0;
7600 bruce@momjian.us 371 :CBC 474 : continue;
372 : : }
2432 peter_e@gmx.net 373 :UBC 0 : return 0;
374 : : }
7600 bruce@momjian.us 375 [ - + ]:CBC 238 : if (n == 0)
2432 peter_e@gmx.net 376 :UBC 0 : return 0;
7600 bruce@momjian.us 377 :CBC 238 : *bitsp = val;
2432 peter_e@gmx.net 378 : 238 : return 1;
379 : : }
380 : :
381 : : static int
7559 bruce@momjian.us 382 : 9 : getv4(const char *src, u_char *dst, int *bitsp)
383 : : {
384 : : static const char digits[] = "0123456789";
385 : 9 : u_char *odst = dst;
386 : : int n;
387 : : u_int val;
388 : : char ch;
389 : :
7600 390 : 9 : val = 0;
391 : 9 : n = 0;
7559 392 [ + + ]: 72 : while ((ch = *src++) != '\0')
393 : : {
394 : : const char *pch;
395 : :
7600 396 : 69 : pch = strchr(digits, ch);
7559 397 [ + + ]: 69 : if (pch != NULL)
398 : : {
7600 399 [ - + - - ]: 36 : if (n++ != 0 && val == 0) /* no leading zeros */
2432 peter_e@gmx.net 400 :UBC 0 : return 0;
7600 bruce@momjian.us 401 :CBC 36 : val *= 10;
402 : 36 : val += (pch - digits);
7559 403 [ - + ]: 36 : if (val > 255) /* range */
2432 peter_e@gmx.net 404 :UBC 0 : return 0;
7600 bruce@momjian.us 405 :CBC 36 : continue;
406 : : }
7559 407 [ + + + - ]: 33 : if (ch == '.' || ch == '/')
408 : : {
409 [ - + ]: 33 : if (dst - odst > 3) /* too many octets? */
2432 peter_e@gmx.net 410 :UBC 0 : return 0;
7600 bruce@momjian.us 411 :CBC 33 : *dst++ = val;
412 [ + + ]: 33 : if (ch == '/')
2432 peter_e@gmx.net 413 : 6 : return getbits(src, bitsp);
7600 bruce@momjian.us 414 : 27 : val = 0;
415 : 27 : n = 0;
416 : 27 : continue;
417 : : }
2432 peter_e@gmx.net 418 :UBC 0 : return 0;
419 : : }
7600 bruce@momjian.us 420 [ - + ]:CBC 3 : if (n == 0)
2432 peter_e@gmx.net 421 :UBC 0 : return 0;
7559 bruce@momjian.us 422 [ - + ]:CBC 3 : if (dst - odst > 3) /* too many octets? */
2432 peter_e@gmx.net 423 :UBC 0 : return 0;
7600 bruce@momjian.us 424 :CBC 3 : *dst++ = val;
2432 peter_e@gmx.net 425 : 3 : return 1;
426 : : }
427 : :
428 : : static int
7600 bruce@momjian.us 429 : 304 : inet_net_pton_ipv6(const char *src, u_char *dst)
430 : : {
431 : 304 : return inet_cidr_pton_ipv6(src, dst, 16);
432 : : }
433 : :
434 : : #define NS_IN6ADDRSZ 16
435 : : #define NS_INT16SZ 2
436 : : #define NS_INADDRSZ 4
437 : :
438 : : static int
7559 439 : 448 : inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size)
440 : : {
441 : : static const char xdigits_l[] = "0123456789abcdef",
442 : : xdigits_u[] = "0123456789ABCDEF";
443 : : u_char tmp[NS_IN6ADDRSZ],
444 : : *tp,
445 : : *endp,
446 : : *colonp;
447 : : const char *xdigits,
448 : : *curtok;
449 : : int ch,
450 : : saw_xdigit;
451 : : u_int val;
452 : : int digits;
453 : : int bits;
454 : :
7600 455 [ - + ]: 448 : if (size < NS_IN6ADDRSZ)
7600 bruce@momjian.us 456 :UBC 0 : goto emsgsize;
457 : :
7600 bruce@momjian.us 458 :CBC 448 : memset((tp = tmp), '\0', NS_IN6ADDRSZ);
459 : 448 : endp = tp + NS_IN6ADDRSZ;
460 : 448 : colonp = NULL;
461 : : /* Leading :: requires some special handling. */
462 [ + + ]: 448 : if (*src == ':')
463 [ - + ]: 24 : if (*++src != ':')
7600 bruce@momjian.us 464 :UBC 0 : goto enoent;
7600 bruce@momjian.us 465 :CBC 448 : curtok = src;
466 : 448 : saw_xdigit = 0;
467 : 448 : val = 0;
468 : 448 : digits = 0;
469 : 448 : bits = -1;
7559 470 [ + + ]: 9900 : while ((ch = *src++) != '\0')
471 : : {
472 : : const char *pch;
473 : :
7600 474 [ + + ]: 9696 : if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
475 : 2276 : pch = strchr((xdigits = xdigits_u), ch);
7559 476 [ + + ]: 9696 : if (pch != NULL)
477 : : {
7600 478 : 7420 : val <<= 4;
479 : 7420 : val |= (pch - xdigits);
480 [ - + ]: 7420 : if (++digits > 4)
7600 bruce@momjian.us 481 :UBC 0 : goto enoent;
7600 bruce@momjian.us 482 :CBC 7420 : saw_xdigit = 1;
483 : 7420 : continue;
484 : : }
7559 485 [ + + ]: 2276 : if (ch == ':')
486 : : {
7600 487 : 2035 : curtok = src;
7559 488 [ + + ]: 2035 : if (!saw_xdigit)
489 : : {
7600 490 [ + + ]: 360 : if (colonp)
491 : 3 : goto enoent;
492 : 357 : colonp = tp;
493 : 357 : continue;
494 : : }
7559 495 [ - + ]: 1675 : else if (*src == '\0')
7600 bruce@momjian.us 496 :UBC 0 : goto enoent;
7600 bruce@momjian.us 497 [ - + ]:CBC 1675 : if (tp + NS_INT16SZ > endp)
2859 tgl@sss.pgh.pa.us 498 :UBC 0 : goto enoent;
7600 bruce@momjian.us 499 :CBC 1675 : *tp++ = (u_char) (val >> 8) & 0xff;
500 : 1675 : *tp++ = (u_char) val & 0xff;
501 : 1675 : saw_xdigit = 0;
502 : 1675 : digits = 0;
503 : 1675 : val = 0;
504 : 1675 : continue;
505 : : }
506 [ + + + - : 250 : if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ - ]
7559 507 : 9 : getv4(curtok, tp, &bits) > 0)
508 : : {
7600 509 : 9 : tp += NS_INADDRSZ;
510 : 9 : saw_xdigit = 0;
7559 511 : 9 : break; /* '\0' was seen by inet_pton4(). */
512 : : }
7600 513 [ + - + - ]: 232 : if (ch == '/' && getbits(src, &bits) > 0)
514 : 232 : break;
7600 bruce@momjian.us 515 :UBC 0 : goto enoent;
516 : : }
7559 bruce@momjian.us 517 [ + + ]:CBC 445 : if (saw_xdigit)
518 : : {
7600 519 [ - + ]: 376 : if (tp + NS_INT16SZ > endp)
7600 bruce@momjian.us 520 :UBC 0 : goto enoent;
7600 bruce@momjian.us 521 :CBC 376 : *tp++ = (u_char) (val >> 8) & 0xff;
522 : 376 : *tp++ = (u_char) val & 0xff;
523 : : }
524 [ + + ]: 445 : if (bits == -1)
525 : 207 : bits = 128;
526 : :
7559 527 : 445 : endp = tmp + 16;
528 : :
529 [ + + ]: 445 : if (colonp != NULL)
530 : : {
531 : : /*
532 : : * Since some memmove()'s erroneously fail to handle overlapping
533 : : * regions, we'll do the shift by hand.
534 : : */
535 : 354 : const int n = tp - colonp;
536 : : int i;
537 : :
7600 538 [ - + ]: 354 : if (tp == endp)
7600 bruce@momjian.us 539 :UBC 0 : goto enoent;
7559 bruce@momjian.us 540 [ + + ]:CBC 2256 : for (i = 1; i <= n; i++)
541 : : {
542 : 1902 : endp[-i] = colonp[n - i];
7600 543 : 1902 : colonp[n - i] = 0;
544 : : }
545 : 354 : tp = endp;
546 : : }
547 [ - + ]: 445 : if (tp != endp)
7600 bruce@momjian.us 548 :UBC 0 : goto enoent;
549 : :
550 : : /*
551 : : * Copy out the result.
552 : : */
7600 bruce@momjian.us 553 :CBC 445 : memcpy(dst, tmp, NS_IN6ADDRSZ);
554 : :
2432 peter_e@gmx.net 555 : 445 : return bits;
556 : :
7559 bruce@momjian.us 557 : 3 : enoent:
7600 558 : 3 : errno = ENOENT;
2432 peter_e@gmx.net 559 : 3 : return -1;
560 : :
7559 bruce@momjian.us 561 :UBC 0 : emsgsize:
7600 562 : 0 : errno = EMSGSIZE;
2432 peter_e@gmx.net 563 : 0 : return -1;
564 : : }
|