* Copyright (c) 1985 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of California at Berkeley. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid
[] = "@(#)res_mkquery.c 6.7 (Berkeley) %G%";
#endif /* LIBC_SCCS and not lint */
#include <arpa/nameser.h>
* Form all types of queries.
* Returns the size of the result or -1.
res_mkquery(op
, dname
, class, type
, data
, datalen
, newrr
, buf
, buflen
)
int op
; /* opcode of query */
char *dname
; /* domain name */
int class, type
; /* class and type of query */
char *data
; /* resource record data */
int datalen
; /* length of data */
struct rrec
*newrr
; /* new rr for modify or append */
char *buf
; /* buffer to put query */
int buflen
; /* size of buffer */
char *dnptrs
[10], **dpp
, **lastdnptr
;
if (_res
.options
& RES_DEBUG
)
printf("res_mkquery(%d, %s, %d, %d)\n", op
, dname
, class, type
);
* Initialize header fields.
hp
->id
= htons(++_res
.id
);
hp
->qr
= hp
->aa
= hp
->tc
= hp
->ra
= 0;
hp
->pr
= (_res
.options
& RES_PRIMARY
) != 0;
hp
->rd
= (_res
.options
& RES_RECURSE
) != 0;
cp
= buf
+ sizeof(HEADER
);
buflen
-= sizeof(HEADER
);
lastdnptr
= dnptrs
+ sizeof(dnptrs
)/sizeof(dnptrs
[0]);
* If the domain name contains no dots (single label), then
* append the default domain name to the one given.
if ((_res
.options
& RES_DEFNAMES
) && dname
!= 0 && dname
[0] != '\0' &&
index(dname
, '.') == NULL
) {
if (!(_res
.options
& RES_INIT
))
if (_res
.defdname
[0] != '\0') {
(void)sprintf(dnbuf
, "%s.%s", dname
, _res
.defdname
);
* perform opcode specific processing
if ((n
= dn_comp(dname
, cp
, buflen
, dnptrs
, lastdnptr
)) < 0)
if (op
== QUERY
|| data
== NULL
)
* Make an additional record for completion domain.
if ((n
= dn_comp(data
, cp
, buflen
, dnptrs
, lastdnptr
)) < 0)
* Initialize answer section
if (buflen
< 1 + RRFIXEDSZ
+ datalen
)
*cp
++ = '\0'; /* no domain name */
bcopy(data
, cp
, datalen
);
* For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
* (Record to be modified is followed by its replacement in msg.)
* 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.
buflen
-= RRFIXEDSZ
+ datalen
;
if ((n
= dn_comp(dname
, cp
, buflen
, dnptrs
, lastdnptr
)) < 0)
bcopy(data
, cp
, datalen
);
if ( (op
== UPDATED
) || (op
== UPDATEDA
) ) {
/* 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)
putshort(newrr
->r_type
, cp
);
putshort(newrr
->r_class
, cp
);
putshort(newrr
->r_size
, cp
);
bcopy(newrr
->r_data
, cp
, newrr
->r_size
);