xref: /original-bsd/lib/libc/net/res_mkquery.c (revision 42f60e33)
1 /*-
2  * Copyright (c) 1985, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  * -
7  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies, and that
12  * the name of Digital Equipment Corporation not be used in advertising or
13  * publicity pertaining to distribution of the document or software without
14  * specific, written prior permission.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
17  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
19  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
20  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
21  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
22  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23  * SOFTWARE.
24  * -
25  * --Copyright--
26  */
27 
28 #if defined(LIBC_SCCS) && !defined(lint)
29 static char sccsid[] = "@(#)res_mkquery.c	8.1 (Berkeley) 06/04/93";
30 static char rcsid[] = "$Id: res_mkquery.c,v 4.9.1.2 1993/05/17 10:00:01 vixie Exp $";
31 #endif /* LIBC_SCCS and not lint */
32 
33 #include <sys/param.h>
34 #include <netinet/in.h>
35 #include <arpa/nameser.h>
36 #include <resolv.h>
37 #include <stdio.h>
38 #include <string.h>
39 
40 /*
41  * Form all types of queries.
42  * Returns the size of the result or -1.
43  */
44 res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
45 	int op;			/* opcode of query */
46 	const char *dname;		/* domain name */
47 	int class, type;	/* class and type of query */
48 	const char *data;		/* resource record data */
49 	int datalen;		/* length of data */
50 	const char *newrr_in;	/* new rr for modify or append */
51 	char *buf;		/* buffer to put query */
52 	int buflen;		/* size of buffer */
53 {
54 	register HEADER *hp;
55 	register char *cp;
56 	register int n;
57 	struct rrec *newrr = (struct rrec *) newrr_in;
58 	char *dnptrs[10], **dpp, **lastdnptr;
59 
60 #ifdef DEBUG
61 	if (_res.options & RES_DEBUG)
62 		printf(";; res_mkquery(%d, %s, %d, %d)\n",
63 		       op, dname, class, type);
64 #endif
65 	/*
66 	 * Initialize header fields.
67 	 */
68 	if ((buf == NULL) || (buflen < sizeof(HEADER)))
69 		return(-1);
70 	bzero(buf, sizeof(HEADER));
71 	hp = (HEADER *) buf;
72 	hp->id = htons(++_res.id);
73 	hp->opcode = op;
74 	hp->pr = (_res.options & RES_PRIMARY) != 0;
75 	hp->rd = (_res.options & RES_RECURSE) != 0;
76 	hp->rcode = NOERROR;
77 	cp = buf + sizeof(HEADER);
78 	buflen -= sizeof(HEADER);
79 	dpp = dnptrs;
80 	*dpp++ = buf;
81 	*dpp++ = NULL;
82 	lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
83 	/*
84 	 * perform opcode specific processing
85 	 */
86 	switch (op) {
87 	case QUERY:
88 		if ((buflen -= QFIXEDSZ) < 0)
89 			return(-1);
90 		if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen,
91 		    (u_char **)dnptrs, (u_char **)lastdnptr)) < 0)
92 			return (-1);
93 		cp += n;
94 		buflen -= n;
95 		__putshort(type, (u_char *)cp);
96 		cp += sizeof(u_int16_t);
97 		__putshort(class, (u_char *)cp);
98 		cp += sizeof(u_int16_t);
99 		hp->qdcount = htons(1);
100 		if (op == QUERY || data == NULL)
101 			break;
102 		/*
103 		 * Make an additional record for completion domain.
104 		 */
105 		buflen -= RRFIXEDSZ;
106 		if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen,
107 		    (u_char **)dnptrs, (u_char **)lastdnptr)) < 0)
108 			return (-1);
109 		cp += n;
110 		buflen -= n;
111 		__putshort(T_NULL, (u_char *)cp);
112 		cp += sizeof(u_int16_t);
113 		__putshort(class, (u_char *)cp);
114 		cp += sizeof(u_int16_t);
115 		__putlong(0, (u_char *)cp);
116 		cp += sizeof(u_int32_t);
117 		__putshort(0, (u_char *)cp);
118 		cp += sizeof(u_int16_t);
119 		hp->arcount = htons(1);
120 		break;
121 
122 	case IQUERY:
123 		/*
124 		 * Initialize answer section
125 		 */
126 		if (buflen < 1 + RRFIXEDSZ + datalen)
127 			return (-1);
128 		*cp++ = '\0';	/* no domain name */
129 		__putshort(type, (u_char *)cp);
130 		cp += sizeof(u_int16_t);
131 		__putshort(class, (u_char *)cp);
132 		cp += sizeof(u_int16_t);
133 		__putlong(0, (u_char *)cp);
134 		cp += sizeof(u_int32_t);
135 		__putshort(datalen, (u_char *)cp);
136 		cp += sizeof(u_int16_t);
137 		if (datalen) {
138 			bcopy(data, cp, datalen);
139 			cp += datalen;
140 		}
141 		hp->ancount = htons(1);
142 		break;
143 
144 #ifdef ALLOW_UPDATES
145 	/*
146 	 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
147 	 * (Record to be modified is followed by its replacement in msg.)
148 	 */
149 	case UPDATEM:
150 	case UPDATEMA:
151 
152 	case UPDATED:
153 		/*
154 		 * The res code for UPDATED and UPDATEDA is the same; user
155 		 * calls them differently: specifies data for UPDATED; server
156 		 * ignores data if specified for UPDATEDA.
157 		 */
158 	case UPDATEDA:
159 		buflen -= RRFIXEDSZ + datalen;
160 		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
161 			return (-1);
162 		cp += n;
163 		__putshort(type, cp);
164                 cp += sizeof(u_int16_t);
165                 __putshort(class, cp);
166                 cp += sizeof(u_int16_t);
167 		__putlong(0, cp);
168 		cp += sizeof(u_int32_t);
169 		__putshort(datalen, cp);
170                 cp += sizeof(u_int16_t);
171 		if (datalen) {
172 			bcopy(data, cp, datalen);
173 			cp += datalen;
174 		}
175 		if ( (op == UPDATED) || (op == UPDATEDA) ) {
176 			hp->ancount = htons(0);
177 			break;
178 		}
179 		/* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
180 
181 	case UPDATEA:	/* Add new resource record */
182 		buflen -= RRFIXEDSZ + datalen;
183 		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
184 			return (-1);
185 		cp += n;
186 		__putshort(newrr->r_type, cp);
187                 cp += sizeof(u_int16_t);
188                 __putshort(newrr->r_class, cp);
189                 cp += sizeof(u_int16_t);
190 		__putlong(0, cp);
191 		cp += sizeof(u_int32_t);
192 		__putshort(newrr->r_size, cp);
193                 cp += sizeof(u_int16_t);
194 		if (newrr->r_size) {
195 			bcopy(newrr->r_data, cp, newrr->r_size);
196 			cp += newrr->r_size;
197 		}
198 		hp->ancount = htons(0);
199 		break;
200 
201 #endif /* ALLOW_UPDATES */
202 	}
203 	return (cp - buf);
204 }
205