Line data Source code
1 : /*
2 : Linux DNS client library implementation
3 : Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
4 : Copyright (C) 2006 Gerald Carter <jerry@samba.org>
5 :
6 : ** NOTE! The following LGPL license applies to the libaddns
7 : ** library. This does NOT imply that all of Samba is released
8 : ** under the LGPL
9 :
10 : This library is free software; you can redistribute it and/or
11 : modify it under the terms of the GNU Lesser General Public
12 : License as published by the Free Software Foundation; either
13 : version 2.1 of the License, or (at your option) any later version.
14 :
15 : This library is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 : Lesser General Public License for more details.
19 :
20 : You should have received a copy of the GNU Lesser General Public
21 : License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "dns.h"
25 : #include "lib/util/genrand.h"
26 :
27 35 : DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name,
28 : uint16_t q_type, uint16_t q_class,
29 : struct dns_request **preq )
30 : {
31 35 : struct dns_request *req = NULL;
32 35 : struct dns_question *q = NULL;
33 : DNS_ERROR err;
34 :
35 53 : if (!(req = talloc_zero(mem_ctx, struct dns_request)) ||
36 53 : !(req->questions = talloc_array(req, struct dns_question *, 1)) ||
37 35 : !(req->questions[0] = talloc(req->questions,
38 : struct dns_question))) {
39 0 : TALLOC_FREE(req);
40 0 : return ERROR_DNS_NO_MEMORY;
41 : }
42 :
43 35 : generate_random_buffer((uint8_t *)&req->id, sizeof(req->id));
44 :
45 35 : req->num_questions = 1;
46 35 : q = req->questions[0];
47 :
48 35 : err = dns_domain_name_from_string(q, name, &q->name);
49 35 : if (!ERR_DNS_IS_OK(err)) {
50 0 : TALLOC_FREE(req);
51 0 : return err;
52 : }
53 :
54 35 : q->q_type = q_type;
55 35 : q->q_class = q_class;
56 :
57 35 : *preq = req;
58 35 : return ERROR_DNS_SUCCESS;
59 : }
60 :
61 103 : DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
62 : struct dns_update_request **preq )
63 : {
64 103 : struct dns_update_request *req = NULL;
65 103 : struct dns_zone *z = NULL;
66 : DNS_ERROR err;
67 :
68 155 : if (!(req = talloc_zero(mem_ctx, struct dns_update_request)) ||
69 155 : !(req->zones = talloc_array(req, struct dns_zone *, 1)) ||
70 103 : !(req->zones[0] = talloc(req->zones, struct dns_zone))) {
71 0 : TALLOC_FREE(req);
72 0 : return ERROR_DNS_NO_MEMORY;
73 : }
74 :
75 103 : req->id = random();
76 103 : req->flags = 0x2800; /* Dynamic update */
77 :
78 103 : req->num_zones = 1;
79 103 : z = req->zones[0];
80 :
81 103 : err = dns_domain_name_from_string(z, name, &z->name);
82 103 : if (!ERR_DNS_IS_OK(err)) {
83 0 : TALLOC_FREE(req);
84 0 : return err;
85 : }
86 :
87 103 : z->z_type = QTYPE_SOA;
88 103 : z->z_class = DNS_CLASS_IN;
89 :
90 103 : *preq = req;
91 103 : return ERROR_DNS_SUCCESS;
92 : }
93 :
94 401 : DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name,
95 : uint16_t type, uint16_t r_class, uint32_t ttl,
96 : uint16_t data_length, uint8_t *data,
97 : struct dns_rrec **prec)
98 : {
99 401 : struct dns_rrec *rec = NULL;
100 : DNS_ERROR err;
101 :
102 401 : if (!(rec = talloc(mem_ctx, struct dns_rrec))) {
103 0 : return ERROR_DNS_NO_MEMORY;
104 : }
105 :
106 401 : err = dns_domain_name_from_string(rec, name, &rec->name);
107 401 : if (!(ERR_DNS_IS_OK(err))) {
108 0 : TALLOC_FREE(rec);
109 0 : return err;
110 : }
111 :
112 401 : rec->type = type;
113 401 : rec->r_class = r_class;
114 401 : rec->ttl = ttl;
115 401 : rec->data_length = data_length;
116 401 : rec->data = talloc_move(rec, &data);
117 :
118 401 : *prec = rec;
119 401 : return ERROR_DNS_SUCCESS;
120 : }
121 :
122 91 : DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
123 : uint32_t ttl, const struct sockaddr_storage *pss,
124 : struct dns_rrec **prec)
125 : {
126 : uint8_t *data;
127 : DNS_ERROR err;
128 : struct in_addr ip;
129 :
130 91 : if (pss->ss_family != AF_INET) {
131 0 : return ERROR_DNS_INVALID_PARAMETER;
132 : }
133 :
134 91 : ip = ((const struct sockaddr_in *)pss)->sin_addr;
135 91 : if (!(data = (uint8_t *)talloc_memdup(mem_ctx, (const void *)&ip.s_addr,
136 : sizeof(ip.s_addr)))) {
137 0 : return ERROR_DNS_NO_MEMORY;
138 : }
139 :
140 91 : err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
141 : sizeof(ip.s_addr), data, prec);
142 :
143 91 : if (!ERR_DNS_IS_OK(err)) {
144 0 : TALLOC_FREE(data);
145 : }
146 :
147 91 : return err;
148 : }
149 :
150 72 : DNS_ERROR dns_create_aaaa_record(TALLOC_CTX *mem_ctx, const char *host,
151 : uint32_t ttl, const struct sockaddr_storage *pss,
152 : struct dns_rrec **prec)
153 : {
154 : #ifdef HAVE_IPV6
155 : uint8_t *data;
156 : DNS_ERROR err;
157 : struct in6_addr ip6;
158 :
159 72 : if (pss->ss_family != AF_INET6) {
160 0 : return ERROR_DNS_INVALID_PARAMETER;
161 : }
162 :
163 72 : ip6 = ((const struct sockaddr_in6 *)pss)->sin6_addr;
164 72 : if (!(data = (uint8_t *)talloc_memdup(mem_ctx, (const void *)&ip6.s6_addr,
165 : sizeof(ip6.s6_addr)))) {
166 0 : return ERROR_DNS_NO_MEMORY;
167 : }
168 :
169 72 : err = dns_create_rrec(mem_ctx, host, QTYPE_AAAA, DNS_CLASS_IN, ttl,
170 : sizeof(ip6.s6_addr), data, prec);
171 :
172 72 : if (!ERR_DNS_IS_OK(err)) {
173 0 : TALLOC_FREE(data);
174 : }
175 :
176 72 : return err;
177 : #else
178 : return ERROR_DNS_INVALID_PARAMETER;
179 : #endif
180 : }
181 :
182 54 : DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
183 : const char *name,
184 : const struct sockaddr_storage *ss,
185 : struct dns_rrec **prec)
186 : {
187 54 : if (ss != NULL) {
188 54 : switch (ss->ss_family) {
189 30 : case AF_INET:
190 30 : return dns_create_a_record(mem_ctx, name, 0, ss, prec);
191 : #ifdef HAVE_IPV6
192 24 : case AF_INET6:
193 24 : return dns_create_aaaa_record(mem_ctx, name, 0, ss, prec);
194 : #endif
195 0 : default:
196 0 : return ERROR_DNS_INVALID_PARAMETER;
197 : }
198 : }
199 :
200 0 : return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0,
201 : NULL, prec);
202 : }
203 :
204 34 : DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx,
205 : const char *name, uint32_t type,
206 : struct dns_rrec **prec)
207 : {
208 34 : return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0,
209 : 0, NULL, prec);
210 : }
211 :
212 68 : DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name,
213 : uint16_t type, uint16_t r_class,
214 : struct dns_rrec **prec)
215 : {
216 68 : return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec);
217 : }
218 :
219 34 : DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname,
220 : const char *algorithm_name, time_t inception,
221 : time_t expiration, uint16_t mode, uint16_t error,
222 : uint16_t key_length, const uint8_t *key,
223 : struct dns_rrec **prec)
224 : {
225 34 : struct dns_buffer *buf = NULL;
226 34 : struct dns_domain_name *algorithm = NULL;
227 : DNS_ERROR err;
228 :
229 34 : if (!(buf = dns_create_buffer(mem_ctx))) {
230 0 : return ERROR_DNS_NO_MEMORY;
231 : }
232 :
233 34 : err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
234 34 : if (!ERR_DNS_IS_OK(err)) goto error;
235 :
236 34 : dns_marshall_domain_name(buf, algorithm);
237 34 : dns_marshall_uint32(buf, inception);
238 34 : dns_marshall_uint32(buf, expiration);
239 34 : dns_marshall_uint16(buf, mode);
240 34 : dns_marshall_uint16(buf, error);
241 34 : dns_marshall_uint16(buf, key_length);
242 34 : dns_marshall_buffer(buf, key, key_length);
243 34 : dns_marshall_uint16(buf, 0); /* Other Size */
244 :
245 34 : if (!ERR_DNS_IS_OK(buf->error)) {
246 0 : err = buf->error;
247 0 : goto error;
248 : }
249 :
250 51 : err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0,
251 34 : buf->offset, buf->data, prec);
252 :
253 34 : error:
254 34 : TALLOC_FREE(buf);
255 34 : return err;
256 : }
257 :
258 34 : DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
259 : struct dns_tkey_record **ptkey)
260 : {
261 : struct dns_tkey_record *tkey;
262 : struct dns_buffer buf;
263 : uint32_t tmp_inception, tmp_expiration;
264 :
265 34 : if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) {
266 0 : return ERROR_DNS_NO_MEMORY;
267 : }
268 :
269 34 : buf.data = rec->data;
270 34 : buf.size = rec->data_length;
271 34 : buf.offset = 0;
272 34 : buf.error = ERROR_DNS_SUCCESS;
273 :
274 34 : dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm);
275 34 : dns_unmarshall_uint32(&buf, &tmp_inception);
276 34 : dns_unmarshall_uint32(&buf, &tmp_expiration);
277 34 : dns_unmarshall_uint16(&buf, &tkey->mode);
278 34 : dns_unmarshall_uint16(&buf, &tkey->error);
279 34 : dns_unmarshall_uint16(&buf, &tkey->key_length);
280 :
281 34 : if (!ERR_DNS_IS_OK(buf.error)) goto error;
282 :
283 34 : if (tkey->key_length) {
284 34 : if (!(tkey->key = talloc_array(tkey, uint8_t, tkey->key_length))) {
285 0 : buf.error = ERROR_DNS_NO_MEMORY;
286 0 : goto error;
287 : }
288 : } else {
289 0 : tkey->key = NULL;
290 : }
291 :
292 34 : dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
293 34 : if (!ERR_DNS_IS_OK(buf.error)) goto error;
294 :
295 34 : tkey->inception = (time_t)tmp_inception;
296 34 : tkey->expiration = (time_t)tmp_expiration;
297 :
298 34 : *ptkey = tkey;
299 34 : return ERROR_DNS_SUCCESS;
300 :
301 0 : error:
302 0 : TALLOC_FREE(tkey);
303 0 : return buf.error;
304 : }
305 :
306 34 : DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
307 : const char *algorithm_name,
308 : time_t time_signed, uint16_t fudge,
309 : uint16_t mac_length, const uint8_t *mac,
310 : uint16_t original_id, uint16_t error,
311 : struct dns_rrec **prec)
312 : {
313 34 : struct dns_buffer *buf = NULL;
314 34 : struct dns_domain_name *algorithm = NULL;
315 : DNS_ERROR err;
316 :
317 34 : if (!(buf = dns_create_buffer(mem_ctx))) {
318 0 : return ERROR_DNS_NO_MEMORY;
319 : }
320 :
321 34 : err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
322 34 : if (!ERR_DNS_IS_OK(err)) goto error;
323 :
324 34 : dns_marshall_domain_name(buf, algorithm);
325 34 : dns_marshall_uint16(buf, 0); /* time prefix */
326 34 : dns_marshall_uint32(buf, time_signed);
327 34 : dns_marshall_uint16(buf, fudge);
328 34 : dns_marshall_uint16(buf, mac_length);
329 34 : dns_marshall_buffer(buf, mac, mac_length);
330 34 : dns_marshall_uint16(buf, original_id);
331 34 : dns_marshall_uint16(buf, error);
332 34 : dns_marshall_uint16(buf, 0); /* Other Size */
333 :
334 34 : if (!ERR_DNS_IS_OK(buf->error)) {
335 0 : err = buf->error;
336 0 : goto error;
337 : }
338 :
339 51 : err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
340 34 : buf->offset, buf->data, prec);
341 :
342 34 : error:
343 34 : TALLOC_FREE(buf);
344 34 : return err;
345 : }
346 :
347 401 : DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
348 : uint16_t *num_records, struct dns_rrec ***records)
349 : {
350 : struct dns_rrec **new_records;
351 :
352 401 : if (!(new_records = talloc_realloc(mem_ctx, *records,
353 : struct dns_rrec *,
354 : (*num_records)+1))) {
355 0 : return ERROR_DNS_NO_MEMORY;
356 : }
357 :
358 401 : new_records[*num_records] = talloc_move(new_records, &rec);
359 :
360 401 : *num_records += 1;
361 401 : *records = new_records;
362 401 : return ERROR_DNS_SUCCESS;
363 : }
364 :
365 : /*
366 : * Create a request that probes a server whether the list of IP addresses
367 : * provides meets our expectations
368 : */
369 :
370 34 : DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
371 : const char *host, int num_ips,
372 : const struct sockaddr_storage *sslist,
373 : struct dns_update_request **preq)
374 : {
375 34 : struct dns_update_request *req = NULL;
376 34 : struct dns_rrec *rec = NULL;
377 : DNS_ERROR err;
378 : uint16_t i;
379 :
380 34 : err = dns_create_update(mem_ctx, zone, &req);
381 34 : if (!ERR_DNS_IS_OK(err)) return err;
382 :
383 34 : err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
384 34 : if (!ERR_DNS_IS_OK(err)) goto error;
385 :
386 34 : err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
387 34 : if (!ERR_DNS_IS_OK(err)) goto error;
388 :
389 88 : for (i=0; i<num_ips; i++) {
390 54 : err = dns_create_name_in_use_record(req, host,
391 54 : &sslist[i], &rec);
392 54 : if (!ERR_DNS_IS_OK(err)) goto error;
393 :
394 54 : err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
395 54 : if (!ERR_DNS_IS_OK(err)) goto error;
396 : }
397 :
398 34 : *preq = req;
399 34 : return ERROR_DNS_SUCCESS;
400 :
401 0 : error:
402 0 : TALLOC_FREE(req);
403 0 : return err;
404 : }
405 :
406 68 : DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
407 : const char *domainname,
408 : const char *hostname,
409 : const struct sockaddr_storage *ss_addrs,
410 : size_t num_addrs,
411 : struct dns_update_request **preq)
412 : {
413 68 : struct dns_update_request *req = NULL;
414 68 : struct dns_rrec *rec = NULL;
415 : DNS_ERROR err;
416 : size_t i;
417 :
418 68 : err = dns_create_update(mem_ctx, domainname, &req);
419 68 : if (!ERR_DNS_IS_OK(err)) return err;
420 :
421 : /*
422 : * Use the same prereq as WinXP -- No CNAME records for this host.
423 : */
424 :
425 68 : err = dns_create_rrec(req, hostname, QTYPE_CNAME, DNS_CLASS_NONE,
426 : 0, 0, NULL, &rec);
427 68 : if (!ERR_DNS_IS_OK(err)) goto error;
428 :
429 68 : err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
430 68 : if (!ERR_DNS_IS_OK(err)) goto error;
431 :
432 : /*
433 : * Delete all existing RRsets from our name
434 : */
435 :
436 68 : err = dns_create_delete_record(req, hostname, QTYPE_ANY, DNS_CLASS_ANY,
437 : &rec);
438 68 : if (!ERR_DNS_IS_OK(err)) goto error;
439 :
440 68 : err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
441 68 : if (!ERR_DNS_IS_OK(err)) goto error;
442 :
443 : /*
444 : * .. and add our IPs
445 : */
446 :
447 176 : for ( i=0; i<num_addrs; i++ ) {
448 :
449 108 : switch(ss_addrs[i].ss_family) {
450 60 : case AF_INET:
451 60 : err = dns_create_a_record(req, hostname, 3600, &ss_addrs[i], &rec);
452 60 : break;
453 : #ifdef HAVE_IPV6
454 48 : case AF_INET6:
455 48 : err = dns_create_aaaa_record(req, hostname, 3600, &ss_addrs[i], &rec);
456 48 : break;
457 : #endif
458 0 : default:
459 0 : continue;
460 : }
461 108 : if (!ERR_DNS_IS_OK(err))
462 0 : goto error;
463 :
464 108 : err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
465 108 : if (!ERR_DNS_IS_OK(err))
466 0 : goto error;
467 : }
468 :
469 68 : *preq = req;
470 68 : return ERROR_DNS_SUCCESS;
471 :
472 0 : error:
473 0 : TALLOC_FREE(req);
474 0 : return err;
475 : }
|