コード例 #1
0
ファイル: mkalias.c プロジェクト: ajinkya93/OpenBSD
static int
check_host(char *address, size_t len, char *host, int dflag, int uflag, int Eflag)
{
	union {
		HEADER hdr;
		u_char buf[PACKETSZ];
	} answer;
	int  status;

	if ((dflag && memchr(address, '@', len)) ||
	    (uflag && memchr(address, '!', len)))
		return(0);

	if ((_res.options & RES_INIT) == 0)
		res_init();

	status = res_search(host, C_IN, T_AAAA, answer.buf, sizeof(answer.buf));

	if (status == -1)
		status = res_search(host, C_IN, T_A, answer.buf, sizeof(answer.buf));

	if (status == -1 && Eflag)
		status = res_search(host, C_IN, T_MX, answer.buf, sizeof(answer.buf));

	return(status == -1);
}
コード例 #2
0
ファイル: base-dns.cpp プロジェクト: danposch/NFD
/**
 * @brief Send DNS SRV request using search domain list
 */
std::string
BaseDns::querySrvRrSearch()
{
  std::cerr << "Sending DNS query for SRV record for _ndn._udp" << std::endl;

  QueryAnswer queryAnswer;

  res_init();

  _res.retrans = 1;
  _res.retry = 2;
  _res.ndots = 10;

  int answerSize = res_search("_ndn._udp",
                              ns_c_in,
                              ns_t_srv,
                              queryAnswer.buf,
                              sizeof(queryAnswer));

  if (answerSize == 0) {
    throw Error("No DNS SRV records found for _ndn._udp");
  }

  return parseSrvRr(queryAnswer, answerSize);
}
コード例 #3
0
ファイル: network.c プロジェクト: 96Levels/roadsend-php
int php_checkdnsrr(char *host, char *typestr) {
#ifdef PCC_MINGW
  return -1;
#else
   unsigned char answer[MAXPACKET];
   int type = T_MX;

   if (strcasecmp(typestr, "MX") == 0)
      type = T_MX;
   else if (strcasecmp(typestr, "A") == 0)
      type = T_A;
   else if (strcasecmp(typestr, "NS") == 0)
      type = T_NS;
   else if (strcasecmp(typestr, "PTR") == 0)
      type = T_PTR;
   else if (strcasecmp(typestr, "ANY") == 0)
      type = T_ANY;
   else if (strcasecmp(typestr, "SOA") == 0)
      type = T_SOA;
   else if (strcasecmp(typestr, "CNAME") == 0)
      type = T_CNAME;
   else
      return -1;
      
   return res_search(host, C_IN, type, answer, MAXPACKET);
#endif /* PCC_MINGW */
}
コード例 #4
0
ファイル: mkalias.c プロジェクト: ryo/netbsd-src
static int
check_host(char *address, char *host, int dflag, int uflag, int Eflag)
{
	u_char answer[PACKETSZ];
	int  status;

	if ((dflag && strchr(address, '@')) ||
	    (uflag && strchr(address, '!')))
		return(0);

	if ((_res.options & RES_INIT) == 0)
		res_init();

	status = res_search(host, C_IN, T_AAAA, answer, sizeof(answer));

	if (status == -1)
		status = res_search(host, C_IN, T_A, answer, sizeof(answer));

	if ((status == -1) && Eflag)
		status = res_search(host, C_IN, T_MX, answer, sizeof(answer));

	return(status == -1);
}
コード例 #5
0
void* fn(void* arg)
{
    char* dn = (char*)arg;

    unsigned char buff[8000];

    if(-1 == res_search(dn, 1, 1, buff, 8000))
    {
        printf("Error: res_search()\n");
    }
    else
    {
        printf("Success!\n");
    }
    return 0;
}
コード例 #6
0
ファイル: network.c プロジェクト: 96Levels/roadsend-php
int php_getmxrr(char *hostname, char *mx_list, char *weight_list) {
#ifdef PCC_MINGW
  return 0;
#else

   char *mx_list_ptr = (char *)(mx_list + sprintf(mx_list, ""));
   char *weight_list_ptr = (char *)(weight_list + sprintf(weight_list, ""));
   unsigned char answer[MAXPACKET];
   unsigned char expand_buffer[MAXHOSTNAMELEN];
   int ans_len = res_search(hostname, C_IN, T_MX, answer, sizeof(answer));
   HEADER *header_ptr = (HEADER *)&answer;
   unsigned char *body_ptr = (unsigned char *)&answer + NS_HFIXEDSZ;
   unsigned char *eom_ptr = (unsigned char *)&answer + sizeof(answer);
   int n, ancount, qdcount, type, weight;
   
   for (qdcount = ntohs((unsigned short)header_ptr->qdcount); qdcount--; body_ptr += (n + NS_QFIXEDSZ))
      if ((n = dn_skipname(body_ptr, eom_ptr)) < 0)
         return -1;

   ancount = ntohs((unsigned short)header_ptr->ancount);
   while (--ancount >= 0 && body_ptr < eom_ptr) {
      if ((n = dn_skipname(body_ptr, eom_ptr)) < 0)
	 return -1;
      body_ptr += n;
      NS_GET16(type, body_ptr);
      body_ptr += (NS_INT16SZ + NS_INT32SZ);
      NS_GET16(n, body_ptr);
      if (type != T_MX) {
 	 body_ptr += n;
	 continue;
      }
      NS_GET16(weight, body_ptr);
      if ((n = dn_expand(answer, eom_ptr, body_ptr, expand_buffer, sizeof(expand_buffer) - 1)) < 0)
	 return -1;
      body_ptr += n;
      mx_list_ptr += sprintf(mx_list_ptr - 1, " %s  ", expand_buffer);
      weight_list_ptr += sprintf(weight_list_ptr - 1, " %d ", weight);
   }
   return 0;
#endif /* PCC_MINGW */
}
コード例 #7
0
int main(int argc, char** argv)
{
    pthread_t pid;
    if(2 != argc)
    {
        printf("Usage: %s <domain>\n", argv[0]);
        return 1;
    }

    _res.options |= RES_DEBUG;
    if(0 != res_init())
    {
        printf("Error: res_init()\n");
        return(1);
    }
#if 1
    
    if(0 != pthread_create(&pid, 0, fn, (void*)argv[1]))
    {
        printf("Failed to create thread.\n");
        return 1;
    }

    pthread_join(pid, 0);
#else
    {
    unsigned char buff[8000];

    if(-1 == res_search(argv[1], 1, 1, buff, 8000))
    {
        printf("Error: res_search()\n");
    }
    else
    {
        printf("Success!\n");
    }
    }
#endif
    return 0;
}
コード例 #8
0
ファイル: resolve.c プロジェクト: miao606/kamailio
/* gets the DNS records for name:type
 * returns a dyn. alloc'ed struct rdata linked list with the parsed responses
 * or 0 on error
 * see rfc1035 for the query/response format */
struct rdata* get_record(char* name, int type, int flags)
{
	int size;
	int skip;
	int qno, answers_no;
	int i, r;
	static union dns_query buff;
	unsigned char* p;
	unsigned char* end;
	unsigned char* rd_end;
	static char rec_name[MAX_DNS_NAME]; /* placeholder for the record name */
	int rec_name_len;
	unsigned short rtype, class, rdlength;
	unsigned int ttl;
	struct rdata* head;
	struct rdata** crt;
	struct rdata** last;
	struct rdata* rd;
	struct srv_rdata* srv_rd;
	struct srv_rdata* crt_srv;
	int search_list_used;
	int name_len;
	struct rdata* fullname_rd;
	char c;
	
#ifdef USE_DNSSEC
	val_status_t val_status;
#endif

	name_len=strlen(name);

	for (i = 0; i < name_len; i++) {
	    c = name[i];
	    if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) ||
		((c >= '0') && (c <= '9')) || (name[i] == '.') ||
		(name[i] == '-') || (name[i] == '_'))
			continue;
	    LM_DBG("'%s' is not domain name\n", name);
	    return 0;
	}

	if (cfg_get(core, core_cfg, dns_search_list)==0) {
		search_list_used=0;
		name_len=0;
	} else {
		search_list_used=1;
	}
	fullname_rd=0;

#ifndef USE_DNSSEC
	size=res_search(name, C_IN, type, buff.buff, sizeof(buff));
#else
	size=val_res_query((val_context_t *) NULL,
                      (char *) name, 
                      (int) C_IN,
		      (int) type, 
                      (unsigned char *) buff.buff, 
		      (int) sizeof(buff),
                      &val_status);	
	if(!val_istrusted(val_status)){
		LOG(L_INFO, "INFO: got not trusted record when resolving %s\n",name);
	}
#endif

	if (unlikely(size<0)) {
		DBG("get_record: lookup(%s, %d) failed\n", name, type);
		goto not_found;
	}
	else if (unlikely(size > sizeof(buff))) size=sizeof(buff);
	head=rd=0;
	last=crt=&head;
	
	p=buff.buff+DNS_HDR_SIZE;
	end=buff.buff+size;
	if (unlikely(p>=end)) goto error_boundary;
	qno=ntohs((unsigned short)buff.hdr.qdcount);

	for (r=0; r<qno; r++){
		/* skip the name of the question */
		if (unlikely((p=dns_skipname(p, end))==0)) {
			LOG(L_ERR, "ERROR: get_record: skipname==0\n");
			goto error;
		}
		p+=2+2; /* skip QCODE & QCLASS */
	#if 0
		for (;(p<end && (*p)); p++);
		p+=1+2+2; /* skip the ending  '\0, QCODE and QCLASS */
	#endif
		if (unlikely(p>end)) {
			LOG(L_ERR, "ERROR: get_record: p>=end\n");
			goto error;
		}
	};
	answers_no=ntohs((unsigned short)buff.hdr.ancount);
