Commit 41109912 authored by Daniel Salzman's avatar Daniel Salzman

utils: add support for quering all resolved addresses and improve kdig processing

Getaddrinfo result for remote server is stored in net_t structure. This allows
to query each resolved address via net_t.srv. It is important for example if
the server has associated AAAA and A records, but listens on IPv4 address only.

refs #2137

Change-Id: Iadd2b011a25a8d9e13f05b239a78f42f8d69b5de
parent 28420ed2
......@@ -144,7 +144,7 @@ Show TTL value.
Set wait for reply interval in seconds (default is 5 seconds).
.TP
\fI+retries=N\fR
Set number of retries (default is 2).
Set number of retries (default is 2). This doesn't apply to AXFR or IXFR.
.TP
\fI+bufsize=B\fR
Set EDNS buffer size in bytes (default is 512 bytes).
......
......@@ -74,6 +74,14 @@ const error_table_t knot_error_msgs[] = {
{KNOT_ESTOP, "Stop." },
{KNOT_ELIMIT, "Exceeded response rate limit." },
/* Network errors. */
{KNOT_NET_EADDR, "Bad address or host name."},
{KNOT_NET_ESOCKET, "Can't create socket."},
{KNOT_NET_ECONNECT, "Can't connect."},
{KNOT_NET_ESEND, "Can't send data."},
{KNOT_NET_ERECV, "Can't receive data."},
{KNOT_NET_ETIMEOUT, "Network timeout."},
/* Zone file loader errors. */
{FLOADER_EFSTAT, "Fstat error."},
{FLOADER_EDIRECTORY, "Zone file is a directory."},
......
......@@ -88,6 +88,14 @@ enum knot_error {
KNOT_ESTOP, /*!< Stop doing something. */
KNOT_ELIMIT, /*!< Exceeded response rate limit. */
/* Network errors. */
KNOT_NET_EADDR,
KNOT_NET_ESOCKET,
KNOT_NET_ECONNECT,
KNOT_NET_ESEND,
KNOT_NET_ERECV,
KNOT_NET_ETIMEOUT,
/* Zone file loader errors. */
FLOADER_EFSTAT,
FLOADER_EDIRECTORY,
......
......@@ -149,11 +149,9 @@ static void print_footer(const size_t total_len,
// Print connection statistics.
if (net != NULL) {
if (incoming) {
printf(";; From %s#%i over %s",
net->addr, net->port, net->proto);
printf(";; From %s", net->remote_str);
} else {
printf(";; To %s#%i over %s",
net->addr, net->port, net->proto);
printf(";; To %s", net->remote_str);
}
if (elapsed >= 0) {
......
This diff is collapsed.
......@@ -28,48 +28,171 @@
#define _UTILS__NETIO_H_
#include <stdint.h> // uint_t
#include <netdb.h> // addrinfo
#include "common/lists.h" // node
#include "utils/common/params.h" // params_t
/*! \brief Structure containing server information. */
typedef struct {
/*!< List node (for list container). */
/*! List node (for list container). */
node n;
/*!< Name or address of the server. */
/*! Name or address of the server. */
char *name;
/*!< Name or number of the service. */
/*! Name or number of the service. */
char *service;
} server_t;
typedef struct {
/*! Socket descriptor. */
int sockfd;
/*! IP protocol type. */
int iptype;
/*! Socket type. */
int socktype;
char *proto;
char *addr;
int port;
/*! Timeout for all network operations. */
int wait;
/*! Local interface parameters. */
const server_t *local;
/*! Remote server parameters. */
const server_t *remote;
/*! Local description string (used for logging). */
char *local_str;
/*! Remote description string (used for logging). */
char *remote_str;
/*! Output from getaddrinfo for remote server. If the server is
* specified using domain name, this structure may contain more
* results.
*/
struct addrinfo *remote_info;
/*! Currently used result from remote_info. */
struct addrinfo *srv;
/*! Output from getaddrinfo for local address. Only first result is
* used.
*/
struct addrinfo *local_info;
} net_t;
/*!
* \brief Creates and fills server structure.
*
* \param name Address or host name.
* \param service Port number or service name.
*
* \retval server if success.
* \retval NULL if error.
*/
server_t* server_create(const char *name, const char *service);
/*!
* \brief Destroys server structure.
*
* \param server Server structure to destroy.
*/
void server_free(server_t *server);
/*!
* \brief Translates enum IP version type to int version.
*
* \param ip IP version to convert.
*
* \retval AF_INET, AF_INET6 or AF_UNSPEC.
*/
int get_iptype(const ip_t ip);
/*!
* \brief Translates enum IP protocol type to int version in context to the
* current DNS query type.
*
* \param proto IP protocol type to convert.
* \param type DNS query type number.
*
* \retval SOCK_STREAM or SOCK_DGRAM.
*/
int get_socktype(const protocol_t proto, const uint16_t type);
int net_connect(const server_t *local,
const server_t *remote,
const int iptype,
const int socktype,
const int wait,
net_t *net);
/*!
* \brief Translates int socket type to the common string one.
*
* \param socktype Socket type (SOCK_STREAM or SOCK_DGRAM).
*
* \retval "TCP" or "UDP".
*/
const char* get_sockname(const int socktype);
/*!
* \brief Initializes network structure and resolves local and remote addresses.
*
* \param local Local address and service description.
* \param remote Remote address and service description.
* \param iptype IP version.
* \param socktype Socket type.
* \param wait Network timeout interval.
* \param net Network structure to initialize.
*
* \retval KNOT_EOK if success.
* \retval errcode if error.
*/
int net_init(const server_t *local,
const server_t *remote,
const int iptype,
const int socktype,
const int wait,
net_t *net);
/*!
* \brief Creates socket and connects (if TCP) to remote address specified
* by net->srv.
*
* \param net Connection parameters.
*
* \retval KNOT_EOK if success.
* \retval errcode if error.
*/
int net_connect(net_t *net);
/*!
* \brief Sends data to connected remote server.
*
* \param net Connection parameters.
* \param buf Data to send.
* \param buf_len Length of the data to send.
*
* \retval KNOT_EOK if success.
* \retval errcode if error.
*/
int net_send(const net_t *net, const uint8_t *buf, const size_t buf_len);
/*!
* \brief Receives data from connected remote server.
*
* \param net Connection parameters.
* \param buf Buffer for incomming data.
* \param buf_len Length of the buffer.
*
* \retval >=0 length of successfully received data.
* \retval errcode if error.
*/
int net_receive(const net_t *net, uint8_t *buf, const size_t buf_len);
/*!
* \brief Closes current network connection.
*
* \param net Connection parameters.
*/
void net_close(net_t *net);
/*!
* \brief Cleans up network structure.
*
* \param net Connection parameters.
*/
void net_clean(net_t *net);
#endif // _UTILS__NETIO_H_
/*! @} */
This diff is collapsed.
......@@ -32,8 +32,6 @@
int dig_exec(const dig_params_t *params);
void process_query(const query_t *query);
#endif // _DIG__DIG_EXEC_H_
/*! @} */
......@@ -153,7 +153,9 @@ void query_free(query_t *query)
}
// Cleanup local address.
server_free(query->local);
if (query->local != NULL) {
server_free(query->local);
}
// Cleanup cryptographic content.
free_sign_context(&query->sign_ctx);
......@@ -469,13 +471,6 @@ void complete_queries(list *queries, const query_t *conf)
// No retries for TCP.
if (q->protocol == PROTO_TCP) {
q->retries = 0;
// If wait/tries < 1 s, set 1 second for each try.
} else {
if (q->wait > 0 && q->wait < ( 1 + q->retries)) {
q->wait = 1;
} else {
q->wait /= (1 + q->retries);
}
}
// Complete nameservers list.
......
......@@ -382,12 +382,14 @@ static int pkt_sendrecv(nsupdate_params_t *params,
net_t net;
int ret;
ret = net_connect(params->srcif,
ret = net_init(params->srcif,
params->server,
get_iptype(params->ip),
get_socktype(params->protocol, KNOT_RRTYPE_SOA),
params->wait,
&net);
ret = net_connect(&net);
DBG("%s: send_msg = %d\n", __func__, net.sockfd);
if (ret != KNOT_EOK) return -1;
......@@ -402,10 +404,12 @@ static int pkt_sendrecv(nsupdate_params_t *params,
DBG("%s: receive_msg = %d\n", __func__, rb);
if (rb <= 0) {
net_close(&net);
net_clean(&net);
return -1;
}
net_close(&net);
net_clean(&net);
return rb;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment