xref: /csrg-svn/lib/libc/net/res_mkquery.c (revision 18548)
1 /*	res_mkquery.c	4.5	85/04/01	*/
2 
3 /*
4  * Copyright (c) 1985 Regents of the University of California
5  *	All Rights Reserved
6  */
7 
8 #include <stdio.h>
9 #include <sys/types.h>
10 #include <netinet/in.h>
11 #include <nameser.h>
12 #include <resolv.h>
13 
14 /*
15  * Form all types of queries.
16  * Returns the size of the result or -1.
17  */
18 res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
19 	int op;			/* opcode of query */
20 	char *dname;		/* domain name */
21 	int class, type;	/* class and type of query */
22 	char *data;		/* resource record data */
23 	int datalen;		/* length of data */
24 	struct rrec *newrr;	/* new rr for modify or append */
25 	char *buf;		/* buffer to put query */
26 	int buflen;		/* size of buffer */
27 {
28 	register HEADER *hp;
29 	register char *cp;
30 	register int n;
31 	char dnbuf[MAXDNAME];
32 	char *dnptrs[10], **dpp, **lastdnptr;
33 	extern char *index();
34 
35 	if (_res.options & RES_DEBUG)
36 		printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
37 	/*
38 	 * Initialize header fields.
39 	 */
40 	hp = (HEADER *) buf;
41 	hp->id = htons(++_res.id);
42 	hp->opcode = op;
43 	hp->qr = hp->aa = hp->tc = hp->ra = 0;
44 	hp->pr = (_res.options & RES_PRIMARY) != 0;
45 	hp->rd = (_res.options & RES_RECURSE) != 0;
46 	hp->rcode = NOERROR;
47 	hp->qdcount = 0;
48 	hp->ancount = 0;
49 	hp->nscount = 0;
50 	hp->arcount = 0;
51 	cp = buf + sizeof(HEADER);
52 	buflen -= sizeof(HEADER);
53 	dpp = dnptrs;
54 	*dpp++ = buf;
55 	*dpp++ = NULL;
56 	lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
57 	/*
58 	 * If the domain name contains no dots (single label), then
59 	 * append the default domain name to the one given.
60 	 */
61 	if ((_res.options & RES_DEFNAMES) && dname[0] != '\0' &&
62 	    index(dname, '.') == NULL) {
63 		if (!(_res.options & RES_INIT))
64 			res_init();
65 		if (_res.defdname[0] != '\0')
66 			dname = sprintf(dnbuf, "%s.%s", dname, _res.defdname);
67 	}
68 	/*
69 	 * perform opcode specific processing
70 	 */
71 	switch (op) {
72 	case QUERY:
73 	case CQUERYM:
74 	case CQUERYU:
75 		buflen -= QFIXEDSZ;
76 		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
77 			return (-1);
78 		cp += n;
79 		buflen -= n;
80 		putshort(type, cp);
81 		cp += sizeof(u_short);
82 		putshort(class, cp);
83 		cp += sizeof(u_short);
84 		hp->qdcount = HTONS(1);
85 		if (op == QUERY || data == NULL)
86 			break;
87 		/*
88 		 * Make an additional record for completion domain.
89 		 */
90 		buflen -= RRFIXEDSZ;
91 		if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)
92 			return (-1);
93 		cp += n;
94 		buflen -= n;
95 		putshort(T_NULL, cp);
96 		cp += sizeof(u_short);
97 		putshort(class, cp);
98 		cp += sizeof(u_short);
99 		putlong(0, cp);
100 		cp += sizeof(u_long);
101 		putshort(0, cp);
102 		cp += sizeof(u_short);
103 		hp->arcount = HTONS(1);
104 		break;
105 
106 	case IQUERY:
107 		/*
108 		 * Initialize answer section
109 		 */
110 		if (buflen < 1 + RRFIXEDSZ + datalen)
111 			return (-1);
112 		*cp++ = '\0';	/* no domain name */
113 		putshort(type, cp);
114 		cp += sizeof(u_short);
115 		putshort(class, cp);
116 		cp += sizeof(u_short);
117 		putlong(0, cp);
118 		cp += sizeof(u_long);
119 		putshort(datalen, cp);
120 		cp += sizeof(u_short);
121 		if (datalen) {
122 			bcopy(data, cp, datalen);
123 			cp += datalen;
124 		}
125 		hp->ancount = HTONS(1);
126 		break;
127 
128 #ifdef notdef
129 	case UPDATED:
130 		/*
131 		 * Put record to be added or deleted in additional section
132 		 */
133 		buflen -= RRFIXEDSZ + datalen;
134 		if ((n = dn_comp(dname, cp, buflen, NULL, NULL)) < 0)
135 			return (-1);
136 		cp += n;
137 		*((u_short *)cp) = htons(type);
138 		cp += sizeof(u_short);
139 		*((u_short *)cp) = htons(class);
140 		cp += sizeof(u_short);
141 		*((u_long *)cp) = 0;
142 		cp += sizeof(u_long);
143 		*((u_short *)cp) = htons(datalen);
144 		cp += sizeof(u_short);
145 		if (datalen) {
146 			bcopy(data, cp, datalen);
147 			cp += datalen;
148 		}
149 		break;
150 
151 	case UPDATEM:
152 		/*
153 		 * Record to be modified followed by its replacement
154 		 */
155 		buflen -= RRFIXEDSZ + datalen;
156 		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
157 			return (-1);
158 		cp += n;
159 		*((u_short *)cp) = htons(type);
160 		cp += sizeof(u_short);
161 		*((u_short *)cp) = htons(class);
162 		cp += sizeof(u_short);
163 		*((u_long *)cp) = 0;
164 		cp += sizeof(u_long);
165 		*((u_short *)cp) = htons(datalen);
166 		cp += sizeof(u_short);
167 		if (datalen) {
168 			bcopy(data, cp, datalen);
169 			cp += datalen;
170 		}
171 
172 	case UPDATEA:
173 		buflen -= RRFIXEDSZ + newrr->r_size;
174 		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
175 			return (-1);
176 		cp += n;
177 		*((u_short *)cp) = htons(newrr->r_type);
178 		cp += sizeof(u_short);
179 		*((u_short *)cp) = htons(newrr->r_type);
180 		cp += sizeof(u_short);
181 		*((u_long *)cp) = htonl(newrr->r_ttl);
182 		cp += sizeof(u_long);
183 		*((u_short *)cp) = htons(newrr->r_size);
184 		cp += sizeof(u_short);
185 		if (newrr->r_size) {
186 			bcopy(newrr->r_data, cp, newrr->r_size);
187 			cp += newrr->r_size;
188 		}
189 		break;
190 #endif
191 	}
192 	return (cp - buf);
193 }
194