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