Ejemplo n.º 1
0
/** parses a PTR record into a ptr_rdata structure */
struct ptr_rdata* dns_ptr_parser( unsigned char* msg, unsigned char* end,
									  unsigned char* rdata)
{
	struct ptr_rdata* pname;
	int len;
	char name[MAX_DNS_NAME];
	
	pname=0;
	if (dn_expand(msg, end, rdata, name, MAX_DNS_NAME-1)==-1)
		goto error;
	len=strlen(name);
	if (len>255)
		goto error;
	/* alloc sizeof struct + space for the null terminated name */
	pname=local_malloc(sizeof(struct ptr_rdata)-1+len+1);
	if(pname==0){
		LM_ERR("out of memory\n");
		goto error;
	}
	pname->ptrdname_len=len;
	memcpy(pname->ptrdname, name, pname->ptrdname_len);
	pname->ptrdname[pname->ptrdname_len]=0;
	return pname;
error:
	if (pname) local_free(pname);
	return 0;
}
Ejemplo n.º 2
0
static int parse_answer(querybuf_t *ans, int len, struct in_addr *addr)
{
  char buf[MAXPACKET];
  HEADER *ahp;
  u_char *cp, *eoa;
  int type, n;

  ahp = &ans->hdr;
  eoa = ans->buf + len;
  cp = ans->buf + sizeof(HEADER);

  while (ahp->qdcount > 0) {
    ahp->qdcount--;
    cp += dn_skipname(cp, eoa) + QFIXEDSZ;
  }
  while (ahp->ancount > 0 && cp < eoa) {
    ahp->ancount--;
    if ((n = dn_expand(ans->buf, eoa, cp, buf, sizeof(buf))) < 0)
      break;
    cp += n;
    type = _getshort(cp);
    cp += 8;
    n = _getshort(cp);
    cp += 2;
    if (type == T_CNAME) {
      cp += n;
      continue;
    }
    memcpy(addr, cp, n);
    return 0;
  }

  h_errno = TRY_AGAIN;
  return -1;
}
Ejemplo n.º 3
0
// ccured wrappers
int dn_expand_wrapper(const u_char *msg, const u_char *eomorig,
		      const u_char *comp_dn, char *exp_dn, int length) {
  __write_at_least(exp_dn, length);
  __verify_nul(comp_dn);
  return ( dn_expand(__ptrof(msg), __ptrof(eomorig), __ptrof(comp_dn),
		     __ptrof(exp_dn), length) );
}
Ejemplo n.º 4
0
int
ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
    int b;
    int tmp;

    /* Make section right. */
    tmp = section;
    if (tmp < 0 || section >= ns_s_max)
        RETERR(ENODEV);
    if (section != handle->_sect)
        setsection(handle, section);

    /* Make rrnum right. */
    if (rrnum == -1)
        rrnum = handle->_rrnum;
    if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
        RETERR(ENODEV);
    if (rrnum < handle->_rrnum)
        setsection(handle, section);
    if (rrnum > handle->_rrnum) {
        b = ns_skiprr(handle->_msg_ptr, handle->_eom, section,
                      rrnum - handle->_rrnum);

        if (b < 0)
            return (-1);
        handle->_msg_ptr += b;
        handle->_rrnum = rrnum;
    }

    /* Do the parse. */
    b = dn_expand(handle->_msg, handle->_eom,
                  handle->_msg_ptr, rr->name, NS_MAXDNAME);
    if (b < 0)
        return (-1);
    handle->_msg_ptr += b;
    if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
        RETERR(EMSGSIZE);
    NS_GET16(rr->type, handle->_msg_ptr);
    NS_GET16(rr->rr_class, handle->_msg_ptr);
    if (section == ns_s_qd) {
        rr->ttl = 0;
        rr->rdlength = 0;
        rr->rdata = NULL;
    } else {
        if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
            RETERR(EMSGSIZE);
        NS_GET32(rr->ttl, handle->_msg_ptr);
        NS_GET16(rr->rdlength, handle->_msg_ptr);
        if (handle->_msg_ptr + rr->rdlength > handle->_eom)
            RETERR(EMSGSIZE);
        rr->rdata = handle->_msg_ptr;
        handle->_msg_ptr += rr->rdlength;
    }
    if (++handle->_rrnum > handle->_counts[(int)section])
        setsection(handle, (ns_sect)((int)section + 1));

    /* All done. */
    return (0);
}
Ejemplo n.º 5
0
static bool GetDN(const unsigned char * reply, const unsigned char * replyEnd, unsigned char * & cp, char * buff)
{
  int len = dn_expand(reply, replyEnd, cp, buff, MAXDNAME);
  if (len < 0)
    return false;
  cp += len;
  return true;
}
Ejemplo n.º 6
0
static int
rrextract(u_char *msg, int msglen, u_char *rrp, u_char *dname, int namelen)
{
  /* cp is used to read data from rrp[] (the Resource Record)
   * cp1 is used to write data into data[]
   * However, we sometimes abuse cp1 and use it for reading too. :-/
   */
  u_char *eom, *cp, *cp1, *rdatap;
  u_int class, type, dlen;
  int n;
  long origTTL;
  u_char data[MAXDATA*2+SPACE_FOR_VARS];
  data [(MAXDATA*2)-1+SPACE_FOR_VARS] = EOS;

  cp = rrp;
  eom = msg + msglen;

  GETSHORT(dlen, cp);
  BOUNDS_CHECK(cp, dlen);


  /* Begin case T_SIG: */

  /* Just read one variable --- the original reads several. */
  BOUNDS_CHECK(cp, SPACE_FOR_VARS);
  cp1 = cp;
  GETLONG(origTTL, cp1);

  /* Skip checks on times which are present in the original. */

  /* Copy over initial fields, which we read above. */
  cp1 = (u_char *)data;
  BOUNDS_CHECK(cp, SPACE_FOR_VARS);
  memcpy(cp1, cp, SPACE_FOR_VARS);
  cp += SPACE_FOR_VARS;
  cp1 += SPACE_FOR_VARS;

  /* Expand the domain name, set cp1 past the end of the uncompressed 
   * domain name. 
   */
  n = dn_expand(msg, eom, cp, (char *)cp1, (sizeof data));		
  if (n < 0) {
    return (-1);
  }
  cp += n;
  cp1 += strlen((char*)cp1)+1;

  /* Figure out the length of the "signature" to copy over and copy it. */
  n = dlen - (SPACE_FOR_VARS + n);
  if (n > (sizeof data) - (cp1 - (u_char *)data)) {
    return (-1);  /* out of room! */
  }
  /* OK */
  r_memcpy(cp1, cp, n);


  return 0;
}
Ejemplo n.º 7
0
static GVariant *
parse_res_ns (guchar  *answer,
              guchar  *end,
              guchar **p)
{
  gchar namebuf[1024];

  *p += dn_expand (answer, end, *p, namebuf, sizeof (namebuf));

  return g_variant_new ("(s)", namebuf);
}
Ejemplo n.º 8
0
static char	*get_name(unsigned char *msg, unsigned char *msg_end, unsigned char **msg_ptr)
{
	int		res;
	static char	buffer[MAX_STRING_LEN];

	if (-1 == (res = dn_expand(msg, msg_end, *msg_ptr, buffer, sizeof(buffer))))
		return NULL;

	*msg_ptr += res;

	return buffer;
}
Ejemplo n.º 9
0
bool
dnsparse::qparse (const u_char **cpp, question *qp)
{
  const u_char *cp = *cpp;
  int n = dn_expand (buf, eom, cp, qp->q_name, sizeof (qp->q_name));
  if (n < 0 || n >= MAXDNAME || cp + n + 4 > eom)
    return false;
  cp += n;
  GETSHORT (qp->q_type, cp);
  GETSHORT (qp->q_class, cp);
  *cpp = cp;
  return true;
}
Ejemplo n.º 10
0
const u_char *
p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
    char name[MAXDNAME];
    int n;

    if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
        return (NULL);
    if (name[0] == '\0')
        putc('.', file);
    else
        fputs(name, file);
    return (cp + n);
}
Ejemplo n.º 11
0
/*
 * krb5int_dns_nextans() - get next answer record
 *
 * Sets pp to NULL if no more records.
 */
