/*
This file is part of GNUnet.
- Copyright (C) 2009-2016 GNUnet e.V.
+ Copyright (C) 2009-2018 GNUnet e.V.
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
+ SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
*/
static struct GNUNET_RESOLVER_RequestHandle *req_tail;
+/**
+ * ID of the last request we sent to the service
+ */
+static uint32_t last_request_id;
+
/**
* How long should we wait to reconnect?
*/
*/
int af;
+ /**
+ * Identifies the request. The response will contain this id.
+ */
+ uint32_t id;
+
/**
* Has this request been transmitted to the service?
* #GNUNET_YES if transmitted
check_config ()
{
char *hostname;
- unsigned int i;
struct sockaddr_in v4;
struct sockaddr_in6 v6;
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_have_value (resolver_cfg,
+ "resolver",
+ "UNIXPATH"))
+ return GNUNET_OK;
memset (&v4, 0, sizeof (v4));
v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
v4.sin_family = AF_INET;
"resolver");
return GNUNET_SYSERR;
}
- if ((1 == inet_pton (AF_INET, hostname, &v4)) ||
- (1 == inet_pton (AF_INET6, hostname, &v6)))
+ if ( (1 == inet_pton (AF_INET, hostname, &v4)) ||
+ (1 == inet_pton (AF_INET6, hostname, &v6)) )
{
GNUNET_free (hostname);
return GNUNET_OK;
}
- i = 0;
- while (NULL != loopback[i])
- if (0 == strcasecmp (loopback[i++], hostname))
+ for (unsigned int i = 0;
+ NULL != loopback[i];
+ i++)
+ if (0 == strcasecmp (loopback[i],
+ hostname))
{
GNUNET_free (hostname);
return GNUNET_OK;
static void
shutdown_task (void *cls)
{
+ (void) cls;
s_task = NULL;
GNUNET_RESOLVER_disconnect ();
backoff = GNUNET_TIME_UNIT_MILLISECONDS;
static void
check_disconnect ()
{
- struct GNUNET_RESOLVER_RequestHandle *rh;
-
- for (rh = req_head; NULL != rh; rh = rh->next)
+ for (struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
+ NULL != rh;
+ rh = rh->next)
if (GNUNET_SYSERR != rh->was_transmitted)
return;
if (NULL != r_task)
if (ip_len != sizeof (struct in_addr))
return NULL;
if (NULL ==
- inet_ntop (AF_INET, ip, buf, sizeof (buf)))
+ inet_ntop (AF_INET,
+ ip,
+ buf,
+ sizeof (buf)))
{
LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
"inet_ntop");
if (ip_len != sizeof (struct in6_addr))
return NULL;
if (NULL ==
- inet_ntop (AF_INET6, ip, buf, sizeof (buf)))
+ inet_ntop (AF_INET6,
+ ip,
+ buf,
+ sizeof (buf)))
{
LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
"inet_ntop");
mq_error_handler (void *cls,
enum GNUNET_MQ_Error error)
{
+ (void) cls;
GNUNET_MQ_destroy (mq);
mq = NULL;
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "MQ error, reconnecting\n");
+ "MQ error %d, reconnecting\n",
+ error);
reconnect ();
}
{
/* nothing to do, release socket really soon if there is nothing
* else happening... */
- s_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
- &shutdown_task,
- NULL);
+ if (NULL == s_task)
+ s_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
+ &shutdown_task,
+ NULL);
return;
}
if (GNUNET_NO != rh->was_transmitted)
GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
msg->direction = htonl (rh->direction);
msg->af = htonl (rh->af);
+ msg->client_id = rh->id;
GNUNET_memcpy (&msg[1],
- &rh[1],
- rh->data_len);
+ &rh[1],
+ rh->data_len);
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Transmitting DNS resolution request to DNS service\n");
+ "Transmitting DNS resolution request (ID %u) to DNS service\n",
+ rh->id);
GNUNET_MQ_send (mq,
env);
rh->was_transmitted = GNUNET_YES;
*/
static int
check_response (void *cls,
- const struct GNUNET_MessageHeader *msg)
+ const struct GNUNET_RESOLVER_ResponseMessage *msg)
{
+ (void) cls;
+ (void) msg;
+
/* implemented in #handle_response() for now */
return GNUNET_OK;
}
*/
static void
handle_response (void *cls,
- const struct GNUNET_MessageHeader *msg)
+ const struct GNUNET_RESOLVER_ResponseMessage *msg)
{
struct GNUNET_RESOLVER_RequestHandle *rh = req_head;
uint16_t size;
char *nret;
+ uint32_t client_request_id = msg->client_id;
+
+ for (; rh != NULL; rh = rh->next)
+ {
+ if (rh->id == client_request_id)
+ break;
+ }
- size = ntohs (msg->size);
- if (size == sizeof (struct GNUNET_MessageHeader))
+ (void) cls;
+ if (NULL == rh)
+ {
+ /* Resolver service sent extra replies to query (after terminator)? Bad! */
+ GNUNET_break (0);
+ GNUNET_MQ_destroy (mq);
+ mq = NULL;
+ reconnect ();
+ return;
+ }
+ size = ntohs (msg->header.size);
+ if (size == sizeof (struct GNUNET_RESOLVER_ResponseMessage))
{
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received empty response from DNS service\n");
GNUNET_free (nret);
}
/* finally, make termination call */
- rh->name_callback (rh->cls,
- NULL);
+ if (GNUNET_SYSERR != rh->was_transmitted)
+ rh->name_callback (rh->cls,
+ NULL);
}
- if (NULL != rh->addr_callback)
- rh->addr_callback (rh->cls,
- NULL,
- 0);
+ if ( (NULL != rh->addr_callback) &&
+ (GNUNET_SYSERR != rh->was_transmitted) )
+ rh->addr_callback (rh->cls,
+ NULL,
+ 0);
}
rh->was_transmitted = GNUNET_NO;
GNUNET_RESOLVER_request_cancel (rh);
const char *hostname;
hostname = (const char *) &msg[1];
- if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')
+ if (hostname[size - sizeof (struct GNUNET_RESOLVER_ResponseMessage) - 1] != '\0')
{
GNUNET_break (0);
if (GNUNET_SYSERR != rh->was_transmitted)
size_t ip_len;
ip = &msg[1];
- ip_len = size - sizeof (struct GNUNET_MessageHeader);
+ ip_len = size - sizeof (struct GNUNET_RESOLVER_ResponseMessage);
if (ip_len == sizeof (struct in_addr))
{
memset (&v4, 0, sizeof (v4));
v6.sin6_len = sizeof (v6);
#endif
hostname = (const char *) &rh[1];
- if (((rh->af == AF_UNSPEC) || (rh->af == AF_INET)) &&
- (1 == inet_pton (AF_INET, hostname, &v4.sin_addr)))
+ if ( ( (rh->af == AF_UNSPEC) ||
+ (rh->af == AF_INET) ) &&
+ (1 == inet_pton (AF_INET,
+ hostname,
+ &v4.sin_addr)) )
{
rh->addr_callback (rh->cls,
(const struct sockaddr *) &v4,
sizeof (v4));
- if ((rh->af == AF_UNSPEC) &&
- (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr)))
+ if ( (rh->af == AF_UNSPEC) &&
+ (GNUNET_SYSERR != rh->was_transmitted) &&
+ (1 == inet_pton (AF_INET6,
+ hostname,
+ &v6.sin6_addr)) )
{
/* this can happen on some systems IF "hostname" is "localhost" */
rh->addr_callback (rh->cls,
(const struct sockaddr *) &v6,
sizeof (v6));
}
- rh->addr_callback (rh->cls,
- NULL,
- 0);
+ if (GNUNET_SYSERR != rh->was_transmitted)
+ rh->addr_callback (rh->cls,
+ NULL,
+ 0);
GNUNET_free (rh);
return;
}
rh->addr_callback (rh->cls,
(const struct sockaddr *) &v6,
sizeof (v6));
- rh->addr_callback (rh->cls,
- NULL,
- 0);
+ if (GNUNET_SYSERR != rh->was_transmitted)
+ rh->addr_callback (rh->cls,
+ NULL,
+ 0);
GNUNET_free (rh);
return;
}
GNUNET_break (0);
break;
}
- rh->addr_callback (rh->cls,
- NULL,
- 0);
+ if (GNUNET_SYSERR != rh->was_transmitted)
+ rh->addr_callback (rh->cls,
+ NULL,
+ 0);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Finished resolving hostname `%s'.\n",
(const char *) &rh[1]);
struct GNUNET_MQ_MessageHandler handlers[] = {
GNUNET_MQ_hd_var_size (response,
GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE,
- struct GNUNET_MessageHeader,
+ struct GNUNET_RESOLVER_ResponseMessage,
NULL),
GNUNET_MQ_handler_end ()
};
+ (void) cls;
r_task = NULL;
if (NULL == req_head)
return; /* no work pending */
{
struct GNUNET_RESOLVER_RequestHandle *rh;
size_t slen;
- unsigned int i;
struct in_addr v4;
struct in6_addr v6;
hostname);
rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen);
rh->af = af;
+ rh->id = ++last_request_id;
rh->addr_callback = callback;
rh->cls = callback_cls;
GNUNET_memcpy (&rh[1],
rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
rh->direction = GNUNET_NO;
/* first, check if this is a numeric address */
- if (((1 == inet_pton (AF_INET, hostname, &v4)) &&
- ((af == AF_INET) || (af == AF_UNSPEC))) ||
- ((1 == inet_pton (AF_INET6, hostname, &v6)) &&
- ((af == AF_INET6) || (af == AF_UNSPEC))))
+ if ( ( (1 == inet_pton (AF_INET,
+ hostname,
+ &v4)) &&
+ ( (af == AF_INET) ||
+ (af == AF_UNSPEC) ) ) ||
+ ( (1 == inet_pton (AF_INET6,
+ hostname,
+ &v6)) &&
+ ( (af == AF_INET6) ||
+ (af == AF_UNSPEC)) ) )
{
rh->task = GNUNET_SCHEDULER_add_now (&numeric_resolution,
rh);
return rh;
}
/* then, check if this is a loopback address */
- i = 0;
- while (NULL != loopback[i])
- if (0 == strcasecmp (loopback[i++],
+ for (unsigned int i = 0;
+ NULL != loopback[i];
+ i++)
+ if (0 == strcasecmp (loopback[i],
hostname))
{
rh->task = GNUNET_SCHEDULER_add_now (&loopback_resolution,
rh->name_callback = callback;
rh->cls = cls;
rh->af = sa->sa_family;
+ rh->id = ++last_request_id;
rh->timeout = GNUNET_TIME_relative_to_absolute (timeout);
GNUNET_memcpy (&rh[1],
- ip,
- ip_len);
+ ip,
+ ip_len);
rh->data_len = ip_len;
rh->direction = GNUNET_YES;
rh->received_response = GNUNET_NO;
{
char hostname[GNUNET_OS_get_hostname_max_length () + 1];
- if (0 != gethostname (hostname, sizeof (hostname) - 1))
+ if (0 != gethostname (hostname,
+ sizeof (hostname) - 1))
{
LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
"gethostname");
int ret;
char *rval;
- if (0 != (ret = getaddrinfo (hostname, NULL, NULL, &ai)))
+ if (0 != (ret = getaddrinfo (hostname,
+ NULL,
+ NULL,
+ &ai)))
{
LOG (GNUNET_ERROR_TYPE_ERROR,
_("Could not resolve our FQDN: %s\n"),
{
struct hostent *host;
- host = gethostbyname2 (hostname, AF_INET);
+ host = gethostbyname2 (hostname,
+ AF_INET);
if (NULL == host)
- host = gethostbyname2 (hostname, AF_INET6);
+ host = gethostbyname2 (hostname,
+ AF_INET6);
if (NULL == host)
{
LOG (GNUNET_ERROR_TYPE_ERROR,