upgradeprovision: do not hold references to messageElements
[Samba/vl.git] / lib / addns / dnsrecord.c
blobe5a43b887ca4c7d753e883877faea46c8aa91b1f
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>
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
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.
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.
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/>.
24 #include "dns.h"
26 DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name,
27 uint16 q_type, uint16 q_class,
28 struct dns_request **preq )
30 struct dns_request *req = NULL;
31 struct dns_question *q = NULL;
32 DNS_ERROR err;
34 if (!(req = talloc_zero(mem_ctx, struct dns_request)) ||
35 !(req->questions = talloc_array(req, struct dns_question *, 1)) ||
36 !(req->questions[0] = talloc(req->questions,
37 struct dns_question))) {
38 TALLOC_FREE(req);
39 return ERROR_DNS_NO_MEMORY;
42 req->id = random();
44 req->num_questions = 1;
45 q = req->questions[0];
47 err = dns_domain_name_from_string(q, name, &q->name);
48 if (!ERR_DNS_IS_OK(err)) {
49 TALLOC_FREE(req);
50 return err;
53 q->q_type = q_type;
54 q->q_class = q_class;
56 *preq = req;
57 return ERROR_DNS_SUCCESS;
60 DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
61 struct dns_update_request **preq )
63 struct dns_update_request *req = NULL;
64 struct dns_zone *z = NULL;
65 DNS_ERROR err;
67 if (!(req = talloc_zero(mem_ctx, struct dns_update_request)) ||
68 !(req->zones = talloc_array(req, struct dns_zone *, 1)) ||
69 !(req->zones[0] = talloc(req->zones, struct dns_zone))) {
70 TALLOC_FREE(req);
71 return ERROR_DNS_NO_MEMORY;
74 req->id = random();
75 req->flags = 0x2800; /* Dynamic update */
77 req->num_zones = 1;
78 z = req->zones[0];
80 err = dns_domain_name_from_string(z, name, &z->name);
81 if (!ERR_DNS_IS_OK(err)) {
82 TALLOC_FREE(req);
83 return err;
86 z->z_type = QTYPE_SOA;
87 z->z_class = DNS_CLASS_IN;
89 *preq = req;
90 return ERROR_DNS_SUCCESS;
93 DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name,
94 uint16 type, uint16 r_class, uint32 ttl,
95 uint16 data_length, uint8 *data,
96 struct dns_rrec **prec)
98 struct dns_rrec *rec = NULL;
99 DNS_ERROR err;
101 if (!(rec = talloc(mem_ctx, struct dns_rrec))) {
102 return ERROR_DNS_NO_MEMORY;
105 err = dns_domain_name_from_string(rec, name, &rec->name);
106 if (!(ERR_DNS_IS_OK(err))) {
107 TALLOC_FREE(rec);
108 return err;
111 rec->type = type;
112 rec->r_class = r_class;
113 rec->ttl = ttl;
114 rec->data_length = data_length;
115 rec->data = talloc_move(rec, &data);
117 *prec = rec;
118 return ERROR_DNS_SUCCESS;
121 DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
122 uint32 ttl, const struct sockaddr_storage *pss,
123 struct dns_rrec **prec)
125 uint8 *data;
126 DNS_ERROR err;
127 struct in_addr ip;
129 if (pss->ss_family != AF_INET) {
130 return ERROR_DNS_INVALID_PARAMETER;
133 ip = ((const struct sockaddr_in *)pss)->sin_addr;
134 if (!(data = (uint8 *)talloc_memdup(mem_ctx, (const void *)&ip.s_addr,
135 sizeof(ip.s_addr)))) {
136 return ERROR_DNS_NO_MEMORY;
139 err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
140 sizeof(ip.s_addr), data, prec);
142 if (!ERR_DNS_IS_OK(err)) {
143 TALLOC_FREE(data);
146 return err;
149 DNS_ERROR dns_create_aaaa_record(TALLOC_CTX *mem_ctx, const char *host,
150 uint32 ttl, const struct sockaddr_storage *pss,
151 struct dns_rrec **prec)
153 #ifdef HAVE_IPV6
154 uint8 *data;
155 DNS_ERROR err;
156 struct in6_addr ip6;
158 if (pss->ss_family != AF_INET6) {
159 return ERROR_DNS_INVALID_PARAMETER;
162 ip6 = ((const struct sockaddr_in6 *)pss)->sin6_addr;
163 if (!(data = (uint8 *)talloc_memdup(mem_ctx, (const void *)&ip6.s6_addr,
164 sizeof(ip6.s6_addr)))) {
165 return ERROR_DNS_NO_MEMORY;
168 err = dns_create_rrec(mem_ctx, host, QTYPE_AAAA, DNS_CLASS_IN, ttl,
169 sizeof(ip6.s6_addr), data, prec);
171 if (!ERR_DNS_IS_OK(err)) {
172 TALLOC_FREE(data);
175 return err;
176 #else
177 return ERROR_DNS_INVALID_PARAMETER;
178 #endif
181 DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
182 const char *name,
183 const struct sockaddr_storage *ss,
184 struct dns_rrec **prec)
186 if (ss != NULL) {
187 switch (ss->ss_family) {
188 case AF_INET:
189 return dns_create_a_record(mem_ctx, name, 0, ss, prec);
190 #ifdef HAVE_IPV6
191 case AF_INET6:
192 return dns_create_aaaa_record(mem_ctx, name, 0, ss, prec);
193 #endif
194 default:
195 return ERROR_DNS_INVALID_PARAMETER;
199 return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0,
200 NULL, prec);
203 DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx,
204 const char *name, uint32 type,
205 struct dns_rrec **prec)
207 return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0,
208 0, NULL, prec);
211 DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name,
212 uint16 type, uint16 r_class,
213 struct dns_rrec **prec)
215 return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec);
218 DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname,
219 const char *algorithm_name, time_t inception,
220 time_t expiration, uint16 mode, uint16 error,
221 uint16 key_length, const uint8 *key,
222 struct dns_rrec **prec)
224 struct dns_buffer *buf = NULL;
225 struct dns_domain_name *algorithm = NULL;
226 DNS_ERROR err;
228 if (!(buf = dns_create_buffer(mem_ctx))) {
229 return ERROR_DNS_NO_MEMORY;
232 err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
233 if (!ERR_DNS_IS_OK(err)) goto error;
235 dns_marshall_domain_name(buf, algorithm);
236 dns_marshall_uint32(buf, inception);
237 dns_marshall_uint32(buf, expiration);
238 dns_marshall_uint16(buf, mode);
239 dns_marshall_uint16(buf, error);
240 dns_marshall_uint16(buf, key_length);
241 dns_marshall_buffer(buf, key, key_length);
242 dns_marshall_uint16(buf, 0); /* Other Size */
244 if (!ERR_DNS_IS_OK(buf->error)) {
245 err = buf->error;
246 goto error;
249 err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0,
250 buf->offset, buf->data, prec);
252 error:
253 TALLOC_FREE(buf);
254 return err;
257 DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
258 struct dns_tkey_record **ptkey)
260 struct dns_tkey_record *tkey;
261 struct dns_buffer buf;
262 uint32 tmp_inception, tmp_expiration;
264 if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) {
265 return ERROR_DNS_NO_MEMORY;
268 buf.data = rec->data;
269 buf.size = rec->data_length;
270 buf.offset = 0;
271 buf.error = ERROR_DNS_SUCCESS;
273 dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm);
274 dns_unmarshall_uint32(&buf, &tmp_inception);
275 dns_unmarshall_uint32(&buf, &tmp_expiration);
276 dns_unmarshall_uint16(&buf, &tkey->mode);
277 dns_unmarshall_uint16(&buf, &tkey->error);
278 dns_unmarshall_uint16(&buf, &tkey->key_length);
280 if (!ERR_DNS_IS_OK(buf.error)) goto error;
282 if (tkey->key_length) {
283 if (!(tkey->key = talloc_array(tkey, uint8, tkey->key_length))) {
284 buf.error = ERROR_DNS_NO_MEMORY;
285 goto error;
287 } else {
288 tkey->key = NULL;
291 dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
292 if (!ERR_DNS_IS_OK(buf.error)) goto error;
294 tkey->inception = (time_t)tmp_inception;
295 tkey->expiration = (time_t)tmp_expiration;
297 *ptkey = tkey;
298 return ERROR_DNS_SUCCESS;
300 error:
301 TALLOC_FREE(tkey);
302 return buf.error;
305 DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
306 const char *algorithm_name,
307 time_t time_signed, uint16 fudge,
308 uint16 mac_length, const uint8 *mac,
309 uint16 original_id, uint16 error,
310 struct dns_rrec **prec)
312 struct dns_buffer *buf = NULL;
313 struct dns_domain_name *algorithm = NULL;
314 DNS_ERROR err;
316 if (!(buf = dns_create_buffer(mem_ctx))) {
317 return ERROR_DNS_NO_MEMORY;
320 err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
321 if (!ERR_DNS_IS_OK(err)) goto error;
323 dns_marshall_domain_name(buf, algorithm);
324 dns_marshall_uint16(buf, 0); /* time prefix */
325 dns_marshall_uint32(buf, time_signed);
326 dns_marshall_uint16(buf, fudge);
327 dns_marshall_uint16(buf, mac_length);
328 dns_marshall_buffer(buf, mac, mac_length);
329 dns_marshall_uint16(buf, original_id);
330 dns_marshall_uint16(buf, error);
331 dns_marshall_uint16(buf, 0); /* Other Size */
333 if (!ERR_DNS_IS_OK(buf->error)) {
334 err = buf->error;
335 goto error;
338 err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
339 buf->offset, buf->data, prec);
341 error:
342 TALLOC_FREE(buf);
343 return err;
346 DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
347 uint16 *num_records, struct dns_rrec ***records)
349 struct dns_rrec **new_records;
351 if (!(new_records = talloc_realloc(mem_ctx, *records,
352 struct dns_rrec *,
353 (*num_records)+1))) {
354 return ERROR_DNS_NO_MEMORY;
357 new_records[*num_records] = talloc_move(new_records, &rec);
359 *num_records += 1;
360 *records = new_records;
361 return ERROR_DNS_SUCCESS;
365 * Create a request that probes a server whether the list of IP addresses
366 * provides meets our expectations
369 DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
370 const char *host, int num_ips,
371 const struct sockaddr_storage *sslist,
372 struct dns_update_request **preq)
374 struct dns_update_request *req = NULL;
375 struct dns_rrec *rec = NULL;
376 DNS_ERROR err;
377 uint16 i;
379 err = dns_create_update(mem_ctx, zone, &req);
380 if (!ERR_DNS_IS_OK(err)) return err;
382 err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
383 if (!ERR_DNS_IS_OK(err)) goto error;
385 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
386 if (!ERR_DNS_IS_OK(err)) goto error;
388 for (i=0; i<num_ips; i++) {
389 err = dns_create_name_in_use_record(req, host,
390 &sslist[i], &rec);
391 if (!ERR_DNS_IS_OK(err)) goto error;
393 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
394 if (!ERR_DNS_IS_OK(err)) goto error;
397 *preq = req;
398 return ERROR_DNS_SUCCESS;
400 error:
401 TALLOC_FREE(req);
402 return err;
405 DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
406 const char *domainname,
407 const char *hostname,
408 const struct sockaddr_storage *ss_addrs,
409 size_t num_addrs,
410 struct dns_update_request **preq)
412 struct dns_update_request *req = NULL;
413 struct dns_rrec *rec = NULL;
414 DNS_ERROR err;
415 size_t i;
417 err = dns_create_update(mem_ctx, domainname, &req);
418 if (!ERR_DNS_IS_OK(err)) return err;
421 * Use the same prereq as WinXP -- No CNAME records for this host.
424 err = dns_create_rrec(req, hostname, QTYPE_CNAME, DNS_CLASS_NONE,
425 0, 0, NULL, &rec);
426 if (!ERR_DNS_IS_OK(err)) goto error;
428 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
429 if (!ERR_DNS_IS_OK(err)) goto error;
432 * Delete any existing A records
435 err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY,
436 &rec);
437 if (!ERR_DNS_IS_OK(err)) goto error;
439 err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
440 if (!ERR_DNS_IS_OK(err)) goto error;
443 * .. and add our IPs
446 for ( i=0; i<num_addrs; i++ ) {
448 switch(ss_addrs[i].ss_family) {
449 case AF_INET:
450 err = dns_create_a_record(req, hostname, 3600, &ss_addrs[i], &rec);
451 break;
452 #ifdef HAVE_IPV6
453 case AF_INET6:
454 err = dns_create_aaaa_record(req, hostname, 3600, &ss_addrs[i], &rec);
455 break;
456 #endif
457 default:
458 continue;
460 if (!ERR_DNS_IS_OK(err))
461 goto error;
463 err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
464 if (!ERR_DNS_IS_OK(err))
465 goto error;
468 *preq = req;
469 return ERROR_DNS_SUCCESS;
471 error:
472 TALLOC_FREE(req);
473 return err;