1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)res_mkquery.c 5.4 (Berkeley) 09/14/85"; 9 #endif not lint 10 11 #include <stdio.h> 12 #include <sys/types.h> 13 #include <netinet/in.h> 14 #include <arpa/nameser.h> 15 #include <arpa/resolv.h> 16 17 /* 18 * Form all types of queries. 19 * Returns the size of the result or -1. 20 */ 21 res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen) 22 int op; /* opcode of query */ 23 char *dname; /* domain name */ 24 int class, type; /* class and type of query */ 25 char *data; /* resource record data */ 26 int datalen; /* length of data */ 27 struct rrec *newrr; /* new rr for modify or append */ 28 char *buf; /* buffer to put query */ 29 int buflen; /* size of buffer */ 30 { 31 register HEADER *hp; 32 register char *cp; 33 register int n; 34 char dnbuf[MAXDNAME]; 35 char *dnptrs[10], **dpp, **lastdnptr; 36 extern char *index(); 37 38 #ifdef DEBUG 39 if (_res.options & RES_DEBUG) 40 printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type); 41 #endif 42 /* 43 * Initialize header fields. 44 */ 45 hp = (HEADER *) buf; 46 hp->id = htons(++_res.id); 47 hp->opcode = op; 48 hp->qr = hp->aa = hp->tc = hp->ra = 0; 49 hp->pr = (_res.options & RES_PRIMARY) != 0; 50 hp->rd = (_res.options & RES_RECURSE) != 0; 51 hp->rcode = NOERROR; 52 hp->qdcount = 0; 53 hp->ancount = 0; 54 hp->nscount = 0; 55 hp->arcount = 0; 56 cp = buf + sizeof(HEADER); 57 buflen -= sizeof(HEADER); 58 dpp = dnptrs; 59 *dpp++ = buf; 60 *dpp++ = NULL; 61 lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 62 /* 63 * If the domain name contains no dots (single label), then 64 * append the default domain name to the one given. 65 */ 66 if ((_res.options & RES_DEFNAMES) && dname[0] != '\0' && 67 index(dname, '.') == NULL) { 68 if (!(_res.options & RES_INIT)) 69 if (res_init() == -1) 70 return(-1); 71 if (_res.defdname[0] != '\0') 72 dname = sprintf(dnbuf, "%s.%s", dname, _res.defdname); 73 } 74 /* 75 * perform opcode specific processing 76 */ 77 switch (op) { 78 case QUERY: 79 case CQUERYM: 80 case CQUERYU: 81 buflen -= QFIXEDSZ; 82 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 83 return (-1); 84 cp += n; 85 buflen -= n; 86 putshort(type, cp); 87 cp += sizeof(u_short); 88 putshort(class, cp); 89 cp += sizeof(u_short); 90 hp->qdcount = htons(1); 91 if (op == QUERY || data == NULL) 92 break; 93 /* 94 * Make an additional record for completion domain. 95 */ 96 buflen -= RRFIXEDSZ; 97 if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) 98 return (-1); 99 cp += n; 100 buflen -= n; 101 putshort(T_NULL, cp); 102 cp += sizeof(u_short); 103 putshort(class, cp); 104 cp += sizeof(u_short); 105 putlong(0, cp); 106 cp += sizeof(u_long); 107 putshort(0, cp); 108 cp += sizeof(u_short); 109 hp->arcount = htons(1); 110 break; 111 112 case IQUERY: 113 /* 114 * Initialize answer section 115 */ 116 if (buflen < 1 + RRFIXEDSZ + datalen) 117 return (-1); 118 *cp++ = '\0'; /* no domain name */ 119 putshort(type, cp); 120 cp += sizeof(u_short); 121 putshort(class, cp); 122 cp += sizeof(u_short); 123 putlong(0, cp); 124 cp += sizeof(u_long); 125 putshort(datalen, cp); 126 cp += sizeof(u_short); 127 if (datalen) { 128 bcopy(data, cp, datalen); 129 cp += datalen; 130 } 131 hp->ancount = htons(1); 132 break; 133 134 #ifdef notdef 135 case UPDATED: 136 /* 137 * Put record to be added or deleted in additional section 138 */ 139 buflen -= RRFIXEDSZ + datalen; 140 if ((n = dn_comp(dname, cp, buflen, NULL, NULL)) < 0) 141 return (-1); 142 cp += n; 143 *((u_short *)cp) = htons(type); 144 cp += sizeof(u_short); 145 *((u_short *)cp) = htons(class); 146 cp += sizeof(u_short); 147 *((u_long *)cp) = 0; 148 cp += sizeof(u_long); 149 *((u_short *)cp) = htons(datalen); 150 cp += sizeof(u_short); 151 if (datalen) { 152 bcopy(data, cp, datalen); 153 cp += datalen; 154 } 155 break; 156 157 case UPDATEM: 158 /* 159 * Record to be modified followed by its replacement 160 */ 161 buflen -= RRFIXEDSZ + datalen; 162 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 163 return (-1); 164 cp += n; 165 *((u_short *)cp) = htons(type); 166 cp += sizeof(u_short); 167 *((u_short *)cp) = htons(class); 168 cp += sizeof(u_short); 169 *((u_long *)cp) = 0; 170 cp += sizeof(u_long); 171 *((u_short *)cp) = htons(datalen); 172 cp += sizeof(u_short); 173 if (datalen) { 174 bcopy(data, cp, datalen); 175 cp += datalen; 176 } 177 178 case UPDATEA: 179 buflen -= RRFIXEDSZ + newrr->r_size; 180 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 181 return (-1); 182 cp += n; 183 *((u_short *)cp) = htons(newrr->r_type); 184 cp += sizeof(u_short); 185 *((u_short *)cp) = htons(newrr->r_type); 186 cp += sizeof(u_short); 187 *((u_long *)cp) = htonl(newrr->r_ttl); 188 cp += sizeof(u_long); 189 *((u_short *)cp) = htons(newrr->r_size); 190 cp += sizeof(u_short); 191 if (newrr->r_size) { 192 bcopy(newrr->r_data, cp, newrr->r_size); 193 cp += newrr->r_size; 194 } 195 break; 196 #endif 197 } 198 return (cp - buf); 199 } 200