/*
* Copyright (C) 2000, 2001, 2004, 2005, 2007, 2014, 2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/* $Id: lwresutil.c,v 1.34 2007/06/19 23:47:22 tbox Exp $ */
/*! \file */
/**
* lwres_string_parse() retrieves a DNS-encoded string starting the
* current pointer of lightweight resolver buffer b: i.e. b->current.
* When the function returns, the address of the first byte of the
* encoded string is returned via *c and the length of that string is
* given by *len. The buffer's current pointer is advanced to point at
* the character following the string length, the encoded string, and
* the trailing NULL character.
*
* lwres_addr_parse() extracts an address from the buffer b. The
* buffer's current pointer b->current is presumed to point at an
* encoded address: the address preceded by a 32-bit protocol family
* identifier and a 16-bit length field. The encoded address is copied
* to addr->address and addr->length indicates the size in bytes of
* the address that was copied. b->current is advanced to point at the
* next byte of available data in the buffer following the encoded
* address.
*
* lwres_getaddrsbyname() and lwres_getnamebyaddr() use the
* lwres_gnbaresponse_t structure defined below:
*
* \code
* typedef struct {
* lwres_uint32_t flags;
* lwres_uint16_t naliases;
* lwres_uint16_t naddrs;
* char *realname;
* char **aliases;
* lwres_uint16_t realnamelen;
* lwres_uint16_t *aliaslen;
* lwres_addrlist_t addrs;
* void *base;
* size_t baselen;
* } lwres_gabnresponse_t;
* \endcode
*
* The contents of this structure are not manipulated directly but
* they are controlled through the \link lwres_gabn.c lwres_gabn*\endlink functions.
*
* The lightweight resolver uses lwres_getaddrsbyname() to perform
* foward lookups. Hostname name is looked up using the resolver
* context ctx for memory allocation. addrtypes is a bitmask
* indicating which type of addresses are to be looked up. Current
* values for this bitmask are #LWRES_ADDRTYPE_V4 for IPv4 addresses
* and #LWRES_ADDRTYPE_V6 for IPv6 addresses. Results of the lookup are
* returned in *structp.
*
* lwres_getnamebyaddr() performs reverse lookups. Resolver context
* ctx is used for memory allocation. The address type is indicated by
* addrtype: #LWRES_ADDRTYPE_V4 or #LWRES_ADDRTYPE_V6. The address to be
* looked up is given by addr and its length is addrlen bytes. The
* result of the function call is made available through *structp.
*
* \section lwresutil_return Return Values
*
* Successful calls to lwres_string_parse() and lwres_addr_parse()
* return #LWRES_R_SUCCESS. Both functions return #LWRES_R_FAILURE if
* the buffer is corrupt or #LWRES_R_UNEXPECTEDEND if the buffer has
* less space than expected for the components of the encoded string
* or address.
*
* lwres_getaddrsbyname() returns #LWRES_R_SUCCESS on success and it
* returns #LWRES_R_NOTFOUND if the hostname name could not be found.
*
* #LWRES_R_SUCCESS is returned by a successful call to
* lwres_getnamebyaddr().
*
* Both lwres_getaddrsbyname() and lwres_getnamebyaddr() return
* #LWRES_R_NOMEMORY when memory allocation requests fail and
* #LWRES_R_UNEXPECTEDEND if the buffers used for sending queries and
* receiving replies are too small.
*
* \section lwresutil_see See Also
*
*/
#include <config.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <lwres/lwbuffer.h>
#include "assert_p.h"
#include "context_p.h"
/*% Parse data. */
/*!
* Requires:
*
* The "current" pointer in "b" points to encoded raw data.
*
* Ensures:
*
* The address of the first byte of the data is returned via "p",
* and the length is returned via "len". If NULL, they are not
* set.
*
* On return, the current pointer of "b" will point to the character
* following the data length and the data.
*
*/
{
unsigned char *data;
/*
* Pull off the length (2 bytes)
*/
if (!SPACE_REMAINING(b, 2))
return (LWRES_R_UNEXPECTEDEND);
/*
* Set the pointer to this string to the right place, then
* advance the buffer pointer.
*/
if (!SPACE_REMAINING(b, datalen))
return (LWRES_R_UNEXPECTEDEND);
if (p != NULL)
*p = data;
return (LWRES_R_SUCCESS);
}
/*% Retrieves a DNS-encoded string. */
/*!
* Requires:
*
* The "current" pointer in "b" point to an encoded string.
*
* Ensures:
*
* The address of the first byte of the string is returned via "c",
* and the length is returned via "len". If NULL, they are not
* set.
*
* On return, the current pointer of "b" will point to the character
* following the string length, the string, and the trailing NULL.
*
*/
{
char *string;
/*
* Pull off the length (2 bytes)
*/
if (!SPACE_REMAINING(b, 2))
return (LWRES_R_UNEXPECTEDEND);
/*
* Set the pointer to this string to the right place, then
* advance the buffer pointer.
*/
if (!SPACE_REMAINING(b, datalen))
return (LWRES_R_UNEXPECTEDEND);
/*
* Skip the "must be zero" byte.
*/
if (!SPACE_REMAINING(b, 1))
return (LWRES_R_UNEXPECTEDEND);
if (0 != lwres_buffer_getuint8(b))
return (LWRES_R_FAILURE);
if (c != NULL)
*c = string;
return (LWRES_R_SUCCESS);
}
/*% Extracts an address from the buffer b. */
{
if (!SPACE_REMAINING(b, 6))
return (LWRES_R_UNEXPECTEDEND);
return (LWRES_R_UNEXPECTEDEND);
return (LWRES_R_FAILURE);
return (LWRES_R_SUCCESS);
}
/*% Used to perform forward lookups. */
{
int ret;
int recvlen;
char *buffer;
unsigned int target_length;
goto out;
}
if (target_length >= sizeof(target_name))
return (LWRES_R_FAILURE);
/*
* Set up our request and render it to a buffer.
*/
if (ret != LWRES_R_SUCCESS)
goto out;
if (ret != LWRES_R_SUCCESS)
goto out;
/*
* Parse the packet header.
*/
if (ret != LWRES_R_SUCCESS)
goto out;
/*
* Sanity check.
*/
goto again;
goto again;
/*
* Free what we've transmitted
*/
goto out;
}
/*
* Parse the response.
*/
if (ret != LWRES_R_SUCCESS)
goto out;
return (LWRES_R_SUCCESS);
out:
return (ret);
}
/*% Used to perform reverse lookups. */
{
int ret;
int recvlen;
char *buffer;
goto out;
}
/*
* Set up our request and render it to a buffer.
*/
if (ret != LWRES_R_SUCCESS)
goto out;
if (ret != LWRES_R_SUCCESS)
goto out;
/*
* Parse the packet header.
*/
if (ret != LWRES_R_SUCCESS)
goto out;
/*
* Sanity check.
*/
goto again;
goto again;
/*
* Free what we've transmitted
*/
goto out;
}
/*
* Parse the response.
*/
if (ret != LWRES_R_SUCCESS)
goto out;
return (LWRES_R_SUCCESS);
out:
return (ret);
}
/*% Get rdata by name. */
{
int ret;
int recvlen;
char *buffer;
unsigned int target_length;
goto out;
}
if (target_length >= sizeof(target_name))
return (LWRES_R_FAILURE);
/*
* Set up our request and render it to a buffer.
*/
if (ret != LWRES_R_SUCCESS)
goto out;
if (ret != LWRES_R_SUCCESS)
goto out;
/*
* Parse the packet header.
*/
if (ret != LWRES_R_SUCCESS)
goto out;
/*
* Sanity check.
*/
goto again;
goto again;
/*
* Free what we've transmitted
*/
goto out;
}
/*
* Parse the response.
*/
if (ret != LWRES_R_SUCCESS)
goto out;
return (LWRES_R_SUCCESS);
out:
return (ret);
}