again:
	for (r=0; (r<answers_no) && (p<end); r++){
#if 0
		/*  ignore it the default domain name */
		if ((p=dns_skipname(p, end))==0) {
			LOG(L_ERR, "ERROR: get_record: skip_name=0 (#2)\n");
			goto error;
		}
#else
		if (unlikely((skip=dn_expand(buff.buff, end, p, rec_name,
							MAX_DNS_NAME-1))==-1)){
			LOG(L_ERR, "ERROR: get_record: dn_expand(rec_name) failed\n");
			goto error;
		}
#endif
		p+=skip;
		rec_name_len=strlen(rec_name);
		if (unlikely(rec_name_len>255)){
			LOG(L_ERR, "ERROR: get_record: dn_expand(rec_name): name too"
					" long  (%d)\n", rec_name_len);
			goto error;
		}
		/* check if enough space is left for type, class, ttl & size */
		if (unlikely((p+2+2+4+2)>end)) goto error_boundary;
		/* get type */
		memcpy((void*) &rtype, (void*)p, 2);
		rtype=ntohs(rtype);
		p+=2;
		/* get  class */
		memcpy((void*) &class, (void*)p, 2);
		class=ntohs(class);
		p+=2;
		/* get ttl*/
		memcpy((void*) &ttl, (void*)p, 4);
		ttl=ntohl(ttl);
		p+=4;
		/* get size */
		memcpy((void*)&rdlength, (void*)p, 2);
		rdlength=ntohs(rdlength);
		p+=2;
		rd_end=p+rdlength;
		if (unlikely((rd_end)>end)) goto error_boundary;
		if ((flags & RES_ONLY_TYPE) && (rtype!=type)){
			/* skip */
			p=rd_end;
			continue;
		}
		/* expand the "type" record  (rdata)*/
		
		rd=(struct rdata*) local_malloc(sizeof(struct rdata)+rec_name_len+
										1-1);
		if (rd==0){
			LOG(L_ERR, "ERROR: get_record: out of memory\n");
			goto error;
		}
		rd->type=rtype;
		rd->pclass=class;
		rd->ttl=ttl;
		rd->next=0;
		memcpy(rd->name, rec_name, rec_name_len);
		rd->name[rec_name_len]=0;
		rd->name_len=rec_name_len;
		/* check if full name matches */
		if ((search_list_used==1)&&(fullname_rd==0)&&
				(rec_name_len>=name_len)&&
				(strncasecmp(rec_name, name, name_len)==0)) {
			/* now we have record whose name is the same (up-to the
			 * name_len with the searched one):
			 * if the length is the same - we found full match, no fake
			 *  cname needed, just clear the flag
			 * if the length of the name differs - it has matched using
			 *  search list remember the rd, so we can create fake CNAME
			 *  record when all answers are used and no better match found
			 */
			if (rec_name_len==name_len)
				search_list_used=0;
			/* this is safe.... here was rec_name_len > name_len */
			else if (rec_name[name_len]=='.') {
#ifdef HAVE_RESOLV_RES
				if ((cfg_get(core, core_cfg, dns_search_fmatch)==0) ||
						(match_search_list(&_res, rec_name+name_len+1)!=0))
#endif
					fullname_rd=rd;
			}
		}
		switch(rtype){
			case T_SRV:
				srv_rd= dns_srv_parser(buff.buff, end, rd_end, p);
				rd->rdata=(void*)srv_rd;
				if (unlikely(srv_rd==0)) goto error_parse;
				
				/* insert sorted into the list */
				for (crt=&head; *crt; crt= &((*crt)->next)){
					if ((*crt)->type!=T_SRV)
						continue;
					crt_srv=(struct srv_rdata*)(*crt)->rdata;
					if ((srv_rd->priority <  crt_srv->priority) ||
					   ( (srv_rd->priority == crt_srv->priority) && 
							 (srv_rd->weight > crt_srv->weight) ) ){
						/* insert here */
						goto skip;
					}
				}
				last=&(rd->next); /*end of for => this will be the last
									element*/
			skip:
				/* insert here */
				rd->next=*crt;
				*crt=rd;
				break;
			case T_A:
				rd->rdata=(void*) dns_a_parser(p, rd_end);
				if (unlikely(rd->rdata==0)) goto error_parse;
				*last=rd; /* last points to the last "next" or the list
							 	head*/
				last=&(rd->next);
				break;
			case T_AAAA:
				rd->rdata=(void*) dns_aaaa_parser(p, rd_end);
				if (unlikely(rd->rdata==0)) goto error_parse;
				*last=rd;
				last=&(rd->next);
				break;
			case T_CNAME:
				rd->rdata=(void*) dns_cname_parser(buff.buff, end, p);
				if(unlikely(rd->rdata==0)) goto error_parse;
				*last=rd;
				last=&(rd->next);
				break;
			case T_NAPTR:
				rd->rdata=(void*)dns_naptr_parser(buff.buff, end, rd_end, p);
				if(unlikely(rd->rdata==0)) goto error_parse;
				*last=rd;
				last=&(rd->next);
				break;
			case T_TXT:
				rd->rdata= dns_txt_parser(buff.buff, rd_end, p);
				if (rd->rdata==0) goto error_parse;
				*last=rd;
				last=&(rd->next);
				break;
			case T_EBL:
				rd->rdata= dns_ebl_parser(buff.buff, end, rd_end, p);
				if (rd->rdata==0) goto error_parse;
				*last=rd;
				last=&(rd->next);
				break;
			case T_PTR:
				rd->rdata=(void*) dns_ptr_parser(buff.buff, end, p);
				if(unlikely(rd->rdata==0)) goto error_parse;
				*last=rd;
				last=&(rd->next);
				break;
			default:
				LOG(L_ERR, "WARNING: get_record: unknown type %d\n", rtype);
				rd->rdata=0;
				*last=rd;
				last=&(rd->next);
		}
		
		p+=rdlength;
		
	}
	if (flags & RES_AR){
		flags&=~RES_AR;
		answers_no=ntohs((unsigned short)buff.hdr.nscount);
#ifdef RESOLVE_DBG
		DBG("get_record: skipping %d NS (p=%p, end=%p)\n", answers_no, p,
				end);
#endif
		for (r=0; (r<answers_no) && (p<end); r++){
			/* skip over the ns records */
			if ((p=dns_skipname(p, end))==0) {
				LOG(L_ERR, "ERROR: get_record: skip_name=0 (#3)\n");
				goto error;
			}
			/* check if enough space is left for type, class, ttl & size */
			if (unlikely((p+2+2+4+2)>end)) goto error_boundary;
			memcpy((void*)&rdlength, (void*)p+2+2+4, 2);
			p+=2+2+4+2+ntohs(rdlength);
		}
		answers_no=ntohs((unsigned short)buff.hdr.arcount);
#ifdef RESOLVE_DBG
		DBG("get_record: parsing %d ARs (p=%p, end=%p)\n", answers_no, p,
				end);
#endif
		goto again; /* add also the additional records */
	}

	/* if the name was expanded using DNS search list
	 * create fake CNAME record to convert the short name
	 * (queried) to long name (answered)
	 */
	if ((search_list_used==1)&&(fullname_rd!=0)) {
		rd=(struct rdata*) local_malloc(sizeof(struct rdata)+name_len+1-1);
		if (unlikely(rd==0)){
			LOG(L_ERR, "ERROR: get_record: out of memory\n");
			goto error;
		}
		rd->type=T_CNAME;
		rd->pclass=fullname_rd->pclass;
		rd->ttl=fullname_rd->ttl;
		rd->next=head;
		memcpy(rd->name, name, name_len);
		rd->name[name_len]=0;
		rd->name_len=name_len;
		/* alloc sizeof struct + space for the null terminated name */
		rd->rdata=(void*)local_malloc(sizeof(struct cname_rdata)-1+
										head->name_len+1);
		if(unlikely(rd->rdata==0)){
			LOG(L_ERR, "ERROR: get_record: out of memory\n");
			goto error_rd;
		}
		((struct cname_rdata*)(rd->rdata))->name_len=fullname_rd->name_len;
		memcpy(((struct cname_rdata*)(rd->rdata))->name, fullname_rd->name,
				fullname_rd->name_len);
		((struct cname_rdata*)(rd->rdata))->name[head->name_len]=0;
		head=rd;
	}

	return head;
error_boundary:
		LOG(L_ERR, "ERROR: get_record: end of query buff reached\n");
		if (head) free_rdata_list(head);
		return 0;
error_parse:
		LOG(L_ERR, "ERROR: get_record: rdata parse error (%s, %d), %p-%p"
						" rtype=%d, class=%d, ttl=%d, rdlength=%d \n",
				name, type,
				p, end, rtype, class, ttl, rdlength);
error_rd:
		if (rd) local_free(rd); /* rd->rdata=0 & rd is not linked yet into
								   the list */
error:
		LOG(L_ERR, "ERROR: get_record \n");
		if (head) free_rdata_list(head);
not_found:
	/* increment error counter */
	counter_inc(dns_cnts_h.failed_dns_req);
	return 0;
}
コード例 #9
0
ファイル: dns.c プロジェクト: bond/dma
int
dns_get_mx_list(const char *host, int port, struct mx_hostentry **he, int no_mx)
{
	char outname[MAXDNAME];
	ns_msg msg;
	ns_rr rr;
	const char *searchhost;
	const unsigned char *cp;
	unsigned char *ans;
	struct mx_hostentry *hosts = NULL;
	size_t nhosts = 0;
	size_t anssz;
	int pref;
	int cname_recurse;
	int err;
	int i;

	res_init();
	searchhost = host;
	cname_recurse = 0;

	anssz = 65536;
	ans = malloc(anssz);
	if (ans == NULL)
		return (1);

	if (no_mx)
		goto out;

repeat:
	err = res_search(searchhost, ns_c_in, ns_t_mx, ans, anssz);
	if (err < 0) {
		switch (h_errno) {
		case NO_DATA:
			/*
			 * Host exists, but no MX (or CNAME) entry.
			 * Not an error, use host name instead.
			 */
			goto out;
		case TRY_AGAIN:
			/* transient error */
			goto transerr;
		case NO_RECOVERY:
		case HOST_NOT_FOUND:
		default:
			errno = ENOENT;
			goto err;
		}
	}

	if (!ns_initparse(ans, anssz, &msg))
		goto transerr;

	switch (ns_msg_getflag(msg, ns_f_rcode)) {
	case ns_r_noerror:
		break;
	case ns_r_nxdomain:
		goto err;
	default:
		goto transerr;
	}

	for (i = 0; i < ns_msg_count(msg, ns_s_an); i++) {
		if (ns_parserr(&msg, ns_s_an, i, &rr))
			goto transerr;

		cp = ns_rr_rdata(rr);

		switch (ns_rr_type(rr)) {
		case ns_t_mx:
			pref = ns_get16(cp);
			cp += 2;
			err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
						 cp, outname, sizeof(outname));
			if (err < 0)
				goto transerr;

			add_host(pref, outname, port, &hosts, &nhosts);
			break;

		case ns_t_cname:
			err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
						 cp, outname, sizeof(outname));
			if (err < 0)
				goto transerr;

			/* Prevent a CNAME loop */
			if (cname_recurse++ > 10)
				goto err;

			searchhost = outname;
			goto repeat;

		default:
			break;
		}
	}

