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.16 (Berkeley) 03/06/91"; 10 #endif /* LIBC_SCCS and not lint */ 11 12 #include <sys/param.h> 13 #include <netinet/in.h> 14 #include <arpa/nameser.h> 15 #include <resolv.h> 16 #include <stdio.h> 17 #include <string.h> 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 const char *dname; /* domain name */ 26 int class, type; /* class and type of query */ 27 const char *data; /* resource record data */ 28 int datalen; /* length of data */ 29 const 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 *dnptrs[10], **dpp, **lastdnptr; 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((u_char *)dname, (u_char *)cp, buflen, 68 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 69 return (-1); 70 cp += n; 71 buflen -= n; 72 __putshort(type, (u_char *)cp); 73 cp += sizeof(u_short); 74 __putshort(class, (u_char *)cp); 75 cp += sizeof(u_short); 76 hp->qdcount = htons(1); 77 if (op == QUERY || data == NULL) 78 break; 79 /* 80 * Make an additional record for completion domain. 81 */ 82 buflen -= RRFIXEDSZ; 83 if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen, 84 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 85 return (-1); 86 cp += n; 87 buflen -= n; 88 __putshort(T_NULL, (u_char *)cp); 89 cp += sizeof(u_short); 90 __putshort(class, (u_char *)cp); 91 cp += sizeof(u_short); 92 __putlong(0, (u_char *)cp); 93 cp += sizeof(u_long); 94 __putshort(0, (u_char *)cp); 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 __putshort(type, (u_char *)cp); 107 cp += sizeof(u_short); 108 __putshort(class, (u_char *)cp); 109 cp += sizeof(u_short); 110 __putlong(0, (u_char *)cp); 111 cp += sizeof(u_long); 112 __putshort(datalen, (u_char *)cp); 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 ALLOW_UPDATES 122 /* 123 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 124 * (Record to be modified is followed by its replacement in msg.) 125 */ 126 case UPDATEM: 127 case UPDATEMA: 128 129 case UPDATED: 130 /* 131 * The res code for UPDATED and UPDATEDA is the same; user 132 * calls them differently: specifies data for UPDATED; server 133 * ignores data if specified for UPDATEDA. 134 */ 135 case UPDATEDA: 136 buflen -= RRFIXEDSZ + datalen; 137 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 138 return (-1); 139 cp += n; 140 __putshort(type, cp); 141 cp += sizeof(u_short); 142 __putshort(class, cp); 143 cp += sizeof(u_short); 144 __putlong(0, cp); 145 cp += sizeof(u_long); 146 __putshort(datalen, cp); 147 cp += sizeof(u_short); 148 if (datalen) { 149 bcopy(data, cp, datalen); 150 cp += datalen; 151 } 152 if ( (op == UPDATED) || (op == UPDATEDA) ) { 153 hp->ancount = htons(0); 154 break; 155 } 156 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 157 158 case UPDATEA: /* Add new resource record */ 159 buflen -= RRFIXEDSZ + datalen; 160 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 161 return (-1); 162 cp += n; 163 __putshort(newrr->r_type, cp); 164 cp += sizeof(u_short); 165 __putshort(newrr->r_class, cp); 166 cp += sizeof(u_short); 167 __putlong(0, cp); 168 cp += sizeof(u_long); 169 __putshort(newrr->r_size, cp); 170 cp += sizeof(u_short); 171 if (newrr->r_size) { 172 bcopy(newrr->r_data, cp, newrr->r_size); 173 cp += newrr->r_size; 174 } 175 hp->ancount = htons(0); 176 break; 177 178 #endif ALLOW_UPDATES 179 } 180 return (cp - buf); 181 } 182