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 #if defined(LIBC_SCCS) && !defined(lint) 8 static char sccsid[] = "@(#)res_mkquery.c 6.4 (Berkeley) 11/10/86"; 9 #endif LIBC_SCCS and not lint 10 11 #include <stdio.h> 12 #include <sys/types.h> 13 #include <netinet/in.h> 14 #include <arpa/nameser.h> 15 #include <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 ALLOW_UPDATES 137 /* 138 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 139 * (Record to be modified is followed by its replacement in msg.) 140 */ 141 case UPDATEM: 142 case UPDATEMA: 143 144 case UPDATED: 145 /* 146 * The res code for UPDATED and UPDATEDA is the same; user 147 * calls them differently: specifies data for UPDATED; server 148 * ignores data if specified for UPDATEDA. 149 */ 150 case UPDATEDA: 151 buflen -= RRFIXEDSZ + datalen; 152 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 153 return (-1); 154 cp += n; 155 putshort(type, cp); 156 cp += sizeof(u_short); 157 putshort(class, cp); 158 cp += sizeof(u_short); 159 putlong(0, cp); 160 cp += sizeof(u_long); 161 putshort(datalen, cp); 162 cp += sizeof(u_short); 163 if (datalen) { 164 bcopy(data, cp, datalen); 165 cp += datalen; 166 } 167 if ( (op == UPDATED) || (op == UPDATEDA) ) { 168 hp->ancount = htons(0); 169 break; 170 } 171 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 172 173 case UPDATEA: /* Add new resource record */ 174 buflen -= RRFIXEDSZ + datalen; 175 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 176 return (-1); 177 cp += n; 178 putshort(newrr->r_type, cp); 179 cp += sizeof(u_short); 180 putshort(newrr->r_class, cp); 181 cp += sizeof(u_short); 182 putlong(0, cp); 183 cp += sizeof(u_long); 184 putshort(newrr->r_size, cp); 185 cp += sizeof(u_short); 186 if (newrr->r_size) { 187 bcopy(newrr->r_data, cp, newrr->r_size); 188 cp += newrr->r_size; 189 } 190 hp->ancount = htons(0); 191 break; 192 193 #endif ALLOW_UPDATES 194 } 195 return (cp - buf); 196 } 197