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}