2 * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or 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: lwdgnba.c,v 1.20.130.2 2008/01/14 23:46:28 tbox Exp $ */
24 #include <isc/socket.h>
25 #include <isc/string.h> /* Required for HP/UX (and others?) */
29 #include <dns/byaddr.h>
30 #include <dns/result.h>
32 #include <named/types.h>
33 #include <named/lwdclient.h>
35 static void start_byaddr(ns_lwdclient_t
*);
38 byaddr_done(isc_task_t
*task
, isc_event_t
*event
) {
39 ns_lwdclient_t
*client
;
40 ns_lwdclientmgr_t
*cm
;
41 dns_byaddrevent_t
*bevent
;
46 lwres_result_t lwresult
;
49 lwres_gnbaresponse_t
*gnba
;
50 isc_uint16_t naliases
;
55 client
= event
->ev_arg
;
56 cm
= client
->clientmgr
;
57 INSIST(client
->byaddr
== (dns_byaddr_t
*)event
->ev_sender
);
59 bevent
= (dns_byaddrevent_t
*)event
;
62 ns_lwdclient_log(50, "byaddr event result = %s",
63 isc_result_totext(bevent
->result
));
65 result
= bevent
->result
;
66 if (result
!= ISC_R_SUCCESS
) {
67 dns_byaddr_destroy(&client
->byaddr
);
68 isc_event_free(&event
);
71 if (client
->na
.family
!= AF_INET6
||
72 (client
->options
& DNS_BYADDROPT_IPV6INT
) != 0) {
73 if (result
== DNS_R_NCACHENXDOMAIN
||
74 result
== DNS_R_NCACHENXRRSET
||
75 result
== DNS_R_NXDOMAIN
||
76 result
== DNS_R_NXRRSET
)
77 lwresult
= LWRES_R_NOTFOUND
;
79 lwresult
= LWRES_R_FAILURE
;
80 ns_lwdclient_errorpktsend(client
, lwresult
);
85 * Fall back to ip6.int reverse if the default ip6.arpa
88 client
->options
|= DNS_BYADDROPT_IPV6INT
;
94 for (name
= ISC_LIST_HEAD(bevent
->names
);
96 name
= ISC_LIST_NEXT(name
, link
))
98 b
= client
->recv_buffer
;
100 result
= dns_name_totext(name
, ISC_TRUE
, &client
->recv_buffer
);
101 if (result
!= ISC_R_SUCCESS
)
103 ns_lwdclient_log(50, "found name '%.*s'",
104 (int)(client
->recv_buffer
.used
- b
.used
),
105 (char *)(b
.base
) + b
.used
);
106 if (gnba
->realname
== NULL
) {
107 gnba
->realname
= (char *)(b
.base
) + b
.used
;
108 gnba
->realnamelen
= client
->recv_buffer
.used
- b
.used
;
110 naliases
= gnba
->naliases
;
111 if (naliases
>= LWRES_MAX_ALIASES
)
113 gnba
->aliases
[naliases
] = (char *)(b
.base
) + b
.used
;
114 gnba
->aliaslen
[naliases
] =
115 client
->recv_buffer
.used
- b
.used
;
120 dns_byaddr_destroy(&client
->byaddr
);
121 isc_event_free(&event
);
126 client
->pkt
.recvlength
= LWRES_RECVLENGTH
;
127 client
->pkt
.authtype
= 0; /* XXXMLG */
128 client
->pkt
.authlength
= 0;
129 client
->pkt
.result
= LWRES_R_SUCCESS
;
131 lwres
= lwres_gnbaresponse_render(cm
->lwctx
,
132 gnba
, &client
->pkt
, &lwb
);
133 if (lwres
!= LWRES_R_SUCCESS
)
138 client
->sendbuf
= r
.base
;
139 client
->sendlength
= r
.length
;
140 result
= ns_lwdclient_sendreply(client
, &r
);
141 if (result
!= ISC_R_SUCCESS
)
144 NS_LWDCLIENT_SETSEND(client
);
149 if (client
->byaddr
!= NULL
)
150 dns_byaddr_destroy(&client
->byaddr
);
151 if (lwb
.base
!= NULL
)
152 lwres_context_freemem(cm
->lwctx
,
153 lwb
.base
, lwb
.length
);
156 isc_event_free(&event
);
160 start_byaddr(ns_lwdclient_t
*client
) {
162 ns_lwdclientmgr_t
*cm
;
164 cm
= client
->clientmgr
;
166 INSIST(client
->byaddr
== NULL
);
168 result
= dns_byaddr_create(cm
->mctx
, &client
->na
, cm
->view
,
169 client
->options
, cm
->task
, byaddr_done
,
170 client
, &client
->byaddr
);
171 if (result
!= ISC_R_SUCCESS
) {
172 ns_lwdclient_errorpktsend(client
, LWRES_R_FAILURE
);
178 init_gnba(ns_lwdclient_t
*client
) {
182 * Initialize the real name and alias arrays in the reply we're
185 for (i
= 0; i
< LWRES_MAX_ALIASES
; i
++) {
186 client
->aliases
[i
] = NULL
;
187 client
->aliaslen
[i
] = 0;
189 for (i
= 0; i
< LWRES_MAX_ADDRS
; i
++) {
190 client
->addrs
[i
].family
= 0;
191 client
->addrs
[i
].length
= 0;
192 memset(client
->addrs
[i
].address
, 0, LWRES_ADDR_MAXLEN
);
193 LWRES_LINK_INIT(&client
->addrs
[i
], link
);
196 client
->gnba
.naliases
= 0;
197 client
->gnba
.realname
= NULL
;
198 client
->gnba
.aliases
= client
->aliases
;
199 client
->gnba
.realnamelen
= 0;
200 client
->gnba
.aliaslen
= client
->aliaslen
;
201 client
->gnba
.base
= NULL
;
202 client
->gnba
.baselen
= 0;
203 isc_buffer_init(&client
->recv_buffer
, client
->buffer
, LWRES_RECVLENGTH
);
207 ns_lwdclient_processgnba(ns_lwdclient_t
*client
, lwres_buffer_t
*b
) {
208 lwres_gnbarequest_t
*req
;
211 ns_lwdclientmgr_t
*cm
;
213 REQUIRE(NS_LWDCLIENT_ISRECVDONE(client
));
214 INSIST(client
->byaddr
== NULL
);
216 cm
= client
->clientmgr
;
219 result
= lwres_gnbarequest_parse(cm
->lwctx
,
220 b
, &client
->pkt
, &req
);
221 if (result
!= LWRES_R_SUCCESS
)
225 if (req
->addr
.family
== LWRES_ADDRTYPE_V4
) {
226 client
->na
.family
= AF_INET
;
227 if (req
->addr
.length
!= 4)
229 memcpy(&client
->na
.type
.in
, req
->addr
.address
, 4);
230 } else if (req
->addr
.family
== LWRES_ADDRTYPE_V6
) {
231 client
->na
.family
= AF_INET6
;
232 if (req
->addr
.length
!= 16)
234 memcpy(&client
->na
.type
.in6
, req
->addr
.address
, 16);
238 isc_sockaddr_fromnetaddr(&sa
, &client
->na
, 53);
240 ns_lwdclient_log(50, "client %p looking for addrtype %08x",
241 client
, req
->addr
.family
);
244 * We no longer need to keep this around.
246 lwres_gnbarequest_free(cm
->lwctx
, &req
);
249 * Initialize the real name and alias arrays in the reply we're
258 start_byaddr(client
);
263 * We're screwed. Return an error packet to our caller.
267 lwres_gnbarequest_free(cm
->lwctx
, &req
);
269 ns_lwdclient_errorpktsend(client
, LWRES_R_FAILURE
);