4 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: byaddr.c,v 1.41 2009/09/02 23:48:02 tbox Exp */
27 #include <isc/netaddr.h>
28 #include <isc/print.h>
29 #include <isc/string.h> /* Required for HP/UX (and others?) */
33 #include <dns/byaddr.h>
35 #include <dns/events.h>
36 #include <dns/lookup.h>
37 #include <dns/rdata.h>
38 #include <dns/rdataset.h>
39 #include <dns/rdatastruct.h>
40 #include <dns/resolver.h>
41 #include <dns/result.h>
45 * XXXRTH We could use a static event...
48 static char hex_digits
[] = {
49 '0', '1', '2', '3', '4', '5', '6', '7',
50 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
54 dns_byaddr_createptrname(isc_netaddr_t
*address
, isc_boolean_t nibble
,
58 * We dropped bitstring labels, so all lookups will use nibbles.
62 return (dns_byaddr_createptrname2(address
,
63 DNS_BYADDROPT_IPV6INT
, name
));
67 dns_byaddr_createptrname2(isc_netaddr_t
*address
, unsigned int options
,
77 REQUIRE(address
!= NULL
);
80 * We create the text representation and then convert to a
81 * dns_name_t. This is not maximally efficient, but it keeps all
82 * of the knowledge of wire format in the dns_name_ routines.
85 bytes
= (unsigned char *)(&address
->type
);
86 if (address
->family
== AF_INET
) {
87 (void)snprintf(textname
, sizeof(textname
),
88 "%u.%u.%u.%u.in-addr.arpa.",
93 } else if (address
->family
== AF_INET6
) {
95 for (i
= 15; i
>= 0; i
--) {
96 *cp
++ = hex_digits
[bytes
[i
] & 0x0f];
98 *cp
++ = hex_digits
[(bytes
[i
] >> 4) & 0x0f];
101 if ((options
& DNS_BYADDROPT_IPV6INT
) != 0)
102 strcpy(cp
, "ip6.int.");
104 strcpy(cp
, "ip6.arpa.");
106 return (ISC_R_NOTIMPLEMENTED
);
108 len
= (unsigned int)strlen(textname
);
109 isc_buffer_init(&buffer
, textname
, len
);
110 isc_buffer_add(&buffer
, len
);
111 return (dns_name_fromtext(name
, &buffer
, dns_rootname
, 0, NULL
));
120 dns_fixedname_t name
;
121 /* Locked by lock. */
122 unsigned int options
;
123 dns_lookup_t
* lookup
;
125 dns_byaddrevent_t
* event
;
126 isc_boolean_t canceled
;
129 #define BYADDR_MAGIC ISC_MAGIC('B', 'y', 'A', 'd')
130 #define VALID_BYADDR(b) ISC_MAGIC_VALID(b, BYADDR_MAGIC)
132 #define MAX_RESTARTS 16
134 static inline isc_result_t
135 copy_ptr_targets(dns_byaddr_t
*byaddr
, dns_rdataset_t
*rdataset
) {
138 dns_rdata_t rdata
= DNS_RDATA_INIT
;
141 * The caller must be holding the byaddr's lock.
144 result
= dns_rdataset_first(rdataset
);
145 while (result
== ISC_R_SUCCESS
) {
147 dns_rdataset_current(rdataset
, &rdata
);
148 result
= dns_rdata_tostruct(&rdata
, &ptr
, NULL
);
149 if (result
!= ISC_R_SUCCESS
)
151 name
= isc_mem_get(byaddr
->mctx
, sizeof(*name
));
153 dns_rdata_freestruct(&ptr
);
154 return (ISC_R_NOMEMORY
);
156 dns_name_init(name
, NULL
);
157 result
= dns_name_dup(&ptr
.ptr
, byaddr
->mctx
, name
);
158 dns_rdata_freestruct(&ptr
);
159 if (result
!= ISC_R_SUCCESS
) {
160 isc_mem_put(byaddr
->mctx
, name
, sizeof(*name
));
161 return (ISC_R_NOMEMORY
);
163 ISC_LIST_APPEND(byaddr
->event
->names
, name
, link
);
164 dns_rdata_reset(&rdata
);
165 result
= dns_rdataset_next(rdataset
);
167 if (result
== ISC_R_NOMORE
)
168 result
= ISC_R_SUCCESS
;
174 lookup_done(isc_task_t
*task
, isc_event_t
*event
) {
175 dns_byaddr_t
*byaddr
= event
->ev_arg
;
176 dns_lookupevent_t
*levent
;
179 REQUIRE(event
->ev_type
== DNS_EVENT_LOOKUPDONE
);
180 REQUIRE(VALID_BYADDR(byaddr
));
181 REQUIRE(byaddr
->task
== task
);
185 levent
= (dns_lookupevent_t
*)event
;
187 if (levent
->result
== ISC_R_SUCCESS
) {
188 result
= copy_ptr_targets(byaddr
, levent
->rdataset
);
189 byaddr
->event
->result
= result
;
191 byaddr
->event
->result
= levent
->result
;
192 isc_event_free(&event
);
193 isc_task_sendanddetach(&byaddr
->task
, (isc_event_t
**)&byaddr
->event
);
197 bevent_destroy(isc_event_t
*event
) {
198 dns_byaddrevent_t
*bevent
;
199 dns_name_t
*name
, *next_name
;
202 REQUIRE(event
->ev_type
== DNS_EVENT_BYADDRDONE
);
203 mctx
= event
->ev_destroy_arg
;
204 bevent
= (dns_byaddrevent_t
*)event
;
206 for (name
= ISC_LIST_HEAD(bevent
->names
);
209 next_name
= ISC_LIST_NEXT(name
, link
);
210 ISC_LIST_UNLINK(bevent
->names
, name
, link
);
211 dns_name_free(name
, mctx
);
212 isc_mem_put(mctx
, name
, sizeof(*name
));
214 isc_mem_put(mctx
, event
, event
->ev_size
);
218 dns_byaddr_create(isc_mem_t
*mctx
, isc_netaddr_t
*address
, dns_view_t
*view
,
219 unsigned int options
, isc_task_t
*task
,
220 isc_taskaction_t action
, void *arg
, dns_byaddr_t
**byaddrp
)
223 dns_byaddr_t
*byaddr
;
226 byaddr
= isc_mem_get(mctx
, sizeof(*byaddr
));
228 return (ISC_R_NOMEMORY
);
230 byaddr
->options
= options
;
232 byaddr
->event
= isc_mem_get(mctx
, sizeof(*byaddr
->event
));
233 if (byaddr
->event
== NULL
) {
234 result
= ISC_R_NOMEMORY
;
237 ISC_EVENT_INIT(byaddr
->event
, sizeof(*byaddr
->event
), 0, NULL
,
238 DNS_EVENT_BYADDRDONE
, action
, arg
, byaddr
,
239 bevent_destroy
, mctx
);
240 byaddr
->event
->result
= ISC_R_FAILURE
;
241 ISC_LIST_INIT(byaddr
->event
->names
);
244 isc_task_attach(task
, &byaddr
->task
);
246 result
= isc_mutex_init(&byaddr
->lock
);
247 if (result
!= ISC_R_SUCCESS
)
250 dns_fixedname_init(&byaddr
->name
);
252 result
= dns_byaddr_createptrname2(address
, options
,
253 dns_fixedname_name(&byaddr
->name
));
254 if (result
!= ISC_R_SUCCESS
)
257 byaddr
->lookup
= NULL
;
258 result
= dns_lookup_create(mctx
, dns_fixedname_name(&byaddr
->name
),
259 dns_rdatatype_ptr
, view
, 0, task
,
260 lookup_done
, byaddr
, &byaddr
->lookup
);
261 if (result
!= ISC_R_SUCCESS
)
264 byaddr
->canceled
= ISC_FALSE
;
265 byaddr
->magic
= BYADDR_MAGIC
;
269 return (ISC_R_SUCCESS
);
272 DESTROYLOCK(&byaddr
->lock
);
275 ievent
= (isc_event_t
*)byaddr
->event
;
276 isc_event_free(&ievent
);
277 byaddr
->event
= NULL
;
279 isc_task_detach(&byaddr
->task
);
282 isc_mem_put(mctx
, byaddr
, sizeof(*byaddr
));
288 dns_byaddr_cancel(dns_byaddr_t
*byaddr
) {
289 REQUIRE(VALID_BYADDR(byaddr
));
293 if (!byaddr
->canceled
) {
294 byaddr
->canceled
= ISC_TRUE
;
295 if (byaddr
->lookup
!= NULL
)
296 dns_lookup_cancel(byaddr
->lookup
);
299 UNLOCK(&byaddr
->lock
);
303 dns_byaddr_destroy(dns_byaddr_t
**byaddrp
) {
304 dns_byaddr_t
*byaddr
;
306 REQUIRE(byaddrp
!= NULL
);
308 REQUIRE(VALID_BYADDR(byaddr
));
309 REQUIRE(byaddr
->event
== NULL
);
310 REQUIRE(byaddr
->task
== NULL
);
311 dns_lookup_destroy(&byaddr
->lookup
);
313 DESTROYLOCK(&byaddr
->lock
);
315 isc_mem_put(byaddr
->mctx
, byaddr
, sizeof(*byaddr
));