Beispiel #1
0
/*
 * Form all types of queries.
 * Returns the size of the result or -1.
 */
int res_mkquery (
    int           op,            /* opcode of query */
    const char   *dname,         /* domain name */
    int           Class,         /* class of query */
    int           type,          /* type of query */
    const u_char *data,          /* resource record data */
    int           datalen,       /* length of data */
    const u_char *newrr_in,      /* new rr for modify or append */
    u_char       *buf,           /* buffer to put query */
    int           buflen)        /* size of buffer */
{
  struct  rrec *newrr = (struct rrec *) newrr_in;
  HEADER  *hp;
  u_char  *cp;
  u_char  *dnptrs[20];
  u_char **dpp, **lastdnptr;
  int      n;

  if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  {
    h_errno = NETDB_INTERNAL;
    return (-1);
  }

  if (_res.options & RES_DEBUG)
     (*_printf) (";; res_mkquery(%d, %s, %d, %d)\n", op, dname, Class, type);

  /* Initialize header fields.
   */
  if (!buf || buflen < HFIXEDSZ)
     return (-1);

  memset (buf, 0, HFIXEDSZ);
  hp = (HEADER*) buf;
  hp->id     = htons (++_res.id);
  hp->opcode = op;
  hp->rd     = (_res.options & RES_RECURSE) != 0;
  hp->rcode  = NOERROR;
  cp      = buf + HFIXEDSZ;
  buflen -= HFIXEDSZ;
  dpp     = dnptrs;
  *dpp++  = buf;
  *dpp++  = NULL;
  lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];

  /* perform opcode specific processing
   */
  switch (op)
  {
    case STATUS:          /** \todo Handle STATUS case */
         return (-1);

    case QUERY:
         /* fallthrough */

    case NS_NOTIFY_OP:    /* Notify secondary server of SOA change */
         buflen -= QFIXEDSZ;
         if (buflen < 0)
            return (-1);

         if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
            return (-1);
         cp     += n;
         buflen -= n;
         __putshort (type, cp);
         cp += INT16SZ;
         __putshort (Class, cp);
         cp += INT16SZ;
         hp->qdcount = htons (1);
         if (op == QUERY || !data)
            break;
         /*
          * Make an additional record for completion domain.
          */
         buflen -= RRFIXEDSZ;
         n = dn_comp ((char*)data, cp, buflen, dnptrs, lastdnptr);
         if (n < 0)
            return (-1);
         cp     += n;
         buflen -= n;
         __putshort (T_NULL, cp);
         cp += INT16SZ;
         __putshort (Class, cp);
         cp += INT16SZ;
         __putlong (0, cp);
         cp += INT32SZ;
         __putshort (0, cp);
         cp += INT16SZ;
         hp->arcount = htons (1);
         break;

    case IQUERY:
         /*
          * Initialize answer section
          */
         if (buflen < 1 + RRFIXEDSZ + datalen)
            return (-1);
         *cp++ = '\0';  /* no domain name */
         __putshort (type, cp);
         cp += INT16SZ;
         __putshort (Class, cp);
         cp += INT16SZ;
         __putlong (0, cp);
         cp += INT32SZ;
         __putshort (datalen, cp);
         cp += INT16SZ;
         if (datalen)
         {
           memcpy (cp,data,datalen);
           cp += datalen;
         }
         hp->ancount = htons (1);
         break;

#if ALLOW_UPDATES
       /*
        * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
        * (Record to be modified is followed by its replacement in msg.)
        */
    case UPDATEM:
    case UPDATEMA:
    case UPDATED:
         /*
          * The res code for UPDATED and UPDATEDA is the same; user
          * calls them differently: specifies data for UPDATED; server
          * ignores data if specified for UPDATEDA.
          */
    case UPDATEDA:
         buflen -= RRFIXEDSZ + datalen;
         if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
            return (-1);
         cp += n;
         __putshort (type, cp);
         cp += INT16SZ;
         __putshort (Class, cp);
         cp += INT16SZ;
         __putlong (0, cp);
         cp += INT32SZ;
         __putshort (datalen, cp);
         cp += INT16SZ;
         if (datalen)
         {
           memcpy (cp,data,datalen);
           cp += datalen;
         }
         if (op == UPDATED || op == UPDATEDA)
         {
           hp->ancount = 0;
           break;
         }
         /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA
          */

    case UPDATEA:  /* Add new resource record */
         buflen -= RRFIXEDSZ + datalen;
         if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
            return (-1);
         cp += n;
         __putshort (newrr->r_type, cp);
         cp += INT16SZ;
         __putshort (newrr->r_class, cp);
         cp += INT16SZ;
         __putlong (0, cp);
         cp += INT32SZ;
         __putshort (newrr->r_size, cp);
         cp += INT16SZ;
         if (newrr->r_size)
         {
           memcpy (cp,newrr->r_data,newrr->r_size);
           cp += newrr->r_size;
         }
         hp->ancount = 0;
         break;
#endif
    default:
         return (-1);
  }

