implement actual network I/O for lw resolver. All I/O is run through the

context, where the sockets are cached.  This means one context per thread.
This commit is contained in:
Michael Graff
2000-01-18 01:43:12 +00:00
parent ada4d10c44
commit 7dbf5a0b64
8 changed files with 245 additions and 11 deletions

View File

@@ -65,24 +65,17 @@ hexdump(char *msg, void *base, size_t len)
}
static char *TESTSTRING = "This is a test. This is only a test. !!!";
static lwres_context_t *ctx;
int
main(int argc, char *argv[])
static void
test_noop(void)
{
int ret;
lwres_context_t *ctx;
lwres_lwpacket_t pkt, pkt2;
lwres_nooprequest_t nooprequest, *nooprequest2;
lwres_noopresponse_t noopresponse, *noopresponse2;
lwres_buffer_t b;
(void)argc;
(void)argv;
ctx = NULL;
ret = lwres_context_create(&ctx, NULL, NULL, NULL);
CHECK(ret, "lwres_context_create");
pkt.flags = 0;
pkt.serial = 0x11223344;
pkt.recvlength = 0x55667788;
@@ -152,6 +145,36 @@ main(int argc, char *argv[])
lwres_context_freemem(ctx, b.base, b.length);
b.base = NULL;
b.length = 0;
}
static void
test_gabn(void)
{
lwres_gabnresponse_t *res;
int ret;
res = NULL;
ret = lwres_getaddrsbyname(ctx, "www.flame.org", LWRES_ADDRTYPE_V4,
&res);
assert(ret == 0);
lwres_gabnresponse_free(ctx, &res);
}
int
main(int argc, char *argv[])
{
int ret;
(void)argc;
(void)argv;
ctx = NULL;
ret = lwres_context_create(&ctx, NULL, NULL, NULL);
CHECK(ret, "lwres_context_create");
test_noop();
test_gabn();
lwres_context_destroy(&ctx);

View File

@@ -22,14 +22,22 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <lwres/context.h>
#include <lwres/lwres.h>
#include "context_p.h"
#include "assert_p.h"
static void *lwres_malloc(void *, size_t);
static void lwres_free(void *, void *, size_t);
static int context_connect(lwres_context_t *);
int
lwres_context_create(lwres_context_t **contextp, void *arg,
@@ -63,10 +71,13 @@ lwres_context_create(lwres_context_t **contextp, void *arg,
ctx->malloc = malloc_function;
ctx->free = free_function;
ctx->arg = arg;
ctx->sock = -1;
ctx->timeout = LWRES_DEFAULT_TIMEOUT;
ctx->serial = (isc_uint32_t)ctx; /* XXXMLG */
(void)context_connect(ctx); /* XXXMLG */
*contextp = ctx;
return (0);
}
@@ -141,3 +152,58 @@ lwres_free(void *arg, void *mem, size_t len)
memset(mem, 0xa9, len);
free(mem);
}
static int
context_connect(lwres_context_t *ctx)
{
int s;
int ret;
struct sockaddr_in localhost;
memset(&localhost, 0, sizeof(localhost));
localhost.sin_family = AF_INET;
localhost.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
localhost.sin_port = htons(LWRES_UDP_PORT);
s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s < 0)
return (-1);
ret = connect(s, (struct sockaddr *)&localhost, sizeof(localhost));
if (ret != 0) {
close(s);
return (-1);
}
ctx->sock = s;
return (0);
}
int
lwres_context_sendrecv(lwres_context_t *ctx,
void *sendbase, int sendlen,
void *recvbase, int recvlen)
{
int ret;
struct sockaddr_in sin;
int fromlen;
ret = send(ctx->sock, sendbase, sendlen, 0);
if (ret < 0)
return (ret);
if (ret != sendlen)
return (-1);
fromlen = sizeof(sin);
ret = recvfrom(ctx->sock, recvbase, recvlen, 0,
(struct sockaddr *)&sin, &fromlen);
if (ret < 0)
return (-1);
if (sin.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
|| sin.sin_port != htons(LWRES_UDP_PORT))
return (-1);
return (ret);
}