out:
	err = 0;
	if (0) {
transerr:
		if (nhosts == 0)
			err = 1;
	}
	if (0) {
err:
		err = -1;
	}

	free(ans);

	if (!err) {
		/*
		 * If we didn't find any MX, use the hostname instead.
		 */
		if (nhosts == 0)
			add_host(0, searchhost, port, &hosts, &nhosts);

		qsort(hosts, nhosts, sizeof(*hosts), sort_pref);
	}

	if (nhosts > 0) {
		/* terminate list */
		*hosts[nhosts].host = 0;
	} else {
		if (hosts != NULL)
			free(hosts);
		hosts = NULL;
	}

	*he = hosts;
	return (err);

	free(ans);
	if (hosts != NULL)
		free(hosts);
	return (err);
}
コード例 #10
0
ファイル: dns.c プロジェクト: loganaden/exim
int
dns_basic_lookup(dns_answer *dnsa, const uschar *name, int type)
{
#ifndef STAND_ALONE
int rc = -1;
const uschar *save_domain;
#endif
res_state resp = os_get_dns_resolver_res();

tree_node *previous;
uschar node_name[290];

/* DNS lookup failures of any kind are cached in a tree. This is mainly so that
a timeout on one domain doesn't happen time and time again for messages that
have many addresses in the same domain. We rely on the resolver and name server
caching for successful lookups. */

sprintf(CS node_name, "%.255s-%s-%lx", name, dns_text_type(type),
  resp->options);
previous = tree_search(tree_dns_fails, node_name);
if (previous != NULL)
  {
  DEBUG(D_dns) debug_printf("DNS lookup of %.255s-%s: using cached value %s\n",
    name, dns_text_type(type),
      (previous->data.val == DNS_NOMATCH)? "DNS_NOMATCH" :
      (previous->data.val == DNS_NODATA)? "DNS_NODATA" :
      (previous->data.val == DNS_AGAIN)? "DNS_AGAIN" :
      (previous->data.val == DNS_FAIL)? "DNS_FAIL" : "??");
  return previous->data.val;
  }

#ifdef EXPERIMENTAL_INTERNATIONAL
/* Convert all names to a-label form before doing lookup */
  {
  uschar * alabel;
  uschar * errstr = NULL;
  DEBUG(D_dns) if (string_is_utf8(name))
    debug_printf("convert utf8 '%s' to alabel for for lookup\n", name);
  if ((alabel = string_domain_utf8_to_alabel(name, &errstr)), errstr)
    {
    DEBUG(D_dns)
      debug_printf("DNS name '%s' utf8 conversion to alabel failed: %s\n", name,
        errstr);
    host_find_failed_syntax = TRUE;
    return DNS_NOMATCH;
    }
  name = alabel;
  }
#endif

/* If configured, check the hygene of the name passed to lookup. Otherwise,
although DNS lookups may give REFUSED at the lower level, some resolvers
turn this into TRY_AGAIN, which is silly. Give a NOMATCH return, since such
domains cannot be in the DNS. The check is now done by a regular expression;
give it space for substring storage to save it having to get its own if the
regex has substrings that are used - the default uses a conditional.

This test is omitted for PTR records. These occur only in calls from the dnsdb
lookup, which constructs the names itself, so they should be OK. Besides,
bitstring labels don't conform to normal name syntax. (But the aren't used any
more.)

For SRV records, we omit the initial _smtp._tcp. components at the start. */

#ifndef STAND_ALONE   /* Omit this for stand-alone tests */

if (check_dns_names_pattern[0] != 0 && type != T_PTR && type != T_TXT)
  {
  const uschar *checkname = name;
  int ovector[3*(EXPAND_MAXN+1)];

  dns_pattern_init();

  /* For an SRV lookup, skip over the first two components (the service and
  protocol names, which both start with an underscore). */

  if (type == T_SRV || type == T_TLSA)
    {
    while (*checkname++ != '.');
    while (*checkname++ != '.');
    }

  if (pcre_exec(regex_check_dns_names, NULL, CCS checkname, Ustrlen(checkname),
      0, PCRE_EOPT, ovector, sizeof(ovector)/sizeof(int)) < 0)
    {
    DEBUG(D_dns)
      debug_printf("DNS name syntax check failed: %s (%s)\n", name,
        dns_text_type(type));
    host_find_failed_syntax = TRUE;
    return DNS_NOMATCH;
    }
  }

#endif /* STAND_ALONE */

/* Call the resolver; for an overlong response, res_search() will return the
number of bytes the message would need, so we need to check for this case. The
effect is to truncate overlong data.

On some systems, res_search() will recognize "A-for-A" queries and return
the IP address instead of returning -1 with h_error=HOST_NOT_FOUND. Some
nameservers are also believed to do this. It is, of course, contrary to the
specification of the DNS, so we lock it out. */

if ((type == T_A || type == T_AAAA) && string_is_ip_address(name, NULL) != 0)
  return DNS_NOMATCH;

/* If we are running in the test harness, instead of calling the normal resolver
(res_search), we call fakens_search(), which recognizes certain special
domains, and interfaces to a fake nameserver for certain special zones. */

dnsa->answerlen = running_in_test_harness
  ? fakens_search(name, type, dnsa->answer, MAXPACKET)
  : res_search(CCS name, C_IN, type, dnsa->answer, MAXPACKET);

if (dnsa->answerlen > MAXPACKET)
  {
  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) resulted in overlong packet (size %d), truncating to %d.\n",
    name, dns_text_type(type), dnsa->answerlen, MAXPACKET);
  dnsa->answerlen = MAXPACKET;
  }

if (dnsa->answerlen < 0) switch (h_errno)
  {
  case HOST_NOT_FOUND:
  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave HOST_NOT_FOUND\n"
    "returning DNS_NOMATCH\n", name, dns_text_type(type));
  return dns_return(name, type, DNS_NOMATCH);

  case TRY_AGAIN:
  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave TRY_AGAIN\n",
    name, dns_text_type(type));

  /* Cut this out for various test programs */
#ifndef STAND_ALONE
  save_domain = deliver_domain;
  deliver_domain = string_copy(name);  /* set $domain */
  rc = match_isinlist(name, (const uschar **)&dns_again_means_nonexist, 0, NULL, NULL,
    MCL_DOMAIN, TRUE, NULL);
  deliver_domain = save_domain;
  if (rc != OK)
    {
    DEBUG(D_dns) debug_printf("returning DNS_AGAIN\n");
    return dns_return(name, type, DNS_AGAIN);
    }
  DEBUG(D_dns) debug_printf("%s is in dns_again_means_nonexist: returning "
    "DNS_NOMATCH\n", name);
  return dns_return(name, type, DNS_NOMATCH);

#else   /* For stand-alone tests */
  return dns_return(name, type, DNS_AGAIN);
#endif

  case NO_RECOVERY:
  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave NO_RECOVERY\n"
    "returning DNS_FAIL\n", name, dns_text_type(type));
  return dns_return(name, type, DNS_FAIL);

  case NO_DATA:
  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave NO_DATA\n"
    "returning DNS_NODATA\n", name, dns_text_type(type));
  return dns_return(name, type, DNS_NODATA);

  default:
  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) gave unknown DNS error %d\n"
    "returning DNS_FAIL\n", name, dns_text_type(type), h_errno);
  return dns_return(name, type, DNS_FAIL);
  }

DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) succeeded\n",
  name, dns_text_type(type));

return DNS_SUCCEED;
}
コード例 #11
0
ファイル: dnsglue.c プロジェクト: Baalmart/krb5
/*
 * krb5int_dns_init()
 *
 * Initialize an opaque handle.  Do name lookup and initial parsing of
 * reply, skipping question section.  Prepare to iterate over answer
 * section.  Returns -1 on error, 0 on success.
 */
