0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2000, 2001, 2003-2005, 2007-2009, 2012-2014, 2016 Internet Systems Consortium, Inc. ("ISC")
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/.
d7201de09b85929a86b157f4b2d91667c68c6b52Automatic Updater/* $Id: context.c,v 1.55 2009/09/02 23:48:03 tbox Exp $ */
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 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 Once memory for the structure has been allocated, it is initialized
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein using lwres_conf_init() and returned via *contextp.
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 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 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 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\section context_return Return Values
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 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 #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\section context_see See Also
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein lwres_conf_init(), malloc, free.
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.
001d1ceec69e181f62367f4d344fb386135d91b1Andreas Gustafsson * Make a socket nonblocking.
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;
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * lwres_result_t
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * Creates a #lwres_context_t structure for use in
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * lightweight resolver operations.
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Grafflwres_context_create(lwres_context_t **contextp, void *arg,
efe2f579ba6fbec4229129015780f2d925085b04Michael Graff unsigned int flags)
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff REQUIRE(contextp != NULL && *contextp == NULL);
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 if (malloc_function == NULL || free_function == NULL) {
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff ctx = malloc_function(arg, sizeof(lwres_context_t));
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff * Set up the context.
1d1d2fa57a954333c32ca3104b812b4e2389196fBrian Wellington ctx->serial = time(NULL); /* XXXMLG or BEW */
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 if ((flags & (LWRES_CONTEXT_USEIPV4 | LWRES_CONTEXT_USEIPV6)) ==
10a6f640ed599cbe4a8b98c46b71a61d24e5bbe7Tatuya JINMEI 神明達哉 if ((flags & (LWRES_CONTEXT_USEIPV4 | LWRES_CONTEXT_USEIPV6)) ==
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.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_context_destroy(lwres_context_t **contextp) {
64bed6c54393c2d213db83e9b171fb7c318cfc8eMichael Graff REQUIRE(contextp != NULL && *contextp != NULL);
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% Increments the serial number and returns the previous value. */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_context_nextserial(lwres_context_t *ctx) {
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% Sets the serial number for context *ctx to serial. */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_context_initserial(lwres_context_t *ctx, lwres_uint32_t serial) {
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% Frees len bytes of space starting at location mem. */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_context_freemem(lwres_context_t *ctx, void *mem, size_t len) {
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% Allocates len bytes of memory and if successful returns a pointer to the allocated storage. */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_context_allocmem(lwres_context_t *ctx, size_t len) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencelwres_free(void *arg, void *mem, size_t len) {
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(&ctx->address, &ctx->confdata.lwservers[0],
5b34d8267e8228b4615b9eae4e32d9ad1f308179Andreas Gustafsson /* The default is the IPv4 loopback address 127.0.0.1. */
5b34d8267e8228b4615b9eae4e32d9ad1f308179Andreas Gustafsson memset(&ctx->address, 0, sizeof(ctx->address));
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington if (ctx->address.family == LWRES_ADDRTYPE_V4) {
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington } else if (ctx->address.family == LWRES_ADDRTYPE_V6) {
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington s = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
47ee25b1f58a5924c51b59194b84621b9b7b6ba5Mark Andrews if (s < 0) {
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafssonlwres_context_getsocket(lwres_context_t *ctx) {
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson ret = sendto(ctx->sock, sendbase, sendlen, 0, NULL, 0);
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington if (ctx->address.family == LWRES_ADDRTYPE_V4) {
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.
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington ret = recvfrom(ctx->sock, recvbase, recvlen, 0, sa, (void *)&fromlen);
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.
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington if (ctx->address.family == LWRES_ADDRTYPE_V4) {
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington || memcmp(&sin.sin_addr, ctx->address.address,
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington || memcmp(&sin6.sin6_addr, ctx->address.address,
8f80322fb58bac39c84bb76cb2bc82406bd6a9ecBrian Wellington || sin6.sin6_port != htons(lwres_udp_port))
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% performs I/O for the context ctx. */
c6b65dff5123de7229b281329928a3b457338f0aAutomatic Updater * Type of tv_sec is 32 bits long.
7bee275ebe250b5e1705a997e2ee3e685d146fbdAndreas Gustafsson result = lwres_context_send(ctx, sendbase, sendlen);
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt * If this is not checked, select() can overflow,
ef22fffeebffacbcbce1f8d68d0c3f29a7d4a59eEvan Hunt * causing corruption elsewhere.
d257033612f3052265085e0d7fdc116c871a28c0Michael Graff ret2 = select(ctx->sock + 1, &readfds, NULL, NULL, &timeout);
b91bbaf50cf6d0c2cad7323720495165595e413bMichael Graff * What happened with select?