⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sres.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
}/** Update config file. * * @retval 1 if DNS server list is different from old one. * @retval 0 when otherwise successful * @retval -1 upon an error */static int sres_update_config(sres_resolver_t *res, int always, time_t now){  sres_config_t *c = NULL;  sres_config_t const *previous;  int retval;  previous = res->res_config;  if (!always && previous && now < res->res_checked)    return 0;  /* Try avoid checking for changes too often. */  res->res_checked = now + SRES_UPDATE_INTERVAL_SECS;     if (!always && previous &&       sres_config_timestamp(previous) == previous->c_modified)    return 0;  c = sres_parse_resolv_conf(res, res->res_options);  if (!c)    return -1;  res->res_config = c;  retval = sres_config_changed_servers(c, previous);  su_home_unref((su_home_t *)previous->c_home);  return retval;}#if HAVE_WIN32/** Number of octets to read from a registry key at a time */#define QUERY_DATALEN         1024#define MAX_DATALEN           65535/** * Uses IP Helper IP to get DNS servers list. */static int sres_parse_win32_ip(sres_config_t *c){  int ret = -1;#if HAVE_IPHLPAPI_H  DWORD dw;  su_home_t *home = c->c_home;  ULONG size = sizeof(FIXED_INFO);  do {    FIXED_INFO *info = (FIXED_INFO *)su_alloc(home, size);    dw = GetNetworkParams(info, &size);    if (dw == ERROR_SUCCESS) {      IP_ADDR_STRING* addr = &info->DnsServerList;      for (; addr; addr = addr->Next) {       SU_DEBUG_3(("Adding nameserver: %s\n", addr->IpAddress.String));       sres_parse_nameserver(c, addr->IpAddress.String);      }      ret = 0;    }    su_free(home, info);  } while (dw == ERROR_BUFFER_OVERFLOW);#endif  return ret;}/** * Parses name servers listed in registry key 'key+lpValueName'. The * key is expected to contain a whitespace separate list of * name server IP addresses. * * @return number of server addresses added */ static int sres_parse_win32_reg_parse_dnsserver(sres_config_t *c, HKEY key, LPCTSTR lpValueName){  su_home_t *home = c->c_home;  su_strlst_t *reg_dns_list;  BYTE *name_servers = su_alloc(home, QUERY_DATALEN);  DWORD name_servers_length = QUERY_DATALEN;  int ret, servers_added = 0;  /* get name servers and ... */  while((ret = RegQueryValueEx(key, 			       lpValueName, 			       NULL, NULL, 			       name_servers, 			       &name_servers_length)) == ERROR_MORE_DATA) {    name_servers_length += QUERY_DATALEN;    /* sanity check, upper limit for memallocs */    if (name_servers_length > MAX_DATALEN) break;    name_servers = su_realloc(home, name_servers, name_servers_length);    if (name_servers == NULL) {      ret = ERROR_BUFFER_OVERFLOW;      break;    }  }  /* if reading the key was succesful, continue */  if (ret == ERROR_SUCCESS) {    if (name_servers[0]){      int i;      /* add to list */      reg_dns_list = su_strlst_split(home, (char *)name_servers, " ");	          for(i = 0 ; i < su_strlst_len(reg_dns_list); i++) {	const char *item = su_strlst_item(reg_dns_list, i);	SU_DEBUG_3(("Adding nameserver: %s (key=%s)\n", item, (char*)lpValueName));	sres_parse_nameserver(c, item);	++servers_added;      }	          su_strlst_destroy(reg_dns_list);    }  }  su_free(home, name_servers);  return servers_added;}/** * Discover system nameservers from Windows registry. * * Refs: *  - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/regqueryvalueex.asp *  - http://support.microsoft.com/default.aspx?scid=kb;en-us;120642 *  - http://support.microsoft.com/kb/314053/EN-US/ *  - IP Helper API (possibly better way than current registry-based impl.) *    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iphlp/iphlp/ip_helper_start_page.asp */static int sres_parse_win32_reg(sres_config_t *c){  int ret = -1;#define MAX_KEY_LEN           255#define MAX_VALUE_NAME_LEN    16383  su_home_t *home = c->c_home;  HKEY key_handle;  #if 0  HKEY interface_key_handle;    FILETIME ftime;  int index, i;#endif  int found = 0;  char *interface_guid = su_alloc(home, MAX_VALUE_NAME_LEN);#if 0#if __MINGW32__  DWORD guid_size = QUERY_DATALEN;#else  int guid_size = MAX_VALUE_NAME_LEN;#endif  /* step: find interface specific nameservers    * - this is currently disabled 2006/Jun (the current check might insert   *   multiple unnecessary nameservers to the search list)    */  /* open the 'Interfaces' registry Key */  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 		   "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces", 		   0, KEY_READ, &key_handle)) {    SU_DEBUG_2(("RegOpenKeyEx failed\n"));  } else {    index = 0;    /* for each interface listed ... */    while (RegEnumKeyEx(key_handle, index,			interface_guid, &guid_size,			NULL,NULL,0,&ftime) == ERROR_SUCCESS){      if (RegOpenKeyEx(key_handle, interface_guid,		       0, KEY_READ, 		       &interface_key_handle) == ERROR_SUCCESS) {	/* note: 'NameServer' is preferred over 'DhcpNameServer' */	found += sres_parse_win32_reg_parse_dnsserver(c, interface_key_handle, "NameServer");	if (found == 0) 	  found += sres_parse_win32_reg_parse_dnsserver(c, interface_key_handle, "DhcpNameServer");	RegCloseKey(interface_key_handle);      } else{	SU_DEBUG_2(("interface RegOpenKeyEx failed\n"));      }      index++;      guid_size = 64;    }    RegCloseKey(key_handle);  }#endif /* #if 0: interface-specific nameservers */  /* step: if no interface-specific nameservers are found,    *       check for system-wide nameservers */  if (found == 0) {    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 		     "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 		     0, KEY_READ, &key_handle)) {      SU_DEBUG_2(("RegOpenKeyEx failed (2)\n"));    } else {      found += sres_parse_win32_reg_parse_dnsserver(c, key_handle, "NameServer");      if (found == 0) 	found += sres_parse_win32_reg_parse_dnsserver(c, key_handle, "DhcpNameServer");      RegCloseKey(key_handle);    }  }  SU_DEBUG_3(("Total of %d name servers found from win32 registry.\n", found));  /* return success if servers found */  if (found) ret = 0;  su_free(home, interface_guid);  return ret;}#endif /* HAVE_WIN32 *//** Parse /etc/resolv.conf file. * * @retval #sres_config_t structure when successful  * @retval NULL upon an error * * @todo The resolv.conf directives @b sortlist and most of the options  *       are currently ignored. */static sres_config_t *sres_parse_resolv_conf(sres_resolver_t *res,				      char const **options){  sres_config_t *c = su_home_new(sizeof *c);  if (c) {    FILE *f;    int i;        f = fopen(c->c_filename = res->res_cnffile, "r");    sres_parse_config(c, f);    if (f)      fclose(f);#if HAVE_WIN32        /* note: no 127.0.0.1 on win32 systems */    /* on win32, query the registry for nameservers */    if (sres_parse_win32_ip(c) == 0 || sres_parse_win32_reg(c) == 0)      /* success */;    else      /* now what? */;#else    /* Use local nameserver by default */    if (c->c_nameservers[0] == NULL)      sres_parse_nameserver(c, "127.0.0.1");#endif          for (i = 0; c->c_nameservers[i] && i < SRES_MAX_NAMESERVERS; i++) {      struct sockaddr_in *sin = (void *)c->c_nameservers[i]->ns_addr;      sin->sin_port = htons(c->c_port);    }    sres_parse_options(c, getenv("RES_OPTIONS"));        if (options)      for (i = 0; options[i]; i++)	sres_parse_options(c, options[i]);    sres_parse_options(c, getenv("SRES_OPTIONS"));    su_home_threadsafe(c->c_home);  }  return c;}uint16_t _sres_default_port = 53;/** Parse config file.  * * @return Number of search domains, if successful. * @retval -1 upon an error (never happens). */staticint sres_parse_config(sres_config_t *c, FILE *f){  su_home_t *home = c->c_home;  int line;  char const *localdomain;  char *search = NULL, *domain = NULL;  char buf[1025];  int i = 0;  localdomain = getenv("LOCALDOMAIN");  /* Default values */  c->c_opt.ndots = 1;  c->c_opt.check_names = 1;  c->c_opt.timeout = SRES_RETRY_INTERVAL;  c->c_opt.attempts = SRES_MAX_RETRY_COUNT;  c->c_port = _sres_default_port;  if (f != NULL) {      for (line = 1; fgets(buf, sizeof(buf), f); line++) {      size_t len;      char *value, *b;      /* Skip whitespace at the beginning ...*/      b = buf + strspn(buf, " \t");      /* ... and at the end of line */      for (len = strlen(b); len > 0 && strchr(" \t\r\n", b[len - 1]); len--)	;      if (len == 0 || b[0] == '#') 	/* Empty line or comment */	continue;      b[len] = '\0';      len = strcspn(b, " \t");      value = b + len; value += strspn(value, " \t");#define MATCH(token) (len == strlen(token) && strncasecmp(token, b, len) == 0)      if (MATCH("nameserver")) {	if (sres_parse_nameserver(c, value) < 0)	  return -1;      }      else if (MATCH("domain")) {	if (localdomain)	/* LOCALDOMAIN overrides */	  continue;	if (search)	  su_free(home, search), search = NULL;	if (domain)	  su_free(home, domain), domain = NULL;	domain = su_strdup(home, value);	if (!domain)	  return -1;      }      else if (MATCH("search")) {	if (localdomain)	/* LOCALDOMAIN overrides */	  continue;	if (search) su_free(home, search), search = NULL;	if (domain) su_free(home, domain), domain = NULL;	search = su_strdup(home, value);	if (!search)	  return -1;      }      else if (MATCH("port")) {	unsigned long port = strtoul(value, NULL, 10);	if (port < 65536)	  c->c_port = port;      }      else if (MATCH("options")) {	sres_parse_options(c, value);      }    }  }  if (f)    c->c_modified = sres_config_timestamp(c);  if (localdomain)    c->c_search[0] = localdomain;  else if (domain)    c->c_search[0] = domain;  else if (search) {    for (i = 0; search[0] && i < SRES_MAX_SEARCH; i++) {      c->c_search[i] = search;      search += strcspn(search, " \t");      if (*search) {	*search++ = '\0';	search += strspn(search, " \t");      }    }  }  return i;}#if DOXYGEN_ONLY/**@ingroup sresolv_env * * Environment variable containing options for Sofia resolver. The options * recognized by Sofia resolver are as follows: * - @b debug           turn on debugging (no effect) * - @b ndots:<i>n</i>  when searching, try first to query name as absolute *                      domain if it contains at least <i>n</i> dots * - @b timeout:<i>secs</i> timeout in seconds * - @b attempts:<i>n</i> fail after <i>n</i> retries * - @b rotate          use round robin selection of nameservers * - @b no-check-names  do not check names for invalid characters * - @b inet6           (no effect)  * - @b ip6-dotint      IPv6 addresses are resolved using suffix ".ip6.int" *                      instead of the standard ".ip6.arpa" suffix * - @b ip6-bytestring  (no effect) * The following option is a Sofia-specific extension: * - @b no-edns0        do not try to use EDNS0 extension (@RFC2671) * * The same options can be listed in @b options directive in resolv.conf, or * in #RES_OPTIONS environment variable. Note that options given in * #SRES_OPTIONS override those specified in #RES_OPTIONS which in turn * override options specified in the @b options directive of resolve.conf. * * The meaning of an option can be reversed with prefix "no-". * * @sa Manual page for resolv.conf, #RES_OPTIONS. */extern SRES_OPTIONS;/**@ingroup sresolv_env * * Environment variable containing resolver options. This environment * variable is also used by standard BIND resolver. * * @sa Manual page for resolv.conf, #SRES_OPTIONS. */extern RES_OPTIONS;/**@ingroup sresolv_env * * Environment variable containing search domain. This environment * variable is also used by standard BIND resolver. * * @sa Manual page for resolv.conf, #RES_OPTIONS, #SRES_OPTIONS. */extern LOCALDOMAIN;#endif/* Parse options line or #SRES_OPTIONS or #RES_OPTIONS environment variable. */static int sres_parse_options(sres_config_t *c, char const *value){  if (!value)    return -1;  while (value[0]) {    char const *b;    size_t len, extra = 0;    unsigned long n = 0;    b = value; len = strcspn(value, " \t:");    value += len;    if (value[0] == ':') {      len++;      n = strtoul(++value, NULL, 10);      value += extra = strcspn(value, " \t");    }    if (*value)      value += strspn(value, " \t");    if (n > 65536) {      SU_DEBUG_3(("sres: %s: invalid %*.0s\n", c->c_filename,		  (int)(len + extra), b));      continue;    }    /* Documented by BIND9 resolv.conf */    if (MATCH("no-debug")) c->c_opt.debug = 0;    else if (MATCH("debug")) c->c_opt.debug = 1;    else if (MATCH("ndots:")) c->c_opt.ndots = n;    else if (MATCH("timeout:")) c->c_opt.timeout = n;    else if (MATCH("attempts:")) c->c_opt.attempts = n;    else if (MATCH("no-rotate")) c->c_opt.rotate = 0;    else if (MATCH("rotate")) c->c_opt.rotate = 1;    else if (MATCH("no-check-names")) c->c_opt.check_names = 0;    else if (MATCH("check-names")) c->c_opt.check_names = 1;    else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -