2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: byaddr.c,v 1.29.2.1.2.8 2004/08/28 06:25:18 marka Exp $ */
23 #include <isc/netaddr.h>
24 #include <isc/print.h>
25 #include <isc/string.h> /* Required for HP/UX (and others?) */
29 #include <dns/byaddr.h>
31 #include <dns/events.h>
32 #include <dns/lookup.h>
33 #include <dns/rdata.h>
34 #include <dns/rdataset.h>
35 #include <dns/rdatastruct.h>
36 #include <dns/resolver.h>
37 #include <dns/result.h>
41 * XXXRTH We could use a static event...
52 dns_lookup_t
* lookup
;
54 dns_byaddrevent_t
* event
;
55 isc_boolean_t canceled
;
58 #define BYADDR_MAGIC ISC_MAGIC('B', 'y', 'A', 'd')
59 #define VALID_BYADDR(b) ISC_MAGIC_VALID(b, BYADDR_MAGIC)
61 #define MAX_RESTARTS 16
63 static char hex_digits
[] = {
64 '0', '1', '2', '3', '4', '5', '6', '7',
65 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
69 dns_byaddr_createptrname(isc_netaddr_t
*address
, isc_boolean_t nibble
,
73 * We dropped bitstring labels, so all lookups will use nibbles.
77 return (dns_byaddr_createptrname2(address
,
78 DNS_BYADDROPT_IPV6INT
, name
));
82 dns_byaddr_createptrname2(isc_netaddr_t
*address
, unsigned int options
,
92 REQUIRE(address
!= NULL
);
95 * We create the text representation and then convert to a
96 * dns_name_t. This is not maximally efficient, but it keeps all
97 * of the knowledge of wire format in the dns_name_ routines.
100 bytes
= (unsigned char *)(&address
->type
);
101 if (address
->family
== AF_INET
) {
102 (void)snprintf(textname
, sizeof(textname
),
103 "%u.%u.%u.%u.in-addr.arpa.",
108 } else if (address
->family
== AF_INET6
) {
110 for (i
= 15; i
>= 0; i
--) {
111 *cp
++ = hex_digits
[bytes
[i
] & 0x0f];
113 *cp
++ = hex_digits
[(bytes
[i
] >> 4) & 0x0f];
116 if ((options
& DNS_BYADDROPT_IPV6INT
) != 0)
117 strcpy(cp
, "ip6.int.");
119 strcpy(cp
, "ip6.arpa.");
121 return (ISC_R_NOTIMPLEMENTED
);
123 len
= (unsigned int)strlen(textname
);
124 isc_buffer_init(&buffer
, textname
, len
);
125 isc_buffer_add(&buffer
, len
);
126 return (dns_name_fromtext(name
, &buffer
, dns_rootname
,
130 static inline isc_result_t
131 copy_ptr_targets(dns_byaddr_t
*byaddr
, dns_rdataset_t
*rdataset
) {
134 dns_rdata_t rdata
= DNS_RDATA_INIT
;
137 * The caller must be holding the byaddr's lock.
140 result
= dns_rdataset_first(rdataset
);
141 while (result
== ISC_R_SUCCESS
) {
143 dns_rdataset_current(rdataset
, &rdata
);
144 result
= dns_rdata_tostruct(&rdata
, &ptr
, NULL
);
145 if (result
!= ISC_R_SUCCESS
)
147 name
= isc_mem_get(byaddr
->mctx
, sizeof(*name
));
149 dns_rdata_freestruct(&ptr
);
150 return (ISC_R_NOMEMORY
);
152 dns_name_init(name
, NULL
);
153 result
= dns_name_dup(&ptr
.ptr
, byaddr
->mctx
, name
);
154 dns_rdata_freestruct(&ptr
);
155 if (result
!= ISC_R_SUCCESS
) {
156 isc_mem_put(byaddr
->mctx
, name
, sizeof(*name
));
157 return (ISC_R_NOMEMORY
);
159 ISC_LIST_APPEND(byaddr
->event
->names
, name
, link
);
160 dns_rdata_reset(&rdata
);
161 result
= dns_rdataset_next(rdataset
);
163 if (result
== ISC_R_NOMORE
)
164 result
= ISC_R_SUCCESS
;
170 lookup_done(isc_task_t
*task
, isc_event_t
*event
) {
171 dns_byaddr_t
*byaddr
= event
->ev_arg
;
172 dns_lookupevent_t
*levent
;
175 REQUIRE(event
->ev_type
== DNS_EVENT_LOOKUPDONE
);
176 REQUIRE(VALID_BYADDR(byaddr
));
177 REQUIRE(byaddr
->task
== task
);
181 levent
= (dns_lookupevent_t
*)event
;
183 if (levent
->result
== ISC_R_SUCCESS
) {
184 result
= copy_ptr_targets(byaddr
, levent
->rdataset
);
185 byaddr
->event
->result
= result
;
187 byaddr
->event
->result
= levent
->result
;
188 isc_event_free(&event
);
189 isc_task_sendanddetach(&byaddr
->task
, (isc_event_t
**)&byaddr
->event
);
193 bevent_destroy(isc_event_t
*event
) {
194 dns_byaddrevent_t
*bevent
;
195 dns_name_t
*name
, *next_name
;
198 REQUIRE(event
->ev_type
== DNS_EVENT_BYADDRDONE
);
199 mctx
= event
->ev_destroy_arg
;
200 bevent
= (dns_byaddrevent_t
*)event
;
202 for (name
= ISC_LIST_HEAD(bevent
->names
);
205 next_name
= ISC_LIST_NEXT(name
, link
);
206 ISC_LIST_UNLINK(bevent
->names
, name
, link
);
207 dns_name_free(name
, mctx
);
208 isc_mem_put(mctx
, name
, sizeof(*name
));
210 isc_mem_put(mctx
, event
, event
->ev_size
);
214 dns_byaddr_create(isc_mem_t
*mctx
, isc_netaddr_t
*address
, dns_view_t
*view
,
215 unsigned int options
, isc_task_t
*task
,
216 isc_taskaction_t action
, void *arg
, dns_byaddr_t
**byaddrp
)
219 dns_byaddr_t
*byaddr
;
222 byaddr
= isc_mem_get(mctx
, sizeof(*byaddr
));
224 return (ISC_R_NOMEMORY
);
226 byaddr
->options
= options
;
228 byaddr
->event
= isc_mem_get(mctx
, sizeof(*byaddr
->event
));
229 if (byaddr
->event
== NULL
) {
230 result
= ISC_R_NOMEMORY
;
233 ISC_EVENT_INIT(byaddr
->event
, sizeof(*byaddr
->event
), 0, NULL
,
234 DNS_EVENT_BYADDRDONE
, action
, arg
, byaddr
,
235 bevent_destroy
, mctx
);
236 byaddr
->event
->result
= ISC_R_FAILURE
;
237 ISC_LIST_INIT(byaddr
->event
->names
);
240 isc_task_attach(task
, &byaddr
->task
);
242 result
= isc_mutex_init(&byaddr
->lock
);
243 if (result
!= ISC_R_SUCCESS
)
246 dns_fixedname_init(&byaddr
->name
);
248 result
= dns_byaddr_createptrname2(address
, options
,
249 dns_fixedname_name(&byaddr
->name
));
250 if (result
!= ISC_R_SUCCESS
)
253 byaddr
->lookup
= NULL
;
254 result
= dns_lookup_create(mctx
, dns_fixedname_name(&byaddr
->name
),
255 dns_rdatatype_ptr
, view
, 0, task
,
256 lookup_done
, byaddr
, &byaddr
->lookup
);
257 if (result
!= ISC_R_SUCCESS
)
260 byaddr
->canceled
= ISC_FALSE
;
261 byaddr
->magic
= BYADDR_MAGIC
;
265 return (ISC_R_SUCCESS
);
268 DESTROYLOCK(&byaddr
->lock
);
271 ievent
= (isc_event_t
*)byaddr
->event
;
272 isc_event_free(&ievent
);
273 byaddr
->event
= NULL
;
275 isc_task_detach(&byaddr
->task
);
278 isc_mem_put(mctx
, byaddr
, sizeof(*byaddr
));
284 dns_byaddr_cancel(dns_byaddr_t
*byaddr
) {
285 REQUIRE(VALID_BYADDR(byaddr
));
289 if (!byaddr
->canceled
) {
290 byaddr
->canceled
= ISC_TRUE
;
291 if (byaddr
->lookup
!= NULL
)
292 dns_lookup_cancel(byaddr
->lookup
);
295 UNLOCK(&byaddr
->lock
);
299 dns_byaddr_destroy(dns_byaddr_t
**byaddrp
) {
300 dns_byaddr_t
*byaddr
;
302 REQUIRE(byaddrp
!= NULL
);
304 REQUIRE(VALID_BYADDR(byaddr
));
305 REQUIRE(byaddr
->event
== NULL
);
306 REQUIRE(byaddr
->task
== NULL
);
307 dns_lookup_destroy(&byaddr
->lookup
);
309 DESTROYLOCK(&byaddr
->lock
);
311 isc_mem_put(byaddr
->mctx
, byaddr
, sizeof(*byaddr
));