Watt-32 tcp/ip  2.2 dev-rel.10
presaddr.c
Go to the documentation of this file.
1 
5 /* Copyright (c) 1996 by Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
12  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
13  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
14  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
16  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
17  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
18  * SOFTWARE.
19  */
20 
21 #include "socket.h"
22 
23 #if defined(USE_BSD_API)
24 
25 static const char *inet_ntop4 (const u_char *src, char *dst, size_t size);
26 static int inet_pton4 (const char *src, u_char *dst);
27 
28 #if defined(USE_IPV6)
29 static const char *inet_ntop6 (const u_char *src, char *dst, size_t size);
30 static int inet_pton6 (const char *src, u_char *dst);
31 #endif
32 
40 const char * W32_CALL inet_ntop (int af, const void *src, char *dst, size_t size)
41 {
42  switch (af)
43  {
44  case AF_INET:
45  return inet_ntop4 ((const u_char*)src, dst, size);
46 #if defined(USE_IPV6)
47  case AF_INET6:
48  return inet_ntop6 ((const u_char*)src, dst, size);
49 #endif
50  default:
51  SOCK_ERRNO (EAFNOSUPPORT);
52  return (NULL);
53  }
54 }
55 
56 
66 int W32_CALL inet_pton (int af, const char *src, void *dst)
67 {
68  switch (af)
69  {
70  case AF_INET:
71  return inet_pton4 (src, (u_char*)dst);
72 #if defined(USE_IPV6)
73  case AF_INET6:
74  return inet_pton6 (src, (u_char*)dst);
75 #endif
76  default:
77  SOCK_ERRNO (EAFNOSUPPORT);
78  return (-1);
79  }
80 }
81 
82 
92 static const char *inet_ntop4 (const u_char *src, char *dst, size_t size)
93 {
94  char tmp [sizeof("255.255.255.255")];
95 
96  if ((size_t)sprintf(tmp,"%u.%u.%u.%u",src[0],src[1],src[2],src[3]) > size)
97  {
98  SOCK_ERRNO (ENOSPC);
99  return (NULL);
100  }
101  return strcpy (dst, tmp);
102 }
103 
104 #if defined(USE_IPV6)
105 
110 static const char *inet_ntop6 (const u_char *src, char *dst, size_t size)
111 {
112  /*
113  * Note that int32_t and int16_t need only be "at least" large enough
114  * to contain a value of the specified size. On some systems, like
115  * Crays, there is no such thing as an integer variable with 16 bits.
116  * Keep this in mind if you think this function should have been coded
117  * to use pointer overlays. All the world's not a VAX.
118  */
119  char tmp [sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
120  char *tp;
121  struct {
122  long base;
123  long len;
124  } best, cur;
125  u_long words [IN6ADDRSZ / INT16SZ];
126  int i;
127 
128  /* Preprocess:
129  * Copy the input (bytewise) array into a wordwise array.
130  * Find the longest run of 0x00's in src[] for :: shorthanding.
131  */
132  memset (words, 0, sizeof(words));
133  for (i = 0; i < IN6ADDRSZ; i++)
134  words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
135 
136  best.base = -1;
137  best.len = 0;
138  cur.base = -1;
139  cur.len = 0;
140  for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
141  {
142  if (words[i] == 0)
143  {
144  if (cur.base == -1)
145  cur.base = i, cur.len = 1;
146  else cur.len++;
147  }
148  else if (cur.base != -1)
149  {
150  if (best.base == -1 || cur.len > best.len)
151  best = cur;
152  cur.base = -1;
153  }
154  }
155  if ((cur.base != -1) && (best.base == -1 || cur.len > best.len))
156  best = cur;
157 
158  if (best.base != -1 && best.len < 2)
159  best.base = -1;
160 
161  /* Format the result.
162  */
163  tp = tmp;
164  for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
165  {
166  /* Are we inside the best run of 0x00's?
167  */
168  if (best.base != -1 && i >= best.base && i < (best.base + best.len))
169  {
170  if (i == best.base)
171  *tp++ = ':';
172  continue;
173  }
174 
175  /* Are we following an initial run of 0x00s or any real hex?
176  */
177  if (i != 0)
178  *tp++ = ':';
179 
180  /* Is this address an encapsulated IPv4?
181  */
182  if (i == 6 && best.base == 0 &&
183  (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
184  {
185  if (!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp)))
186  {
187  SOCK_ERRNO (ENOSPC);
188  return (NULL);
189  }
190  tp += strlen (tp);
191  break;
192  }
193  tp += sprintf (tp, "%lX", words[i]);
194  }
195 
196  /* Was it a trailing run of 0x00's?
197  */
198  if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
199  *tp++ = ':';
200  *tp++ = '\0';
201 
202  /* Check for overflow, copy, and we're done.
203  */
204  if ((size_t)(tp - tmp) > size)
205  {
206  SOCK_ERRNO (ENOSPC);
207  return (NULL);
208  }
209  return strcpy (dst, tmp);
210 }
211 #endif /* USE_IPV6 */
212 
222 static int inet_pton4 (const char *src, u_char *dst)
223 {
224  static const char digits[] = "0123456789";
225  int saw_digit, octets, ch;
226  u_char tmp[INADDRSZ];
227  u_char *tp;
228 
229  saw_digit = 0;
230  octets = 0;
231  *(tp = tmp) = '\0';
232  while ((ch = *src++) != '\0')
233  {
234  const char *pch;
235 
236  if ((pch = strchr(digits, ch)) != NULL)
237  {
238  u_int New = *tp * 10 + (pch - digits);
239 
240  if (New > 255)
241  return (0);
242  *tp = New;
243  if (! saw_digit)
244  {
245  if (++octets > 4)
246  return (0);
247  saw_digit = 1;
248  }
249  }
250  else if (ch == '.' && saw_digit)
251  {
252  if (octets == 4)
253  return (0);
254  *++tp = '\0';
255  saw_digit = 0;
256  }
257  else
258  return (0);
259  }
260  if (octets < 4)
261  return (0);
262 
263  memcpy (dst, tmp, INADDRSZ);
264  return (1);
265 }
266 
267 #if defined(USE_IPV6)
268 
280 static int inet_pton6 (const char *src, u_char *dst)
281 {
282  u_char tmp [IN6ADDRSZ];
283  u_char *endp, *colonp, *tp = tmp;
284  const char *curtok;
285  int ch, saw_xdigit;
286  u_int val;
287 
288  memset (tmp, 0, sizeof(tmp));
289  endp = tmp + sizeof(tmp);
290  colonp = NULL;
291 
292  /* Leading :: requires some special handling.
293  */
294  if (*src == ':' && *++src != ':')
295  return (0);
296 
297  curtok = src;
298  saw_xdigit = 0;
299  val = 0;
300 
301  while ((ch = *src++) != '\0')
302  {
303  const char *pch;
304 
305  ch = tolower (ch);
306  pch = strchr (hex_chars_lower, ch);
307  if (pch)
308  {
309  val <<= 4;
310  val |= (pch - hex_chars_lower);
311  if (val > 0xffff)
312  return (0);
313  saw_xdigit = 1;
314  continue;
315  }
316  if (ch == ':')
317  {
318  curtok = src;
319  if (!saw_xdigit)
320  {
321  if (colonp)
322  return (0);
323  colonp = tp;
324  continue;
325  }
326  if (tp + INT16SZ > endp)
327  return (0);
328 
329  *tp++ = (u_char) (val >> 8) & 0xff;
330  *tp++ = (u_char) (val & 0xff);
331  saw_xdigit = 0;
332  val = 0;
333  continue;
334  }
335  if (ch == '.' && ((tp + INADDRSZ) <= endp) && inet_pton4(curtok,tp) > 0)
336  {
337  tp += INADDRSZ;
338  saw_xdigit = 0;
339  break; /* '\0' was seen by inet_pton4(). */
340  }
341  return (0);
342  }
343  if (saw_xdigit)
344  {
345  if (tp + INT16SZ > endp)
346  return (0);
347  *tp++ = (u_char) (val >> 8) & 0xff;
348  *tp++ = (u_char) val & 0xff;
349  }
350  if (colonp)
351  {
352  /*
353  * Since some memmove()'s erroneously fail to handle
354  * overlapping regions, we'll do the shift by hand.
355  */
356  const int n = tp - colonp;
357  int i;
358 
359  for (i = 1; i <= n; i++)
360  {
361  endp[-i] = colonp[n-i];
362  colonp[n-i] = '\0';
363  }
364  tp = endp;
365  }
366  if (tp != endp)
367  return (0);
368 
369  memcpy (dst, tmp, IN6ADDRSZ);
370  return (1);
371 }
372 #endif /* USE_IPV6 */
373 
374 
375 #if defined(TEST_PROG)
376 
377 int main (int argc, char **argv)
378 {
379  const char *ip6_str;
380  ip6_address ip6_addr;
381 
382  if (argc != 2)
383  {
384  printf ("Usage: %s ip6-address\n", argv[0]);
385  return (-1);
386  }
387 
388  ip6_str = argv[1];
389  memset (&ip6_addr, 0, sizeof(ip6_addr));
390  if (!inet_pton(AF_INET6, ip6_str, &ip6_addr))
391  {
392  printf ("Invalid IPv6 address `%s'\n", ip6_str);
393  return (-1);
394  }
395 
396  printf ("inet_pton(AF_INET6): %s -> %s\n",
397  ip6_str, _inet6_ntoa(&ip6_addr));
398  return (0);
399 }
400 #endif /* TEST_PROG */
401 #endif /* USE_BSD_API */
402 
403 
const char *W32_CALL inet_ntop(int af, const void *src, char *dst, size_t size)
Convert a network format address to presentation format.
Definition: presaddr.c:40
static int inet_pton6(const char *src, u_char *dst)
Convert presentation level address to network order binary form.
Definition: presaddr.c:280
static const char * inet_ntop4(const u_char *src, char *dst, size_t size)
Format an IPv4 address, more or less like inet_ntoa().
Definition: presaddr.c:92
int W32_CALL inet_pton(int af, const char *src, void *dst)
Convert from presentation format (which usually means ASCII printable) to network format (which is us...
Definition: presaddr.c:66
static int inet_pton4(const char *src, u_char *dst)
Like inet_aton() but without all the hexadecimal and shorthand.
Definition: presaddr.c:222
static const char * inet_ntop6(const u_char *src, char *dst, size_t size)
Convert IPv6 binary address into presentation (printable) format.
Definition: presaddr.c:110
const char * _inet6_ntoa(const void *ip)
Convert an IPv6-address 'ip' into a string.
Definition: netaddr.c:401
int main(int argc, char **argv)
Definition: echo.c:223