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