INADDR_NONE, not -1; bug report 4.3BSD/lib/22
[unix-history] / usr / src / lib / libc / net / res_mkquery.c
CommitLineData
b423e985 1/*
8ea4199d
DF
2 * Copyright (c) 1985 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
b423e985 5 */
5e95d9b7 6
2ce81398 7#if defined(LIBC_SCCS) && !defined(lint)
70fe6623 8static char sccsid[] = "@(#)res_mkquery.c 6.5 (Berkeley) %G%";
2ce81398 9#endif LIBC_SCCS and not lint
8ea4199d 10
5e95d9b7
RC
11#include <stdio.h>
12#include <sys/types.h>
13#include <netinet/in.h>
61e99f72 14#include <arpa/nameser.h>
f94b2f50 15#include <resolv.h>
5e95d9b7 16
71f8df6d
KD
17extern char *sprintf();
18
5e95d9b7
RC
19/*
20 * Form all types of queries.
21 * Returns the size of the result or -1.
22 */
31f0ead0 23res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
5e95d9b7
RC
24 int op; /* opcode of query */
25 char *dname; /* domain name */
26 int class, type; /* class and type of query */
27 char *data; /* resource record data */
28 int datalen; /* length of data */
29 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 dnbuf[MAXDNAME];
37 char *dnptrs[10], **dpp, **lastdnptr;
11e57e73 38 extern char *index();
5e95d9b7 39
ae94a224 40#ifdef DEBUG
5e95d9b7 41 if (_res.options & RES_DEBUG)
31f0ead0 42 printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
2d8db2bc 43#endif DEBUG
5e95d9b7
RC
44 /*
45 * Initialize header fields.
46 */
47 hp = (HEADER *) buf;
48 hp->id = htons(++_res.id);
49 hp->opcode = op;
50 hp->qr = hp->aa = hp->tc = hp->ra = 0;
51 hp->pr = (_res.options & RES_PRIMARY) != 0;
52 hp->rd = (_res.options & RES_RECURSE) != 0;
53 hp->rcode = NOERROR;
54 hp->qdcount = 0;
55 hp->ancount = 0;
56 hp->nscount = 0;
57 hp->arcount = 0;
58 cp = buf + sizeof(HEADER);
59 buflen -= sizeof(HEADER);
60 dpp = dnptrs;
61 *dpp++ = buf;
62 *dpp++ = NULL;
36534519 63 lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
5e95d9b7 64 /*
11e57e73 65 * If the domain name contains no dots (single label), then
5e95d9b7
RC
66 * append the default domain name to the one given.
67 */
2d8db2bc 68 if ((_res.options & RES_DEFNAMES) && dname != 0 && dname[0] != '\0' &&
11e57e73 69 index(dname, '.') == NULL) {
5e95d9b7 70 if (!(_res.options & RES_INIT))
ae94a224
JB
71 if (res_init() == -1)
72 return(-1);
5e95d9b7
RC
73 if (_res.defdname[0] != '\0')
74 dname = sprintf(dnbuf, "%s.%s", dname, _res.defdname);
75 }
76 /*
77 * perform opcode specific processing
78 */
79 switch (op) {
80 case QUERY:
5e95d9b7
RC
81 buflen -= QFIXEDSZ;
82 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
83 return (-1);
84 cp += n;
85 buflen -= n;
11e57e73 86 putshort(type, cp);
5e95d9b7 87 cp += sizeof(u_short);
11e57e73 88 putshort(class, cp);
5e95d9b7 89 cp += sizeof(u_short);
a766fb4a 90 hp->qdcount = htons(1);
5e95d9b7
RC
91 if (op == QUERY || data == NULL)
92 break;
93 /*
94 * Make an additional record for completion domain.
95 */
11e57e73 96 buflen -= RRFIXEDSZ;
5e95d9b7
RC
97 if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)
98 return (-1);
99 cp += n;
100 buflen -= n;
11e57e73 101 putshort(T_NULL, cp);
5e95d9b7 102 cp += sizeof(u_short);
11e57e73 103 putshort(class, cp);
5e95d9b7 104 cp += sizeof(u_short);
11e57e73 105 putlong(0, cp);
5e95d9b7 106 cp += sizeof(u_long);
11e57e73 107 putshort(0, cp);
5e95d9b7 108 cp += sizeof(u_short);
a766fb4a 109 hp->arcount = htons(1);
5e95d9b7
RC
110 break;
111
112 case IQUERY:
113 /*
114 * Initialize answer section
115 */
116 if (buflen < 1 + RRFIXEDSZ + datalen)
117 return (-1);
118 *cp++ = '\0'; /* no domain name */
11e57e73 119 putshort(type, cp);
5e95d9b7 120 cp += sizeof(u_short);
11e57e73 121 putshort(class, cp);
5e95d9b7 122 cp += sizeof(u_short);
11e57e73 123 putlong(0, cp);
5e95d9b7 124 cp += sizeof(u_long);
11e57e73 125 putshort(datalen, cp);
5e95d9b7
RC
126 cp += sizeof(u_short);
127 if (datalen) {
128 bcopy(data, cp, datalen);
129 cp += datalen;
130 }
a766fb4a 131 hp->ancount = htons(1);
5e95d9b7
RC
132 break;
133
3bf25746
KD
134#ifdef ALLOW_UPDATES
135 /*
136 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
137 * (Record to be modified is followed by its replacement in msg.)
138 */
5e95d9b7 139 case UPDATEM:
3bf25746
KD
140 case UPDATEMA:
141
142 case UPDATED:
5e95d9b7 143 /*
3bf25746
KD
144 * The res code for UPDATED and UPDATEDA is the same; user
145 * calls them differently: specifies data for UPDATED; server
146 * ignores data if specified for UPDATEDA.
5e95d9b7 147 */
3bf25746 148 case UPDATEDA:
5e95d9b7
RC
149 buflen -= RRFIXEDSZ + datalen;
150 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
151 return (-1);
152 cp += n;
3bf25746
KD
153 putshort(type, cp);
154 cp += sizeof(u_short);
155 putshort(class, cp);
156 cp += sizeof(u_short);
157 putlong(0, cp);
5e95d9b7 158 cp += sizeof(u_long);
3bf25746
KD
159 putshort(datalen, cp);
160 cp += sizeof(u_short);
5e95d9b7
RC
161 if (datalen) {
162 bcopy(data, cp, datalen);
163 cp += datalen;
164 }
3bf25746
KD
165 if ( (op == UPDATED) || (op == UPDATEDA) ) {
166 hp->ancount = htons(0);
167 break;
168 }
169 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
5e95d9b7 170
3bf25746
KD
171 case UPDATEA: /* Add new resource record */
172 buflen -= RRFIXEDSZ + datalen;
5e95d9b7
RC
173 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
174 return (-1);
175 cp += n;
3bf25746
KD
176 putshort(newrr->r_type, cp);
177 cp += sizeof(u_short);
178 putshort(newrr->r_class, cp);
179 cp += sizeof(u_short);
180 putlong(0, cp);
5e95d9b7 181 cp += sizeof(u_long);
3bf25746
KD
182 putshort(newrr->r_size, cp);
183 cp += sizeof(u_short);
5e95d9b7
RC
184 if (newrr->r_size) {
185 bcopy(newrr->r_data, cp, newrr->r_size);
186 cp += newrr->r_size;
187 }
3bf25746 188 hp->ancount = htons(0);
5e95d9b7 189 break;
3bf25746
KD
190
191#endif ALLOW_UPDATES
5e95d9b7
RC
192 }
193 return (cp - buf);
194}