1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #if defined(LIBC_SCCS) && !defined(lint) 9 static char sccsid[] = "@(#)res_mkquery.c 6.12 (Berkeley) 06/01/90"; 10 #endif /* LIBC_SCCS and not lint */ 11 12 #include <stdio.h> 13 #include <sys/types.h> 14 #include <netinet/in.h> 15 #include <arpa/nameser.h> 16 #include <resolv.h> 17 18 /* 19 * Form all types of queries. 20 * Returns the size of the result or -1. 21 */ 22 res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen) 23 int op; /* opcode of query */ 24 char *dname; /* domain name */ 25 int class, type; /* class and type of query */ 26 char *data; /* resource record data */ 27 int datalen; /* length of data */ 28 struct rrec *newrr; /* new rr for modify or append */ 29 char *buf; /* buffer to put query */ 30 int buflen; /* size of buffer */ 31 { 32 register HEADER *hp; 33 register char *cp; 34 register int n; 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 if ((buf == NULL) || (buflen < sizeof(HEADER))) 46 return(-1); 47 bzero(buf, sizeof(HEADER)); 48 hp = (HEADER *) buf; 49 hp->id = htons(++_res.id); 50 hp->opcode = op; 51 hp->pr = (_res.options & RES_PRIMARY) != 0; 52 hp->rd = (_res.options & RES_RECURSE) != 0; 53 hp->rcode = NOERROR; 54 cp = buf + sizeof(HEADER); 55 buflen -= sizeof(HEADER); 56 dpp = dnptrs; 57 *dpp++ = buf; 58 *dpp++ = NULL; 59 lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 60 /* 61 * perform opcode specific processing 62 */ 63 switch (op) { 64 case QUERY: 65 if ((buflen -= QFIXEDSZ) < 0) 66 return(-1); 67 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 68 return (-1); 69 cp += n; 70 buflen -= n; 71 putshort(type, cp); 72 cp += sizeof(u_short); 73 putshort(class, cp); 74 cp += sizeof(u_short); 75 hp->qdcount = htons(1); 76 if (op == QUERY || data == NULL) 77 break; 78 /* 79 * Make an additional record for completion domain. 80 */ 81 buflen -= RRFIXEDSZ; 82 if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) 83 return (-1); 84 cp += n; 85 buflen -= n; 86 putshort(T_NULL, cp); 87 cp += sizeof(u_short); 88 putshort(class, cp); 89 cp += sizeof(u_short); 90 putlong(0, cp); 91 cp += sizeof(u_long); 92 putshort(0, cp); 93 cp += sizeof(u_short); 94 hp->arcount = htons(1); 95 break; 96 97 case IQUERY: 98 /* 99 * Initialize answer section 100 */ 101 if (buflen < 1 + RRFIXEDSZ + datalen) 102 return (-1); 103 *cp++ = '\0'; /* no domain name */ 104 putshort(type, cp); 105 cp += sizeof(u_short); 106 putshort(class, cp); 107 cp += sizeof(u_short); 108 putlong(0, cp); 109 cp += sizeof(u_long); 110 putshort(datalen, cp); 111 cp += sizeof(u_short); 112 if (datalen) { 113 bcopy(data, cp, datalen); 114 cp += datalen; 115 } 116 hp->ancount = htons(1); 117 break; 118 119 #ifdef ALLOW_UPDATES 120 /* 121 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 122 * (Record to be modified is followed by its replacement in msg.) 123 */ 124 case UPDATEM: 125 case UPDATEMA: 126 127 case UPDATED: 128 /* 129 * The res code for UPDATED and UPDATEDA is the same; user 130 * calls them differently: specifies data for UPDATED; server 131 * ignores data if specified for UPDATEDA. 132 */ 133 case UPDATEDA: 134 buflen -= RRFIXEDSZ + datalen; 135 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 136 return (-1); 137 cp += n; 138 putshort(type, cp); 139 cp += sizeof(u_short); 140 putshort(class, cp); 141 cp += sizeof(u_short); 142 putlong(0, cp); 143 cp += sizeof(u_long); 144 putshort(datalen, cp); 145 cp += sizeof(u_short); 146 if (datalen) { 147 bcopy(data, cp, datalen); 148 cp += datalen; 149 } 150 if ( (op == UPDATED) || (op == UPDATEDA) ) { 151 hp->ancount = htons(0); 152 break; 153 } 154 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 155 156 case UPDATEA: /* Add new resource record */ 157 buflen -= RRFIXEDSZ + datalen; 158 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 159 return (-1); 160 cp += n; 161 putshort(newrr->r_type, cp); 162 cp += sizeof(u_short); 163 putshort(newrr->r_class, cp); 164 cp += sizeof(u_short); 165 putlong(0, cp); 166 cp += sizeof(u_long); 167 putshort(newrr->r_size, cp); 168 cp += sizeof(u_short); 169 if (newrr->r_size) { 170 bcopy(newrr->r_data, cp, newrr->r_size); 171 cp += newrr->r_size; 172 } 173 hp->ancount = htons(0); 174 break; 175 176 #endif ALLOW_UPDATES 177 } 178 return (cp - buf); 179 } 180