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