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