Watt-32 tcp/ip  2.2 dev-rel.10
netaddr.c
Go to the documentation of this file.
1 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 
28 #include "wattcp.h"
29 #include "misc.h"
30 #include "strings.h"
31 #include "netaddr.h"
32 
33 #if defined(USE_BSD_API)
34 #include "socket.h"
35 #endif
36 
43 char * W32_CALL _inet_ntoa (char *s, DWORD ip)
44 {
45  static char buf[4][20];
46  static int idx = 0;
47  char *p = s;
48 
49  if (!p)
50  {
51  p = buf [idx++];
52  idx &= 3;
53  }
54  itoa ((int)(ip >> 24), p, 10);
55  strcat (p, ".");
56  itoa ((int)(ip >> 16) & 0xFF, strchr(p,'\0'), 10);
57  strcat (p, ".");
58  itoa ((int)(ip >> 8) & 0xFF, strchr(p,'\0'), 10);
59  strcat (p, ".");
60  itoa ((int)(ip & 0xFF), strchr(p,'\0'), 10);
61  return (p);
62 }
63 
69 DWORD W32_CALL _inet_addr (const char *s)
70 {
71  DWORD addr = 0;
72 
73  if (isaddr(s))
74  return aton (s);
75  if (isaddr_dotless(s,&addr))
76  return (addr);
77  return (0);
78 }
79 
80 
86 DWORD W32_CALL aton (const char *str)
87 {
88  DWORD ip = 0;
89  int i;
90  char *s = (char*)str;
91 
92  if (*s == '[')
93  ++s;
94 
95  for (i = 24; i >= 0; i -= 8)
96  {
97  int cur = ATOI (s);
98 
99  ip |= (DWORD)(cur & 0xFF) << i;
100  if (!i)
101  return (ip);
102 
103  s = strchr (s, '.');
104  if (!s)
105  return (0); /* return 0 on error */
106  s++;
107  }
108  return (0); /* cannot happen ?? */
109 }
110 
115 DWORD W32_CALL aton_dotless (const char *str)
116 {
117  DWORD ip = 0UL;
118 
119  isaddr_dotless (str, &ip);
120  return (ip);
121 }
122 
128 BOOL W32_CALL isaddr (const char *str)
129 {
130  int ch;
131 
132  while ((ch = *str++) != 0)
133  {
134  if (isdigit(ch))
135  continue;
136  if (ch == '.' || ch == ' ' || ch == '[' || ch == ']')
137  continue;
138  return (FALSE);
139  }
140  return (TRUE);
141 }
142 
148 BOOL W32_CALL isaddr_dotless (const char *str, DWORD *ip)
149 {
150  char buf[10] = { 0 };
151  int ch, i = 0;
152  DWORD addr;
153 
154  while ((ch = *str++) != '\0')
155  {
156  if (ch == '.' || i == SIZEOF(buf))
157  return (FALSE);
158 
159  if (isdigit(ch))
160  {
161  buf[i++] = ch;
162  continue;
163  }
164  if (ch == ' ' || ch == '[' || ch == ']')
165  continue;
166  return (FALSE);
167  }
168 
169  buf[i] = '\0';
170  addr = atol (buf);
171  if (addr == 0)
172  return (FALSE);
173 
174  if ((addr % 256) == 0) /* LSB must be non-zero */
175  return (FALSE);
176 
177  if (((addr >> 24) % 256) == 0) /* MSB must be non-zero */
178  return (FALSE);
179 
180  if (ip)
181  *ip = addr;
182  return (TRUE);
183 }
184 
185 char * W32_CALL inet_ntoa (struct in_addr addr)
186 {
187  static char buf [4][20]; /* use max 4 at a time */
188  static int idx = 0;
189  char *rc = buf [idx++];
190 
191  idx &= 3;
192  return _inet_ntoa (rc, ntohl(addr.s_addr));
193 }
194 
205 const char *_inet_atoeth (const char *src, eth_address *p_eth)
206 {
207  BYTE *eth = (BYTE*)p_eth;
208 
209 #if (DOSX)
210  int tmp [sizeof(eth_address)];
211  BOOL ok, colon = (src[2] == ':');
212 
213  ok = colon ? (sscanf(src,"%02x:%02x:%02x:%02x:%02x:%02x",
214  &tmp[0], &tmp[1], &tmp[2],
215  &tmp[3], &tmp[4], &tmp[5]) == DIM(tmp)) :
216  (sscanf(src,"%02x-%02x-%02x-%02x-%02x-%02x",
217  &tmp[0], &tmp[1], &tmp[2],
218  &tmp[3], &tmp[4], &tmp[5]) == DIM(tmp));
219  if (!ok)
220  return (NULL);
221 
222  eth [0] = tmp [0];
223  eth [1] = tmp [1];
224  eth [2] = tmp [2];
225  eth [3] = tmp [3];
226  eth [4] = tmp [4];
227  eth [5] = tmp [5];
228  src = strrchr(src, colon ? ':' : '-') + 3;
229 #else
230  eth [0] = atox (src-2); /* xx:xx:xx:xx:xx:xx */
231  eth [1] = atox (src+1); /* ^src-2 */
232  eth [2] = atox (src+4); /* ^src+1 */
233  eth [3] = atox (src+7);
234  eth [4] = atox (src+10);
235  eth [5] = atox (src+13);
236 
237  src += strlen ("xx:xx:xx:xx:xx:xx");
238 #endif
239 
240  if (*src == ',')
241  ++src;
242  return strltrim (src);
243 }
244 
245 #if defined(USE_BSD_API)
246 
247 char * W32_CALL inet_ntoa_r (struct in_addr addr, char *buf, int buflen)
248 {
249  if (buf && buflen >= SIZEOF("255.255.255.255"))
250  return _inet_ntoa (buf, ntohl(addr.s_addr));
251  return (NULL);
252 }
253 
254 int W32_CALL inet_aton (const char *name, struct in_addr *addr)
255 {
256  u_long ip = inet_addr (name);
257 
258  if (ip == INADDR_NONE && strcmp(name,"255.255.255.255"))
259  return (0);
260  addr->s_addr = ip;
261  return (1);
262 }
263 
264 u_long W32_CALL inet_addr (const char *addr)
265 {
266  DWORD ip = htonl (_inet_addr(addr));
267 
268  if (ip)
269  return (ip);
270  return (INADDR_NONE);
271 }
272 
273 u_long W32_CALL inet_network (const char *name)
274 {
275  u_long val, base;
276  u_long parts[4];
277  u_long *pp = parts;
278  int i, c, n;
279 
280 again:
281  /* Collect number up to ``.''. Values are specified as for C:
282  * 0x=hex, 0=octal, other=decimal.
283  */
284  val = 0;
285  base = 10;
286 
287  /* The 4.4BSD version of this file also accepts 'x__' as a hexa
288  * number. I don't think this is correct. -- Uli
289  */
290  if (*name == '0')
291  {
292  if (*++name == 'x' || *name == 'X')
293  base = 16, name++;
294  else base = 8;
295  }
296  while ((c = *name) != '\0')
297  {
298  if (isdigit(c))
299  {
300  val = (val * base) + (c - '0');
301  name++;
302  continue;
303  }
304  if (base == 16 && isxdigit(c))
305  {
306  val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
307  name++;
308  continue;
309  }
310  break;
311  }
312  if (*name == '.')
313  {
314  if (pp >= parts + 4)
315  return (INADDR_NONE);
316 
317  *pp++ = val;
318  name++;
319  goto again;
320  }
321  if (*name && !isspace((int)*name))
322  return (INADDR_NONE);
323 
324  *pp++ = val;
325  n = (int) (pp - parts);
326  if (n > 4)
327  return (INADDR_NONE);
328 
329  for (val = 0, i = 0; i < n; i++)
330  {
331  val <<= 8;
332  val |= parts[i] & 0xff;
333  }
334  return (val);
335 }
336 
341 u_long W32_CALL inet_netof (struct in_addr addr)
342 {
343  u_long a = ntohl (addr.s_addr);
344 
345  if (IN_CLASSA(a))
346  return ((a & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
347 
348  if (IN_CLASSB(a))
349  return ((a & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
350 
351  return ((a & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
352 }
353 
360 u_long W32_CALL inet_lnaof (struct in_addr addr)
361 {
362  u_long a = ntohl (addr.s_addr);
363 
364  if (IN_CLASSA(a))
365  return (a & IN_CLASSA_HOST);
366 
367  if (IN_CLASSB(a))
368  return (a & IN_CLASSB_HOST);
369 
370  return (a & IN_CLASSC_HOST);
371 }
372 
377 struct in_addr W32_CALL inet_makeaddr (u_long net, u_long host)
378 {
379  u_long addr;
380 
381  if (net < 128)
382  addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
383 
384  else if (net < 65536)
385  addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
386 
387  else if (net < 16777216L)
388  addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
389 
390  else addr = (net | host);
391 
392  addr = htonl (addr);
393  return (*(struct in_addr*) &addr);
394 }
395 
401 const char *_inet6_ntoa (const void *ip)
402 {
403  static char buf [4][50]; /* use max 4 at a time */
404  static int idx = 0;
405  char *rc = buf [idx++];
406 
407  /* inet_ntop() should never return NULL.
408  */
409  idx &= 3;
410  rc = (char*) inet_ntop (AF_INET6, ip, rc, sizeof(buf[0]));
411  return (const char*)rc;
412 }
413 
419 const ip6_address *_inet6_addr (const char *str)
420 {
421  static ip6_address ip6;
422 
423  if (!inet_pton(AF_INET6, str, &ip6))
424  return (NULL);
425  return (const ip6_address*)ip6;
426 }
427 
428 /*
429  * Convert ASCII to network addresses.
430  */
431 int W32_CALL ascii2addr (int af, const char *ascii, void *result)
432 {
433  struct in_addr *ina;
434  char strbuf [4*sizeof("123")]; /* long enough for V4 only */
435 
436  switch (af)
437  {
438  case AF_INET:
439  ina = (struct in_addr*) result;
440  strbuf[0] = '\0';
441  strncat (strbuf, ascii, sizeof(strbuf)-1);
442  if (inet_aton (strbuf, ina))
443  return sizeof (*ina);
444  SOCK_ERRNO (EINVAL);
445  break;
446 
447  case AF_LINK:
448  link_addr (ascii, (struct sockaddr_dl*)result);
449  /* oops... no way to detect failure */
450  return sizeof (struct sockaddr_dl);
451 
452 #if defined(USE_IPV6)
453  case AF_INET6:
454  return inet_pton (AF_INET6, ascii, result);
455 #endif
456 
457  default:
458  SOCK_ERRNO (EPROTONOSUPPORT);
459  break;
460  }
461  return (-1);
462 }
463 
464 /*-
465  * Convert a network address from binary to printable numeric format.
466  * This API is copied from INRIA's IPv6 implementation, but it is a
467  * bit bogus in two ways:
468  *
469  * 1) There is no value in passing both an address family and
470  * an address length; either one should imply the other,
471  * or we should be passing sockaddrs instead.
472  * 2) There should by contrast be /added/ a length for the buffer
473  * that we pass in, so that programmers are spared the need to
474  * manually calculate (read: ``guess'') the maximum length.
475  *
476  * Flash: the API is also the same in the NRL implementation, and seems to
477  * be some sort of standard, so we appear to be stuck with both the bad
478  * naming and the poor choice of arguments.
479  */
480 char * W32_CALL addr2ascii (int af, const void *addrp, int len, char *buf)
481 {
482  static char staticbuf[64]; /* 64 for AF_LINK > 16 for AF_INET */
483 
484  if (!buf)
485  buf = staticbuf;
486 
487  switch (af)
488  {
489  case AF_INET:
490  if (len != sizeof (struct in_addr))
491  {
492  SOCK_ERRNO (ENAMETOOLONG);
493  return (NULL);
494  }
495  strcpy (buf, inet_ntoa (*(const struct in_addr *) addrp));
496  break;
497 
498  case AF_LINK:
499  if (len != sizeof (struct sockaddr_dl))
500  {
501  SOCK_ERRNO (ENAMETOOLONG);
502  return (NULL);
503  }
504  strcpy (buf, link_ntoa ((const struct sockaddr_dl *) addrp));
505  break;
506 
507  default:
508  SOCK_ERRNO (EPROTONOSUPPORT);
509  return (NULL);
510  }
511  return (buf);
512 }
513 #endif /* USE_BSD_API */
514 
515 
516 BOOL W32_CALL priv_addr (DWORD ip)
517 {
528  if (ip >= aton("10.0.0.0") && ip <= aton("10.255.255.255"))
529  return (TRUE);
530 
531  if (ip >= aton("172.16.0.0") && ip <= aton("172.31.255.255"))
532  return (TRUE);
533 
534  if (ip >= aton("192.168.0.0") && ip <= aton("192.168.255.255"))
535  return (TRUE);
536 
537  return (FALSE);
538 }
539 
540 /*
541  * Lev Walkin <vlm@lionet.info> provided these handy mask-checking
542  * macros/routines.
543  *
544  * Masklen to mask convertor.
545  */
546 #define MLEN2MASK(mlen) ((mlen) ? (((DWORD)-1) << (32 - (mlen))) : 0)
547 
548 /*
549  * Get the number of 0-bits of a mask.
550  * E.g. 255.255.255.0 -> 8
551  */
552 int mask_len (DWORD mask)
553 {
554  int len = 0;
555 
556  mask = ~mask;
557  while (mask & 1)
558  {
559  len++;
560  mask >>= 1;
561  }
562  return (len);
563 }
564 
565 /* Determine number of bits set in an IPv4 mask.
566  */
567 static DWORD bit_set (DWORD v)
568 {
569  DWORD m = v;
570 
571  m = (m & 0x55555555) + ((m & 0xAAAAAAAA) >> 1);
572  m = (m & 0x33333333) + ((m & 0xCCCCCCCC) >> 2);
573  m = (m & 0x0F0F0F0F) + ((m & 0xF0F0F0F0) >> 4);
574  m = (m & 0x00FF00FF) + ((m & 0xFF00FF00) >> 8);
575  m = (m & 0x0000FFFF) + ((m & 0xFFFF0000) >> 16);
576  return (m);
577 }
578 
579 /*
580  * Check the mask for correctness.
581  */
582 int check_mask (DWORD mask)
583 {
584  DWORD v = bit_set (mask);
585  return (MLEN2MASK(v) == mask);
586 }
587 
588 #if defined(USE_BSD_API)
589 /*
590  * The string-based version of above function.
591  * Inside 'USE_BSD_API' since inet_aton() is needed.
592  */
593 int check_mask2 (const char *mask)
594 {
595  struct in_addr imask;
596 
597  if (inet_aton(mask,&imask) != 1)
598  return (-1);
599  return check_mask (ntohl(imask.s_addr));
600 }
601 #endif /* USE_BSD_API */
602 
603 
DWORD W32_CALL aton(const char *str)
Converts [a.b.c.d] or a.b.c.d to 32 bit IPv4 address.
Definition: netaddr.c:86
char * strltrim(const char *s)
Return pointer to first non-blank (space/tab) in a string.
Definition: strings.c:243
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
Core definitions.
BOOL W32_CALL isaddr_dotless(const char *str, DWORD *ip)
Check if 'str' is a dotless ip address.
Definition: netaddr.c:148
Definition: ip.h:67
Definition: in.h:146
struct in_addr W32_CALL inet_makeaddr(u_long net, u_long host)
Formulate an Internet address from network + host (with subnet address).
Definition: netaddr.c:377
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
BOOL W32_CALL isaddr(const char *str)
Check if 'str' is simply an ip address.
Definition: netaddr.c:128
DWORD W32_CALL _inet_addr(const char *s)
Convert a string into an IP-address.
Definition: netaddr.c:69
u_long W32_CALL inet_netof(struct in_addr addr)
Return the network number from an internet address; handles class A/B/C network #'s.
Definition: netaddr.c:341
BYTE atox(const char *hex)
Convert hexstring "0x??" to hex.
Definition: strings.c:194
DWORD W32_CALL aton_dotless(const char *str)
Converts `[dotless]' or `dotless' to 32 bit long (host order)
Definition: netaddr.c:115
const char * _inet_atoeth(const char *src, eth_address *p_eth)
Parse string "ether-addr, ip-addr".
Definition: netaddr.c:205
const char * _inet6_ntoa(const void *ip)
Convert an IPv6-address 'ip' into a string.
Definition: netaddr.c:401
BOOL W32_CALL priv_addr(DWORD ip)
Definition: netaddr.c:516
const ip6_address * _inet6_addr(const char *str)
Convert a string 'str' into an IPv6-address.
Definition: netaddr.c:419
char *W32_CALL _inet_ntoa(char *s, DWORD ip)
Convert an IP-address 'ip' into a string.
Definition: netaddr.c:43
u_long W32_CALL inet_lnaof(struct in_addr addr)
Return the local network address portion of an internet address; handles class A/B/C network number f...
Definition: netaddr.c:360