struct GNUNET_DNSSTUB_RequestSocket *rs;
struct GNUNET_NETWORK_FDSet *rset;
- rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
- DNS_SOCKET_MAX)];
+ for (unsigned int i=0;i<256;i++)
+ {
+ rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+ DNS_SOCKET_MAX)];
+ if (NULL == rs->rc)
+ break;
+ }
+ if (NULL != rs->rc)
+ {
+ /* signal "failure" */
+ rs->rc (rs->rc_cls,
+ rs,
+ NULL,
+ 0);
+ rs->rc = NULL;
+ }
rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
switch (af)
{
return NULL;
rset = GNUNET_NETWORK_fdset_create ();
if (NULL != rs->dnsout4)
- GNUNET_NETWORK_fdset_set (rset, rs->dnsout4);
+ GNUNET_NETWORK_fdset_set (rset,
+ rs->dnsout4);
if (NULL != rs->dnsout6)
- GNUNET_NETWORK_fdset_set (rset, rs->dnsout6);
+ GNUNET_NETWORK_fdset_set (rset,
+ rs->dnsout6);
rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
REQUEST_TIMEOUT,
rset,
*
* @param ctx stub resolver to use
* @param sa the socket address
- * @param sa_len the socket length
+ * @param sa_len the length of @a sa
* @param request DNS request to transmit
- * @param request_len number of bytes in msg
+ * @param request_len number of bytes in @a request
* @param rc function to call with result
- * @param rc_cls closure for 'rc'
+ * @param rc_cls closure for @a rc
* @return socket used for the request, NULL on error
*/
struct GNUNET_DNSSTUB_RequestSocket *
if (NULL == (rs = get_request_socket (ctx,
sa->sa_family)))
return NULL;
+ GNUNET_assert (NULL == rs->rc);
GNUNET_memcpy (&rs->addr,
sa,
sa_len);
memset (&v4, 0, sizeof (v4));
memset (&v6, 0, sizeof (v6));
- if (1 == inet_pton (AF_INET, ctx->dns_exit, &v4.sin_addr))
+ if (1 == inet_pton (AF_INET,
+ ctx->dns_exit,
+ &v4.sin_addr))
{
salen = sizeof (v4);
v4.sin_family = AF_INET;
sa = (struct sockaddr *) &v4;
af = AF_INET;
}
- else if (1 == inet_pton (AF_INET6, ctx->dns_exit, &v6.sin6_addr))
+ else if (1 == inet_pton (AF_INET6,
+ ctx->dns_exit,
+ &v6.sin6_addr))
{
salen = sizeof (v6);
v6.sin6_family = AF_INET6;
GNUNET_break (0);
return NULL;
}
- if (NULL == (rs = get_request_socket (ctx, af)))
+ if (NULL == (rs = get_request_socket (ctx,
+ af)))
return NULL;
+ GNUNET_assert (NULL == rs->rc);
if (NULL != rs->dnsout4)
dnsout = rs->dnsout4;
else
return NULL;
}
GNUNET_memcpy (&rs->addr,
- sa,
- salen);
+ sa,
+ salen);
rs->addrlen = salen;
rs->rc = rc;
rs->rc_cls = rc_cls;
if (GNUNET_SYSERR ==
GNUNET_NETWORK_socket_sendto (dnsout,
request,
- request_len, sa, salen))
+ request_len,
+ sa,
+ salen))
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
_("Failed to send DNS request to %s\n"),
GNUNET_a2s (sa, salen));
int len;
#ifndef MINGW
- if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len))
+ if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout),
+ FIONREAD,
+ &len))
{
/* conservative choice: */
len = UINT16_MAX;
addrlen = sizeof (addr);
memset (&addr, 0, sizeof (addr));
r = GNUNET_NETWORK_socket_recvfrom (dnsout,
- buf, sizeof (buf),
- (struct sockaddr*) &addr, &addrlen);
+ buf,
+ sizeof (buf),
+ (struct sockaddr*) &addr,
+ &addrlen);
if (-1 == r)
{
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom");
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+ "recvfrom");
GNUNET_NETWORK_socket_close (dnsout);
return GNUNET_SYSERR;
}
}
/* read and process ready sockets */
if ((NULL != rs->dnsout4) &&
- (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout4)) &&
- (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout4)))
+ (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+ rs->dnsout4)) &&
+ (GNUNET_SYSERR == do_dns_read (rs,
+ rs->dnsout4)))
rs->dnsout4 = NULL;
if ((NULL != rs->dnsout6) &&
- (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout6)) &&
- (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout6)))
+ (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+ rs->dnsout6)) &&
+ (GNUNET_SYSERR == do_dns_read (rs,
+ rs->dnsout6)))
rs->dnsout6 = NULL;
/* re-schedule read task */
rset = GNUNET_NETWORK_fdset_create ();
if (NULL != rs->dnsout4)
- GNUNET_NETWORK_fdset_set (rset, rs->dnsout4);
+ GNUNET_NETWORK_fdset_set (rset,
+ rs->dnsout4);
if (NULL != rs->dnsout6)
- GNUNET_NETWORK_fdset_set (rset, rs->dnsout6);
+ GNUNET_NETWORK_fdset_set (rset,
+ rs->dnsout6);
rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
GNUNET_TIME_absolute_get_remaining (rs->timeout),
rset,
NULL,
- &read_response, rs);
+ &read_response,
+ rs);
GNUNET_NETWORK_fdset_destroy (rset);
}
* Number of bytes in @e udp_msg.
*/
size_t udp_msg_size;
+
+ /**
+ * ID of the original request.
+ */
+ uint16_t original_request_id;
};
struct Request *request = cls;
(void) rs;
+ if (NULL == dns)
+ {
+ /* DNSSTUB gave up, so we trigger timeout early */
+ GNUNET_SCHEDULER_cancel (request->timeout_task);
+ do_timeout (request);
+ return;
+ }
+ if (request->original_request_id != dns->id)
+ {
+ /* for a another query, ignore */
+ return;
+ }
request->packet = GNUNET_DNSPARSER_parse ((char*)dns,
r);
send_response (request);
{
struct Request *request = cls;
struct GNUNET_DNSPARSER_Packet *packet;
- uint32_t i;
struct GNUNET_DNSPARSER_Record rec;
request->lookup = NULL;
"Using DNS resolver IP `%s' to resolve `%s'\n",
dns_ip,
request->packet->queries[0].name);
+ request->original_request_id = request->packet->id;
GNUNET_DNSPARSER_free_packet (request->packet);
request->packet = NULL;
request->dns_lookup = GNUNET_DNSSTUB_resolve2 (dns_stub,
&dns_result_processor,
request);
return;
- }
+ }
packet = request->packet;
packet->flags.query_or_response = 1;
packet->flags.return_code = GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR;
packet->flags.message_truncated = 0;
packet->flags.authoritative_answer = 0;
//packet->flags.opcode = GNUNET_TUN_DNS_OPCODE_STATUS; // ???
- for (i=0;i<rd_count;i++)
+ for (uint32_t i=0;i<rd_count;i++)
{
// FIXME: do we need to hanlde #GNUNET_GNSRECORD_RF_SHADOW_RECORD
// here? Or should we do this in libgnunetgns?
*/
unsigned int loop_limiter;
+ /**
+ * 16 bit random ID we used in the @e dns_request.
+ */
+ uint16_t original_dns_id;
+
};
unsigned int i;
(void) rs;
- rh->dns_request = NULL;
- GNUNET_SCHEDULER_cancel (rh->task_id);
- rh->task_id = NULL;
+ if (NULL == dns)
+ {
+ rh->dns_request = NULL;
+ GNUNET_SCHEDULER_cancel (rh->task_id);
+ rh->task_id = NULL;
+ rh->proc (rh->proc_cls,
+ 0,
+ NULL);
+ GNS_resolver_lookup_cancel (rh);
+ return;
+ }
+ if (rh->original_dns_id != dns->id)
+ {
+ /* DNS answer, but for another query */
+ return;
+ }
p = GNUNET_DNSPARSER_parse ((const char *) dns,
dns_len);
if (NULL == p)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
_("Failed to parse DNS response\n"));
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
}
else
{
+ rh->original_dns_id = p->id;
rh->dns_request = GNUNET_DNSSTUB_resolve (dns_handle,
(const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip,
sa_len,