summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/res_mkquery.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net/res_mkquery.c')
-rw-r--r--src/lib/libc/net/res_mkquery.c258
1 files changed, 127 insertions, 131 deletions
diff --git a/src/lib/libc/net/res_mkquery.c b/src/lib/libc/net/res_mkquery.c
index 25f025e147..5c6b273abe 100644
--- a/src/lib/libc/net/res_mkquery.c
+++ b/src/lib/libc/net/res_mkquery.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_mkquery.c,v 1.5 1995/02/25 06:20:58 cgd Exp $ */ 1/* $OpenBSD: res_mkquery.c,v 1.17 2005/08/06 20:30:04 espie Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1993
5 * -
4 * Copyright (c) 1985, 1993 6 * Copyright (c) 1985, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -12,14 +14,10 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 19 * without specific prior written permission.
22 * 20 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -53,101 +51,109 @@
53 * --Copyright-- 51 * --Copyright--
54 */ 52 */
55 53
56#if defined(LIBC_SCCS) && !defined(lint) 54#include <sys/types.h>
57#if 0
58static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: res_mkquery.c,v 4.9.1.2 1993/05/17 10:00:01 vixie Exp ";
60#else
61static char rcsid[] = "$NetBSD: res_mkquery.c,v 1.5 1995/02/25 06:20:58 cgd Exp $";
62#endif
63#endif /* LIBC_SCCS and not lint */
64
65#include <sys/param.h> 55#include <sys/param.h>
66#include <netinet/in.h> 56#include <netinet/in.h>
67#include <arpa/nameser.h> 57#include <arpa/nameser.h>
68#include <resolv.h> 58
69#include <stdio.h> 59#include <stdio.h>
60#include <netdb.h>
61#include <resolv.h>
70#include <string.h> 62#include <string.h>
71 63
64#include "thread_private.h"
65
72/* 66/*
73 * Form all types of queries. 67 * Form all types of queries.
74 * Returns the size of the result or -1. 68 * Returns the size of the result or -1.
75 */ 69 */
76res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) 70/* ARGSUSED */
77 int op; /* opcode of query */ 71int
78 const char *dname; /* domain name */ 72res_mkquery(int op,
79 int class, type; /* class and type of query */ 73 const char *dname, /* opcode of query */
80 const char *data; /* resource record data */ 74 int class, /* domain name */
81 int datalen; /* length of data */ 75 int type, /* class and type of query */
82 const char *newrr_in; /* new rr for modify or append */ 76 const u_char *data, /* resource record data */
83 char *buf; /* buffer to put query */ 77 int datalen, /* length of data */
84 int buflen; /* size of buffer */ 78 const u_char *newrr_in, /* new rr for modify or append */
79 u_char *buf, /* buffer to put query */
80 int buflen) /* size of buffer */
85{ 81{
86 register HEADER *hp; 82 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
87 register char *cp; 83 HEADER *hp;
88 register int n; 84 u_char *cp, *ep;
89 struct rrec *newrr = (struct rrec *) newrr_in; 85 int n;
90 char *dnptrs[10], **dpp, **lastdnptr; 86 u_char *dnptrs[20], **dpp, **lastdnptr;
91 87
88 if (_res_init(0) == -1) {
89 h_errno = NETDB_INTERNAL;
90 return (-1);
91 }
92#ifdef DEBUG 92#ifdef DEBUG
93 if (_res.options & RES_DEBUG) 93 if (_resp->options & RES_DEBUG)
94 printf(";; res_mkquery(%d, %s, %d, %d)\n", 94 printf(";; res_mkquery(%d, %s, %d, %d)\n",
95 op, dname, class, type); 95 op, dname, class, type);
96#endif 96#endif
97 /* 97 /*
98 * Initialize header fields. 98 * Initialize header fields.
99 *
100 * A special random number generator is used to create non predictable
101 * and non repeating ids over a long period. It also avoids reuse
102 * by switching between two distinct number cycles.
99 */ 103 */
100 if ((buf == NULL) || (buflen < sizeof(HEADER))) 104
101 return(-1); 105 if ((buf == NULL) || (buflen < HFIXEDSZ))
102 bzero(buf, sizeof(HEADER)); 106 return (-1);
107 bzero(buf, HFIXEDSZ);
103 hp = (HEADER *) buf; 108 hp = (HEADER *) buf;
104 hp->id = htons(++_res.id); 109 _resp->id = res_randomid();
110 hp->id = htons(_resp->id);
105 hp->opcode = op; 111 hp->opcode = op;
106 hp->pr = (_res.options & RES_PRIMARY) != 0; 112 hp->rd = (_resp->options & RES_RECURSE) != 0;
107 hp->rd = (_res.options & RES_RECURSE) != 0;
108 hp->rcode = NOERROR; 113 hp->rcode = NOERROR;
109 cp = buf + sizeof(HEADER); 114 cp = buf + HFIXEDSZ;
110 buflen -= sizeof(HEADER); 115 ep = buf + buflen;
111 dpp = dnptrs; 116 dpp = dnptrs;
112 *dpp++ = buf; 117 *dpp++ = buf;
113 *dpp++ = NULL; 118 *dpp++ = NULL;
114 lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 119 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
115 /* 120 /*
116 * perform opcode specific processing 121 * perform opcode specific processing
117 */ 122 */
118 switch (op) { 123 switch (op) {
119 case QUERY: 124 case QUERY: /*FALLTHROUGH*/
120 if ((buflen -= QFIXEDSZ) < 0) 125 case NS_NOTIFY_OP:
121 return(-1); 126 if (ep - cp < QFIXEDSZ)
122 if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen, 127 return (-1);
123 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 128 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
129 lastdnptr)) < 0)
124 return (-1); 130 return (-1);
125 cp += n; 131 cp += n;
126 buflen -= n; 132 __putshort(type, cp);
127 __putshort(type, (u_char *)cp); 133 cp += INT16SZ;
128 cp += sizeof(u_int16_t); 134 __putshort(class, cp);
129 __putshort(class, (u_char *)cp); 135 cp += INT16SZ;
130 cp += sizeof(u_int16_t);
131 hp->qdcount = htons(1); 136 hp->qdcount = htons(1);
132 if (op == QUERY || data == NULL) 137 if (op == QUERY || data == NULL)
133 break; 138 break;
134 /* 139 /*
135 * Make an additional record for completion domain. 140 * Make an additional record for completion domain.
136 */ 141 */
137 buflen -= RRFIXEDSZ; 142 if (ep - cp < RRFIXEDSZ)
138 if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen, 143 return (-1);
139 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 144 n = dn_comp((char *)data, cp, ep - cp - RRFIXEDSZ, dnptrs,
145 lastdnptr);
146 if (n < 0)
140 return (-1); 147 return (-1);
141 cp += n; 148 cp += n;
142 buflen -= n; 149 __putshort(T_NULL, cp);
143 __putshort(T_NULL, (u_char *)cp); 150 cp += INT16SZ;
144 cp += sizeof(u_int16_t); 151 __putshort(class, cp);
145 __putshort(class, (u_char *)cp); 152 cp += INT16SZ;
146 cp += sizeof(u_int16_t); 153 __putlong(0, cp);
147 __putlong(0, (u_char *)cp); 154 cp += INT32SZ;
148 cp += sizeof(u_int32_t); 155 __putshort(0, cp);
149 __putshort(0, (u_char *)cp); 156 cp += INT16SZ;
150 cp += sizeof(u_int16_t);
151 hp->arcount = htons(1); 157 hp->arcount = htons(1);
152 break; 158 break;
153 159
@@ -155,82 +161,72 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
155 /* 161 /*
156 * Initialize answer section 162 * Initialize answer section
157 */ 163 */
158 if (buflen < 1 + RRFIXEDSZ + datalen) 164 if (ep - cp < 1 + RRFIXEDSZ + datalen)
159 return (-1); 165 return (-1);
160 *cp++ = '\0'; /* no domain name */ 166 *cp++ = '\0'; /* no domain name */
161 __putshort(type, (u_char *)cp);
162 cp += sizeof(u_int16_t);
163 __putshort(class, (u_char *)cp);
164 cp += sizeof(u_int16_t);
165 __putlong(0, (u_char *)cp);
166 cp += sizeof(u_int32_t);
167 __putshort(datalen, (u_char *)cp);
168 cp += sizeof(u_int16_t);
169 if (datalen) {
170 bcopy(data, cp, datalen);
171 cp += datalen;
172 }
173 hp->ancount = htons(1);
174 break;
175
176#ifdef ALLOW_UPDATES
177 /*
178 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
179 * (Record to be modified is followed by its replacement in msg.)
180 */
181 case UPDATEM:
182 case UPDATEMA:
183
184 case UPDATED:
185 /*
186 * The res code for UPDATED and UPDATEDA is the same; user
187 * calls them differently: specifies data for UPDATED; server
188 * ignores data if specified for UPDATEDA.
189 */
190 case UPDATEDA:
191 buflen -= RRFIXEDSZ + datalen;
192 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
193 return (-1);
194 cp += n;
195 __putshort(type, cp); 167 __putshort(type, cp);
196 cp += sizeof(u_int16_t); 168 cp += INT16SZ;
197 __putshort(class, cp); 169 __putshort(class, cp);
198 cp += sizeof(u_int16_t); 170 cp += INT16SZ;
199 __putlong(0, cp); 171 __putlong(0, cp);
200 cp += sizeof(u_int32_t); 172 cp += INT32SZ;
201 __putshort(datalen, cp); 173 __putshort(datalen, cp);
202 cp += sizeof(u_int16_t); 174 cp += INT16SZ;
203 if (datalen) { 175 if (datalen) {
204 bcopy(data, cp, datalen); 176 bcopy(data, cp, datalen);
205 cp += datalen; 177 cp += datalen;
206 } 178 }
207 if ( (op == UPDATED) || (op == UPDATEDA) ) { 179 hp->ancount = htons(1);
208 hp->ancount = htons(0);
209 break;
210 }
211 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
212
213 case UPDATEA: /* Add new resource record */
214 buflen -= RRFIXEDSZ + datalen;
215 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
216 return (-1);
217 cp += n;
218 __putshort(newrr->r_type, cp);
219 cp += sizeof(u_int16_t);
220 __putshort(newrr->r_class, cp);
221 cp += sizeof(u_int16_t);
222 __putlong(0, cp);
223 cp += sizeof(u_int32_t);
224 __putshort(newrr->r_size, cp);
225 cp += sizeof(u_int16_t);
226 if (newrr->r_size) {
227 bcopy(newrr->r_data, cp, newrr->r_size);
228 cp += newrr->r_size;
229 }
230 hp->ancount = htons(0);
231 break; 180 break;
232 181
233#endif /* ALLOW_UPDATES */ 182 default:
183 return (-1);
234 } 184 }
235 return (cp - buf); 185 return (cp - buf);
236} 186}
187
188/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
189int
190res_opt(int n0,
191 u_char *buf, /* buffer to put query */
192 int buflen, /* size of buffer */
193 int anslen) /* answer buffer length */
194{
195 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
196 HEADER *hp;
197 u_char *cp, *ep;
198
199 hp = (HEADER *) buf;
200 cp = buf + n0;
201 ep = buf + buflen;
202
203 if (ep - cp < 1 + RRFIXEDSZ)
204 return -1;
205
206 *cp++ = 0; /* "." */
207
208 __putshort(T_OPT, cp); /* TYPE */
209 cp += INT16SZ;
210 if (anslen > 0xffff)
211 anslen = 0xffff; /* limit to 16bit value */
212 __putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */
213 cp += INT16SZ;
214 *cp++ = NOERROR; /* extended RCODE */
215 *cp++ = 0; /* EDNS version */
216 if (_resp->options & RES_USE_DNSSEC) {
217#ifdef DEBUG
218 if (_resp->options & RES_DEBUG)
219 printf(";; res_opt()... ENDS0 DNSSEC OK\n");
220#endif /* DEBUG */
221 __putshort(DNS_MESSAGEEXTFLAG_DO, cp); /* EDNS Z field */
222 cp += INT16SZ;
223 } else {
224 __putshort(0, cp); /* EDNS Z field */
225 cp += INT16SZ;
226 }
227 __putshort(0, cp); /* RDLEN */
228 cp += INT16SZ;
229 hp->arcount = htons(ntohs(hp->arcount) + 1);
230
231 return cp - buf;
232}