QNResolvUtil.m 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. //
  2. // QNResolvUtil.m
  3. // HappyDNS
  4. //
  5. // Created by bailong on 16/5/28.
  6. // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. #include <arpa/inet.h>
  10. #include <resolv.h>
  11. #include <string.h>
  12. #include <netdb.h>
  13. #include <netinet/in.h>
  14. #include <netinet/in.h>
  15. #include <netinet/tcp.h>
  16. #include <unistd.h>
  17. #import "QNIP.h"
  18. #if __IPHONE_OS_VERSION_MIN_REQUIRED
  19. #import <MobileCoreServices/MobileCoreServices.h>
  20. #import <UIKit/UIKit.h>
  21. #endif
  22. BOOL isV6(NSString *address) {
  23. return strchr(address.UTF8String, ':') != NULL;
  24. }
  25. int setup_dns_server(void *_res_state, NSString *dns_server, NSUInteger timeout) {
  26. res_state res = (res_state)_res_state;
  27. int r = res_ninit(res);
  28. if (r != 0) {
  29. return r;
  30. }
  31. res->retrans = (int)timeout;
  32. res->retry = 1;
  33. if (dns_server == nil) {
  34. return 0;
  35. }
  36. res->options |= RES_IGNTC;
  37. union res_sockaddr_union server = {0};
  38. struct addrinfo hints = {0}, *ai = NULL;
  39. hints.ai_family = AF_UNSPEC;
  40. hints.ai_socktype = SOCK_STREAM;
  41. int ret = getaddrinfo(dns_server.UTF8String, "53", &hints, &ai);
  42. if (ret != 0) {
  43. return ret;
  44. }
  45. int family = ai->ai_family;
  46. if (family == AF_INET6) {
  47. ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = htons(53);
  48. server.sin6 = *((struct sockaddr_in6 *)ai->ai_addr);
  49. } else {
  50. server.sin = *((struct sockaddr_in *)ai->ai_addr);
  51. }
  52. if (![QNIP isIpV6FullySupported] && family == AF_INET) {
  53. if ([QNIP isV6]) {
  54. freeaddrinfo(ai);
  55. ai = NULL;
  56. bzero(&hints, 0);
  57. hints.ai_family = AF_UNSPEC;
  58. hints.ai_socktype = SOCK_STREAM;
  59. char buf[64] = {0};
  60. qn_nat64(buf, sizeof(buf), (uint32_t)server.sin.sin_addr.s_addr);
  61. int ret = getaddrinfo(buf, "53", &hints, &ai);
  62. if (ret != 0) {
  63. return -1;
  64. }
  65. ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = htons(53);
  66. server.sin6 = *((struct sockaddr_in6 *)ai->ai_addr);
  67. }
  68. }
  69. freeaddrinfo(ai);
  70. res_setservers(res, &server, 1);
  71. return 0;
  72. }