Commit dd16d9d9 authored by Brian Wellington's avatar Brian Wellington
Browse files

564. [func] Add sortlist support to lwresd.

parent 284b13b9
564. [func] Add sortlist support to lwresd.
563. [func] New public functions dns_rdatatype_format() and
dns_rdataclass_format(), for convenient formatting
of rdata type/class mnemonics in log messages.
......
......@@ -13,7 +13,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.59 2000/11/15 00:36:41 gson Exp $
# $Id: Makefile.in,v 1.60 2000/11/15 23:56:19 bwelling Exp $
srcdir = @srcdir@
VPATH = @srcdir@
......@@ -53,7 +53,7 @@ OBJS = aclconf.@O@ client.@O@ interfacemgr.@O@ listenlist.@O@ \
omapiconf.@O@ query.@O@ server.@O@ sortlist.@O@ \
tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \
zoneconf.@O@ \
lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \
lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \
lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@
UOBJS = unix/os.@O@
......@@ -63,7 +63,7 @@ SRCS = aclconf.c client.c interfacemgr.c listenlist.c \
omapiconf.c query.c server.c sortlist.c \
tkeyconf.c tsigconf.c update.c xfrout.c \
zoneconf.c \
lwresd.c lwdclient.c lwderror.c lwdgabn.c \
lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \
lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c
@BIND9_MAKE_RULES@
......
/*
* Copyright (C) 2000 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: lwaddr.h,v 1.1 2000/11/15 23:56:23 bwelling Exp $ */
#include <lwres/lwres.h>
isc_result_t
lwaddr_netaddr_fromlwresaddr(isc_netaddr_t *na, lwres_addr_t *la);
isc_result_t
lwaddr_sockaddr_fromlwresaddr(isc_sockaddr_t *sa, lwres_addr_t *la,
in_port_t port);
isc_result_t
lwaddr_lwresaddr_fromnetaddr(lwres_addr_t *la, isc_netaddr_t *na);
isc_result_t
lwaddr_lwresaddr_fromsockaddr(lwres_addr_t *la, isc_sockaddr_t *sa);
/*
* Copyright (C) 2000 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: lwaddr.c,v 1.1 2000/11/15 23:56:20 bwelling Exp $ */
#include <config.h>
#include <string.h>
#include <isc/result.h>
#include <isc/netaddr.h>
#include <isc/sockaddr.h>
#include <lwres/lwres.h>
#include <named/lwaddr.h>
/*
* Convert addresses from lwres to isc format.
*/
isc_result_t
lwaddr_netaddr_fromlwresaddr(isc_netaddr_t *na, lwres_addr_t *la) {
if (la->family != LWRES_ADDRTYPE_V4 && la->family != LWRES_ADDRTYPE_V6)
return (ISC_R_FAMILYNOSUPPORT);
if (la->family == LWRES_ADDRTYPE_V4) {
struct in_addr ina;
memcpy(&ina.s_addr, la->address, 4);
isc_netaddr_fromin(na, &ina);
} else {
struct in6_addr ina6;
memcpy(&ina6.s6_addr, la->address, 16);
isc_netaddr_fromin6(na, &ina6);
}
return (ISC_R_SUCCESS);
}
isc_result_t
lwaddr_sockaddr_fromlwresaddr(isc_sockaddr_t *sa, lwres_addr_t *la,
in_port_t port)
{
isc_netaddr_t na;
isc_result_t result;
result = lwaddr_netaddr_fromlwresaddr(&na, la);
if (result != ISC_R_SUCCESS)
return (result);
isc_sockaddr_fromnetaddr(sa, &na, port);
return (ISC_R_SUCCESS);
}
/*
* Convert addresses from isc to lwres format.
*/
isc_result_t
lwaddr_lwresaddr_fromnetaddr(lwres_addr_t *la, isc_netaddr_t *na) {
if (na->family != AF_INET && na->family != AF_INET6)
return (ISC_R_FAMILYNOSUPPORT);
if (na->family == AF_INET) {
la->family = LWRES_ADDRTYPE_V4;
la->length = 4;
memcpy(la->address, &na->type.in, 4);
} else {
la->family = LWRES_ADDRTYPE_V6;
la->length = 16;
memcpy(la->address, &na->type.in, 16);
}
return (ISC_R_SUCCESS);
}
isc_result_t
lwaddr_lwresaddr_fromsockaddr(lwres_addr_t *la, isc_sockaddr_t *sa) {
isc_netaddr_t na;
isc_netaddr_fromsockaddr(&na, sa);
return (lwaddr_lwresaddr_fromnetaddr(la, &na));
}
......@@ -15,10 +15,14 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: lwdgabn.c,v 1.9 2000/10/31 22:39:26 bwelling Exp $ */
/* $Id: lwdgabn.c,v 1.10 2000/11/15 23:56:20 bwelling Exp $ */
#include <config.h>
#include <stdlib.h>
#include <isc/netaddr.h>
#include <isc/sockaddr.h>
#include <isc/socket.h>
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/util.h>
......@@ -28,9 +32,11 @@
#include <dns/result.h>
#include <named/types.h>
#include <named/lwaddr.h>
#include <named/lwdclient.h>
#include <named/lwresd.h>
#include <named/lwsearch.h>
#include <named/sortlist.h>
#define NEED_V4(c) ((((c)->find_wanted & LWRES_ADDRTYPE_V4) != 0) \
&& ((c)->v4find == NULL))
......@@ -65,8 +71,7 @@ setup_addresses(ns_lwdclient_t *client, dns_adbfind_t *find, unsigned int at) {
lwres_addr_t *addr;
int af;
const struct sockaddr *sa;
const struct sockaddr_in *sin;
const struct sockaddr_in6 *sin6;
isc_result_t result;
if (at == DNS_ADBFIND_INET)
af = AF_INET;
......@@ -81,22 +86,9 @@ setup_addresses(ns_lwdclient_t *client, dns_adbfind_t *find, unsigned int at) {
addr = &client->addrs[client->gabn.naddrs];
switch (sa->sa_family) {
case AF_INET:
sin = &ai->sockaddr.type.sin;
addr->family = LWRES_ADDRTYPE_V4;
memcpy(addr->address, &sin->sin_addr, 4);
addr->length = 4;
break;
case AF_INET6:
sin6 = &ai->sockaddr.type.sin6;
addr->family = LWRES_ADDRTYPE_V6;
memcpy(addr->address, &sin6->sin6_addr, 16);
addr->length = 16;
break;
default:
result = lwaddr_lwresaddr_fromsockaddr(addr, &ai->sockaddr);
if (result != ISC_R_SUCCESS)
goto next;
}
ns_lwdclient_log(50, "adding address %p, family %d, length %d",
addr->address, addr->family, addr->length);
......@@ -110,6 +102,62 @@ setup_addresses(ns_lwdclient_t *client, dns_adbfind_t *find, unsigned int at) {
}
}
typedef struct {
isc_netaddr_t address;
int rank;
} rankedaddress;
static int
addr_compare(const void *av, const void *bv) {
const rankedaddress *a = (const rankedaddress *) av;
const rankedaddress *b = (const rankedaddress *) bv;
return (a->rank - b->rank);
}
static void
sort_addresses(ns_lwdclient_t *client) {
unsigned int naddrs;
rankedaddress *addrs;
isc_netaddr_t remote;
dns_addressorderfunc_t order;
void *arg;
ns_lwresd_t *lwresd = client->clientmgr->listener->manager;
unsigned int i;
isc_result_t result;
naddrs = client->gabn.naddrs;
if (naddrs <= 1 || lwresd->view->sortlist == NULL)
return;
addrs = isc_mem_get(lwresd->mctx, sizeof(rankedaddress) * naddrs);
if (addrs == NULL)
return;
isc_netaddr_fromsockaddr(&remote, &client->address);
ns_sortlist_byaddrsetup(lwresd->view->sortlist,
&remote, &order, &arg);
if (order == NULL) {
isc_mem_put(lwresd->mctx, addrs,
sizeof(rankedaddress) * naddrs);
return;
}
for (i = 0; i < naddrs; i++) {
result = lwaddr_netaddr_fromlwresaddr(&addrs[i].address,
&client->addrs[i]);
INSIST(result == ISC_R_SUCCESS);
addrs[i].rank = (*order)(&addrs[i].address, arg);
}
qsort(addrs, naddrs, sizeof(rankedaddress), addr_compare);
for (i = 0; i < naddrs; i++) {
result = lwaddr_lwresaddr_fromnetaddr(&client->addrs[i],
&addrs[i].address);
INSIST(result == ISC_R_SUCCESS);
}
isc_mem_put(lwresd->mctx, addrs, sizeof(rankedaddress) * naddrs);
}
static void
generate_reply(ns_lwdclient_t *client) {
isc_result_t result;
......@@ -175,16 +223,15 @@ generate_reply(ns_lwdclient_t *client) {
client->pkt.authlength = 0;
/*
* If there are no addresses, return incomplete or failure , depending
* on whether or not there are aliases.
* If there are no addresses, return failure.
*/
if (client->gabn.naddrs != 0)
client->pkt.result = LWRES_R_SUCCESS;
else if (client->gabn.naliases != 0)
client->pkt.result = LWRES_R_INCOMPLETE;
else
client->pkt.result = LWRES_R_NOTFOUND;
sort_addresses(client);
lwres = lwres_gabnresponse_render(cm->lwctx, &client->gabn,
&client->pkt, &lwb);
if (lwres != LWRES_R_SUCCESS)
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: lwresd.c,v 1.25 2000/11/04 01:11:27 bwelling Exp $ */
/* $Id: lwresd.c,v 1.26 2000/11/15 23:56:21 bwelling Exp $ */
/*
* Main program for the Lightweight Resolver Daemon.
......@@ -45,6 +45,7 @@
#include <named/globals.h>
#include <named/log.h>
#include <named/lwaddr.h>
#include <named/lwresd.h>
#include <named/lwdclient.h>
#include <named/lwsearch.h>
......@@ -89,6 +90,70 @@ ns__lwresd_memfree(void *arg, void *mem, size_t size) {
}
#define CHECK(op) \
do { result = (op); \
if (result != ISC_R_SUCCESS) goto cleanup; \
} while (0)
static isc_result_t
parse_sortlist(lwres_conf_t *lwc, isc_mem_t *mctx,
dns_c_ipmatchlist_t **sortlist)
{
dns_c_ipmatchlist_t *inner = NULL, *middle = NULL, *outer = NULL;
dns_c_ipmatchelement_t *element = NULL;
int i;
isc_result_t result;
REQUIRE(sortlist != NULL && *sortlist == NULL);
REQUIRE (lwc->sortlistnxt > 0);
CHECK(dns_c_ipmatchlist_new(mctx, &middle));
CHECK(dns_c_ipmatchany_new(mctx, &element));
ISC_LIST_APPEND(middle->elements, element, next);
element = NULL;
CHECK(dns_c_ipmatchlist_new(mctx, &inner));
for (i = 0; i < lwc->sortlistnxt; i++) {
isc_sockaddr_t sa;
isc_netaddr_t ma;
unsigned int mask;
CHECK(lwaddr_sockaddr_fromlwresaddr(&sa,
&lwc->sortlist[i].addr,
0));
CHECK(lwaddr_netaddr_fromlwresaddr(&ma,
&lwc->sortlist[i].mask));
CHECK(isc_netaddr_masktoprefixlen(&ma, &mask));
CHECK(dns_c_ipmatchpattern_new(mctx, &element, sa, mask));
ISC_LIST_APPEND(inner->elements, element, next);
element = NULL;
}
CHECK(dns_c_ipmatchindirect_new(mctx, &element, inner, NULL));
dns_c_ipmatchlist_detach(&inner);
ISC_LIST_APPEND(middle->elements, element, next);
element = NULL;
CHECK(dns_c_ipmatchlist_new(mctx, &outer));
CHECK(dns_c_ipmatchindirect_new(mctx, &element, middle, NULL));
dns_c_ipmatchlist_detach(&middle);
ISC_LIST_APPEND(outer->elements, element, next);
*sortlist = outer;
return (ISC_R_SUCCESS);
cleanup:
if (inner != NULL)
dns_c_ipmatchlist_detach(&inner);
if (outer != NULL)
dns_c_ipmatchlist_detach(&outer);
if (element != NULL)
dns_c_ipmatchelement_delete(mctx, &element);
return (result);
}
/*
* Convert a resolv.conf file into a config structure.
*/
......@@ -106,24 +171,27 @@ ns_lwresd_parseresolvconf(isc_mem_t *mctx, dns_c_ctx_t **ctxp) {
dns_c_lwres_t *lwres = NULL;
dns_c_search_t *search = NULL;
dns_c_searchlist_t *searchlist = NULL;
dns_c_ipmatchlist_t *sortlist = NULL;
isc_result_t result;
lwres_result_t lwresult;
struct in_addr localhost;
result = dns_c_ctx_new(mctx, &ctx);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_ctx_new(mctx, &ctx));
lwctx = NULL;
lwresult = lwres_context_create(&lwctx, mctx, ns__lwresd_memalloc,
ns__lwresd_memfree,
LWRES_CONTEXT_SERVERMODE);
if (lwresult != LWRES_R_SUCCESS)
if (lwresult != LWRES_R_SUCCESS) {
result = ISC_R_NOMEMORY;
goto cleanup;
}
lwresult = lwres_conf_parse(lwctx, lwresd_g_resolvconffile);
if (lwresult != LWRES_R_SUCCESS)
if (lwresult != LWRES_R_SUCCESS) {
result = DNS_R_SYNTAX;
goto cleanup;
}
lwc = lwres_conf_get(lwctx);
INSIST(lwc != NULL);
......@@ -132,9 +200,7 @@ ns_lwresd_parseresolvconf(isc_mem_t *mctx, dns_c_ctx_t **ctxp) {
* Build the list of forwarders.
*/
if (lwc->nsnext > 0) {
result = dns_c_iplist_new(mctx, lwc->nsnext, &forwarders);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_iplist_new(mctx, lwc->nsnext, &forwarders));
if (ns_g_port != 0)
port = ns_g_port;
......@@ -142,39 +208,24 @@ ns_lwresd_parseresolvconf(isc_mem_t *mctx, dns_c_ctx_t **ctxp) {
port = 53;
for (i = 0 ; i < lwc->nsnext ; i++) {
if (lwc->nameservers[i].family != LWRES_ADDRTYPE_V4 &&
lwc->nameservers[i].family != LWRES_ADDRTYPE_V6)
CHECK(lwaddr_sockaddr_fromlwresaddr(
&sa,
&lwc->nameservers[i],
port));
if (result != ISC_R_SUCCESS)
continue;
if (lwc->nameservers[i].family == LWRES_ADDRTYPE_V4) {
struct in_addr ina;
memcpy(&ina.s_addr,
lwc->nameservers[i].address, 4);
isc_sockaddr_fromin(&sa, &ina, port);
} else {
struct in6_addr ina6;
memcpy(&ina6.s6_addr,
lwc->nameservers[i].address, 16);
isc_sockaddr_fromin6(&sa, &ina6, port);
}
#ifndef NOMINUM_PUBLIC
result = dns_c_iplist_append(forwarders, sa, NULL);
CHECK(dns_c_iplist_append(forwarders, sa, NULL));
#else /* NOMINUM_PUBLIC */
result = dns_c_iplist_append(forwarders, sa);
CHECK(dns_c_iplist_append(forwarders, sa));
#endif /* NOMINUM_PUBLIC */
if (result != ISC_R_SUCCESS)
goto cleanup;
}
if (forwarders->nextidx != 0) {
result = dns_c_ctx_setforwarders(ctx, ISC_FALSE,
forwarders);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_ctx_setforwarders(ctx, ISC_FALSE,
forwarders));
forwarders = NULL;
result = dns_c_ctx_setforward(ctx, dns_c_forw_first);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_ctx_setforward(ctx, dns_c_forw_first));
}
}
......@@ -182,26 +233,25 @@ ns_lwresd_parseresolvconf(isc_mem_t *mctx, dns_c_ctx_t **ctxp) {
* Build the search path
*/
if (lwc->searchnxt > 0) {
result = dns_c_searchlist_new(mctx, &searchlist);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_searchlist_new(mctx, &searchlist));
for (i = 0; i < lwc->searchnxt; i++) {
search = NULL;
result = dns_c_search_new(mctx, lwc->search[i],
&search);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_search_new(mctx, lwc->search[i], &search));
dns_c_searchlist_append(searchlist, search);
}
}
result = dns_c_lwreslist_new(mctx, &lwreslist);
if (result != ISC_R_SUCCESS)
goto cleanup;
/*
* Build the sortlist
*/
if (lwc->sortlistnxt > 0) {
CHECK(parse_sortlist(lwc, mctx, &sortlist));
CHECK(dns_c_ctx_setsortlist(ctx, sortlist));
dns_c_ipmatchlist_detach(&sortlist);
}
result = dns_c_lwres_new(mctx, &lwres);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_lwreslist_new(mctx, &lwreslist));
CHECK(dns_c_lwres_new(mctx, &lwres));
port = lwresd_g_listenport;
if (port == 0)
......@@ -211,57 +261,29 @@ ns_lwresd_parseresolvconf(isc_mem_t *mctx, dns_c_ctx_t **ctxp) {
localhost.s_addr = htonl(INADDR_LOOPBACK);
isc_sockaddr_fromin(&sa, &localhost, port);
} else {
if (lwc->lwservers[0].family != LWRES_ADDRTYPE_V4 &&
lwc->lwservers[0].family != LWRES_ADDRTYPE_V6)
{
result = ISC_R_FAMILYNOSUPPORT;
goto cleanup;
}
if (lwc->lwservers[0].family == LWRES_ADDRTYPE_V4) {
struct in_addr ina;
memcpy(&ina.s_addr, lwc->lwservers[0].address, 4);
isc_sockaddr_fromin(&sa, &ina, port);
} else {
struct in6_addr ina6;
memcpy(&ina6.s6_addr, lwc->lwservers[0].address, 16);
isc_sockaddr_fromin6(&sa, &ina6, port);
}
CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, &lwc->lwservers[0],
port));
}
result = dns_c_iplist_new(mctx, 1, &locallist);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_iplist_new(mctx, 1, &locallist));
#ifndef NOMINUM_PUBLIC
result = dns_c_iplist_append(locallist, sa, NULL);
CHECK(dns_c_iplist_append(locallist, sa, NULL));
#else /* NOMINUM_PUBLIC */
result = dns_c_iplist_append(locallist, sa);
CHECK(dns_c_iplist_append(locallist, sa));
#endif /* NOMINUM_PUBLIC */
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_c_lwres_setlistenon(lwres, locallist);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_lwres_setlistenon(lwres, locallist));
dns_c_iplist_detach(&locallist);
result = dns_c_lwres_setsearchlist(lwres, searchlist);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_lwres_setsearchlist(lwres, searchlist));
searchlist = NULL;
result = dns_c_lwres_setndots(lwres, lwc->ndots);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_lwres_setndots(lwres, lwc->ndots));
result = dns_c_lwreslist_append(lwreslist, lwres);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_lwreslist_append(lwreslist, lwres));
lwres = NULL;
result = dns_c_ctx_setlwres(ctx, lwreslist);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_c_ctx_setlwres(ctx, lwreslist));
lwreslist = NULL;
*ctxp = ctx;
......@@ -276,6 +298,8 @@ ns_lwresd_parseresolvconf(isc_mem_t *mctx, dns_c_ctx_t **ctxp) {
dns_c_iplist_detach(&locallist);
if (searchlist != NULL)
dns_c_searchlist_delete(&searchlist);
if (sortlist != NULL)
dns_c_ipmatchlist_detach(&sortlist);
if (lwres != NULL)
dns_c_lwres_delete(&lwres);
if (lwreslist != NULL)
......
......@@ -41,6 +41,7 @@
./bin/named/include/named/listenlist.h C 2000
./bin/named/include/named/log.h C 1999,2000
./bin/named/include/named/logconf.h C 1999,2000
./bin/named/include/named/lwaddr.h C 2000
./bin/named/include/named/lwdclient.h C 2000
./bin/named/include/named/lwresd.h C 2000
./bin/named/include/named/lwsearch.h C 2000
......@@ -57,6 +58,7 @@
./bin/named/listenlist.c C 2000
./bin/named/log.c C 1999,2000
./bin/named/logconf.c C 1999,2000
./bin/named/lwaddr.c C 2000
./bin/named/lwdclient.c C 2000
./bin/named/lwderror.c C 2000
./bin/named/lwdgabn.c C 2000
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment