inet_pton
https://man7.org/linux/man-pages/man3/inet_pton.3.html
Representation format to network address.
The resulting network address is in network order, i.e., big endian.
./code/inet_pton.c
1#include <arpa/inet.h>
2#include <stdio.h>
3
4int main() {
5 struct in_addr addr;
6 int res = inet_pton(AF_INET, "192.168.1.2", &addr);
7 printf("%08x\n", addr.s_addr);
8 printf("192: %x\n", 192);
9 printf("168: %x\n", 168);
10 printf("1: %x\n", 1);
11 printf("2: %x\n", 2);
12 return 0;
13}
14#if 0
15./inet_pton
160201a8c0
17192: c0
18168: a8
191: 1
202: 2
21#endif
Its implementation can be found at https://github.com/bminor/glibc/blob/master/resolv/inet_pton.c
./code/inet_pton_impl.c
1// See https://github.com/bminor/glibc/blob/master/resolv/inet_pton.c
2//
3/* Copyright (C) 1996-2022 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
19
20/*
21 * Copyright (c) 1996,1999 by Internet Software Consortium.
22 *
23 * Permission to use, copy, modify, and distribute this software for any
24 * purpose with or without fee is hereby granted, provided that the above
25 * copyright notice and this permission notice appear in all copies.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
28 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
29 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
30 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
31 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
32 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
33 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
34 * SOFTWARE.
35 */
36
37#include <arpa/inet.h>
38#include <arpa/nameser.h>
39#include <ctype.h>
40#include <errno.h>
41#include <netinet/in.h>
42#include <resolv/resolv-internal.h>
43#include <string.h>
44#include <sys/socket.h>
45#include <sys/types.h>
46
47static int inet_pton4 (const char *src, const char *src_end, u_char *dst);
48static int inet_pton6 (const char *src, const char *src_end, u_char *dst);
49
50int
51__inet_pton_length (int af, const char *src, size_t srclen, void *dst)
52{
53 switch (af)
54 {
55 case AF_INET:
56 return inet_pton4 (src, src + srclen, dst);
57 case AF_INET6:
58 return inet_pton6 (src, src + srclen, dst);
59 default:
60 __set_errno (EAFNOSUPPORT);
61 return -1;
62 }
63}
64libc_hidden_def (__inet_pton_length)
65
66/* Like __inet_pton_length, but use strlen (SRC) as the length of
67 SRC. */
68int
69__inet_pton (int af, const char *src, void *dst)
70{
71 return __inet_pton_length (af, src, strlen (src), dst);
72}
73libc_hidden_def (__inet_pton)
74weak_alias (__inet_pton, inet_pton)
75libc_hidden_weak (inet_pton)
76
77/* Like inet_aton but without all the hexadecimal, octal and shorthand
78 (and trailing garbage is not ignored). Return 1 if SRC is a valid
79 dotted quad, else 0. This function does not touch DST unless it's
80 returning 1.
81 Author: Paul Vixie, 1996. */
82static int
83inet_pton4 (const char *src, const char *end, unsigned char *dst)
84{
85 int saw_digit, octets, ch;
86 unsigned char tmp[NS_INADDRSZ], *tp;
87
88 saw_digit = 0;
89 octets = 0;
90 *(tp = tmp) = 0;
91 while (src < end)
92 {
93 ch = *src++;
94 if (ch >= '0' && ch <= '9')
95 {
96 unsigned int new = *tp * 10 + (ch - '0');
97
98 if (saw_digit && *tp == 0)
99 return 0;
100 if (new > 255)
101 return 0;
102 *tp = new;
103 if (! saw_digit)
104 {
105 if (++octets > 4)
106 return 0;
107 saw_digit = 1;
108 }
109 }
110 else if (ch == '.' && saw_digit)
111 {
112 if (octets == 4)
113 return 0;
114 *++tp = 0;
115 saw_digit = 0;
116 }
117 else
118 return 0;
119 }
120 if (octets < 4)
121 return 0;
122 memcpy (dst, tmp, NS_INADDRSZ);
123 return 1;
124}
125
126/* Return the value of CH as a hexademical digit, or -1 if it is a
127 different type of character. */
128static int
129hex_digit_value (char ch)
130{
131 if ('0' <= ch && ch <= '9')
132 return ch - '0';
133 if ('a' <= ch && ch <= 'f')
134 return ch - 'a' + 10;
135 if ('A' <= ch && ch <= 'F')
136 return ch - 'A' + 10;
137 return -1;
138}
139
140/* Convert presentation-level IPv6 address to network order binary
141 form. Return 1 if SRC is a valid [RFC1884 2.2] address, else 0.
142 This function does not touch DST unless it's returning 1.
143 Author: Paul Vixie, 1996. Inspired by Mark Andrews. */
144static int
145inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
146{
147 unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
148 const char *curtok;
149 int ch;
150 size_t xdigits_seen; /* Number of hex digits since colon. */
151 unsigned int val;
152
153 tp = memset (tmp, '\0', NS_IN6ADDRSZ);
154 endp = tp + NS_IN6ADDRSZ;
155 colonp = NULL;
156
157 /* Leading :: requires some special handling. */
158 if (src == src_endp)
159 return 0;
160 if (*src == ':')
161 {
162 ++src;
163 if (src == src_endp || *src != ':')
164 return 0;
165 }
166
167 curtok = src;
168 xdigits_seen = 0;
169 val = 0;
170 while (src < src_endp)
171 {
172 ch = *src++;
173 int digit = hex_digit_value (ch);
174 if (digit >= 0)
175 {
176 if (xdigits_seen == 4)
177 return 0;
178 val <<= 4;
179 val |= digit;
180 if (val > 0xffff)
181 return 0;
182 ++xdigits_seen;
183 continue;
184 }
185 if (ch == ':')
186 {
187 curtok = src;
188 if (xdigits_seen == 0)
189 {
190 if (colonp)
191 return 0;
192 colonp = tp;
193 continue;
194 }
195 else if (src == src_endp)
196 return 0;
197 if (tp + NS_INT16SZ > endp)
198 return 0;
199 *tp++ = (unsigned char) (val >> 8) & 0xff;
200 *tp++ = (unsigned char) val & 0xff;
201 xdigits_seen = 0;
202 val = 0;
203 continue;
204 }
205 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp)
206 && inet_pton4 (curtok, src_endp, tp) > 0)
207 {
208 tp += NS_INADDRSZ;
209 xdigits_seen = 0;
210 break; /* '\0' was seen by inet_pton4. */
211 }
212 return 0;
213 }
214 if (xdigits_seen > 0)
215 {
216 if (tp + NS_INT16SZ > endp)
217 return 0;
218 *tp++ = (unsigned char) (val >> 8) & 0xff;
219 *tp++ = (unsigned char) val & 0xff;
220 }
221 if (colonp != NULL)
222 {
223 /* Replace :: with zeros. */
224 if (tp == endp)
225 /* :: would expand to a zero-width field. */
226 return 0;
227 size_t n = tp - colonp;
228 memmove (endp - n, colonp, n);
229 memset (colonp, 0, endp - n - colonp);
230 tp = endp;
231 }
232 if (tp != endp)
233 return 0;
234 memcpy (dst, tmp, NS_IN6ADDRSZ);
235 return 1;
236}