
1: /* 2: * Copyright (c) 1985, 1993 3: * The Regents of the University of California. All rights reserved. 4: * 5: * Redistribution and use in source and binary forms, with or without 6: * modification, are permitted provided that the following conditions 7: * are met: 8: * 1. Redistributions of source code must retain the above copyright 9: * notice, this list of conditions and the following disclaimer. 10: * 2. Redistributions in binary form must reproduce the above copyright 11: * notice, this list of conditions and the following disclaimer in the 12: * documentation and/or other materials provided with the distribution. 13: * 4. Neither the name of the University nor the names of its contributors 14: * may be used to endorse or promote products derived from this software 15: * without specific prior written permission. 16: * 17: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27: * SUCH DAMAGE. 28: */ 29: 30: /* 31: * Portions Copyright (c) 1993 by Digital Equipment Corporation. 32: * 33: * Permission to use, copy, modify, and distribute this software for any 34: * purpose with or without fee is hereby granted, provided that the above 35: * copyright notice and this permission notice appear in all copies, and that 36: * the name of Digital Equipment Corporation not be used in advertising or 37: * publicity pertaining to distribution of the document or software without 38: * specific, written prior permission. 39: * 40: * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 41: * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 42: * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 43: * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 44: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 45: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 46: * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 47: * SOFTWARE. 48: */ 49: 50: /* 51: * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 52: * 53: * Permission to use, copy, modify, and distribute this software for any 54: * purpose with or without fee is hereby granted, provided that the above 55: * copyright notice and this permission notice appear in all copies. 56: * 57: * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 58: * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 59: * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 60: * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 61: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 62: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 63: * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 64: * SOFTWARE. 65: */ 66: 67: #if defined(LIBC_SCCS) && !defined(lint) 68: static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; 69: static const char rcsid[] = "$BINDId: res_mkquery.c,v 8.12 1999/10/13 16:39:40 vixie Exp $"; 70: #endif /* LIBC_SCCS and not lint */ 71: 72: #include <sys/types.h> 73: #include <sys/param.h> 74: #include <netinet/in.h> 75: #include <arpa/nameser.h> 76: #include <netdb.h> 77: #include <resolv.h> 78: #include <stdio.h> 79: #include <string.h> 80: 81: /* Options. Leave them on. */ 82: /* #define DEBUG */ 83: 84: #ifdef _LIBC 85: # include <hp-timing.h> 86: # if HP_TIMING_AVAIL 87: # define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; } 88: # endif 89: #endif 90: 91: /* 92: * Form all types of queries. 93: * Returns the size of the result or -1. 94: */ 95: int 96: res_nmkquery(res_state statp, 97: int op, /* opcode of query */ 98: const char *dname, /* domain name */ 99: int class, int type, /* class and type of query */ 100: const u_char *data, /* resource record data */ 101: int datalen, /* length of data */ 102: const u_char *newrr_in, /* new rr for modify or append */ 103: u_char *buf, /* buffer to put query */ 104: int buflen) /* size of buffer */ 105: { 106: register HEADER *hp; 107: register u_char *cp; 108: register int n; 109: u_char *dnptrs[20], **dpp, **lastdnptr; 110: 111: #ifdef DEBUG 112: if (statp->options & RES_DEBUG) 113: printf(";; res_nmkquery(%s, %s, %s, %s)\n", 114: _res_opcodes[op], dname, p_class(class), p_type(type)); 115: #endif 116: /* 117: * Initialize header fields. 118: */ 119: if ((buf == NULL) || (buflen < HFIXEDSZ)) 120: return (-1); 121: memset(buf, 0, HFIXEDSZ); 122: hp = (HEADER *) buf; 123: /* We randomize the IDs every time. The old code just 124: incremented by one after the initial randomization which 125: still predictable if the application does multiple 126: requests. */ 127: int randombits; 128: do 129: { 130: #ifdef RANDOM_BITS 131: RANDOM_BITS (randombits); 132: #else 133: struct timeval tv; 134: __gettimeofday (&tv, NULL); 135: randombits = (tv.tv_sec << 8) ^ tv.tv_usec; 136: #endif 137: } 138: while ((randombits & 0xffff) == 0); 139: statp->id = (statp->id + randombits) & 0xffff; 140: hp->id = statp->id; 141: hp->opcode = op; 142: hp->rd = (statp->options & RES_RECURSE) != 0; 143: hp->rcode = NOERROR; 144: cp = buf + HFIXEDSZ; 145: buflen -= HFIXEDSZ; 146: dpp = dnptrs; 147: *dpp++ = buf; 148: *dpp++ = NULL; 149: lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; 150: /* 151: * perform opcode specific processing 152: */ 153: switch (op) { 154: case NS_NOTIFY_OP: 155: if ((buflen -= QFIXEDSZ + (data == NULL ? 0 : RRFIXEDSZ)) < 0) 156: return (-1); 157: goto compose; 158: 159: case QUERY: 160: if ((buflen -= QFIXEDSZ) < 0) 161: return (-1); 162: compose: 163: if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 164: return (-1); 165: cp += n; 166: buflen -= n; 167: NS_PUT16 (type, cp); 168: NS_PUT16 (class, cp); 169: hp->qdcount = htons(1); 170: if (op == QUERY || data == NULL) 171: break; 172: /* 173: * Make an additional record for completion domain. 174: */ 175: n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr); 176: if (__builtin_expect (n < 0, 0)) 177: return (-1); 178: cp += n; 179: buflen -= n; 180: NS_PUT16 (T_NULL, cp); 181: NS_PUT16 (class, cp); 182: NS_PUT32 (0, cp); 183: NS_PUT16 (0, cp); 184: hp->arcount = htons(1); 185: break; 186: 187: case IQUERY: 188: /* 189: * Initialize answer section 190: */ 191: if (__builtin_expect (buflen < 1 + RRFIXEDSZ + datalen, 0)) 192: return (-1); 193: *cp++ = '\0'; /* no domain name */ 194: NS_PUT16 (type, cp); 195: NS_PUT16 (class, cp); 196: NS_PUT32 (0, cp); 197: NS_PUT16 (datalen, cp); 198: if (datalen) { 199: memcpy(cp, data, datalen); 200: cp += datalen; 201: } 202: hp->ancount = htons(1); 203: break; 204: 205: default: 206: return (-1); 207: } 208: return (cp - buf); 209: } 210: libresolv_hidden_def (res_nmkquery) 211: 212: 213: /* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */ 214: #ifndef T_OPT 215: #define T_OPT 41 216: #endif 217: 218: int 219: __res_nopt(res_state statp, 220: int n0, /* current offset in buffer */ 221: u_char *buf, /* buffer to put query */ 222: int buflen, /* size of buffer */ 223: int anslen) /* UDP answer buffer size */ 224: { 225: u_int16_t flags = 0; 226: 227: #ifdef DEBUG 228: if ((statp->options & RES_DEBUG) != 0U) 229: printf(";; res_nopt()\n"); 230: #endif 231: 232: HEADER *hp = (HEADER *) buf; 233: u_char *cp = buf + n0; 234: u_char *ep = buf + buflen; 235: 236: if ((ep - cp) < 1 + RRFIXEDSZ) 237: return -1; 238: 239: *cp++ = 0; /* "." */ 240: 241: ns_put16(T_OPT, cp); /* TYPE */ 242: cp += INT16SZ; 243: ns_put16(anslen & 0xffff, cp); /* CLASS = UDP payload size */ 244: cp += INT16SZ; 245: *cp++ = NOERROR; /* extended RCODE */ 246: *cp++ = 0; /* EDNS version */ 247: /* XXX Once we support DNSSEC we change the flag value here. */ 248: ns_put16(flags, cp); 249: cp += INT16SZ; 250: ns_put16(0, cp); /* RDLEN */ 251: cp += INT16SZ; 252: hp->arcount = htons(ntohs(hp->arcount) + 1); 253: 254: return cp - buf; 255: } 256: libresolv_hidden_def (__res_nopt)