int
krb5int_dns_init(struct krb5int_dns_state **dsp,
                 char *host, int nclass, int ntype)
{
#if USE_RES_NINIT
    struct __res_state statbuf;
#endif
    struct krb5int_dns_state *ds;
    int len, ret;
    size_t nextincr, maxincr;
    unsigned char *p;

    *dsp = ds = malloc(sizeof(*ds));
    if (ds == NULL)
        return -1;

    ret = -1;
    ds->nclass = nclass;
    ds->ntype = ntype;
    ds->ansp = NULL;
    ds->anslen = 0;
    ds->ansmax = 0;
    nextincr = 2048;
    maxincr = INT_MAX;

#if HAVE_NS_INITPARSE
    ds->cur_ans = 0;
#endif

#if USE_RES_NINIT
    memset(&statbuf, 0, sizeof(statbuf));
    ret = res_ninit(&statbuf);
#else
    ret = res_init();
#endif
    if (ret < 0)
        return -1;

    do {
        p = (ds->ansp == NULL)
            ? malloc(nextincr) : realloc(ds->ansp, nextincr);

        if (p == NULL) {
            ret = -1;
            goto errout;
        }
        ds->ansp = p;
        ds->ansmax = nextincr;

#if USE_RES_NINIT
        len = res_nsearch(&statbuf, host, ds->nclass, ds->ntype,
                          ds->ansp, ds->ansmax);
#else
        len = res_search(host, ds->nclass, ds->ntype,
                         ds->ansp, ds->ansmax);
#endif
        if ((size_t) len > maxincr) {
            ret = -1;
            goto errout;
        }
        while (nextincr < (size_t) len)
            nextincr *= 2;
        if (len < 0 || nextincr > maxincr) {
            ret = -1;
            goto errout;
        }
    } while (len > ds->ansmax);

    ds->anslen = len;
#if HAVE_NS_INITPARSE
    ret = ns_initparse(ds->ansp, ds->anslen, &ds->msg);
#else
    ret = initparse(ds);
#endif
    if (ret < 0)
        goto errout;

    ret = 0;

errout:
#if USE_RES_NINIT
    res_ndestroy(&statbuf);
#endif
    if (ret < 0) {
        if (ds->ansp != NULL) {
            free(ds->ansp);
            ds->ansp = NULL;
        }
    }

    return ret;
}
コード例 #12
0
ファイル: dns.c プロジェクト: dancahill/nsp
static int dns_lookup(nsp_state *N, obj_t *tobj, const char *domain)
{
#define __FN__ __FILE__ ":dns_lookup()"
#ifdef WIN32
	DNS_FREE_TYPE freetype;
	DNS_STATUS status;
	PDNS_RECORD pDnsRecord;
	PDNS_RECORD pDnsCur;
	obj_t *stobj;
	IN_ADDR ipaddr;
	char namebuf[8];
	register int i;

	freetype = DnsFreeRecordListDeep;
	/* status=DnsQuery_A(domain, DNS_TYPE_ANY, DNS_QUERY_STANDARD, NULL, &pDnsRecord, NULL); */
	status = DnsQuery_A(domain, DNS_TYPE_ANY, DNS_QUERY_BYPASS_CACHE, NULL, &pDnsRecord, NULL);
	if (status) {
		if (N->debug) n_warn(N, __FN__, "res_search failed");
		return -1;
	}
	/* Loop through the answer buffer and extract records. */
	i = 0;
	pDnsCur = pDnsRecord;
	while (pDnsCur != NULL) {
		stobj = nsp_settable(N, tobj, n_ntoa(N, namebuf, i, 10, 0));
		switch (pDnsCur->wType) {
		case DNS_TYPE_A: {
			ipaddr.S_un.S_addr = (pDnsCur->Data.A.IpAddress);
			nsp_setstr(N, stobj, "type", "A", -1);
			nsp_setstr(N, stobj, "host", pDnsCur->pName, -1);
			nsp_setstr(N, stobj, "addr", inet_ntoa(ipaddr), -1);
			if (N->debug) n_warn(N, __FN__, "A  [%s]", inet_ntoa(ipaddr));
			break;
		}
		case DNS_TYPE_NS: {
			nsp_setstr(N, stobj, "type", "NS", -1);
			/* is PTR the right struct? */
			nsp_setstr(N, stobj, "host", pDnsCur->Data.PTR.pNameHost, -1);
			if (N->debug) n_warn(N, __FN__, "NS [%s]", pDnsCur->Data.PTR.pNameHost);
			break;
		}
		case DNS_TYPE_SOA: {
			nsp_setstr(N, stobj, "type", "SOA", -1);
			nsp_setstr(N, stobj, "host", pDnsCur->Data.SOA.pNamePrimaryServer, -1);
			nsp_setstr(N, stobj, "mail", pDnsCur->Data.SOA.pNameAdministrator, -1);
			nsp_setnum(N, stobj, "serial", pDnsCur->Data.SOA.dwSerialNo);
			nsp_setnum(N, stobj, "refresh", pDnsCur->Data.SOA.dwRefresh);
			nsp_setnum(N, stobj, "retry", pDnsCur->Data.SOA.dwRetry);
			nsp_setnum(N, stobj, "expire", pDnsCur->Data.SOA.dwExpire);
			nsp_setnum(N, stobj, "minttl", pDnsCur->Data.SOA.dwDefaultTtl);
			break;
		}
		case DNS_TYPE_PTR: {
			nsp_setstr(N, stobj, "type", "PTR", -1);
			nsp_setstr(N, stobj, "host", pDnsCur->Data.PTR.pNameHost, -1);
			if (N->debug) n_warn(N, __FN__, "PTR [%s]", pDnsCur->Data.PTR.pNameHost);
			break;
		}
		case DNS_TYPE_MX: {
			nsp_setstr(N, stobj, "type", "MX", -1);
			nsp_setnum(N, stobj, "pref", pDnsCur->Data.MX.wPreference);
			nsp_setstr(N, stobj, "host", pDnsCur->Data.MX.pNameExchange, -1);
			if (N->debug) n_warn(N, __FN__, "MX [%s]", pDnsCur->Data.MX.pNameExchange);
			break;
		}
		default: {
			/* skip data we're too dumb to parse */
			nsp_setnum(N, stobj, "type", pDnsCur->wType);
			/* if (N->debug) */ n_warn(N, __FN__, "xx[%d]", pDnsCur->wType);
			break;
		}
		}
		i++;
		pDnsCur = pDnsCur->pNext;
	}
	DnsRecordListFree(pDnsRecord, freetype);
	return 0;
#else
	char hostbuf[HOSTBUF + 1];
	char abuf[20];
	char namebuf[8];
	querybuf answer;
	HEADER *hp;
	int ancount, qdcount;
	uchar *msg, *eom, *cp;
	//int type, class, ttl, dlen;
	int type, dlen;
	unsigned short pref;
	register int i;
	register int n;
	uchar *e;
	obj_t *stobj;

	/* Query the nameserver to retrieve mx records for the given domain. */
	n = res_search(domain, C_ANY, T_ANY, (u_char *)&answer, sizeof(answer));
	if (n < 0) {
		if (N->debug) n_warn(N, __FN__, "res_search failed");
		return -1;
	}
	if (n < HFIXEDSZ) return -1;
	/* avoid problems after truncation in tcp packets */
	if (n > (int)sizeof(answer)) n = (int)sizeof(answer);
	/* Valid answer received. Skip the query record. */
	hp = (HEADER *)&answer;
	qdcount = ntohs((u_short)hp->qdcount);
	ancount = ntohs((u_short)hp->ancount);
	msg = (u_char *)&answer;
	eom = (u_char *)&answer + n;
	cp = (u_char *)&answer + HFIXEDSZ;
	while (qdcount-->0 && cp < eom) {
		n = dn_skipname(cp, eom);
		if (n < 0) return -1;
		cp += n;
		cp += QFIXEDSZ;
	}
	/* Loop through the answer buffer and extract records. */
	i = 0;
	memset(hostbuf, 0, sizeof(hostbuf));
	while (ancount-->0 && cp < eom) {
		stobj = nsp_settable(N, tobj, n_ntoa(N, namebuf, i, 10, 0));
		if ((n = dn_expand(msg, eom, cp, hostbuf, HOSTBUF)) < 0) break;
		if (N->debug) n_warn(N, __FN__, "?[%s]", hostbuf);
		cp += n;
		GETSHORT(type, cp);
		//		GETSHORT(class, cp);
		//		GETLONG(ttl, cp);
		GETSHORT(dlen, cp);
		e = cp + dlen;
		switch (type) {
		case T_A: {
			snprintf(abuf, sizeof(abuf), "%d.%d.%d.%d", (int)cp[0], (int)cp[1], (int)cp[2], (int)cp[3]);
			nsp_setstr(N, stobj, "type", "A", -1);
			nsp_setstr(N, stobj, "host", hostbuf, -1);
			nsp_setstr(N, stobj, "addr", abuf, -1);
			if (N->debug) n_warn(N, __FN__, "A  [%s]", abuf);
			cp += dlen;
			break;
		}
		case T_NS: {
			if ((n = dn_expand(msg, eom, cp, hostbuf, HOSTBUF)) < 0) return -1;
			cp += n;
			n = strlen(hostbuf);
			nsp_setstr(N, stobj, "type", "NS", -1);
			nsp_setstr(N, stobj, "host", hostbuf, n);
			if (N->debug) n_warn(N, __FN__, "NS [%s]", hostbuf);
			break;
		}
		case T_SOA: {
			unsigned int n;

			nsp_setstr(N, stobj, "type", "SOA", -1);
			if ((n = dn_expand(msg, eom, cp, hostbuf, HOSTBUF)) < 0) return -1;
			cp += n;
			nsp_setstr(N, stobj, "host", hostbuf, -1);
			if ((n = dn_expand(msg, eom, cp, hostbuf, HOSTBUF)) < 0) return -1;
			cp += n;
			nsp_setstr(N, stobj, "mail", hostbuf, -1);
			GETLONG(n, cp); nsp_setnum(N, stobj, "serial", n);
			GETLONG(n, cp); nsp_setnum(N, stobj, "refresh", n);
			GETLONG(n, cp); nsp_setnum(N, stobj, "retry", n);
			GETLONG(n, cp); nsp_setnum(N, stobj, "expire", n);
			GETLONG(n, cp); nsp_setnum(N, stobj, "minttl", n);
			break;
		}
		case T_PTR: {
			if ((n = dn_expand(msg, eom, cp, hostbuf, HOSTBUF)) < 0) return -1;
			cp += n;
			n = strlen(hostbuf);
			nsp_setstr(N, stobj, "type", "PTR", -1);
			nsp_setstr(N, stobj, "host", hostbuf, n);
			if (N->debug) n_warn(N, __FN__, "PTR [%s]", hostbuf);
			break;
		}
		case T_MX: {
			GETSHORT(pref, cp);
			if ((n = dn_expand(msg, eom, cp, hostbuf, HOSTBUF)) < 0) return -1;
			cp += n;
			n = strlen(hostbuf);
			nsp_setstr(N, stobj, "type", "MX", -1);
			nsp_setnum(N, stobj, "pref", pref);
			nsp_setstr(N, stobj, "host", hostbuf, n);
			if (N->debug) n_warn(N, __FN__, "MX [%s]", hostbuf);
			break;
		}
		default: {
			/* skip data we're too dumb to parse */
			nsp_setnum(N, stobj, "type", type);
			/* if (N->debug) */ n_warn(N, __FN__, "xx[%d]", type);
			cp += dlen;
			break;
		}
		}
		i++;
		if (cp != e) n_warn(N, __FN__, "SOA[%d %d]", cp, e);
		cp = e;
	}
#endif
	return 0;
#undef __FN__
}
コード例 #13
0
ファイル: srv_gai.c プロジェクト: besco/binkd
int srv_getaddrinfo(const char *node, const char *service,
		    const struct addrinfo *hints,
		    struct addrinfo **res)
{
    char *srv_name;
    size_t srv_name_size;
    char tgt_port[6];
#ifdef WIN32
    PDNS_RECORD resp, entry;
    char *tgt_name;
#else
    char tgt_name[BINKD_FQDNLEN + 1];
    unsigned char resp[SRVGAI_DNSRESPLEN];
    ns_msg nsb;
    ns_rr rrb;
    int rlen, i, rrlen;
    const unsigned char *p;
    struct in_addr dummy_addr;
#endif
    int rc;
    struct addrinfo *ai, **ai_last = res;

    /* we need sensible information for all parameters */
    if (!node || (node && !*node) || !service || (service && !*service) ||
	    !hints || !res)
	return getaddrinfo(node, service, hints, res);

    /* only domain names are supported */
    if (hints->ai_flags & AI_NUMERICHOST)
	return getaddrinfo(node, service, hints, res);

    /* detect IP addresses */
    if ((hints->ai_family == AF_INET || hints->ai_family == AF_UNSPEC) && 
#ifdef WIN32
	    inet_addr(node) != INADDR_NONE
#else
	    inet_aton(node, &dummy_addr) != 0
#endif
	    )
	return getaddrinfo(node, service, hints, res);
#ifdef AF_INET6
    if ((hints->ai_family == AF_INET6 || hints->ai_family == AF_UNSPEC) && 
	    strchr(node, ':'))
	return getaddrinfo(node, service, hints, res);
#endif

    /* only named services are supported */
    if ((hints->ai_flags & AI_NUMERICSERV) || *service == '0' ||
	    atoi(service) > 0)
	return getaddrinfo(node, service, hints, res);

    /* only TCP and UDP are supported */
    if (hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != SOCK_DGRAM)
	return getaddrinfo(node, service, hints, res);

    /*              _ <service>           ._  tcp . <node>           \0 */
    srv_name_size = 1 + strlen(service) + 2 + 3 + 1 + strlen(node) + 1;
    srv_name = malloc(srv_name_size);
    if (!srv_name)
	return EAI_MEMORY;

    /* construct domain name for SRV query */
    snprintf(srv_name, srv_name_size, "_%s._%s.%s", service,
	    hints->ai_socktype == SOCK_STREAM ? "tcp" : "udp", node);

#ifdef WIN32
    rc = DnsQuery(srv_name, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &resp, NULL);
#else
    rlen = res_search(srv_name, ns_c_in, ns_t_srv, resp, sizeof(resp));
#endif
    free(srv_name);

    /* fallback if DNS query does not return a single entry */
#ifdef WIN32
    if (rc != ERROR_SUCCESS)
#else
    if (rlen < 1)
#endif
	return getaddrinfo(node, service, hints, res);

#ifndef WIN32
    /* fallback in case we cannot parse the response */
    if (ns_initparse(resp, rlen, &nsb) < 0)
	return getaddrinfo(node, service, hints, res);
#endif

