inet_pton.c 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #include <sys/socket.h>
  2. #include <netdb.h>
  3. #include <arpa/inet.h>
  4. #include <stdlib.h>
  5. #include <ctype.h>
  6. #include <errno.h>
  7. #include <string.h>
  8. static int hexval(unsigned c)
  9. {
  10. if (c-'0'<10) return c-'0';
  11. c |= 32;
  12. if (c-'a'<6) return c-'a'+10;
  13. return -1;
  14. }
  15. int inet_pton(int af, const char *restrict s, void *restrict a0)
  16. {
  17. uint16_t ip[8];
  18. unsigned char *a = a0;
  19. const char *z;
  20. unsigned long x;
  21. int i, j, v, d, brk=-1, need_v4=0;
  22. /* Reimplement this because inet_pton cannot accept special v4 forms */
  23. if (af==AF_INET) {
  24. for (i=0; i<4 && *s; i++) {
  25. a[i] = x = strtoul(s, (char **)&z, 10);
  26. if (!isdigit(*s) || z==s || (*z && *z != '.') || x>255)
  27. return 0;
  28. s=z+1;
  29. }
  30. return 1;
  31. } else if (af!=AF_INET6) {
  32. errno = EAFNOSUPPORT;
  33. return -1;
  34. }
  35. if (s[0]==':' && s[1]==':') s++;
  36. for (i=0; ; i++, s+=j+1) {
  37. if (s[0]==':' && brk<0) {
  38. brk=i;
  39. j=0;
  40. ip[i]=0;
  41. if (!s[1]) break;
  42. continue;
  43. }
  44. if (hexval(s[0])<0) return -1;
  45. while (s[0]=='0' && s[1]=='0') s++;
  46. for (v=j=0; j<5 && (d=hexval(s[j]))>=0; j++)
  47. v=16*v+d;
  48. if (v > 65535) return -1;
  49. ip[i] = v;
  50. if (!s[j]) {
  51. if (brk<0 && i!=7) return -1;
  52. break;
  53. }
  54. if (i<7) {
  55. if (s[j]==':') continue;
  56. if (s[j]!='.') return -1;
  57. need_v4=1;
  58. i++;
  59. break;
  60. }
  61. return -1;
  62. }
  63. if (brk>=0) {
  64. memmove(ip+brk+7-i, ip+brk, 2*(i+1-brk));
  65. for (j=0; j<7-i; j++) ip[brk+j] = 0;
  66. }
  67. for (j=0; j<8; j++) {
  68. *a++ = ip[j]>>8;
  69. *a++ = ip[j];
  70. }
  71. if (need_v4 &&inet_pton(AF_INET, (void *)s, a-4) <= 0) return -1;
  72. return 1;
  73. }