|
|
|
|
|
|
|
/* Copyright (C) 2009-2013 by Daniel Stenberg
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this
|
|
|
|
* software and its documentation for any purpose and without
|
|
|
|
* fee is hereby granted, provided that the above copyright
|
|
|
|
* notice appear in all copies and that both that copyright
|
|
|
|
* notice and this permission notice appear in supporting
|
|
|
|
* documentation, and that the name of M.I.T. not be used in
|
|
|
|
* advertising or publicity pertaining to distribution of the
|
|
|
|
* software without specific, written prior permission.
|
|
|
|
* M.I.T. makes no representations about the suitability of
|
|
|
|
* this software for any purpose. It is provided "as is"
|
|
|
|
* without express or implied warranty.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "ares_setup.h"
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
#include "ares.h"
|
|
|
|
#include "ares_data.h"
|
|
|
|
#include "ares_private.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** ares_free_data() - c-ares external API function.
|
|
|
|
**
|
|
|
|
** This function must be used by the application to free data memory that
|
|
|
|
** has been internally allocated by some c-ares function and for which a
|
|
|
|
** pointer has already been returned to the calling application. The list
|
|
|
|
** of c-ares functions returning pointers that must be free'ed using this
|
|
|
|
** function is:
|
|
|
|
**
|
|
|
|
** ares_get_servers()
|
|
|
|
** ares_parse_srv_reply()
|
|
|
|
** ares_parse_txt_reply()
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ares_free_data(void *dataptr)
|
|
|
|
{
|
|
|
|
struct ares_data *ptr;
|
|
|
|
|
|
|
|
if (!dataptr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
#ifdef __INTEL_COMPILER
|
|
|
|
# pragma warning(push)
|
|
|
|
# pragma warning(disable:1684)
|
|
|
|
/* 1684: conversion from pointer to same-sized integral type */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data));
|
|
|
|
|
|
|
|
#ifdef __INTEL_COMPILER
|
|
|
|
# pragma warning(pop)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (ptr->mark != ARES_DATATYPE_MARK)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (ptr->type)
|
|
|
|
{
|
|
|
|
case ARES_DATATYPE_MX_REPLY:
|
|
|
|
|
|
|
|
if (ptr->data.mx_reply.next)
|
|
|
|
ares_free_data(ptr->data.mx_reply.next);
|
|
|
|
if (ptr->data.mx_reply.host)
|
|
|
|
ares_free(ptr->data.mx_reply.host);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARES_DATATYPE_SRV_REPLY:
|
|
|
|
|
|
|
|
if (ptr->data.srv_reply.next)
|
|
|
|
ares_free_data(ptr->data.srv_reply.next);
|
|
|
|
if (ptr->data.srv_reply.host)
|
|
|
|
ares_free(ptr->data.srv_reply.host);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARES_DATATYPE_TXT_REPLY:
|
|
|
|
case ARES_DATATYPE_TXT_EXT:
|
|
|
|
|
|
|
|
if (ptr->data.txt_reply.next)
|
|
|
|
ares_free_data(ptr->data.txt_reply.next);
|
|
|
|
if (ptr->data.txt_reply.txt)
|
|
|
|
ares_free(ptr->data.txt_reply.txt);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARES_DATATYPE_ADDR_NODE:
|
|
|
|
|
|
|
|
if (ptr->data.addr_node.next)
|
|
|
|
ares_free_data(ptr->data.addr_node.next);
|
|
|
|
break;
|
|
|
|
|
api: Add entrypoints to allow use of per-server ports
Add user-visible entrypoints ares_{get,set}_servers_ports(3), which
take struct ares_addr_port_node rather than struct ares_addr_node.
This structure includes a UDP and TCP port number; if this is set
to zero, the channel-wide port values are used as before.
Similarly, add a new ares_set_servers_ports_csv(3) entrypoint, which
is analogous to ares_set_servers(3) except it doesn't ignore any
specified port information; instead, any per-server specified port
is used as both the UDP and TCP port for that server.
The internal struct ares_addr is extended to hold the UDP/TCP ports,
stored in network order, with the convention that a value of zero
indicates that the channel-wide UDP/TCP port should be used.
For the internal implementation of ares_dup(3), shift to use the
_ports() version of the get/set functions, so port information is
transferred correctly to the new channel.
Update manpages, and add missing ares_set_servers_csv to the lists
while we're at it
9 years ago
|
|
|
case ARES_DATATYPE_ADDR_PORT_NODE:
|
|
|
|
|
|
|
|
if (ptr->data.addr_port_node.next)
|
|
|
|
ares_free_data(ptr->data.addr_port_node.next);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARES_DATATYPE_NAPTR_REPLY:
|
|
|
|
|
|
|
|
if (ptr->data.naptr_reply.next)
|
|
|
|
ares_free_data(ptr->data.naptr_reply.next);
|
|
|
|
if (ptr->data.naptr_reply.flags)
|
|
|
|
ares_free(ptr->data.naptr_reply.flags);
|
|
|
|
if (ptr->data.naptr_reply.service)
|
|
|
|
ares_free(ptr->data.naptr_reply.service);
|
|
|
|
if (ptr->data.naptr_reply.regexp)
|
|
|
|
ares_free(ptr->data.naptr_reply.regexp);
|
|
|
|
if (ptr->data.naptr_reply.replacement)
|
|
|
|
ares_free(ptr->data.naptr_reply.replacement);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARES_DATATYPE_SOA_REPLY:
|
|
|
|
if (ptr->data.soa_reply.nsname)
|
|
|
|
ares_free(ptr->data.soa_reply.nsname);
|
|
|
|
if (ptr->data.soa_reply.hostmaster)
|
|
|
|
ares_free(ptr->data.soa_reply.hostmaster);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ares_free(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
** ares_malloc_data() - c-ares internal helper function.
|
|
|
|
**
|
|
|
|
** This function allocates memory for a c-ares private ares_data struct
|
|
|
|
** for the specified ares_datatype, initializes c-ares private fields
|
|
|
|
** and zero initializes those which later might be used from the public
|
|
|
|
** API. It returns an interior pointer which can be passed by c-ares
|
|
|
|
** functions to the calling application, and that must be free'ed using
|
|
|
|
** c-ares external API function ares_free_data().
|
|
|
|
*/
|
|
|
|
|
|
|
|
void *ares_malloc_data(ares_datatype type)
|
|
|
|
{
|
|
|
|
struct ares_data *ptr;
|
|
|
|
|
|
|
|
ptr = ares_malloc(sizeof(struct ares_data));
|
|
|
|
if (!ptr)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case ARES_DATATYPE_MX_REPLY:
|
|
|
|
ptr->data.mx_reply.next = NULL;
|
|
|
|
ptr->data.mx_reply.host = NULL;
|
|
|
|
ptr->data.mx_reply.priority = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARES_DATATYPE_SRV_REPLY:
|
|
|
|
ptr->data.srv_reply.next = NULL;
|
|
|
|
ptr->data.srv_reply.host = NULL;
|
|
|
|
ptr->data.srv_reply.priority = 0;
|
|
|
|
ptr->data.srv_reply.weight = 0;
|
|
|
|
ptr->data.srv_reply.port = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARES_DATATYPE_TXT_EXT:
|
|
|
|
ptr->data.txt_ext.record_start = 0;
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
|
|
|
|
case ARES_DATATYPE_TXT_REPLY:
|
|
|
|
ptr->data.txt_reply.next = NULL;
|
|
|
|
ptr->data.txt_reply.txt = NULL;
|
|
|
|
ptr->data.txt_reply.length = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARES_DATATYPE_ADDR_NODE:
|
|
|
|
ptr->data.addr_node.next = NULL;
|
|
|
|
ptr->data.addr_node.family = 0;
|
|
|
|
memset(&ptr->data.addr_node.addrV6, 0,
|
|
|
|
sizeof(ptr->data.addr_node.addrV6));
|
|
|
|
break;
|
|
|
|
|
api: Add entrypoints to allow use of per-server ports
Add user-visible entrypoints ares_{get,set}_servers_ports(3), which
take struct ares_addr_port_node rather than struct ares_addr_node.
This structure includes a UDP and TCP port number; if this is set
to zero, the channel-wide port values are used as before.
Similarly, add a new ares_set_servers_ports_csv(3) entrypoint, which
is analogous to ares_set_servers(3) except it doesn't ignore any
specified port information; instead, any per-server specified port
is used as both the UDP and TCP port for that server.
The internal struct ares_addr is extended to hold the UDP/TCP ports,
stored in network order, with the convention that a value of zero
indicates that the channel-wide UDP/TCP port should be used.
For the internal implementation of ares_dup(3), shift to use the
_ports() version of the get/set functions, so port information is
transferred correctly to the new channel.
Update manpages, and add missing ares_set_servers_csv to the lists
while we're at it
9 years ago
|
|
|
case ARES_DATATYPE_ADDR_PORT_NODE:
|
|
|
|
ptr->data.addr_port_node.next = NULL;
|
|
|
|
ptr->data.addr_port_node.family = 0;
|
|
|
|
ptr->data.addr_port_node.udp_port = 0;
|
|
|
|
ptr->data.addr_port_node.tcp_port = 0;
|
|
|
|
memset(&ptr->data.addr_port_node.addrV6, 0,
|
|
|
|
sizeof(ptr->data.addr_port_node.addrV6));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARES_DATATYPE_NAPTR_REPLY:
|
|
|
|
ptr->data.naptr_reply.next = NULL;
|
|
|
|
ptr->data.naptr_reply.flags = NULL;
|
|
|
|
ptr->data.naptr_reply.service = NULL;
|
|
|
|
ptr->data.naptr_reply.regexp = NULL;
|
|
|
|
ptr->data.naptr_reply.replacement = NULL;
|
|
|
|
ptr->data.naptr_reply.order = 0;
|
|
|
|
ptr->data.naptr_reply.preference = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ARES_DATATYPE_SOA_REPLY:
|
|
|
|
ptr->data.soa_reply.nsname = NULL;
|
|
|
|
ptr->data.soa_reply.hostmaster = NULL;
|
|
|
|
ptr->data.soa_reply.serial = 0;
|
|
|
|
ptr->data.soa_reply.refresh = 0;
|
|
|
|
ptr->data.soa_reply.retry = 0;
|
|
|
|
ptr->data.soa_reply.expire = 0;
|
|
|
|
ptr->data.soa_reply.minttl = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ares_free(ptr);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr->mark = ARES_DATATYPE_MARK;
|
|
|
|
ptr->type = type;
|
|
|
|
|
|
|
|
return &ptr->data;
|
|
|
|
}
|