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