int
krb5int_dns_nextans(struct krb5int_dns_state *ds,
		    const unsigned char **pp, int *lenp)
{
    int len;
    unsigned char *p;
    unsigned short ntype, nclass, rdlen;
#if !HAVE_DN_SKIPNAME
    char host[MAXDNAME];
#endif

    *pp = NULL;
    *lenp = 0;
    p = ds->ptr;

    while (ds->nanswers--) {
#if HAVE_DN_SKIPNAME
	len = dn_skipname(p, (unsigned char *)ds->ansp + ds->anslen);
#else
	len = dn_expand(ds->ansp, (unsigned char *)ds->ansp + ds->anslen,
			p, host, sizeof(host));
#endif
	if (len < 0 || !INCR_OK(ds->ansp, ds->anslen, p, len))
	    return -1;
	p += len;
	SAFE_GETUINT16(ds->ansp, ds->anslen, p, 2, ntype, out);
	/* Also skip 4 bytes of TTL */
	SAFE_GETUINT16(ds->ansp, ds->anslen, p, 6, nclass, out);
	SAFE_GETUINT16(ds->ansp, ds->anslen, p, 2, rdlen, out);

	if (!INCR_OK(ds->ansp, ds->anslen, p, rdlen))
	    return -1;
/* Solaris Kerberos - resync */
#if 0
	if (rdlen > INT_MAX)
	    return -1;
#endif
	if (nclass == ds->nclass && ntype == ds->ntype) {
	    *pp = p;
	    *lenp = rdlen;
	    ds->ptr = p + rdlen;
	    return 0;
	}
	p += rdlen;
    }
    return 0;
out:
    return -1;
}
Ejemplo n.º 12
0
/*
 * krb5int_dns_expand - wrapper for dn_expand()
 */
int
krb5int_dns_expand(struct krb5int_dns_state *ds, const unsigned char *p,
                   char *buf, int len)
{

#if HAVE_NS_NAME_UNCOMPRESS
    return ns_name_uncompress(ds->ansp,
                              (unsigned char *)ds->ansp + ds->anslen,
                              p, buf, (size_t)len);
#else
    return dn_expand(ds->ansp,
                     (unsigned char *)ds->ansp + ds->anslen,
                     p, buf, len);
#endif
}
Ejemplo n.º 13
0
char *
p_cdname(char *cp, char *msg, FILE *file)
{
	char name[MAXDNAME];
	int n;

	if ((n = dn_expand(msg, msg + 512, cp, name, sizeof(name))) < 0)
		return (NULL);
	if (name[0] == '\0') {
		name[0] = '.';
		name[1] = '\0';
	}
	fputs(name, file);
	return (cp + n);
}
Ejemplo n.º 14
0
static GVariant *
parse_res_mx (guchar  *answer,
              guchar  *end,
              guchar **p)
{
  gchar namebuf[1024];
  guint16 preference;

  GETSHORT (preference, *p);

  *p += dn_expand (answer, end, *p, namebuf, sizeof (namebuf));

  return g_variant_new ("(qs)",
                        preference,
                        namebuf);
}
Ejemplo n.º 15
0
const u_char *
p_fqnname (const u_char *cp, const u_char *msg, int msglen, char *name,
	   int namelen)
{
	int n, newlen;

	if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
		return (NULL);
	newlen = strlen(name);
	if (newlen == 0 || name[newlen - 1] != '.') {
		if (newlen + 1 >= namelen)	/* Lack space for final dot */
			return (NULL);
		else
			strcpy(name + newlen, ".");
	}
	return (cp + n);
}
Ejemplo n.º 16
0
static void fqdn_to_env(const char *name, const uint8_t *fqdn, size_t len)
{
	size_t buf_len = strlen(name);
	size_t buf_size = len + buf_len + 2;
	const uint8_t *fqdn_end = fqdn + len;
	char *buf = realloc(NULL, len + buf_len + 2);
	memcpy(buf, name, buf_len);
	buf[buf_len++] = '=';
	int l = 1;
	while (l > 0 && fqdn < fqdn_end) {
		l = dn_expand(fqdn, fqdn_end, fqdn, &buf[buf_len], buf_size - buf_len);
		fqdn += l;
		buf_len += strlen(&buf[buf_len]);
		buf[buf_len++] = ' ';
	}
	buf[buf_len - 1] = '\0';
	putenv(buf);
}
Ejemplo n.º 17
0
static GVariant *
parse_res_srv (guchar  *answer,
               guchar  *end,
               guchar **p)
{
  gchar namebuf[1024];
  guint16 priority, weight, port;

  GETSHORT (priority, *p);
  GETSHORT (weight, *p);
  GETSHORT (port, *p);
  *p += dn_expand (answer, end, *p, namebuf, sizeof (namebuf));

  return g_variant_new ("(qqqs)",
                        priority,
                        weight,
                        port,
                        namebuf);
}
Ejemplo n.º 18
0
char* getMailserver(const char* domain) {
	int len;
	char answer[NS_PACKETSZ];
	char *mailserver = malloc(NS_PACKETSZ);
	ns_msg msg;
	ns_rr rr;

	if(res_init() == -1) {
		return NULL;
	}
	len = res_query(domain,C_ANY,T_MX,answer,NS_PACKETSZ);
	if(len == -1) {
		return NULL;
	}
	/* return first MX record */	
	ns_initparse(answer,len,&msg);
	ns_parserr(&msg,ns_s_an,0,&rr);
	dn_expand(ns_msg_base(msg),ns_msg_base(msg)+ns_msg_size(msg),ns_rr_rdata(rr)+NS_INT16SZ,mailserver,NS_PACKETSZ);
	return mailserver; 
}
Ejemplo n.º 19
0
/* SRV rdata format:
 *            111111
 *  0123456789012345
 * +----------------+
 * |     priority   |
 * |----------------|
 * |     weight     |
 * |----------------|
 * |   port number  |
 * |----------------|
 * |                |
 * ~      name      ~
 * |                |
 * +----------------+
 */