    /* iterate through result set -- might be incomplete */
#ifdef WIN32
    for (entry = resp; entry != NULL; entry = entry->pNext) {
	switch (entry->wType) {
	case DNS_TYPE_SRV:
	    snprintf(tgt_port, sizeof(tgt_port), "%d", entry->Data.SRV.wPort);
	    tgt_name = entry->Data.SRV.pNameTarget;
#else
    for (i = 0; i < ns_msg_count(nsb, ns_s_an); i++) {
	rc = ns_parserr(&nsb, ns_s_an, i, &rrb);
	if (rc < 0)
	    continue;

	if (ns_rr_class(rrb) != ns_c_in)
	    continue;

	switch (ns_rr_type(rrb)) {
	case ns_t_srv:
	    rrlen = ns_rr_rdlen(rrb);
	    if (rrlen < 8)	/* 2+2+2 and at least 2 for host */
		break;

	    /* extract host and port */
	    p = ns_rr_rdata(rrb);
	    rc = dn_expand(resp, resp+rlen, p+6, tgt_name, sizeof(tgt_name));
	    if (rc < 2)
		break;
	    snprintf(tgt_port, sizeof(tgt_port), "%u", 
		    (unsigned int)p[4] << 8 | (unsigned int)p[5]);
#endif

	    /* resolve and add to end of list */
	    if (getaddrinfo(tgt_name, tgt_port, hints, ai_last) != 0)
		break;

	    /* get end of list */
	    for (ai=*ai_last; ai != NULL; ai = ai->ai_next)
		ai_last = &(ai->ai_next);

	    break;
	default:    /* someone stupid might use CNAME */
	    break;
	}
    }

#ifdef WIN32
    /* free result set */
    DnsRecordListFree(resp, DnsFreeRecordList);
#endif

    /* fallback in case no resolution via SRV is possible */
    if (ai_last == res)
	return getaddrinfo(node, service, hints, res);

    return 0;
}
コード例 #14
0
ファイル: dns.c プロジェクト: Brenhilt/libpki
/*! \brief Returns a MEM STACK with the requested DNS records */
PKI_MEM_STACK *URL_get_data_dns_url(URL *url, ssize_t size) {

	PKI_MEM_STACK *ret = NULL;

#ifdef HAVE_LIBRESOLV

	int type = T_A;
	PKI_MEM *obj = NULL;

	if( (!url) || (!url->addr)) {
		return NULL;
	}

	unsigned char response[NS_PACKETSZ];

	ns_msg dnsMessage;
	ns_rr dnsRecord;

	int dnsRecordSection = ns_s_an;
	int dns_msgCount = 0;
	int len = 0;

	// Check the Type of record
	if ((type = URL_get_dns_type(url->attrs)) == -1) return NULL;

	PKI_log_debug("DNS URI: Searching for %s (%s/%d)",
		url->addr, url->attrs, type);

	if ((len = res_search(url->addr, C_IN, type, response, sizeof(response))) < 0)
	{
		// An Error Occurred
		PKI_log_err("DNS URI: search failed\n");
		return NULL;
	}

	if (ns_initparse(response, len, &dnsMessage) < 0)
	{
		// This should not happen if the record is correct
		PKI_log_err("DNS URI: can not init DNS parsing of the dnsMessage\n");
		return NULL;
	}

	len = ns_msg_count(dnsMessage, dnsRecordSection);
	PKI_log_debug("DNS_URI: msg count ==> %d\n", len);

	if (len <= 0) return NULL;

	if((ret = PKI_STACK_MEM_new()) == NULL ) {
		PKI_log_debug ("DNS URI: Memory Failure");
		return NULL;
	}

	for (dns_msgCount = 0; dns_msgCount < len; dns_msgCount++)
	{
		PKI_log_debug("DNS URI: Retrieving DNS record #%d",dns_msgCount);

		if (ns_parserr(&dnsMessage, dnsRecordSection, dns_msgCount, &dnsRecord))
		{
			// ERROR: ns_parserr failed, let's continue to the next record
			PKI_log_err("DNS URI: Can not parse record %d of %d", dns_msgCount, len);
			continue;
		}

		PKI_log_debug("DNS URI: type = %d (req: %d)\n", ns_rr_type(dnsRecord), type);

		if (type == pki_ns_t_address)
		{
			switch (ns_rr_type(dnsRecord))
			{
				case T_A:
				case T_AAAA:
				case T_CNAME:
					break;
				default:
					continue;
			}
		}
		else if (type != ns_rr_type(dnsRecord))
		{
			PKI_log_debug("DNS URI: recived type %d is different from requested (%d)", 
				type, ns_rr_type(dnsRecord));
			// continue;
		}

		// int i = 0;
		int rv = 0;
		// int len = 0;
		int offset = 0;

		char dnsRecordName[MAXDNAME];

		memset(dnsRecordName, '\x0', MAXDNAME);
		// Parse the different types of DNS records
		if ((ns_rr_type(dnsRecord) == T_A) || (ns_rr_type(dnsRecord) == T_AAAA))
		{
			// These require Translation using IPv4/IPv6 functions
			int family = AF_INET;

			if (ns_rr_type(dnsRecord) == T_A) family = AF_INET;
			else family = AF_INET6;

			if(inet_ntop(family, ns_rr_rdata(dnsRecord), dnsRecordName, 
				sizeof(dnsRecordName)) == NULL)
			{
				// Can not convert
				continue;
			}
		}
		else if ((ns_rr_type(dnsRecord) == T_CNAME) || (ns_rr_type(dnsRecord) == T_MX) ||
			(ns_rr_type(dnsRecord) == T_NS))
		{
			if (ns_rr_type(dnsRecord) == T_MX) offset = NS_INT16SZ;

			rv = ns_name_uncompress(ns_msg_base(dnsMessage), ns_msg_end(dnsMessage),
				ns_rr_rdata(dnsRecord) + offset, dnsRecordName, MAXDNAME);

			// ERROR, can not uncompress the names
			if (rv < 0) continue;
		}
		else if (ns_rr_type(dnsRecord) == T_SRV)
		{
			// This requires special handling, the format is [SHORT][SHORT][SHORT][DATA]
			// unsigned short *pri = (unsigned short *) ns_rr_rdata(dnsRecord);
			// unsigned short *weight = (unsigned short *) &(ns_rr_rdata(dnsRecord)[2]);
			// unsigned short *port = (unsigned short *) &(ns_rr_rdata(dnsRecord)[4]);

			// Shall we return the additional data too ?
			// printf("PRI : %d\n", *pri);
			// printf("WEIGHT : %d\n", ntohs(*weight));
			// printf("PORT : %d\n", ntohs(*port));

			offset = 6;
			rv = ns_name_uncompress(ns_msg_base(dnsMessage), ns_msg_end(dnsMessage),
				ns_rr_rdata(dnsRecord) + offset, dnsRecordName, MAXDNAME);

			if (rv < 0) continue;
		}
		else if (ns_rr_type(dnsRecord) == T_TXT)
		{
			// Special handling required. Format is [BYTE][DATA]
			unsigned char *p = (unsigned char *)ns_rr_rdata(dnsRecord);

			snprintf(dnsRecordName, (size_t) *p+1, "%s", &ns_rr_rdata(dnsRecord)[1]);
		}
		else
		{
			PKI_log_debug("DNS URI: record type not supported [%d]", ns_rr_type(dnsRecord));
			continue;
		}

		if((obj = PKI_MEM_new_null()) == NULL ) {
			// Memory Allocation Error, we abort
			break;
		}

		if (strlen(dnsRecordName) > 0) {
			// If it is a printable value, we add the parsed version of the
			// record
			if(PKI_MEM_add(obj, (char *) dnsRecordName, strlen(dnsRecordName)) == PKI_ERR) {
				/* ERROR in memory growth */;
				PKI_log_err("DNS URI: Memory Allocation Error");
				break;
			}
		} else {
			// The value is not parsed/parsable, we return the raw data
			// the application should know what to do with the data!
			if(PKI_MEM_add(obj, (char *) ns_rr_rdata(dnsRecord), 
					ns_rr_rdlen(dnsRecord)) == PKI_ERR) {
				/* ERROR in memory growth */;
				PKI_log_err("DNS URI: Memory Allocation Error");
				break;
			}
		}

/*
		printf("MSG Data [%d]:\n", ns_rr_rdlen(dnsRecord));
		for (i=0; i < ns_rr_rdlen(dnsRecord); i++)
		{
			unsigned char *kk;

			kk = (unsigned char *) &ns_rr_rdata(dnsRecord)[i];
			printf("%x:", *kk);
		};
		printf("\n");

		fprintf(stderr, "DEBUG: RV => %d (err: %d, %s)\n", rv, h_errno, hstrerror(h_errno));
		fprintf(stderr, "DEBUG: name => %s (%s)\n", ns_rr_name(dnsRecord), url->addr);
		fprintf(stderr, "DEBUG: value => %s\n", dnsRecordName);
		fprintf(stderr, "DEBUG: type => %d\n", ns_rr_type(dnsRecord));
		fprintf(stderr, "DEBUG: class => %d\n", ns_rr_class(dnsRecord));
*/

		PKI_STACK_MEM_push(ret, obj);

		// PKI_log_debug("DNS URI: Added object #%d to stack", PKI_STACK_MEM_elements(ret));
	}

#endif

	return ret;
};
コード例 #15
0
ファイル: cldc-dns.c プロジェクト: henrich/hail
/*
 * Fill out host list, based on DNS lookups.
 * This is not reentrant.  Better be called before any other threads
 * are started.
 */
int cldc_getaddr(GList **host_list, const char *thishost, struct hail_log *log)
{
	enum { hostsz = 64 };
	char cldb[hostsz];
	unsigned char resp[512];
	int rlen;
	ns_msg nsb;
	ns_rr rrb;
	int rrlen;
	char hostb[hostsz];
	int i;
	struct cldc_host hp;
	const unsigned char *p;
	int rc;
	int search_retries = 10;

	/*
	 * We must create FQDN or else the first thing the resolver does
	 * is a lookup in the DNS root (probably the standard-compliant
	 * dot between "_cld" and "_udp" hurts us here).
	 */
	if (cldc_make_fqdn(cldb, hostsz, "_cld._udp", thishost) != 0) {
		HAIL_INFO(log, "internal error in cldc_make_fqdn(%s)",
			  thishost);
		return -1;
	}

do_try_again:
	rc = res_search(cldb, ns_c_in, ns_t_srv, resp, 512);
	if (rc < 0) {
		switch (h_errno) {
		case HOST_NOT_FOUND:
			HAIL_INFO(log, "%s: No _cld._udp SRV record", __func__);
			return -1;
		case NO_DATA:
			HAIL_INFO(log, "%s: Cannot find _cld._udp"
				  " SRV record", __func__);
			return -1;
		case TRY_AGAIN:
			if (search_retries-- > 0)
				goto do_try_again;
			/* fall through */
		case NO_RECOVERY:
		default:
			HAIL_ERR(log, "%s: res_search error (%d): %s",
				 __func__, h_errno, hstrerror(h_errno));
			return -1;
		}
	}
	rlen = rc;

	if (rlen == 0) {
		HAIL_INFO(log, "%s: res_search returned empty reply", __func__);
		return -1;
	}

	if (ns_initparse(resp, rlen, &nsb) < 0) {
		HAIL_ERR(log, "%s: ns_initparse error", __func__);
		return -1;
	}

	for (i = 0; i < ns_msg_count(nsb, ns_s_an); i++) {
		rc = ns_parserr(&nsb, ns_s_an, i, &rrb);
		if (rc < 0)
			continue;

		if (ns_rr_class(rrb) != ns_c_in)
			continue;

		memset(&hp, 0, sizeof(hp));

		switch (ns_rr_type(rrb)) {
		case ns_t_srv:
			rrlen = ns_rr_rdlen(rrb);
			if (rrlen < 8) {	/* 2+2+2 and 2 for host */
				HAIL_DEBUG(log, "%s: SRV len %d",
					   __func__, rrlen);
				break;
			}
			p = ns_rr_rdata(rrb);
			rc = dn_expand(resp, resp+rlen, p+6, hostb, hostsz);
			if (rc < 0) {
				HAIL_DEBUG(log, "%s: dn_expand error %d",
					   __func__, rc);
				break;
			}
			if (rc < 2) {
				HAIL_DEBUG(log, "%s: dn_expand short %d",
					   __func__, rc);
				break;
			}

			if (cldc_saveaddr(&hp, ns_get16(p+0),
					  ns_get16(p+2), ns_get16(p+4),
					  rc, hostb, NULL))
				break;

			HAIL_DEBUG(log, "%s: found CLD host %s port %u"
				   " prio %d weight %d",
				   __func__, hp.host, hp.port,
				   hp.prio, hp.weight);

			push_host(host_list, &hp);
			break;
		case ns_t_cname:	/* impossible, but */
			HAIL_DEBUG(log, "%s: CNAME in SRV request, ignored",
				   __func__);
			break;
		default:
			;
		}
	}

	return 0;
}
コード例 #16
0
ファイル: dns.c プロジェクト: Chaohua/exim
static int
fakens_search(const uschar *domain, int type, uschar *answerptr, int size)
{
int len = Ustrlen(domain);
int asize = size;                  /* Locally modified */
uschar *endname;
uschar name[256];
uschar utilname[256];
uschar *aptr = answerptr;          /* Locally modified */
struct stat statbuf;

/* Remove terminating dot. */

if (domain[len - 1] == '.') len--;
Ustrncpy(name, domain, len);
name[len] = 0;
endname = name + len;

/* This code, for forcing TRY_AGAIN and NO_RECOVERY, is here so that it works
for the old test suite that uses a real nameserver. When the old test suite is
eventually abandoned, this code could be moved into the fakens utility. */

if (len >= 14 && Ustrcmp(endname - 14, "test.again.dns") == 0)
  {
  int delay = Uatoi(name);  /* digits at the start of the name */
  DEBUG(D_dns) debug_printf("Return from DNS lookup of %s (%s) faked for testing\n",
    name, dns_text_type(type));
  if (delay > 0)
    {
    DEBUG(D_dns) debug_printf("delaying %d seconds\n", delay);
    sleep(delay);
    }
  h_errno = TRY_AGAIN;
  return -1;
  }

if (len >= 13 && Ustrcmp(endname - 13, "test.fail.dns") == 0)
  {
  DEBUG(D_dns) debug_printf("Return from DNS lookup of %s (%s) faked for testing\n",
    name, dns_text_type(type));
  h_errno = NO_RECOVERY;
  return -1;
  }

/* Look for the fakens utility, and if it exists, call it. */

(void)string_format(utilname, sizeof(utilname), "%s/../bin/fakens",
  spool_directory);

if (stat(CS utilname, &statbuf) >= 0)
  {
  pid_t pid;
  int infd, outfd, rc;
  uschar *argv[5];

  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) using fakens\n",
    name, dns_text_type(type));

  argv[0] = utilname;
  argv[1] = spool_directory;
  argv[2] = name;
  argv[3] = dns_text_type(type);
  argv[4] = NULL;

  pid = child_open(argv, NULL, 0000, &infd, &outfd, FALSE);
  if (pid < 0)
    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to run fakens: %s",
      strerror(errno));

