date and time created 91/03/07 10:23:53 by bostic
[unix-history] / usr / src / lib / libc / net / res_mkquery.c
CommitLineData
b423e985 1/*
8ea4199d 2 * Copyright (c) 1985 Regents of the University of California.
6b2f9dd0
KB
3 * All rights reserved.
4 *
269a7923 5 * %sccs.include.redist.c%
b423e985 6 */
5e95d9b7 7
2ce81398 8#if defined(LIBC_SCCS) && !defined(lint)
16dfe61e 9static char sccsid[] = "@(#)res_mkquery.c 6.16 (Berkeley) %G%";
6b2f9dd0 10#endif /* LIBC_SCCS and not lint */
8ea4199d 11
7596199c 12#include <sys/param.h>
5e95d9b7 13#include <netinet/in.h>
61e99f72 14#include <arpa/nameser.h>
f94b2f50 15#include <resolv.h>
24fac7d8
KB
16#include <stdio.h>
17#include <string.h>
5e95d9b7
RC
18
19/*
20 * Form all types of queries.
21 * Returns the size of the result or -1.
22 */
31f0ead0 23res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
5e95d9b7 24 int op; /* opcode of query */
24fac7d8 25 const char *dname; /* domain name */
5e95d9b7 26 int class, type; /* class and type of query */
24fac7d8 27 const char *data; /* resource record data */
5e95d9b7 28 int datalen; /* length of data */
24fac7d8 29 const struct rrec *newrr; /* new rr for modify or append */
5e95d9b7
RC
30 char *buf; /* buffer to put query */
31 int buflen; /* size of buffer */
32{
33 register HEADER *hp;
34 register char *cp;
35 register int n;
5e95d9b7 36 char *dnptrs[10], **dpp, **lastdnptr;
5e95d9b7 37
ae94a224 38#ifdef DEBUG
5e95d9b7 39 if (_res.options & RES_DEBUG)
31f0ead0 40 printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
2d8db2bc 41#endif DEBUG
5e95d9b7
RC
42 /*
43 * Initialize header fields.
44 */
43c7d2d3
JB
45 if ((buf == NULL) || (buflen < sizeof(HEADER)))
46 return(-1);
83d504bd 47 bzero(buf, sizeof(HEADER));
5e95d9b7
RC
48 hp = (HEADER *) buf;
49 hp->id = htons(++_res.id);
50 hp->opcode = op;
5e95d9b7
RC
51 hp->pr = (_res.options & RES_PRIMARY) != 0;
52 hp->rd = (_res.options & RES_RECURSE) != 0;
53 hp->rcode = NOERROR;
5e95d9b7
RC
54 cp = buf + sizeof(HEADER);
55 buflen -= sizeof(HEADER);
56 dpp = dnptrs;
57 *dpp++ = buf;
58 *dpp++ = NULL;
36534519 59 lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
5e95d9b7
RC
60 /*
61 * perform opcode specific processing
62 */
63 switch (op) {
64 case QUERY:
43c7d2d3
JB
65 if ((buflen -= QFIXEDSZ) < 0)
66 return(-1);
24fac7d8
KB
67 if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen,
68 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0)
5e95d9b7
RC
69 return (-1);
70 cp += n;
71 buflen -= n;
16dfe61e 72 __putshort(type, (u_char *)cp);
5e95d9b7 73 cp += sizeof(u_short);
16dfe61e 74 __putshort(class, (u_char *)cp);
5e95d9b7 75 cp += sizeof(u_short);
a766fb4a 76 hp->qdcount = htons(1);
5e95d9b7
RC
77 if (op == QUERY || data == NULL)
78 break;
79 /*
80 * Make an additional record for completion domain.
81 */
11e57e73 82 buflen -= RRFIXEDSZ;
24fac7d8
KB
83 if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen,
84 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0)
5e95d9b7
RC
85 return (-1);
86 cp += n;
87 buflen -= n;
16dfe61e 88 __putshort(T_NULL, (u_char *)cp);
5e95d9b7 89 cp += sizeof(u_short);
16dfe61e 90 __putshort(class, (u_char *)cp);
5e95d9b7 91 cp += sizeof(u_short);
16dfe61e 92 __putlong(0, (u_char *)cp);
5e95d9b7 93 cp += sizeof(u_long);
16dfe61e 94 __putshort(0, (u_char *)cp);
5e95d9b7 95 cp += sizeof(u_short);
a766fb4a 96 hp->arcount = htons(1);
5e95d9b7
RC
97 break;
98
99 case IQUERY:
100 /*
101 * Initialize answer section
102 */
103 if (buflen < 1 + RRFIXEDSZ + datalen)
104 return (-1);
105 *cp++ = '\0'; /* no domain name */
16dfe61e 106 __putshort(type, (u_char *)cp);
5e95d9b7 107 cp += sizeof(u_short);
16dfe61e 108 __putshort(class, (u_char *)cp);
5e95d9b7 109 cp += sizeof(u_short);
16dfe61e 110 __putlong(0, (u_char *)cp);
5e95d9b7 111 cp += sizeof(u_long);
16dfe61e 112 __putshort(datalen, (u_char *)cp);
5e95d9b7
RC
113 cp += sizeof(u_short);
114 if (datalen) {
115 bcopy(data, cp, datalen);
116 cp += datalen;
117 }
a766fb4a 118 hp->ancount = htons(1);
5e95d9b7
RC
119 break;
120
3bf25746
KD
121#ifdef ALLOW_UPDATES
122 /*
123 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
124 * (Record to be modified is followed by its replacement in msg.)
125 */
5e95d9b7 126 case UPDATEM:
3bf25746
KD
127 case UPDATEMA:
128
129 case UPDATED:
5e95d9b7 130 /*
3bf25746
KD
131 * The res code for UPDATED and UPDATEDA is the same; user
132 * calls them differently: specifies data for UPDATED; server
133 * ignores data if specified for UPDATEDA.
5e95d9b7 134 */
3bf25746 135 case UPDATEDA:
5e95d9b7
RC
136 buflen -= RRFIXEDSZ + datalen;
137 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
138 return (-1);
139 cp += n;
371d3c9b 140 __putshort(type, cp);
3bf25746 141 cp += sizeof(u_short);
371d3c9b 142 __putshort(class, cp);
3bf25746 143 cp += sizeof(u_short);
371d3c9b 144 __putlong(0, cp);
5e95d9b7 145 cp += sizeof(u_long);
371d3c9b 146 __putshort(datalen, cp);
3bf25746 147 cp += sizeof(u_short);
5e95d9b7
RC
148 if (datalen) {
149 bcopy(data, cp, datalen);
150 cp += datalen;
151 }
3bf25746
KD
152 if ( (op == UPDATED) || (op == UPDATEDA) ) {
153 hp->ancount = htons(0);
154 break;
155 }
156 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
5e95d9b7 157
3bf25746
KD
158 case UPDATEA: /* Add new resource record */
159 buflen -= RRFIXEDSZ + datalen;
5e95d9b7
RC
160 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
161 return (-1);
162 cp += n;
371d3c9b 163 __putshort(newrr->r_type, cp);
3bf25746 164 cp += sizeof(u_short);
371d3c9b 165 __putshort(newrr->r_class, cp);
3bf25746 166 cp += sizeof(u_short);
371d3c9b 167 __putlong(0, cp);
5e95d9b7 168 cp += sizeof(u_long);
371d3c9b 169 __putshort(newrr->r_size, cp);
3bf25746 170 cp += sizeof(u_short);
5e95d9b7
RC
171 if (newrr->r_size) {
172 bcopy(newrr->r_data, cp, newrr->r_size);
173 cp += newrr->r_size;
174 }
3bf25746 175 hp->ancount = htons(0);
5e95d9b7 176 break;
3bf25746
KD
177
178#endif ALLOW_UPDATES
5e95d9b7
RC
179 }
180 return (cp - buf);
181}