Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/resolv/res_mkquery.c
39476 views
1
/*-
2
* SPDX-License-Identifier: (ISC AND BSD-3-Clause)
3
*
4
* Portions Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
5
* Portions Copyright (C) 1996, 1997, 1988, 1999, 2001, 2003 Internet Software Consortium.
6
*
7
* Permission to use, copy, modify, and/or distribute this software for any
8
* purpose with or without fee is hereby granted, provided that the above
9
* copyright notice and this permission notice appear in all copies.
10
*
11
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
* PERFORMANCE OF THIS SOFTWARE.
18
*/
19
20
/*-
21
* Copyright (c) 1985, 1993
22
* The Regents of the University of California. All rights reserved.
23
*
24
* Redistribution and use in source and binary forms, with or without
25
* modification, are permitted provided that the following conditions
26
* are met:
27
* 1. Redistributions of source code must retain the above copyright
28
* notice, this list of conditions and the following disclaimer.
29
* 2. Redistributions in binary form must reproduce the above copyright
30
* notice, this list of conditions and the following disclaimer in the
31
* documentation and/or other materials provided with the distribution.
32
* 3. Neither the name of the University nor the names of its contributors
33
* may be used to endorse or promote products derived from this software
34
* without specific prior written permission.
35
*
36
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
37
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
40
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
42
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
44
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
45
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46
* SUCH DAMAGE.
47
*/
48
49
/*
50
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
51
*
52
* Permission to use, copy, modify, and distribute this software for any
53
* purpose with or without fee is hereby granted, provided that the above
54
* copyright notice and this permission notice appear in all copies, and that
55
* the name of Digital Equipment Corporation not be used in advertising or
56
* publicity pertaining to distribution of the document or software without
57
* specific, written prior permission.
58
*
59
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
60
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
61
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
62
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
63
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
64
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
65
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
66
* SOFTWARE.
67
*/
68
69
#include "port_before.h"
70
#include <sys/param.h>
71
#include <netinet/in.h>
72
#include <arpa/nameser.h>
73
#include <netdb.h>
74
#include <resolv.h>
75
#include <stdio.h>
76
#include <string.h>
77
#include "port_after.h"
78
79
extern const char *_res_opcodes[];
80
81
/*%
82
* Form all types of queries.
83
* Returns the size of the result or -1.
84
*/
85
int
86
res_nmkquery(res_state statp,
87
int op, /*!< opcode of query */
88
const char *dname, /*!< domain name */
89
int class, int type, /*!< class and type of query */
90
const u_char *data, /*!< resource record data */
91
int datalen, /*!< length of data */
92
const u_char *newrr_in, /*!< new rr for modify or append */
93
u_char *buf, /*!< buffer to put query */
94
int buflen) /*!< size of buffer */
95
{
96
HEADER *hp;
97
u_char *cp, *ep;
98
int n;
99
u_char *dnptrs[20], **dpp, **lastdnptr;
100
101
UNUSED(newrr_in);
102
103
#ifdef DEBUG
104
if (statp->options & RES_DEBUG)
105
printf(";; res_nmkquery(%s, %s, %s, %s)\n",
106
_res_opcodes[op], dname, p_class(class), p_type(type));
107
#endif
108
/*
109
* Initialize header fields.
110
*/
111
if ((buf == NULL) || (buflen < HFIXEDSZ))
112
return (-1);
113
memset(buf, 0, HFIXEDSZ);
114
hp = (HEADER *) buf;
115
statp->id = res_nrandomid(statp);
116
hp->id = htons(statp->id);
117
hp->opcode = op;
118
hp->rd = (statp->options & RES_RECURSE) != 0U;
119
hp->rcode = NOERROR;
120
cp = buf + HFIXEDSZ;
121
ep = buf + buflen;
122
dpp = dnptrs;
123
*dpp++ = buf;
124
*dpp++ = NULL;
125
lastdnptr = dnptrs + nitems(dnptrs);
126
/*
127
* perform opcode specific processing
128
*/
129
switch (op) {
130
case QUERY: /*FALLTHROUGH*/
131
case NS_NOTIFY_OP:
132
if (ep - cp < QFIXEDSZ)
133
return (-1);
134
if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
135
lastdnptr)) < 0)
136
return (-1);
137
cp += n;
138
ns_put16(type, cp);
139
cp += INT16SZ;
140
ns_put16(class, cp);
141
cp += INT16SZ;
142
hp->qdcount = htons(1);
143
if (op == QUERY || data == NULL)
144
break;
145
/*
146
* Make an additional record for completion domain.
147
*/
148
if ((ep - cp) < RRFIXEDSZ)
149
return (-1);
150
n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ,
151
dnptrs, lastdnptr);
152
if (n < 0)
153
return (-1);
154
cp += n;
155
ns_put16(T_NULL, cp);
156
cp += INT16SZ;
157
ns_put16(class, cp);
158
cp += INT16SZ;
159
ns_put32(0, cp);
160
cp += INT32SZ;
161
ns_put16(0, cp);
162
cp += INT16SZ;
163
hp->arcount = htons(1);
164
break;
165
166
case IQUERY:
167
/*
168
* Initialize answer section
169
*/
170
if (ep - cp < 1 + RRFIXEDSZ + datalen)
171
return (-1);
172
*cp++ = '\0'; /*%< no domain name */
173
ns_put16(type, cp);
174
cp += INT16SZ;
175
ns_put16(class, cp);
176
cp += INT16SZ;
177
ns_put32(0, cp);
178
cp += INT32SZ;
179
ns_put16(datalen, cp);
180
cp += INT16SZ;
181
if (datalen) {
182
memcpy(cp, data, datalen);
183
cp += datalen;
184
}
185
hp->ancount = htons(1);
186
break;
187
188
default:
189
return (-1);
190
}
191
return (cp - buf);
192
}
193
194
#ifdef RES_USE_EDNS0
195
/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
196
197
int
198
res_nopt(res_state statp,
199
int n0, /*%< current offset in buffer */
200
u_char *buf, /*%< buffer to put query */
201
int buflen, /*%< size of buffer */
202
int anslen) /*%< UDP answer buffer size */
203
{
204
HEADER *hp;
205
u_char *cp, *ep;
206
u_int16_t flags = 0;
207
208
#ifdef DEBUG
209
if ((statp->options & RES_DEBUG) != 0U)
210
printf(";; res_nopt()\n");
211
#endif
212
213
hp = (HEADER *) buf;
214
cp = buf + n0;
215
ep = buf + buflen;
216
217
if ((ep - cp) < 1 + RRFIXEDSZ)
218
return (-1);
219
220
*cp++ = 0; /*%< "." */
221
ns_put16(ns_t_opt, cp); /*%< TYPE */
222
cp += INT16SZ;
223
if (anslen > 0xffff)
224
anslen = 0xffff; /* limit to 16bit value */
225
ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */
226
cp += INT16SZ;
227
*cp++ = NOERROR; /*%< extended RCODE */
228
*cp++ = 0; /*%< EDNS version */
229
230
if (statp->options & RES_USE_DNSSEC) {
231
#ifdef DEBUG
232
if (statp->options & RES_DEBUG)
233
printf(";; res_opt()... ENDS0 DNSSEC\n");
234
#endif
235
flags |= NS_OPT_DNSSEC_OK;
236
}
237
ns_put16(flags, cp);
238
cp += INT16SZ;
239
240
ns_put16(0U, cp); /*%< RDLEN */
241
cp += INT16SZ;
242
243
hp->arcount = htons(ntohs(hp->arcount) + 1);
244
245
return (cp - buf);
246
}
247
248
/*
249
* Construct variable data (RDATA) block for OPT pseudo-RR, append it
250
* to the buffer, then update the RDLEN field (previously set to zero by
251
* res_nopt()) with the new RDATA length.
252
*/
253
int
254
res_nopt_rdata(res_state statp,
255
int n0, /*%< current offset in buffer */
256
u_char *buf, /*%< buffer to put query */
257
int buflen, /*%< size of buffer */
258
u_char *rdata, /*%< ptr to start of opt rdata */
259
u_short code, /*%< OPTION-CODE */
260
u_short len, /*%< OPTION-LENGTH */
261
u_char *data) /*%< OPTION_DATA */
262
{
263
register u_char *cp, *ep;
264
265
#ifdef DEBUG
266
if ((statp->options & RES_DEBUG) != 0U)
267
printf(";; res_nopt_rdata()\n");
268
#endif
269
270
cp = buf + n0;
271
ep = buf + buflen;
272
273
if ((ep - cp) < (4 + len))
274
return (-1);
275
276
if (rdata < (buf + 2) || rdata >= ep)
277
return (-1);
278
279
ns_put16(code, cp);
280
cp += INT16SZ;
281
282
ns_put16(len, cp);
283
cp += INT16SZ;
284
285
memcpy(cp, data, len);
286
cp += len;
287
288
len = cp - rdata;
289
ns_put16(len, rdata - 2); /* Update RDLEN field */
290
291
return (cp - buf);
292
}
293
#endif
294
295
/*! \file */
296
297