Libinfo-173.tar.gz
[apple/libinfo.git] / dns.subproj / res_mkquery.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * ++Copyright++ 1985, 1993
27 * -
28 * Copyright (c) 1985, 1993
29 * The Regents of the University of California. All rights reserved.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 * -
59 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
60 *
61 * Permission to use, copy, modify, and distribute this software for any
62 * purpose with or without fee is hereby granted, provided that the above
63 * copyright notice and this permission notice appear in all copies, and that
64 * the name of Digital Equipment Corporation not be used in advertising or
65 * publicity pertaining to distribution of the document or software without
66 * specific, written prior permission.
67 *
68 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
69 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
70 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
71 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
72 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
73 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
74 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
75 * SOFTWARE.
76 * -
77 * --Copyright--
78 */
79
80 #if defined(LIBC_SCCS) && !defined(lint)
81 static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
82 static char rcsid[] = "$Id: res_mkquery.c,v 1.3 2003/02/18 17:29:24 majka Exp $";
83 #endif /* LIBC_SCCS and not lint */
84
85 #include <sys/param.h>
86 #include <netinet/in.h>
87 #include <arpa/nameser8_compat.h>
88
89 #include <stdio.h>
90 #include <netdb.h>
91 #include <resolv8_compat.h>
92 #if defined(BSD) && (BSD >= 199103)
93 # include <string.h>
94 #else
95 # include "portability.h"
96 #endif
97
98 #if defined(USE_OPTIONS_H)
99 # include "options.h"
100 #endif
101
102 /*
103 * Form all types of queries.
104 * Returns the size of the result or -1.
105 */
106 int
107 res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
108 int op; /* opcode of query */
109 const char *dname; /* domain name */
110 int class, type; /* class and type of query */
111 const u_char *data; /* resource record data */
112 int datalen; /* length of data */
113 const u_char *newrr_in; /* new rr for modify or append */
114 u_char *buf; /* buffer to put query */
115 int buflen; /* size of buffer */
116 {
117 register HEADER *hp;
118 register u_char *cp;
119 register int n;
120 #ifdef ALLOW_UPDATES
121 struct rrec *newrr = (struct rrec *) newrr_in;
122 #endif
123 u_char *dnptrs[20], **dpp, **lastdnptr;
124
125 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
126 h_errno = NETDB_INTERNAL;
127 return (-1);
128 }
129 #ifdef DEBUG
130 if (_res.options & RES_DEBUG)
131 printf(";; res_mkquery(%d, %s, %d, %d)\n",
132 op, dname, class, type);
133 #endif
134 /*
135 * Initialize header fields.
136 */
137 if ((buf == NULL) || (buflen < HFIXEDSZ))
138 return (-1);
139 bzero(buf, HFIXEDSZ);
140 hp = (HEADER *) buf;
141 hp->id = htons(++_res.id);
142 hp->opcode = op;
143 hp->rd = (_res.options & RES_RECURSE) != 0;
144 hp->rcode = NOERROR;
145 cp = buf + HFIXEDSZ;
146 buflen -= HFIXEDSZ;
147 dpp = dnptrs;
148 *dpp++ = buf;
149 *dpp++ = NULL;
150 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
151 /*
152 * perform opcode specific processing
153 */
154 switch (op) {
155 case QUERY: /*FALLTHROUGH*/
156 case NS_NOTIFY_OP:
157 if ((buflen -= QFIXEDSZ) < 0)
158 return (-1);
159 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
160 return (-1);
161 cp += n;
162 buflen -= n;
163 __putshort(type, cp);
164 cp += INT16SZ;
165 __putshort(class, cp);
166 cp += INT16SZ;
167 hp->qdcount = htons(1);
168 if (op == QUERY || data == NULL)
169 break;
170 /*
171 * Make an additional record for completion domain.
172 */
173 buflen -= RRFIXEDSZ;
174 n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
175 if (n < 0)
176 return (-1);
177 cp += n;
178 buflen -= n;
179 __putshort(T_NULL, cp);
180 cp += INT16SZ;
181 __putshort(class, cp);
182 cp += INT16SZ;
183 __putlong(0, cp);
184 cp += INT32SZ;
185 __putshort(0, cp);
186 cp += INT16SZ;
187 hp->arcount = htons(1);
188 break;
189
190 case IQUERY:
191 /*
192 * Initialize answer section
193 */
194 if (buflen < 1 + RRFIXEDSZ + datalen)
195 return (-1);
196 *cp++ = '\0'; /* no domain name */
197 __putshort(type, cp);
198 cp += INT16SZ;
199 __putshort(class, cp);
200 cp += INT16SZ;
201 __putlong(0, cp);
202 cp += INT32SZ;
203 __putshort(datalen, cp);
204 cp += INT16SZ;
205 if (datalen) {
206 bcopy(data, cp, datalen);
207 cp += datalen;
208 }
209 hp->ancount = htons(1);
210 break;
211
212 #ifdef ALLOW_UPDATES
213 /*
214 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
215 * (Record to be modified is followed by its replacement in msg.)
216 */
217 case UPDATEM:
218 case UPDATEMA:
219
220 case UPDATED:
221 /*
222 * The res code for UPDATED and UPDATEDA is the same; user
223 * calls them differently: specifies data for UPDATED; server
224 * ignores data if specified for UPDATEDA.
225 */
226 case UPDATEDA:
227 buflen -= RRFIXEDSZ + datalen;
228 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
229 return (-1);
230 cp += n;
231 __putshort(type, cp);
232 cp += INT16SZ;
233 __putshort(class, cp);
234 cp += INT16SZ;
235 __putlong(0, cp);
236 cp += INT32SZ;
237 __putshort(datalen, cp);
238 cp += INT16SZ;
239 if (datalen) {
240 bcopy(data, cp, datalen);
241 cp += datalen;
242 }
243 if ( (op == UPDATED) || (op == UPDATEDA) ) {
244 hp->ancount = htons(0);
245 break;
246 }
247 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
248
249 case UPDATEA: /* Add new resource record */
250 buflen -= RRFIXEDSZ + datalen;
251 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
252 return (-1);
253 cp += n;
254 __putshort(newrr->r_type, cp);
255 cp += INT16SZ;
256 __putshort(newrr->r_class, cp);
257 cp += INT16SZ;
258 __putlong(0, cp);
259 cp += INT32SZ;
260 __putshort(newrr->r_size, cp);
261 cp += INT16SZ;
262 if (newrr->r_size) {
263 bcopy(newrr->r_data, cp, newrr->r_size);
264 cp += newrr->r_size;
265 }
266 hp->ancount = htons(0);
267 break;
268 #endif /* ALLOW_UPDATES */
269 default:
270 return (-1);
271 }
272 return (cp - buf);
273 }