NCBI C++ ToolKit
ncbi_ipv6.c
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: ncbi_ipv6.c 95391 2021-11-12 04:20:23Z lavr $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Anton Lavrentiev
27  *
28  * File Description:
29  * IPv6 addressing support
30  *
31  */
32 
33 #include "ncbi_ansi_ext.h"
34 #include "ncbi_priv.h"
35 #include <connect/ncbi_socket.h>
36 #include <connect/ncbi_ipv6.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 
44 struct SIPDNSsfx {
45  const char* sfx;
46  const size_t len;
47 };
48 static const struct SIPDNSsfx kIPv6DNS = { ".ip6.arpa", 9 };
49 static const struct SIPDNSsfx kIPv4DNS = { ".in-addr.arpa", 13 };
50 
51 
52 static int/*bool*/ x_NcbiIsIPv4(const TNCBI_IPv6Addr* addr, int/*bool*/ compat)
53 {
54  /* RFC 4291 2.1, 3
55  NB: 2.5.5.1 and 2.5.5.2 - both obsoleted by RFC 6052 2.1 */
56  unsigned short word;
57  size_t i;
58  for (i = 0; i < 5; ++i) {
59  memcpy(&word, addr->octet + i * sizeof(word), sizeof(word));
60  if (word)
61  return 0/*false*/;
62  }
63  memcpy(&word, addr->octet + i * sizeof(word), sizeof(word));
64  if (word == 0x0000) {
65  /* IPv4-compatible IPv6 */
66  if (compat) {
67  unsigned int temp;
68  memcpy(&temp, addr->octet + sizeof(addr->octet) - sizeof(temp),
69  sizeof(temp));
70  if (SOCK_NetToHostLong(temp) & 0xFF000000)
71  return 1/*true*/;
72  }
73  return 0/*false*/;
74  }
75  /* mapped IPv4 */
76  return word == 0xFFFF ? 1/*true*/ : 0/*false*/;
77 }
78 
79 
80 extern int/*bool*/ NcbiIsEmptyIPv6(const TNCBI_IPv6Addr* addr)
81 {
82  return !addr
83  || !memcchr(addr->octet, 0, sizeof(addr->octet))
84  || (x_NcbiIsIPv4(addr, 0/*mapped*/) && !NcbiIPv6ToIPv4(addr, 0))
85  ? 1/*true*/ : 0/*false*/;
86 }
87 
88 
89 extern int/*bool*/ NcbiIsIPv4(const TNCBI_IPv6Addr* addr)
90 {
91  return addr && x_NcbiIsIPv4(addr, 0/*mapped*/) ? 1/*true*/ : 0/*false*/;
92 }
93 
94 
95 extern int/*bool*/ NcbiIsIPv4Ex(const TNCBI_IPv6Addr* addr, int/*bool*/ compat)
96 {
97  return addr && x_NcbiIsIPv4(addr, compat) ? 1/*true*/ : 0/*false*/;
98 }
99 
100 
101 extern unsigned int NcbiIPv6ToIPv4(const TNCBI_IPv6Addr* addr, size_t pfxlen)
102 {
103  unsigned int ipv4;
104  static const size_t size = sizeof(ipv4);
105  if (!addr)
106  return 0;
107  if (pfxlen == 0) {
108  if (!x_NcbiIsIPv4(addr, 1/*compat*/))
109  return 0;
110  pfxlen = 96;
111  }
112  switch (pfxlen) { /*RFC 6052 2.2*/
113  case 32:
114  memcpy( &ipv4, &addr->octet[4], size);
115  break;
116  case 40:
117  memcpy( &ipv4, &addr->octet[5], size - 1);
118  memcpy((char*) &ipv4 + size - 1, &addr->octet[9], 1);
119  break;
120  case 48:
121  memcpy( &ipv4, &addr->octet[6], size - 2);
122  memcpy((char*) &ipv4 + size - 2, &addr->octet[9], 2);
123  break;
124  case 56:
125  memcpy( &ipv4, &addr->octet[7], size - 3);
126  memcpy((char*) &ipv4 + size - 3, &addr->octet[9], 3);
127  break;
128  case 64:
129  memcpy( &ipv4, &addr->octet[9], size);
130  break;
131  case 96:
132  memcpy( &ipv4, &addr->octet[12], size);
133  break;
134  default:
135  assert(0);
136  return (unsigned int)(-1)/*failure*/;
137  }
138  return ipv4;
139 }
140 
141 
142 extern int/*bool*/ NcbiIPv4ToIPv6(TNCBI_IPv6Addr* addr,
143  unsigned int ipv4, size_t pfxlen)
144 {
145  static const size_t size = sizeof(ipv4);
146  if (!addr)
147  return 0/*failure*/;
148  if (pfxlen == 0) {
149  /* creates IPv6 mapped */
150  memset(addr, 0, sizeof(*addr));
151  memset(addr->octet + (5 << 1), '\xFF', sizeof(unsigned short));
152  pfxlen = 96;
153  }
154  switch (pfxlen) { /*RFC 6052 2.2*/
155  case 32:
156  memcpy(&addr->octet[4], &ipv4, size);
157  break;
158  case 40:
159  memcpy(&addr->octet[5], &ipv4, size - 1);
160  memcpy(&addr->octet[9], (char*) &ipv4 + size - 1, 1);
161  break;
162  case 48:
163  memcpy(&addr->octet[6], &ipv4, size - 2);
164  memcpy(&addr->octet[9], (char*) &ipv4 + size - 2, 2);
165  break;
166  case 56:
167  memcpy(&addr->octet[7], &ipv4, size - 3);
168  memcpy(&addr->octet[9], (char*) &ipv4 + size - 3, 3);
169  break;
170  case 64:
171  memcpy(&addr->octet[9], &ipv4, size);
172  break;
173  case 96:
174  memcpy(&addr->octet[12], &ipv4, size);
175  break;
176  default:
177  assert(0);
178  return 0/*failure*/;
179  }
180  return 1/*success*/;
181 }
182 
183 
184 /* Parse "str" as an IPv4 address, and return 0 if failed, otherwise a pointer
185  * to the first non-parsed char (which is neither a digit nor a dot) and "dst"
186  * updated with the just read IPv4 address in network byte order.
187  */
188 static const char* x_StringToIPv4(unsigned int* dst,
189  const char* str, size_t len)
190 {
191  size_t n;
192  int octets = 0;
193  unsigned int tmp;
194  int/*bool*/ was_digit = 0/*false*/;
195  unsigned char *ptr = (unsigned char*) &tmp;
196 
197  *ptr = 0;
198  for (n = 0; n < len; ++n) {
199  char c = str[n];
200  if ('0' <= c && c <= '9') {
201  unsigned int val;
202  if (was_digit && !*ptr)
203  return 0/*leading "0" in octet*/;
204  val = (unsigned int)(*ptr * 10 + (c - '0'));
205  if (val > 255)
206  return 0;
207  *ptr = (unsigned char) val;
208  if (!was_digit) {
209  ++octets;
210  assert(octets <= 4);
211  was_digit = 1/*true*/;
212  }
213  } else if (c == '.') {
214  if (!was_digit || octets >= 4)
215  return 0;
216  was_digit = 0/*false*/;
217  *++ptr = 0;
218  } else
219  break;
220  }
221  if (octets != 4)
222  return 0/*failure*/;
223 
224  *dst = tmp;
225  return str + n;
226 }
227 
228 
229 static char* x_IPv4ToString(char* buf, size_t bufsize, const void* src)
230 {
231  char tmp[sizeof("255.255.255.255")];
232  unsigned char* ptr = (unsigned char*) src;
233  size_t len
234  = (size_t) sprintf(tmp, "%u.%u.%u.%u", ptr[0], ptr[1], ptr[2], ptr[3]);
235  return len < bufsize ? (char*) memcpy(buf, tmp, len + 1/*EOS*/) + len : 0;
236 }
237 
238 
239 /* Returns ptr past read (0 on error) */
240 static const char* x_StringToIPv6(TNCBI_IPv6Addr* addr,
241  const char* str, size_t len)
242 {
243  unsigned short word;
244  struct {
245  const char* ptr;
246  size_t len;
247  } token[sizeof(addr->octet) / sizeof(word) + 1];
248  size_t maxt = sizeof(token) / sizeof(token[0]) - 1, t, n;
249  TNCBI_IPv6Addr temp;
250  unsigned char* dst;
251  int/*bool*/ ipv4;
252  unsigned int ip;
253  size_t gap;
254 
255  if (len < 2 || (str[n = 0] == ':' && str[++n] != ':'))
256  return 0/*failure*/;
257  gap = 0;
258  ipv4 = 0/*false*/;
259  token[t = 0].ptr = str + n;
260  while (n <= len) {
261  assert(t <= maxt);
262  if (n == len || str[n] == ':') {
263  token[t].len = (size_t)(&str[n] - token[t].ptr);
264  if (token[t].len) {
265  if (n++ == len) {
266  if (++t > maxt)
267  return 0/*failure*/;
268  break;
269  }
270  } else {
271  if (n++ == len)
272  break;
273  if (gap++) /*RFC 4291 2.2, 2*/
274  return 0/*failure*/;
275  }
276  /*str[n - 1] == ':'*/
277  token[t].len++;
278  if (++t > maxt)
279  return 0/*failure*/;
280  token[t].ptr = str + n;
281  continue;
282  }
283  if (!isxdigit((unsigned char) str[n])) {
284  token[t].len = (size_t)(&str[n] - token[t].ptr);
285  if (token[t].len) {
286  if (str[n] == '.') {
287  if (t <= maxt - sizeof(ip) / sizeof(word)) {
288  const char* end
289  = x_StringToIPv4(&ip,
290  token[t].ptr,
291  token[t].len + (len - n));
292  if (end && *end != ':'
293  && t <= (maxt -= sizeof(ip) / sizeof(word))) {
294  token[t].len = (size_t)(end - token[t].ptr);
295  ipv4 = 1/*true*/;
296  break;
297  }
298  }
299  return 0/*failure*/;
300  }
301  if (++t > maxt)
302  return 0/*failure*/;
303  }
304  break;
305  }
306  n++;
307  }
308 
309  assert(t <= maxt);
310  if (t < maxt && !gap)
311  return 0/*failure*/;
312 
313  dst = temp.octet;
314  for (n = 0; n < t; ++n) {
315  assert(token[n].len);
316  if (*token[n].ptr != ':') {
317  char* end;
318  long val;
319  assert(isxdigit((unsigned char) token[n].ptr[0]));
320  errno = 0;
321  val = strtol(token[n].ptr, &end, 16);
322  if (errno || val ^ (val & 0xFFFF))
323  return 0/*failure*/;
324  assert(end == token[n].ptr + token[n].len - (*end == ':'));
325  if (*end == ':' && n == t - !ipv4)
326  return 0/*failure*/;
327  word = SOCK_HostToNetShort((unsigned short) val);
328  memcpy(dst, &word, sizeof(word));
329  dst += sizeof(word);
330  } else {
331  gap = (maxt - t) * sizeof(word) + sizeof(word);
332  memset(dst, 0, gap);
333  dst += gap;
334  }
335  }
336  if (ipv4) {
337  memcpy(dst, &ip, sizeof(ip));
338  ++t;
339  }
340 
341  *addr = temp;
342  return token[t - 1].ptr + token[t - 1].len;
343 }
344 
345 
346 extern const char* NcbiStringToIPv4(unsigned int* addr,
347  const char* str, size_t len)
348 {
349  size_t n;
350  if (!addr)
351  return 0/*failure*/;
352  *addr = 0;
353  if (!str)
354  return 0/*failure*/;
355  if (!len)
356  len = strlen(str);
357  for (n = 0; n < len; ++n) {
358  if (!isspace((unsigned char) str[n]))
359  break;
360  }
361  return x_StringToIPv4(addr, str + n, len - n);
362 }
363 
364 
365 extern const char* NcbiStringToIPv6(TNCBI_IPv6Addr* addr,
366  const char* str, size_t len)
367 {
368  size_t n;
369  if (!addr)
370  return 0/*failure*/;
371  memset(addr, 0, sizeof(*addr));
372  if (!str || !*str)
373  return 0/*failure*/;
374  if (!len)
375  len = strlen(str);
376  for (n = 0; n < len; ++n) {
377  if (!isspace((unsigned char) str[n]))
378  break;
379  }
380  return x_StringToIPv6(addr, str + n, len - n);
381 }
382 
383 
384 static char* x_IPv6ToString(char* buf, size_t bufsize,
385  const TNCBI_IPv6Addr* addr)
386 {
387  char ipv6[64/*enough for sizeof(8 * "xxxx:")*/];
388  char ipv4[sizeof("255.255.255.255")];
389  size_t i, n, pos, len, zpos, zlen;
390  unsigned short word;
391  char* ptr = ipv6;
392 
393  if (x_NcbiIsIPv4(addr, 1/*compat*/)) {
394  unsigned int ip;
395  n = sizeof(addr->octet) - sizeof(ip);
396  memcpy(&ip, addr->octet + n, sizeof(ip));
397  SOCK_ntoa(ip, ipv4, sizeof(ipv4));
398  n /= sizeof(word);
399  } else {
400  n = sizeof(addr->octet) / sizeof(word);
401  *ipv4 = '\0';
402  }
403 
404  pos = i = zpos = zlen = 0;
405  for (;;) {
406  if (i < n) {
407  memcpy(&word, &addr->octet[i * sizeof(word)], sizeof(word));
408  if (!word) {
409  ++i;
410  continue;
411  }
412  }
413  len = i - pos;
414  if (len > 1) { /*RFC 5952 4.2.2*/
415  if (zlen < len) {
416  zlen = len; /*RFC 5952 4.2.1*/
417  zpos = pos;
418  }
419  }
420  if (i == n)
421  break;
422  pos = ++i;
423  }
424 
425  i = 0;
426  while (i < n) {
427  if (zlen && zpos == i) {
428  assert(zlen > 1);
429  *ptr++ = ':';
430  if (zlen == n - i)
431  *ptr++ = ':';
432  i += zlen;
433  zlen = 0; /*RFC 5952 4.2.3*/
434  continue;
435  }
436  memcpy(&word, &addr->octet[i * sizeof(word)], sizeof(word));
437  ptr += sprintf(ptr, &":%x"[!i], /*RFC 5952 4.1, 4.3*/
438  SOCK_NetToHostShort(word));
439  ++i;
440  }
441  assert(ptr > ipv6);
442 
443  i = strlen(ipv4);
444  if (i) {
445  if (ptr[-1] != ':')
446  *ptr++ = ':';
447  }
448  n = (size_t)(ptr - ipv6);
449  len = n + i;
450  if (len < bufsize) {
451  memcpy(buf, ipv6, n);
452  buf += n;
453  memcpy(buf, ipv4, i);
454  buf += i;
455  *buf = '\0';
456  } else
457  buf = 0;
458  return buf;
459 }
460 
461 
462 /* Returns ptr past written (points to '\0'); 0 on error */
463 extern char* NcbiIPv4ToString(char* buf, size_t bufsize,
464  unsigned int addr)
465 {
466  /* sanity */
467  if (!buf || !bufsize)
468  return 0;
469  *buf = '\0';
470 
471  return x_IPv4ToString(buf, bufsize, &addr);
472 }
473 
474 
475 /* Returns ptr past written (points to '\0'); 0 on error */
476 extern char* NcbiIPv6ToString(char* buf, size_t bufsize,
477  const TNCBI_IPv6Addr* addr)
478 {
479  /* sanity */
480  if (!buf || !bufsize)
481  return 0;
482  *buf = '\0';
483  if (!addr)
484  return 0;
485 
486  return x_IPv6ToString(buf, bufsize, addr);
487 }
488 
489 
490 extern char* NcbiAddrToString(char* buf, size_t bufsize,
491  const TNCBI_IPv6Addr* addr)
492 {
493  if (!buf || !bufsize)
494  return 0;
495  *buf = '\0';
496  if (!addr)
497  return 0;
498 
499  if (x_NcbiIsIPv4(addr, 0/*mapped*/)) {
500  unsigned int ipv4 = NcbiIPv6ToIPv4(addr, 0);
501  return x_IPv4ToString(buf, bufsize, &ipv4);
502  }
503  return x_IPv6ToString(buf, bufsize, addr);
504 }
505 
506 
507 extern const char* NcbiAddrToDNS(char* buf, size_t bufsize,
508  const TNCBI_IPv6Addr* addr)
509 {
510  char tmp[sizeof(addr->octet)*4 + 16/*slack*/], *dst = tmp;
511  const struct SIPDNSsfx* sfx;
512  const unsigned char* src;
513  size_t n, len;
514 
515  if (!buf || !bufsize)
516  return 0;
517  *buf = '\0';
518  if (!addr)
519  return 0;
520 
521  len = 0;
522  src = addr->octet + sizeof(addr->octet) - 1;
523  if (x_NcbiIsIPv4(addr, 0/*mapped*/)) {
524  sfx = &kIPv4DNS;
525  for (n = 0; n < sizeof(unsigned int); ++n) {
526  size_t off = (size_t)sprintf(dst, "%d.", *src--);
527  dst += off;
528  len += off;
529  }
530  } else {
531  sfx = &kIPv6DNS;
532  for (n = 0; n < sizeof(addr->octet); ++n) {
533  size_t off = (size_t)sprintf(dst, "%x.%x.", *src & 0xF, *src >> 4);
534  dst += off;
535  len += off;
536  --src;
537  }
538  }
539  if (len + sfx->len <= bufsize) {
540  memcpy(buf, tmp, len);
541  buf += len;
542  memcpy(buf, sfx->sfx + 1, sfx->len);
543  buf += sfx->len;
544  } else
545  buf = 0;
546  return buf;
547 }
548 
549 
550 /* NB: "str" is actually bounded by the ".in-addr.apra" suffix */
551 static const char* x_DNSToIPv4(unsigned int* addr,
552  const char* str, size_t len)
553 {
554  size_t n;
555  unsigned int temp;
556  CORE_DEBUG_ARG(const char* end = str + len;)
557  unsigned char* ptr = (unsigned char*) &temp + sizeof(temp);
558  assert(*end == '.');
559  if (len < 7/*"x.x.x.x"*/ || 15/*xxx.xxx.xxx.xxx*/ < len)
560  return 0/*failure*/;
561  for (n = 0; n < sizeof(temp); ++n) {
562  char s[4];
563  char* e;
564  long d;
565  errno = 0;
566  d = strtol(str, &e, 10); /*NB: "str" may be at "in-addr" safely here*/
567  if (errno || str == e || e - str > 3 || *e != '.'
568  || d < 0 || 255 < d
569  || sprintf(s, "%u", (unsigned int) d) != (int)(e - str)) {
570  return 0/*failure*/;
571  }
572  assert(e <= end);
573  *--ptr = (unsigned char) d;
574  str = ++e;
575  }
576  *addr = temp;
577  return --str;
578 }
579 
580 
581 /* NB: "str" is actually bounded by the ".ip6.arpa" suffix */
582 static const char* x_DNSToIPv6(TNCBI_IPv6Addr* addr,
583  const char* str, size_t len)
584 {
585  static const char xdigits[] = "0123456789abcdef";
586  CORE_DEBUG_ARG(const char* end = str + len;)
587  TNCBI_IPv6Addr temp;
588  unsigned char* dst;
589  size_t n;
590  assert(*end == '.');
591  if (len != 4 * sizeof(addr->octet) - 1)
592  return 0/*failure*/;
593  dst = temp.octet + sizeof(temp.octet) - 1;
594  for (n = 0; n < 2 * sizeof(addr->octet); ++n) {
595  const char* ptr = strchr(xdigits, tolower((unsigned char)(*str++)));
596  unsigned char val;
597  assert(str <= end);
598  if (!ptr || *str++ != '.')
599  return 0/*failure*/;
600  val = (unsigned char)(ptr - xdigits);
601  if (n & 1) {
602  val <<= 4;
603  *dst-- |= val;
604  } else
605  *dst = val;
606  }
607  *addr = temp;
608  return --str;
609 }
610 
611 
613  eNcbiIP_Dot = 1, /* Accept dotted notation */
614  eNcbiIP_Dns = 2 /* Accept DNS notation */
615 };
616 typedef unsigned int TNcbiIP_Form; /* Bitwise OR of ENcbiIP_Form */
617 
618 static const char* s_StringToAddr(TNCBI_IPv6Addr* addr,
619  const char* str, size_t len,
620  TNcbiIP_Form how)
621 {
622  unsigned int ipv4;
623  const char* tmp;
624  size_t n;
625 
626  assert(how);
627  if (!addr)
628  return 0/*failure*/;
629  memset(addr, 0, sizeof(*addr));
630  if (!str || !*str)
631  return 0/*failure*/;
632 
633  if (!len)
634  len = strlen(str);
635  for (n = 0; n < len; ++n) {
636  if (!isspace((unsigned char) str[n]))
637  break;
638  }
639  str += n;
640  len -= n;
641  for (n = 0; n < len; ++n) {
642  if (!str[n] || isspace((unsigned char) str[n]))
643  break;
644  }
645  if (!(len = n))
646  return 0/*failure*/;
647 
648  if (how & eNcbiIP_Dns) {
649  size_t/*bool*/ dns = str[--n] == '.' ? 1/*true*/ : 0/*false*/;
650  if (len > kIPv4DNS.len
651  && strncasecmp(tmp = str + len - (kIPv4DNS.len + dns),
652  kIPv4DNS.sfx, kIPv4DNS.len) == 0) {
653  if (x_DNSToIPv4(&ipv4, str, len - (kIPv4DNS.len + dns)) == tmp) {
654  NcbiIPv4ToIPv6(addr, ipv4, 0);
655  return tmp + (kIPv4DNS.len + dns);
656  } else if (dns)
657  return 0/*failure*/;
658  }
659  if (len > kIPv6DNS.len
660  && strncasecmp(tmp = str + len - (kIPv6DNS.len + dns),
661  kIPv6DNS.sfx, kIPv6DNS.len) == 0) {
662  if (x_DNSToIPv6(addr, str, len - (kIPv6DNS.len + dns)) == tmp)
663  return tmp + (kIPv6DNS.len + dns);
664  else if (dns)
665  return 0/*failure*/;
666  }
667  }
668  if (!(how & eNcbiIP_Dot))
669  return 0/*failure*/;
670 
671  if ((tmp = x_StringToIPv4(&ipv4, str, len)) != 0) {
672  NcbiIPv4ToIPv6(addr, ipv4, 0);
673  return tmp;
674  }
675  return x_StringToIPv6(addr, str, len);
676 }
677 
678 
679 extern const char* NcbiIPToAddr(TNCBI_IPv6Addr* addr,
680  const char* str, size_t len)
681 {
682  const char* rv = s_StringToAddr(addr, str, len, eNcbiIP_Dot);
683  assert(!rv || rv > str);
684  return rv;
685 }
686 
687 
688 extern const char* NcbiStringToAddr(TNCBI_IPv6Addr* addr,
689  const char* str, size_t len)
690 {
691  const char* rv = s_StringToAddr(addr, str, len, eNcbiIP_Dns | eNcbiIP_Dot);
692  assert(!rv || rv > str);
693  return rv;
694 }
695 
696 
697 extern const char* NcbiDNSIPToAddr(TNCBI_IPv6Addr* addr,
698  const char* str, size_t len)
699 {
700  const char* rv = s_StringToAddr(addr, str, len, eNcbiIP_Dns);
701  assert(!rv || rv > str);
702  return rv;
703 }
704 
705 
706 extern int/*bool*/ NcbiIsInIPv6Network(const TNCBI_IPv6Addr* base,
707  unsigned int bits,
708  const TNCBI_IPv6Addr* addr)
709 {
710  size_t n;
711 
712  if (!base || !addr)
713  return 0/*false*/;
714 
715  if (bits > (sizeof(base->octet) << 3))
716  return 0/*false*/;
717 
718  for (n = 0; n < sizeof(addr->octet); ++n) {
719  unsigned char mask;
720  if (!bits) {
721  mask = 0;
722  } else if (8 > bits) {
723  mask = (unsigned char)(~0 << (8 - bits));
724  bits = 0;
725  } else {
726  mask = (unsigned char)(~0);
727  bits -= 8;
728  }
729  if ((addr->octet[n] & mask) ^ base->octet[n])
730  return 0/*false*/;
731  }
732 
733  return 1/*true*/;
734 }
735 
736 
737 extern int/*bool*/ NcbiIPv6Subnet(TNCBI_IPv6Addr* addr, unsigned int bits)
738 {
739  int/*bool*/ zero = 1/*true*/;
740 
741  if (addr) {
742  size_t n;
743  for (n = 0; n < sizeof(addr->octet); ++n) {
744  if (!bits) {
745  addr->octet[n] = 0;
746  } else if (8 > bits) {
747  unsigned char mask = (unsigned char)(~0 << (8 - bits));
748  if (addr->octet[n] &= mask)
749  zero = 0/*false*/;
750  bits = 0;
751  } else {
752  bits -= 8;
753  if (addr->octet[n])
754  zero = 0/*false*/;
755  }
756  }
757  }
758 
759  return !zero;
760 }
761 
762 
763 extern int/*bool*/ NcbiIPv6Suffix(TNCBI_IPv6Addr* addr, unsigned int bits)
764 {
765  int/*bool*/ zero = 1/*true*/;
766 
767  if (addr) {
768  size_t n;
769  if (bits < sizeof(addr->octet) * 8)
770  bits = sizeof(addr->octet) * 8 - bits;
771  else
772  bits = 0;
773  for (n = 0; n < sizeof(addr->octet); ++n) {
774  if (!bits) {
775  if (addr->octet[n])
776  zero = 0/*false*/;
777  } else if (8 > bits) {
778  unsigned char mask = (unsigned char)(~0 << (8 - bits));
779  if (addr->octet[n] &= ~mask)
780  zero = 0/*false*/;
781  bits = 0;
782  } else {
783  bits -= 8;
784  addr->octet[n] = 0;
785  }
786  }
787  }
788 
789  return !zero;
790 }
ncbi::TMaskedQueryRegions mask
static const char ip[]
Definition: des.c:75
static const char * str(char *buf, int n)
Definition: stats.c:84
static char tmp[3200]
Definition: utf8.c:42
#define SOCK_NetToHostLong
Definition: ncbi_socket.h:2096
#define SOCK_NetToHostShort
Definition: ncbi_socket.h:2106
unsigned short SOCK_HostToNetShort(unsigned short value)
See man for the BSDisms, htonl() and htons().
Definition: ncbi_socket.c:8742
int SOCK_ntoa(unsigned int addr, char *buf, size_t bufsize)
Convert IP address to a string in dotted notation.
Definition: ncbi_socket.c:8661
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
char * buf
int i
yy_size_t n
int len
const struct ncbi::grid::netcache::search::fields::SIZE size
#define strncasecmp
#define memcchr
int NcbiIsEmptyIPv6(const TNCBI_IPv6Addr *addr)
Return non-zero if the address is empty (either as IPv6 or IPv4); return zero otherwise.
Definition: ncbi_ipv6.c:80
const char * NcbiStringToIPv6(TNCBI_IPv6Addr *addr, const char *str, size_t len)
Convert into an IPv6 address, the first "len" (or "strlen(str)" if "len" is 0) bytes of "str" from a ...
Definition: ncbi_ipv6.c:365
const char * NcbiDNSIPToAddr(TNCBI_IPv6Addr *addr, const char *str, size_t len)
Convert into an IPv6 address, the first "len" (or "strlen(str)" if "len" is 0) bytes of "str",...
Definition: ncbi_ipv6.c:697
unsigned int TNcbiIP_Form
Definition: ncbi_ipv6.c:616
static char * x_IPv6ToString(char *buf, size_t bufsize, const TNCBI_IPv6Addr *addr)
Definition: ncbi_ipv6.c:384
static char * x_IPv4ToString(char *buf, size_t bufsize, const void *src)
Definition: ncbi_ipv6.c:229
unsigned int NcbiIPv6ToIPv4(const TNCBI_IPv6Addr *addr, size_t pfxlen)
Extract and return a network byte order IPv4 embedded address from an IPv6 address,...
Definition: ncbi_ipv6.c:101
char * NcbiAddrToString(char *buf, size_t bufsize, const TNCBI_IPv6Addr *addr)
Convert an IPv6 address into either a full-quad text IPv4 (for IPv4-mapped IPv6 addresses) or a hex c...
Definition: ncbi_ipv6.c:490
static const char * x_DNSToIPv6(TNCBI_IPv6Addr *addr, const char *str, size_t len)
Definition: ncbi_ipv6.c:582
static int x_NcbiIsIPv4(const TNCBI_IPv6Addr *addr, int compat)
Definition: ncbi_ipv6.c:52
int NcbiIPv6Suffix(TNCBI_IPv6Addr *addr, unsigned int bits)
Retain last "bits" in a given "addr", resetting all remaining bits to 0.
Definition: ncbi_ipv6.c:763
ENcbiIP_Form
Definition: ncbi_ipv6.c:612
@ eNcbiIP_Dns
Definition: ncbi_ipv6.c:614
@ eNcbiIP_Dot
Definition: ncbi_ipv6.c:613
char * NcbiIPv6ToString(char *buf, size_t bufsize, const TNCBI_IPv6Addr *addr)
Convert an IPv6 address into a hex colon-separated text form and store the result in the "buf" of siz...
Definition: ncbi_ipv6.c:476
int NcbiIsIPv4(const TNCBI_IPv6Addr *addr)
Return non-zero(true) if the address is a true IPv4 address (a mapped IPv4 address); return zero(fals...
Definition: ncbi_ipv6.c:89
static const char * x_DNSToIPv4(unsigned int *addr, const char *str, size_t len)
Definition: ncbi_ipv6.c:551
const char * NcbiStringToIPv4(unsigned int *addr, const char *str, size_t len)
Convert into a network byte order IPv4 address, the first "len" (or "strlen(str)" if "len" is 0) byte...
Definition: ncbi_ipv6.c:346
int NcbiIsIPv4Ex(const TNCBI_IPv6Addr *addr, int compat)
Return non-zero(true) if the address is either a mapped IPv4 address or (optionally) an IPv4-compatib...
Definition: ncbi_ipv6.c:95
static const struct SIPDNSsfx kIPv6DNS
Definition: ncbi_ipv6.c:48
char * NcbiIPv4ToString(char *buf, size_t bufsize, unsigned int addr)
Convert a network byte order IPv4 into a full-quad text form and store the result in the "buf" of siz...
Definition: ncbi_ipv6.c:463
int NcbiIPv6Subnet(TNCBI_IPv6Addr *addr, unsigned int bits)
Retain first "bits" in a given "addr", resetting all remaining bits to 0.
Definition: ncbi_ipv6.c:737
const char * NcbiStringToAddr(TNCBI_IPv6Addr *addr, const char *str, size_t len)
Convert into an IPv6 address, the first "len" (or "strlen(str)" if "len" is 0) bytes of "str",...
Definition: ncbi_ipv6.c:688
static const char * x_StringToIPv4(unsigned int *dst, const char *str, size_t len)
Definition: ncbi_ipv6.c:188
int NcbiIsInIPv6Network(const TNCBI_IPv6Addr *base, unsigned int bits, const TNCBI_IPv6Addr *addr)
Return non-zero(true) if "addr" belongs to the network specified as CIDR "base/bits"; return a zero(f...
Definition: ncbi_ipv6.c:706
const char * NcbiAddrToDNS(char *buf, size_t bufsize, const TNCBI_IPv6Addr *addr)
Convert an IPv6 address into either .in-addr.arpa domain (for IPv4-mapped IPv6 addresses) or ....
Definition: ncbi_ipv6.c:507
static const char * x_StringToIPv6(TNCBI_IPv6Addr *addr, const char *str, size_t len)
Definition: ncbi_ipv6.c:240
int NcbiIPv4ToIPv6(TNCBI_IPv6Addr *addr, unsigned int ipv4, size_t pfxlen)
Embed a passed network byte order IPv4 address into an IPv6 address using the specified prefix length...
Definition: ncbi_ipv6.c:142
static const struct SIPDNSsfx kIPv4DNS
Definition: ncbi_ipv6.c:49
const char * NcbiIPToAddr(TNCBI_IPv6Addr *addr, const char *str, size_t len)
Convert into an IPv6 address, the first "len" (or "strlen(str)" if "len" is 0) bytes of "str" from ei...
Definition: ncbi_ipv6.c:679
static const char * s_StringToAddr(TNCBI_IPv6Addr *addr, const char *str, size_t len, TNcbiIP_Form how)
Definition: ncbi_ipv6.c:618
EIPRangeType t
Definition: ncbi_localip.c:101
#define CORE_DEBUG_ARG(arg)
Definition: ncbi_priv.h:139
int isspace(Uchar c)
Definition: ncbictype.hpp:69
int tolower(Uchar c)
Definition: ncbictype.hpp:72
int isxdigit(Uchar c)
Definition: ncbictype.hpp:71
static int bufsize
Definition: pcregrep.c:162
#define assert(x)
Definition: srv_diag.hpp:58
const size_t len
Definition: ncbi_ipv6.c:46
const char * sfx
Definition: ncbi_ipv6.c:45
unsigned char octet[16]
Definition: ncbi_ipv6.h:47
Modified on Wed May 01 14:18:52 2024 by modify_doxy.py rev. 669887