xref: /original-bsd/lib/libc/net/res_mkquery.c (revision 50dd0bba)
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