xref: /original-bsd/lib/libc/net/res_mkquery.c (revision 0a33e010)
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.12 (Berkeley) 06/01/90";
10 #endif /* LIBC_SCCS and not lint */
11 
12 #include <stdio.h>
13 #include <sys/types.h>
14 #include <netinet/in.h>
15 #include <arpa/nameser.h>
16 #include <resolv.h>
17 
18 /*
19  * Form all types of queries.
20  * Returns the size of the result or -1.
21  */
22 res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
23 	int op;			/* opcode of query */
24 	char *dname;		/* domain name */
25 	int class, type;	/* class and type of query */
26 	char *data;		/* resource record data */
27 	int datalen;		/* length of data */
28 	struct rrec *newrr;	/* new rr for modify or append */
29 	char *buf;		/* buffer to put query */
30 	int buflen;		/* size of buffer */
31 {
32 	register HEADER *hp;
33 	register char *cp;
34 	register int n;
35 	char *dnptrs[10], **dpp, **lastdnptr;
36 	extern char *index();
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(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
68 			return (-1);
69 		cp += n;
70 		buflen -= n;
71 		putshort(type, cp);
72 		cp += sizeof(u_short);
73 		putshort(class, cp);
74 		cp += sizeof(u_short);
75 		hp->qdcount = htons(1);
76 		if (op == QUERY || data == NULL)
77 			break;
78 		/*
79 		 * Make an additional record for completion domain.
80 		 */
81 		buflen -= RRFIXEDSZ;
82 		if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)
83 			return (-1);
84 		cp += n;
85 		buflen -= n;
86 		putshort(T_NULL, cp);
87 		cp += sizeof(u_short);
88 		putshort(class, cp);
89 		cp += sizeof(u_short);
90 		putlong(0, cp);
91 		cp += sizeof(u_long);
92 		putshort(0, cp);
93 		cp += sizeof(u_short);
94 		hp->arcount = htons(1);
95 		break;
96 
97 	case IQUERY:
98 		/*
99 		 * Initialize answer section
100 		 */
101 		if (buflen < 1 + RRFIXEDSZ + datalen)
102 			return (-1);
103 		*cp++ = '\0';	/* no domain name */
104 		putshort(type, cp);
105 		cp += sizeof(u_short);
106 		putshort(class, cp);
107 		cp += sizeof(u_short);
108 		putlong(0, cp);
109 		cp += sizeof(u_long);
110 		putshort(datalen, cp);
111 		cp += sizeof(u_short);
112 		if (datalen) {
113 			bcopy(data, cp, datalen);
114 			cp += datalen;
115 		}
116 		hp->ancount = htons(1);
117 		break;
118 
119 #ifdef ALLOW_UPDATES
120 	/*
121 	 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
122 	 * (Record to be modified is followed by its replacement in msg.)
123 	 */
124 	case UPDATEM:
125 	case UPDATEMA:
126 
127 	case UPDATED:
128 		/*
129 		 * The res code for UPDATED and UPDATEDA is the same; user
130 		 * calls them differently: specifies data for UPDATED; server
131 		 * ignores data if specified for UPDATEDA.
132 		 */
133 	case UPDATEDA:
134 		buflen -= RRFIXEDSZ + datalen;
135 		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
136 			return (-1);
137 		cp += n;
138 		putshort(type, cp);
139                 cp += sizeof(u_short);
140                 putshort(class, cp);
141                 cp += sizeof(u_short);
142 		putlong(0, cp);
143 		cp += sizeof(u_long);
144 		putshort(datalen, cp);
145                 cp += sizeof(u_short);
146 		if (datalen) {
147 			bcopy(data, cp, datalen);
148 			cp += datalen;
149 		}
150 		if ( (op == UPDATED) || (op == UPDATEDA) ) {
151 			hp->ancount = htons(0);
152 			break;
153 		}
154 		/* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
155 
156 	case UPDATEA:	/* Add new resource record */
157 		buflen -= RRFIXEDSZ + datalen;
158 		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
159 			return (-1);
160 		cp += n;
161 		putshort(newrr->r_type, cp);
162                 cp += sizeof(u_short);
163                 putshort(newrr->r_class, cp);
164                 cp += sizeof(u_short);
165 		putlong(0, cp);
166 		cp += sizeof(u_long);
167 		putshort(newrr->r_size, cp);
168                 cp += sizeof(u_short);
169 		if (newrr->r_size) {
170 			bcopy(newrr->r_data, cp, newrr->r_size);
171 			cp += newrr->r_size;
172 		}
173 		hp->ancount = htons(0);
174 		break;
175 
176 #endif ALLOW_UPDATES
177 	}
178 	return (cp - buf);
179 }
180