struct srv_rdata* dns_srv_parser( unsigned char* msg, unsigned char* end,
								  unsigned char* eor,
								  unsigned char* rdata)
{
	struct srv_rdata* srv;
	unsigned short priority;
	unsigned short weight;
	unsigned short port;
	int len;
	char name[MAX_DNS_NAME];
	
	srv=0;
	if ((rdata+6+1)>eor) goto error;
	
	memcpy((void*)&priority, rdata, 2);
	memcpy((void*)&weight,   rdata+2, 2);
	memcpy((void*)&port,     rdata+4, 2);
	rdata+=6;
	if (dn_expand(msg, end, rdata, name, MAX_DNS_NAME-1)<0)
		goto error;
	len=strlen(name);
	if (len>255)
		goto error;
	/* alloc enought space for the struct + null terminated name */
	srv=local_malloc(sizeof(struct srv_rdata)-1+len+1);
	if (srv==0){
		LOG(L_ERR, "ERROR: dns_srv_parser: out of memory\n");
		goto error;
	}
	srv->priority=ntohs(priority);
	srv->weight=ntohs(weight);
	srv->port=ntohs(port);
	srv->name_len=len;
	memcpy(srv->name, name, srv->name_len);
	srv->name[srv->name_len]=0;
	
	return srv;
error:
	if (srv) local_free(srv);
	return 0;
}
Ejemplo n.º 20
0
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 */
}
Ejemplo n.º 21
0
/*  EBL rdata format:
 *  (see http://tools.ietf.org/html/draft-ietf-enum-branch-location-record-03)
 * one or several character strings:
 *  01234567
 * +--------+
 * | postion|
 * +-----------+
 * / separator /
 * +-----------+
 * /   apex    /
 * +----------+
 *
 * where separator is a character string ( 8 bit len, followed by len chars)
 * and apex is a domain-name.
 */
static struct ebl_rdata* dns_ebl_parser(unsigned char* msg, unsigned char* end,
										unsigned char* eor,
										unsigned char* rdata)
{
	struct ebl_rdata* ebl;
	int sep_len;
	int apex_len;
	char apex[MAX_DNS_NAME];
	
	ebl=0;
	/* check if len is at least 4 chars (minimum possible):
	     pos (1 byte) +  sep. (min 1 byte) + apex (min. 2 bytes) 
	   and also check if rdata+1 (pos) + 1 (sep. len) + sep_len + 1 is ok*/
	if (unlikely(((rdata+4)>eor)||((rdata+1+1+rdata[1]+2)>eor))) goto error;
	sep_len=rdata[1];
	if (unlikely(dn_expand(msg, end, rdata+1+1+sep_len,
							apex, MAX_DNS_NAME-1)==-1))
		goto error;
	apex_len=strlen(apex);
	/* alloc sizeof struct + space for the 2 null-terminated strings */
	ebl=local_malloc(sizeof(struct ebl_rdata)-1+sep_len+1+apex_len+1);
	if (ebl==0){
		LOG(L_ERR, "ERROR: dns_ebl_parser: out of memory\n");
		goto error;
	}
	ebl->position=rdata[0];
	ebl->separator=&ebl->str_table[0];
	ebl->apex=ebl->separator+sep_len+1;
	ebl->separator_len=sep_len;
	ebl->apex_len=apex_len;
	memcpy(ebl->separator, rdata+2, sep_len);
	ebl->separator[sep_len]=0;
	memcpy(ebl->apex, apex, apex_len);
	ebl->apex[apex_len]=0;
	
	return ebl;
error:
	if (ebl) local_free(ebl);
	return 0;
}
Ejemplo n.º 22
0
/*
 * initparse
 *
 * Skip header and question section of reply.  Set a pointer to the
 * beginning of the answer section, and prepare to iterate over
 * answer records.
 */
static int
initparse(struct krb5int_dns_state *ds)
{
    HEADER *hdr;
    unsigned char *p;
    unsigned short nqueries, nanswers;
    int len;
#if !HAVE_DN_SKIPNAME
    char host[MAXDNAME];
#endif

    if ((size_t) ds->anslen < sizeof(HEADER))
        return -1;

    hdr = (HEADER *)ds->ansp;
    p = ds->ansp;
    nqueries = ntohs((unsigned short)hdr->qdcount);
    nanswers = ntohs((unsigned short)hdr->ancount);
    p += sizeof(HEADER);

    /*
     * Skip query records.
     */
    while (nqueries--) {
#if HAVE_DN_SKIPNAME
        len = dn_skipname(p, (unsigned char *)ds->ansp + ds->anslen);
#else
        len = dn_expand(ds->ansp, (unsigned char *)ds->ansp + ds->anslen,
                        p, host, sizeof(host));
#endif
        if (len < 0 || !INCR_OK(ds->ansp, ds->anslen, p, len + 4))
            return -1;
        p += len + 4;
    }
    ds->ptr = p;
    ds->nanswers = nanswers;
    return 0;
}
Ejemplo n.º 23
0
static int
app_parse_srv(radiodns_app_t *app, ns_msg handle, ns_rr rr, char *dnbuf, radiodns_srv_t *srv)
{
	const unsigned char *rdata;
	
	(void) app;

	rdata = ns_rr_rdata(rr);
	srv->priority = ns_get16(rdata);
	rdata += NS_INT16SZ;

	srv->weight = ns_get16(rdata);
	rdata += NS_INT16SZ;
	
	srv->port = ns_get16(rdata);
	rdata += NS_INT16SZ;
	
	dn_expand(ns_msg_base(handle), ns_msg_base(handle) + ns_msg_size(handle), rdata, dnbuf, MAXDNAME);
	if(!(srv->target = strdup(dnbuf)))
	{
		return -2;
	}
	return 0;
}
static int
rrextract(u_char *msg, int msglen, u_char *rrp, u_char *dname, int namelen)
{
  u_char *eom, *cp, *cp1, *rdatap;
  u_int class, type, dlen;
  int n;
  u_char data[MAXDATA*2 + SPACE_FOR_VARS];
  data [(MAXDATA*2 + SPACE_FOR_VARS)-1] = EOS;

  cp = rrp;
  eom = msg + msglen;

  GETSHORT(dlen, cp);
  BOUNDS_CHECK(cp, dlen);

  /* Cut a bunch of stuff which we can reintroduce later. */

  n = dn_expand(msg, eom, cp, (char *)data, sizeof data);
	   
  if (n < 0 || n >= dlen) {
    return (-1);
  }

  if (nondet_int()) {
    return (-1);
  }
  cp += n;
  cp1 = data + strlen((char *)data) + 1;

  /* von mir eingefügt*/
  assert(dlen - n <= sizeof data - (strlen((char *)data) + 1));
  /* BAD */
  r_memcpy(cp1, cp, dlen - n);

  return 0;
}
Ejemplo n.º 25
0
/*
 * int res_nameinquery(name, type, class, buf, eom)
 *    look for (name,type,class) in the query section of packet (buf,eom)
 * returns:
 *    -1 : format error
 *     0 : not found
 *    >0 : found
 * author:
 *     paul vixie, 29may94
 */
