Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat https://www.fefe.de/libowfat/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

114 lines
2.2 KiB

  1. #include "scan.h"
  2. #include "ip4.h"
  3. #include "ip6.h"
  4. /*
  5. * IPv6 addresses are really ugly to parse.
  6. * Syntax: (h = hex digit)
  7. * 1. hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh
  8. * 2. any number of 0000 may be abbreviated as "::", but only once
  9. * 3. The last two words may be written as IPv4 address
  10. */
  11. unsigned int scan_ip6(const char *s,char ip[16])
  12. {
  13. unsigned int i;
  14. unsigned int len=0;
  15. unsigned long u;
  16. char suffix[16];
  17. int prefixlen=0;
  18. int suffixlen=0;
  19. for (i=0; i<16; i++) ip[i]=0;
  20. if ((i=scan_ip4(s,ip+12))) {
  21. for (len=0; len<12; ++len) ip[len]=V4mappedprefix[len];
  22. return i;
  23. }
  24. for (;;) {
  25. if (*s == ':') {
  26. len++;
  27. if (s[1] == ':') { /* Found "::", skip to part 2 */
  28. s+=2;
  29. len++;
  30. break;
  31. }
  32. s++;
  33. }
  34. i = scan_xlong(s,&u);
  35. if (!i) return 0;
  36. if (prefixlen==12 && s[i]=='.') {
  37. /* the last 4 bytes may be written as IPv4 address */
  38. i=scan_ip4(s,ip+12);
  39. if (i)
  40. return i+len;
  41. else
  42. return 0;
  43. }
  44. ip[prefixlen++] = (u >> 8);
  45. ip[prefixlen++] = (u & 255);
  46. s += i; len += i;
  47. if (prefixlen==16)
  48. return len;
  49. }
  50. /* part 2, after "::" */
  51. for (;;) {
  52. if (*s == ':') {
  53. if (suffixlen==0)
  54. break;
  55. s++;
  56. len++;
  57. } else if (suffixlen!=0)
  58. break;
  59. i = scan_xlong(s,&u);
  60. if (!i) {
  61. len--;
  62. break;
  63. }
  64. if (suffixlen+prefixlen<=12 && s[i]=='.') {
  65. int j=scan_ip4(s,suffix+suffixlen);
  66. if (j) {
  67. suffixlen+=4;
  68. len+=j;
  69. break;
  70. } else
  71. prefixlen=12-suffixlen; /* make end-of-loop test true */
  72. }
  73. suffix[suffixlen++] = (u >> 8);
  74. suffix[suffixlen++] = (u & 255);
  75. s += i; len += i;
  76. if (prefixlen+suffixlen==16)
  77. break;
  78. }
  79. for (i=0; i<suffixlen; i++)
  80. ip[16-suffixlen+i] = suffix[i];
  81. return len;
  82. }
  83. static long int fromhex(unsigned char c) {
  84. if (c>='0' && c<='9')
  85. return c-'0';
  86. else if (c>='A' && c<='F')
  87. return c-'A'+10;
  88. else if (c>='a' && c<='f')
  89. return c-'a'+10;
  90. return -1;
  91. }
  92. unsigned int scan_ip6_flat(const char *s,char ip[16])
  93. {
  94. int i;
  95. for (i=0; i<16; i++) {
  96. int tmp;
  97. tmp=fromhex(*s++);
  98. if (tmp<0) return 0;
  99. ip[i]=tmp << 4;
  100. tmp=fromhex(*s++);
  101. if (tmp<0) return 0;
  102. ip[i]+=tmp;
  103. }
  104. return 32;
  105. }