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
;