|
|
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: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #if defined(LIBC_SCCS) && !defined(lint)
21: static char sccsid[] = "@(#)res_mkquery.c 6.12 (Berkeley) 6/1/90";
22: #endif /* LIBC_SCCS and not lint */
23:
24: #include <stdio.h>
25: #include <sys/types.h>
26: #include <netinet/in.h>
27: #include <arpa/nameser.h>
28: #include <resolv.h>
29:
30: /*
31: * Form all types of queries.
32: * Returns the size of the result or -1.
33: */
34: res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
35: int op; /* opcode of query */
36: char *dname; /* domain name */
37: int class, type; /* class and type of query */
38: char *data; /* resource record data */
39: int datalen; /* length of data */
40: struct rrec *newrr; /* new rr for modify or append */
41: char *buf; /* buffer to put query */
42: int buflen; /* size of buffer */
43: {
44: register HEADER *hp;
45: register char *cp;
46: register int n;
47: char *dnptrs[10], **dpp, **lastdnptr;
48: extern char *index();
49:
50: #ifdef DEBUG
51: if (_res.options & RES_DEBUG)
52: printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
53: #endif DEBUG
54: /*
55: * Initialize header fields.
56: */
57: if ((buf == NULL) || (buflen < sizeof(HEADER)))
58: return(-1);
59: bzero(buf, sizeof(HEADER));
60: hp = (HEADER *) buf;
61: hp->id = htons(++_res.id);
62: hp->opcode = op;
63: hp->pr = (_res.options & RES_PRIMARY) != 0;
64: hp->rd = (_res.options & RES_RECURSE) != 0;
65: hp->rcode = NOERROR;
66: cp = buf + sizeof(HEADER);
67: buflen -= sizeof(HEADER);
68: dpp = dnptrs;
69: *dpp++ = buf;
70: *dpp++ = NULL;
71: lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
72: /*
73: * perform opcode specific processing
74: */
75: switch (op) {
76: case QUERY:
77: if ((buflen -= QFIXEDSZ) < 0)
78: return(-1);
79: if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
80: return (-1);
81: cp += n;
82: buflen -= n;
83: putshort(type, cp);
84: cp += sizeof(u_short);
85: putshort(class, cp);
86: cp += sizeof(u_short);
87: hp->qdcount = htons(1);
88: if (op == QUERY || data == NULL)
89: break;
90: /*
91: * Make an additional record for completion domain.
92: */
93: buflen -= RRFIXEDSZ;
94: if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)
95: return (-1);
96: cp += n;
97: buflen -= n;
98: putshort(T_NULL, cp);
99: cp += sizeof(u_short);
100: putshort(class, cp);
101: cp += sizeof(u_short);
102: putlong(0, cp);
103: cp += sizeof(u_long);
104: putshort(0, cp);
105: cp += sizeof(u_short);
106: hp->arcount = htons(1);
107: break;
108:
109: case IQUERY:
110: /*
111: * Initialize answer section
112: */
113: if (buflen < 1 + RRFIXEDSZ + datalen)
114: return (-1);
115: *cp++ = '\0'; /* no domain name */
116: putshort(type, cp);
117: cp += sizeof(u_short);
118: putshort(class, cp);
119: cp += sizeof(u_short);
120: putlong(0, cp);
121: cp += sizeof(u_long);
122: putshort(datalen, cp);
123: cp += sizeof(u_short);
124: if (datalen) {
125: bcopy(data, cp, datalen);
126: cp += datalen;
127: }
128: hp->ancount = htons(1);
129: break;
130:
131: #ifdef ALLOW_UPDATES
132: /*
133: * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
134: * (Record to be modified is followed by its replacement in msg.)
135: */
136: case UPDATEM:
137: case UPDATEMA:
138:
139: case UPDATED:
140: /*
141: * The res code for UPDATED and UPDATEDA is the same; user
142: * calls them differently: specifies data for UPDATED; server
143: * ignores data if specified for UPDATEDA.
144: */
145: case UPDATEDA:
146: buflen -= RRFIXEDSZ + datalen;
147: if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
148: return (-1);
149: cp += n;
150: putshort(type, cp);
151: cp += sizeof(u_short);
152: putshort(class, cp);
153: cp += sizeof(u_short);
154: putlong(0, cp);
155: cp += sizeof(u_long);
156: putshort(datalen, cp);
157: cp += sizeof(u_short);
158: if (datalen) {
159: bcopy(data, cp, datalen);
160: cp += datalen;
161: }
162: if ( (op == UPDATED) || (op == UPDATEDA) ) {
163: hp->ancount = htons(0);
164: break;
165: }
166: /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
167:
168: case UPDATEA: /* Add new resource record */
169: buflen -= RRFIXEDSZ + datalen;
170: if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
171: return (-1);
172: cp += n;
173: putshort(newrr->r_type, cp);
174: cp += sizeof(u_short);
175: putshort(newrr->r_class, cp);
176: cp += sizeof(u_short);
177: putlong(0, cp);
178: cp += sizeof(u_long);
179: putshort(newrr->r_size, cp);
180: cp += sizeof(u_short);
181: if (newrr->r_size) {
182: bcopy(newrr->r_data, cp, newrr->r_size);
183: cp += newrr->r_size;
184: }
185: hp->ancount = htons(0);
186: break;
187:
188: #endif ALLOW_UPDATES
189: }
190: return (cp - buf);
191: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.