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 43 : 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 43 : struct dns_request *req = NULL;
32 43 : struct dns_question *q = NULL;
33 0 : DNS_ERROR err;
34 :
35 43 : if (!(req = talloc_zero(mem_ctx, struct dns_request)) ||
36 43 : !(req->questions = talloc_array(req, struct dns_question *, 1)) ||
37 43 : !(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 43 : generate_random_buffer((uint8_t *)&req->id, sizeof(req->id));
44 :
45 43 : req->num_questions = 1;
46 43 : q = req->questions[0];
47 :
48 43 : err = dns_domain_name_from_string(q, name, &q->name);
49 43 : if (!ERR_DNS_IS_OK(err)) {
50 0 : TALLOC_FREE(req);
51 0 : return err;
52 : }
53 :
54 43 : q->q_type = q_type;
55 43 : q->q_class = q_class;
56 :
57 43 : *preq = req;
58 43 : return ERROR_DNS_SUCCESS;
59 : }
60 :
61 127 : DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
62 : struct dns_update_request **preq )
63 : {
64 127 : struct dns_update_request *req = NULL;
65 127 : struct dns_zone *z = NULL;
66 0 : DNS_ERROR err;
67 :
68 127 : if (!(req = talloc_zero(mem_ctx, struct dns_update_request)) ||
69 127 : !(req->zones = talloc_array(req, struct dns_zone *, 1)) ||
70 127 : !(req->zones[0] = talloc(req->zones, struct dns_zone))) {
71 0 : TALLOC_FREE(req);
72 0 : return ERROR_DNS_NO_MEMORY;
73 : }
74 :
75 127 : req->id = random();
76 127 : req->flags = 0x2800; /* Dynamic update */
77 :
78 127 : req->num_zones = 1;
79 127 : z = req->zones[0];
80 :
81 127 : err = dns_domain_name_from_string(z, name, &z->name);
82 127 : if (!ERR_DNS_IS_OK(err)) {
83 0 : TALLOC_FREE(req);
84 0 : return err;
85 : }
86 :
87 127 : z->z_type = QTYPE_SOA;
88 127 : z->z_class = DNS_CLASS_IN;
89 :
90 127 : *preq = req;
91 127 : return ERROR_DNS_SUCCESS;
92 : }
93 :
94 469 : 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 469 : struct dns_rrec *rec = NULL;
100 0 : DNS_ERROR err;
101 :
102 469 : if (!(rec = talloc(mem_ctx, struct dns_rrec))) {
103 0 : return ERROR_DNS_NO_MEMORY;
104 : }
105 :
106 469 : err = dns_domain_name_from_string(rec, name, &rec->name);
107 469 : if (!(ERR_DNS_IS_OK(err))) {
108 0 : TALLOC_FREE(rec);
109 0 : return err;
110 : }
111 :
112 469 : rec->type = type;
113 469 : rec->r_class = r_class;
114 469 : rec->ttl = ttl;
115 469 : rec->data_length = data_length;
116 469 : rec->data = talloc_move(rec, &data);
117 :
118 469 : *prec = rec;
119 469 : return ERROR_DNS_SUCCESS;
120 : }
121 :
122 103 : 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 0 : uint8_t *data;
127 0 : DNS_ERROR err;
128 0 : struct in_addr ip;
129 :
130 103 : if (pss->ss_family != AF_INET) {
131 0 : return ERROR_DNS_INVALID_PARAMETER;
132 : }
133 :
134 103 : ip = ((const struct sockaddr_in *)pss)->sin_addr;
135 103 : 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 103 : err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
141 : sizeof(ip.s_addr), data, prec);
142 :
143 103 : if (!ERR_DNS_IS_OK(err)) {
144 0 : TALLOC_FREE(data);
145 : }
146 :
147 103 : 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 0 : uint8_t *data;
156 0 : DNS_ERROR err;
157 0 : 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 58 : 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 58 : if (ss != NULL) {
188 58 : switch (ss->ss_family) {
189 34 : case AF_INET:
190 34 : 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 42 : 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 42 : return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0,
209 : 0, NULL, prec);
210 : }
211 :
212 84 : 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 84 : return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec);
217 : }
218 :
219 42 : 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 42 : struct dns_buffer *buf = NULL;
226 42 : struct dns_domain_name *algorithm = NULL;
227 0 : DNS_ERROR err;
228 :
229 42 : if (!(buf = dns_create_buffer(mem_ctx))) {
230 0 : return ERROR_DNS_NO_MEMORY;
231 : }
232 :
233 42 : err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
234 42 : if (!ERR_DNS_IS_OK(err)) goto error;
235 :
236 42 : dns_marshall_domain_name(buf, algorithm);
237 42 : dns_marshall_uint32(buf, inception);
238 42 : dns_marshall_uint32(buf, expiration);
239 42 : dns_marshall_uint16(buf, mode);
240 42 : dns_marshall_uint16(buf, error);
241 42 : dns_marshall_uint16(buf, key_length);
242 42 : dns_marshall_buffer(buf, key, key_length);
243 42 : dns_marshall_uint16(buf, 0); /* Other Size */
244 :
245 42 : if (!ERR_DNS_IS_OK(buf->error)) {
246 0 : err = buf->error;
247 0 : goto error;
248 : }
249 :
250 42 : err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0,
251 42 : buf->offset, buf->data, prec);
252 :
253 42 : error:
254 42 : TALLOC_FREE(buf);
255 42 : return err;
256 : }
257 :
258 42 : DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
259 : struct dns_tkey_record **ptkey)
260 : {
261 0 : struct dns_tkey_record *tkey;
262 0 : struct dns_buffer buf;
263 0 : uint32_t tmp_inception, tmp_expiration;
264 :
265 42 : if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) {
266 0 : return ERROR_DNS_NO_MEMORY;
267 : }
268 :
269 42 : buf.data = rec->data;
270 42 : buf.size = rec->data_length;
271 42 : buf.offset = 0;
272 42 : buf.error = ERROR_DNS_SUCCESS;
273 :
274 42 : dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm);
275 42 : dns_unmarshall_uint32(&buf, &tmp_inception);
276 42 : dns_unmarshall_uint32(&buf, &tmp_expiration);
277 42 : dns_unmarshall_uint16(&buf, &tkey->mode);
278 42 : dns_unmarshall_uint16(&buf, &tkey->error);
279 42 : dns_unmarshall_uint16(&buf, &tkey->key_length);
280 :
281 42 : if (!ERR_DNS_IS_OK(buf.error)) goto error;
282 :
283 42 : if (tkey->key_length) {
284 42 : 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 42 : dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
293 42 : if (!ERR_DNS_IS_OK(buf.error)) goto error;
294 :
295 42 : tkey->inception = (time_t)tmp_inception;
296 42 : tkey->expiration = (time_t)tmp_expiration;
297 :
298 42 : *ptkey = tkey;
299 42 : return ERROR_DNS_SUCCESS;
300 :
301 0 : error:
302 0 : TALLOC_FREE(tkey);
303 0 : return buf.error;
304 : }
305 :
306 42 : 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 42 : struct dns_buffer *buf = NULL;
314 42 : struct dns_domain_name *algorithm = NULL;
315 0 : DNS_ERROR err;
316 :
317 42 : if (!(buf = dns_create_buffer(mem_ctx))) {
318 0 : return ERROR_DNS_NO_MEMORY;
319 : }
320 :
321 42 : err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
322 42 : if (!ERR_DNS_IS_OK(err)) goto error;
323 :
324 42 : dns_marshall_domain_name(buf, algorithm);
325 42 : dns_marshall_uint16(buf, 0); /* time prefix */
326 42 : dns_marshall_uint32(buf, time_signed);
327 42 : dns_marshall_uint16(buf, fudge);
328 42 : dns_marshall_uint16(buf, mac_length);
329 42 : dns_marshall_buffer(buf, mac, mac_length);
330 42 : dns_marshall_uint16(buf, original_id);
331 42 : dns_marshall_uint16(buf, error);
332 42 : dns_marshall_uint16(buf, 0); /* Other Size */
333 :
334 42 : if (!ERR_DNS_IS_OK(buf->error)) {
335 0 : err = buf->error;
336 0 : goto error;
337 : }
338 :
339 42 : err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
340 42 : buf->offset, buf->data, prec);
341 :
342 42 : error:
343 42 : TALLOC_FREE(buf);
344 42 : return err;
345 : }
346 :
347 469 : DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
348 : uint16_t *num_records, struct dns_rrec ***records)
349 : {
350 0 : struct dns_rrec **new_records;
351 :
352 469 : 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 469 : new_records[*num_records] = talloc_move(new_records, &rec);
359 :
360 469 : *num_records += 1;
361 469 : *records = new_records;
362 469 : 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 42 : 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 42 : struct dns_update_request *req = NULL;
376 42 : struct dns_rrec *rec = NULL;
377 0 : DNS_ERROR err;
378 0 : uint16_t i;
379 :
380 42 : err = dns_create_update(mem_ctx, zone, &req);
381 42 : if (!ERR_DNS_IS_OK(err)) return err;
382 :
383 42 : err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
384 42 : if (!ERR_DNS_IS_OK(err)) goto error;
385 :
386 42 : err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
387 42 : if (!ERR_DNS_IS_OK(err)) goto error;
388 :
389 100 : for (i=0; i<num_ips; i++) {
390 58 : err = dns_create_name_in_use_record(req, host,
391 58 : &sslist[i], &rec);
392 58 : if (!ERR_DNS_IS_OK(err)) goto error;
393 :
394 58 : err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
395 58 : if (!ERR_DNS_IS_OK(err)) goto error;
396 : }
397 :
398 42 : *preq = req;
399 42 : return ERROR_DNS_SUCCESS;
400 :
401 0 : error:
402 0 : TALLOC_FREE(req);
403 0 : return err;
404 : }
405 :
406 84 : 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 : uint32_t ttl,
412 : struct dns_update_request **preq)
413 : {
414 84 : struct dns_update_request *req = NULL;
415 84 : struct dns_rrec *rec = NULL;
416 0 : DNS_ERROR err;
417 0 : size_t i;
418 :
419 84 : err = dns_create_update(mem_ctx, domainname, &req);
420 84 : if (!ERR_DNS_IS_OK(err)) return err;
421 :
422 : /*
423 : * Use the same prereq as WinXP -- No CNAME records for this host.
424 : */
425 :
426 84 : err = dns_create_rrec(req, hostname, QTYPE_CNAME, DNS_CLASS_NONE,
427 : 0, 0, NULL, &rec);
428 84 : if (!ERR_DNS_IS_OK(err)) goto error;
429 :
430 84 : err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
431 84 : if (!ERR_DNS_IS_OK(err)) goto error;
432 :
433 : /*
434 : * Delete all existing RRsets from our name
435 : */
436 :
437 84 : err = dns_create_delete_record(req, hostname, QTYPE_ANY, DNS_CLASS_ANY,
438 : &rec);
439 84 : if (!ERR_DNS_IS_OK(err)) goto error;
440 :
441 84 : err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
442 84 : if (!ERR_DNS_IS_OK(err)) goto error;
443 :
444 : /*
445 : * .. and add our IPs
446 : */
447 :
448 200 : for ( i=0; i<num_addrs; i++ ) {
449 :
450 116 : switch(ss_addrs[i].ss_family) {
451 68 : case AF_INET:
452 68 : err = dns_create_a_record(req,
453 : hostname,
454 : ttl,
455 68 : &ss_addrs[i],
456 : &rec);
457 68 : break;
458 : #ifdef HAVE_IPV6
459 48 : case AF_INET6:
460 48 : err = dns_create_aaaa_record(req,
461 : hostname,
462 : ttl,
463 48 : &ss_addrs[i],
464 : &rec);
465 48 : break;
466 : #endif
467 0 : default:
468 0 : continue;
469 : }
470 116 : if (!ERR_DNS_IS_OK(err))
471 0 : goto error;
472 :
473 116 : err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
474 116 : if (!ERR_DNS_IS_OK(err))
475 0 : goto error;
476 : }
477 :
478 84 : *preq = req;
479 84 : return ERROR_DNS_SUCCESS;
480 :
481 0 : error:
482 0 : TALLOC_FREE(req);
483 0 : return err;
484 : }
|