📄 sresolv.c
字号:
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 + -