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