lwdgabn.c revision d7201de09b85929a86b157f4b2d91667c68c6b52
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff/*
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * Copyright (C) 2000, 2001 Internet Software Consortium.
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff *
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * Permission to use, copy, modify, and/or distribute this software for any
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * purpose with or without fee is hereby granted, provided that the above
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * copyright notice and this permission notice appear in all copies.
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff *
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * PERFORMANCE OF THIS SOFTWARE.
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff */
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff/* $Id: lwdgabn.c,v 1.24 2009/09/02 23:48:01 tbox Exp $ */
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff/*! \file */
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff#include <config.h>
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff#include <stdlib.h>
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff#include <isc/netaddr.h>
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff#include <isc/sockaddr.h>
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff#include <isc/socket.h>
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff#include <isc/string.h> /* Required for HP/UX (and others?) */
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff#include <isc/util.h>
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff#include <dns/adb.h>
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff#include <dns/events.h>
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff#include <dns/result.h>
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff#include <named/types.h>
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff#include <named/lwaddr.h>
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff#include <named/lwdclient.h>
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff#include <named/lwresd.h>
3ac63b472022ff92691d1fe69ac715a729671965Michael Graff#include <named/lwsearch.h>
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff#include <named/sortlist.h>
e45d323a2a0f4ca08d4b139546e60a5fa7bd3f0cMichael Graff
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff#define NEED_V4(c) ((((c)->find_wanted & LWRES_ADDRTYPE_V4) != 0) \
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff && ((c)->v4find == NULL))
11efdeb076d65fa9f0c5fc067dc040e7c99dfba6Michael Graff#define NEED_V6(c) ((((c)->find_wanted & LWRES_ADDRTYPE_V6) != 0) \
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff && ((c)->v6find == NULL))
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graffstatic isc_result_t start_find(ns_lwdclient_t *);
11efdeb076d65fa9f0c5fc067dc040e7c99dfba6Michael Graffstatic void restart_find(ns_lwdclient_t *);
11efdeb076d65fa9f0c5fc067dc040e7c99dfba6Michael Graffstatic void init_gabn(ns_lwdclient_t *);
439c0011e642fb1d26011116144af698125262dbMichael Graff
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff/*%
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * Destroy any finds. This can be used to "start over from scratch" and
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * should only be called when events are _not_ being generated by the finds.
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff */
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graffstatic void
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graffcleanup_gabn(ns_lwdclient_t *client) {
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff ns_lwdclient_log(50, "cleaning up client %p", client);
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff if (client->v6find != NULL) {
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff if (client->v6find == client->v4find)
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff client->v6find = NULL;
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff else
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff dns_adb_destroyfind(&client->v6find);
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff }
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff if (client->v4find != NULL)
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff dns_adb_destroyfind(&client->v4find);
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff}
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graff
31fab17bcdbe302592a6c0dc5374ef56333ee879Michael Graffstatic void
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graffsetup_addresses(ns_lwdclient_t *client, dns_adbfind_t *find, unsigned int at) {
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graff dns_adbaddrinfo_t *ai;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff lwres_addr_t *addr;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff int af;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff const struct sockaddr *sa;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff isc_result_t result;
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff if (at == DNS_ADBFIND_INET)
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff af = AF_INET;
3ac63b472022ff92691d1fe69ac715a729671965Michael Graff else
3ac63b472022ff92691d1fe69ac715a729671965Michael Graff af = AF_INET6;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff ai = ISC_LIST_HEAD(find->list);
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff while (ai != NULL && client->gabn.naddrs < LWRES_MAX_ADDRS) {
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff sa = &ai->sockaddr.type.sa;
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff if (sa->sa_family != af)
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff goto next;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff addr = &client->addrs[client->gabn.naddrs];
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff result = lwaddr_lwresaddr_fromsockaddr(addr, &ai->sockaddr);
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graff if (result != ISC_R_SUCCESS)
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff goto next;
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff ns_lwdclient_log(50, "adding address %p, family %d, length %d",
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff addr->address, addr->family, addr->length);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff client->gabn.naddrs++;
439c0011e642fb1d26011116144af698125262dbMichael Graff REQUIRE(!LWRES_LINK_LINKED(addr, link));
11efdeb076d65fa9f0c5fc067dc040e7c99dfba6Michael Graff LWRES_LIST_APPEND(client->gabn.addrs, addr, link);
3ac63b472022ff92691d1fe69ac715a729671965Michael Graff
11efdeb076d65fa9f0c5fc067dc040e7c99dfba6Michael Graff next:
3ac63b472022ff92691d1fe69ac715a729671965Michael Graff ai = ISC_LIST_NEXT(ai, publink);
3ac63b472022ff92691d1fe69ac715a729671965Michael Graff }
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff}
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Grafftypedef struct {
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff isc_netaddr_t address;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff int rank;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff} rankedaddress;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graffstatic int
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graffaddr_compare(const void *av, const void *bv) {
2992344aacdb08e4af936c176d49ef789f5673ddMichael Graff const rankedaddress *a = (const rankedaddress *) av;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff const rankedaddress *b = (const rankedaddress *) bv;
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graff return (a->rank - b->rank);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff}
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graffstatic void
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graffsort_addresses(ns_lwdclient_t *client) {
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff unsigned int naddrs;
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff rankedaddress *addrs;
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff isc_netaddr_t remote;
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff dns_addressorderfunc_t order;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff const void *arg;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff ns_lwresd_t *lwresd = client->clientmgr->listener->manager;
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff unsigned int i;
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff isc_result_t result;
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff naddrs = client->gabn.naddrs;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff if (naddrs <= 1 || lwresd->view->sortlist == NULL)
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff return;
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff addrs = isc_mem_get(lwresd->mctx, sizeof(rankedaddress) * naddrs);
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff if (addrs == NULL)
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff return;
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff isc_netaddr_fromsockaddr(&remote, &client->address);
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff ns_sortlist_byaddrsetup(lwresd->view->sortlist,
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff &remote, &order, &arg);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff if (order == NULL) {
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff isc_mem_put(lwresd->mctx, addrs,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff sizeof(rankedaddress) * naddrs);
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff return;
1f90c108282533a23b8362c34bcde4267c1eb4b1Michael Graff }
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff for (i = 0; i < naddrs; i++) {
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff result = lwaddr_netaddr_fromlwresaddr(&addrs[i].address,
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff &client->addrs[i]);
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff INSIST(result == ISC_R_SUCCESS);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff addrs[i].rank = (*order)(&addrs[i].address, arg);
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff }
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff qsort(addrs, naddrs, sizeof(rankedaddress), addr_compare);
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graff for (i = 0; i < naddrs; i++) {
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff result = lwaddr_lwresaddr_fromnetaddr(&client->addrs[i],
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff &addrs[i].address);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff INSIST(result == ISC_R_SUCCESS);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff }
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graff
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graff isc_mem_put(lwresd->mctx, addrs, sizeof(rankedaddress) * naddrs);
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graff}
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graff
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graffstatic void
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graffgenerate_reply(ns_lwdclient_t *client) {
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff isc_result_t result;
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graff int lwres;
bb143613cf26e0f27dfd9caf1a7336065d064b26Michael Graff isc_region_t r;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff lwres_buffer_t lwb;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff ns_lwdclientmgr_t *cm;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff cm = client->clientmgr;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff lwb.base = NULL;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff ns_lwdclient_log(50, "generating gabn reply for client %p", client);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff /*
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * We must make certain the client->find is not still active.
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff * If it is either the v4 or v6 answer, just set it to NULL and
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * let the cleanup code destroy it. Otherwise, destroy it now.
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff */
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff if (client->find == client->v4find || client->find == client->v6find)
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff client->find = NULL;
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff else
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff if (client->find != NULL)
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff dns_adb_destroyfind(&client->find);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff /*
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * perhaps there are some here?
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff */
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff if (NEED_V6(client) && client->v4find != NULL)
439c0011e642fb1d26011116144af698125262dbMichael Graff client->v6find = client->v4find;
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff /*
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff * Run through the finds we have and wire them up to the gabn
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * structure.
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff */
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff LWRES_LIST_INIT(client->gabn.addrs);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff if (client->v4find != NULL)
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff setup_addresses(client, client->v4find, DNS_ADBFIND_INET);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff if (client->v6find != NULL)
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff setup_addresses(client, client->v6find, DNS_ADBFIND_INET6);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff /*
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * If there are no addresses, try the next element in the search
439c0011e642fb1d26011116144af698125262dbMichael Graff * path, if there are any more. Otherwise, fall through into
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * the error handling code below.
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff */
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff if (client->gabn.naddrs == 0) {
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff do {
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff result = ns_lwsearchctx_next(&client->searchctx);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff if (result == ISC_R_SUCCESS) {
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff cleanup_gabn(client);
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff result = start_find(client);
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff if (result == ISC_R_SUCCESS)
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff return;
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff }
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff } while (result == ISC_R_SUCCESS);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff }
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff /*
439c0011e642fb1d26011116144af698125262dbMichael Graff * Render the packet.
439c0011e642fb1d26011116144af698125262dbMichael Graff */
439c0011e642fb1d26011116144af698125262dbMichael Graff client->pkt.recvlength = LWRES_RECVLENGTH;
439c0011e642fb1d26011116144af698125262dbMichael Graff client->pkt.authtype = 0; /* XXXMLG */
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graff client->pkt.authlength = 0;
439c0011e642fb1d26011116144af698125262dbMichael Graff
439c0011e642fb1d26011116144af698125262dbMichael Graff /*
439c0011e642fb1d26011116144af698125262dbMichael Graff * If there are no addresses, return failure.
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff */
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff if (client->gabn.naddrs != 0)
439c0011e642fb1d26011116144af698125262dbMichael Graff client->pkt.result = LWRES_R_SUCCESS;
439c0011e642fb1d26011116144af698125262dbMichael Graff else
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff client->pkt.result = LWRES_R_NOTFOUND;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff
439c0011e642fb1d26011116144af698125262dbMichael Graff sort_addresses(client);
439c0011e642fb1d26011116144af698125262dbMichael Graff
439c0011e642fb1d26011116144af698125262dbMichael Graff lwres = lwres_gabnresponse_render(cm->lwctx, &client->gabn,
439c0011e642fb1d26011116144af698125262dbMichael Graff &client->pkt, &lwb);
439c0011e642fb1d26011116144af698125262dbMichael Graff if (lwres != LWRES_R_SUCCESS)
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff goto out;
439c0011e642fb1d26011116144af698125262dbMichael Graff
439c0011e642fb1d26011116144af698125262dbMichael Graff r.base = lwb.base;
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff r.length = lwb.used;
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff client->sendbuf = r.base;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->sendlength = r.length;
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff result = ns_lwdclient_sendreply(client, &r);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff if (result != ISC_R_SUCCESS)
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff goto out;
439c0011e642fb1d26011116144af698125262dbMichael Graff
439c0011e642fb1d26011116144af698125262dbMichael Graff NS_LWDCLIENT_SETSEND(client);
439c0011e642fb1d26011116144af698125262dbMichael Graff
439c0011e642fb1d26011116144af698125262dbMichael Graff /*
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * All done!
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff */
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff cleanup_gabn(client);
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff return;
2992344aacdb08e4af936c176d49ef789f5673ddMichael Graff
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff out:
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff cleanup_gabn(client);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
3ac63b472022ff92691d1fe69ac715a729671965Michael Graff if (lwb.base != NULL)
651228967966ba4fb2e52f92d1207c790af4b130Michael Graff lwres_context_freemem(client->clientmgr->lwctx,
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff lwb.base, lwb.length);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff}
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff/*
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff * Take the current real name, move it to an alias slot (if any are
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff * open) then put this new name in as the real name for the target.
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff *
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff * Return success if it can be rendered, otherwise failure. Note that
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff * not having enough alias slots open is NOT a failure.
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff */
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graffstatic isc_result_t
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graffadd_alias(ns_lwdclient_t *client) {
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff isc_buffer_t b;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff isc_result_t result;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff isc_uint16_t naliases;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff b = client->recv_buffer;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff /*
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff * Render the new name to the buffer.
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff */
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff result = dns_name_totext(dns_fixedname_name(&client->target_name),
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff ISC_TRUE, &client->recv_buffer);
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff if (result != ISC_R_SUCCESS)
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff return (result);
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff /*
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff * Are there any open slots?
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff */
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff naliases = client->gabn.naliases;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff if (naliases < LWRES_MAX_ALIASES) {
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff client->gabn.aliases[naliases] = client->gabn.realname;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff client->gabn.aliaslen[naliases] = client->gabn.realnamelen;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff client->gabn.naliases++;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff }
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff /*
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff * Save this name away as the current real name.
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff */
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff client->gabn.realname = (char *)(b.base) + b.used;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff client->gabn.realnamelen = client->recv_buffer.used - b.used;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff return (ISC_R_SUCCESS);
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff}
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graffstatic isc_result_t
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graffstore_realname(ns_lwdclient_t *client) {
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff isc_buffer_t b;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff isc_result_t result;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff dns_name_t *tname;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff b = client->recv_buffer;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff tname = dns_fixedname_name(&client->target_name);
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff result = ns_lwsearchctx_current(&client->searchctx, tname);
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff if (result != ISC_R_SUCCESS)
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff return (result);
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff /*
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff * Render the new name to the buffer.
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff */
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff result = dns_name_totext(tname, ISC_TRUE, &client->recv_buffer);
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff if (result != ISC_R_SUCCESS)
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff return (result);
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff /*
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff * Save this name away as the current real name.
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff */
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff client->gabn.realname = (char *) b.base + b.used;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff client->gabn.realnamelen = client->recv_buffer.used - b.used;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff return (ISC_R_SUCCESS);
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff}
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graffstatic void
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graffprocess_gabn_finddone(isc_task_t *task, isc_event_t *ev) {
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff ns_lwdclient_t *client = ev->ev_arg;
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff isc_eventtype_t evtype;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff isc_boolean_t claimed;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff ns_lwdclient_log(50, "find done for task %p, client %p", task, client);
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff evtype = ev->ev_type;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff isc_event_free(&ev);
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff /*
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff * No more info to be had? If so, we have all the good stuff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff * right now, so we can render things.
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff */
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff claimed = ISC_FALSE;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff if (evtype == DNS_EVENT_ADBNOMOREADDRESSES) {
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff if (NEED_V4(client)) {
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff client->v4find = client->find;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff claimed = ISC_TRUE;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff }
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff if (NEED_V6(client)) {
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff client->v6find = client->find;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff claimed = ISC_TRUE;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff }
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff if (client->find != NULL) {
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff if (claimed)
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff client->find = NULL;
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff else
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff dns_adb_destroyfind(&client->find);
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff
2bcb48cfcae36398454c98e40c563e2cde748e07Michael Graff }
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff generate_reply(client);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff return;
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff }
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff /*
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff * We probably don't need this find anymore. We're either going to
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff * reissue it, or an error occurred. Either way, we're done with
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff * it.
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff */
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff if ((client->find != client->v4find)
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff && (client->find != client->v6find)) {
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff dns_adb_destroyfind(&client->find);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff } else {
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff client->find = NULL;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff }
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff /*
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff * We have some new information we can gather. Run off and fetch
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff * it.
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff */
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff if (evtype == DNS_EVENT_ADBMOREADDRESSES) {
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff restart_find(client);
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff return;
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff }
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff /*
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff * An error or other strangeness happened. Drop this query.
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff */
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff cleanup_gabn(client);
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff}
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graffstatic void
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graffrestart_find(ns_lwdclient_t *client) {
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff unsigned int options;
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff isc_result_t result;
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff isc_boolean_t claimed;
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff ns_lwdclient_log(50, "starting find for client %p", client);
7ec42e4be45c0486ce80461293f377fb4b904dc0Michael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff /*
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff * Issue a find for the name contained in the request. We won't
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff * set the bit that says "anything is good enough" -- we want it
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff * all.
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff */
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff options = 0;
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff options |= DNS_ADBFIND_WANTEVENT;
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff options |= DNS_ADBFIND_RETURNLAME;
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff /*
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff * Set the bits up here to mark that we want this address family
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff * and that we do not currently have a find pending. We will
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff * set that bit again below if it turns out we will get an event.
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff */
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff if (NEED_V4(client))
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff options |= DNS_ADBFIND_INET;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff if (NEED_V6(client))
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff options |= DNS_ADBFIND_INET6;
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff find_again:
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff INSIST(client->find == NULL);
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff result = dns_adb_createfind(client->clientmgr->view->adb,
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff client->clientmgr->task,
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff process_gabn_finddone, client,
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff dns_fixedname_name(&client->target_name),
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff dns_rootname, 0, options, 0,
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff dns_fixedname_name(&client->target_name),
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff client->clientmgr->view->dstport,
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff &client->find);
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff /*
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff * Did we get an alias? If so, save it and re-issue the query.
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff */
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff if (result == DNS_R_ALIAS) {
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff ns_lwdclient_log(50, "found alias, restarting query");
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff dns_adb_destroyfind(&client->find);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff cleanup_gabn(client);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff result = add_alias(client);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff if (result != ISC_R_SUCCESS) {
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff ns_lwdclient_log(50,
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff "out of buffer space adding alias");
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff return;
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff }
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff goto find_again;
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff }
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff ns_lwdclient_log(50, "find returned %d (%s)", result,
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff isc_result_totext(result));
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff /*
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff * Did we get an error?
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff */
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff if (result != ISC_R_SUCCESS) {
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff if (client->find != NULL)
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff dns_adb_destroyfind(&client->find);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff cleanup_gabn(client);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff return;
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff }
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff claimed = ISC_FALSE;
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff /*
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff * Did we get our answer to V4 addresses?
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff */
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff if (NEED_V4(client)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff && ((client->find->query_pending & DNS_ADBFIND_INET) == 0)) {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff ns_lwdclient_log(50, "client %p ipv4 satisfied by find %p",
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client, client->find);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff claimed = ISC_TRUE;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->v4find = client->find;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff }
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff /*
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Did we get our answer to V6 addresses?
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff */
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff if (NEED_V6(client)
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff && ((client->find->query_pending & DNS_ADBFIND_INET6) == 0)) {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff ns_lwdclient_log(50, "client %p ipv6 satisfied by find %p",
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client, client->find);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff claimed = ISC_TRUE;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->v6find = client->find;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff }
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff /*
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * If we're going to get an event, set our internal pending flag
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * and return. When we get an event back we'll do the right
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * thing, basically by calling this function again, perhaps with a
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * new target name.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff *
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * If we have both v4 and v6, and we are still getting an event,
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff * we have a programming error, so die hard.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff */
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff if ((client->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff ns_lwdclient_log(50, "event will be sent");
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff INSIST(client->v4find == NULL || client->v6find == NULL);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff return;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff }
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff ns_lwdclient_log(50, "no event will be sent");
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff if (claimed)
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff client->find = NULL;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff else
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff dns_adb_destroyfind(&client->find);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff /*
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff * We seem to have everything we asked for, or at least we are
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * able to respond with things we've learned.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff */
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff generate_reply(client);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff}
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graffstatic isc_result_t
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffstart_find(ns_lwdclient_t *client) {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff isc_result_t result;
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff /*
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff * Initialize the real name and alias arrays in the reply we're
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff * going to build up.
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff */
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff init_gabn(client);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff result = store_realname(client);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff if (result != ISC_R_SUCCESS)
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff return (result);
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff restart_find(client);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff return (ISC_R_SUCCESS);
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff}
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graffstatic void
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graffinit_gabn(ns_lwdclient_t *client) {
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff int i;
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff /*
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff * Initialize the real name and alias arrays in the reply we're
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * going to build up.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff */
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff for (i = 0; i < LWRES_MAX_ALIASES; i++) {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->aliases[i] = NULL;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->aliaslen[i] = 0;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff }
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff for (i = 0; i < LWRES_MAX_ADDRS; i++) {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->addrs[i].family = 0;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->addrs[i].length = 0;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff LWRES_LINK_INIT(&client->addrs[i], link);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff }
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->gabn.naliases = 0;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->gabn.naddrs = 0;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->gabn.realname = NULL;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->gabn.aliases = client->aliases;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->gabn.realnamelen = 0;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->gabn.aliaslen = client->aliaslen;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff LWRES_LIST_INIT(client->gabn.addrs);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->gabn.base = NULL;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff client->gabn.baselen = 0;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff /*
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Set up the internal buffer to point to the receive region.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff */
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff}
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff/*
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * When we are called, we can be assured that:
d43c2cc7bc4022701f141e299ea8f3fb1d0640c2Michael Graff *
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * client->sockaddr contains the address we need to reply to,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff *
ff9bb3fc5453bbf310b67c560fbf04a5c0fb60daMichael Graff * client->pkt contains the packet header data,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff *
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * the packet "checks out" overall -- any MD5 hashes or crypto
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * bits have been verified,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff *
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * "b" points to the remaining data after the packet header
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * was parsed off.
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff *
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff * We are in a the RECVDONE state.
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff *
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff * From this state we will enter the SEND state if we happen to have
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff * everything we need or we need to return an error packet, or to the
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff * FINDWAIT state if we need to look things up.
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff */
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graffvoid
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graffns_lwdclient_processgabn(ns_lwdclient_t *client, lwres_buffer_t *b) {
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff isc_result_t result;
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff lwres_gabnrequest_t *req;
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff ns_lwdclientmgr_t *cm;
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff isc_buffer_t namebuf;
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff cm = client->clientmgr;
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff req = NULL;
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff result = lwres_gabnrequest_parse(client->clientmgr->lwctx,
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff b, &client->pkt, &req);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff if (result != LWRES_R_SUCCESS)
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff goto out;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff if (req->name == NULL)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff goto out;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff isc_buffer_init(&namebuf, req->name, req->namelen);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff isc_buffer_add(&namebuf, req->namelen);
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff dns_fixedname_init(&client->target_name);
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff dns_fixedname_init(&client->query_name);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff result = dns_name_fromtext(dns_fixedname_name(&client->query_name),
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff &namebuf, NULL, 0, NULL);
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff if (result != ISC_R_SUCCESS)
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff goto out;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff ns_lwsearchctx_init(&client->searchctx,
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff cm->listener->manager->search,
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff dns_fixedname_name(&client->query_name),
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff cm->listener->manager->ndots);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff ns_lwsearchctx_first(&client->searchctx);
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff client->find_wanted = req->addrtypes;
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff ns_lwdclient_log(50, "client %p looking for addrtypes %08x",
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff client, client->find_wanted);
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff /*
897c9ddb4d745b2bfecf98b17e5487bb6656299aMichael Graff * We no longer need to keep this around.
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff */
2a0b8796d46265c078ba7f4dea2979c62ebf5badBob Halley lwres_gabnrequest_free(client->clientmgr->lwctx, &req);
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff /*
2a0b8796d46265c078ba7f4dea2979c62ebf5badBob Halley * Start the find.
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff */
1c3bc66ada38236cc81c41b7174a9f0a872c9ab6Michael Graff result = start_find(client);
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff if (result != ISC_R_SUCCESS)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff goto out;
c803787146cadcb2d7e10cbf4491f3be513dfa1aMichael Graff
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff return;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff /*
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff * We're screwed. Return an error packet to our caller.
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff */
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff out:
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff if (req != NULL)
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff lwres_gabnrequest_free(client->clientmgr->lwctx, &req);
a253e35c2451818fb39f9b808c7641adb5275fb3Michael Graff
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff}
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff