|
|
1.1 root 1: /*
2: * Copyright (c) 1985 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that this notice is preserved and that due credit is given
7: * to the University of California at Berkeley. The name of the University
8: * may not be used to endorse or promote products derived from this
9: * software without specific prior written permission. This software
10: * is provided ``as is'' without express or implied warranty.
11: */
12:
13: #if defined(LIBC_SCCS) && !defined(lint)
14: static char sccsid[] = "@(#)res_mkquery.c 6.7 (Berkeley) 3/7/88";
15: #endif /* LIBC_SCCS and not lint */
16:
17: #include <stdio.h>
18: #include <sys/types.h>
19: #include <netinet/in.h>
20: #include <arpa/nameser.h>
21: #include <resolv.h>
22:
23: /*
24: * Form all types of queries.
25: * Returns the size of the result or -1.
26: */
27: res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
28: int op; /* opcode of query */
29: char *dname; /* domain name */
30: int class, type; /* class and type of query */
31: char *data; /* resource record data */
32: int datalen; /* length of data */
33: struct rrec *newrr; /* new rr for modify or append */
34: char *buf; /* buffer to put query */
35: int buflen; /* size of buffer */
36: {
37: register HEADER *hp;
38: register char *cp;
39: register int n;
40: char dnbuf[MAXDNAME];
41: char *dnptrs[10], **dpp, **lastdnptr;
42: extern char *index();
43:
44: #ifdef DEBUG
45: if (_res.options & RES_DEBUG)
46: printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
47: #endif DEBUG
48: /*
49: * Initialize header fields.
50: */
51: hp = (HEADER *) buf;
52: hp->id = htons(++_res.id);
53: hp->opcode = op;
54: hp->qr = hp->aa = hp->tc = hp->ra = 0;
55: hp->pr = (_res.options & RES_PRIMARY) != 0;
56: hp->rd = (_res.options & RES_RECURSE) != 0;
57: hp->rcode = NOERROR;
58: hp->qdcount = 0;
59: hp->ancount = 0;
60: hp->nscount = 0;
61: hp->arcount = 0;
62: cp = buf + sizeof(HEADER);
63: buflen -= sizeof(HEADER);
64: dpp = dnptrs;
65: *dpp++ = buf;
66: *dpp++ = NULL;
67: lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
68: /*
69: * If the domain name contains no dots (single label), then
70: * append the default domain name to the one given.
71: */
72: if ((_res.options & RES_DEFNAMES) && dname != 0 && dname[0] != '\0' &&
73: index(dname, '.') == NULL) {
74: if (!(_res.options & RES_INIT))
75: if (res_init() == -1)
76: return(-1);
77: if (_res.defdname[0] != '\0') {
78: (void)sprintf(dnbuf, "%s.%s", dname, _res.defdname);
79: dname = dnbuf;
80: }
81: }
82: /*
83: * perform opcode specific processing
84: */
85: switch (op) {
86: case QUERY:
87: buflen -= QFIXEDSZ;
88: if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
89: return (-1);
90: cp += n;
91: buflen -= n;
92: putshort(type, cp);
93: cp += sizeof(u_short);
94: putshort(class, cp);
95: cp += sizeof(u_short);
96: hp->qdcount = htons(1);
97: if (op == QUERY || data == NULL)
98: break;
99: /*
100: * Make an additional record for completion domain.
101: */
102: buflen -= RRFIXEDSZ;
103: if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)
104: return (-1);
105: cp += n;
106: buflen -= n;
107: putshort(T_NULL, cp);
108: cp += sizeof(u_short);
109: putshort(class, cp);
110: cp += sizeof(u_short);
111: putlong(0, cp);
112: cp += sizeof(u_long);
113: putshort(0, cp);
114: cp += sizeof(u_short);
115: hp->arcount = htons(1);
116: break;
117:
118: case IQUERY:
119: /*
120: * Initialize answer section
121: */
122: if (buflen < 1 + RRFIXEDSZ + datalen)
123: return (-1);
124: *cp++ = '\0'; /* no domain name */
125: putshort(type, cp);
126: cp += sizeof(u_short);
127: putshort(class, cp);
128: cp += sizeof(u_short);
129: putlong(0, cp);
130: cp += sizeof(u_long);
131: putshort(datalen, cp);
132: cp += sizeof(u_short);
133: if (datalen) {
134: bcopy(data, cp, datalen);
135: cp += datalen;
136: }
137: hp->ancount = htons(1);
138: break;
139:
140: #ifdef ALLOW_UPDATES
141: /*
142: * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
143: * (Record to be modified is followed by its replacement in msg.)
144: */
145: case UPDATEM:
146: case UPDATEMA:
147:
148: case UPDATED:
149: /*
150: * The res code for UPDATED and UPDATEDA is the same; user
151: * calls them differently: specifies data for UPDATED; server
152: * ignores data if specified for UPDATEDA.
153: */
154: case UPDATEDA:
155: buflen -= RRFIXEDSZ + datalen;
156: if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
157: return (-1);
158: cp += n;
159: putshort(type, cp);
160: cp += sizeof(u_short);
161: putshort(class, cp);
162: cp += sizeof(u_short);
163: putlong(0, cp);
164: cp += sizeof(u_long);
165: putshort(datalen, cp);
166: cp += sizeof(u_short);
167: if (datalen) {
168: bcopy(data, cp, datalen);
169: cp += datalen;
170: }
171: if ( (op == UPDATED) || (op == UPDATEDA) ) {
172: hp->ancount = htons(0);
173: break;
174: }
175: /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
176:
177: case UPDATEA: /* Add new resource record */
178: buflen -= RRFIXEDSZ + datalen;
179: if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
180: return (-1);
181: cp += n;
182: putshort(newrr->r_type, cp);
183: cp += sizeof(u_short);
184: putshort(newrr->r_class, cp);
185: cp += sizeof(u_short);
186: putlong(0, cp);
187: cp += sizeof(u_long);
188: putshort(newrr->r_size, cp);
189: cp += sizeof(u_short);
190: if (newrr->r_size) {
191: bcopy(newrr->r_data, cp, newrr->r_size);
192: cp += newrr->r_size;
193: }
194: hp->ancount = htons(0);
195: break;
196:
197: #endif ALLOW_UPDATES
198: }
199: return (cp - buf);
200: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.