context.c revision e61793f0865117ad87a19d6e245bea8f3b712d1b
1ccbfca64ae86ace521053773001cb995352f96fBob Halley/*
2a3747006563cfa1c07516ec594cc6d1f0db7ff2Tinderbox User * Copyright (C) 2000, 2001 Internet Software Consortium.
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews *
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Permission to use, copy, modify, and distribute this software for any
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * purpose with or without fee is hereby granted, provided that the above
1ccbfca64ae86ace521053773001cb995352f96fBob Halley * copyright notice and this permission notice appear in all copies.
1ccbfca64ae86ace521053773001cb995352f96fBob Halley *
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1ccbfca64ae86ace521053773001cb995352f96fBob Halley */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/* $Id: context.c,v 1.42 2001/11/19 03:08:40 mayer Exp $ */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#include <config.h>
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#include <fcntl.h>
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#include <limits.h>
1ccbfca64ae86ace521053773001cb995352f96fBob Halley#include <stdlib.h>
1ccbfca64ae86ace521053773001cb995352f96fBob Halley#include <string.h>
341323e0e7ef69f7c425cd3462afe06d0930c528Michael Graff#include <time.h>
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington#include <unistd.h>
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington#include <lwres/lwres.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <lwres/net.h>
364a82f7c25b62967678027043425201a5e5171aBob Halley#include <lwres/platform.h>
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#ifdef LWRES_PLATFORM_NEEDSYSSELECTH
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt#include <sys/select.h>
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington#endif
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt
c03ce72a3b1bd639d5bc430ed37f791051125c56Andreas Gustafsson#include "context_p.h"
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley#include "assert_p.h"
341323e0e7ef69f7c425cd3462afe06d0930c528Michael Graff
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley/*
cfb1587eb9a6dc6d1d36ea0344e1b20068b81e88Evan Hunt * Some systems define the socket length argument as an int, some as size_t,
b20ee662a7c847c9ef7b96ab9e5e34543efe5c0dMark Andrews * some as socklen_t. The last is what the current POSIX standard mandates.
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley * This definition is here so it can be portable but easily changed if needed.
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#ifndef LWRES_SOCKADDR_LEN_T
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#define LWRES_SOCKADDR_LEN_T unsigned int
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley#endif
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington/*
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington * Make a socket nonblocking.
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington */
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington#ifndef MAKE_NONBLOCKING
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington#define MAKE_NONBLOCKING(sd, retval) \
77ac297199fc44809d9628558223627c10ae3f31Brian Wellingtondo { \
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley retval = fcntl(sd, F_GETFL, 0); \
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (retval != -1) { \
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley retval |= O_NONBLOCK; \
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley retval = fcntl(sd, F_SETFL, retval); \
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley } \
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley} while (0)
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington#endif
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob HalleyLIBLWRES_EXTERNAL_DATA lwres_uint16_t lwres_udp_port = LWRES_UDP_PORT;
1ccbfca64ae86ace521053773001cb995352f96fBob HalleyLIBLWRES_EXTERNAL_DATA const char *lwres_resolv_conf = LWRES_RESOLV_CONF;
0e3ad060581e366d3e682caf2dd5d9ea2e0f4893Bob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halleystatic void *
77ac297199fc44809d9628558223627c10ae3f31Brian Wellingtonlwres_malloc(void *, size_t);
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
77ac297199fc44809d9628558223627c10ae3f31Brian Wellingtonstatic void
77ac297199fc44809d9628558223627c10ae3f31Brian Wellingtonlwres_free(void *, void *, size_t);
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
77ac297199fc44809d9628558223627c10ae3f31Brian Wellingtonstatic lwres_result_t
77ac297199fc44809d9628558223627c10ae3f31Brian Wellingtoncontext_connect(lwres_context_t *);
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
b61c97cebd9c23e7bbfbdc9508cf022c68461d46Danny Mayerlwres_result_t
77ac297199fc44809d9628558223627c10ae3f31Brian Wellingtonlwres_context_create(lwres_context_t **contextp, void *arg,
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington lwres_malloc_t malloc_function,
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington lwres_free_t free_function,
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington unsigned int flags)
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington{
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington lwres_context_t *ctx;
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington REQUIRE(contextp != NULL && *contextp == NULL);
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington UNUSED(flags);
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington /*
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington * If we were not given anything special to use, use our own
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington * functions. These are just wrappers around malloc() and free().
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington */
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington if (malloc_function == NULL || free_function == NULL) {
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington REQUIRE(malloc_function == NULL);
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington REQUIRE(free_function == NULL);
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington malloc_function = lwres_malloc;
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington free_function = lwres_free;
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington }
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington ctx = malloc_function(arg, sizeof(lwres_context_t));
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington if (ctx == NULL)
e672951ed28b2e9cc7a19c3d7fa4a258382f981cAutomatic Updater return (LWRES_R_NOMEMORY);
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington /*
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington * Set up the context.
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington */
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington ctx->malloc = malloc_function;
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington ctx->free = free_function;
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington ctx->arg = arg;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley ctx->sock = -1;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley ctx->timeout = LWRES_DEFAULT_TIMEOUT;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley ctx->serial = time(NULL); /* XXXMLG or BEW */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff /*
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * Init resolv.conf bits.
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews */
1ccbfca64ae86ace521053773001cb995352f96fBob Halley lwres_conf_init(ctx);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington *contextp = ctx;
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington return (LWRES_R_SUCCESS);
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington}
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleyvoid
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleylwres_context_destroy(lwres_context_t **contextp) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley lwres_context_t *ctx;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley REQUIRE(contextp != NULL && *contextp != NULL);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley ctx = *contextp;
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington *contextp = NULL;
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington if (ctx->sock != -1) {
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington close(ctx->sock);
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington ctx->sock = -1;
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington }
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington CTXFREE(ctx, sizeof(lwres_context_t));
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington}
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington
77ac297199fc44809d9628558223627c10ae3f31Brian Wellingtonlwres_uint32_t
77ac297199fc44809d9628558223627c10ae3f31Brian Wellingtonlwres_context_nextserial(lwres_context_t *ctx) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley REQUIRE(ctx != NULL);
c03ce72a3b1bd639d5bc430ed37f791051125c56Andreas Gustafsson
c03ce72a3b1bd639d5bc430ed37f791051125c56Andreas Gustafsson return (ctx->serial++);
c03ce72a3b1bd639d5bc430ed37f791051125c56Andreas Gustafsson}
c03ce72a3b1bd639d5bc430ed37f791051125c56Andreas Gustafsson
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graffvoid
1ccbfca64ae86ace521053773001cb995352f96fBob Halleylwres_context_initserial(lwres_context_t *ctx, lwres_uint32_t serial) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley REQUIRE(ctx != NULL);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley ctx->serial = serial;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley}
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleyvoid
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleylwres_context_freemem(lwres_context_t *ctx, void *mem, size_t len) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley REQUIRE(mem != NULL);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley REQUIRE(len != 0);
2d63e8f8d2a8ef70e404182caf5b0d95dbcf2027Andreas Gustafsson
1ccbfca64ae86ace521053773001cb995352f96fBob Halley CTXFREE(mem, len);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley}
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleyvoid *
1ccbfca64ae86ace521053773001cb995352f96fBob Halleylwres_context_allocmem(lwres_context_t *ctx, size_t len) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley REQUIRE(len != 0);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley return (CTXMALLOC(len));
1ccbfca64ae86ace521053773001cb995352f96fBob Halley}
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleystatic void *
1ccbfca64ae86ace521053773001cb995352f96fBob Halleylwres_malloc(void *arg, size_t len) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley void *mem;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley UNUSED(arg);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley mem = malloc(len);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley if (mem == NULL)
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley return (NULL);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley memset(mem, 0xe5, len);
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister return (mem);
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister}
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister
d549c3734869b48e740c64e80890bcb6f3ce672cJames Bristerstatic void
d549c3734869b48e740c64e80890bcb6f3ce672cJames Bristerlwres_free(void *arg, void *mem, size_t len) {
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister UNUSED(arg);
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister
d549c3734869b48e740c64e80890bcb6f3ce672cJames Brister memset(mem, 0xa9, len);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley free(mem);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley}
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleystatic lwres_result_t
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleycontext_connect(lwres_context_t *ctx) {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley int s;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence int ret;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley struct sockaddr_in sin;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley struct sockaddr_in6 sin6;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley struct sockaddr *sa;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley LWRES_SOCKADDR_LEN_T salen;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley int domain;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
1ccbfca64ae86ace521053773001cb995352f96fBob Halley if (ctx->confdata.lwnext != 0) {
1ccbfca64ae86ace521053773001cb995352f96fBob Halley memcpy(&ctx->address, &ctx->confdata.lwservers[0],
1ccbfca64ae86ace521053773001cb995352f96fBob Halley sizeof(lwres_addr_t));
1ccbfca64ae86ace521053773001cb995352f96fBob Halley LWRES_LINK_INIT(&ctx->address, link);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley } else {
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley /* The default is the IPv4 loopback address 127.0.0.1. */
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley memset(&ctx->address, 0, sizeof(ctx->address));
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley ctx->address.family = LWRES_ADDRTYPE_V4;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence ctx->address.length = 4;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley ctx->address.address[0] = 127;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley ctx->address.address[1] = 0;
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews ctx->address.address[2] = 0;
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews ctx->address.address[3] = 1;
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews }
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews if (ctx->address.family == LWRES_ADDRTYPE_V4) {
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews memcpy(&sin.sin_addr, ctx->address.address,
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews sizeof(sin.sin_addr));
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews sin.sin_port = htons(lwres_udp_port);
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews sin.sin_family = AF_INET;
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews sa = (struct sockaddr *)&sin;
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews salen = sizeof(sin);
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews domain = PF_INET;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence } else if (ctx->address.family == LWRES_ADDRTYPE_V6) {
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews memcpy(&sin6.sin6_addr, ctx->address.address,
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews sizeof(sin6.sin6_addr));
a6733246eafeb43755ce6d7ec3627ac4209cbccbMark Andrews sin6.sin6_port = htons(lwres_udp_port);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley sin6.sin6_family = AF_INET6;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley sa = (struct sockaddr *)&sin6;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley salen = sizeof(sin6);
1ccbfca64ae86ace521053773001cb995352f96fBob Halley domain = PF_INET6;
1ccbfca64ae86ace521053773001cb995352f96fBob Halley } else
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews return (LWRES_R_IOERROR);
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews s = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (s < 0)
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews return (LWRES_R_IOERROR);
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews ret = connect(s, sa, salen);
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (ret != 0) {
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews close(s);
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews return (LWRES_R_IOERROR);
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews }
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews MAKE_NONBLOCKING(s, ret);
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (ret < 0)
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews return (LWRES_R_IOERROR);
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley ctx->sock = s;
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley return (LWRES_R_SUCCESS);
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley}
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrenceint
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halleylwres_context_getsocket(lwres_context_t *ctx) {
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley return (ctx->sock);
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley}
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halley
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halleylwres_result_t
b3e2e7c4d6b5c5ee90ba5bb775d635834dccec81Bob Halleylwres_context_send(lwres_context_t *ctx,
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington void *sendbase, int sendlen) {
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington int ret;
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington lwres_result_t lwresult;
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington if (ctx->sock == -1) {
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington lwresult = context_connect(ctx);
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington if (lwresult != LWRES_R_SUCCESS)
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington return (lwresult);
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington }
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington ret = sendto(ctx->sock, sendbase, sendlen, 0, NULL, 0);
fe12eb4fc27f49c6b3e42b1d7a6b40310e41e6dfBrian Wellington if (ret < 0)
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halley return (LWRES_R_IOERROR);
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halley if (ret != sendlen)
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley return (LWRES_R_IOERROR);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley return (LWRES_R_SUCCESS);
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley}
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halley
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halleylwres_result_t
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halleylwres_context_recv(lwres_context_t *ctx,
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halley void *recvbase, int recvlen,
a99979c686ae04efd55ba8f0aacf32493b4aa7faBob Halley int *recvd_len)
48481c9b6e19501457bcbc2995555412f352b99fBob Halley{
48481c9b6e19501457bcbc2995555412f352b99fBob Halley LWRES_SOCKADDR_LEN_T fromlen;
48481c9b6e19501457bcbc2995555412f352b99fBob Halley struct sockaddr_in sin;
48481c9b6e19501457bcbc2995555412f352b99fBob Halley struct sockaddr_in6 sin6;
48481c9b6e19501457bcbc2995555412f352b99fBob Halley struct sockaddr *sa;
48481c9b6e19501457bcbc2995555412f352b99fBob Halley int ret;
48481c9b6e19501457bcbc2995555412f352b99fBob Halley
48481c9b6e19501457bcbc2995555412f352b99fBob Halley if (ctx->address.family == LWRES_ADDRTYPE_V4) {
48481c9b6e19501457bcbc2995555412f352b99fBob Halley sa = (struct sockaddr *)&sin;
48481c9b6e19501457bcbc2995555412f352b99fBob Halley fromlen = sizeof(sin);
48481c9b6e19501457bcbc2995555412f352b99fBob Halley } else {
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff sa = (struct sockaddr *)&sin6;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb fromlen = sizeof(sin6);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley }
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley /*
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley * The address of fromlen is cast to void * to shut up compiler
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley * warnings, namely on systems that have the sixth parameter
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * prototyped as a signed int when LWRES_SOCKADDR_LEN_T is
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley * defined as unsigned.
7829fad4093f2c1985b1efb7cea00287ff015d2bckb */
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley ret = recvfrom(ctx->sock, recvbase, recvlen, 0, sa, (void *)&fromlen);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff if (ret < 0)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (LWRES_R_IOERROR);
7a00d69909ace5dc11bcff9c1e07c311f92a7f8eWitold Krecicki
7a00d69909ace5dc11bcff9c1e07c311f92a7f8eWitold Krecicki if (ret == recvlen)
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley return (LWRES_R_TOOLARGE);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley /*
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley * If we got something other than what we expect, have the caller
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley * wait for another packet. This can happen if an old result
7829fad4093f2c1985b1efb7cea00287ff015d2bckb * comes in, or if someone is sending us random stuff.
7829fad4093f2c1985b1efb7cea00287ff015d2bckb */
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley if (ctx->address.family == LWRES_ADDRTYPE_V4) {
7a00d69909ace5dc11bcff9c1e07c311f92a7f8eWitold Krecicki if (fromlen != sizeof(sin)
7a00d69909ace5dc11bcff9c1e07c311f92a7f8eWitold Krecicki || memcmp(&sin.sin_addr, ctx->address.address,
7a00d69909ace5dc11bcff9c1e07c311f92a7f8eWitold Krecicki sizeof(sin.sin_addr)) != 0
7a00d69909ace5dc11bcff9c1e07c311f92a7f8eWitold Krecicki || sin.sin_port != htons(lwres_udp_port))
7a00d69909ace5dc11bcff9c1e07c311f92a7f8eWitold Krecicki return (LWRES_R_RETRY);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb } else {
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley if (fromlen != sizeof(sin6)
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley || memcmp(&sin6.sin6_addr, ctx->address.address,
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff sizeof(sin6.sin6_addr)) != 0
bad8294771671374e811afac79a20cc6927e3e2fBob Halley || sin6.sin6_port != htons(lwres_udp_port))
553ead32ff5b00284e574dcabc39115d4d74ec66Evan Hunt return (LWRES_R_RETRY);
e174044290953a2499f574e35cc9c22ba126a303Mark Andrews }
e174044290953a2499f574e35cc9c22ba126a303Mark Andrews
e174044290953a2499f574e35cc9c22ba126a303Mark Andrews if (recvd_len != NULL)
e174044290953a2499f574e35cc9c22ba126a303Mark Andrews *recvd_len = ret;
553ead32ff5b00284e574dcabc39115d4d74ec66Evan Hunt
553ead32ff5b00284e574dcabc39115d4d74ec66Evan Hunt return (LWRES_R_SUCCESS);
553ead32ff5b00284e574dcabc39115d4d74ec66Evan Hunt}
553ead32ff5b00284e574dcabc39115d4d74ec66Evan Hunt
553ead32ff5b00284e574dcabc39115d4d74ec66Evan Huntlwres_result_t
7a00d69909ace5dc11bcff9c1e07c311f92a7f8eWitold Krecickilwres_context_sendrecv(lwres_context_t *ctx,
7a00d69909ace5dc11bcff9c1e07c311f92a7f8eWitold Krecicki void *sendbase, int sendlen,
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff void *recvbase, int recvlen,
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley int *recvd_len)
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley{
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley lwres_result_t result;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley int ret2;
62837b832f6a9999976d607eb0a9125bbbbb138bBob Halley fd_set readfds;
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley struct timeval timeout;
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley /*
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley * Type of tv_sec is long, so make sure the unsigned long timeout
0deebcd15ad440c7ecaaa77f8e06232b331aae79Mark Andrews * does not overflow it.
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley */
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley if (ctx->timeout <= LONG_MAX)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb timeout.tv_sec = (long)ctx->timeout;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff else
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley timeout.tv_sec = LONG_MAX;
e174044290953a2499f574e35cc9c22ba126a303Mark Andrews
e174044290953a2499f574e35cc9c22ba126a303Mark Andrews timeout.tv_usec = 0;
e174044290953a2499f574e35cc9c22ba126a303Mark Andrews
7829fad4093f2c1985b1efb7cea00287ff015d2bckb result = lwres_context_send(ctx, sendbase, sendlen);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley if (result != LWRES_R_SUCCESS)
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley return (result);
27ffc5a69779c3c7224580a89aa2bf0a3ff8c16dBob Halley again:
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley FD_ZERO(&readfds);
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley FD_SET(ctx->sock, &readfds);
86529bb6979dbe3ffd7bc2df078fac21cb339953Mark Andrews ret2 = select(ctx->sock + 1, &readfds, NULL, NULL, &timeout);
86529bb6979dbe3ffd7bc2df078fac21cb339953Mark Andrews
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley /*
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley * What happened with select?
7d44d8aacda98eb2b526af34757a6bbcc97cd388Bob Halley */
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley if (ret2 < 0)
b03b67a6f1ea2966367e7beb2ef276ed6a1d3f92Bob Halley return (LWRES_R_IOERROR);
8e6b386ab7e2d1bd8efedecbb8f4efb6b572a866Tinderbox User if (ret2 == 0)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (LWRES_R_TIMEOUT);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb result = lwres_context_recv(ctx, recvbase, recvlen, recvd_len);
7829fad4093f2c1985b1efb7cea00287ff015d2bckb if (result == LWRES_R_RETRY)
7829fad4093f2c1985b1efb7cea00287ff015d2bckb goto again;
7829fad4093f2c1985b1efb7cea00287ff015d2bckb
7829fad4093f2c1985b1efb7cea00287ff015d2bckb return (result);
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff}
bad8294771671374e811afac79a20cc6927e3e2fBob Halley