  len = 0;
  rc = -1;
  while (asize > 0 && (rc = read(outfd, aptr, asize)) > 0)
    {
    len += rc;
    aptr += rc;       /* Don't modify the actual arguments, because they */
    asize -= rc;      /* may need to be passed on to res_search(). */
    }

  if (rc < 0)
    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "read from fakens failed: %s",
      strerror(errno));

  switch(child_close(pid, 0))
    {
    case 0: return len;
    case 1: h_errno = HOST_NOT_FOUND; return -1;
    case 2: h_errno = TRY_AGAIN; return -1;
    default:
    case 3: h_errno = NO_RECOVERY; return -1;
    case 4: h_errno = NO_DATA; return -1;
    case 5: /* Pass on to res_search() */
    DEBUG(D_dns) debug_printf("fakens returned PASS_ON\n");
    }
  }

/* fakens utility not found, or it returned "pass on" */

DEBUG(D_dns) debug_printf("passing %s on to res_search()\n", domain);

return res_search(CS domain, C_IN, type, answerptr, size);
}
コード例 #17
0
ファイル: dns.c プロジェクト: loganaden/exim
static int
fakens_search(const uschar *domain, int type, uschar *answerptr, int size)
{
int len = Ustrlen(domain);
int asize = size;                  /* Locally modified */
uschar *endname;
uschar name[256];
uschar utilname[256];
uschar *aptr = answerptr;          /* Locally modified */
struct stat statbuf;

/* Remove terminating dot. */

if (domain[len - 1] == '.') len--;
Ustrncpy(name, domain, len);
name[len] = 0;
endname = name + len;

/* Look for the fakens utility, and if it exists, call it. */

(void)string_format(utilname, sizeof(utilname), "%s/bin/fakens",
  config_main_directory);

if (stat(CS utilname, &statbuf) >= 0)
  {
  pid_t pid;
  int infd, outfd, rc;
  uschar *argv[5];

  DEBUG(D_dns) debug_printf("DNS lookup of %s (%s) using fakens\n", name, dns_text_type(type));

  argv[0] = utilname;
  argv[1] = config_main_directory;
  argv[2] = name;
  argv[3] = dns_text_type(type);
  argv[4] = NULL;

  pid = child_open(argv, NULL, 0000, &infd, &outfd, FALSE);
  if (pid < 0)
    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "failed to run fakens: %s",
      strerror(errno));

  len = 0;
  rc = -1;
  while (asize > 0 && (rc = read(outfd, aptr, asize)) > 0)
    {
    len += rc;
    aptr += rc;       /* Don't modify the actual arguments, because they */
    asize -= rc;      /* may need to be passed on to res_search(). */
    }

  /* If we ran out of output buffer before exhasting the return,
  carry on reading and counting it. */

  if (asize == 0)
    while ((rc = read(outfd, name, sizeof(name))) > 0)
      len += rc;

  if (rc < 0)
    log_write(0, LOG_MAIN|LOG_PANIC_DIE, "read from fakens failed: %s",
      strerror(errno));

  switch(child_close(pid, 0))
    {
    case 0: return len;
    case 1: h_errno = HOST_NOT_FOUND; return -1;
    case 2: h_errno = TRY_AGAIN; return -1;
    default:
    case 3: h_errno = NO_RECOVERY; return -1;
    case 4: h_errno = NO_DATA; return -1;
    case 5: /* Pass on to res_search() */
    DEBUG(D_dns) debug_printf("fakens returned PASS_ON\n");
    }
  }
else
  {
  DEBUG(D_dns) debug_printf("fakens (%s) not found\n", utilname);
  }

/* fakens utility not found, or it returned "pass on" */

DEBUG(D_dns) debug_printf("passing %s on to res_search()\n", domain);

