integrate changes from bind 4.9 (most of them); continue to use address
[unix-history] / usr / src / lib / libc / net / res_mkquery.c
CommitLineData
882ceeb2 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%
882ceeb2
MK
6 * -
7 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies, and that
12 * the name of Digital Equipment Corporation not be used in advertising or
13 * publicity pertaining to distribution of the document or software without
14 * specific, written prior permission.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
17 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
19 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
20 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
21 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
22 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23 * SOFTWARE.
24 * -
25 * --Copyright--
b423e985 26 */
5e95d9b7 27
2ce81398 28#if defined(LIBC_SCCS) && !defined(lint)
882ceeb2
MK
29static char sccsid[] = "@(#)res_mkquery.c 6.17 (Berkeley) %G%";
30static char rcsid[] = "$Id: res_mkquery.c,v 4.9.1.2 1993/05/17 10:00:01 vixie Exp $";
6b2f9dd0 31#endif /* LIBC_SCCS and not lint */
8ea4199d 32
7596199c 33#include <sys/param.h>
5e95d9b7 34#include <netinet/in.h>
61e99f72 35#include <arpa/nameser.h>
f94b2f50 36#include <resolv.h>
24fac7d8
KB
37#include <stdio.h>
38#include <string.h>
5e95d9b7
RC
39
40/*
41 * Form all types of queries.
42 * Returns the size of the result or -1.
43 */
882ceeb2 44res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
5e95d9b7 45 int op; /* opcode of query */
24fac7d8 46 const char *dname; /* domain name */
5e95d9b7 47 int class, type; /* class and type of query */
24fac7d8 48 const char *data; /* resource record data */
5e95d9b7 49 int datalen; /* length of data */
882ceeb2 50 const char *newrr_in; /* new rr for modify or append */
5e95d9b7
RC
51 char *buf; /* buffer to put query */
52 int buflen; /* size of buffer */
53{
54 register HEADER *hp;
55 register char *cp;
56 register int n;
882ceeb2 57 struct rrec *newrr = (struct rrec *) newrr_in;
5e95d9b7 58 char *dnptrs[10], **dpp, **lastdnptr;
5e95d9b7 59
ae94a224 60#ifdef DEBUG
5e95d9b7 61 if (_res.options & RES_DEBUG)
882ceeb2
MK
62 printf(";; res_mkquery(%d, %s, %d, %d)\n",
63 op, dname, class, type);
64#endif
5e95d9b7
RC
65 /*
66 * Initialize header fields.
67 */
43c7d2d3
JB
68 if ((buf == NULL) || (buflen < sizeof(HEADER)))
69 return(-1);
83d504bd 70 bzero(buf, sizeof(HEADER));
5e95d9b7
RC
71 hp = (HEADER *) buf;
72 hp->id = htons(++_res.id);
73 hp->opcode = op;
5e95d9b7
RC
74 hp->pr = (_res.options & RES_PRIMARY) != 0;
75 hp->rd = (_res.options & RES_RECURSE) != 0;
76 hp->rcode = NOERROR;
5e95d9b7
RC
77 cp = buf + sizeof(HEADER);
78 buflen -= sizeof(HEADER);
79 dpp = dnptrs;
80 *dpp++ = buf;
81 *dpp++ = NULL;
36534519 82 lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
5e95d9b7
RC
83 /*
84 * perform opcode specific processing
85 */
86 switch (op) {
87 case QUERY:
43c7d2d3
JB
88 if ((buflen -= QFIXEDSZ) < 0)
89 return(-1);
24fac7d8
KB
90 if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen,
91 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0)
5e95d9b7
RC
92 return (-1);
93 cp += n;
94 buflen -= n;
16dfe61e 95 __putshort(type, (u_char *)cp);
882ceeb2 96 cp += sizeof(u_int16_t);
16dfe61e 97 __putshort(class, (u_char *)cp);
882ceeb2 98 cp += sizeof(u_int16_t);
a766fb4a 99 hp->qdcount = htons(1);
5e95d9b7
RC
100 if (op == QUERY || data == NULL)
101 break;
102 /*
103 * Make an additional record for completion domain.
104 */
11e57e73 105 buflen -= RRFIXEDSZ;
24fac7d8
KB
106 if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen,
107 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0)
5e95d9b7
RC
108 return (-1);
109 cp += n;
110 buflen -= n;
16dfe61e 111 __putshort(T_NULL, (u_char *)cp);
882ceeb2 112 cp += sizeof(u_int16_t);
16dfe61e 113 __putshort(class, (u_char *)cp);
882ceeb2 114 cp += sizeof(u_int16_t);
16dfe61e 115 __putlong(0, (u_char *)cp);
882ceeb2 116 cp += sizeof(u_int32_t);
16dfe61e 117 __putshort(0, (u_char *)cp);
882ceeb2 118 cp += sizeof(u_int16_t);
a766fb4a 119 hp->arcount = htons(1);
5e95d9b7
RC
120 break;
121
122 case IQUERY:
123 /*
124 * Initialize answer section
125 */
126 if (buflen < 1 + RRFIXEDSZ + datalen)
127 return (-1);
128 *cp++ = '\0'; /* no domain name */
16dfe61e 129 __putshort(type, (u_char *)cp);
882ceeb2 130 cp += sizeof(u_int16_t);
16dfe61e 131 __putshort(class, (u_char *)cp);
882ceeb2 132 cp += sizeof(u_int16_t);
16dfe61e 133 __putlong(0, (u_char *)cp);
882ceeb2 134 cp += sizeof(u_int32_t);
16dfe61e 135 __putshort(datalen, (u_char *)cp);
882ceeb2 136 cp += sizeof(u_int16_t);
5e95d9b7
RC
137 if (datalen) {
138 bcopy(data, cp, datalen);
139 cp += datalen;
140 }
a766fb4a 141 hp->ancount = htons(1);
5e95d9b7
RC
142 break;
143
3bf25746
KD
144#ifdef ALLOW_UPDATES
145 /*
146 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
147 * (Record to be modified is followed by its replacement in msg.)
148 */
5e95d9b7 149 case UPDATEM:
3bf25746
KD
150 case UPDATEMA:
151
152 case UPDATED:
5e95d9b7 153 /*
3bf25746
KD
154 * The res code for UPDATED and UPDATEDA is the same; user
155 * calls them differently: specifies data for UPDATED; server
156 * ignores data if specified for UPDATEDA.
5e95d9b7 157 */
3bf25746 158 case UPDATEDA:
5e95d9b7
RC
159 buflen -= RRFIXEDSZ + datalen;
160 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
161 return (-1);
162 cp += n;
371d3c9b 163 __putshort(type, cp);
882ceeb2 164 cp += sizeof(u_int16_t);
371d3c9b 165 __putshort(class, cp);
882ceeb2 166 cp += sizeof(u_int16_t);
371d3c9b 167 __putlong(0, cp);
882ceeb2 168 cp += sizeof(u_int32_t);
371d3c9b 169 __putshort(datalen, cp);
882ceeb2 170 cp += sizeof(u_int16_t);
5e95d9b7
RC
171 if (datalen) {
172 bcopy(data, cp, datalen);
173 cp += datalen;
174 }
3bf25746
KD
175 if ( (op == UPDATED) || (op == UPDATEDA) ) {
176 hp->ancount = htons(0);
177 break;
178 }
179 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
5e95d9b7 180
3bf25746
KD
181 case UPDATEA: /* Add new resource record */
182 buflen -= RRFIXEDSZ + datalen;
5e95d9b7
RC
183 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
184 return (-1);
185 cp += n;
371d3c9b 186 __putshort(newrr->r_type, cp);
882ceeb2 187 cp += sizeof(u_int16_t);
371d3c9b 188 __putshort(newrr->r_class, cp);
882ceeb2 189 cp += sizeof(u_int16_t);
371d3c9b 190 __putlong(0, cp);
882ceeb2 191 cp += sizeof(u_int32_t);
371d3c9b 192 __putshort(newrr->r_size, cp);
882ceeb2 193 cp += sizeof(u_int16_t);
5e95d9b7
RC
194 if (newrr->r_size) {
195 bcopy(newrr->r_data, cp, newrr->r_size);
196 cp += newrr->r_size;
197 }
3bf25746 198 hp->ancount = htons(0);
5e95d9b7 199 break;
3bf25746 200
882ceeb2 201#endif /* ALLOW_UPDATES */
5e95d9b7
RC
202 }
203 return (cp - buf);
204}