View File

@@ -35,6 +35,11 @@ struct lwres_context {
unsigned int timeout; /* time to wait for reply */
isc_uint32_t serial; /* serial number state */
/*
* For network I/O.
*/
int sock; /* socket to send on */
/*
* Function pointers for allocating memory.
*/

View File

@@ -77,6 +77,11 @@ lwres_context_freemem(lwres_context_t *ctx, void *mem, size_t len);
void *
lwres_context_allocmem(lwres_context_t *ctx, size_t len);
int
lwres_context_sendrecv(lwres_context_t *ctx,
void *sendbase, int sendlen,
void *recvbase, int recvlen);
ISC_LANG_ENDDECLS
#endif /* LWRES_CONTEXT_H */

View File

@@ -86,6 +86,9 @@
#define LWRES_STRING_LENGTH(x) (sizeof(isc_uint16_t) + strlen(x) + 1)
#define LWRES_UDP_PORT 921 /* XXXMLG */
#define LWRES_RECVLENGTH 2048 /* XXXMLG */
/*
* NO-OP
*/
@@ -116,6 +119,7 @@ typedef struct {
typedef struct {
/* public */
isc_uint32_t addrtypes;
char *name;
} lwres_gabnrequest_t;
@@ -126,6 +130,9 @@ typedef struct {
char *real_name;
char **aliases;
lwres_addr_t *addrs;
/* if base != NULL, it will be freed when this structure is freed. */
void *base;
size_t baselen;
} lwres_gabnresponse_t;
/*
@@ -142,6 +149,9 @@ typedef struct {
isc_uint16_t naliases;
char *real_name;
char **aliases;
/* if base != NULL, it will be freed when this structure is freed. */
void *base;
size_t baselen;
} lwres_gnbaresponse_t;
#define LWRES_ADDRTYPE_V4 0x00000001U /* ipv4 */
@@ -336,6 +346,10 @@ lwres_string_parse(lwres_buffer_t *b, char **c, isc_uint16_t *len);
int
lwres_addr_parse(lwres_buffer_t *b, lwres_addr_t *addr);
int
lwres_getaddrsbyname(lwres_context_t *ctx, const char *name,
isc_uint32_t addrtypes, lwres_gabnresponse_t **structp);
ISC_LANG_ENDDECLS
#endif /* LWRES_LWRES_H */

View File

@@ -47,7 +47,7 @@ lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req,
datalen = strlen(req->name);
payload_length = LWRES_STRING_LENGTH(req->name);
payload_length = LWRES_STRING_LENGTH(req->name) + 4;
buflen = LWRES_LWPACKET_LENGTH + payload_length;
buf = CTXMALLOC(buflen);
@@ -74,6 +74,11 @@ lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req,
INSIST(SPACE_OK(b, payload_length));
/*
* Address types we'll accept.
*/
lwres_buffer_putuint32(b, req->addrtypes);
/*
* Put the length and the data. We know this will fit because we
* just checked for it.
@@ -180,6 +185,7 @@ lwres_gabnrequest_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt,
int ret;
char *name;
lwres_gabnrequest_t *gabn;
isc_uint32_t addrtypes;
REQUIRE(ctx != NULL);
REQUIRE(pkt != NULL);
@@ -189,6 +195,11 @@ lwres_gabnrequest_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt,
if ((pkt->flags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
return (-1);
if (!SPACE_REMAINING(b, 4))
return (-1);
addrtypes = lwres_buffer_getuint32(b);
/*
* Pull off the name itself
*/
@@ -203,6 +214,7 @@ lwres_gabnrequest_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt,
if (gabn == NULL)
return (-1);
gabn->addrtypes = addrtypes;
gabn->name = name;
*structp = gabn;
@@ -249,6 +261,7 @@ lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt,
goto out;
}
gabn->naliases = naliases;
gabn->base = NULL;
gabn->addrs = CTXMALLOC(sizeof(lwres_addr_t) * naddrs);
if (gabn->addrs == NULL) {
@@ -326,5 +339,7 @@ lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp)
CTXFREE(gabn->aliases, sizeof(char *) * gabn->naliases);
if (gabn->naddrs > 0)
CTXFREE(gabn->addrs, sizeof(lwres_addr_t *) * gabn->naddrs);
if (gabn->base != NULL)
CTXFREE(gabn->base, gabn->baselen);
CTXFREE(gabn, sizeof(lwres_gabnresponse_t));
}

