#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include "crossl.h"
int __areweinnamed()
{
return (0);
}
static int _confcheck()
{
int ns;
struct stat rc_stat;
struct sockaddr_in ns_sin;
if (stat(_PATH_RESCONF, &rc_stat) == -1 && errno == ENOENT) {
if (__areweinnamed())
return (0);
if (_res.nsaddr.sin_addr.S_un.S_addr == htonl(INADDR_LOOPBACK)) {
ns = socket(AF_INET, SOCK_STREAM, 0);
IN_SET_LOOPBACK_ADDR(&ns_sin);
ns_sin.sin_port = htons(NAMESERVER_PORT);
if (connect(ns, (struct sockaddr *) &ns_sin,
sizeof ns_sin) == -1) {
(void) close(ns);
return(-1);
}
else {
(void) close(ns);
return(0);
}
}
return(0);
}
return (0);
}
int
res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
int op;
char *dname;
int class, type;
char *data;
int datalen;
struct rrec *newrr;
char *buf;
int buflen;
{
register HEADER *hp;
register u_char *cp;
register int n;
u_char *dnptrs[10], **dpp, **lastdnptr;
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
#endif
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
h_errno = NO_RECOVERY;
return(-1);
}
if (_confcheck() == -1) {
_res.options &= ~RES_INIT;
h_errno = NO_RECOVERY;
return(-1);
}
if ((buf == NULL) || (buflen < sizeof (HEADER)))
return (-1);
#ifdef SYSV
(void) memset(buf, 0, sizeof (HEADER));
#else
bzero(buf, sizeof (HEADER));
#endif
hp = (HEADER *) buf;
hp->id = htons(++_res.id);
hp->opcode = op;
hp->pr = (_res.options & RES_PRIMARY) != 0;
hp->rd = (_res.options & RES_RECURSE) != 0;
hp->rcode = NOERROR;
cp = (u_char *)(buf + sizeof (HEADER));
buflen -= sizeof (HEADER);
dpp = dnptrs;
*dpp++ = (u_char *)buf;
*dpp++ = NULL;
lastdnptr = dnptrs + sizeof (dnptrs) / sizeof (dnptrs[0]);
switch (op) {
case QUERY:
if ((buflen -= QFIXEDSZ) < 0)
return (-1);
if ((n = dn_comp((u_char *)dname, cp, buflen,
dnptrs, lastdnptr)) < 0)
return (-1);
cp += n;
buflen -= n;
putshort(type, cp);
cp += sizeof (u_short);
putshort(class, cp);
cp += sizeof (u_short);
hp->qdcount = htons(1);
if (op == QUERY || data == NULL)
break;
buflen -= RRFIXEDSZ;
if ((n = dn_comp((u_char *)data, cp, buflen,
dnptrs, lastdnptr)) < 0)
return (-1);
cp += n;
buflen -= n;
putshort(T_NULL, cp);
cp += sizeof (u_short);
putshort(class, cp);
cp += sizeof (u_short);
putlong(0, cp);
cp += sizeof (u_long);
putshort(0, cp);
cp += sizeof (u_short);
hp->arcount = htons(1);
break;
case IQUERY:
if (buflen < 1 + RRFIXEDSZ + datalen)
return (-1);
*cp++ = '\0';
putshort(type, cp);
cp += sizeof (u_short);
putshort(class, cp);
cp += sizeof (u_short);
putlong(0, cp);
cp += sizeof (u_long);
putshort(datalen, cp);
cp += sizeof (u_short);
if (datalen) {
#ifdef SYSV
(void) memcpy((void *)cp, (void *)data, datalen);
#else
bcopy(data, cp, datalen);
#endif
cp += datalen;
}
hp->ancount = htons(1);
break;
#ifdef ALLOW_UPDATES
case UPDATEM:
case UPDATEMA:
case UPDATED:
case UPDATEDA:
buflen -= RRFIXEDSZ + datalen;
if ((n = dn_comp((u_char *)dname, cp, buflen,
dnptrs, lastdnptr)) < 0)
return (-1);
cp += n;
putshort(type, cp);
cp += sizeof (u_short);
putshort(class, cp);
cp += sizeof (u_short);
putlong(0, cp);
cp += sizeof (u_long);
putshort(datalen, cp);
cp += sizeof (u_short);
if (datalen) {
#ifdef SYSV
memcpy((void *)cp, (void *)data, datalen);
#else
bcopy(data, cp, datalen);
#endif
cp += datalen;
}
if ((op == UPDATED) || (op == UPDATEDA)) {
hp->ancount = htons(0);
break;
}
case UPDATEA:
buflen -= RRFIXEDSZ + datalen;
if ((n = dn_comp((u_char *)dname, cp, buflen,
dnptrs, lastdnptr)) < 0)
return (-1);
cp += n;
putshort(newrr->r_type, cp);
cp += sizeof (u_short);
putshort(newrr->r_class, cp);
cp += sizeof (u_short);
putlong(0, cp);
cp += sizeof (u_long);
putshort(newrr->r_size, cp);
cp += sizeof (u_short);
if (newrr->r_size) {
#ifdef SYSV
memcpy((void *)cp, newrr->r_data, newrr->r_size);
#else
bcopy(newrr->r_data, cp, newrr->r_size);
#endif
cp += newrr->r_size;
}
hp->ancount = htons(0);
break;
#endif
}
return ((char *)cp - buf);
}