64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff/*
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2000, 2001, 2003-2005, 2007-2009, 2012-2014, 2016 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff */
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
d7201de09b85929a86b157f4b2d91667c68c6b52Automatic Updater/* $Id: context.c,v 1.55 2009/09/02 23:48:03 tbox Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
c6b65dff5123de7229b281329928a3b457338f0aAutomatic Updater/*! \file context.c
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_context_create() creates a #lwres_context_t structure for use in
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lightweight resolver operations. It holds a socket and other data
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein needed for communicating with a resolver daemon. The new
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_context_t is returned through contextp, a pointer to a
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_context_t pointer. This lwres_context_t pointer must initially
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein be NULL, and is modified to point to the newly created
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_context_t.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein When the lightweight resolver needs to perform dynamic memory
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein allocation, it will call malloc_function to allocate memory and
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein free_function to free it. If malloc_function and free_function are
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein NULL, memory is allocated using malloc and free. It is not
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein permitted to have a NULL malloc_function and a non-NULL free_function
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein or vice versa. arg is passed as the first parameter to the memory
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein allocation functions. If malloc_function and free_function are NULL,
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein arg is unused and should be passed as NULL.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein Once memory for the structure has been allocated, it is initialized
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein using lwres_conf_init() and returned via *contextp.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_context_destroy() destroys a #lwres_context_t, closing its
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein socket. contextp is a pointer to a pointer to the context that is to
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein be destroyed. The pointer will be set to NULL when the context has
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein been destroyed.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein The context holds a serial number that is used to identify resolver
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein request packets and associate responses with the corresponding
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein requests. This serial number is controlled using
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_context_initserial() and lwres_context_nextserial().
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_context_initserial() sets the serial number for context *ctx to
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein serial. lwres_context_nextserial() increments the serial number and
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein returns the previous value.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein Memory for a lightweight resolver context is allocated and freed using
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_context_allocmem() and lwres_context_freemem(). These use
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein whatever allocations were defined when the context was created with
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_context_create(). lwres_context_allocmem() allocates len bytes
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein of memory and if successful returns a pointer to the allocated
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein storage. lwres_context_freemem() frees len bytes of space starting at
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein location mem.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_context_sendrecv() performs I/O for the context ctx. Data are
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein read and written from the context's socket. It writes data from
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein sendbase -- typically a lightweight resolver query packet -- and waits
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein for a reply which is copied to the receive buffer at recvbase. The
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein number of bytes that were written to this receive buffer is returned
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein in *recvd_len.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein\section context_return Return Values
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_context_create() returns #LWRES_R_NOMEMORY if memory for the
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein struct lwres_context could not be allocated, #LWRES_R_SUCCESS
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein otherwise.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein Successful calls to the memory allocator lwres_context_allocmem()
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein return a pointer to the start of the allocated space. It returns NULL
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein if memory could not be allocated.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein #LWRES_R_SUCCESS is returned when lwres_context_sendrecv() completes
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein successfully. #LWRES_R_IOERROR is returned if an I/O error occurs and
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein #LWRES_R_TIMEOUT is returned if lwres_context_sendrecv() times out
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein waiting for a response.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein\section context_see See Also
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_conf_init(), malloc, free.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein */
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff#include <config.h>
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff#include <fcntl.h>
74cf566d92d610c2dc090a0dc7f77651c0fb0635David Lawrence#include <limits.h>
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff#include <stdlib.h>
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff#include <string.h>
90c845947a6987a95d4facaed61406362fbb58dfBrian Wellington#include <time.h>
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff#include <unistd.h>
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff#include <lwres/lwres.h>
3c0a81897768d0378813865278a49d285c95b8b8Brian Wellington#include <lwres/net.h>
363cb30a83e8e57bc8874e621910f0e23dd84909Mark Andrews#include <lwres/platform.h>
363cb30a83e8e57bc8874e621910f0e23dd84909Mark Andrews
363cb30a83e8e57bc8874e621910f0e23dd84909Mark Andrews#ifdef LWRES_PLATFORM_NEEDSYSSELECTH
363cb30a83e8e57bc8874e621910f0e23dd84909Mark Andrews#include <sys/select.h>
363cb30a83e8e57bc8874e621910f0e23dd84909Mark Andrews#endif
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff#include "context_p.h"
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff#include "assert_p.h"
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*!
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrence * Some systems define the socket length argument as an int, some as size_t,
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrence * some as socklen_t. The last is what the current POSIX standard mandates.
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrence * This definition is here so it can be portable but easily changed if needed.
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrence */
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrence#ifndef LWRES_SOCKADDR_LEN_T
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrence#define LWRES_SOCKADDR_LEN_T unsigned int
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrence#endif
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrence
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*!
001d1ceec69e181f62367f4d344fb386135d91b1Andreas Gustafsson * Make a socket nonblocking.
71811653336a000f6c61d26d4b2a0c0d2cec9c25Danny Mayer */
71811653336a000f6c61d26d4b2a0c0d2cec9c25Danny Mayer#ifndef MAKE_NONBLOCKING
001d1ceec69e181f62367f4d344fb386135d91b1Andreas Gustafsson#define MAKE_NONBLOCKING(sd, retval) \
001d1ceec69e181f62367f4d344fb386135d91b1Andreas Gustafssondo { \
001d1ceec69e181f62367f4d344fb386135d91b1Andreas Gustafsson retval = fcntl(sd, F_GETFL, 0); \
001d1ceec69e181f62367f4d344fb386135d91b1Andreas Gustafsson if (retval != -1) { \
3489d64bde03af5c7950661b083b530bd285ec27Mark Andrews retval |= O_NONBLOCK; \
001d1ceec69e181f62367f4d344fb386135d91b1Andreas Gustafsson retval = fcntl(sd, F_SETFL, retval); \
001d1ceec69e181f62367f4d344fb386135d91b1Andreas Gustafsson } \
71811653336a000f6c61d26d4b2a0c0d2cec9c25Danny Mayer} while (0)
71811653336a000f6c61d26d4b2a0c0d2cec9c25Danny Mayer#endif
71811653336a000f6c61d26d4b2a0c0d2cec9c25Danny Mayer
e61793f0865117ad87a19d6e245bea8f3b712d1bDanny MayerLIBLWRES_EXTERNAL_DATA lwres_uint16_t lwres_udp_port = LWRES_UDP_PORT;
e61793f0865117ad87a19d6e245bea8f3b712d1bDanny MayerLIBLWRES_EXTERNAL_DATA const char *lwres_resolv_conf = LWRES_RESOLV_CONF;
412e5c62115e881cce79921e2467c6c0990a0a8aBrian Wellington
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrencestatic void *
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrencelwres_malloc(void *, size_t);
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrence
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrencestatic void
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrencelwres_free(void *, void *, size_t);
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrence
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*!
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * lwres_result_t
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein */
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrencestatic lwres_result_t
03a0fca86dd9db6a40743107ec9dea7c33e46a7aDavid Lawrencecontext_connect(lwres_context_t *);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*%
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * Creates a #lwres_context_t structure for use in
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * lightweight resolver operations.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein */
01933e930208da3291de3722cb0d0787636b1e4fMichael Grafflwres_result_t
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Grafflwres_context_create(lwres_context_t **contextp, void *arg,
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff lwres_malloc_t malloc_function,
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff lwres_free_t free_function,
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff unsigned int flags)
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff{
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff lwres_context_t *ctx;
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff REQUIRE(contextp != NULL && *contextp == NULL);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff /*
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * If we were not given anything special to use, use our own
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * functions. These are just wrappers around malloc() and free().
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff */
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff if (malloc_function == NULL || free_function == NULL) {
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff REQUIRE(malloc_function == NULL);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff REQUIRE(free_function == NULL);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff malloc_function = lwres_malloc;
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff free_function = lwres_free;
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff }
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff ctx = malloc_function(arg, sizeof(lwres_context_t));
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Graff if (ctx == NULL)
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Graff return (LWRES_R_NOMEMORY);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff /*
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * Set up the context.
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff */
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff ctx->malloc = malloc_function;
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff ctx->free = free_function;
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff ctx->arg = arg;
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff ctx->sock = -1;
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff ctx->timeout = LWRES_DEFAULT_TIMEOUT;
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews#ifndef WIN32
1d1d2fa57a954333c32ca3104b812b4e2389196fBrian Wellington ctx->serial = time(NULL); /* XXXMLG or BEW */
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews#else
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews ctx->serial = _time32(NULL);
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews#endif
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 ctx->use_ipv4 = 1;
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 ctx->use_ipv6 = 1;
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 if ((flags & (LWRES_CONTEXT_USEIPV4 | LWRES_CONTEXT_USEIPV6)) ==
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 LWRES_CONTEXT_USEIPV6) {
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 ctx->use_ipv4 = 0;
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 }
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 if ((flags & (LWRES_CONTEXT_USEIPV4 | LWRES_CONTEXT_USEIPV6)) ==
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 LWRES_CONTEXT_USEIPV4) {
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 ctx->use_ipv6 = 0;
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 }
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff /*
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff * Init resolv.conf bits.
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff */
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff lwres_conf_init(ctx);
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff *contextp = ctx;
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Graff return (LWRES_R_SUCCESS);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff}
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*%
c6b65dff5123de7229b281329928a3b457338f0aAutomatic UpdaterDestroys a #lwres_context_t, closing its socket.
c6b65dff5123de7229b281329928a3b457338f0aAutomatic Updatercontextp is a pointer to a pointer to the context that is
c6b65dff5123de7229b281329928a3b457338f0aAutomatic Updaterto be destroyed. The pointer will be set to NULL
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austeinwhen the context has been destroyed.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein */
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graffvoid
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_context_destroy(lwres_context_t **contextp) {
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff lwres_context_t *ctx;
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff REQUIRE(contextp != NULL && *contextp != NULL);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff ctx = *contextp;
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff *contextp = NULL;
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
c1cfd8ef05f47f2ccb5db80639e9501c9f16864cMichael Graff if (ctx->sock != -1) {
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#ifdef WIN32
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews DestroySockets();
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#endif
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson (void)close(ctx->sock);
c1cfd8ef05f47f2ccb5db80639e9501c9f16864cMichael Graff ctx->sock = -1;
c1cfd8ef05f47f2ccb5db80639e9501c9f16864cMichael Graff }
c1cfd8ef05f47f2ccb5db80639e9501c9f16864cMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff CTXFREE(ctx, sizeof(lwres_context_t));
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff}
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% Increments the serial number and returns the previous value. */
7a166c5c61a5aaa6eeb929bed152dc0a6b128e3dMichael Grafflwres_uint32_t
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_context_nextserial(lwres_context_t *ctx) {
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff REQUIRE(ctx != NULL);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff return (ctx->serial++);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff}
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% Sets the serial number for context *ctx to serial. */
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graffvoid
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_context_initserial(lwres_context_t *ctx, lwres_uint32_t serial) {
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff REQUIRE(ctx != NULL);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff ctx->serial = serial;
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff}
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% Frees len bytes of space starting at location mem. */
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graffvoid
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_context_freemem(lwres_context_t *ctx, void *mem, size_t len) {
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff REQUIRE(mem != NULL);
5eb91bd90e3ad3426e5e3213031556a737cf3809Mark Andrews REQUIRE(len != 0U);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff CTXFREE(mem, len);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff}
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% Allocates len bytes of memory and if successful returns a pointer to the allocated storage. */
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graffvoid *
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_context_allocmem(lwres_context_t *ctx, size_t len) {
5eb91bd90e3ad3426e5e3213031556a737cf3809Mark Andrews REQUIRE(len != 0U);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff return (CTXMALLOC(len));
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff}
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graffstatic void *
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_malloc(void *arg, size_t len) {
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff void *mem;
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
68aa880dd538ab5643abdb07a800d0443e630d2eBrian Wellington UNUSED(arg);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff mem = malloc(len);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff if (mem == NULL)
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff return (NULL);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff memset(mem, 0xe5, len);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff return (mem);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff}
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graffstatic void
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_free(void *arg, void *mem, size_t len) {
68aa880dd538ab5643abdb07a800d0443e630d2eBrian Wellington UNUSED(arg);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff memset(mem, 0xa9, len);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff free(mem);
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff}
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff
01933e930208da3291de3722cb0d0787636b1e4fMichael Graffstatic lwres_result_t
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencecontext_connect(lwres_context_t *ctx) {
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews#ifndef WIN32
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff int s;
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews#else
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews SOCKET s;
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews#endif
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff int ret;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington struct sockaddr_in sin;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington struct sockaddr_in6 sin6;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington struct sockaddr *sa;
3c0a81897768d0378813865278a49d285c95b8b8Brian Wellington LWRES_SOCKADDR_LEN_T salen;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington int domain;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington if (ctx->confdata.lwnext != 0) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&ctx->address, &ctx->confdata.lwservers[0],
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt sizeof(lwres_addr_t));
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington LWRES_LINK_INIT(&ctx->address, link);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington } else {
5b34d8267e8228b4615b9eae4e32d9ad1f308179Andreas Gustafsson /* The default is the IPv4 loopback address 127.0.0.1. */
5b34d8267e8228b4615b9eae4e32d9ad1f308179Andreas Gustafsson memset(&ctx->address, 0, sizeof(ctx->address));
5b34d8267e8228b4615b9eae4e32d9ad1f308179Andreas Gustafsson ctx->address.family = LWRES_ADDRTYPE_V4;
5b34d8267e8228b4615b9eae4e32d9ad1f308179Andreas Gustafsson ctx->address.length = 4;
5b34d8267e8228b4615b9eae4e32d9ad1f308179Andreas Gustafsson ctx->address.address[0] = 127;
5b34d8267e8228b4615b9eae4e32d9ad1f308179Andreas Gustafsson ctx->address.address[1] = 0;
5b34d8267e8228b4615b9eae4e32d9ad1f308179Andreas Gustafsson ctx->address.address[2] = 0;
5b34d8267e8228b4615b9eae4e32d9ad1f308179Andreas Gustafsson ctx->address.address[3] = 1;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington }
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington if (ctx->address.family == LWRES_ADDRTYPE_V4) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&sin.sin_addr, ctx->address.address,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt sizeof(sin.sin_addr));
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington sin.sin_port = htons(lwres_udp_port);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington sin.sin_family = AF_INET;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington sa = (struct sockaddr *)&sin;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington salen = sizeof(sin);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington domain = PF_INET;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington } else if (ctx->address.family == LWRES_ADDRTYPE_V6) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&sin6.sin6_addr, ctx->address.address,
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt sizeof(sin6.sin6_addr));
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington sin6.sin6_port = htons(lwres_udp_port);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington sin6.sin6_family = AF_INET6;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington sa = (struct sockaddr *)&sin6;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington salen = sizeof(sin6);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington domain = PF_INET6;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington } else
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington return (LWRES_R_IOERROR);
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#ifdef WIN32
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews InitSockets();
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#endif
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington s = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews#ifndef WIN32
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews if (s < 0) {
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews return (LWRES_R_IOERROR);
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews }
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews#else
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews if (s == INVALID_SOCKET) {
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews DestroySockets();
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Graff return (LWRES_R_IOERROR);
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews }
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews#endif
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington ret = connect(s, sa, salen);
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff if (ret != 0) {
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#ifdef WIN32
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews DestroySockets();
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#endif
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson (void)close(s);
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Graff return (LWRES_R_IOERROR);
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff }
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff
001d1ceec69e181f62367f4d344fb386135d91b1Andreas Gustafsson MAKE_NONBLOCKING(s, ret);
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews if (ret < 0) {
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#ifdef WIN32
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews DestroySockets();
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews#endif
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews (void)close(s);
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson return (LWRES_R_IOERROR);
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews }
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews ctx->sock = (int)s;
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Graff return (LWRES_R_SUCCESS);
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff}
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafssonint
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafssonlwres_context_getsocket(lwres_context_t *ctx) {
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson return (ctx->sock);
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson}
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafssonlwres_result_t
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafssonlwres_context_send(lwres_context_t *ctx,
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson void *sendbase, int sendlen) {
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson int ret;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington lwres_result_t lwresult;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington if (ctx->sock == -1) {
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington lwresult = context_connect(ctx);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington if (lwresult != LWRES_R_SUCCESS)
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington return (lwresult);
47c5b8af920a93763c97d9a93ea1fd766961a5b3Evan Hunt INSIST(ctx->sock >= 0);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington }
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson ret = sendto(ctx->sock, sendbase, sendlen, 0, NULL, 0);
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson if (ret < 0)
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson return (LWRES_R_IOERROR);
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson if (ret != sendlen)
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson return (LWRES_R_IOERROR);
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson return (LWRES_R_SUCCESS);
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson}
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafssonlwres_result_t
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafssonlwres_context_recv(lwres_context_t *ctx,
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson void *recvbase, int recvlen,
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson int *recvd_len)
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson{
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson LWRES_SOCKADDR_LEN_T fromlen;
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson struct sockaddr_in sin;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington struct sockaddr_in6 sin6;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington struct sockaddr *sa;
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson int ret;
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington if (ctx->address.family == LWRES_ADDRTYPE_V4) {
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington sa = (struct sockaddr *)&sin;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington fromlen = sizeof(sin);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington } else {
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington sa = (struct sockaddr *)&sin6;
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington fromlen = sizeof(sin6);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington }
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson /*
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson * The address of fromlen is cast to void * to shut up compiler
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson * warnings, namely on systems that have the sixth parameter
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson * prototyped as a signed int when LWRES_SOCKADDR_LEN_T is
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson * defined as unsigned.
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson */
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington ret = recvfrom(ctx->sock, recvbase, recvlen, 0, sa, (void *)&fromlen);
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson if (ret < 0)
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson return (LWRES_R_IOERROR);
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson
5733d25b06b46067b3751d10436d82aef09cd705Brian Wellington if (ret == recvlen)
5733d25b06b46067b3751d10436d82aef09cd705Brian Wellington return (LWRES_R_TOOLARGE);
5733d25b06b46067b3751d10436d82aef09cd705Brian Wellington
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson /*
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson * If we got something other than what we expect, have the caller
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson * wait for another packet. This can happen if an old result
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson * comes in, or if someone is sending us random stuff.
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson */
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington if (ctx->address.family == LWRES_ADDRTYPE_V4) {
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington if (fromlen != sizeof(sin)
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington || memcmp(&sin.sin_addr, ctx->address.address,
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington sizeof(sin.sin_addr)) != 0
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington || sin.sin_port != htons(lwres_udp_port))
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington return (LWRES_R_RETRY);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington } else {
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington if (fromlen != sizeof(sin6)
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington || memcmp(&sin6.sin6_addr, ctx->address.address,
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington sizeof(sin6.sin6_addr)) != 0
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington || sin6.sin6_port != htons(lwres_udp_port))
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington return (LWRES_R_RETRY);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington }
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson if (recvd_len != NULL)
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson *recvd_len = ret;
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson return (LWRES_R_SUCCESS);
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson}
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% performs I/O for the context ctx. */
01933e930208da3291de3722cb0d0787636b1e4fMichael Grafflwres_result_t
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Grafflwres_context_sendrecv(lwres_context_t *ctx,
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff void *sendbase, int sendlen,
1a70537f01305cb84d402c84b1ba7cc89b97a5dcMichael Graff void *recvbase, int recvlen,
1a70537f01305cb84d402c84b1ba7cc89b97a5dcMichael Graff int *recvd_len)
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff{
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson lwres_result_t result;
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff int ret2;
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff fd_set readfds;
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff struct timeval timeout;
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff
74cf566d92d610c2dc090a0dc7f77651c0fb0635David Lawrence /*
c6b65dff5123de7229b281329928a3b457338f0aAutomatic Updater * Type of tv_sec is 32 bits long.
74cf566d92d610c2dc090a0dc7f77651c0fb0635David Lawrence */
0d51617897658fcd9eed3a22f7ac8d77a7a260beMark Andrews if (ctx->timeout <= 0x7FFFFFFFU)
0d51617897658fcd9eed3a22f7ac8d77a7a260beMark Andrews timeout.tv_sec = (int)ctx->timeout;
74cf566d92d610c2dc090a0dc7f77651c0fb0635David Lawrence else
0d51617897658fcd9eed3a22f7ac8d77a7a260beMark Andrews timeout.tv_sec = 0x7FFFFFFF;
74cf566d92d610c2dc090a0dc7f77651c0fb0635David Lawrence
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff timeout.tv_usec = 0;
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson result = lwres_context_send(ctx, sendbase, sendlen);
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson if (result != LWRES_R_SUCCESS)
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson return (result);
d7201de09b85929a86b157f4b2d91667c68c6b52Automatic Updater
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt /*
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt * If this is not checked, select() can overflow,
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt * causing corruption elsewhere.
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt */
d364948549856a00bb6d4cd1a9475cb25544cc8eTatuya JINMEI 神明達哉 if (ctx->sock >= (int)FD_SETSIZE) {
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt close(ctx->sock);
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt ctx->sock = -1;
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt return (LWRES_R_IOERROR);
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt }
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Graff again:
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff FD_ZERO(&readfds);
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff FD_SET(ctx->sock, &readfds);
d257033612f3052265085e0d7fdc116c871a28c0Michael Graff ret2 = select(ctx->sock + 1, &readfds, NULL, NULL, &timeout);
c6b65dff5123de7229b281329928a3b457338f0aAutomatic Updater
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff /*
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff * What happened with select?
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff */
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff if (ret2 < 0)
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff return (LWRES_R_IOERROR);
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff if (ret2 == 0)
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff return (LWRES_R_TIMEOUT);
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson result = lwres_context_recv(ctx, recvbase, recvlen, recvd_len);
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson if (result == LWRES_R_RETRY)
8cd870e3f5e3db9808a4a0d6f98db3d1a5348e40Michael Graff goto again;
c6b65dff5123de7229b281329928a3b457338f0aAutomatic Updater
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson return (result);
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff}