1 /* $NetBSD: res_mkquery.c,v 1.6 2006/01/24 17:40:32 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1985, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 /* 37 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 38 * 39 * Permission to use, copy, modify, and distribute this software for any 40 * purpose with or without fee is hereby granted, provided that the above 41 * copyright notice and this permission notice appear in all copies, and that 42 * the name of Digital Equipment Corporation not be used in advertising or 43 * publicity pertaining to distribution of the document or software without 44 * specific, written prior permission. 45 * 46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 53 * SOFTWARE. 54 */ 55 56 /* 57 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 58 * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 59 * 60 * Permission to use, copy, modify, and distribute this software for any 61 * purpose with or without fee is hereby granted, provided that the above 62 * copyright notice and this permission notice appear in all copies. 63 * 64 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 65 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 66 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 67 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 68 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 69 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 70 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 71 */ 72 73 #define LOG_TAG "resolv" 74 75 #include <algorithm> // std::min() 76 77 #include <arpa/nameser.h> 78 #include <netdb.h> 79 #include <netinet/in.h> 80 #include <string.h> 81 82 #include <android-base/logging.h> 83 #include <netd_resolv/resolv.h> // NET_CONTEXT_FLAG_USE_DNS_OVER_TLS 84 85 #include "res_comp.h" 86 #include "res_debug.h" 87 #include "resolv_private.h" // res_state 88 89 // Queries will be padded to a multiple of this length when EDNS0 is active. 90 constexpr uint16_t kEdns0Padding = 128; 91 92 extern const char* const _res_opcodes[] = { 93 "QUERY", "IQUERY", "CQUERYM", "CQUERYU", /* experimental */ 94 "NOTIFY", /* experimental */ 95 "UPDATE", "6", "7", "8", "9", "10", 96 "11", "12", "13", "ZONEINIT", "ZONEREF", 97 }; 98 99 // Form all types of queries. Returns the size of the result or -1. 100 int res_nmkquery(int op, // opcode of query 101 const char* dname, // domain name 102 int cl, int type, // class and type of query 103 const uint8_t* data, // resource record data 104 int datalen, // length of data 105 uint8_t* buf, // buffer to put query 106 int buflen, // size of buffer 107 int netcontext_flags) { 108 HEADER* hp; 109 uint8_t *cp, *ep; 110 int n; 111 uint8_t *dnptrs[20], **dpp, **lastdnptr; 112 113 LOG(DEBUG) << __func__ << ": (" << _res_opcodes[op] << ", " << p_class(cl) << ", " 114 << p_type(type) << ")"; 115 116 /* 117 * Initialize header fields. 118 */ 119 if ((buf == NULL) || (buflen < HFIXEDSZ)) return (-1); 120 memset(buf, 0, HFIXEDSZ); 121 hp = (HEADER*) (void*) buf; 122 hp->id = htons(arc4random_uniform(65536)); 123 hp->opcode = op; 124 hp->rd = true; 125 hp->ad = (netcontext_flags & NET_CONTEXT_FLAG_USE_DNS_OVER_TLS) != 0U; 126 hp->rcode = NOERROR; 127 cp = buf + HFIXEDSZ; 128 ep = buf + buflen; 129 dpp = dnptrs; 130 *dpp++ = buf; 131 *dpp++ = NULL; 132 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; 133 /* 134 * perform opcode specific processing 135 */ 136 switch (op) { 137 case QUERY: 138 [[fallthrough]]; 139 case NS_NOTIFY_OP: 140 if (ep - cp < QFIXEDSZ) return (-1); 141 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr)) < 0) return (-1); 142 cp += n; 143 *reinterpret_cast<uint16_t*>(cp) = htons(type); 144 cp += INT16SZ; 145 *reinterpret_cast<uint16_t*>(cp) = htons(cl); 146 cp += INT16SZ; 147 hp->qdcount = htons(1); 148 if (op == QUERY || data == NULL) break; 149 /* 150 * Make an additional record for completion domain. 151 */ 152 if ((ep - cp) < RRFIXEDSZ) return (-1); 153 n = dn_comp((const char*) data, cp, ep - cp - RRFIXEDSZ, dnptrs, lastdnptr); 154 if (n < 0) return (-1); 155 cp += n; 156 *reinterpret_cast<uint16_t*>(cp) = htons(ns_t_null); 157 cp += INT16SZ; 158 *reinterpret_cast<uint16_t*>(cp) = htons(cl); 159 cp += INT16SZ; 160 *reinterpret_cast<uint32_t*>(cp) = htonl(0); 161 cp += INT32SZ; 162 *reinterpret_cast<uint16_t*>(cp) = htons(0); 163 cp += INT16SZ; 164 hp->arcount = htons(1); 165 break; 166 167 case IQUERY: 168 /* 169 * Initialize answer section 170 */ 171 if (ep - cp < 1 + RRFIXEDSZ + datalen) return (-1); 172 *cp++ = '\0'; /* no domain name */ 173 *reinterpret_cast<uint16_t*>(cp) = htons(type); 174 cp += INT16SZ; 175 *reinterpret_cast<uint16_t*>(cp) = htons(cl); 176 cp += INT16SZ; 177 *reinterpret_cast<uint32_t*>(cp) = htonl(0); 178 cp += INT32SZ; 179 *reinterpret_cast<uint16_t*>(cp) = htons(datalen); 180 cp += INT16SZ; 181 if (datalen) { 182 memcpy(cp, data, (size_t) 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 int res_nopt(res_state statp, int n0, /* current offset in buffer */ 195 uint8_t* buf, /* buffer to put query */ 196 int buflen, /* size of buffer */ 197 int anslen) /* UDP answer buffer size */ 198 { 199 HEADER* hp; 200 uint8_t *cp, *ep; 201 uint16_t flags = 0; 202 203 LOG(DEBUG) << __func__; 204 205 hp = (HEADER*) (void*) buf; 206 cp = buf + n0; 207 ep = buf + buflen; 208 209 if ((ep - cp) < 1 + RRFIXEDSZ) return (-1); 210 211 *cp++ = 0; /* "." */ 212 213 // Attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). 214 *reinterpret_cast<uint16_t*>(cp) = htons(ns_t_opt); /* TYPE */ 215 cp += INT16SZ; 216 if (anslen > 0xffff) anslen = 0xffff; 217 *reinterpret_cast<uint16_t*>(cp) = htons(anslen); /* CLASS = UDP payload size */ 218 cp += INT16SZ; 219 *cp++ = NOERROR; /* extended RCODE */ 220 *cp++ = 0; /* EDNS version */ 221 if (statp->netcontext_flags & NET_CONTEXT_FLAG_USE_DNS_OVER_TLS) { 222 LOG(DEBUG) << __func__ << ": ENDS0 DNSSEC"; 223 flags |= NS_OPT_DNSSEC_OK; 224 } 225 *reinterpret_cast<uint16_t*>(cp) = htons(flags); 226 cp += INT16SZ; 227 228 // EDNS0 padding 229 const uint16_t minlen = static_cast<uint16_t>(cp - buf) + 3 * INT16SZ; 230 const uint16_t extra = minlen % kEdns0Padding; 231 uint16_t padlen = (kEdns0Padding - extra) % kEdns0Padding; 232 if (minlen > buflen) { 233 return -1; 234 } 235 padlen = std::min(padlen, static_cast<uint16_t>(buflen - minlen)); 236 *reinterpret_cast<uint16_t*>(cp) = htons(padlen + 2 * INT16SZ); /* RDLEN */ 237 cp += INT16SZ; 238 *reinterpret_cast<uint16_t*>(cp) = htons(NS_OPT_PADDING); /* OPTION-CODE */ 239 cp += INT16SZ; 240 *reinterpret_cast<uint16_t*>(cp) = htons(padlen); /* OPTION-LENGTH */ 241 cp += INT16SZ; 242 memset(cp, 0, padlen); 243 cp += padlen; 244 245 hp->arcount = htons(ntohs(hp->arcount) + 1); 246 return (cp - buf); 247 } 248