ipv6spec.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*====================================================================*
  2. *
  3. * size_t ipv6spec (char const * string, byte memory []);
  4. *
  5. * memory.h
  6. *
  7. * encode a 16-byte memory region with the binary equivalent of an
  8. * ipv6 address string; ipv6 addresses are defined as 8 16-bit hex
  9. * numbers separated with colons; two consecutive colons represent
  10. * one or more 0000 fields;
  11. *
  12. * Motley Tools by Charles Maier;
  13. * Copyright (c) 2001-2006 by Charles Maier Associates;
  14. * Licensed under the Internet Software Consortium License;
  15. *
  16. *--------------------------------------------------------------------*/
  17. #ifndef IPV6SPEC_SOURCE
  18. #define IPV6SPEC_SOURCE
  19. #include <memory.h>
  20. #include <ctype.h>
  21. #include <errno.h>
  22. #include "../tools/memory.h"
  23. #include "../tools/number.h"
  24. #include "../tools/error.h"
  25. size_t ipv6spec (char const * string, void * memory)
  26. {
  27. char const * number = string;
  28. byte * origin = (byte *)(memory);
  29. byte * offset = (byte *)(memory);
  30. byte * extent = offset + IPv6_LEN;
  31. byte * marker = offset + IPv6_LEN;
  32. unsigned radix = RADIX_HEX;
  33. unsigned digit = 0;
  34. while ((*number) && (offset < extent))
  35. {
  36. uint32_t value = 0;
  37. if (offset > origin)
  38. {
  39. if (*number == HEX_EXTENDER)
  40. {
  41. number++;
  42. }
  43. if (*number == HEX_EXTENDER)
  44. {
  45. marker = offset;
  46. }
  47. }
  48. while ((digit = todigit (*number)) < radix)
  49. {
  50. value *= radix;
  51. value += digit;
  52. if (value >> 16)
  53. {
  54. error (1, ERANGE, "IPv6 '%s' field %d exceeds 16 bits", string, 1 + ((unsigned)(offset - origin) >> 1));
  55. }
  56. number++;
  57. }
  58. *offset++ = (byte)(value >> 8);
  59. *offset++ = (byte)(value >> 0);
  60. }
  61. #if defined (WIN32)
  62. while (isspace (*number))
  63. {
  64. number++;
  65. }
  66. #endif
  67. if (*number)
  68. {
  69. error (1, EINVAL, "IPv6 '%s' includes trash '%s'", string, number);
  70. }
  71. if (offset < extent)
  72. {
  73. while (offset > marker)
  74. {
  75. *--extent = *--offset;
  76. }
  77. while (extent > offset)
  78. {
  79. *--extent = 0;
  80. }
  81. }
  82. if (offset < marker)
  83. {
  84. error (1, EINVAL, "IPv6 '%s' has only %d fields", string, (unsigned)(offset - origin) >> 1);
  85. }
  86. return (offset - origin);
  87. }
  88. /*====================================================================*
  89. * demo/test program;
  90. *--------------------------------------------------------------------*/
  91. #if 0
  92. #include <stdio.h>
  93. char const * program_name = "ipv6spec";
  94. int main (int argc, char * argv [])
  95. {
  96. byte memory [16];
  97. char string [48];
  98. while (*++argv)
  99. {
  100. ipv6spec (* argv, memory);
  101. hexdecode (memory, sizeof (memory), string, sizeof (string));
  102. printf ("%s %s\n", string, * argv);
  103. }
  104. return (0);
  105. }
  106. #endif
  107. /*====================================================================*
  108. *
  109. *--------------------------------------------------------------------*/
  110. #endif