View File

@@ -224,6 +224,7 @@ lwres_gnbaresponse_parse(lwres_context_t *ctx, lwres_lwpacket_t *pkt,
if (gnba == NULL)
return (-1);
gnba->naliases = 0;
gnba->base = NULL;
gnba->aliases = CTXMALLOC(sizeof(char *) * naliases);
if (gnba->aliases == NULL) {
@@ -290,5 +291,7 @@ lwres_gnbaresponse_free(lwres_context_t *ctx, lwres_gnbaresponse_t **structp)
if (gnba->naliases > 0)
CTXFREE(gnba->aliases, sizeof(char *) * gnba->naliases);
if (gnba->base != NULL)
CTXFREE(gnba->base, gnba->baselen);
CTXFREE(gnba, sizeof(lwres_gnbaresponse_t));
}

View File

@@ -21,11 +21,18 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <lwres/lwbuffer.h>
#include <lwres/lwres.h>
#include "assert_p.h"
#include "context_p.h"
/*
* Requires:
@@ -86,3 +93,99 @@ lwres_addr_parse(lwres_buffer_t *b, lwres_addr_t *addr)
return (0);
}
int
lwres_getaddrsbyname(lwres_context_t *ctx, const char *name,
isc_uint32_t addrtypes, lwres_gabnresponse_t **structp)
{
lwres_gabnrequest_t request;
lwres_gabnresponse_t *response;
int ret;
int free_b;
lwres_buffer_t b;
lwres_lwpacket_t pkt;
isc_uint32_t serial;
char *buffer;
REQUIRE(ctx != NULL);
REQUIRE(name != NULL);
REQUIRE(addrtypes != 0);
REQUIRE(structp != NULL && *structp == NULL);
response = NULL;
free_b = 0;
buffer = NULL;
serial = (isc_uint32_t)name;
buffer = CTXMALLOC(LWRES_RECVLENGTH);
if (buffer == NULL) {
ret = -1;
goto out;
}
/*
* Set up our request and render it to a buffer.
*/
request.addrtypes = addrtypes;
request.name = (char *)name;
pkt.flags = 0;
pkt.serial = serial;
pkt.result = 0;
pkt.recvlength = LWRES_RECVLENGTH;
ret = lwres_gabnrequest_render(ctx, &request, &pkt, &b);
if (ret != 0)
goto out;
free_b = 1;
ret = lwres_context_sendrecv(ctx, b.base, b.length, buffer,
LWRES_RECVLENGTH);
if (ret < 0)
goto out;
CTXFREE(b.base, b.length);
free_b = 0;
lwres_buffer_init(&b, buffer, ret);
/*
* Parse the packet header.
*/
ret = lwres_lwpacket_parseheader(&b, &pkt);
if (ret != 0)
goto out;
/*
* Sanity check.
*/
if (pkt.serial != serial) {
ret = -1;
goto out;
}
if (pkt.opcode != LWRES_OPCODE_GETADDRSBYNAME) {
ret = -1;
goto out;
}
/*
* Parse the response.
*/
ret = lwres_gabnresponse_parse(ctx, &pkt, &b, &response);
if (ret != 0)
goto out;
response->base = buffer;
response->baselen = LWRES_RECVLENGTH;
buffer = NULL; /* don't free this below */
*structp = response;
return (0);
out:
if (free_b != 0)
CTXFREE(b.base, b.length);
if (buffer != NULL)
CTXFREE(buffer, LWRES_RECVLENGTH);
if (response != NULL)
lwres_gabnresponse_free(ctx, &response);
return (ret);
}