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

📄 sres.c

📁 sip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
		char const *domain){  if (socket == -1)    return errno = EINVAL, NULL;  return sres_query(res, callback, context, type, domain);}/** Make a reverse DNS query. * * Send a query to DNS server with specified @a type and domain name formed * from the socket address @a addr. The sres resolver takes care of * retransmitting the query if sres_resolver_timer() is called in regular * intervals. It generates an error record with nonzero status if no * response is received. * * This function just makes sure that we have the @a socket is valid, * otherwise it behaves exactly like sres_query_sockaddr(). */sres_query_t *sres_query_make_sockaddr(sres_resolver_t *res,			 sres_answer_f *callback,			 sres_context_t *context,			 int socket,			 uint16_t type,			 struct sockaddr const *addr){  char name[80];   if (!res || !addr)    return su_seterrno(EFAULT), (void *)NULL;  if (socket == -1)    return errno = EINVAL, NULL;  if (!sres_sockaddr2string(res, name, sizeof(name), addr))    return NULL;  return sres_query_make(res, callback, context, socket, type, name);}/** Bind a query with another callback and context pointer. * * @param query pointer to a query object to bind * @param callback pointer to new callback function (may be NULL) * @param context pointer to callback context (may be NULL)*/void sres_query_bind(sres_query_t *query,                     sres_answer_f *callback,                     sres_context_t *context){  if (query) {    query->q_callback = callback;    query->q_context = context;  }}/**Get a list of matching (type/domain) records from cache. * * @return * pointer to an array of pointers to cached records, or * NULL if no entry was found. * * @ERRORS * @ERROR ENAMETOOLONG @a domain is longer than SRES_MAXDNAME * @ERROR ENOENT no cached records were found * @ERROR EFAULT @a res or @a domain point outside the address space * @ERROR ENOMEM memory exhausted */sres_record_t **sres_cached_answers(sres_resolver_t *res,		    uint16_t type,		    char const *domain){  sres_record_t **result;  char rooted_domain[SRES_MAXDNAME];  if (!res)    return su_seterrno(EFAULT), (void *)NULL;  domain = sres_toplevel(rooted_domain, sizeof rooted_domain, domain);  if (!domain)    return NULL;    if (!sres_cache_get(res->res_cache, type, domain, &result))    return su_seterrno(ENOENT), (void *)NULL;  return result;}/**Search for a list of matching (type/name) records from cache. * * @return * pointer to an array of pointers to cached records, or * NULL if no entry was found. * * @ERRORS * @ERROR ENAMETOOLONG @a name or resulting domain is longer than SRES_MAXDNAME * @ERROR ENOENT no cached records were found * @ERROR EFAULT @a res or @a domain point outside the address space * @ERROR ENOMEM memory exhausted * * @sa sres_search(), sres_cached_answers() */sres_record_t **sres_search_cached_answers(sres_resolver_t *res,			   uint16_t type,			   char const *name){  char const *domain = name;  sres_record_t **search_results[SRES_MAX_SEARCH + 1] = { NULL };  char rooted_domain[SRES_MAXDNAME];  unsigned dots; char const *dot;  size_t found = 0;  int i;  SU_DEBUG_9(("sres_search_cached_answers(%p, %s, \"%s\") called\n",	      res, sres_record_type(type, rooted_domain), domain));  if (!res || !name)    return su_seterrno(EFAULT), (void *)NULL;  if (sres_has_search_domain(res))    for (dots = 0, dot = strchr(domain, '.');	 dots < res->res_config->c_opt.ndots && dot; 	 dots++, dot = strchr(dot + 1, '.'))      ;  else    dots = 0;  domain = sres_toplevel(rooted_domain, sizeof rooted_domain, domain);  if (!domain)    return NULL;  if (sres_cache_get(res->res_cache, type, domain, &search_results[0]))    found = 1;  if (dots < res->res_config->c_opt.ndots) {    char const **domains = res->res_config->c_search;    size_t dlen = strlen(domain);    for (i = 0; domains[i] && i < SRES_MAX_SEARCH; i++) {      size_t len = strlen(domains[i]);      if (dlen + len + 1 >= SRES_MAXDNAME)	continue;      if (domain != rooted_domain)	domain = memcpy(rooted_domain, domain, dlen);      memcpy(rooted_domain + dlen, domains[i], len);      strcpy(rooted_domain + dlen + len, ".");      if (sres_cache_get(res->res_cache, type, domain, search_results + i + 1))	found++;    }  }  if (found == 0)    return su_seterrno(ENOENT), (void *)NULL;  if (found == 1) {    for (i = 0; i <= SRES_MAX_SEARCH; i++)      if (search_results[i])	return search_results[i];  }  return sres_combine_results(res, search_results);}/**Get a list of matching (type/domain) reverse records from cache. * *  * * @retval  * pointer to an array of pointers to cached records, or * NULL if no entry was found. * * @ERRORS * @ERROR EAFNOSUPPORT address family specified in @a addr is not supported * @ERROR ENOENT no cached records were found * @ERROR EFAULT @a res or @a addr point outside the address space * @ERROR ENOMEM memory exhausted */sres_record_t **sres_cached_answers_sockaddr(sres_resolver_t *res,			     uint16_t type,			     struct sockaddr const *addr){  sres_record_t **result;  char name[80];  if (!res || !addr)    return su_seterrno(EFAULT), (void *)NULL;  if (!sres_sockaddr2string(res, name, sizeof name, addr))    return NULL;  if (!sres_cache_get(res->res_cache, type, name, &result))    su_seterrno(ENOENT), (void *)NULL;  return result;}/** Sort answers. */intsres_sort_answers(sres_resolver_t *res, sres_record_t **answers){  int i, j;  if (res == NULL || answers == NULL)    return su_seterrno(EFAULT);  if (answers[0] == NULL || answers[1] == NULL)    return 0;  /* Simple insertion sorting */  /*   * We do not use qsort because we want later extend this to sort    * local A records first etc.   */  for (i = 1; answers[i]; i++) {    for (j = 0; j < i; j++) {      if (sres_record_compare(answers[i], answers[j]) < 0)	break;    }    if (j < i) {      sres_record_t *r = answers[i];      for (; j < i; i--) {	answers[i] = answers[i - 1];      }      answers[j] = r;    }  }  return 0;}/** Sort and filter query results */intsres_filter_answers(sres_resolver_t *res, 		    sres_record_t **answers, 		    uint16_t type){		      int i, n;  for (n = 0, i = 0; answers && answers[i]; i++) {    if (answers[i]->sr_record->r_status ||	answers[i]->sr_record->r_class != sres_class_in ||	(type != 0 && answers[i]->sr_record->r_type != type)) {      sres_free_answer(res, answers[i]);      continue;    }    answers[n++] = answers[i];  }  answers[n] = NULL;  sres_sort_answers(res, answers);  return n;}/** Free and zero one record. */void sres_free_answer(sres_resolver_t *res, sres_record_t *answer){  if (res && answer)    sres_cache_free_one(res->res_cache, answer);}/** Free and zero an array of records. *  * The array of records can be returned by sres_cached_answers() or  * given by callback function. */void sres_free_answers(sres_resolver_t *res,		  sres_record_t **answers){  if (res && answers)    sres_cache_free_answers(res->res_cache, answers);}/** Convert type to its name. */char const *sres_record_type(int type, char buffer[8]){  switch (type) {  case sres_type_a: return "A";  case sres_type_ns: return "NS";  case sres_type_mf: return "MF";  case sres_type_cname: return "CNAME";  case sres_type_soa: return "SOA";  case sres_type_mb: return "MB";  case sres_type_mg: return "MG";  case sres_type_mr: return "MR";  case sres_type_null: return "NULL";  case sres_type_wks: return "WKS";  case sres_type_ptr: return "PTR";  case sres_type_hinfo: return "HINFO";  case sres_type_minfo: return "MINFO";  case sres_type_mx: return "MX";  case sres_type_txt: return "TXT";  case sres_type_rp: return "RP";  case sres_type_afsdb: return "AFSDB";  case sres_type_x25: return "X25";  case sres_type_isdn: return "ISDN";  case sres_type_rt: return "RT";  case sres_type_nsap: return "NSAP";  case sres_type_nsap_ptr: return "NSAP_PTR";  case sres_type_sig: return "SIG";  case sres_type_key: return "KEY";  case sres_type_px: return "PX";  case sres_type_gpos: return "GPOS";  case sres_type_aaaa: return "AAAA";  case sres_type_loc: return "LOC";  case sres_type_nxt: return "NXT";  case sres_type_eid: return "EID";  case sres_type_nimloc: return "NIMLOC";  case sres_type_srv: return "SRV";  case sres_type_atma: return "ATMA";  case sres_type_naptr: return "NAPTR";  case sres_type_kx: return "KX";  case sres_type_cert: return "CERT";  case sres_type_a6: return "A6";  case sres_type_dname: return "DNAME";  case sres_type_sink: return "SINK";  case sres_type_opt: return "OPT";  case sres_qtype_tsig: return "TSIG";  case sres_qtype_ixfr: return "IXFR";  case sres_qtype_axfr: return "AXFR";  case sres_qtype_mailb: return "MAILB";  case sres_qtype_maila: return "MAILA";  case sres_qtype_any: return "ANY";      default:    sprintf(buffer, "%u?", type & 65535);    return buffer;  }}/** Convert class to its name. */char const *sres_record_class(int rclass, char buffer[8]){  switch (rclass) {  case 1: return "IN";  case 2: return "2?";  case 3: return "CHAOS";  case 4: return "HS";  case 254: return "NONE";  case 255: return "ANY";  default:    sprintf(buffer, "%u?", rclass & 65535);    return buffer;  }}/** Compare two records. */int sres_record_compare(sres_record_t const *aa, sres_record_t const *bb){  int D;  sres_common_t const *a = aa->sr_record, *b = bb->sr_record;  D = a->r_status - b->r_status; if (D) return D;  D = a->r_class - b->r_class; if (D) return D;  D = a->r_type - b->r_type; if (D) return D;  if (a->r_status)    return 0;    switch (a->r_type) {  case sres_type_soa:     {      sres_soa_record_t const *A = aa->sr_soa, *B = bb->sr_soa;      D = A->soa_serial - B->soa_serial; if (D) return D;      D = strcasecmp(A->soa_mname, B->soa_mname); if (D) return D;      D = strcasecmp(A->soa_rname, B->soa_rname); if (D) return D;      D = A->soa_refresh - B->soa_refresh; if (D) return D;      D = A->soa_retry - B->soa_retry; if (D) return D;      D = A->soa_expire - B->soa_expire; if (D) return D;      D = A->soa_minimum - B->soa_minimum; if (D) return D;      return 0;    }  case sres_type_a:    {      sres_a_record_t const *A = aa->sr_a, *B = bb->sr_a;      return memcmp(&A->a_addr, &B->a_addr, sizeof A->a_addr);    }  case sres_type_a6:    {      sres_a6_record_t const *A = aa->sr_a6, *B = bb->sr_a6;      D = A->a6_prelen - B->a6_prelen; if (D) return D;      D = !A->a6_prename - !B->a6_prename;       if (D == 0 && A->a6_prename && B->a6_prename)	D = strcasecmp(A->a6_prename, B->a6_prename); if (D) return D;      return memcmp(&A->a6_suffix, &B->a6_suffix, sizeof A->a6_suffix);    }  case sres_type_aaaa:    {      sres_aaaa_record_t const *A = aa->sr_aaaa, *B = bb->sr_aaaa;      return memcmp(&A->aaaa_addr, &B->aaaa_addr, sizeof A->aaaa_addr);          }  case sres_type_cname:    {      sres_cname_record_t const *A = aa->sr_cname, *B = bb->sr_cname;      return strcmp(A->cn_cname, B->cn_cname);    }  case sres_type_ptr:    {      sres_ptr_record_t const *A = aa->sr_ptr, *B = bb->sr_ptr;      return strcmp(A->ptr_domain, B->ptr_domain);    }  case sres_type_srv:    {      sres_srv_record_t const *A = aa->sr_srv, *B = bb->sr_srv;      D = A->srv_priority - B->srv_priority; if (D) return D;      /* Record with larger weight first */      D = B->srv_weight - A->srv_weight; if (D) return D;      D = strcmp(A->srv_target, B->srv_target); if (D) return D;      return A->srv_port - B->srv_port;    }  case sres_type_naptr:    {      sres_naptr_record_t const *A = aa->sr_naptr, *B = bb->sr_naptr;      D = A->na_order - B->na_order; if (D) return D;      D = A->na_prefer - B->na_prefer; if (D) return D;      D = strcmp(A->na_flags, B->na_flags); if (D) return D;      D = strcmp(A->na_services, B->na_services); if (D) return D;      D = strcmp(A->na_regexp, B->na_regexp); if (D) return D;      return strcmp(A->na_replace, B->na_replace);     }  default:    return 0;  }}/* ---------------------------------------------------------------------- *//* Private functions */static void sres_resolver_destructor(void *arg){  sres_resolver_t *res = arg;  assert(res);  sres_cache_unref(res->res_cache);   res->res_cache = NULL;  sres_servers_unref(res, res->res_servers);  if (res->res_updcb)    res->res_updcb(res->res_async, -1, -1);}/* * 3571 is a prime =>  * we hash successive id values to different parts of hash tables */#define Q_PRIME 3571#define SRES_QUERY_HASH(q) ((q)->q_hash)HTABLE_BODIES(sres_qtable, qt, sres_query_t, SRES_QUERY_HASH);/** Allocate a query structure */staticsres_query_t *sres_query_alloc(sres_resolver_t *res,		 sres_answer_f *callback,		 sres_context_t *context,		 uint16_t type,		 char const *domain){  sres_query_t *query;  size_t dlen = strlen(domain);  if (sres_qtable_is_full(res->res_queries))    if (sres_qtable_resize(res->res_home, res->res_queries, 0) < 0)      return NULL;  query = su_alloc(res->res_home, sizeof(*query) + dlen + 1);  if (query) {    memset(query, 0, sizeof *query);    query->q_res = res;    query->q_callback = callback;    query->q_context = context;    query->q_type = type;    query->q_class = sres_class_in;    query->q_timestamp = res->res_now;    query->q_name = strcpy((char *)(query + 1), domain);    query->q_id = sres_new_id(res); assert(query->q_id);    query->q_i_server = res->res_i_server;    query->q_n_servers = res->res_n_servers;

⌨️ 快捷键说明

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