123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- //
- // QNGetAddrInfo.c
- // HappyDNS
- //
- // Created by bailong on 16/7/19.
- // Copyright © 2016年 Qiniu Cloud Storage. All rights reserved.
- //
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <stdlib.h>
- #include <string.h>
- #include "QNGetAddrInfo.h"
- //fast judge domain or ip, not verify ip right.
- static int isIp(const char* domain) {
- size_t l = strlen(domain);
- if (l > 15 || l < 7) {
- return 0;
- }
- for (const char* p = domain; p < domain + l; p++) {
- if ((*p < '0' || *p > '9') && *p != '.') {
- return 0;
- }
- }
- return 1;
- }
- static struct addrinfo* addrinfo_clone(struct addrinfo* addr) {
- struct addrinfo* ai;
- ai = (struct addrinfo*)calloc(sizeof(struct addrinfo) + addr->ai_addrlen, 1);
- if (ai) {
- memcpy(ai, addr, sizeof(struct addrinfo));
- ai->ai_addr = (struct sockaddr*)(ai + 1);
- memcpy(ai->ai_addr, addr->ai_addr, addr->ai_addrlen);
- if (addr->ai_canonname) {
- ai->ai_canonname = strdup(addr->ai_canonname);
- }
- ai->ai_next = NULL;
- }
- return ai;
- }
- static void append_addrinfo(struct addrinfo** head, struct addrinfo* addr) {
- if (*head == NULL) {
- *head = addr;
- return;
- }
- struct addrinfo* ai = *head;
- while (ai->ai_next != NULL) {
- ai = ai->ai_next;
- }
- ai->ai_next = addr;
- }
- void qn_free_ips_ret(qn_ips_ret* ip_list) {
- if (ip_list == NULL) {
- return;
- }
- char** p = ip_list->ips;
- while (*p != NULL) {
- free(*p);
- p++;
- }
- free(ip_list);
- }
- static qn_dns_callback dns_callback = NULL;
- int qn_getaddrinfo(const char* hostname, const char* servname, const struct addrinfo* hints, struct addrinfo** res) {
- if (dns_callback == NULL || hostname == NULL || isIp(hostname)) {
- return getaddrinfo(hostname, servname, hints, res);
- }
- qn_ips_ret* ret = dns_callback(hostname);
- if (ret == NULL) {
- return EAI_NODATA;
- }
- if (ret->ips[0] == NULL) {
- qn_free_ips_ret(ret);
- return EAI_NODATA;
- }
- int i;
- struct addrinfo* ai = NULL;
- struct addrinfo* store = NULL;
- int r = 0;
- for (i = 0; ret->ips[i] != NULL; i++) {
- r = getaddrinfo(ret->ips[i], servname, hints, &ai);
- if (r != 0) {
- break;
- }
- struct addrinfo* temp = ai;
- ai = addrinfo_clone(ai);
- append_addrinfo(&store, ai);
- freeaddrinfo(temp);
- ai = NULL;
- }
- qn_free_ips_ret(ret);
- if (r != 0) {
- qn_freeaddrinfo(store);
- return r;
- }
- *res = store;
- return 0;
- }
- void qn_freeaddrinfo(struct addrinfo* ai) {
- if (ai == NULL) {
- return;
- }
- struct addrinfo* next;
- do {
- next = ai->ai_next;
- if (ai->ai_canonname)
- free(ai->ai_canonname);
- /* no need to free(ai->ai_addr) */
- free(ai);
- ai = next;
- } while (ai);
- }
- void qn_set_dns_callback(qn_dns_callback cb) {
- dns_callback = cb;
- }
- static qn_ip_report_callback ip_report_cb = NULL;
- void qn_set_ip_report_callback(qn_ip_report_callback cb) {
- ip_report_cb = cb;
- }
- void qn_ip_report(const struct addrinfo* info, int code, int time_ms) {
- if (ip_report_cb == NULL || info == NULL) {
- return;
- }
- char ip_str_buf[32] = {0};
- const char* c_ip;
- if (info->ai_family == AF_INET6) {
- c_ip = inet_ntop(info->ai_family, &((struct sockaddr_in6*)(info->ai_addr))->sin6_addr, ip_str_buf, sizeof(ip_str_buf));
- } else {
- c_ip = inet_ntop(info->ai_family, &((struct sockaddr_in*)(info->ai_addr))->sin_addr, ip_str_buf, sizeof(ip_str_buf));
- }
- if (c_ip == NULL) {
- c_ip = "";
- }
- ip_report_cb(c_ip, code, time_ms);
- }
|