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
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/>.
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;
31
struct dns_question *q;
34
if (!(req = TALLOC_ZERO_P(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))) {
39
return ERROR_DNS_NO_MEMORY;
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)) {
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;
67
if (!(req = TALLOC_ZERO_P(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))) {
71
return ERROR_DNS_NO_MEMORY;
75
req->flags = 0x2800; /* Dynamic update */
80
err = dns_domain_name_from_string(z, name, &z->name);
81
if (!ERR_DNS_IS_OK(err)) {
86
z->z_type = QTYPE_SOA;
87
z->z_class = DNS_CLASS_IN;
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)
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))) {
112
rec->r_class = r_class;
114
rec->data_length = data_length;
115
rec->data = talloc_move(rec, &data);
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)
129
if (pss->ss_family != AF_INET) {
130
/* Silently ignore this. */
131
return ERROR_DNS_SUCCESS;
134
ip = ((struct sockaddr_in *)pss)->sin_addr;
135
if (!(data = (uint8 *)TALLOC_MEMDUP(mem_ctx, (const void *)&ip.s_addr,
136
sizeof(ip.s_addr)))) {
137
return ERROR_DNS_NO_MEMORY;
140
err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
141
sizeof(ip.s_addr), data, prec);
143
if (!ERR_DNS_IS_OK(err)) {
150
DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
152
const struct sockaddr_storage *ss,
153
struct dns_rrec **prec)
156
return dns_create_a_record(mem_ctx, name, 0, ss, prec);
159
return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0,
163
DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx,
164
const char *name, uint32 type,
165
struct dns_rrec **prec)
167
return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0,
171
DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name,
172
uint16 type, uint16 r_class,
173
struct dns_rrec **prec)
175
return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec);
178
DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname,
179
const char *algorithm_name, time_t inception,
180
time_t expiration, uint16 mode, uint16 error,
181
uint16 key_length, const uint8 *key,
182
struct dns_rrec **prec)
184
struct dns_buffer *buf;
185
struct dns_domain_name *algorithm;
188
if (!(buf = dns_create_buffer(mem_ctx))) {
189
return ERROR_DNS_NO_MEMORY;
192
err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
193
if (!ERR_DNS_IS_OK(err)) goto error;
195
dns_marshall_domain_name(buf, algorithm);
196
dns_marshall_uint32(buf, inception);
197
dns_marshall_uint32(buf, expiration);
198
dns_marshall_uint16(buf, mode);
199
dns_marshall_uint16(buf, error);
200
dns_marshall_uint16(buf, key_length);
201
dns_marshall_buffer(buf, key, key_length);
202
dns_marshall_uint16(buf, 0); /* Other Size */
204
if (!ERR_DNS_IS_OK(buf->error)) {
209
err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0,
210
buf->offset, buf->data, prec);
217
DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
218
struct dns_tkey_record **ptkey)
220
struct dns_tkey_record *tkey;
221
struct dns_buffer buf;
222
uint32 tmp_inception, tmp_expiration;
224
if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) {
225
return ERROR_DNS_NO_MEMORY;
228
buf.data = rec->data;
229
buf.size = rec->data_length;
231
buf.error = ERROR_DNS_SUCCESS;
233
dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm);
234
dns_unmarshall_uint32(&buf, &tmp_inception);
235
dns_unmarshall_uint32(&buf, &tmp_expiration);
236
dns_unmarshall_uint16(&buf, &tkey->mode);
237
dns_unmarshall_uint16(&buf, &tkey->error);
238
dns_unmarshall_uint16(&buf, &tkey->key_length);
240
if (!ERR_DNS_IS_OK(buf.error)) goto error;
242
if (tkey->key_length) {
243
if (!(tkey->key = TALLOC_ARRAY(tkey, uint8, tkey->key_length))) {
244
buf.error = ERROR_DNS_NO_MEMORY;
251
dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
252
if (!ERR_DNS_IS_OK(buf.error)) goto error;
254
tkey->inception = (time_t)tmp_inception;
255
tkey->expiration = (time_t)tmp_expiration;
258
return ERROR_DNS_SUCCESS;
265
DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
266
const char *algorithm_name,
267
time_t time_signed, uint16 fudge,
268
uint16 mac_length, const uint8 *mac,
269
uint16 original_id, uint16 error,
270
struct dns_rrec **prec)
272
struct dns_buffer *buf;
273
struct dns_domain_name *algorithm;
276
if (!(buf = dns_create_buffer(mem_ctx))) {
277
return ERROR_DNS_NO_MEMORY;
280
err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
281
if (!ERR_DNS_IS_OK(err)) goto error;
283
dns_marshall_domain_name(buf, algorithm);
284
dns_marshall_uint16(buf, 0); /* time prefix */
285
dns_marshall_uint32(buf, time_signed);
286
dns_marshall_uint16(buf, fudge);
287
dns_marshall_uint16(buf, mac_length);
288
dns_marshall_buffer(buf, mac, mac_length);
289
dns_marshall_uint16(buf, original_id);
290
dns_marshall_uint16(buf, error);
291
dns_marshall_uint16(buf, 0); /* Other Size */
293
if (!ERR_DNS_IS_OK(buf->error)) {
298
err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
299
buf->offset, buf->data, prec);
306
DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
307
uint16 *num_records, struct dns_rrec ***records)
309
struct dns_rrec **new_records;
311
if (!(new_records = TALLOC_REALLOC_ARRAY(mem_ctx, *records,
313
(*num_records)+1))) {
314
return ERROR_DNS_NO_MEMORY;
317
new_records[*num_records] = talloc_move(new_records, &rec);
320
*records = new_records;
321
return ERROR_DNS_SUCCESS;
325
* Create a request that probes a server whether the list of IP addresses
326
* provides meets our expectations
329
DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
330
const char *host, int num_ips,
331
const struct sockaddr_storage *sslist,
332
struct dns_update_request **preq)
334
struct dns_update_request *req;
335
struct dns_rrec *rec;
339
err = dns_create_update(mem_ctx, zone, &req);
340
if (!ERR_DNS_IS_OK(err)) goto error;
342
err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
343
if (!ERR_DNS_IS_OK(err)) goto error;
345
err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
346
if (!ERR_DNS_IS_OK(err)) goto error;
348
for (i=0; i<num_ips; i++) {
349
err = dns_create_name_in_use_record(req, host,
351
if (!ERR_DNS_IS_OK(err)) goto error;
353
err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
354
if (!ERR_DNS_IS_OK(err)) goto error;
358
return ERROR_DNS_SUCCESS;
365
DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
366
const char *domainname,
367
const char *hostname,
368
const struct sockaddr_storage *ss_addrs,
370
struct dns_update_request **preq)
372
struct dns_update_request *req;
373
struct dns_rrec *rec;
377
err = dns_create_update(mem_ctx, domainname, &req);
378
if (!ERR_DNS_IS_OK(err)) return err;
381
* Use the same prereq as WinXP -- No CNAME records for this host.
384
err = dns_create_rrec(req, hostname, QTYPE_CNAME, DNS_CLASS_NONE,
386
if (!ERR_DNS_IS_OK(err)) goto error;
388
err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
389
if (!ERR_DNS_IS_OK(err)) goto error;
392
* Delete any existing A records
395
err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY,
397
if (!ERR_DNS_IS_OK(err)) goto error;
399
err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
400
if (!ERR_DNS_IS_OK(err)) goto error;
406
for ( i=0; i<num_addrs; i++ ) {
407
err = dns_create_a_record(req, hostname, 3600, &ss_addrs[i], &rec);
408
if (!ERR_DNS_IS_OK(err))
411
err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
412
if (!ERR_DNS_IS_OK(err))
417
return ERROR_DNS_SUCCESS;