1 /* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 7 /* 8 * Portions Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") 9 * Portions Copyright (C) 1996, 1997, 1988, 1999, 2001, 2003 Internet Software Consortium. 10 * 11 * Permission to use, copy, modify, and/or distribute this software for any 12 * purpose with or without fee is hereby granted, provided that the above 13 * copyright notice and this permission notice appear in all copies. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 16 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 17 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 18 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 19 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 20 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24 /* 25 * Copyright (c) 1985, 1993 26 * The Regents of the University of California. All rights reserved. 27 * 28 * Redistribution and use in source and binary forms, with or without 29 * modification, are permitted provided that the following conditions 30 * are met: 31 * 1. Redistributions of source code must retain the above copyright 32 * notice, this list of conditions and the following disclaimer. 33 * 2. Redistributions in binary form must reproduce the above copyright 34 * notice, this list of conditions and the following disclaimer in the 35 * documentation and/or other materials provided with the distribution. 36 * 3. All advertising materials mentioning features or use of this software 37 * must display the following acknowledgement: 38 * This product includes software developed by the University of 39 * California, Berkeley and its contributors. 40 * 4. Neither the name of the University nor the names of its contributors 41 * may be used to endorse or promote products derived from this software 42 * without specific prior written permission. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * SUCH DAMAGE. 55 */ 56 57 /* 58 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 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, and that 63 * the name of Digital Equipment Corporation not be used in advertising or 64 * publicity pertaining to distribution of the document or software without 65 * specific, written prior permission. 66 * 67 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 68 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 69 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 70 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 71 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 72 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 73 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 74 * SOFTWARE. 75 */ 76 77 #if defined(LIBC_SCCS) && !defined(lint) 78 static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; 79 static const char rcsid[] = "$Id: res_mkquery.c,v 1.10 2008/12/11 09:59:00 marka Exp $"; 80 #endif /* LIBC_SCCS and not lint */ 81 82 #include "port_before.h" 83 #include <sys/types.h> 84 #include <sys/param.h> 85 #include <netinet/in.h> 86 #include <arpa/nameser.h> 87 88 #ifdef SUNW_CONFCHECK 89 #include <sys/socket.h> 90 #include <errno.h> 91 #include <sys/stat.h> 92 #endif /* SUNW_CONFCHECK */ 93 94 95 #include <netdb.h> 96 #include <resolv.h> 97 #include <stdio.h> 98 #include <string.h> 99 #include "port_after.h" 100 101 /* Options. Leave them on. */ 102 #define DEBUG 103 104 extern const char *_res_opcodes[]; 105 106 #ifdef SUNW_CONFCHECK 107 static int _confcheck(res_state statp); 108 #endif /* SUNW_CONFCHECK */ 109 110 111 /*% 112 * Form all types of queries. 113 * Returns the size of the result or -1. 114 */ 115 int 116 res_nmkquery(res_state statp, 117 int op, /*!< opcode of query */ 118 const char *dname, /*!< domain name */ 119 int class, int type, /*!< class and type of query */ 120 const u_char *data, /*!< resource record data */ 121 int datalen, /*!< length of data */ 122 const u_char *newrr_in, /*!< new rr for modify or append */ 123 u_char *buf, /*!< buffer to put query */ 124 int buflen) /*!< size of buffer */ 125 { 126 register HEADER *hp; 127 register u_char *cp, *ep; 128 register int n; 129 u_char *dnptrs[20], **dpp, **lastdnptr; 130 131 UNUSED(newrr_in); 132 133 #ifdef DEBUG 134 if (statp->options & RES_DEBUG) 135 printf(";; res_nmkquery(%s, %s, %s, %s)\n", 136 _res_opcodes[op], dname, p_class(class), p_type(type)); 137 #endif 138 139 #ifdef SUNW_CONFCHECK 140 /* 141 * 1247019, 1265838, and 4034368: Check to see if we can 142 * bailout quickly. 143 */ 144 if (_confcheck(statp) == -1) { 145 RES_SET_H_ERRNO(statp, NO_RECOVERY); 146 return(-1); 147 } 148 #endif /* SUNW_CONFCHECK */ 149 150 /* 151 * Initialize header fields. 152 */ 153 if ((buf == NULL) || (buflen < HFIXEDSZ)) 154 return (-1); 155 memset(buf, 0, HFIXEDSZ); 156 hp = (HEADER *) buf; 157 statp->id = res_nrandomid(statp); 158 hp->id = htons(statp->id); 159 hp->opcode = op; 160 hp->rd = (statp->options & RES_RECURSE) != 0U; 161 hp->rcode = NOERROR; 162 cp = buf + HFIXEDSZ; 163 ep = buf + buflen; 164 dpp = dnptrs; 165 *dpp++ = buf; 166 *dpp++ = NULL; 167 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; 168 /* 169 * perform opcode specific processing 170 */ 171 switch (op) { 172 case QUERY: /*FALLTHROUGH*/ 173 case NS_NOTIFY_OP: 174 if (ep - cp < QFIXEDSZ) 175 return (-1); 176 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs, 177 lastdnptr)) < 0) 178 return (-1); 179 cp += n; 180 ns_put16(type, cp); 181 cp += INT16SZ; 182 ns_put16(class, cp); 183 cp += INT16SZ; 184 hp->qdcount = htons(1); 185 if (op == QUERY || data == NULL) 186 break; 187 /* 188 * Make an additional record for completion domain. 189 */ 190 if ((ep - cp) < RRFIXEDSZ) 191 return (-1); 192 n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ, 193 dnptrs, lastdnptr); 194 if (n < 0) 195 return (-1); 196 cp += n; 197 ns_put16(T_NULL, cp); 198 cp += INT16SZ; 199 ns_put16(class, cp); 200 cp += INT16SZ; 201 ns_put32(0, cp); 202 cp += INT32SZ; 203 ns_put16(0, cp); 204 cp += INT16SZ; 205 hp->arcount = htons(1); 206 break; 207 208 case IQUERY: 209 /* 210 * Initialize answer section 211 */ 212 if (ep - cp < 1 + RRFIXEDSZ + datalen) 213 return (-1); 214 *cp++ = '\0'; /*%< no domain name */ 215 ns_put16(type, cp); 216 cp += INT16SZ; 217 ns_put16(class, cp); 218 cp += INT16SZ; 219 ns_put32(0, cp); 220 cp += INT32SZ; 221 ns_put16(datalen, cp); 222 cp += INT16SZ; 223 if (datalen) { 224 memcpy(cp, data, datalen); 225 cp += datalen; 226 } 227 hp->ancount = htons(1); 228 break; 229 230 default: 231 return (-1); 232 } 233 return (cp - buf); 234 } 235 236 #ifdef RES_USE_EDNS0 237 /* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */ 238 239 int 240 res_nopt(res_state statp, 241 int n0, /*%< current offset in buffer */ 242 u_char *buf, /*%< buffer to put query */ 243 int buflen, /*%< size of buffer */ 244 int anslen) /*%< UDP answer buffer size */ 245 { 246 register HEADER *hp; 247 register u_char *cp, *ep; 248 u_int16_t flags = 0; 249 250 #ifdef DEBUG 251 if ((statp->options & RES_DEBUG) != 0U) 252 printf(";; res_nopt()\n"); 253 #endif 254 255 hp = (HEADER *) buf; 256 cp = buf + n0; 257 ep = buf + buflen; 258 259 if ((ep - cp) < 1 + RRFIXEDSZ) 260 return (-1); 261 262 *cp++ = 0; /*%< "." */ 263 ns_put16(ns_t_opt, cp); /*%< TYPE */ 264 cp += INT16SZ; 265 ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */ 266 cp += INT16SZ; 267 *cp++ = NOERROR; /*%< extended RCODE */ 268 *cp++ = 0; /*%< EDNS version */ 269 270 if (statp->options & RES_USE_DNSSEC) { 271 #ifdef DEBUG 272 if (statp->options & RES_DEBUG) 273 printf(";; res_opt()... ENDS0 DNSSEC\n"); 274 #endif 275 flags |= NS_OPT_DNSSEC_OK; 276 } 277 ns_put16(flags, cp); 278 cp += INT16SZ; 279 280 ns_put16(0U, cp); /*%< RDLEN */ 281 cp += INT16SZ; 282 283 hp->arcount = htons(ntohs(hp->arcount) + 1); 284 285 return (cp - buf); 286 } 287 288 /* 289 * Construct variable data (RDATA) block for OPT psuedo-RR, append it 290 * to the buffer, then update the RDLEN field (previously set to zero by 291 * res_nopt()) with the new RDATA length. 292 */ 293 int 294 res_nopt_rdata(res_state statp, 295 int n0, /*%< current offset in buffer */ 296 u_char *buf, /*%< buffer to put query */ 297 int buflen, /*%< size of buffer */ 298 u_char *rdata, /*%< ptr to start of opt rdata */ 299 u_short code, /*%< OPTION-CODE */ 300 u_short len, /*%< OPTION-LENGTH */ 301 u_char *data) /*%< OPTION_DATA */ 302 { 303 register u_char *cp, *ep; 304 305 #ifdef DEBUG 306 if ((statp->options & RES_DEBUG) != 0U) 307 printf(";; res_nopt_rdata()\n"); 308 #endif 309 310 cp = buf + n0; 311 ep = buf + buflen; 312 313 if ((ep - cp) < (4 + len)) 314 return (-1); 315 316 if (rdata < (buf + 2) || rdata >= ep) 317 return (-1); 318 319 ns_put16(code, cp); 320 cp += INT16SZ; 321 322 ns_put16(len, cp); 323 cp += INT16SZ; 324 325 memcpy(cp, data, len); 326 cp += len; 327 328 len = cp - rdata; 329 ns_put16(len, rdata - 2); /* Update RDLEN field */ 330 331 return (cp - buf); 332 } 333 #endif 334 335 #ifdef SUNW_CONFCHECK 336 337 /* 338 * Time out quickly if there is no /etc/resolv.conf and a TCP connection 339 * to the local DNS server fails. 340 */ 341 static int _confcheck(res_state statp) 342 { 343 int ns; 344 struct stat rc_stat; 345 struct sockaddr_in ns_sin; 346 347 /* First, we check to see if /etc/resolv.conf exists. 348 * If it doesn't, then it is likely that the localhost is 349 * the nameserver. 350 */ 351 if (stat(_PATH_RESCONF, &rc_stat) == -1 && errno == ENOENT) { 352 353 /* Next, we check to see if _res.nsaddr is set to loopback. 354 * If it isn't, it has been altered by the application 355 * explicitly and we then want to bail with success. 356 */ 357 if (statp->nsaddr.sin_addr.S_un.S_addr == 358 htonl(INADDR_LOOPBACK)) { 359 360 /* Lastly, we try to connect to the TCP port of the 361 * nameserver. If this fails, then we know that 362 * DNS is misconfigured and we can quickly exit. 363 */ 364 ns = socket(AF_INET, SOCK_STREAM, 0); 365 IN_SET_LOOPBACK_ADDR(&ns_sin); 366 ns_sin.sin_port = htons(NAMESERVER_PORT); 367 if (connect(ns, (struct sockaddr *) &ns_sin, 368 sizeof ns_sin) == -1) { 369 close(ns); 370 return(-1); 371 } 372 else { 373 close(ns); 374 375 return(0); 376 } 377 } 378 379 return(0); 380 } 381 382 return (0); 383 } 384 #endif /* SUNW_CONFCHECK */ 385 386 /*! \file */ 387