return res_search(CS domain, C_IN, type, answerptr, size);
}
コード例 #18
0
ファイル: lookup_bep_034.c プロジェクト: erdgeist/bep034
/* This function expects the bep034_lock to be held by caller,
   releases it while working and returns with the lock held
*/
static bep034_status bep034_fill_hostrecord( const char * hostname, bep034_hostrecord ** hostrecord, uintptr_t dns_handle ) {
  uint8_t answer[NS_PACKETSZ];
  bep034_hostrecord * hr = 0;
  int answer_len, num_msgs, max_entries, i;
  ns_msg msg;
  ns_rr rr;

  /* Reset hostrecord pointer */
  * hostrecord = 0;

  /* If we find a record in cache, return it */
  hr = bep034_find_hostrecord( hostname, &i /* dummy */ );
  if( hr ) {
    *hostrecord = hr;
    return BEP_034_INPROGRESS;
  }

  /* Return mutex, we'll be blocking now and do not
     hold any resources in need of guarding  */
  bep034_dounlock();

  /* Query resolver for TXT records for the trackers domain */
#ifdef __MACH__
  {
    struct sockaddr tmp;
    uint32_t tmplen;
    answer_len = dns_search( (dns_handle_t)dns_handle, hostname, ns_c_in, ns_t_txt, answer, sizeof(answer), &tmp, &tmplen );
  }
#else
  (void)dns_handle;
  answer_len = res_search(hostname, ns_c_in, ns_t_txt, answer, sizeof(answer));
#endif
  if( answer_len < 0 ) {
    /* Here we enter race condition land */
    switch( h_errno ) {
    case NO_RECOVERY: case HOST_NOT_FOUND: return BEP_034_NXDOMAIN;
    case NO_DATA: return BEP_034_NORECORD;
    case NETDB_INTERNAL: case TRY_AGAIN: default: return BEP_034_TIMEOUT;
    }
  }

  ns_initparse (answer, answer_len, &msg);
  num_msgs = ns_msg_count (msg, ns_s_an);
  for( i=0; i<num_msgs; ++i) {
    ns_parserr (&msg, ns_s_an, i, &rr);
    if (ns_rr_class(rr) == ns_c_in && ns_rr_type(rr) == ns_t_txt ) {
      uint32_t record_ttl = ns_rr_ttl(rr);
      uint16_t record_len = ns_rr_rdlen(rr);
      const uint8_t *record_ptr = ns_rr_rdata(rr);
      const char * string_ptr, * string_end;

      /* First octet is length of (first) string in the txt record.
         Since BEP034 does not say anything about multiple strings,
         we ignore all but the first string in each TXT record. */
      uint8_t string_len = *record_ptr;

      /* If we would read beyond buffer end, ignore record */
      if( record_ptr + 1 + string_len > answer + answer_len )
        continue;

      /* Sanitize string length against record length */
      if( string_len + 1 > record_len )
        string_len = record_len - 1;

      /* Test if we are interested in the record */
      if( string_len < 10 /* strlen( "BITTORRENT" ) */ )
        continue;

      /* Although the BEP is not very specific, we interpret the wording
         "This should always be the first word in the record" as a requirment
         to not start the record with a space */
      if( memcmp( record_ptr + 1, "BITTORRENT", 10 ) )
        continue;

      /* We found a BITTORRENT TXT record. Now start parsing:
         Given entries of the form "UDP:\d+\s" i.e. 6 bytes,
         in a record of length N we have an upper bound of
         ( N - 11 ) / 6 records.
      */
      max_entries = 1 + ( string_len - 11 ) / 6;

      /* Allocate memory for host record */
      hr = (bep034_hostrecord*)
        malloc( sizeof(bep034_hostrecord) + sizeof( uint32_t ) * max_entries );
      if( !hr )
        return BEP_034_TIMEOUT;

      /* Init host record */
      hr->hostname = strdup( hostname );
      hr->entries = 0;
      hr->expiry = NOW() + record_ttl;

      /* Look for "\s(TCP|UDP):\d+" */
      string_ptr = record_ptr + 1;
      string_end = string_ptr + string_len;
      string_ptr += 10 /* strlen( "BITTORRENT" ) */;

      while( string_ptr + 6 < string_end ) { /* We need at least 6 bytes for a word */
        int found;
        uint32_t port = 0;

        ++string_ptr;
        if( string_ptr[-1] != ' ' || string_ptr[2] != 'P' || string_ptr[3] != ':' )
          continue;
        if( string_ptr[0] == 'T' && string_ptr[1] == 'C' )
          found = 0;
        else if( string_ptr[0] == 'U' && string_ptr[1] == 'D' )
          found = 1;
        else
          continue;

        /* Now we're sure, we've found UDP: or TCP: and assume, from string_ptr + 4 there's
           a port number*/
        string_ptr += 4;
        while( string_ptr < string_end && (*string_ptr >= '0' && *string_ptr <= '9' ) )
          port = port * 10 + *(string_ptr++) - '0';

        /* If no digit was found, word is invalid */
        if( string_ptr[-1] == ':' ) continue;

        /* If number did not terminate on end of string or with a space, word is invalid */
        if( string_ptr != string_end && *string_ptr != ' ' ) continue;

        /* If we have an invalid port number, word is invalid */
        if( port > 65335 ) continue;

        /* Valid word found, add it to tracker list */
        hr->trackers[ hr->entries++ ] = port | ( found ? 0x10000 : 0 );
      }

      /* Ensure exclusive access to the host record list, lock will be held
         on return so that the caller can work with hr */
      bep034_dolock();

      /* Hand over record to cache, from now the cache has to release memory */
      if( bep034_save_record( &hr ) )
        return BEP_034_TIMEOUT;

      /* Dump what we found */
      bep034_dump_record( hr );

      /* Once the first line in the first record has been parsed, return host record */
      *hostrecord = hr;
      return BEP_034_INPROGRESS;
    }
  }
}
コード例 #19
0
ファイル: dnsSD.c プロジェクト: Chansie/host-sflow
  static
  int dnsSD_Request(HSP *sp, char *dname, uint16_t rtype, HSPDnsCB callback, HSPSFlowSettings *settings)
  {
    u_char buf[PACKETSZ];

    // We could have a config option to set the DNS servers that we will ask. If so
    // they should be written into this array of sockaddrs...
    // myDebug(1,"_res_nsaddr=%p", &_res.nsaddr);

    myDebug(1,"=== res_search(%s, C_IN, %u) ===", dname, rtype);
    int anslen = res_search(dname, C_IN, rtype, buf, PACKETSZ);
    if(anslen == -1) {
      if(errno == 0 && (h_errno == HOST_NOT_FOUND || h_errno == NO_DATA)) {
	// although res_search returned -1, the request did actually get an answer,
	// it's just that there was no SRV record configured,  or the response was
	// not authoritative. Interpret this the same way as answer_count==0.
	myDebug(1,"res_search(%s, C_IN, %u) came up blank (h_errno=%d)", dname, rtype, h_errno);
	return 0;
      }
      else {
	myLog(LOG_ERR,"res_search(%s, C_IN, %u) failed : %s (h_errno=%d)", dname, rtype, strerror(errno), h_errno);
	return -1;
      }
    }
    if(anslen < sizeof(HEADER)) {
      myLog(LOG_ERR,"res_search(%s) returned %d (too short)", dname, anslen);
      return -1;
    }
    HEADER *ans = (HEADER *)buf;
    if(ans->rcode != NOERROR) {
      myLog(LOG_ERR,"res_search(%s) returned response code %d", dname, ans->rcode);
      return -1;
    }

    uint32_t answer_count = (ntohs(ans->ancount));
    if(answer_count == 0) {
      myLog(LOG_INFO,"res_search(%s) returned no answer", dname);
      return 0;
    }
    myDebug(1, "dnsSD: answer_count = %d", answer_count);

    u_char *p = buf + sizeof(HEADER);
    u_char *endp = buf + anslen;

    // consume query
    int query_name_len = dn_skipname(p, endp);
    if(query_name_len == -1) {
      myLog(LOG_ERR,"dn_skipname() <query> failed");
      return -1;
    }
    myDebug(1, "dnsSD: (compressed) query_name_len = %d", query_name_len);
    p += (query_name_len);
    p += QFIXEDSZ;

    // collect array of results
    for(int entry = 0; entry < answer_count; entry++) {

      myDebug(1, "dnsSD: entry %d, bytes_left=%d", entry, (endp - p));

      // consume name (again)
      query_name_len = dn_skipname(p, endp);
      if(query_name_len == -1) {
	myLog(LOG_ERR,"dn_skipname() <ans> failed");
	return -1;
      }
      p += (query_name_len);

      // now p should be looking at:
      // [type:16][class:16][ttl:32][len:16][record]
      if((endp - p) <= 16) {
	myLog(LOG_ERR,"ans %d of %d: ran off end -- only %d bytes left",
	      entry, answer_count, (endp-p));
	return -1;
      }
      uint16_t res_typ =  (p[0] << 8)  |  p[1];
      uint16_t res_cls =  (p[2] << 8)  |  p[3];
      uint32_t res_ttl =  (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7];
      uint16_t res_len =  (p[8] << 8)  |  p[9];
      p += 10;
      // use another pointer to walk the payload and move p to the next answer
      u_char *x = p;
      p += res_len;
      uint16_t res_payload = res_len;

      // sanity check
      if(res_typ != rtype ||
	 res_cls != C_IN) {
	myLog(LOG_ERR,"expected t=%d,c=%d, got t=%d,c=%d", rtype, C_IN, res_typ, res_cls);
	return -1;
      }
      
      switch(rtype) {
      case T_SRV:
	{
	  // now x should see
	  // [priority:2][weight:2][port:2][FQDN:res_len-6]
	  uint16_t res_pri = (x[0] << 8)  | x[1];
	  uint16_t res_wgt = (x[2] << 8)  | x[3];
	  uint32_t res_prt = (x[4] << 8)  | x[5];
	  x += 6;
	  res_payload -= 6;
	  
	  // still got room for an FQDN?
	  if((endp - x) < HSP_MIN_DNAME) {
	    myLog(LOG_ERR,"no room for target name -- only %d bytes left", (endp - x));
	    return -1;
	  }
	  
	  char fqdn[MAXDNAME];
	  int ans_len = dn_expand(buf, endp, x, fqdn, MAXDNAME);
	  if(ans_len == -1) {
	    myLog(LOG_ERR,"dn_expand() failed");
	    return -1;
	  }
	  
	  // cross-check
	  if(ans_len != res_payload) {
	    myLog(LOG_ERR,"target name len cross-check failed");
	    return -1;
	  }
	  
	  if(ans_len < HSP_MIN_DNAME) {
	    // just ignore this one -- e.g. might just be "."
	  }
	  else {
	    // fqdn[ans_len] = '\0';
	    myDebug(1, "answer %d is <%s>:<%u> (wgt=%d; pri=%d; ttl=%d; ans_len=%d; res_len=%d)",
			    entry,
			    fqdn,
			    res_prt,
			    res_wgt,
			    res_pri,
			    res_ttl,
			    ans_len,
			    res_len);
	    if(callback) {
	      char fqdn_port[PACKETSZ];
	      sprintf(fqdn_port, "%s/%u", fqdn, res_prt);
	      // use key == NULL to indicate that the value is host:port
	      (*callback)(sp, rtype, res_ttl, NULL, 0, (u_char *)fqdn_port, strlen(fqdn_port), settings);
	    }
	  }
	}
	break;
      case T_TXT:
	{
	  // now x should see
	  // [TXT:res_len]

	  // still got room for a text record?
	  if((endp - x) < HSP_MIN_TXT) {
	    myLog(LOG_ERR,"no room for text record -- only %d bytes left", (endp - x));
	    return -1;
	  }

	  if(getDebug()) {
	    printf("dsnSD TXT Record: ");
	    for(int i = 0; i < res_len; i++) {
	      int ch = x[i];
	      if(isalnum(ch)) printf("%c", ch);
	      else printf("{%02x}", ch);
	    } 
	    printf("\n");
	  }

	  // format is [len][<key>=<val>][len][<key>=<val>]...
	  // so we can pull out the settings and give them directly
	  // to the callback fn without copying
	  u_char *txtend = x + res_len;
	  // need at least 3 chars for a var=val setting
	  while((txtend - x) >= 3) {
	    int pairlen = *x++;
	    int klen = strcspn((char *)x, "=");
	    if(klen < 0) {
	      myLog(LOG_ERR, "dsnSD TXT record not in var=val format: %s", x);
	    }
	    else {
	      if(callback) (*callback)(sp, rtype, res_ttl, x, klen, (x+klen+1), (pairlen - klen - 1), settings);
	    }
	    x += pairlen;
	  }
	}
	break;

      default:
	myLog(LOG_ERR, "unsupported query type: %u" , rtype);
	return -1;
	break;
      }
    }
    return answer_count;
  }
