1*6e778a7eSPedro F. Giffuni /*-
2*6e778a7eSPedro F. Giffuni * SPDX-License-Identifier: ISC
3*6e778a7eSPedro F. Giffuni *
465e96449SHajimu UMEMOTO * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
565e96449SHajimu UMEMOTO * Copyright (c) 1996,1999 by Internet Software Consortium.
665e96449SHajimu UMEMOTO *
765e96449SHajimu UMEMOTO * Permission to use, copy, modify, and distribute this software for any
865e96449SHajimu UMEMOTO * purpose with or without fee is hereby granted, provided that the above
965e96449SHajimu UMEMOTO * copyright notice and this permission notice appear in all copies.
1065e96449SHajimu UMEMOTO *
1165e96449SHajimu UMEMOTO * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
1265e96449SHajimu UMEMOTO * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1365e96449SHajimu UMEMOTO * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
1465e96449SHajimu UMEMOTO * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1565e96449SHajimu UMEMOTO * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1665e96449SHajimu UMEMOTO * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1765e96449SHajimu UMEMOTO * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1865e96449SHajimu UMEMOTO */
1965e96449SHajimu UMEMOTO
2065e96449SHajimu UMEMOTO #include "port_before.h"
2165e96449SHajimu UMEMOTO #include <sys/param.h>
2265e96449SHajimu UMEMOTO #include <sys/socket.h>
2365e96449SHajimu UMEMOTO #include <netinet/in.h>
2465e96449SHajimu UMEMOTO #include <arpa/inet.h>
2565e96449SHajimu UMEMOTO #include <arpa/nameser.h>
2665e96449SHajimu UMEMOTO #include <string.h>
2765e96449SHajimu UMEMOTO #include <errno.h>
2865e96449SHajimu UMEMOTO #include "port_after.h"
2965e96449SHajimu UMEMOTO
30dde4a85dSHajimu UMEMOTO /*%
3165e96449SHajimu UMEMOTO * WARNING: Don't even consider trying to compile this on a system where
3265e96449SHajimu UMEMOTO * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
3365e96449SHajimu UMEMOTO */
3465e96449SHajimu UMEMOTO
35ab96eeabSHajimu UMEMOTO static int inet_pton4(const char *src, u_char *dst);
36ab96eeabSHajimu UMEMOTO static int inet_pton6(const char *src, u_char *dst);
3765e96449SHajimu UMEMOTO
3865e96449SHajimu UMEMOTO /* int
3965e96449SHajimu UMEMOTO * inet_pton(af, src, dst)
4065e96449SHajimu UMEMOTO * convert from presentation format (which usually means ASCII printable)
4165e96449SHajimu UMEMOTO * to network format (which is usually some kind of binary format).
4265e96449SHajimu UMEMOTO * return:
4365e96449SHajimu UMEMOTO * 1 if the address was valid for the specified address family
4465e96449SHajimu UMEMOTO * 0 if the address wasn't valid (`dst' is untouched in this case)
4565e96449SHajimu UMEMOTO * -1 if some other error occurred (`dst' is untouched in this case, too)
4665e96449SHajimu UMEMOTO * author:
4765e96449SHajimu UMEMOTO * Paul Vixie, 1996.
4865e96449SHajimu UMEMOTO */
4965e96449SHajimu UMEMOTO int
inet_pton(int af,const char * __restrict src,void * __restrict dst)50ab96eeabSHajimu UMEMOTO inet_pton(int af, const char * __restrict src, void * __restrict dst)
5165e96449SHajimu UMEMOTO {
5265e96449SHajimu UMEMOTO switch (af) {
5365e96449SHajimu UMEMOTO case AF_INET:
5465e96449SHajimu UMEMOTO return (inet_pton4(src, dst));
5565e96449SHajimu UMEMOTO case AF_INET6:
5665e96449SHajimu UMEMOTO return (inet_pton6(src, dst));
5765e96449SHajimu UMEMOTO default:
5865e96449SHajimu UMEMOTO errno = EAFNOSUPPORT;
5965e96449SHajimu UMEMOTO return (-1);
6065e96449SHajimu UMEMOTO }
6165e96449SHajimu UMEMOTO /* NOTREACHED */
6265e96449SHajimu UMEMOTO }
6365e96449SHajimu UMEMOTO
6465e96449SHajimu UMEMOTO /* int
6565e96449SHajimu UMEMOTO * inet_pton4(src, dst)
6665e96449SHajimu UMEMOTO * like inet_aton() but without all the hexadecimal and shorthand.
6765e96449SHajimu UMEMOTO * return:
6865e96449SHajimu UMEMOTO * 1 if `src' is a valid dotted quad, else 0.
6965e96449SHajimu UMEMOTO * notice:
7065e96449SHajimu UMEMOTO * does not touch `dst' unless it's returning 1.
7165e96449SHajimu UMEMOTO * author:
7265e96449SHajimu UMEMOTO * Paul Vixie, 1996.
7365e96449SHajimu UMEMOTO */
7465e96449SHajimu UMEMOTO static int
inet_pton4(const char * src,u_char * dst)75ab96eeabSHajimu UMEMOTO inet_pton4(const char *src, u_char *dst)
7665e96449SHajimu UMEMOTO {
7765e96449SHajimu UMEMOTO static const char digits[] = "0123456789";
7865e96449SHajimu UMEMOTO int saw_digit, octets, ch;
7965e96449SHajimu UMEMOTO u_char tmp[NS_INADDRSZ], *tp;
8065e96449SHajimu UMEMOTO
8165e96449SHajimu UMEMOTO saw_digit = 0;
8265e96449SHajimu UMEMOTO octets = 0;
8365e96449SHajimu UMEMOTO *(tp = tmp) = 0;
8465e96449SHajimu UMEMOTO while ((ch = *src++) != '\0') {
8565e96449SHajimu UMEMOTO const char *pch;
8665e96449SHajimu UMEMOTO
8765e96449SHajimu UMEMOTO if ((pch = strchr(digits, ch)) != NULL) {
8865e96449SHajimu UMEMOTO u_int new = *tp * 10 + (pch - digits);
8965e96449SHajimu UMEMOTO
9065e96449SHajimu UMEMOTO if (saw_digit && *tp == 0)
9165e96449SHajimu UMEMOTO return (0);
9265e96449SHajimu UMEMOTO if (new > 255)
9365e96449SHajimu UMEMOTO return (0);
9465e96449SHajimu UMEMOTO *tp = new;
9565e96449SHajimu UMEMOTO if (!saw_digit) {
9665e96449SHajimu UMEMOTO if (++octets > 4)
9765e96449SHajimu UMEMOTO return (0);
9865e96449SHajimu UMEMOTO saw_digit = 1;
9965e96449SHajimu UMEMOTO }
10065e96449SHajimu UMEMOTO } else if (ch == '.' && saw_digit) {
10165e96449SHajimu UMEMOTO if (octets == 4)
10265e96449SHajimu UMEMOTO return (0);
10365e96449SHajimu UMEMOTO *++tp = 0;
10465e96449SHajimu UMEMOTO saw_digit = 0;
10565e96449SHajimu UMEMOTO } else
10665e96449SHajimu UMEMOTO return (0);
10765e96449SHajimu UMEMOTO }
10865e96449SHajimu UMEMOTO if (octets < 4)
10965e96449SHajimu UMEMOTO return (0);
11065e96449SHajimu UMEMOTO memcpy(dst, tmp, NS_INADDRSZ);
11165e96449SHajimu UMEMOTO return (1);
11265e96449SHajimu UMEMOTO }
11365e96449SHajimu UMEMOTO
11465e96449SHajimu UMEMOTO /* int
11565e96449SHajimu UMEMOTO * inet_pton6(src, dst)
11665e96449SHajimu UMEMOTO * convert presentation level address to network order binary form.
11765e96449SHajimu UMEMOTO * return:
11865e96449SHajimu UMEMOTO * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
11965e96449SHajimu UMEMOTO * notice:
12065e96449SHajimu UMEMOTO * (1) does not touch `dst' unless it's returning 1.
12165e96449SHajimu UMEMOTO * (2) :: in a full address is silently ignored.
12265e96449SHajimu UMEMOTO * credit:
12365e96449SHajimu UMEMOTO * inspired by Mark Andrews.
12465e96449SHajimu UMEMOTO * author:
12565e96449SHajimu UMEMOTO * Paul Vixie, 1996.
12665e96449SHajimu UMEMOTO */
12765e96449SHajimu UMEMOTO static int
inet_pton6(const char * src,u_char * dst)128ab96eeabSHajimu UMEMOTO inet_pton6(const char *src, u_char *dst)
12965e96449SHajimu UMEMOTO {
13065e96449SHajimu UMEMOTO static const char xdigits_l[] = "0123456789abcdef",
13165e96449SHajimu UMEMOTO xdigits_u[] = "0123456789ABCDEF";
13265e96449SHajimu UMEMOTO u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
13365e96449SHajimu UMEMOTO const char *xdigits, *curtok;
13465e96449SHajimu UMEMOTO int ch, seen_xdigits;
13565e96449SHajimu UMEMOTO u_int val;
13665e96449SHajimu UMEMOTO
13765e96449SHajimu UMEMOTO memset((tp = tmp), '\0', NS_IN6ADDRSZ);
13865e96449SHajimu UMEMOTO endp = tp + NS_IN6ADDRSZ;
13965e96449SHajimu UMEMOTO colonp = NULL;
14065e96449SHajimu UMEMOTO /* Leading :: requires some special handling. */
14165e96449SHajimu UMEMOTO if (*src == ':')
14265e96449SHajimu UMEMOTO if (*++src != ':')
14365e96449SHajimu UMEMOTO return (0);
14465e96449SHajimu UMEMOTO curtok = src;
14565e96449SHajimu UMEMOTO seen_xdigits = 0;
14665e96449SHajimu UMEMOTO val = 0;
14765e96449SHajimu UMEMOTO while ((ch = *src++) != '\0') {
14865e96449SHajimu UMEMOTO const char *pch;
14965e96449SHajimu UMEMOTO
15065e96449SHajimu UMEMOTO if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
15165e96449SHajimu UMEMOTO pch = strchr((xdigits = xdigits_u), ch);
15265e96449SHajimu UMEMOTO if (pch != NULL) {
15365e96449SHajimu UMEMOTO val <<= 4;
15465e96449SHajimu UMEMOTO val |= (pch - xdigits);
15565e96449SHajimu UMEMOTO if (++seen_xdigits > 4)
15665e96449SHajimu UMEMOTO return (0);
15765e96449SHajimu UMEMOTO continue;
15865e96449SHajimu UMEMOTO }
15965e96449SHajimu UMEMOTO if (ch == ':') {
16065e96449SHajimu UMEMOTO curtok = src;
16165e96449SHajimu UMEMOTO if (!seen_xdigits) {
16265e96449SHajimu UMEMOTO if (colonp)
16365e96449SHajimu UMEMOTO return (0);
16465e96449SHajimu UMEMOTO colonp = tp;
16565e96449SHajimu UMEMOTO continue;
16665e96449SHajimu UMEMOTO } else if (*src == '\0') {
16765e96449SHajimu UMEMOTO return (0);
16865e96449SHajimu UMEMOTO }
16965e96449SHajimu UMEMOTO if (tp + NS_INT16SZ > endp)
17065e96449SHajimu UMEMOTO return (0);
17165e96449SHajimu UMEMOTO *tp++ = (u_char) (val >> 8) & 0xff;
17265e96449SHajimu UMEMOTO *tp++ = (u_char) val & 0xff;
17365e96449SHajimu UMEMOTO seen_xdigits = 0;
17465e96449SHajimu UMEMOTO val = 0;
17565e96449SHajimu UMEMOTO continue;
17665e96449SHajimu UMEMOTO }
17765e96449SHajimu UMEMOTO if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
17865e96449SHajimu UMEMOTO inet_pton4(curtok, tp) > 0) {
17965e96449SHajimu UMEMOTO tp += NS_INADDRSZ;
18065e96449SHajimu UMEMOTO seen_xdigits = 0;
181dde4a85dSHajimu UMEMOTO break; /*%< '\\0' was seen by inet_pton4(). */
18265e96449SHajimu UMEMOTO }
18365e96449SHajimu UMEMOTO return (0);
18465e96449SHajimu UMEMOTO }
18565e96449SHajimu UMEMOTO if (seen_xdigits) {
18665e96449SHajimu UMEMOTO if (tp + NS_INT16SZ > endp)
18765e96449SHajimu UMEMOTO return (0);
18865e96449SHajimu UMEMOTO *tp++ = (u_char) (val >> 8) & 0xff;
18965e96449SHajimu UMEMOTO *tp++ = (u_char) val & 0xff;
19065e96449SHajimu UMEMOTO }
19165e96449SHajimu UMEMOTO if (colonp != NULL) {
19265e96449SHajimu UMEMOTO /*
19365e96449SHajimu UMEMOTO * Since some memmove()'s erroneously fail to handle
19465e96449SHajimu UMEMOTO * overlapping regions, we'll do the shift by hand.
19565e96449SHajimu UMEMOTO */
19665e96449SHajimu UMEMOTO const int n = tp - colonp;
19765e96449SHajimu UMEMOTO int i;
19865e96449SHajimu UMEMOTO
19965e96449SHajimu UMEMOTO if (tp == endp)
20065e96449SHajimu UMEMOTO return (0);
20165e96449SHajimu UMEMOTO for (i = 1; i <= n; i++) {
20265e96449SHajimu UMEMOTO endp[- i] = colonp[n - i];
20365e96449SHajimu UMEMOTO colonp[n - i] = 0;
20465e96449SHajimu UMEMOTO }
20565e96449SHajimu UMEMOTO tp = endp;
20665e96449SHajimu UMEMOTO }
20765e96449SHajimu UMEMOTO if (tp != endp)
20865e96449SHajimu UMEMOTO return (0);
20965e96449SHajimu UMEMOTO memcpy(dst, tmp, NS_IN6ADDRSZ);
21065e96449SHajimu UMEMOTO return (1);
21165e96449SHajimu UMEMOTO }
212ab96eeabSHajimu UMEMOTO
213ab96eeabSHajimu UMEMOTO /*
214ab96eeabSHajimu UMEMOTO * Weak aliases for applications that use certain private entry points,
215ab96eeabSHajimu UMEMOTO * and fail to include <arpa/inet.h>.
216ab96eeabSHajimu UMEMOTO */
217ab96eeabSHajimu UMEMOTO #undef inet_pton
218ab96eeabSHajimu UMEMOTO __weak_reference(__inet_pton, inet_pton);
219dde4a85dSHajimu UMEMOTO
220dde4a85dSHajimu UMEMOTO /*! \file */
221