From d95e6b2631a1cb164480c5bce91b2d4e2aee4689 Mon Sep 17 00:00:00 2001 From: Michael Graff Date: Mon, 31 Jan 2000 19:04:58 +0000 Subject: [PATCH] add the byaddr bits I hacked on Friday --- bin/lwresd/client.c | 3 + bin/lwresd/client.h | 11 ++- bin/lwresd/main.c | 1 + bin/lwresd/process_gabn.c | 5 +- bin/lwresd/process_gnba.c | 186 +++++++++++++++++++++++++++++++++++++- bin/tests/byaddr_test.c | 28 +++--- 6 files changed, 212 insertions(+), 22 deletions(-) diff --git a/bin/lwresd/client.c b/bin/lwresd/client.c index 505f65b888..73553ebddb 100644 --- a/bin/lwresd/client.c +++ b/bin/lwresd/client.c @@ -350,4 +350,7 @@ client_init_gnba(client_t *client) client->gnba.aliaslen = client->aliaslen; client->gnba.base = NULL; client->gnba.baselen = NULL; + + isc_buffer_init(&client->recv_buffer, client->buffer, + LWRES_RECVLENGTH, ISC_BUFFERTYPE_TEXT); } diff --git a/bin/lwresd/client.h b/bin/lwresd/client.h index e71fee0f8b..b833a0b030 100644 --- a/bin/lwresd/client.h +++ b/bin/lwresd/client.h @@ -23,17 +23,20 @@ #include #include #include +#include #include #include #include #include +#include #include #include -#include #include -#include #include +#include +#include +#include #define LWRD_EVENTCLASS ISC_EVENTCLASS(4242) @@ -78,6 +81,9 @@ struct client_s { * gnba (get name by address) state info. */ lwres_gnbaresponse_t gnba; + dns_byaddr_t *byaddr; + unsigned int options; + isc_netaddr_t na; /* * Alias and address info. This is copied up to the gabn/gnba @@ -153,6 +159,7 @@ struct client_s { #define CLIENT_SETSENDDONE(c) ((c)->state = CLIENT_STATE_SENDDONE) struct clientmgr_s { + isc_mem_t *mctx; isc_task_t *task; /* owning task */ isc_socket_t *sock; /* socket to use */ dns_view_t *view; diff --git a/bin/lwresd/main.c b/bin/lwresd/main.c index a75a84464f..babfdc6ceb 100644 --- a/bin/lwresd/main.c +++ b/bin/lwresd/main.c @@ -245,6 +245,7 @@ main(int argc, char **argv) if (result != ISC_R_SUCCESS) break; isc_task_setname(cmgr[i].task, "lwresd client", &cmgr[i]); + cmgr[i].mctx = mem; cmgr[i].lwctx = NULL; result = lwres_context_create(&cmgr[i].lwctx, mem, mem_alloc, mem_free); diff --git a/bin/lwresd/process_gabn.c b/bin/lwresd/process_gabn.c index b109fbd62f..59da4e79fd 100644 --- a/bin/lwresd/process_gabn.c +++ b/bin/lwresd/process_gabn.c @@ -272,7 +272,7 @@ add_alias(client_t *client) /* * Save this name away as the current real name. */ - client->gabn.realname = (char *) b.base + b.used; + client->gabn.realname = (char *)(b.base) + b.used; client->gabn.realnamelen = client->recv_buffer.used - b.used; return (ISC_R_SUCCESS); @@ -533,7 +533,8 @@ process_gabn(client_t *client, lwres_buffer_t *b) goto out; client->find_wanted = req->addrtypes; - DP(50, "Client %p looking for addrtypes %08x", client, client->find_wanted); + DP(50, "Client %p looking for addrtypes %08x", + client, client->find_wanted); /* * We no longer need to keep this around. diff --git a/bin/lwresd/process_gnba.c b/bin/lwresd/process_gnba.c index 5e7b35af4d..f314802b36 100644 --- a/bin/lwresd/process_gnba.c +++ b/bin/lwresd/process_gnba.c @@ -21,25 +21,203 @@ #include #include +#include #include #include #include #include #include -#include +#include #include #include #include "client.h" +static void start_byaddr(client_t *); + +static void +byaddr_done(isc_task_t *task, isc_event_t *event) +{ + client_t *client; + dns_byaddrevent_t *bevent; + int lwres; + lwres_buffer_t lwb; + dns_name_t *name; + isc_result_t result; + isc_region_t r; + isc_buffer_t b; + lwres_gnbaresponse_t *gnba; + isc_uint16_t naliases; + + (void)task; + + client = event->arg; + INSIST(client->byaddr == event->sender); + + bevent = (dns_byaddrevent_t *)event; + gnba = &client->gnba; + + DP(50, "byaddr event result = %s\n", + isc_result_totext(bevent->result)); + + if (bevent->result != ISC_R_SUCCESS) { + dns_byaddr_destroy(&client->byaddr); + + if (client->options & DNS_BYADDROPT_IPV6NIBBLE) { + error_pkt_send(client, LWRES_R_FAILURE); + goto out; + } + + client->options |= DNS_BYADDROPT_IPV6NIBBLE; + + start_byaddr(client); + goto out; + } + + for (name = ISC_LIST_HEAD(bevent->names); + name != NULL; + name = ISC_LIST_NEXT(name, link)) { + b = client->recv_buffer; + + result = dns_name_totext(name, ISC_TRUE, &client->recv_buffer); + if (result != ISC_R_SUCCESS) + goto out; + if (gnba->realname == NULL) { + gnba->realname = (char *)(b.base) + b.used; + gnba->realnamelen = client->recv_buffer.used - b.used; + } else { + naliases = gnba->naliases; + if (naliases < LWRES_MAX_ALIASES) { + gnba->aliases[naliases] = (char *)(b.base) + b.used; + gnba->aliaslen[naliases] = client->recv_buffer.used + - b.used; + gnba->naliases++; + } + } + } + + dns_byaddr_destroy(&client->byaddr); + + /* + * Render the packet. + */ + client->pkt.recvlength = LWRES_RECVLENGTH; + client->pkt.authtype = 0; /* XXXMLG */ + client->pkt.authlength = 0; + client->pkt.result = LWRES_R_SUCCESS; + + lwres_buffer_init(&lwb, client->buffer, LWRES_RECVLENGTH); + lwres = lwres_gnbaresponse_render(client->clientmgr->lwctx, + &client->gnba, &client->pkt, &lwb); + +#if 0 + hexdump("Sending to client", b.base, b.used); +#endif + + if (lwres != LWRES_R_SUCCESS) + goto out; + + r.base = lwb.base; + r.length = lwb.used; + client->sendbuf = r.base; + client->sendlength = r.length; + result = isc_socket_sendto(client->clientmgr->sock, &r, + client->clientmgr->task, client_send, + client, &client->address, NULL); + if (result != ISC_R_SUCCESS) + goto out; + + CLIENT_SETSEND(client); + + out: + if (client->byaddr != NULL) + dns_byaddr_destroy(&client->byaddr); + isc_event_free(&event); +} + +static void +start_byaddr(client_t *client) +{ + isc_result_t result; + clientmgr_t *cm; + + cm = client->clientmgr; + + INSIST(client->byaddr == NULL); + + result = dns_byaddr_create(cm->mctx, &client->na, cm->view, + client->options, cm->task, byaddr_done, + client, &client->byaddr); + if (result != ISC_R_SUCCESS) { + error_pkt_send(client, LWRES_R_FAILURE); + return; + } +} + void process_gnba(client_t *client, lwres_buffer_t *b) { - lwres_lwpacket_t rpkt; lwres_gnbarequest_t *req; - lwres_gnbaresponse_t resp; + isc_result_t result; - return /*XXX (ISC_R_NOTIMPLEMENTED)*/; + REQUIRE(CLIENT_ISRECVDONE(client)); + INSIST(client->byaddr == NULL); + + req = NULL; + + result = lwres_gnbarequest_parse(client->clientmgr->lwctx, + b, &client->pkt, &req); + if (result != LWRES_R_SUCCESS) + goto out; + if (req->addr.address == NULL) + goto out; + + client->options = 0; + if (req->addr.family == LWRES_ADDRTYPE_V4) { + client->na.family = AF_INET; + if (req->addr.length != 4) + goto out; + memcpy(&client->na.type.in, req->addr.address, 4); + } else if (req->addr.family == LWRES_ADDRTYPE_V6) { + client->na.family = AF_INET6; + if (req->addr.length != 16) + goto out; + memcpy(&client->na.type.in6, req->addr.address, 16); + } else { + goto out; + } + + DP(50, "Client %p looking for addrtype %08x", + client, req->addr.family); + + /* + * We no longer need to keep this around. + */ + lwres_gnbarequest_free(client->clientmgr->lwctx, &req); + + /* + * Initialize the real name and alias arrays in the reply we're + * going to build up. + */ + client_init_gnba(client); + + /* + * Start the find. + */ + start_byaddr(client); + + return; + + /* + * We're screwed. Return an error packet to our caller. + */ + out: + if (req != NULL) + lwres_gnbarequest_free(client->clientmgr->lwctx, &req); + + error_pkt_send(client, LWRES_R_FAILURE); + + return; } diff --git a/bin/tests/byaddr_test.c b/bin/tests/byaddr_test.c index be7d09868b..ec0883b89e 100644 --- a/bin/tests/byaddr_test.c +++ b/bin/tests/byaddr_test.c @@ -25,29 +25,29 @@ #include #include +#include #include +#include #include #include #include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include static void