#if ALLOW_UPDATES == 0
  ARGSUSED (newrr);
  ARGSUSED (newrr_in);
#endif

  return (cp - buf);
}
Beispiel #2
0
int
build_rr(char* p, PDNS_RECORD ptr, int qclass)
{
    int i = 0;
    int n = 0;
    char* cp = p;
    char* temp = NULL;
    unsigned int index = 0;

    i = put_qname(cp, ptr->pName);
    cp = p + i;

    __putshort(ptr->wType, (u_char *)cp);
    i += sizeof(u_short);
    cp = p + i;
    __putshort(qclass, (u_char *)cp);
    i += sizeof(u_short);
    cp = p + i;
    __putlong(ptr->dwTtl, (u_char*)cp);
    i += sizeof(u_long);
    cp = p + i;
    switch (ptr->wType)
    {
    case DNS_TYPE_A:
	__putshort(sizeof(ptr->Data.A), (u_char*)cp); //RDLENGTH
	i += sizeof(u_short);
	cp = p + i;
	memcpy(cp, &(ptr->Data.A), sizeof(ptr->Data.A));
	i += sizeof(ptr->Data.A);
	break;
    case DNS_TYPE_NS:
    case DNS_TYPE_MD:         
    case DNS_TYPE_MF:
    case DNS_TYPE_CNAME:
    case DNS_TYPE_MB:
    case DNS_TYPE_MG:
    case DNS_TYPE_MR:
    case DNS_TYPE_PTR:
	temp = cp;     // hold the spot for RD length
	i += sizeof(u_short); 
	cp = p+i;
	n = put_qname(cp, ptr->Data.Ptr.pNameHost);
	i += n;
	__putshort(n, (u_char*)temp); //set RDLENGTH
	break;
    case DNS_TYPE_TEXT:
    case DNS_TYPE_HINFO:
    case DNS_TYPE_ISDN:
    case DNS_TYPE_X25:
	temp = cp; // hold the spot for RDLENGTH
	i += sizeof(u_short); 
	cp = p + i;
	n = 0;
	for (index = 0; index < ptr->Data.Txt.dwStringCount; index++)
	{
	    *cp = (int)(strlen(ptr->Data.Txt.pStringArray[index]));
	    n += *cp;
	    n++;
	    strcpy(++cp, ptr->Data.Txt.pStringArray[index]);
	}
	i += n;
	__putshort(n,(u_char*)temp); // set RDLENGTH
	break;
    case DNS_TYPE_SRV:
	temp = cp; // hold the spot for RDLENGTH
	i += sizeof(u_short); 
	cp = p + i;
	// priority
	__putshort(ptr->Data.Srv.wPriority, (u_char*)cp); 
	i += sizeof(u_short);
	cp = p + i;
	//weight
	__putshort(ptr->Data.Srv.wWeight, (u_char*)cp); 
	i += sizeof(u_short);
	cp = p + i;
	//port
	__putshort(ptr->Data.Srv.wPort, (u_char*)cp); 
	i += sizeof(u_short);
	cp = p + i;

	n = put_qname(cp, ptr->Data.Srv.pNameTarget);
	i+=n;
	__putshort((u_short)(n + sizeof(u_short)*3),(u_char*)temp);

	break;
    case DNS_TYPE_MX:
    case DNS_TYPE_AFSDB:
    case DNS_TYPE_RT:
	temp = cp; // hold the spot for RDLENGTH
	i += sizeof(u_short); 
	cp = p + i;
	__putshort(ptr->Data.Mx.wPreference, (u_char*)cp); // put wPreference
	i += sizeof(u_short);
	cp = p + i;
	n = put_qname(cp, ptr->Data.Mx.pNameExchange);
	i+=n;
	__putshort((u_short)(n+sizeof(u_short)),(u_char*)temp);
	break;
	case DNS_TYPE_SOA:
	temp = cp; // hold the spot for RDLENGTH
	i += sizeof(u_short); 
	cp = p + i;
	// primary server name
	n = put_qname(cp, ptr->Data.Soa.pNamePrimaryServer);
	i+= n;
	cp = p + i;
	//the person responsible for this zone.
	n += put_qname(cp, ptr->Data.Soa.pNameAdministrator);
	i += n;
	cp = p + i;
	//SERIAL
	__putlong(ptr->Data.Soa.dwSerialNo, cp);
	n += sizeof(u_long);
	i += sizeof(u_long);
	cp = p + i;
	//refresh
	__putlong(ptr->Data.Soa.dwRefresh, cp);
	n += sizeof(u_long);
	i += sizeof(u_long);
	cp = p + i;
	//retry
	__putlong(ptr->Data.Soa.dwRetry, cp);
	n += sizeof(u_long);
	i += sizeof(u_long);
	cp = p + i;
	// expire
	__putlong(ptr->Data.Soa.dwExpire, cp);
	n += sizeof(u_long);
	i += sizeof(u_long);
	cp = p + i;
	// minimum TTL
	__putlong(ptr->Data.Soa.dwDefaultTtl, cp);
	n += sizeof(u_long);
	i += sizeof(u_long);
	// set RDLength
	__putshort(n,(u_char*)temp);
	break;
	case DNS_TYPE_NULL:
	__putshort((short)ptr->Data.Null.dwByteCount, (u_char*)cp); //RDLENGTH
	i += sizeof(u_short);
	cp = p + i;
	memcpy(cp, ptr->Data.Null.Data, ptr->Data.Null.dwByteCount);
	i += ptr->Data.Null.dwByteCount;	
	break;
	case DNS_TYPE_WKS:   // needs more work
	temp = cp; // hold the spot for RDLENGTH
	i += sizeof(u_short); 
	cp = p + i;
	// address
	memcpy(cp, &(ptr->Data.Wks.IpAddress), sizeof(ptr->Data.Wks.IpAddress));
	n = sizeof(ptr->Data.Wks.IpAddress);
	i += sizeof(ptr->Data.Wks.IpAddress);
	cp = p + i;
	// protocol
	*cp = ptr->Data.Wks.chProtocol;
	i++;
	n++;
	cp = p + i;
	//bit mask
	memcpy(cp, &(ptr->Data.Wks.BitMask), sizeof(ptr->Data.Wks.BitMask));
	n+=sizeof(ptr->Data.Wks.BitMask);
	i += n;
	// set RDLength
	__putshort(n,(u_char*)temp);	
	break;
	case DNS_TYPE_MINFO:
	case DNS_TYPE_RP:
	temp = cp; // hold the spot for RDLENGTH
	i += sizeof(u_short); 
	cp = p + i;
	// pNameMailbox
	n = put_qname(cp, ptr->Data.Minfo.pNameMailbox);
	i+= n;
	cp = p + i;
	// pNameErrorsMailbox;
	n += put_qname(cp, ptr->Data.Minfo.pNameMailbox);
	i += n;
	// set RDLength
	__putshort(n,(u_char*)temp);	
    break;
	case DNS_TYPE_AAAA:
	__putshort(sizeof(ptr->Data.AAAA), (u_char*)cp); //RDLENGTH
	i += sizeof(u_short);
	cp = p + i;
	memcpy(cp, &(ptr->Data.AAAA), sizeof(ptr->Data.AAAA));
	i += sizeof(ptr->Data.AAAA);

    break;
    }
    return i;
}