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

📄 sresolv.c

📁 Internet Phone, Chat, Conferencing
💻 C
📖 第 1 页 / 共 5 页
字号:
  m->m_size = num_bytes;  if (!LOCK(res))    return -1;  time(&res->res_now);  /* Decode the received message and get the matching query object */  error = sres_decode_msg(res, m, &query, &reply);  sres_log_response(res, m, from, query, reply);  if (query == NULL)    ;  else if (error == SRES_EDNS0_ERR) {    dns->dns_edns = 0;    assert(query->q_id);    sres_remove_query(res, query, 0);    query->q_id = sres_new_id(res);    query->q_hash = query->q_id * Q_PRIME;    sres_qtable_append(res->res_queries, query);    sres_send_dns_query(res, query);    query->q_retry_count++;  }   else if (!error && reply) {    /* Remove the query from the pending list and notify the listener */    sres_remove_query(res, query, 1);    UNLOCK(res);    if (query->q_callback != NULL)      (query->q_callback)(query->q_context, query, reply);     LOCK(res);    sres_free_query(res, query);  }  else {    sres_query_report_error(res, query, reply);  }  UNLOCK(res);  return 1;}staticvoid sres_log_response(sres_resolver_t const *res, 		       sres_message_t const *m,		       struct sockaddr_storage const *from,		       sres_query_t const *query,		       sres_record_t * const *reply){  if (SU_LOG->log_level >= 5) {#ifndef ADDRSIZE#define ADDRSIZE 48#endif    char host[ADDRSIZE];    if (from->ss_family == AF_INET) {      struct sockaddr_in const *sin = (void *)from;      inet_ntop(AF_INET, &sin->sin_addr, host, sizeof host);    } #if HAVE_SIN6    else if (from->ss_family == AF_INET6) {      struct sockaddr_in6 const *sin6 = (void *)from;      inet_ntop(AF_INET6, &sin6->sin6_addr, host, sizeof host);    }#endif    else      strcpy(host, "*");    SU_DEBUG_5(("sres_resolver_receive(%p, %p) id=%u (from [%s]:%u)\n", 		res, query, m->m_id, 		host, ntohs(((struct sockaddr_in *)from)->sin_port)));  }}/** Decode DNS message. * */staticintsres_decode_msg(sres_resolver_t *res, 		sres_message_t *m,		sres_query_t **qq,		sres_record_t ***aanswers){  sres_record_t *rr = NULL, **answers = NULL, *error = NULL;  sres_query_t *query = NULL, **hq;  hash_value_t hash;  int i, err;  assert(res && m && aanswers);  *qq = NULL;  *aanswers = answers;  m->m_offset = sizeof(m->m_packet.mp_header);  if (m->m_size < m->m_offset) {    SU_DEBUG_5(("sres_decode_msg: truncated message\n"));    return -1;  }  m->m_flags   = ntohs(m->m_flags);  m->m_qdcount = ntohs(m->m_qdcount);  m->m_ancount = ntohs(m->m_ancount);   m->m_nscount = ntohs(m->m_nscount);   m->m_arcount = ntohs(m->m_arcount);   hash = Q_PRIME * m->m_id;  /* Search for query with this ID */  for (hq = sres_qtable_hash(res->res_queries, hash);       *hq;       hq = sres_qtable_next(res->res_queries, hq))    if (hash == (*hq)->q_hash)      break;  *qq = query = *hq;  if (!query) {    SU_DEBUG_5(("sres_decode_msg: %u has no matching query\n", m->m_id));    return -1;  }  assert(query && m->m_id == query->q_id);  if ((m->m_flags & 15) == SRES_FORMAT_ERR && query->q_edns)    return SRES_EDNS0_ERR;  /* Scan question section */  for (i = 0; i < m->m_qdcount; i++) {    char name[1024];    uint16_t qtype, qclass;    m_get_domain(name, sizeof(name), m, 0); /* Query domain */    qtype = m_get_uint16(m);  /* Query type */    qclass = m_get_uint16(m); /* Query class */  }  if (m->m_error) {    SU_DEBUG_5(("sres_decode_msg: %s\n", m->m_error));    return -1;  }  err = m->m_flags & SRES_HDR_RCODE;  if (m->m_ancount) {    *aanswers = answers = su_zalloc(res->res_home, 				    (m->m_ancount + 1) * sizeof answers[0]);    assert(answers);  } #if 1  else if (err == 0 || err == SRES_NAME_ERR || err == SRES_UNIMPL_ERR) {    if (err == 0)       err = SRES_RECORD_ERR;    *aanswers = answers = su_zalloc(res->res_home, 2 * sizeof answers[0]);    if (answers) {      error = sres_create_error_rr(res, query, err);      if (error) {	sres_store(res, error);	*answers++ = error;	error->sr_refcount++;      }    }  }#endif  else {    *aanswers = answers = NULL;  }  /* Scan resource records */  /* XXX - this should be atomic  */   for (i = 0; i < m->m_ancount + m->m_nscount + m->m_arcount; i++) {    rr = sres_create_record(res, m);     if (!rr) {      SU_DEBUG_5(("sres_create_record: %s\n", m->m_error));      return -1;    }    if (error && rr->sr_type == sres_type_soa) {      sres_soa_record_t *soa = (sres_soa_record_t *)rr;      if (error->sr_ttl > soa->soa_minimum && soa->soa_minimum > 10)	  error->sr_ttl = soa->soa_minimum;    }	    sres_store(res, rr);    if (i < m->m_ancount) {      *answers++ = rr;      rr->sr_refcount++;    }   }  return err;}  staticsres_record_t *sres_alloc_record(sres_resolver_t *res, uint16_t qtype, uint16_t rdlen){  int size;  sres_record_t *sr;  switch (qtype) {  case sres_type_soa:     size = sizeof(sres_soa_record_t); break;  case sres_type_a:       size = sizeof(sres_a_record_t); break;#if SU_HAVE_IN6  case sres_type_a6:      size = sizeof(sres_a6_record_t); break;  case sres_type_aaaa:    size = sizeof(sres_aaaa_record_t); break;#endif  case sres_type_cname:   size = sizeof(sres_cname_record_t); break;  case sres_type_ptr:     size = sizeof(sres_ptr_record_t); break;  case sres_type_srv:     size = sizeof(sres_srv_record_t); break;  case sres_type_naptr:   size = sizeof(sres_naptr_record_t); break;  default:                size = sizeof(sres_common_t) + rdlen; break;  }  sr = su_zalloc(res->res_home, size);  if (sr)     sr->sr_size = size;      return sr;}staticsres_record_t *sres_create_record(sres_resolver_t *res, sres_message_t *m){  sres_record_t *rr = NULL;  uint16_t qtype, qclass, rdlen, size_old;  uint32_t ttl;  char name[1024];  int name_length;  name_length = m_get_domain(name, sizeof(name), m, 0);	/* Name */  qtype = m_get_uint16(m);  /* Type */  qclass = m_get_uint16(m); /* Class */  ttl = m_get_uint32(m);    /* TTL */  rdlen = m_get_uint16(m);   /* rdlength */  SU_DEBUG_9(("rr: %s %d %d %d %d\n", name, qtype, qclass, ttl, rdlen));  if (m->m_error)    return NULL;  /* temporarily adjust m_size to check if the current rr is truncated */  size_old = m->m_size;   m->m_size = m->m_offset + rdlen;  rr = sres_alloc_record(res, qtype, rdlen);  if (rr) switch(qtype) {  case sres_type_soa:    sres_init_rr_soa(res, rr->sr_soa, m);    break;  case sres_type_a:    sres_init_rr_a(res, rr->sr_a, m);    break;#if SU_HAVE_IN6  case sres_type_a6:    sres_init_rr_a6(res, rr->sr_a6, m);    break;  case sres_type_aaaa:    sres_init_rr_aaaa(res, rr->sr_aaaa, m);    break;#endif  case sres_type_cname:    sres_init_rr_cname(res, rr->sr_cname, m);    break;  case sres_type_ptr:    sres_init_rr_ptr(res, rr->sr_ptr, m);    break;  case sres_type_srv:    sres_init_rr_srv(res, rr->sr_srv, m);    break;  case sres_type_naptr:    sres_init_rr_naptr(res, rr->sr_naptr, m);    break;  default: /* copy the raw rdata to rr->r_data */    if (m->m_offset + rdlen > m->m_size) {      m->m_error = "truncated message";    } else {      memcpy(rr->sr_rdata, m->m_data + m->m_offset, rdlen);      m->m_offset += rdlen;    }  }  else     m->m_error = "memory exhausted";    if (m->m_error) {    SU_DEBUG_5(("sres_create_rr: %s\n", m->m_error));    su_free(res->res_home, rr);    return NULL;  }  m->m_size = size_old;  /* Fill in the common fields */  if (rr != NULL) {    rr->sr_name = su_strdup(res->res_home, name);    rr->sr_type = qtype;    rr->sr_class = qclass;    rr->sr_ttl = ttl;    rr->sr_rdlen = rdlen;  }  return rr;}static voidsres_init_rr_soa(sres_resolver_t *res, 		 sres_soa_record_t *rr,		 sres_message_t *m){  assert(rr->soa_record->r_size == sizeof(sres_soa_record_t));  sres_get_domain(res, &rr->soa_mname, m);  sres_get_domain(res, &rr->soa_rname, m);  rr->soa_serial = m_get_uint32(m);  rr->soa_refresh = m_get_uint32(m);  rr->soa_retry = m_get_uint32(m);  rr->soa_expire = m_get_uint32(m);  rr->soa_minimum = m_get_uint32(m);}static voidsres_init_rr_a(sres_resolver_t *res, 	       sres_a_record_t *rr,	       sres_message_t *m){  assert(rr->a_record->r_size == sizeof(sres_a_record_t));  rr->a_addr.s_addr = htonl(m_get_uint32(m));}#if SU_HAVE_IN6static voidsres_init_rr_a6(sres_resolver_t *res,		sres_a6_record_t *rr,		sres_message_t *m){  int suffix_length, i;  assert(rr->a6_record->r_size == sizeof(sres_a6_record_t));  rr->a6_prelen = m_get_uint8(m);  suffix_length = (128 - rr->a6_prelen) / 8;        if ((128 - rr->a6_prelen) % 8 != 0)    suffix_length++;  for (i = 16 - suffix_length; i < 16; i++) {    if (i >= 0) {      rr->a6_suffix.s6_addr[i] = m_get_uint8(m);    }  }  if (suffix_length < 16)    sres_get_domain(res, &rr->a6_prename, m);}static voidsres_init_rr_aaaa(sres_resolver_t *res,		  sres_aaaa_record_t *rr,		  sres_message_t *m){  assert(rr->aaaa_record->r_size == sizeof(sres_aaaa_record_t));  if (m->m_offset + sizeof(rr->aaaa_addr.s6_addr) > m->m_size) {    m->m_error = "truncated message";    return;  }  memcpy(rr->aaaa_addr.s6_addr, 	 m->m_data + m->m_offset, 	 sizeof(rr->aaaa_addr.s6_addr));  m->m_offset += sizeof(rr->aaaa_addr.s6_addr);}#endif /* SU_HAVE_IN6 */static voidsres_init_rr_cname(sres_resolver_t *res,		   sres_cname_record_t *rr,		   sres_message_t *m){  assert(rr->cname_record->r_size == sizeof(sres_cname_record_t));  sres_get_domain(res, &rr->cn_cname, m);}static voidsres_init_rr_ptr(sres_resolver_t *res,		 sres_ptr_record_t *rr,		 sres_message_t *m){  assert(rr->ptr_record->r_size == sizeof(sres_ptr_record_t));  sres_get_domain(res, &rr->ptr_domain, m);}static voidsres_init_rr_srv(sres_resolver_t *res,		 sres_srv_record_t *rr,		 sres_message_t *m){  assert(rr->srv_record->r_size == sizeof(sres_srv_record_t));  rr->srv_priority = m_get_uint16(m);  rr->srv_weight = m_get_uint16(m);  rr->srv_port = m_get_uint16(m);  sres_get_domain(res, &rr->srv_target, m);}static voidsres_init_rr_naptr(sres_resolver_t *res,		   sres_naptr_record_t *rr,		   sres_message_t *m){  assert(rr->na_record->r_size == sizeof(sres_naptr_record_t));  rr->na_order = m_get_uint16(m);  rr->na_prefer = m_get_uint16(m);  sres_get_string(res, &rr->na_flags, m);  sres_get_string(res, &rr->na_services, m);  sres_get_string(res, &rr->na_regexp, m);  sres_get_domain(res, &rr->na_replace, m);}staticsres_record_t *sres_create_error_rr(sres_resolver_t *res,		     sres_query_t const *q,		     uint16_t errcode){  sres_record_t *sr;  char buf[SRES_MAXDNAME];  sr = sres_alloc_record(res, q->q_type, 0);    if (sr) {    sr->sr_status = errcode;    sr->sr_name = su_strdup(res->res_home, sres_toplevel(buf, q->q_name));    sr->sr_type = q->q_type;    sr->sr_class = q->q_class;    sr->sr_ttl = 10 * 60;    /* sr->sr_ttl = 30; */  }  return sr;}staticintsres_get_domain(sres_resolver_t *res,		char **buf,		sres_message_t *m){  char name[1024];  int length = 0;  assert(buf);  if (buf) {    length = m_get_domain(name, sizeof(name), m, 0);    *buf = su_zalloc(res->res_home, length + 1);    assert(*buf);    if (*buf) {      memcpy(*buf, name, length);      *(*buf + length) = 0;    }  }  return length;}staticint sres_get_string(sres_resolver_t *res,		char **buf,		sres_message_t *m){  char name[1024];  int length = 0;  assert(buf);  if (buf) {    length = m_get_string(name, sizeof(name), m);    *buf = su_zalloc(res->res_home, length + 1);    assert(*buf);    if (*buf) {      memcpy(*buf, name, length);      *(*buf + length) = 0;    }  }  return length;}/* Cache-related functions */HTABLE_BODIES(sres_htable, ht, sres_rr_hash_entry_t, SRES_HENTRY_HASH);staticvoid sres_store(sres_resolver_t *res, sres_r

⌨️ 快捷键说明

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