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, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
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
;
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
))) {
41 return ERROR_DNS_NO_MEMORY
;
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
)) {
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
;
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
))) {
73 return ERROR_DNS_NO_MEMORY
;
77 req
->flags
= 0x2800; /* Dynamic update */
82 err
= dns_domain_name_from_string(z
, name
, &z
->name
);
83 if (!ERR_DNS_IS_OK(err
)) {
88 z
->z_type
= QTYPE_SOA
;
89 z
->z_class
= DNS_CLASS_IN
;
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
;
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
))) {
114 rec
->r_class
= r_class
;
116 rec
->data_length
= data_length
;
117 rec
->data
= talloc_move(rec
, &data
);
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
)
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
)) {
145 DNS_ERROR
dns_create_name_in_use_record(TALLOC_CTX
*mem_ctx
,
147 const struct in_addr
*ip
,
148 struct dns_rrec
**prec
)
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,
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,
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
;
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
)) {
204 err
= dns_create_rrec(mem_ctx
, keyname
, QTYPE_TKEY
, DNS_CLASS_ANY
, 0,
205 buf
->offset
, buf
->data
, prec
);
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
;
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
;
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
;
253 return ERROR_DNS_SUCCESS
;
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
;
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
)) {
293 err
= dns_create_rrec(mem_ctx
, keyname
, QTYPE_TSIG
, DNS_CLASS_ANY
, 0,
294 buf
->offset
, buf
->data
, prec
);
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
,
308 (*num_records
)+1))) {
309 return ERROR_DNS_NO_MEMORY
;
312 new_records
[*num_records
] = talloc_move(new_records
, &rec
);
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
;
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
,
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
;
353 return ERROR_DNS_SUCCESS
;
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
,
365 struct dns_update_request
**preq
)
367 struct dns_update_request
*req
;
368 struct dns_rrec
*rec
;
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
,
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
,
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
;
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
))
406 err
= dns_add_rrec(req
, rec
, &req
->num_updates
, &req
->updates
);
407 if (!ERR_DNS_IS_OK(err
))
412 return ERROR_DNS_SUCCESS
;