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

📄 sres.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
      }      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;}static int sres_parse_options(sres_config_t *c, char const *value){  if (!value)    return -1;  while (value[0]) {    char const *b;    int 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 %*.s\n", c->c_filename, 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 if (MATCH("no-inet6")) c->c_opt.ip6int = 0;    else if (MATCH("inet6")) c->c_opt.inet6 = 1;    else if (MATCH("no-ip6-dotint")) c->c_opt.ip6int = 0;    else if (MATCH("ip6-dotint")) c->c_opt.ip6int = 1;    else if (MATCH("no-ip6-bytestring")) c->c_opt.ip6bytestring = 0;    else if (MATCH("ip6-bytestring")) c->c_opt.ip6bytestring = 1;    /* Sofia-specific extensions: */    else if (MATCH("no-edns0")) c->c_opt.edns = edns_not_supported;    else if (MATCH("edns0")) c->c_opt.edns = edns0_configured;    else {      SU_DEBUG_3(("sres: %s: unknown option %*.s\n", c->c_filename, len + extra, b));    }  }  return 0;}staticint sres_parse_nameserver(sres_config_t *c, char const *server){  sres_nameserver_t *ns;  struct sockaddr *sa;  int err, i;  for (i = 0; i < SRES_MAX_NAMESERVERS; i++)    if (c->c_nameservers[i] == NULL)      break;  if (i >= SRES_MAX_NAMESERVERS)    return 0 /* Silently discard extra nameservers */;  ns = su_zalloc(c->c_home, (sizeof *ns) + strlen(server) + 1);  if (!ns)    return -1;  sa = (void *)ns->ns_addr;#if HAVE_SIN6  if (strchr(server, ':')) {    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;    memset(sa, 0, ns->ns_addrlen = sizeof *sin6);    err = inet_pton(sa->sa_family = AF_INET6, server, &sin6->sin6_addr);  }   else #endif    {      struct sockaddr_in *sin = (struct sockaddr_in *)sa;      memset(sa, 0, ns->ns_addrlen = sizeof *sin);      err = inet_pton(sa->sa_family = AF_INET, server, &sin->sin_addr);    }  if (err <= 0) {    SU_DEBUG_3(("sres: nameserver %s: invalid address\n", server));    su_free(c->c_home, ns);    return 0;  }#if HAVE_SA_LEN  sa->sa_len = ns->ns_addrlen;#endif  c->c_nameservers[i] = ns;  return 1;}/** Get current timestamp of resolv.conf file */statictime_t sres_config_timestamp(sres_config_t const *c){#ifndef _WIN32  struct stat st;  if (stat(c->c_filename, &st) == 0)    return st.st_mtime;  /** @return If the resolv.conf file does not exists, return old timestamp. */  return c->c_modified;#else  /** On WIN32, return always different timestamp */  return c->c_modified + SRES_UPDATE_INTERVAL_SECS;#endif}/* ---------------------------------------------------------------------- *//** Check if the new configuration has different servers than the old */static int sres_config_changed_servers(sres_config_t const *new_c, 				sres_config_t const *old_c){  int i;  sres_nameserver_t const *new_ns, *old_ns;  if (old_c == NULL)    return 1;  for (i = 0; i < SRES_MAX_NAMESERVERS; i++) {    new_ns = new_c->c_nameservers[i];    old_ns = old_c->c_nameservers[i];    if (!new_ns != !old_ns)      return 1;    if (!new_ns)      return 0;    if (new_ns->ns_addrlen != old_ns->ns_addrlen)      return 1;    if (memcmp(new_ns->ns_addr, old_ns->ns_addr, new_ns->ns_addrlen))      return 1;  }  return 0;}/** Allocate new servers structure */staticsres_server_t **sres_servers_new(sres_resolver_t *res,				 sres_config_t const *c){  sres_server_t **servers, *dns;  sres_nameserver_t *ns;  int N, i;  size_t size;  for (N = 0; c->c_nameservers[N] && N < SRES_MAX_NAMESERVERS; N++)    ;  size = (N + 1) * (sizeof *servers) + N * (sizeof **servers);  servers = su_zalloc(res->res_home, size); if (!servers) return servers;  dns = (void *)(servers + N + 1);  for (i = 0; i < N; i++) {    dns->dns_socket = -1;    ns = c->c_nameservers[i];    memcpy(dns->dns_addr, ns->ns_addr, dns->dns_addrlen = ns->ns_addrlen);    inet_ntop(dns->dns_addr->ss_family, SS_ADDR(dns->dns_addr), 	      dns->dns_name, sizeof dns->dns_name);    dns->dns_edns = c->c_opt.edns;    servers[i] = dns++;  }  return servers;}staticvoid sres_servers_unref(sres_resolver_t *res,			sres_server_t **servers){  int i;  if (res == NULL || servers == NULL)    return;  for (i = 0; i < SRES_MAX_NAMESERVERS; i++) {    if (!servers[i])      break;    if (servers[i]->dns_socket != -1) {      if (res->res_updcb)	res->res_updcb(res->res_async, -1, servers[i]->dns_socket);      closesocket(servers[i]->dns_socket);    }  }  su_free(res->res_home, servers);}staticint sres_servers_count(sres_server_t *const *servers){  int i;  if (!servers)    return 0;  for (i = 0; i < SRES_MAX_NAMESERVERS; i++) {    if (!servers[i])      break;  }    return i;}staticint sres_server_socket(sres_resolver_t *res, sres_server_t *dns){  int family = dns->dns_addr->ss_family;  int s;  if (dns->dns_socket != -1)    return dns->dns_socket;  s = socket(family, SOCK_DGRAM, IPPROTO_UDP);  if (s == -1) {    SU_DEBUG_1(("%s: %s: %s\n", "sres_server_socket", "socket",		su_strerror(su_errno())));    dns->dns_error = time(NULL);    return s;  }#if HAVE_IP_RECVERR  if (family == AF_INET || family == AF_INET6) {    int const one = 1;    if (setsockopt(s, SOL_IP, IP_RECVERR, &one, sizeof(one)) < 0) {      if (family == AF_INET)	SU_DEBUG_3(("setsockopt(IPVRECVERR): %s\n", su_strerror(su_errno())));    }  }#endif#if HAVE_IPV6_RECVERR  if (family == AF_INET6) {    int const one = 1;    if (setsockopt(s, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one)) < 0)      SU_DEBUG_3(("setsockopt(IPV6_RECVERR): %s\n", su_strerror(su_errno())));  }#endif  if (connect(s, (void *)dns->dns_addr, dns->dns_addrlen) < 0) {    char ipaddr[64];    char const *lb = "", *rb = "";    if (family == AF_INET) {      void *addr = &((struct sockaddr_in *)dns->dns_addr)->sin_addr;      inet_ntop(family, addr, ipaddr, sizeof ipaddr);    }#if HAVE_SIN6    else if (family == AF_INET6) {      void *addr = &((struct sockaddr_in6 *)dns->dns_addr)->sin6_addr;      inet_ntop(family, addr, ipaddr, sizeof ipaddr);      lb = "[", rb = "]";    }#endif    else      snprintf(ipaddr, sizeof ipaddr, "<af=%u>", family);    SU_DEBUG_1(("%s: %s: %s: %s%s%s:%u\n", "sres_server_socket", "connect",		su_strerror(su_errno()), lb, ipaddr, rb,		ntohs(((struct sockaddr_in *)dns->dns_addr)->sin_port)));    closesocket(s);    dns->dns_error = time(NULL);    return -1;  }    if (res->res_updcb) {    if (res->res_updcb(res->res_async, s, -1) < 0) {      SU_DEBUG_1(("%s: %s: %s\n", "sres_server_socket", "update callback",		  su_strerror(su_errno())));      closesocket(s);      dns->dns_error = time(NULL);      return -1;    }  }  dns->dns_socket = s;    return s;}/* ---------------------------------------------------------------------- *//** Send a query packet */static int sres_send_dns_query(sres_resolver_t *res, 		    sres_query_t *q){                          sres_message_t m[1];  uint8_t i, i0, N = res->res_n_servers;  int s, transient, error = 0;  unsigned size, no_edns_size, edns_size;  uint16_t id = q->q_id;  uint16_t type = q->q_type;  char const *domain = q->q_name;  time_t now = res->res_now;  sres_server_t **servers = res->res_servers, *dns;  char b[8];  if (now == 0) time(&now);  SU_DEBUG_9(("sres_send_dns_query(%p, %p) called\n", res, q));  if (domain == NULL)    return -1;  if (servers == NULL)    return -1;  memset(m, 0, offsetof(sres_message_t, m_data[sizeof m->m_packet.mp_header]));  /* Create a DNS message */  m->m_size = sizeof(m->m_data);  m->m_offset = size = sizeof(m->m_packet.mp_header);    m->m_id = id;  m->m_flags = htons(SRES_HDR_QUERY | SRES_HDR_RD);    /* Query record */  m->m_qdcount = htons(1);  m_put_domain(m, domain, 0, NULL);  m_put_uint16(m, type);  m_put_uint16(m, sres_class_in);    no_edns_size = m->m_offset;  /* EDNS0 record (optional) */  m_put_domain(m, ".", 0, NULL);  m_put_uint16(m, sres_type_opt);  m_put_uint16(m, sizeof(m->m_packet)); /* Class: our UDP payload size */  m_put_uint32(m, 0);		/* TTL: extended RCODE & flags */  m_put_uint16(m, 0);    edns_size = m->m_offset;  if (m->m_error) {    SU_DEBUG_3(("%s(): encoding: %s\n", "sres_send_dns_query", m->m_error));    su_seterrno(EIO);    return -1;  }  transient = 0;  i0 = q->q_i_server; assert(i0 < N);  if (res->res_config->c_opt.rotate ||       servers[i0]->dns_error || servers[i0]->dns_icmp)    dns = sres_next_server(res, &q->q_i_server, 0), i = q->q_i_server;  else     dns = servers[i0], i = i0;  for (; dns; dns = sres_next_server(res, &i, 0)) {    /* If server supports EDNS, include EDNS0 record */    q->q_edns = dns->dns_edns;    /* 0 (no EDNS) or 1 (EDNS supported) additional data records */    m->m_arcount = htons(q->q_edns != 0);     /* Size with or without EDNS record */    size = q->q_edns ? edns_size : no_edns_size;     s = sres_server_socket(res, dns);    /* Send the DNS message via the UDP socket */    if (s != -1 && send(s, m->m_data, size, 0) == size)      break;    error = su_errno();    dns->dns_icmp = now;    /* EINVAL is returned if destination address is bad */    if (transient++ < 3 && error != EINVAL && s != -1)      continue;    transient = 0;    dns->dns_error = now;	/* Mark as a bad destination */  }  if (!dns) {    /* All servers have reported errors */    SU_DEBUG_5(("%s(): sendto: %s\n", "sres_send_dns_query",		su_strerror(error)));    return su_seterrno(error);  }  q->q_i_server = i;  SU_DEBUG_5(("%s(%p, %p) id=%u %s %s (to [%s]:%u)\n", 	      "sres_send_dns_query",	      res, q, id, sres_record_type(type, b), domain, 	      dns->dns_name, 	      htons(((struct sockaddr_in *)dns->dns_addr)->sin_port)));  return 0;}/** Select next server */staticsres_server_t *sres_next_server(sres_resolver_t *res, 				uint8_t *in_out_i,				int timeout){  int i, j, N;  sres_server_t **servers;  assert(res && in_out_i);  N = res->res_n_servers;  servers = res->res_servers;  i = *in_out_i;  assert(res->res_servers && res->res_servers[i]);    /* Retry using another server? */  for (j = (i + 1) % N; (j != i); j = (j + 1) % N) {    if (servers[j]->dns_icmp == 0) {      return *in_out_i = j, servers[j];    }  }  for (j = (i + 1) % N; (j != i); j = (j + 1) % N) {    if (servers[j]->dns_error == 0) {      return *in_out_i = j, servers[j];    }  }  if (timeout)    return servers[i];    return NULL;}/** * Callback function for subqueries */staticvoid sres_answer_subquery(

⌨️ 快捷键说明

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