1 /*- 2 * Copyright (c) 1985, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * - 7 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies, and that 12 * the name of Digital Equipment Corporation not be used in advertising or 13 * publicity pertaining to distribution of the document or software without 14 * specific, written prior permission. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 17 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 19 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 20 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 21 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 22 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 23 * SOFTWARE. 24 * - 25 * --Copyright-- 26 */ 27 28 #if defined(LIBC_SCCS) && !defined(lint) 29 static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 06/04/93"; 30 static char rcsid[] = "$Id: res_mkquery.c,v 4.9.1.2 1993/05/17 10:00:01 vixie Exp $"; 31 #endif /* LIBC_SCCS and not lint */ 32 33 #include <sys/param.h> 34 #include <netinet/in.h> 35 #include <arpa/nameser.h> 36 #include <resolv.h> 37 #include <stdio.h> 38 #include <string.h> 39 40 /* 41 * Form all types of queries. 42 * Returns the size of the result or -1. 43 */ 44 res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) 45 int op; /* opcode of query */ 46 const char *dname; /* domain name */ 47 int class, type; /* class and type of query */ 48 const char *data; /* resource record data */ 49 int datalen; /* length of data */ 50 const char *newrr_in; /* new rr for modify or append */ 51 char *buf; /* buffer to put query */ 52 int buflen; /* size of buffer */ 53 { 54 register HEADER *hp; 55 register char *cp; 56 register int n; 57 struct rrec *newrr = (struct rrec *) newrr_in; 58 char *dnptrs[10], **dpp, **lastdnptr; 59 60 #ifdef DEBUG 61 if (_res.options & RES_DEBUG) 62 printf(";; res_mkquery(%d, %s, %d, %d)\n", 63 op, dname, class, type); 64 #endif 65 /* 66 * Initialize header fields. 67 */ 68 if ((buf == NULL) || (buflen < sizeof(HEADER))) 69 return(-1); 70 bzero(buf, sizeof(HEADER)); 71 hp = (HEADER *) buf; 72 hp->id = htons(++_res.id); 73 hp->opcode = op; 74 hp->pr = (_res.options & RES_PRIMARY) != 0; 75 hp->rd = (_res.options & RES_RECURSE) != 0; 76 hp->rcode = NOERROR; 77 cp = buf + sizeof(HEADER); 78 buflen -= sizeof(HEADER); 79 dpp = dnptrs; 80 *dpp++ = buf; 81 *dpp++ = NULL; 82 lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 83 /* 84 * perform opcode specific processing 85 */ 86 switch (op) { 87 case QUERY: 88 if ((buflen -= QFIXEDSZ) < 0) 89 return(-1); 90 if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen, 91 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 92 return (-1); 93 cp += n; 94 buflen -= n; 95 __putshort(type, (u_char *)cp); 96 cp += sizeof(u_int16_t); 97 __putshort(class, (u_char *)cp); 98 cp += sizeof(u_int16_t); 99 hp->qdcount = htons(1); 100 if (op == QUERY || data == NULL) 101 break; 102 /* 103 * Make an additional record for completion domain. 104 */ 105 buflen -= RRFIXEDSZ; 106 if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen, 107 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 108 return (-1); 109 cp += n; 110 buflen -= n; 111 __putshort(T_NULL, (u_char *)cp); 112 cp += sizeof(u_int16_t); 113 __putshort(class, (u_char *)cp); 114 cp += sizeof(u_int16_t); 115 __putlong(0, (u_char *)cp); 116 cp += sizeof(u_int32_t); 117 __putshort(0, (u_char *)cp); 118 cp += sizeof(u_int16_t); 119 hp->arcount = htons(1); 120 break; 121 122 case IQUERY: 123 /* 124 * Initialize answer section 125 */ 126 if (buflen < 1 + RRFIXEDSZ + datalen) 127 return (-1); 128 *cp++ = '\0'; /* no domain name */ 129 __putshort(type, (u_char *)cp); 130 cp += sizeof(u_int16_t); 131 __putshort(class, (u_char *)cp); 132 cp += sizeof(u_int16_t); 133 __putlong(0, (u_char *)cp); 134 cp += sizeof(u_int32_t); 135 __putshort(datalen, (u_char *)cp); 136 cp += sizeof(u_int16_t); 137 if (datalen) { 138 bcopy(data, cp, datalen); 139 cp += datalen; 140 } 141 hp->ancount = htons(1); 142 break; 143 144 #ifdef ALLOW_UPDATES 145 /* 146 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 147 * (Record to be modified is followed by its replacement in msg.) 148 */ 149 case UPDATEM: 150 case UPDATEMA: 151 152 case UPDATED: 153 /* 154 * The res code for UPDATED and UPDATEDA is the same; user 155 * calls them differently: specifies data for UPDATED; server 156 * ignores data if specified for UPDATEDA. 157 */ 158 case UPDATEDA: 159 buflen -= RRFIXEDSZ + datalen; 160 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 161 return (-1); 162 cp += n; 163 __putshort(type, cp); 164 cp += sizeof(u_int16_t); 165 __putshort(class, cp); 166 cp += sizeof(u_int16_t); 167 __putlong(0, cp); 168 cp += sizeof(u_int32_t); 169 __putshort(datalen, cp); 170 cp += sizeof(u_int16_t); 171 if (datalen) { 172 bcopy(data, cp, datalen); 173 cp += datalen; 174 } 175 if ( (op == UPDATED) || (op == UPDATEDA) ) { 176 hp->ancount = htons(0); 177 break; 178 } 179 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 180 181 case UPDATEA: /* Add new resource record */ 182 buflen -= RRFIXEDSZ + datalen; 183 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 184 return (-1); 185 cp += n; 186 __putshort(newrr->r_type, cp); 187 cp += sizeof(u_int16_t); 188 __putshort(newrr->r_class, cp); 189 cp += sizeof(u_int16_t); 190 __putlong(0, cp); 191 cp += sizeof(u_int32_t); 192 __putshort(newrr->r_size, cp); 193 cp += sizeof(u_int16_t); 194 if (newrr->r_size) { 195 bcopy(newrr->r_data, cp, newrr->r_size); 196 cp += newrr->r_size; 197 } 198 hp->ancount = htons(0); 199 break; 200 201 #endif /* ALLOW_UPDATES */ 202 } 203 return (cp - buf); 204 } 205