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