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

📄 sres.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
    return (void)su_seterrno(ENETDOWN), (sres_query_t *)NULL;  query = sres_query_alloc(res, callback, context, type, domain);  if (query && sres_send_dns_query(res, query) != 0)    sres_free_query(res, query), query = NULL;  return query;}/**Search DNS. * * Sends DNS queries with specified @a type and @a name to the DNS server.  * If the @a name does not contain enought dots, the search domains are * appended to the name and resulting domain name are also queried. When * answer to all the search domains is received, the @a callback function * is called with @a context and combined records from answers as arguments. *  * The sres resolver takes care of retransmitting the queries if a root * object is associate with the resolver or if sres_resolver_timer() is * called in regular intervals. It generates an error record with nonzero * status if no response is received. * * @param res pointer to resolver object * @param callback pointer to completion function * @param context argument given to the completion function * @param type record type to search (or sres_qtype_any for any record) * @param name host or domain name to search from DNS * * @ERRORS * @ERROR EFAULT @a res or @a domain point outside the address space * @ERROR ENAMETOOLONG @a domain is longer than SRES_MAXDNAME * @ERROR ENETDOWN no DNS servers configured * @ERROR ENOMEM memory exhausted * * @sa sres_query(), sres_blocking_search(), sres_search_cached_answers(). */sres_query_t *sres_search(sres_resolver_t *res,	    sres_answer_f *callback,	    sres_context_t *context,	    uint16_t type,	    char const *name){  char const *domain = name;  sres_query_t *query = NULL;  size_t dlen;  unsigned dots; char const *dot;  char b[8];  SU_DEBUG_9(("sres_search(%p, %p, %s, \"%s\") called\n",			  (void *)res, (void *)context, sres_record_type(type, b), domain));  if (res == NULL || domain == NULL)    return su_seterrno(EFAULT), (void *)NULL;  dlen = strlen(domain);  if (dlen > SRES_MAXDNAME ||      (dlen == SRES_MAXDNAME && domain[dlen - 1] != '.')) {    su_seterrno(ENAMETOOLONG);    return NULL;  }  sres_resolver_update(res, 0);  if (res->res_n_servers == 0)    return (void)su_seterrno(ENETDOWN), (sres_query_t *)NULL;  if (domain[dlen - 1] == '.')    /* Domain ends with dot - do not search */    dots = res->res_config->c_opt.ndots;  else 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;  query = sres_query_alloc(res, callback, context, type, domain);  if (query) {    /* Create sub-query for each search domain */    if (dots < res->res_config->c_opt.ndots) {      sres_query_t *sub;      int i, subs;      size_t len;      char const *const *domains = res->res_config->c_search;      char search[SRES_MAXDNAME + 1];      assert(dlen < SRES_MAXDNAME);      memcpy(search, domain, dlen);      search[dlen++] = '.';      search[dlen] = '\0';      for (i = 0, subs = 0; i <= SRES_MAX_SEARCH; i++) {	if (domains[i]) {	  len = strlen(domains[i]);	  	  if (dlen + len + 1 > SRES_MAXDNAME)	    continue;	  memcpy(search + dlen, domains[i], len);	  search[dlen + len] = '.';	  search[dlen + len + 1] = '\0';	  sub = sres_query_alloc(res, sres_answer_subquery, (void *)query,				 type, search);	  if (sub == NULL) {	  }	  else if (sres_send_dns_query(res, sub) == 0) {	    query->q_subqueries[i] = sub;	  }	  else {	    sres_free_query(res, sub), sub = NULL;	  }	  subs += sub != NULL;	}      }      query->q_n_subs = subs;    }    if (sres_send_dns_query(res, query) != 0) {      if (!query->q_n_subs)	sres_free_query(res, query), query = NULL;      else	query->q_id = 0;    }  }  return query;}/** 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 a root object is associate with the resolver or * if sres_resolver_timer() is called in regular intervals. It generates an * error record with nonzero status if no response is received. * * @param res pointer to resolver * @param callback function called when query is answered or times out * @param context pointer given as an extra argument to @a callback function * @param type record type to query (or sres_qtype_any for any record) * @param addr socket address structure *  * The @a type should be #sres_type_ptr. The @a addr should contain either * IPv4 (AF_INET) or IPv6 (AF_INET6) address. * * If the #SRES_OPTIONS environment variable, #RES_OPTIONS environment * variable, or an "options" entry in resolv.conf file contains an option * "ip6-dotint", the IPv6 addresses are resolved using suffix ".ip6.int" * instead of the standard ".ip6.arpa" suffix. * * @ERRORS * @ERROR EAFNOSUPPORT address family specified in @a addr is not supported * @ERROR ENETDOWN no DNS servers configured * @ERROR EFAULT @a res or @a addr point outside the address space * @ERROR ENOMEM memory exhausted * * @sa sres_query(), sres_blocking_query_sockaddr(), * sres_cached_answers_sockaddr() * */sres_query_t *sres_query_sockaddr(sres_resolver_t *res,		    sres_answer_f *callback,		    sres_context_t *context,		    uint16_t type,		    struct sockaddr const *addr){  char name[80];   if (!res || !addr)    return su_seterrno(EFAULT), (void *)NULL;  if (!sres_sockaddr2string(res, name, sizeof(name), addr))    return NULL;  return sres_query(res, callback, context, type, name);}/** Make a DNS query. * * @deprecated Use sres_query() instead. */sres_query_t *sres_query_make(sres_resolver_t *res,		sres_answer_f *callback,		sres_context_t *context,		int dummy,		uint16_t type,		char const *domain){  return sres_query(res, callback, context, type, domain);}/** Make a reverse DNS query. * * @deprecated Use sres_query_sockaddr() instead. */sres_query_t *sres_query_make_sockaddr(sres_resolver_t *res,			 sres_answer_f *callback,			 sres_context_t *context,			 int dummy,			 uint16_t type,			 struct sockaddr const *addr){  char name[80];   if (!res || !addr)    return su_seterrno(EFAULT), (void *)NULL;  if (!sres_sockaddr2string(res, name, sizeof(name), addr))    return NULL;  return sres_query_make(res, callback, context, dummy, 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",	      (void *)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 *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. * * @param res pointer to resolver * @param type record type to query (or sres_qtype_any for any record) * @param addr socket address structure *  * The @a type should be #sres_type_ptr. The @a addr should contain either * IPv4 (AF_INET) or IPv6 (AF_INET6) address. * * If the #SRES_OPTIONS environment variable, #RES_OPTIONS environment * variable or an "options" entry in resolv.conf file contains an option * "ip6-dotint", the IPv6 addresses are resolved using suffix ".ip6.int" * instead of default ".ip6.arpa". * * @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;}/** Set the priority of the matching cached SRV record. * * The SRV records with the domain name, target and port are matched and * their priority value is adjusted. This function is used to implement * greylisting of SIP servers. * * @param res      pointer to resolver * @param domain   domain name of the SRV record(s) to modify * @param target   SRV target of the SRV record(s) to modify * @param port     port number of SRV record(s) to modify  *                 (in host byte order)  * @param ttl      new ttl for SRV records of the domain * @param priority new priority value (0=highest, 65535=lowest) * * @sa sres_cache_set_srv_priority() *  * @NEW_1_12_8 */int sres_set_cached_srv_priority(sres_resolver_t *res,				 char const *domain,				 char const *target,				 uint16_t port,				 uint32_t ttl,				 uint16_t priority){  char rooted_domain[SRES_MAXDNAME];  if (res == NULL || res->res_cache == NULL)    return su_seterrno(EFAULT);  domain = sres_toplevel(rooted_domain, sizeof rooted_domain, domain);  if (!domain)    return -1;  return sres_cache_set_srv_priority(res->res_cache, 				     domain, target, port, 				     ttl, priority);}/** 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;  if (res == NULL || answers == NULL)

⌨️ 快捷键说明

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