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 #if defined(LIBC_SCCS) && !defined(lint) 70 static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; 71 static const char rcsid[] = "$Id: res_mkquery.c,v 1.10 2008/12/11 09:59:00 marka Exp $"; 72 #endif /* LIBC_SCCS and not lint */ 73 #include <sys/cdefs.h> 74 __FBSDID("$FreeBSD$"); 75 76 #include "port_before.h" 77 #include <sys/param.h> 78 #include <netinet/in.h> 79 #include <arpa/nameser.h> 80 #include <netdb.h> 81 #include <resolv.h> 82 #include <stdio.h> 83 #include <string.h> 84 #include "port_after.h" 85 86 /* Options. Leave them on. */ 87 #ifndef DEBUG 88 #define DEBUG 89 #endif 90 91 extern const char *_res_opcodes[]; 92 93 /*% 94 * Form all types of queries. 95 * Returns the size of the result or -1. 96 */ 97 int 98 res_nmkquery(res_state statp, 99 int op, /*!< opcode of query */ 100 const char *dname, /*!< domain name */ 101 int class, int type, /*!< class and type of query */ 102 const u_char *data, /*!< resource record data */ 103 int datalen, /*!< length of data */ 104 const u_char *newrr_in, /*!< new rr for modify or append */ 105 u_char *buf, /*!< buffer to put query */ 106 int buflen) /*!< size of buffer */ 107 { 108 HEADER *hp; 109 u_char *cp, *ep; 110 int n; 111 u_char *dnptrs[20], **dpp, **lastdnptr; 112 113 UNUSED(newrr_in); 114 115 #ifdef DEBUG 116 if (statp->options & RES_DEBUG) 117 printf(";; res_nmkquery(%s, %s, %s, %s)\n", 118 _res_opcodes[op], dname, p_class(class), p_type(type)); 119 #endif 120 /* 121 * Initialize header fields. 122 */ 123 if ((buf == NULL) || (buflen < HFIXEDSZ)) 124 return (-1); 125 memset(buf, 0, HFIXEDSZ); 126 hp = (HEADER *) buf; 127 statp->id = res_nrandomid(statp); 128 hp->id = htons(statp->id); 129 hp->opcode = op; 130 hp->rd = (statp->options & RES_RECURSE) != 0U; 131 hp->rcode = NOERROR; 132 cp = buf + HFIXEDSZ; 133 ep = buf + buflen; 134 dpp = dnptrs; 135 *dpp++ = buf; 136 *dpp++ = NULL; 137 lastdnptr = dnptrs + nitems(dnptrs); 138 /* 139 * perform opcode specific processing 140 */ 141 switch (op) { 142 case QUERY: /*FALLTHROUGH*/ 143 case NS_NOTIFY_OP: 144 if (ep - cp < QFIXEDSZ) 145 return (-1); 146 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs, 147 lastdnptr)) < 0) 148 return (-1); 149 cp += n; 150 ns_put16(type, cp); 151 cp += INT16SZ; 152 ns_put16(class, cp); 153 cp += INT16SZ; 154 hp->qdcount = htons(1); 155 if (op == QUERY || data == NULL) 156 break; 157 /* 158 * Make an additional record for completion domain. 159 */ 160 if ((ep - cp) < RRFIXEDSZ) 161 return (-1); 162 n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ, 163 dnptrs, lastdnptr); 164 if (n < 0) 165 return (-1); 166 cp += n; 167 ns_put16(T_NULL, cp); 168 cp += INT16SZ; 169 ns_put16(class, cp); 170 cp += INT16SZ; 171 ns_put32(0, cp); 172 cp += INT32SZ; 173 ns_put16(0, cp); 174 cp += INT16SZ; 175 hp->arcount = htons(1); 176 break; 177 178 case IQUERY: 179 /* 180 * Initialize answer section 181 */ 182 if (ep - cp < 1 + RRFIXEDSZ + datalen) 183 return (-1); 184 *cp++ = '\0'; /*%< no domain name */ 185 ns_put16(type, cp); 186 cp += INT16SZ; 187 ns_put16(class, cp); 188 cp += INT16SZ; 189 ns_put32(0, cp); 190 cp += INT32SZ; 191 ns_put16(datalen, cp); 192 cp += INT16SZ; 193 if (datalen) { 194 memcpy(cp, data, datalen); 195 cp += datalen; 196 } 197 hp->ancount = htons(1); 198 break; 199 200 default: 201 return (-1); 202 } 203 return (cp - buf); 204 } 205 206 #ifdef RES_USE_EDNS0 207 /* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */ 208 209 int 210 res_nopt(res_state statp, 211 int n0, /*%< current offset in buffer */ 212 u_char *buf, /*%< buffer to put query */ 213 int buflen, /*%< size of buffer */ 214 int anslen) /*%< UDP answer buffer size */ 215 { 216 HEADER *hp; 217 u_char *cp, *ep; 218 u_int16_t flags = 0; 219 220 #ifdef DEBUG 221 if ((statp->options & RES_DEBUG) != 0U) 222 printf(";; res_nopt()\n"); 223 #endif 224 225 hp = (HEADER *) buf; 226 cp = buf + n0; 227 ep = buf + buflen; 228 229 if ((ep - cp) < 1 + RRFIXEDSZ) 230 return (-1); 231 232 *cp++ = 0; /*%< "." */ 233 ns_put16(ns_t_opt, cp); /*%< TYPE */ 234 cp += INT16SZ; 235 if (anslen > 0xffff) 236 anslen = 0xffff; /* limit to 16bit value */ 237 ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */ 238 cp += INT16SZ; 239 *cp++ = NOERROR; /*%< extended RCODE */ 240 *cp++ = 0; /*%< EDNS version */ 241 242 if (statp->options & RES_USE_DNSSEC) { 243 #ifdef DEBUG 244 if (statp->options & RES_DEBUG) 245 printf(";; res_opt()... ENDS0 DNSSEC\n"); 246 #endif 247 flags |= NS_OPT_DNSSEC_OK; 248 } 249 ns_put16(flags, cp); 250 cp += INT16SZ; 251 252 ns_put16(0U, cp); /*%< RDLEN */ 253 cp += INT16SZ; 254 255 hp->arcount = htons(ntohs(hp->arcount) + 1); 256 257 return (cp - buf); 258 } 259 260 /* 261 * Construct variable data (RDATA) block for OPT pseudo-RR, append it 262 * to the buffer, then update the RDLEN field (previously set to zero by 263 * res_nopt()) with the new RDATA length. 264 */ 265 int 266 res_nopt_rdata(res_state statp, 267 int n0, /*%< current offset in buffer */ 268 u_char *buf, /*%< buffer to put query */ 269 int buflen, /*%< size of buffer */ 270 u_char *rdata, /*%< ptr to start of opt rdata */ 271 u_short code, /*%< OPTION-CODE */ 272 u_short len, /*%< OPTION-LENGTH */ 273 u_char *data) /*%< OPTION_DATA */ 274 { 275 register u_char *cp, *ep; 276 277 #ifdef DEBUG 278 if ((statp->options & RES_DEBUG) != 0U) 279 printf(";; res_nopt_rdata()\n"); 280 #endif 281 282 cp = buf + n0; 283 ep = buf + buflen; 284 285 if ((ep - cp) < (4 + len)) 286 return (-1); 287 288 if (rdata < (buf + 2) || rdata >= ep) 289 return (-1); 290 291 ns_put16(code, cp); 292 cp += INT16SZ; 293 294 ns_put16(len, cp); 295 cp += INT16SZ; 296 297 memcpy(cp, data, len); 298 cp += len; 299 300 len = cp - rdata; 301 ns_put16(len, rdata - 2); /* Update RDLEN field */ 302 303 return (cp - buf); 304 } 305 #endif 306 307 /*! \file */ 308