int res_nameinquery (const char *name, int type, int Class,
                     const u_char *buf, const u_char *eom)
{
  const u_char *cp = buf + HFIXEDSZ;
  int   qdcount    = ntohs (((HEADER*)buf)->qdcount);

  while (qdcount-- > 0)
  {
    char tname[MAXDNAME+1];
    int n, ttype, tclass;

    n = dn_expand (buf, eom, cp, tname, sizeof(tname));
    if (n < 0)
       return (-1);
    cp += n;
    ttype  = _getshort (cp);
    cp    += INT16SZ;
    tclass = _getshort (cp);
    cp    += INT16SZ;
    if (ttype == type && tclass == Class && !stricmp(tname,name))
       return (1);
  }
  return (0);
}
Ejemplo n.º 26
0
int
getsrv(const char *name,struct srventry **list)
{
    unsigned char answer[2048];
    int r,srvcount=0;
    unsigned char *pt,*emsg;
    u16 count,dlen;
    HEADER *header=(HEADER *)answer;

    *list=NULL;

    r=res_query(name,C_IN,T_SRV,answer,2048);
    if(r<sizeof(HEADER) || r>2048)
        return -1;

    if(header->rcode==NOERROR && (count=ntohs(header->ancount)))
    {
        int i,rc;

        emsg=&answer[r];
        pt=&answer[sizeof(HEADER)];

        /* Skip over the query */

        rc=dn_skipname(pt,emsg);
        if(rc==-1)
            goto fail;

        pt+=rc+QFIXEDSZ;

        while(count-->0 && pt<emsg)
        {
            struct srventry *srv=NULL;
            u16 type,class;

            srv=realloc(*list,(srvcount+1)*sizeof(struct srventry));
            if(!srv)
                goto fail;

            *list=srv;
            memset(&(*list)[srvcount],0,sizeof(struct srventry));
            srv=&(*list)[srvcount];
            srvcount++;

            rc=dn_skipname(pt,emsg); /* the name we just queried for */
            if(rc==-1)
                goto fail;
            pt+=rc;

            /* Truncated message? */
            if((emsg-pt)<16)
                goto fail;

            type=*pt++ << 8;
            type|=*pt++;
            /* We asked for SRV and got something else !? */
            if(type!=T_SRV)
                goto fail;

            class=*pt++ << 8;
            class|=*pt++;
            /* We asked for IN and got something else !? */
            if(class!=C_IN)
                goto fail;

            pt+=4; /* ttl */
            dlen=*pt++ << 8;
            dlen|=*pt++;
            srv->priority=*pt++ << 8;
            srv->priority|=*pt++;
            srv->weight=*pt++ << 8;
            srv->weight|=*pt++;
            srv->port=*pt++ << 8;
            srv->port|=*pt++;

            /* Get the name.  2782 doesn't allow name compression, but
               dn_expand still works to pull the name out of the
               packet. */
            rc=dn_expand(answer,emsg,pt,srv->target,MAXDNAME);
            if(rc==1 && srv->target[0]==0) /* "." */
                goto noanswer;
            if(rc==-1)
                goto fail;
            pt+=rc;
            /* Corrupt packet? */
            if(dlen!=rc+6)
                goto fail;

#if 0
            printf("count=%d\n",srvcount);
            printf("priority=%d\n",srv->priority);
            printf("weight=%d\n",srv->weight);
            printf("port=%d\n",srv->port);
            printf("target=%s\n",srv->target);
#endif
        }

        /* Now we have an array of all the srv records. */

        /* Order by priority */
        qsort(*list,srvcount,sizeof(struct srventry),priosort);

        /* For each priority, move the zero-weighted items first. */
        for(i=0; i<srvcount; i++)
        {
            int j;

            for(j=i; j<srvcount && (*list)[i].priority==(*list)[j].priority; j++)
            {
                if((*list)[j].weight==0)
                {
                    /* Swap j with i */
                    if(j!=i)
                    {
                        struct srventry temp;

                        memcpy(&temp,&(*list)[j],sizeof(struct srventry));
                        memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
                        memcpy(&(*list)[i],&temp,sizeof(struct srventry));
                    }

                    break;
                }
            }
        }

        /* Run the RFC-2782 weighting algorithm.  We don't need very
        high quality randomness for this, so regular libc srand/rand
         is sufficient. */
        srand(time(NULL)*getpid());

        for(i=0; i<srvcount; i++)
        {
            int j;
            float prio_count=0,chose;

            for(j=i; j<srvcount && (*list)[i].priority==(*list)[j].priority; j++)
            {
                prio_count+=(*list)[j].weight;
                (*list)[j].run_count=prio_count;
            }

            chose=prio_count*rand()/RAND_MAX;

            for(j=i; j<srvcount && (*list)[i].priority==(*list)[j].priority; j++)
            {
                if(chose<=(*list)[j].run_count)
                {
                    /* Swap j with i */
                    if(j!=i)
                    {
                        struct srventry temp;

                        memcpy(&temp,&(*list)[j],sizeof(struct srventry));
                        memcpy(&(*list)[j],&(*list)[i],sizeof(struct srventry));
                        memcpy(&(*list)[i],&temp,sizeof(struct srventry));
                    }
                    break;
                }
            }
        }
    }
Ejemplo n.º 27
0
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;
}
Ejemplo n.º 28
0
CAMLprim value mlresolv_query(value vdname, value vclass, value vtype)
{
  union {
    HEADER hdr;              /* defined in resolv.h */
    u_char buf[PACKETSZ];    /* defined in arpa/nameser.h */
  } response;
  int rc;

  u_char *cp, *tcp;
  u_char *eom;

  char r_name[MAXDNAME+1];
  u_short r_class;
  u_short r_type;
  u_int32_t r_ttl;
  u_short r_len;

  int ancount, qdcount;

  value vres = Val_emptylist;

  if(vtype == caml_hash_variant("PTR")) {
    int a, b, c, d;
    a = b = c = d = 0;
    sscanf(String_val(vdname), "%u.%u.%u.%u", &a, &b, &c, &d);
    sprintf(r_name, "%u.%u.%u.%u.in-addr.arpa", d, c, b, a);
    rc = res_query(r_name,
		   mlvariant_to_c(rr_class, vclass),
		   mlvariant_to_c(rr_type, vtype),
		   (u_char*)&response, sizeof(response));
  } else
    rc = res_query(String_val(vdname),
		   mlvariant_to_c(rr_class, vclass),
		   mlvariant_to_c(rr_type, vtype),
		   (u_char*)&response, sizeof(response));

  if (rc < 0) {
    switch (h_errno) {
    case NETDB_INTERNAL:  
      mlresolv_error(errno);
    case HOST_NOT_FOUND:  /* Authoritative Answer Host not found */
      raise_constant(*mlresolv_host_not_found_exn);
    case TRY_AGAIN:       /* Non-Authoritative Host not found, or SERVERFAIL */
      raise_constant(*mlresolv_try_again_exn);
    case NO_RECOVERY:
      raise_constant(*mlresolv_no_recovery_exn);
    case NO_DATA:         /* Valid name, no data record of requested type */
      raise_constant(*mlresolv_no_data_exn);
    case NETDB_SUCCESS:   /* no problem */
    defaykt:
      failwith("res_query: unknown error");
    }
  }

  cp = (u_char *)&response.buf + sizeof(HEADER);
  eom = (u_char *)&response.buf + rc;

  ancount = ntohs(response.hdr.ancount) + ntohs(response.hdr.nscount);
  qdcount = ntohs(response.hdr.qdcount);
  for (; (qdcount > 0) && (cp < eom); qdcount--) {
    rc = dn_skipname(cp, eom) + QFIXEDSZ;
    if(rc < 0)
      failwith("dn_skipname failed");
    cp += rc;
  }

  for (; (ancount > 0) && (cp < eom); ancount--) {
    value vrdata, vfields = Val_unit;

    rc = dn_expand(response.buf, eom, cp, (void*)r_name, MAXDNAME);
    if(rc < 0)
      failwith("dn_expand1 failed");

    cp += rc;

    NS_GET16(r_type, cp);
    NS_GET16(r_class, cp);
    NS_GET32(r_ttl, cp);
    NS_GET16(r_len, cp);

    if(cp + r_len > eom) /* is this check necessary? */
      r_len = eom - cp;

    tcp = cp;

    switch(r_type) {

    case ns_t_a:
      /* if(r_class == ns_c_in || r_class == ns_c_hs) { */

      if(INADDRSZ > r_len)
	vfields = copy_string("");
      else {
	struct in_addr inaddr;
	char *address;

	bcopy(tcp, (char *)&inaddr, INADDRSZ);
	address = (char *)inet_ntoa(inaddr);
	vfields = copy_string(address);
      }
      break;

    case ns_t_cname:
    case ns_t_ns:
    case ns_t_mb:
    case ns_t_md:
    case ns_t_mf:
    case ns_t_mg:
    case ns_t_mr:
    case ns_t_ptr: 
    case ns_t_nsap_ptr:
      {
	char r_name[MAXDNAME+1];
	rc = dn_expand(response.buf, eom, cp, (void *) r_name, MAXDNAME);
	if(rc < 0)
	  vfields = copy_string("");
	else
	  vfields = copy_string(r_name);
	break;
    }

    case ns_t_null:  /* max up to 65535 */
      vfields = caml_alloc_string(r_len);
      memmove(String_val(vfields), cp, r_len);
      break;

    case ns_t_txt: {
      int txtlen, rdata_len = r_len;
      value newcons, txt;
      vfields = Val_emptylist;

      while(tcp < eom && *tcp <= rdata_len) {
	txtlen = *tcp++;
	txt = caml_alloc_string(txtlen);
	memmove(String_val(txt), tcp, txtlen);
	tcp += txtlen;
	rdata_len -= txtlen+1;

	newcons = alloc_small(2, 0);
	Field(newcons, 0) = txt;
	Field(newcons, 1) = vfields;
	vfields = newcons;
      }
      break;
    }

    case ns_t_srv:
      if(INT16SZ * 3 <= r_len) {
	char r_name[MAXDNAME+1];
	int prio, weight, port;
      
	NS_GET16(prio, tcp);
	NS_GET16(weight, tcp);
	NS_GET16(port, tcp);

	rc = dn_expand(response.buf, eom, tcp, (void *) r_name, MAXDNAME);

	vfields = alloc_small(4, 0);
	Field(vfields, 0) = Val_int(prio);
	Field(vfields, 1) = Val_int(weight);
	Field(vfields, 2) = Val_int(port);
      
	if(rc < 0)
	  Field(vfields, 3) = copy_string("");
	else
	  Field(vfields, 3) = copy_string(r_name);
      }
      break;

    case ns_t_mx:
    case ns_t_rt:
    case ns_t_afsdb:
      if(INT16SZ <= r_len) {
	char r_name[MAXDNAME+1];
	int prio;

	NS_GET16(prio, tcp);

	rc = dn_expand(response.buf, eom, tcp, (void *) r_name, MAXDNAME);

	vfields = alloc_small(2, 0);
	Field(vfields, 0) = Val_int(prio);

	if(rc < 0)
	  Field(vfields, 1) = copy_string("");
	else
	  Field(vfields, 1) = copy_string(r_name);
      }
      break;

    case ns_t_soa: 
      {
	char mname[MAXDNAME+1];
	char rname[MAXDNAME+1];
	u_int serial, minimum;
	int refresh, retry, expire;
	
	if((rc = dn_expand(response.buf, eom, tcp, (void *)mname, MAXDNAME)) < 0)
	  break;
	tcp += rc;
	
	if((rc = dn_expand(response.buf, eom, tcp, (void *)rname, MAXDNAME)) < 0)
	  break;
	tcp += rc;
	
	if (tcp - cp + INT32SZ * 5 > r_len)
	  break;
      
	NS_GET32(serial, tcp);
	NS_GET32(refresh, tcp);
	NS_GET32(retry, tcp);
	NS_GET32(expire, tcp);
	NS_GET32(minimum, tcp);
      
	vfields = alloc_small(7, 0);
	Field(vfields, 0) = copy_string(mname);
	Field(vfields, 1) = copy_string(rname);
	Field(vfields, 2) = Val_int(serial);
	Field(vfields, 3) = Val_int(refresh);
	Field(vfields, 4) = Val_int(retry);
	Field(vfields, 5) = Val_int(expire);
	Field(vfields, 6) = Val_int(minimum);
      }
      break;

    case ns_t_minfo: 
      {
	char rmailbx[MAXDNAME+1];
	char emailbx[MAXDNAME+1];

	if((rc = dn_expand(response.buf, eom, tcp, rmailbx, MAXDNAME)) < 0)
	  break;
	tcp += rc;
	if((rc = dn_expand(response.buf, eom, tcp, emailbx, MAXDNAME)) < 0)
	  break;

	vfields = alloc_small(2, 0);
	Field(vfields, 0) = copy_string(rmailbx);
	Field(vfields, 1) = copy_string(emailbx);
      }
      break;

      /* two strings */
    case ns_t_hinfo:
    case ns_t_isdn: /* <ISDN-address> <sa> */
    case ns_t_nsap:
      if(r_len > 0 && *tcp < r_len) {
	value str1;
	value str2;

	rc = *tcp++;
	if(r_type == ns_t_nsap) {
	  int result = 0;
	  for(; rc; rc--, tcp++)
	    result += result * 10 + (*tcp - 0x38);
	  str1 = Val_int(result);
	}
	else {
	  str1 = caml_alloc_string(rc);
	  memmove(String_val(str1), tcp, rc);
	  tcp += rc;
	}      
	if(rc + 1 > r_len && *tcp + rc + 2 >= r_len) {
	  rc = *tcp++;
	  str2 = caml_alloc_string(rc);
	  memmove(String_val(str2), tcp, rc);
	}
	else
	  str2 = copy_string("");

	vfields = caml_alloc_small(2, 0);
	Field(vfields, 0) = str1;
	Field(vfields, 1) = str2;
      }
      break;

    case ns_t_wks:
      
      if(INADDRSZ + 1 <= r_len) {
	struct in_addr inaddr;
	char* address;
	u_short protocol;
	value bitmap;

	bcopy(tcp, (char *) &inaddr, INADDRSZ);
	address = (char*) inet_ntoa(inaddr);
	tcp += INADDRSZ;
      
	protocol = *tcp++;  /* getprotobynumber(*cp) */
      
	/*
	  n = 0;
	  while (cp < eom) {
	  c = *cp++;
	  do {
	  if (c & 0200) {
	  int port;
	  
	  port = htons((u_short)n);
	  if (protocol != NULL)
	  service = getservbyport(port, protocol->p_name);
	  else
	  service = NULL;
	  
	  if (service != NULL)
	  doprintf((" %s", service->s_name));
	  else
	  doprintf((" %s", dtoa(n)));
	}
	c <<= 1;
	} while (++n & 07);
	}
	doprintf((" )"));
	*/
      
	bitmap = caml_alloc_string(r_len - INADDRSZ - 1);
	memmove(String_val(bitmap), tcp, eom - tcp);
      
	vfields = alloc_small(4, 0);
	Field(vfields, 0) = copy_string(address);
	Field(vfields, 1) = Val_int(protocol);
	Field(vfields, 2) = bitmap;
      }
      break;

    case ns_t_rp:  /* <mbox-dname> <txt-dname> */
      {
	char rname1[MAXDNAME+1];
	char rname2[MAXDNAME+1];

	rc = dn_expand(response.buf, eom, tcp, rname1, MAXDNAME);
	if(rc < 0)
	  break;
	tcp += rc;
	
	rc = dn_expand(response.buf, eom, tcp, rname2, MAXDNAME);
	if(rc < 0)
	  break;

	vfields = alloc_small(2, 0);
	Field(vfields, 0) = copy_string(rname1);
	Field(vfields, 1) = copy_string(rname2);
      }
      break;

    case ns_t_x25: /* <PSDN-address> */
      if(r_len > 0 && *tcp >= r_len) {
	rc = *tcp++;
	vfields = caml_alloc_string(rc);
	memmove(String_val(vfields), tcp, rc);
      }
      else
	vfields = copy_string("");
      break;
      

    case ns_t_px:
      if(r_len > INT16SZ) {
	int pref;
	char rname1[MAXDNAME];
	char rname2[MAXDNAME];

	NS_GET16(pref, tcp);
	rc = dn_expand(response.buf, eom, tcp, rname1, MAXDNAME);
	if(rc < 0)
	  break;
	tcp += rc;
	rc = dn_expand(response.buf, eom, tcp, rname2, MAXDNAME);
	if(rc < 0)
	  break;
	tcp += rc;

	vfields = alloc_small(2, 0);
	Field(vfields, 0) = copy_string(rname1);
	Field(vfields, 1) = copy_string(rname2);
      }
      break;

    case ns_t_gpos:
      if(r_len > 0 && *tcp <= r_len) {
	float f1, f2, f3;
	char *tmp;
	rc = *tcp++;

	tmp = (char *) malloc(rc + 1);
	bcopy(tcp, tmp, rc);
	tmp[rc] = '\0';
	f1 = atof(tmp);
	tcp += rc;
	
	if(tcp < eom && tcp + *tcp <= eom) {
	  if(*tcp > rc)
	    tmp = realloc(tmp, *tcp);
	  rc = *tcp++;
	  bcopy(tcp, tmp, rc);
	  tmp[rc] = '\0';
	  f2 = atof(tmp);
	  tcp += rc;
	}
	else
	  f2 = 0.0;

	if(tcp < eom && tcp + *tcp <= eom) {
	  if(*tcp > rc)
	    tmp = realloc(tmp, *tcp);
	  rc = *tcp++;
	  bcopy(tcp, tmp, rc);
	  tmp[rc] = '\0';
	  f3 = atof(tmp);
	  tcp += rc;
	}
	else
	  f3 = 0.0;

	free(tmp);

	vfields = alloc_small(3, 0);
	Field(vfields, 0) = copy_double((double)f1);
	Field(vfields, 1) = copy_double((double)f2);
	Field(vfields, 2) = copy_double((double)f3);
      }	
      break;

    case ns_t_loc:
      failwith("LOC not implemented");

      /*
      if(r_len > 0 && *tcp != 0)
	failwith("Invalid version in LOC RDATA");

      if(r_len > 0) {
	rc = INT
      n = INT32SZ + 3*INT32SZ;
      if (check_size(rname, type, cp, msg, eor, n) < 0)
	break;
      c = _getlong(cp);
      cp += INT32SZ;
      
      n = _getlong(cp);
      doprintf(("\t%s ", pr_spherical(n, "N", "S")));
      cp += INT32SZ;
      
      n = _getlong(cp);
      doprintf((" %s ", pr_spherical(n, "E", "W")));
      cp += INT32SZ;
      
      n = _getlong(cp);
      doprintf((" %sm ", pr_vertical(n, "", "-")));
      cp += INT32SZ;
      
      doprintf((" %sm", pr_precision((c >> 16) & 0xff)));
      doprintf((" %sm", pr_precision((c >>  8) & 0xff)));
      doprintf((" %sm", pr_precision((c >>  0) & 0xff)));
      break;
      */

      /*
    case T_UID:
    case T_GID:
      if(INT32SZ <= r_len)
	NS_GET32(rc, cp);
      
      if (dlen == INT32SZ) {
        n = _getlong(cp);
	doprintf(("\t%s", dtoa(n)));
	cp += INT32SZ;
      }
      break;
      
    case T_UINFO:
      doprintf(("\t\"%s\"", stoa(cp, dlen, TRUE)));
      cp += dlen;
      break;

    case T_UNSPEC:
      cp += dlen;
      break;
      
    case T_AAAA:
      if (dlen == IPNGSIZE) {
	doprintf(("\t%s", ipng_ntoa(cp)));
	cp += IPNGSIZE;
      }
      break;
      
    case T_SIG:
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      if (n >= T_FIRST && n <= T_LAST)
	doprintf(("\t%s", pr_type(n)));
      else
	doprintf(("\t%s", dtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" %s", dtoa(n)));
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" %s", dtoa(n)));
      
      n = 3*INT32SZ + INT16SZ;
      if (check_size(rname, type, cp, msg, eor, n) < 0)
	break;
      doprintf((" ("));
      
      n = _getlong(cp);
      doprintf(("\n\t\t\t%s", dtoa(n)));
      doprintf(("\t\t;original ttl"));
      cp += INT32SZ;
      
      n = _getlong(cp);
      doprintf(("\n\t\t\t%s", pr_date(n)));
      doprintf(("\t;signature expiration"));
      cp += INT32SZ;
      
      n = _getlong(cp);
      doprintf(("\n\t\t\t%s", pr_date(n)));
      doprintf(("\t;signature inception"));
      cp += INT32SZ;
      
      n = _getshort(cp);
      doprintf(("\n\t\t\t%s", dtoa(n)));
      doprintf(("\t\t;key tag"));
      cp += INT16SZ;
      
      n = expand_name(rname, type, cp, msg, eom, dname);
      if (n < 0)
	break;
      doprintf(("\n\t\t\t%s", pr_name(dname)));
      cp += n;
      
      if (cp < eor) {
	register char *buf;
	register int size;
	  
	n = eor - cp;
	buf = base_ntoa(cp, n);
	size = strlength(buf);
	cp += n;
	  
	while ((n = (size > 64) ? 64 : size) > 0) {
	  doprintf(("\n\t%s", stoa((u_char *)buf, n, FALSE)));
	  buf += n; size -= n;
	}
      }
      doprintf(("\n\t\t\t)"));
      break;
      
    case T_KEY:
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf(("\t0x%s", xtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
        doprintf((" %s", dtoa(n)));
	
        if (check_size(rname, type, cp, msg, eor, 1) < 0)
	  break;
        n = *cp++;
        doprintf((" %s", dtoa(n)));
	
        if (cp < eor) {
	  register char *buf;
	  register int size;
	    
	  n = eor - cp;
	  buf = base_ntoa(cp, n);
	  size = strlength(buf);
	  cp += n;
	    
	  doprintf((" ("));
	  while ((n = (size > 64) ? 64 : size) > 0) {
	    doprintf(("\n\t%s", stoa((u_char *)buf, n, FALSE)));
	    buf += n; size -= n;
	  }
	  doprintf(("\n\t\t\t)"));
	}
        break;
	
    case T_NXT:
      n = expand_name(rname, type, cp, msg, eom, dname);
      if (n < 0)
	break;
      doprintf(("\t%s", pr_name(dname)));
      cp += n;
      
      n = 0;
      while (cp < eor) {
	c = *cp++;
	do {
	  if (c & 0200) {
	    if (n >= T_FIRST && n <= T_LAST)
	      doprintf((" %s", pr_type(n)));
	    else
	      doprintf((" %s", dtoa(n)));
                }
	  c <<= 1;
	} while (++n & 07);
      }
      break;
      
    case T_NAPTR:
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf(("\t%s", dtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf((" %s", dtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" \"%s\"", stoa(cp, n, TRUE)));
      cp += n;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" \"%s\"", stoa(cp, n, TRUE)));
      cp += n;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" \"%s\"", stoa(cp, n, TRUE)));
      cp += n;
      
      n = expand_name(rname, type, cp, msg, eom, dname);
      if (n < 0)
	break;
      doprintf((" %s", pr_name(dname)));
      cp += n;
      break;
      
    case T_KX:
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf(("\t%s", dtoa(n)));
      cp += INT16SZ;
      
      n = expand_name(rname, type, cp, msg, eom, dname);
      if (n < 0)
	break;
      doprintf((" %s", pr_name(dname)));
      cp += n;
      break;
      
    case T_CERT:
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf(("\t%s", dtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, INT16SZ) < 0)
	break;
      n = _getshort(cp);
      doprintf((" %s", dtoa(n)));
      cp += INT16SZ;
      
      if (check_size(rname, type, cp, msg, eor, 1) < 0)
	break;
      n = *cp++;
      doprintf((" %s", dtoa(n)));
      
      if (cp < eor) {
	register char *buf;
	register int size;
	
	n = eor - cp;
	buf = base_ntoa(cp, n);
	size = strlength(buf);
	cp += n;
	
	doprintf((" ("));
	while ((n = (size > 64) ? 64 : size) > 0) {
	  doprintf(("\n\t%s", stoa((u_char *)buf, n, FALSE)));
	  buf += n; size -= n;
	}
	doprintf(("\n\t\t\t)"));
      }
      break;

    case T_EID:
      failwith("EID not implemented");
      break;

    case T_NIMLOC:
      failwith("NIMLOC not implemented");
      break;

    case T_ATMA:
      failwith("ATMA not implemented");

      */

    default:
      failwith("unknown RDATA type");
    }

    if(vfields != Val_unit) {
      value vrecord, vrdata, newcons;

      Begin_root(vres);

      vrecord = alloc_small(5, 0);
      Field(vrecord, 0) = copy_string(r_name);
      Field(vrecord, 1) = c_to_mlvariant(rr_type, r_type);
      Field(vrecord, 2) = c_to_mlvariant(rr_class, r_class);
      Field(vrecord, 3) = Val_int(r_ttl);
      vrdata = alloc_small(2, 0);
      Field(vrdata, 0) = c_to_mlvariant(rr_type, r_type);
      Field(vrdata, 1) = vfields;
      Field(vrecord, 4) = vrdata;

      newcons = alloc_small(2, 0);
      Field(newcons, 0) = vrecord;
      Field(newcons, 1) = vres;
      vres = newcons;
      End_roots();
      vrdata = Val_unit;
    }
    cp += r_len;
  }
  return vres;
}
Ejemplo n.º 29
0
bool HHVM_FUNCTION(getmxrr, const String& hostname,
                   VRefParam mxhostsRef,
                   VRefParam weightsRef /* = null */) {
    IOStatusHelper io("dns_get_mx", hostname.data());
    int count, qdc;
    unsigned short type, weight;
    unsigned char ans[MAXPACKET];
    char buf[MAXHOSTNAMELEN];
    unsigned char *cp, *end;

    Array mxhosts;
    Array weights;
    SCOPE_EXIT {
        mxhostsRef = mxhosts;
        weightsRef = weights;
    };

    /* Go! */
    struct __res_state *res;
    res = ResolverInit::s_res.get()->getResolver();
    if (res == NULL) {
        return false;
    }

    int i = res_nsearch(res, hostname.data(), C_IN, DNS_T_MX,
                        (unsigned char*)&ans, sizeof(ans));
    if (i < 0) {
        res_nclose(res);
        php_dns_free_res(res);
        return false;
    }
    if (i > (int)sizeof(ans)) {
        i = sizeof(ans);
    }
    HEADER *hp = (HEADER *)&ans;
    cp = (unsigned char *)&ans + HFIXEDSZ;
    end = (unsigned char *)&ans +i;
    for (qdc = ntohs((unsigned short)hp->qdcount); qdc--; cp += i + QFIXEDSZ) {
        if ((i = dn_skipname(cp, end)) < 0 ) {
            res_nclose(res);
            php_dns_free_res(res);
            return false;
        }
    }
    count = ntohs((unsigned short)hp->ancount);
    while (--count >= 0 && cp < end) {
        if ((i = dn_skipname(cp, end)) < 0 ) {
            res_nclose(res);
            php_dns_free_res(res);
            return false;
        }
        cp += i;
        GETSHORT(type, cp);
        cp += INT16SZ + INT32SZ;
        GETSHORT(i, cp);
        if (type != DNS_T_MX) {
            cp += i;
            continue;
        }
        GETSHORT(weight, cp);
        if ((i = dn_expand(ans, end, cp, buf, sizeof(buf)-1)) < 0) {
            res_nclose(res);
            php_dns_free_res(res);
            return false;
        }
        cp += i;
        mxhosts.append(String(buf, CopyString));
        weights.append(weight);
    }
    res_nclose(res);
    php_dns_free_res(res);
    return true;
}
Ejemplo n.º 30
0
static unsigned char *php_parserr(unsigned char *cp, unsigned char* end,
                                  querybuf *answer,
                                  int type_to_fetch, bool store,
                                  Array &subarray) {
    unsigned short type, cls ATTRIBUTE_UNUSED, dlen;
    unsigned long ttl;
    int64_t n, i;
    unsigned short s;
    unsigned char *tp, *p;
    char name[MAXHOSTNAMELEN];
    int have_v6_break = 0, in_v6_break = 0;

    n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2);
    if (n < 0) {
        return NULL;
    }
    cp += n;

    CHECKCP(10);
    GETSHORT(type, cp);
    GETSHORT(cls, cp);
    GETLONG(ttl, cp);
    GETSHORT(dlen, cp);
    CHECKCP(dlen);
    if (type_to_fetch != T_ANY && type != type_to_fetch) {
        cp += dlen;
        return cp;
    }

    if (!store) {
        cp += dlen;
        return cp;
    }

    subarray.set(s_host, String(name, CopyString));
    switch (type) {
    case DNS_T_A:
        CHECKCP(4);
        subarray.set(s_type, s_A);
        snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
        subarray.set(s_ip, String(name, CopyString));
        cp += dlen;
        break;
    case DNS_T_MX:
        CHECKCP(2);
        subarray.set(s_type, s_MX);
        GETSHORT(n, cp);
        subarray.set(s_pri, n);
    /* no break; */
    case DNS_T_CNAME:
        if (type == DNS_T_CNAME) {
            subarray.set(s_type, s_CNAME);
        }
    /* no break; */
    case DNS_T_NS:
        if (type == DNS_T_NS) {
            subarray.set(s_type, s_NS);
        }
    /* no break; */
    case DNS_T_PTR:
        if (type == DNS_T_PTR) {
            subarray.set(s_type, s_PTR);
        }
        n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_target, String(name, CopyString));
        break;
    case DNS_T_HINFO:
        /* See RFC 1010 for values */
        subarray.set(s_type, s_HINFO);
        CHECKCP(1);
        n = *cp & 0xFF;
        cp++;
        CHECKCP(n);
        subarray.set(s_cpu, String((const char *)cp, n, CopyString));
        cp += n;
        CHECKCP(1);
        n = *cp & 0xFF;
        cp++;
        CHECKCP(n);
        subarray.set(s_os, String((const char *)cp, n, CopyString));
        cp += n;
        break;
    case DNS_T_TXT: {
        int l1 = 0, l2 = 0;

        String s = String(dlen, ReserveString);
        tp = (unsigned char *)s.bufferSlice().ptr;

        while (l1 < dlen) {
            n = cp[l1];
            if ((n + l1) > dlen) {
                // bad record, don't set anything
                break;
            }
            memcpy(tp + l1 , cp + l1 + 1, n);
            l1 = l1 + n + 1;
            l2 = l2 + n;
        }
        s.setSize(l2);
        cp += dlen;

        subarray.set(s_type, s_TXT);
        subarray.set(s_txt, s);
        break;
    }
    case DNS_T_SOA:
        subarray.set(s_type, s_SOA);
        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_mname, String(name, CopyString));
        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_rname, String(name, CopyString));
        CHECKCP(5*4);
        GETLONG(n, cp);
        subarray.set(s_serial, n);
        GETLONG(n, cp);
        subarray.set(s_refresh, n);
        GETLONG(n, cp);
        subarray.set(s_retry, n);
        GETLONG(n, cp);
        subarray.set(s_expire, n);
        GETLONG(n, cp);
        subarray.set(s_minimum_ttl, n);
        break;
    case DNS_T_AAAA:
        tp = (unsigned char *)name;
        CHECKCP(8*2);
        for (i = 0; i < 8; i++) {
            GETSHORT(s, cp);
            if (s != 0) {
                if (tp > (u_char *)name) {
                    in_v6_break = 0;
                    tp[0] = ':';
                    tp++;
                }
                tp += sprintf((char *)tp, "%x", s);
            } else {
                if (!have_v6_break) {
                    have_v6_break = 1;
                    in_v6_break = 1;
                    tp[0] = ':';
                    tp++;
                } else if (!in_v6_break) {
                    tp[0] = ':';
                    tp++;
                    tp[0] = '0';
                    tp++;
                }
            }
        }
        if (have_v6_break && in_v6_break) {
            tp[0] = ':';
            tp++;
        }
        tp[0] = '\0';
        subarray.set(s_type, s_AAAA);
        subarray.set(s_ipv6, String(name, CopyString));
        break;
    case DNS_T_A6:
        p = cp;
        subarray.set(s_type, s_A6);
        CHECKCP(1);
        n = ((int)cp[0]) & 0xFF;
        cp++;
        subarray.set(s_masklen, n);
        tp = (unsigned char *)name;
        if (n > 15) {
            have_v6_break = 1;
            in_v6_break = 1;
            tp[0] = ':';
            tp++;
        }
        if (n % 16 > 8) {
            /* Partial short */
            if (cp[0] != 0) {
                if (tp > (u_char *)name) {
                    in_v6_break = 0;
                    tp[0] = ':';
                    tp++;
                }
                sprintf((char *)tp, "%x", cp[0] & 0xFF);
            } else {
                if (!have_v6_break) {
                    have_v6_break = 1;
                    in_v6_break = 1;
                    tp[0] = ':';
                    tp++;
                } else if (!in_v6_break) {
                    tp[0] = ':';
                    tp++;
                    tp[0] = '0';
                    tp++;
                }
            }
            cp++;
        }
        for (i = (n + 8)/16; i < 8; i++) {
            CHECKCP(2);
            GETSHORT(s, cp);
            if (s != 0) {
                if (tp > (u_char *)name) {
                    in_v6_break = 0;
                    tp[0] = ':';
                    tp++;
                }
                tp += sprintf((char*)tp,"%x",s);
            } else {
                if (!have_v6_break) {
                    have_v6_break = 1;
                    in_v6_break = 1;
                    tp[0] = ':';
                    tp++;
                } else if (!in_v6_break) {
                    tp[0] = ':';
                    tp++;
                    tp[0] = '0';
                    tp++;
                }
            }
        }
        if (have_v6_break && in_v6_break) {
            tp[0] = ':';
            tp++;
        }
        tp[0] = '\0';
        subarray.set(s_ipv6, String(name, CopyString));
        if (cp < p + dlen) {
            n = dn_expand(answer->qb2, end, cp, name,
                          (sizeof name) - 2);
            if (n < 0) {
                return NULL;
            }
            cp += n;
            subarray.set(s_chain, String(name, CopyString));
        }
        break;
    case DNS_T_SRV:
        CHECKCP(3*2);
        subarray.set(s_type, s_SRV);
        GETSHORT(n, cp);
        subarray.set(s_pri, n);
        GETSHORT(n, cp);
        subarray.set(s_weight, n);
        GETSHORT(n, cp);
        subarray.set(s_port, n);
        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_target, String(name, CopyString));
        break;
    case DNS_T_NAPTR:
        CHECKCP(2*2);
        subarray.set(s_type, s_NAPTR);
        GETSHORT(n, cp);
        subarray.set(s_order, n);
        GETSHORT(n, cp);
        subarray.set(s_pref, n);

        CHECKCP(1);
        n = (cp[0] & 0xFF);
        ++cp;
        CHECKCP(n);
        subarray.set(s_flags, String((const char *)cp, n, CopyString));
        cp += n;

        CHECKCP(1);
        n = (cp[0] & 0xFF);
        ++cp;
        CHECKCP(n);
        subarray.set(s_services, String((const char *)cp, n, CopyString));
        cp += n;

        CHECKCP(1);
        n = (cp[0] & 0xFF);
        ++cp;
        CHECKCP(n);
        subarray.set(s_regex, String((const char *)cp, n, CopyString));
        cp += n;

        n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2);
        if (n < 0) {
            return NULL;
        }
        cp += n;
        subarray.set(s_replacement, String(name, CopyString));
        break;
    default:
        cp += dlen;
    }

    subarray.set(s_class, s_IN);
    subarray.set(s_ttl, (int)ttl);
    return cp;
}