smbpasswd -W docs patch from Aruna Prabakar <aruna.prabakar@hp.com>
[Samba.git] / source / libaddns / dnsrecord.c
blobc649dbd7de4b1627e1db038cd46f5fc1624f3fc6
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, struct in_addr ip,
125 struct dns_rrec **prec)
127 uint8 *data;
128 DNS_ERROR err;
130 if (!(data = (uint8 *)TALLOC_MEMDUP(mem_ctx, (const void *)&ip.s_addr,
131 sizeof(ip.s_addr)))) {
132 return ERROR_DNS_NO_MEMORY;
135 err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
136 sizeof(ip.s_addr), 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 struct in_addr *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_length) {
238 if (!(tkey->key = TALLOC_ARRAY(tkey, uint8, tkey->key_length))) {
239 buf.error = ERROR_DNS_NO_MEMORY;
240 goto error;
242 } else {
243 tkey->key = NULL;
246 dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
247 if (!ERR_DNS_IS_OK(buf.error)) goto error;
249 tkey->inception = (time_t)tmp_inception;
250 tkey->expiration = (time_t)tmp_expiration;
252 *ptkey = tkey;
253 return ERROR_DNS_SUCCESS;
255 error:
256 TALLOC_FREE(tkey);
257 return buf.error;
260 DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
261 const char *algorithm_name,
262 time_t time_signed, uint16 fudge,
263 uint16 mac_length, const uint8 *mac,
264 uint16 original_id, uint16 error,
265 struct dns_rrec **prec)
267 struct dns_buffer *buf;
268 struct dns_domain_name *algorithm;
269 DNS_ERROR err;
271 if (!(buf = dns_create_buffer(mem_ctx))) {
272 return ERROR_DNS_NO_MEMORY;
275 err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
276 if (!ERR_DNS_IS_OK(err)) goto error;
278 dns_marshall_domain_name(buf, algorithm);
279 dns_marshall_uint16(buf, 0); /* time prefix */
280 dns_marshall_uint32(buf, time_signed);
281 dns_marshall_uint16(buf, fudge);
282 dns_marshall_uint16(buf, mac_length);
283 dns_marshall_buffer(buf, mac, mac_length);
284 dns_marshall_uint16(buf, original_id);
285 dns_marshall_uint16(buf, error);
286 dns_marshall_uint16(buf, 0); /* Other Size */
288 if (!ERR_DNS_IS_OK(buf->error)) {
289 err = buf->error;
290 goto error;
293 err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
294 buf->offset, buf->data, prec);
296 error:
297 TALLOC_FREE(buf);
298 return err;
301 DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
302 uint16 *num_records, struct dns_rrec ***records)
304 struct dns_rrec **new_records;
306 if (!(new_records = TALLOC_REALLOC_ARRAY(mem_ctx, *records,
307 struct dns_rrec *,
308 (*num_records)+1))) {
309 return ERROR_DNS_NO_MEMORY;
312 new_records[*num_records] = talloc_move(new_records, &rec);
314 *num_records += 1;
315 *records = new_records;
316 return ERROR_DNS_SUCCESS;
320 * Create a request that probes a server whether the list of IP addresses
321 * provides meets our expectations
324 DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
325 const char *host, int num_ips,
326 const struct in_addr *iplist,
327 struct dns_update_request **preq)
329 struct dns_update_request *req;
330 struct dns_rrec *rec;
331 DNS_ERROR err;
332 uint16 i;
334 err = dns_create_update(mem_ctx, zone, &req);
335 if (!ERR_DNS_IS_OK(err)) goto error;
337 err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
338 if (!ERR_DNS_IS_OK(err)) goto error;
340 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
341 if (!ERR_DNS_IS_OK(err)) goto error;
343 for (i=0; i<num_ips; i++) {
344 err = dns_create_name_in_use_record(req, host,
345 &iplist[i], &rec);
346 if (!ERR_DNS_IS_OK(err)) goto error;
348 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
349 if (!ERR_DNS_IS_OK(err)) goto error;
352 *preq = req;
353 return ERROR_DNS_SUCCESS;
355 error:
356 TALLOC_FREE(req);
357 return err;
360 DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
361 const char *domainname,
362 const char *hostname,
363 const struct in_addr *ip_addrs,
364 size_t num_addrs,
365 struct dns_update_request **preq)
367 struct dns_update_request *req;
368 struct dns_rrec *rec;
369 DNS_ERROR err;
370 size_t i;
372 err = dns_create_update(mem_ctx, domainname, &req);
373 if (!ERR_DNS_IS_OK(err)) return err;
376 * The zone must be used at all
379 err = dns_create_rrec(req, domainname, QTYPE_ANY, DNS_CLASS_ANY,
380 0, 0, NULL, &rec);
381 if (!ERR_DNS_IS_OK(err)) goto error;
383 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
384 if (!ERR_DNS_IS_OK(err)) goto error;
387 * Delete any existing A records
390 err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY,
391 &rec);
392 if (!ERR_DNS_IS_OK(err)) goto error;
394 err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
395 if (!ERR_DNS_IS_OK(err)) goto error;
398 * .. and add our IPs
401 for ( i=0; i<num_addrs; i++ ) {
402 err = dns_create_a_record(req, hostname, 3600, ip_addrs[i], &rec);
403 if (!ERR_DNS_IS_OK(err))
404 goto error;
406 err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
407 if (!ERR_DNS_IS_OK(err))
408 goto error;
411 *preq = req;
412 return ERROR_DNS_SUCCESS;
414 error:
415 TALLOC_FREE(req);
416 return err;