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