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