コード例 #20
0
ファイル: res_query.c プロジェクト: SylvestreG/bitrig
int
main(int argc, char *argv[])
{
	struct timeval		 start, end;
	time_t			 when;
	int			 ch, i, qflag, dflag, r;
	uint16_t		 type = T_A;
	char			 buf[1024], *host;

	dflag = 0;
	qflag = 0;

	while((ch = getopt(argc, argv, "deqt:")) !=  -1) {
		switch(ch) {
		case 'd':
			dflag = 1;
			break;
		case 'e':
			long_err += 1;
			break;
		case 'q':
			qflag = 1;
			break;
		case 't':
			if ((type = strtotype(optarg)) == 0)
				usage();
			break;
		default:
			usage();
			/* NOTREACHED */
		}
	}
	argc -= optind;
	argv += optind;

	for (i = 0; i < argc; i++) {

		if (i)
			printf("\n");

		printf("===> \"%s\"\n", argv[i]);
		host = gethostarg(argv[i]);

		errno = 0;
		h_errno = 0;
		gai_errno = 0;
		rrset_errno = 0;

		if (gettimeofday(&start, NULL) != 0)
			err(1, "gettimeofday");

		if (qflag)
			r = res_query(host, C_IN, type, buf, sizeof(buf));
		else
			r = res_search(host, C_IN, type, buf, sizeof(buf));

		if (gettimeofday(&end, NULL) != 0)
			err(1, "gettimeofday");

		if (r != -1) {
			dump_packet(buf, r);
			printf("\n");
			if (dflag) {
				printf(";; Query time: %d msec\n",
				    msec(start, end));
				when = time(NULL);
				printf(";; WHEN: %s", ctime(&when));
			}
			printf(";; MSG SIZE  rcvd: %i\n", r);
		}
		print_errors();
	}

	return (0);
}
コード例 #21
0
ファイル: cellconfig.c プロジェクト: openafs/openafs
int
afsconf_LookupServer(const char *service, const char *protocol,
		     const char *cellName, unsigned short afsdbPort,
		     afs_uint32 *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS],
		     unsigned short ports[], unsigned short ipRanks[],
		     int *numServers, int *ttl, char **arealCellName)
{
    int code = 0;
    int r;
    int len;
    unsigned char answer[4096];
    unsigned char *p;
    char *dotcellname = NULL;
    char *realCellName;
    char host[256];
    int server_num = 0;
    int minttl = 0;
    int try_init = 0;
    int dnstype = 0;
    int pass = 0;
    char *IANAname = (char *) afsconf_FindIANAName(service);
    int tservice = afsconf_FindService(service);

    realCellName = NULL;

    *numServers = 0;
    *ttl = 0;
    if (tservice <= 0 || !IANAname)
	return AFSCONF_NOTFOUND;	/* service not found */

    if (strchr(cellName,'.'))
	pass += 2;

#ifdef HAVE_RES_RETRANSRETRY
    if ((_res.options & RES_INIT) == 0 && res_init() == -1)
      return (0);

    /*
     * Rx timeout is typically 56 seconds; limit user experience to
     * similar timeout
     */
    _res.retrans = 18;
    _res.retry = 3;
#endif

 retryafsdb:
    r = -1;
    switch (pass) {
    case 0:
	dnstype = T_SRV;
	r = asprintf(&dotcellname, "_%s._%s.%s.", IANAname, protocol, cellName);
	break;
    case 1:
	dnstype = T_AFSDB;
	r = asprintf(&dotcellname, "%s.", cellName);
	break;
    case 2:
	dnstype = T_SRV;
	r = asprintf(&dotcellname, "_%s._%s.%s", IANAname, protocol, cellName);
	break;
    case 3:
	dnstype = T_AFSDB;
	r = asprintf(&dotcellname, "%s", cellName);
	break;
    }
    if (r < 0 || dotcellname == NULL)
	goto findservererror;

    LOCK_GLOBAL_MUTEX;
    len = res_search(dotcellname, C_IN, dnstype, answer, sizeof(answer));
    UNLOCK_GLOBAL_MUTEX;

    if (dotcellname != NULL) {
	free(dotcellname);
	dotcellname = NULL;
    }

    if (len < 0) {
	if (try_init < 1) {
	    try_init++;
	    res_init();
	    goto retryafsdb;
	}
	if (pass < 3) {
	    pass++;
	    goto retryafsdb;
	} else {
	    code = AFSCONF_NOTFOUND;
	    goto findservererror;
	}
    }

    p = answer + sizeof(HEADER);	/* Skip header */
    code = dn_expand(answer, answer + len, p, host, sizeof(host));
    if (code < 0) {
	code = AFSCONF_NOTFOUND;
	goto findservererror;
    }

    p += code + QFIXEDSZ;	/* Skip name */

    while (p < answer + len) {
	int type, ttl, size;

	code = dn_expand(answer, answer + len, p, host, sizeof(host));
	if (code < 0) {
	    code = AFSCONF_NOTFOUND;
	    goto findservererror;
	}

	p += code;		/* Skip the name */
	type = (p[0] << 8) | p[1];
	p += 4;			/* Skip type and class */
	ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
	p += 4;			/* Skip the TTL */
	size = (p[0] << 8) | p[1];
	p += 2;			/* Skip the size */

	if (type == T_AFSDB) {
	    struct hostent *he;
	    short afsdb_type;

	    afsdb_type = (p[0] << 8) | p[1];
	    if (afsdb_type == 1) {
		/*
		 * We know this is an AFSDB record for our cell, of the
		 * right AFSDB type.  Write down the true cell name that
		 * the resolver gave us above.
		 */
		if (!realCellName)
		    realCellName = strdup(host);
	    }

	    code = dn_expand(answer, answer + len, p + 2, host, sizeof(host));
	    if (code < 0) {
		code = AFSCONF_NOTFOUND;
		goto findservererror;
	    }

	    if ((afsdb_type == 1) && (server_num < MAXHOSTSPERCELL) &&
		/* Do we want to get TTL data for the A record as well? */
		(he = gethostbyname(host))) {
		if (he->h_addrtype == AF_INET) {
		    afs_uint32 ipaddr;
		    memcpy(&ipaddr, he->h_addr, sizeof(ipaddr));
		    cellHostAddrs[server_num] = ipaddr;
		    ports[server_num] = afsdbPort;
		    ipRanks[server_num] = 0;
		    strncpy(cellHostNames[server_num], host,
			    sizeof(cellHostNames[server_num]));
		    server_num++;
		    if (!minttl || ttl < minttl)
			minttl = ttl;
		}
	    }
	}
	if (type == T_SRV) {
	    struct hostent *he;
	    /* math here: _ is 1, _ ._ is 3, _ ._ . is 4. then the domain. */
	    if ((strncmp(host + 1, IANAname, strlen(IANAname)) == 0) &&
		(strncmp(host + strlen(IANAname) + 3, protocol,
			 strlen(protocol)) == 0)) {
		if (!realCellName)
		    realCellName = strdup(host + strlen(IANAname) +
					  strlen(protocol) + 4);
	    }

	    code = dn_expand(answer, answer + len, p + 6, host, sizeof(host));
	    if (code < 0) {
		code = AFSCONF_NOTFOUND;
		goto findservererror;
	    }

	    if ((server_num < MAXHOSTSPERCELL) &&
		/* Do we want to get TTL data for the A record as well? */
		(he = gethostbyname(host))) {
		if (he->h_addrtype == AF_INET) {
		    afs_uint32 ipaddr;

		    memcpy(&ipaddr, he->h_addr, sizeof(ipaddr));
		    cellHostAddrs[server_num] = ipaddr;
		    ipRanks[server_num] = (p[0] << 8) | p[1];
		    ports[server_num] = htons((p[4] << 8) | p[5]);
		    /* weight = (p[2] << 8) | p[3]; */
		    strncpy(cellHostNames[server_num], host,
			    sizeof(cellHostNames[server_num]));
		    server_num++;

		    if (!minttl || ttl < minttl)
			minttl = ttl;
		}
	    }
	}

	p += size;
    }

    if (server_num == 0) {	/* No AFSDB or SRV records */
	code = AFSCONF_NOTFOUND;
	goto findservererror;
    }

    if (realCellName) {
	/* Convert the real cell name to lowercase */
	for (p = (unsigned char *)realCellName; *p; p++)
	    *p = tolower(*p);
    }

    *numServers = server_num;
    *ttl = minttl ? (time(0) + minttl) : 0;

    if ( *numServers > 0 ) {
        code =  0;
	*arealCellName = realCellName;
    } else
        code = AFSCONF_NOTFOUND;

findservererror:
    if (code && realCellName)
	free(realCellName);
    return code;
}
コード例 #22
0
ファイル: dnsresolve.c プロジェクト: ee08b397/mlkit
static uintptr_t *
apdns_getFQDN_MX_1 (Region rAddrLPairs, Region rAddrEPairs,
		    Region rAddrString, char *str, uintptr_t *list, int depth, request_data *rd)
{
  if (depth < 0)
    return list;
  // i,j are used as loop counters
  // the dnspackage returned from the resolver is scanned from top to buttom
  // next is the package pointer relative to the start of the package
  int j, next;
  char ans[NS_PACKETSZ + 1];
  char dnsnamesa[NS_MAXDNAME];
  char *dnsnames = dnsnamesa;
  char *input = str;
  uintptr_t *pair, *listpair;
  String rs;
  dnshead *head = (dnshead *) ans;
  // get the dns package
  int n = res_search (input, C_IN, T_MX, (unsigned char *) ans, NS_PACKETSZ + 1);
  input = 0;
  if (n == -1)
    return list;
  if (n < sizeof (dnshead))
    return list;
  ntohhead (ans, head);
  if ((head->flags & 0xF) != 0)
    return list;
  if (head->anscount < 1)
    return list;
  // skip questions
  next = NS_HFIXEDSZ;
  for (j = 0; j < head->questcount; j++)
    {
      next = skipname (ans, next, n);
      next = iflessthan (next + 4, n);
      if (next < 0)
	return list;
    }
  // The answers
  int rv;
  for (j = 0; j < head->anscount; j++)
    {
//      int a_name = next;
      if (next >= n)
	return list;
      next = skipname (ans, next, n);
      if (next + NS_RRFIXEDSZ >= n || next < 0)
	return list;
      uint16_t a_type = twocharto16 (ans[next], ans[next + 1]);
      next += 4;
      uint32_t a_ttl =
	fourcharto32 (ans[next], ans[next + 1], ans[next + 2], ans[next + 3]);
      next += 4;
      uint16_t a_rdlength = twocharto16 (ans[next], ans[next + 1]);
      next += 2;
      if (a_type == T_MX)
	{			// We got a mx record
	  if (next + a_rdlength >= n || a_rdlength < 3)
	    return list;
	  uint16_t a_mx_pref = twocharto16 (ans[next], ans[next + 1]);
	  rv = dumpname (dnsnames, NS_MAXDNAME, ans, next + 2, n);
	  rs = convertStringToML (rAddrString, dnsnames);
	  allocRecordML (rAddrEPairs, 3, pair);
	  elemRecordML (pair, 0) = (uintptr_t) a_mx_pref;
	  elemRecordML (pair, 1) = (uintptr_t) a_ttl;
	  elemRecordML (pair, 2) = (uintptr_t) rs;
	  allocRecordML (rAddrLPairs, 2, listpair);
	  first (listpair) = (uintptr_t) pair;
	  second (listpair) = (uintptr_t) list;
	  makeCONS (listpair, list);
    ap_log_error (APLOG_MARK, LOG_DEBUG, 0, rd->server, 
        "apdns_getFQDN_MX: pref %i, ttl %i, %s", a_mx_pref, a_ttl, dnsnames);
	}
      else if (a_type == T_CNAME)
	{			// we got an alias (cononical name)
	  rv = dumpname (dnsnames, NS_MAXDNAME, ans, next, n);
	  input = dnsnames;
	  break;
	}
      else
	{			// we got something we did not ask for
	  // or cannot handle at the momnet
	  return list;
	}
      next += a_rdlength;
    }
  if (input)
    return apdns_getFQDN_MX_1 (rAddrLPairs, rAddrEPairs,
			       rAddrString, input, list, depth - 1, rd);
  return list;
}