1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #if defined(LIBC_SCCS) && !defined(lint) 19 static char sccsid[] = "@(#)res_mkquery.c 6.9 (Berkeley) 12/08/88"; 20 #endif /* LIBC_SCCS and not lint */ 21 22 #include <stdio.h> 23 #include <sys/types.h> 24 #include <netinet/in.h> 25 #include <arpa/nameser.h> 26 #include <resolv.h> 27 28 /* 29 * Form all types of queries. 30 * Returns the size of the result or -1. 31 */ 32 res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen) 33 int op; /* opcode of query */ 34 char *dname; /* domain name */ 35 int class, type; /* class and type of query */ 36 char *data; /* resource record data */ 37 int datalen; /* length of data */ 38 struct rrec *newrr; /* new rr for modify or append */ 39 char *buf; /* buffer to put query */ 40 int buflen; /* size of buffer */ 41 { 42 register HEADER *hp; 43 register char *cp; 44 register int n; 45 char dnbuf[MAXDNAME]; 46 char *dnptrs[10], **dpp, **lastdnptr; 47 extern char *index(); 48 49 #ifdef DEBUG 50 if (_res.options & RES_DEBUG) 51 printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type); 52 #endif DEBUG 53 /* 54 * Initialize header fields. 55 */ 56 bzero(buf, sizeof(HEADER)); 57 hp = (HEADER *) buf; 58 hp->id = htons(++_res.id); 59 hp->opcode = op; 60 hp->pr = (_res.options & RES_PRIMARY) != 0; 61 hp->rd = (_res.options & RES_RECURSE) != 0; 62 hp->rcode = NOERROR; 63 cp = buf + sizeof(HEADER); 64 buflen -= sizeof(HEADER); 65 dpp = dnptrs; 66 *dpp++ = buf; 67 *dpp++ = NULL; 68 lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 69 /* 70 * perform opcode specific processing 71 */ 72 switch (op) { 73 case QUERY: 74 buflen -= QFIXEDSZ; 75 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 76 return (-1); 77 cp += n; 78 buflen -= n; 79 putshort(type, cp); 80 cp += sizeof(u_short); 81 putshort(class, cp); 82 cp += sizeof(u_short); 83 hp->qdcount = htons(1); 84 if (op == QUERY || data == NULL) 85 break; 86 /* 87 * Make an additional record for completion domain. 88 */ 89 buflen -= RRFIXEDSZ; 90 if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) 91 return (-1); 92 cp += n; 93 buflen -= n; 94 putshort(T_NULL, cp); 95 cp += sizeof(u_short); 96 putshort(class, cp); 97 cp += sizeof(u_short); 98 putlong(0, cp); 99 cp += sizeof(u_long); 100 putshort(0, cp); 101 cp += sizeof(u_short); 102 hp->arcount = htons(1); 103 break; 104 105 case IQUERY: 106 /* 107 * Initialize answer section 108 */ 109 if (buflen < 1 + RRFIXEDSZ + datalen) 110 return (-1); 111 *cp++ = '\0'; /* no domain name */ 112 putshort(type, cp); 113 cp += sizeof(u_short); 114 putshort(class, cp); 115 cp += sizeof(u_short); 116 putlong(0, cp); 117 cp += sizeof(u_long); 118 putshort(datalen, cp); 119 cp += sizeof(u_short); 120 if (datalen) { 121 bcopy(data, cp, datalen); 122 cp += datalen; 123 } 124 hp->ancount = htons(1); 125 break; 126 127 #ifdef ALLOW_UPDATES 128 /* 129 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA 130 * (Record to be modified is followed by its replacement in msg.) 131 */ 132 case UPDATEM: 133 case UPDATEMA: 134 135 case UPDATED: 136 /* 137 * The res code for UPDATED and UPDATEDA is the same; user 138 * calls them differently: specifies data for UPDATED; server 139 * ignores data if specified for UPDATEDA. 140 */ 141 case UPDATEDA: 142 buflen -= RRFIXEDSZ + datalen; 143 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 144 return (-1); 145 cp += n; 146 putshort(type, cp); 147 cp += sizeof(u_short); 148 putshort(class, cp); 149 cp += sizeof(u_short); 150 putlong(0, cp); 151 cp += sizeof(u_long); 152 putshort(datalen, cp); 153 cp += sizeof(u_short); 154 if (datalen) { 155 bcopy(data, cp, datalen); 156 cp += datalen; 157 } 158 if ( (op == UPDATED) || (op == UPDATEDA) ) { 159 hp->ancount = htons(0); 160 break; 161 } 162 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ 163 164 case UPDATEA: /* Add new resource record */ 165 buflen -= RRFIXEDSZ + datalen; 166 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) 167 return (-1); 168 cp += n; 169 putshort(newrr->r_type, cp); 170 cp += sizeof(u_short); 171 putshort(newrr->r_class, cp); 172 cp += sizeof(u_short); 173 putlong(0, cp); 174 cp += sizeof(u_long); 175 putshort(newrr->r_size, cp); 176 cp += sizeof(u_short); 177 if (newrr->r_size) { 178 bcopy(newrr->r_data, cp, newrr->r_size); 179 cp += newrr->r_size; 180 } 181 hp->ancount = htons(0); 182 break; 183 184 #endif ALLOW_UPDATES 185 } 186 return (cp - buf); 187 } 188