__ipparse.c 1.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. #include <stdlib.h>
  2. #include <ctype.h>
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <arpa/inet.h>
  6. #include "__dns.h"
  7. int __ipparse(void *dest, int family, const char *s0)
  8. {
  9. const char *s = s0;
  10. unsigned char *d = dest;
  11. unsigned long a[16] = { 0 };
  12. char *z;
  13. int i;
  14. if (family == AF_INET6) goto not_v4;
  15. for (i=0; i<4; i++) {
  16. a[i] = strtoul(s, &z, 0);
  17. if (z==s || (*z && *z != '.') || !isdigit(*s)) {
  18. if (family == AF_INET) return -1;
  19. goto not_v4;
  20. }
  21. if (!*z) break;
  22. s=z+1;
  23. }
  24. if (i==4) return -1;
  25. switch (i) {
  26. case 0:
  27. a[1] = a[0] & 0xffffff;
  28. a[0] >>= 24;
  29. case 1:
  30. a[2] = a[1] & 0xffff;
  31. a[1] >>= 16;
  32. case 2:
  33. a[3] = a[2] & 0xff;
  34. a[2] >>= 8;
  35. }
  36. ((struct sockaddr_in *)d)->sin_family = AF_INET;
  37. d = (void *)&((struct sockaddr_in *)d)->sin_addr;
  38. for (i=0; i<4; i++) {
  39. if (a[i] > 255) return -1;
  40. d[i] = a[i];
  41. }
  42. return 0;
  43. not_v4:
  44. s = s0;
  45. ((struct sockaddr_in6 *)d)->sin6_family = AF_INET6;
  46. return inet_pton(AF_INET6, s, (void *)&((struct sockaddr_in6 *)d)->sin6_addr) <= 0 ? -1 : 0;
  47. }