r20257: Hey, change_owner_to_parent is now static :-)
[Samba.git] / source / libaddns / dnsrecord.c
blob6dfb8edf5cf447aad604b33869e91ef3b86d4cce
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, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 02110-1301 USA
26 #include "dns.h"
28 DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name,
29 uint16 q_type, uint16 q_class,
30 struct dns_request **preq )
32 struct dns_request *req;
33 struct dns_question *q;
34 DNS_ERROR err;
36 if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request)) ||
37 !(req->questions = TALLOC_ARRAY(req, struct dns_question *, 1)) ||
38 !(req->questions[0] = talloc(req->questions,
39 struct dns_question))) {
40 TALLOC_FREE(req);
41 return ERROR_DNS_NO_MEMORY;
44 req->id = random();
46 req->num_questions = 1;
47 q = req->questions[0];
49 err = dns_domain_name_from_string(q, name, &q->name);
50 if (!ERR_DNS_IS_OK(err)) {
51 TALLOC_FREE(req);
52 return err;
55 q->q_type = q_type;
56 q->q_class = q_class;
58 *preq = req;
59 return ERROR_DNS_SUCCESS;
62 DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
63 struct dns_update_request **preq )
65 struct dns_update_request *req;
66 struct dns_zone *z;
67 DNS_ERROR err;
69 if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_update_request)) ||
70 !(req->zones = TALLOC_ARRAY(req, struct dns_zone *, 1)) ||
71 !(req->zones[0] = talloc(req->zones, struct dns_zone))) {
72 TALLOC_FREE(req);
73 return ERROR_DNS_NO_MEMORY;
76 req->id = random();
77 req->flags = 0x2800; /* Dynamic update */
79 req->num_zones = 1;
80 z = req->zones[0];
82 err = dns_domain_name_from_string(z, name, &z->name);
83 if (!ERR_DNS_IS_OK(err)) {
84 TALLOC_FREE(req);
85 return err;
88 z->z_type = QTYPE_SOA;
89 z->z_class = DNS_CLASS_IN;
91 *preq = req;
92 return ERROR_DNS_SUCCESS;
95 DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name,
96 uint16 type, uint16 r_class, uint32 ttl,
97 uint16 data_length, uint8 *data,
98 struct dns_rrec **prec)
100 struct dns_rrec *rec;
101 DNS_ERROR err;
103 if (!(rec = talloc(mem_ctx, struct dns_rrec))) {
104 return ERROR_DNS_NO_MEMORY;
107 err = dns_domain_name_from_string(rec, name, &rec->name);
108 if (!(ERR_DNS_IS_OK(err))) {
109 TALLOC_FREE(rec);
110 return err;
113 rec->type = type;
114 rec->r_class = r_class;
115 rec->ttl = ttl;
116 rec->data_length = data_length;
117 rec->data = talloc_move(rec, &data);
119 *prec = rec;
120 return ERROR_DNS_SUCCESS;
123 DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
124 uint32 ttl, in_addr_t ip,
125 struct dns_rrec **prec)
127 uint8 *data;
128 DNS_ERROR err;
130 if (!(data = (uint8 *)TALLOC_MEMDUP(mem_ctx, (const void *)&ip,
131 sizeof(ip)))) {
132 return ERROR_DNS_NO_MEMORY;
135 err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
136 sizeof(ip), data, prec);
138 if (!ERR_DNS_IS_OK(err)) {
139 TALLOC_FREE(data);
142 return err;
145 DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
146 const char *name,
147 const in_addr_t *ip,
148 struct dns_rrec **prec)
150 if (ip != NULL) {
151 return dns_create_a_record(mem_ctx, name, 0, *ip, prec);
154 return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0,
155 NULL, prec);
158 DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx,
159 const char *name, uint32 type,
160 struct dns_rrec **prec)
162 return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0,
163 0, NULL, prec);
166 DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name,
167 uint16 type, uint16 r_class,
168 struct dns_rrec **prec)
170 return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec);
173 DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname,
174 const char *algorithm_name, time_t inception,
175 time_t expiration, uint16 mode, uint16 error,
176 uint16 key_length, const uint8 *key,
177 struct dns_rrec **prec)
179 struct dns_buffer *buf;
180 struct dns_domain_name *algorithm;
181 DNS_ERROR err;
183 if (!(buf = dns_create_buffer(mem_ctx))) {
184 return ERROR_DNS_NO_MEMORY;
187 err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
188 if (!ERR_DNS_IS_OK(err)) goto error;
190 dns_marshall_domain_name(buf, algorithm);
191 dns_marshall_uint32(buf, inception);
192 dns_marshall_uint32(buf, expiration);
193 dns_marshall_uint16(buf, mode);
194 dns_marshall_uint16(buf, error);
195 dns_marshall_uint16(buf, key_length);
196 dns_marshall_buffer(buf, key, key_length);
197 dns_marshall_uint16(buf, 0); /* Other Size */
199 if (!ERR_DNS_IS_OK(buf->error)) {
200 err = buf->error;
201 goto error;
204 err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0,
205 buf->offset, buf->data, prec);
207 error:
208 TALLOC_FREE(buf);
209 return err;
212 DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
213 struct dns_tkey_record **ptkey)
215 struct dns_tkey_record *tkey;
216 struct dns_buffer buf;
217 uint32 tmp_inception, tmp_expiration;
219 if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) {
220 return ERROR_DNS_NO_MEMORY;
223 buf.data = rec->data;
224 buf.size = rec->data_length;
225 buf.offset = 0;
226 buf.error = ERROR_DNS_SUCCESS;
228 dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm);
229 dns_unmarshall_uint32(&buf, &tmp_inception);
230 dns_unmarshall_uint32(&buf, &tmp_expiration);
231 dns_unmarshall_uint16(&buf, &tkey->mode);
232 dns_unmarshall_uint16(&buf, &tkey->error);
233 dns_unmarshall_uint16(&buf, &tkey->key_length);
235 if (!ERR_DNS_IS_OK(buf.error)) goto error;
237 if (!(tkey->key = TALLOC_ARRAY(tkey, uint8, tkey->key_length))) {
238 buf.error = ERROR_DNS_NO_MEMORY;
239 goto error;
242 dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
243 if (!ERR_DNS_IS_OK(buf.error)) goto error;
245 tkey->inception = (time_t)tmp_inception;
246 tkey->expiration = (time_t)tmp_expiration;
248 *ptkey = tkey;
249 return ERROR_DNS_SUCCESS;
251 error:
252 TALLOC_FREE(tkey);
253 return buf.error;
256 DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
257 const char *algorithm_name,
258 time_t time_signed, uint16 fudge,
259 uint16 mac_length, const uint8 *mac,
260 uint16 original_id, uint16 error,
261 struct dns_rrec **prec)
263 struct dns_buffer *buf;
264 struct dns_domain_name *algorithm;
265 DNS_ERROR err;
267 if (!(buf = dns_create_buffer(mem_ctx))) {
268 return ERROR_DNS_NO_MEMORY;
271 err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
272 if (!ERR_DNS_IS_OK(err)) goto error;
274 dns_marshall_domain_name(buf, algorithm);
275 dns_marshall_uint16(buf, 0); /* time prefix */
276 dns_marshall_uint32(buf, time_signed);
277 dns_marshall_uint16(buf, fudge);
278 dns_marshall_uint16(buf, mac_length);
279 dns_marshall_buffer(buf, mac, mac_length);
280 dns_marshall_uint16(buf, original_id);
281 dns_marshall_uint16(buf, error);
282 dns_marshall_uint16(buf, 0); /* Other Size */
284 if (!ERR_DNS_IS_OK(buf->error)) {
285 err = buf->error;
286 goto error;
289 err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
290 buf->offset, buf->data, prec);
292 error:
293 TALLOC_FREE(buf);
294 return err;
297 DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
298 uint16 *num_records, struct dns_rrec ***records)
300 struct dns_rrec **new_records;
302 if (!(new_records = TALLOC_REALLOC_ARRAY(mem_ctx, *records,
303 struct dns_rrec *,
304 (*num_records)+1))) {
305 return ERROR_DNS_NO_MEMORY;
308 new_records[*num_records] = talloc_move(new_records, &rec);
310 *num_records += 1;
311 *records = new_records;
312 return ERROR_DNS_SUCCESS;
316 * Create a request that probes a server whether the list of IP addresses
317 * provides meets our expectations
320 DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
321 const char *host, int num_ips,
322 const struct in_addr *iplist,
323 struct dns_update_request **preq)
325 struct dns_update_request *req;
326 struct dns_rrec *rec;
327 DNS_ERROR err;
328 uint16 i;
330 err = dns_create_update(mem_ctx, zone, &req);
331 if (!ERR_DNS_IS_OK(err)) goto error;
333 err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
334 if (!ERR_DNS_IS_OK(err)) goto error;
336 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
337 if (!ERR_DNS_IS_OK(err)) goto error;
339 for (i=0; i<num_ips; i++) {
340 err = dns_create_name_in_use_record(req, host,
341 &iplist[i].s_addr, &rec);
342 if (!ERR_DNS_IS_OK(err)) goto error;
344 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
345 if (!ERR_DNS_IS_OK(err)) goto error;
348 *preq = req;
349 return ERROR_DNS_SUCCESS;
351 error:
352 TALLOC_FREE(req);
353 return err;
356 DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
357 const char *domainname,
358 const char *hostname,
359 in_addr_t ip_addr,
360 struct dns_update_request **preq)
362 struct dns_update_request *req;
363 struct dns_rrec *rec;
364 DNS_ERROR err;
366 err = dns_create_update(mem_ctx, domainname, &req);
367 if (!ERR_DNS_IS_OK(err)) return err;
370 * The zone must be used at all
373 err = dns_create_rrec(req, domainname, QTYPE_ANY, DNS_CLASS_ANY,
374 0, 0, NULL, &rec);
375 if (!ERR_DNS_IS_OK(err)) goto error;
377 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
378 if (!ERR_DNS_IS_OK(err)) goto error;
381 * Delete any existing A records
384 err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY,
385 &rec);
386 if (!ERR_DNS_IS_OK(err)) goto error;
388 err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
389 if (!ERR_DNS_IS_OK(err)) goto error;
392 * .. and add our IP
395 err = dns_create_a_record(req, hostname, 3600, ip_addr, &rec);
396 if (!ERR_DNS_IS_OK(err)) goto error;
398 err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
399 if (!ERR_DNS_IS_OK(err)) goto error;
401 *preq = req;
402 return ERROR_DNS_SUCCESS;
404 error:
405 TALLOC_FREE(req);
406 return err;