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

📄 sres.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
			       char const *info);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);static int sres_decode_msg(sres_resolver_t *res, 			   sres_message_t *m,			   sres_query_t **,			   sres_record_t ***aanswers);static char const *sres_toplevel(char buf[], size_t bsize, char const *domain);static sres_record_t *sres_create_record(sres_resolver_t *, sres_message_t *m);static sres_record_t *sres_init_rr_soa(sres_cache_t *cache,				       sres_soa_record_t *,				       sres_message_t *m);static sres_record_t *sres_init_rr_a(sres_cache_t *cache,				     sres_a_record_t *,				     sres_message_t *m);static sres_record_t *sres_init_rr_a6(sres_cache_t *cache,				      sres_a6_record_t *,				      sres_message_t *m);static sres_record_t *sres_init_rr_aaaa(sres_cache_t *cache,					sres_aaaa_record_t *,					sres_message_t *m);static sres_record_t *sres_init_rr_cname(sres_cache_t *cache,					 sres_cname_record_t *,					 sres_message_t *m);static sres_record_t *sres_init_rr_ptr(sres_cache_t *cache,				       sres_ptr_record_t *,				       sres_message_t *m);static sres_record_t *sres_init_rr_srv(sres_cache_t *cache,				       sres_srv_record_t *,				       sres_message_t *m);static sres_record_t *sres_init_rr_naptr(sres_cache_t *cache,					 sres_naptr_record_t *,					 sres_message_t *m);static sres_record_t *sres_init_rr_unknown(sres_cache_t *cache,					   sres_common_t *r,					   sres_message_t *m);static sres_record_t *sres_create_error_rr(sres_cache_t *cache,                                           sres_query_t const *q,                                           uint16_t errcode);static void m_put_uint16(sres_message_t *m, uint16_t h);static void m_put_uint32(sres_message_t *m, uint32_t w);static uint16_t m_put_domain(sres_message_t *m,                              char const *domain,                              uint16_t top,                              char const *topdomain);static uint32_t m_get_uint32(sres_message_t *m);static uint16_t m_get_uint16(sres_message_t *m);static uint8_t m_get_uint8(sres_message_t *m);static int m_get_string(char *d, int n, sres_message_t *m, uint16_t offset);static int m_get_domain(char *d, int n, sres_message_t *m, uint16_t offset);/* ---------------------------------------------------------------------- */#define SU_LOG sresolv_log#include <sofia-sip/su_debug.h>#ifdef HAVE_WIN32#include <winreg.h>#endif/**@ingroup sresolv_env * * Environment variable determining the debug log level for @b sresolv * module. * * The SRESOLV_DEBUG environment variable is used to determine the debug * logging level for @b sresolv module. The default level is 3. *  * @sa <sofia-sip/su_debug.h>, sresolv_log, SOFIA_DEBUG */#ifdef DOXYGENextern char const SRESOLV_DEBUG[]; /* dummy declaration for Doxygen */#endif#ifndef SU_DEBUG#define SU_DEBUG 3#endif/**Debug log for @b sresolv module.  *  * The sresolv_log is the log object used by @b sresolv module. The level of * #sresolv_log is set using #SRESOLV_DEBUG environment variable. */su_log_t sresolv_log[] = { SU_LOG_INIT("sresolv", "SRESOLV_DEBUG", SU_DEBUG) };/** Internal errors */enum {  SRES_EDNS0_ERR = 255		/**< Server did not support EDNS. */};/* ---------------------------------------------------------------------- *//**Create a resolver. * * Allocate and initialize a new sres resolver object. The resolver object * contains the parsed resolv.conf file, a cache object containing past * answers from DNS, and a list of active queries. The default resolv.conf * file can be overriden by giving the name of the configuration file as @a * conf_file_path. * * @param conf_file_path name of the resolv.conf configuration file  * * @return A pointer to a newly created sres resolver object, or NULL upon * an error. */sres_resolver_t *sres_resolver_new(char const *conf_file_path){  return sres_resolver_new_internal(NULL, NULL, conf_file_path, NULL);}/** Copy a resolver. * * Make a copy of resolver sharing the configuration and cache with old * resolver. */sres_resolver_t *sres_resolver_copy(sres_resolver_t *res){  char const *cnffile;  sres_config_t *config;  sres_cache_t *cache;  char const **options;  if (!res)    return NULL;  cnffile = res->res_cnffile;  config = su_home_ref(res->res_config->c_home);  cache = res->res_cache;  options = res->res_options;  return sres_resolver_new_internal(cache, config, cnffile, options);}/**New resolver object. * * Allocate and initialize a new sres resolver object. The resolver object * contains the parsed resolv.conf file, a cache object containing past * answers from DNS, and a list of active queries. The default resolv.conf * file can be overriden by giving the name of the configuration file as @a * conf_file_path. * * It is also possible to override the values in the resolv.conf and * RES_OPTIONS by giving the directives in the NULL-terminated list. * * @param conf_file_path name of the resolv.conf configuration file  * @param cache          optional pointer to a resolver cache (may be NULL) * @param option, ...    list of resolv.conf options directives  *                       (overriding options in conf_file) * * @par Environment Variables * - #LOCALDOMAIN overrides @c domain or @c search directives * - #RES_OPTIONS overrides values of @a options in resolv.conf * - #SRES_OPTIONS overrides values of @a options in resolv.conf, #RES_OPTIONS, *   and @a options, ... list given as argument for this function * * @return A pointer to a newly created sres resolver object, or NULL upon * an error. */sres_resolver_t *sres_resolver_new_with_cache(char const *conf_file_path,			     sres_cache_t *cache,			     char const *option, ...){  sres_resolver_t *retval;  va_list va;  va_start(va, option);  retval = sres_resolver_new_with_cache_va(conf_file_path, cache, option, va);  va_end(va);  return retval;}/**Create a resolver. * * Allocate and initialize a new sres resolver object.  * * This is a stdarg version of sres_resolver_new_with_cache(). */sres_resolver_t *sres_resolver_new_with_cache_va(char const *conf_file_path,				sres_cache_t *cache,				char const *option,				va_list va){  va_list va0;  size_t i;  char const *o, *oarray[16], **olist = oarray;  sres_resolver_t *res;  va_copy(va0, va);    for (i = 0, o = option; o; o = va_arg(va0, char const *)) {    if (i < 16)      olist[i] = o;    i++;  }  if (i >= 16) {    olist = malloc((i + 1) * sizeof *olist);    if (!olist)      return NULL;    for (i = 0, o = option; o; o = va_arg(va, char const *)) {      olist[i++] = o;      i++;    }  }  olist[i] = NULL;  res = sres_resolver_new_internal(cache, NULL, conf_file_path, olist);  if (olist != oarray)    free(olist);  return res;}sres_resolver_t *sres_resolver_new_internal(sres_cache_t *cache,			   sres_config_t const *config,			   char const *conf_file_path,			   char const **options){  sres_resolver_t *res;  size_t i, n, len;  char **array, *o, *end;   for (n = 0, len = 0; options && options[n]; n++)    len += strlen(options[n]) + 1;  res = su_home_new(sizeof(*res) + (n + 1) * (sizeof *options) + len);  if (res == NULL)    return NULL;  array = (void *)(res + 1);  o = (void *)(array + n + 1);  end = o + len;  for (i = 0; options && options[i]; i++)    o = memccpy(array[i] = o, options[i], '\0', len - (end - o));  assert(o == end);  su_home_destructor(res->res_home, sres_resolver_destructor);  while (res->res_id == 0) {#if HAVE_DEV_URANDOM    int fd;    if ((fd = open("/dev/urandom", O_RDONLY, 0)) != -1) {      size_t len = read(fd, &res->res_id, (sizeof res->res_id)); (void)len;      close(fd);    }    else#endif    res->res_id = time(NULL);  }  time(&res->res_now);  if (cache)    res->res_cache = sres_cache_ref(cache);  else    res->res_cache = sres_cache_new(0);  res->res_config = config;  if (conf_file_path && conf_file_path != sres_conf_file_path)    res->res_cnffile = su_strdup(res->res_home, conf_file_path);  else    res->res_cnffile = conf_file_path = sres_conf_file_path;  if (!res->res_cache || !res->res_cnffile) {    perror("sres: malloc");  }  else if (sres_qtable_resize(res->res_home, res->res_queries, 0) < 0) {    perror("sres: res_qtable_resize");  }  else if (sres_resolver_update(res, config == NULL) < 0) {    perror("sres: sres_resolver_update");  }  else {    return res;  }  sres_resolver_unref(res);  return NULL;}/** Increase reference count on a resolver object. */sres_resolver_t *sres_resolver_ref(sres_resolver_t *res){  return su_home_ref(res->res_home);}		     /** Decrease the reference count on a resolver object.  */voidsres_resolver_unref(sres_resolver_t *res){  su_home_unref(res->res_home);}/** Set userdata pointer. * * @return New userdata pointer. *  * @ERRORS * @ERROR EFAULT @a res points outside the address space */void *sres_resolver_set_userdata(sres_resolver_t *res, 			   void *userdata){  void *old;  if (!res)    return su_seterrno(EFAULT), (void *)NULL;  old = res->res_userdata, res->res_userdata = userdata;  return old;}/**Get userdata pointer. * * @return Userdata pointer. *  * @ERRORS * @ERROR EFAULT @a res points outside the address space */void *sres_resolver_get_userdata(sres_resolver_t const *res){  if (res == NULL)    return su_seterrno(EFAULT), (void *)NULL;  else    return res->res_userdata;}/** Set async object. * * @return Set async object. *  * @ERRORS * @ERROR EFAULT @a res points outside the address space * @ERROR EALREADY different async callback already set */sres_async_t *sres_resolver_set_async(sres_resolver_t *res,			sres_update_f *callback,			sres_async_t *async, 			int update_all){  if (!res)    return su_seterrno(EFAULT), (void *)NULL;  if (res->res_updcb && res->res_updcb != callback)    return su_seterrno(EALREADY), (void *)NULL;      res->res_async = async;  res->res_updcb = callback;  res->res_update_all = callback && update_all != 0;  return async;}/** Get async object */sres_async_t *sres_resolver_get_async(sres_resolver_t const *res,			sres_update_f *callback){  if (res == NULL)    return su_seterrno(EFAULT), (void *)NULL;  else if (callback == NULL)    return res->res_async ? (sres_async_t *)-1 : 0;  else if (res->res_updcb != callback)    return NULL;  else    return res->res_async;}/** Register resolver timer callback. */int sres_resolver_set_timer_cb(sres_resolver_t *res,			       sres_schedule_f *callback,			       sres_async_t *async){  if (res == NULL)    return su_seterrno(EFAULT);  if (res->res_async != async)    return su_seterrno(EALREADY);  res->res_schedulecb = callback;  return 0;}/**Send a DNS query. * * Sends a DNS query with specified @a type and @a domain to the DNS server. * When an answer is received, the @a callback function is called with * @a context and returned records as arguments. * * 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 (see #sres_qtypes) * @param domain name to query * * Query types also indicate the record type of the result. * Any record can be queried with #sres_qtype_any. * Well-known query types understood and decoded by @b sres include * #sres_type_a,  * #sres_type_aaaa, * #sres_type_cname, * #sres_type_ptr  * #sres_type_soa,  * #sres_type_aaaa,  * #sres_type_srv, and * #sres_type_naptr. * * Deprecated query type #sres_type_a6 is also decoded. * * @note The domain name is @b not concatenated with the domains from seach * path or with the local domain. Use sres_search() in order to try domains * in search path. * * @sa sres_search(), sres_blocking_query(), sres_cached_answers(), * sres_query_sockaddr() * * @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 */sres_query_t *sres_query(sres_resolver_t *res,	   sres_answer_f *callback,	   sres_context_t *context,	   uint16_t type,	   char const *domain){  sres_query_t *query = NULL;  size_t dlen;    char b[8];  SU_DEBUG_9(("sres_query(%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;  }  /* Reread resolv.conf if needed */  sres_resolver_update(res, 0);  if (res->res_n_servers == 0)

⌨️ 快捷键说明

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