📄 ares_init.c
字号:
/* Copyright 1998 by the Massachusetts Institute of Technology. * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" * without express or implied warranty. */#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <time.h>#include <assert.h>#ifndef WIN32#include <sys/time.h>#include <sys/param.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/socket.h>#ifndef __CYGWIN__# include <arpa/nameser.h>#endif#include <unistd.h>#include <errno.h>#include <netdb.h>#else#include <Winsock2.h>#include <iphlpapi.h>#include <io.h>#include <Windns.h>#endif#include "ares.h"#include "ares_private.h"#if defined(__APPLE__) || defined(__MACH__)#define __CF_USE_FRAMEWORK_INCLUDES__#include <SystemConfiguration/SystemConfiguration.h>#endifstatic int init_by_options(ares_channel channel, struct ares_options *options, int optmask);static int init_by_environment(ares_channel channel);static int init_by_resolv_conf(ares_channel channel);static int init_by_defaults(ares_channel channel);static int config_domain(ares_channel channel, char *str);static int config_lookup(ares_channel channel, const char *str);static int config_nameserver(struct server_state **servers, int *nservers, const char *str);static int config_sortlist(struct apattern **sortlist, int *nsort, const char *str);static int set_search(ares_channel channel, const char *str);static int set_options(ares_channel channel, const char *str);static char *try_config(char *s, char *opt);static const char *try_option(const char *p, const char *q, const char *opt);static int ip_addr(const char *s, int len, struct in_addr *addr);static void natural_mask(struct apattern *pat);static int find_server(struct server_state *servers, int nservers, struct in_addr addr);static int get_physical_address(char *physicalAddr, int physicalAddrBufSz, int* physAddrLen, struct in_addr addr);static int inet_pton4(const char *src, u_char *dst);#ifdef USE_IPV6static int inet_pton6(const char *src, u_char *dst);#endif #ifdef WIN32char w32hostspath[256];#endifint ares_capabilities(int capmask){#ifdef USE_IPV6 static int ares_caps = ARES_CAP_IPV6;#else static int ares_caps = 0;#endif return (capmask & ares_caps);}int ares_init(ares_channel *channelptr){ return ares_init_options_with_socket_function(channelptr, NULL, 0, NULL);}int ares_init_with_socket_function(ares_channel *channelptr, socket_function_ptr socketFunc){ return ares_init_options_with_socket_function(channelptr, NULL, 0, socketFunc);}int ares_init_options(ares_channel *channelptr, struct ares_options *options, int optmask){ return ares_init_options_with_socket_function(channelptr, options, optmask, NULL);}int ares_init_options_with_socket_function(ares_channel *channelptr, struct ares_options *options, int optmask, socket_function_ptr socketFunc){ ares_channel channel; int i, status; struct server_state *server;#ifdef WIN32 { HKEY hKey; char hostpath[256]; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { DWORD dwSize = sizeof(hostpath); if(RegQueryValueEx(hKey, TEXT("DatabasePath"), 0, 0, (LPBYTE)&hostpath, &dwSize) == ERROR_SUCCESS) { hostpath[dwSize] = '\0';#if defined(UNDER_CE) ZeroMemory(hostpath,strlen(hostpath)*sizeof(TCHAR));#else ExpandEnvironmentStrings(hostpath, w32hostspath, sizeof(w32hostspath));#endif if(strlen(w32hostspath) < sizeof(w32hostspath) - 6) { strcat(w32hostspath, "\\hosts"); } } RegCloseKey(hKey); } }#endif // struct timeval tv; channel = malloc(sizeof(struct ares_channeldata)); if (!channel) return ARES_ENOMEM; /* Set everything to distinguished values so we know they haven't * been set yet. */ channel->socket_function = socketFunc; channel->flags = -1; channel->timeout = -1; channel->tries = -1; channel->ndots = -1; channel->udp_port = -1; channel->tcp_port = -1; channel->nservers = -1; channel->ndomains = -1; channel->nsort = -1; channel->lookups = NULL; /* Initialize configuration by each of the four sources, from highest * precedence to lowest. */ status = init_by_options(channel, options, optmask); if (status == ARES_SUCCESS) status = init_by_environment(channel); if (status == ARES_SUCCESS) status = init_by_resolv_conf(channel); if (status == ARES_SUCCESS) status = init_by_defaults(channel); if (status != ARES_SUCCESS) { /* Something failed; clean up memory we may have allocated. */ if (channel->nservers != -1) free(channel->servers); if (channel->ndomains != -1) { for (i = 0; i < channel->ndomains; i++) free(channel->domains[i]); free(channel->domains); } if (channel->nsort != -1) free(channel->sortlist); free(channel->lookups); free(channel); return status; } /* Trim to one server if ARES_FLAG_PRIMARY is set. */ if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1) channel->nservers = 1; /* Initialize server states. */ for (i = 0; i < channel->nservers; i++) { server = &channel->servers[i]; server->udp_socket = -1; server->tcp_socket = -1; server->tcp_lenbuf_pos = 0; server->tcp_buffer = NULL; server->qhead = NULL; server->qtail = NULL; } /* Choose a somewhat random query ID. The main point is to avoid * collisions with stale queries. An attacker trying to spoof a DNS * answer also has to guess the query ID, but it's only a 16-bit * field, so there's not much to be done about that. */// gettimeofday(&tv, NULL);// channel->next_id = (tv.tv_sec ^ tv.tv_usec ^ getpid()) & 0xffff; { static int cjNextID=1; channel->next_id = cjNextID++; } channel->queries = NULL; *channelptr = channel; return ARES_SUCCESS;}static int init_by_options(ares_channel channel, struct ares_options *options, int optmask){ int i; /* Easy stuff. */ if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1) channel->flags = options->flags; if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1) channel->timeout = options->timeout; if ((optmask & ARES_OPT_TRIES) && channel->tries == -1) channel->tries = options->tries; if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1) channel->ndots = options->ndots; if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1) channel->udp_port = options->udp_port; if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1) channel->tcp_port = options->tcp_port; /* Copy the servers, if given. */ if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1) { channel->servers = malloc(options->nservers * sizeof(struct server_state)); if (!channel->servers && options->nservers != 0) return ARES_ENOMEM; memset(channel->servers, '\0', options->nservers * sizeof(struct server_state)); for (i = 0; i < options->nservers; i++) {#ifdef USE_IPV6 channel->servers[i].family = options->servers[i].family; if (options->servers[i].family == AF_INET6) { channel->servers[i].addr6 = options->servers[i].addr6; } else { channel->servers[i].addr = options->servers[i].addr; }#else channel->servers[i].addr = options->servers[i];#endif channel->nservers = options->nservers; } } /* Copy the domains, if given. Keep channel->ndomains consistent so * we can clean up in case of error. */ if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1) { channel->domains = malloc(options->ndomains * sizeof(char *)); if (!channel->domains && options->ndomains != 0) return ARES_ENOMEM; for (i = 0; i < options->ndomains; i++) { channel->ndomains = i; channel->domains[i] = strdup(options->domains[i]); if (!channel->domains[i]) return ARES_ENOMEM; } channel->ndomains = options->ndomains; } /* Set lookups, if given. */ if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups) { channel->lookups = strdup(options->lookups); if (!channel->lookups) return ARES_ENOMEM; } return ARES_SUCCESS;}static int init_by_environment(ares_channel channel){ const char *localdomain, *res_options; int status;#if defined(UNDER_CE) localdomain = NULL;#else localdomain = getenv("LOCALDOMAIN");#endif if (localdomain && channel->ndomains == -1) { status = set_search(channel, localdomain); if (status != ARES_SUCCESS) return status; }#if defined(UNDER_CE) res_options = NULL;#else res_options = getenv("RES_OPTIONS");#endif if (res_options) { status = set_options(channel, res_options); if (status != ARES_SUCCESS) return status; } return ARES_SUCCESS;}static int init_by_resolv_conf(ares_channel channel){ FILE *fp; char *line = NULL, *p; int linesize, status, nservers = 0, nsort = 0; struct server_state *servers = NULL; struct apattern *sortlist = NULL; fp = fopen(PATH_RESOLV_CONF, "r");#if defined(UNDER_CE) errno = ENOENT;#endif if (!fp) return (errno == ENOENT) ? ARES_SUCCESS : ARES_EFILE; while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { if ((p = try_config(line, "domain")) && channel->ndomains == -1) status = config_domain(channel, p); else if ((p = try_config(line, "lookup")) && !channel->lookups) status = config_lookup(channel, p); else if ((p = try_config(line, "search")) && channel->ndomains == -1) status = set_search(channel, p); else if ((p = try_config(line, "nameserver")) && channel->nservers == -1) status = config_nameserver(&servers, &nservers, p); else if ((p = try_config(line, "sortlist")) && channel->nsort == -1) status = config_sortlist(&sortlist, &nsort, p); else if ((p = try_config(line, "options"))) status = set_options(channel, p); else status = ARES_SUCCESS; if (status != ARES_SUCCESS) break; } free(line); fclose(fp); /* Handle errors. */ if (status != ARES_EOF) { free(servers); free(sortlist); return status; } /* If we got any name server entries, fill them in. */ if (servers) { channel->servers = servers; channel->nservers = nservers; } /* If we got any sortlist entries, fill them in. */ if (sortlist) { channel->sortlist = sortlist; channel->nsort = nsort; } return ARES_SUCCESS;}#if defined(__APPLE__) || defined(__MACH__)static void init_by_defaults_systemconfiguration(ares_channel channel)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -