This file is part of GNUnet.
Copyright (C) 2012-2013 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 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.
-*/
+ 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/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
/**
* @file gnunet-dns2gns.c
* @brief DNS server that translates DNS requests to GNS
uint16_t original_request_id;
};
+/**
+ * The address to bind to
+ */
+static in_addr_t address;
+
+/**
+ * The IPv6 address to bind to
+ */
+static struct in6_addr address6;
+
/**
* Handle to GNS resolver.
}
}
+/**
+ * Shuffle answers
+ * Fisher-Yates (aka Knuth) Shuffle
+ *
+ * @param request context for the request (with answers)
+ */
+static void
+shuffle_answers (struct Request *request)
+{
+ unsigned int idx = request->packet->num_answers;
+ unsigned int r_idx;
+ struct GNUNET_DNSPARSER_Record tmp_answer;
+
+ while (0 != idx)
+ {
+ r_idx = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ request->packet->num_answers);
+ idx--;
+ tmp_answer = request->packet->answers[idx];
+ memcpy (&request->packet->answers[idx], &request->packet->answers[r_idx],
+ sizeof (struct GNUNET_DNSPARSER_Record));
+ memcpy (&request->packet->answers[r_idx], &tmp_answer,
+ sizeof (struct GNUNET_DNSPARSER_Record));
+ }
+}
/**
* Send the response for the given request and clean up.
size_t size;
ssize_t sret;
+ shuffle_answers (request);
if (GNUNET_SYSERR ==
GNUNET_DNSPARSER_pack (request->packet,
- UINT16_MAX /* is this not too much? */,
- &buf,
- &size))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Failed to pack DNS response into UDP packet!\n"));
- }
+ UINT16_MAX /* is this not too much? */,
+ &buf,
+ &size))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _ ("Failed to pack DNS response into UDP packet!\n"));
+ }
else
- {
- sret = GNUNET_NETWORK_socket_sendto (request->lsock,
- buf,
- size,
- request->addr,
- request->addr_len);
- if ( (sret < 0) ||
- (size != (size_t) sret) )
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "sendto");
- GNUNET_free (buf);
- }
+ {
+ sret = GNUNET_NETWORK_socket_sendto (request->lsock,
+ buf,
+ size,
+ request->addr,
+ request->addr_len);
+ if ((sret < 0) ||
+ (size != (size_t) sret))
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "sendto");
+ GNUNET_free (buf);
+ }
GNUNET_SCHEDULER_cancel (request->timeout_task);
GNUNET_DNSPARSER_free_packet (request->packet);
GNUNET_free (request->udp_msg);
*/
static void
dns_result_processor (void *cls,
- const struct GNUNET_TUN_DnsHeader *dns,
- size_t r)
+ const struct GNUNET_TUN_DnsHeader *dns,
+ size_t r)
{
struct Request *request = cls;
/* for a another query, ignore */
return;
}
- request->packet = GNUNET_DNSPARSER_parse ((char*)dns,
- r);
+ request->packet = GNUNET_DNSPARSER_parse ((char *) dns,
+ r);
+ GNUNET_DNSSTUB_resolve_cancel (request->dns_lookup);
send_response (request);
}
*/
static void
result_processor (void *cls,
- int was_gns,
- uint32_t rd_count,
- const struct GNUNET_GNSRECORD_Data *rd)
+ int was_gns,
+ uint32_t rd_count,
+ const struct GNUNET_GNSRECORD_Data *rd)
{
struct Request *request = cls;
struct GNUNET_DNSPARSER_Packet *packet;
{
/* TLD not configured for GNS, fall back to DNS */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Using DNS resolver IP `%s' to resolve `%s'\n",
- dns_ip,
- request->packet->queries[0].name);
+ "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;
packet->flags.recursion_available = 1;
packet->flags.message_truncated = 0;
packet->flags.authoritative_answer = 0;
- //packet->flags.opcode = GNUNET_TUN_DNS_OPCODE_STATUS; // ???
- for (uint32_t i=0;i<rd_count;i++)
+ // packet->flags.opcode = GNUNET_TUN_DNS_OPCODE_STATUS; // ???
+ for (uint32_t i = 0; i < rd_count; i++)
+ {
+ rec.expiration_time.abs_value_us = rd[i].expiration_time;
+ switch (rd[i].record_type)
{
- // FIXME: do we need to hanlde #GNUNET_GNSRECORD_RF_SHADOW_RECORD
- // here? Or should we do this in libgnunetgns?
- rec.expiration_time.abs_value_us = rd[i].expiration_time;
- switch (rd[i].record_type)
- {
- case GNUNET_DNSPARSER_TYPE_A:
- GNUNET_assert (sizeof (struct in_addr) == rd[i].data_size);
- rec.name = GNUNET_strdup (packet->queries[0].name);
- rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
- rec.type = GNUNET_DNSPARSER_TYPE_A;
- rec.data.raw.data = GNUNET_new (struct in_addr);
- GNUNET_memcpy (rec.data.raw.data,
- rd[i].data,
- rd[i].data_size);
- rec.data.raw.data_len = sizeof (struct in_addr);
- GNUNET_array_append (packet->answers,
- packet->num_answers,
- rec);
- break;
- case GNUNET_DNSPARSER_TYPE_AAAA:
- GNUNET_assert (sizeof (struct in6_addr) == rd[i].data_size);
- rec.name = GNUNET_strdup (packet->queries[0].name);
- rec.data.raw.data = GNUNET_new (struct in6_addr);
- rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
- rec.type = GNUNET_DNSPARSER_TYPE_AAAA;
- GNUNET_memcpy (rec.data.raw.data,
- rd[i].data,
- rd[i].data_size);
- rec.data.raw.data_len = sizeof (struct in6_addr);
- GNUNET_array_append (packet->answers,
- packet->num_answers,
- rec);
- break;
- case GNUNET_DNSPARSER_TYPE_CNAME:
- rec.name = GNUNET_strdup (packet->queries[0].name);
- rec.data.hostname = GNUNET_strdup (rd[i].data);
- rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
- rec.type = GNUNET_DNSPARSER_TYPE_CNAME;
- GNUNET_memcpy (rec.data.hostname,
- rd[i].data,
- rd[i].data_size);
- GNUNET_array_append (packet->answers,
- packet->num_answers,
- rec);
- break;
- default:
- /* skip */
- break;
- }
+ case GNUNET_DNSPARSER_TYPE_A:
+ GNUNET_assert (sizeof(struct in_addr) == rd[i].data_size);
+ rec.name = GNUNET_strdup (packet->queries[0].name);
+ rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
+ rec.type = GNUNET_DNSPARSER_TYPE_A;
+ rec.data.raw.data = GNUNET_new (struct in_addr);
+ GNUNET_memcpy (rec.data.raw.data,
+ rd[i].data,
+ rd[i].data_size);
+ rec.data.raw.data_len = sizeof(struct in_addr);
+ GNUNET_array_append (packet->answers,
+ packet->num_answers,
+ rec);
+ break;
+
+ case GNUNET_DNSPARSER_TYPE_AAAA:
+ GNUNET_assert (sizeof(struct in6_addr) == rd[i].data_size);
+ rec.name = GNUNET_strdup (packet->queries[0].name);
+ rec.data.raw.data = GNUNET_new (struct in6_addr);
+ rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
+ rec.type = GNUNET_DNSPARSER_TYPE_AAAA;
+ GNUNET_memcpy (rec.data.raw.data,
+ rd[i].data,
+ rd[i].data_size);
+ rec.data.raw.data_len = sizeof(struct in6_addr);
+ GNUNET_array_append (packet->answers,
+ packet->num_answers,
+ rec);
+ break;
+
+ case GNUNET_DNSPARSER_TYPE_CNAME:
+ rec.name = GNUNET_strdup (packet->queries[0].name);
+ rec.data.hostname = GNUNET_strdup (rd[i].data);
+ rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
+ rec.type = GNUNET_DNSPARSER_TYPE_CNAME;
+ GNUNET_memcpy (rec.data.hostname,
+ rd[i].data,
+ rd[i].data_size);
+ GNUNET_array_append (packet->answers,
+ packet->num_answers,
+ rec);
+ break;
+
+ default:
+ /* skip */
+ break;
}
+ }
send_response (request);
}
*/
static void
handle_request (struct GNUNET_NETWORK_Handle *lsock,
- const void *addr,
- size_t addr_len,
- const char *udp_msg,
- size_t udp_msg_size)
+ const void *addr,
+ size_t addr_len,
+ const char *udp_msg,
+ size_t udp_msg_size)
{
struct Request *request;
struct GNUNET_DNSPARSER_Packet *packet;
packet = GNUNET_DNSPARSER_parse (udp_msg,
- udp_msg_size);
+ udp_msg_size);
if (NULL == packet)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Cannot parse DNS request from %s\n"),
- GNUNET_a2s (addr, addr_len));
+ _ ("Cannot parse DNS request from %s\n"),
+ GNUNET_a2s (addr, addr_len));
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received request for `%s' with flags %u, #answers %d, #auth %d, #additional %d\n",
- packet->queries[0].name,
- (unsigned int) packet->flags.query_or_response,
- (int) packet->num_answers,
- (int) packet->num_authority_records,
- (int) packet->num_additional_records);
- if ( (0 != packet->flags.query_or_response) ||
- (0 != packet->num_answers) ||
- (0 != packet->num_authority_records))
+ "Received request for `%s' with flags %u, #answers %d, #auth %d, #additional %d\n",
+ packet->queries[0].name,
+ (unsigned int) packet->flags.query_or_response,
+ (int) packet->num_answers,
+ (int) packet->num_authority_records,
+ (int) packet->num_additional_records);
+ if ((0 != packet->flags.query_or_response) ||
+ (0 != packet->num_answers) ||
+ (0 != packet->num_authority_records))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Received malformed DNS request from %s\n"),
- GNUNET_a2s (addr, addr_len));
+ _ ("Received malformed DNS request from %s\n"),
+ GNUNET_a2s (addr, addr_len));
GNUNET_DNSPARSER_free_packet (packet);
return;
}
- if ( (1 != packet->num_queries) )
+ if ((1 != packet->num_queries))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Received unsupported DNS request from %s\n"),
- GNUNET_a2s (addr,
- addr_len));
+ _ ("Received unsupported DNS request from %s\n"),
+ GNUNET_a2s (addr,
+ addr_len));
GNUNET_DNSPARSER_free_packet (packet);
return;
}
- request = GNUNET_malloc (sizeof (struct Request) + addr_len);
+ request = GNUNET_malloc (sizeof(struct Request) + addr_len);
request->lsock = lsock;
request->packet = packet;
request->addr = &request[1];
request->addr_len = addr_len;
GNUNET_memcpy (&request[1],
- addr,
- addr_len);
+ addr,
+ addr_len);
request->udp_msg_size = udp_msg_size;
request->udp_msg = GNUNET_memdup (udp_msg,
- udp_msg_size);
+ udp_msg_size);
request->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
- &do_timeout,
- request);
+ &do_timeout,
+ request);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Calling GNS on `%s'\n",
- packet->queries[0].name);
+ "Calling GNS on `%s'\n",
+ packet->queries[0].name);
request->lookup = GNUNET_GNS_lookup_with_tld (gns,
- packet->queries[0].name,
- packet->queries[0].type,
- GNUNET_NO,
- &result_processor,
- request);
+ packet->queries[0].name,
+ packet->queries[0].type,
+ GNUNET_GNS_LO_DEFAULT,
+ &result_processor,
+ request);
}
GNUNET_assert (listen_socket4 == cls);
t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- listen_socket4,
- &read_dns4,
- listen_socket4);
+ listen_socket4,
+ &read_dns4,
+ listen_socket4);
tc = GNUNET_SCHEDULER_get_task_context ();
if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason))
return; /* shutdown? */
size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket4);
if (0 > size)
- {
- GNUNET_break (0);
- return; /* read error!? */
- }
+ {
+ GNUNET_break (0);
+ return; /* read error!? */
+ }
{
char buf[size + 1];
ssize_t sret;
- addrlen = sizeof (v4);
+ addrlen = sizeof(v4);
sret = GNUNET_NETWORK_socket_recvfrom (listen_socket4,
- buf,
- size + 1,
- (struct sockaddr *) &v4,
- &addrlen);
+ buf,
+ size + 1,
+ (struct sockaddr *) &v4,
+ &addrlen);
if (0 > sret)
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "recvfrom");
+ "recvfrom");
return;
}
GNUNET_break (size == sret);
handle_request (listen_socket4,
- &v4,
- addrlen,
- buf,
- size);
+ &v4,
+ addrlen,
+ buf,
+ size);
}
}
GNUNET_assert (listen_socket6 == cls);
t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- listen_socket6,
- &read_dns6,
- listen_socket6);
+ listen_socket6,
+ &read_dns6,
+ listen_socket6);
tc = GNUNET_SCHEDULER_get_task_context ();
if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason))
return; /* shutdown? */
size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket6);
if (0 > size)
- {
- GNUNET_break (0);
- return; /* read error!? */
- }
+ {
+ GNUNET_break (0);
+ return; /* read error!? */
+ }
{
char buf[size];
ssize_t sret;
- addrlen = sizeof (v6);
+ addrlen = sizeof(v6);
sret = GNUNET_NETWORK_socket_recvfrom (listen_socket6,
- buf,
- size,
- (struct sockaddr *) &v6,
- &addrlen);
+ buf,
+ size,
+ (struct sockaddr *) &v6,
+ &addrlen);
if (0 > sret)
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
- "recvfrom");
+ "recvfrom");
return;
}
GNUNET_break (size == sret);
handle_request (listen_socket6,
- &v6,
- addrlen,
- buf,
- size);
+ &v6,
+ addrlen,
+ buf,
+ size);
}
}
const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *c)
{
+ char *addr_str;
+
(void) cls;
(void) args;
(void) cfgfile;
if (NULL == dns_ip)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("No DNS server specified!\n"));
+ _ ("No DNS server specified!\n"));
return;
}
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
- NULL);
+ NULL);
if (NULL == (gns = GNUNET_GNS_connect (cfg)))
return;
GNUNET_assert (NULL != (dns_stub = GNUNET_DNSSTUB_start (128)));
gns = NULL;
return;
}
+
+ /* Get address to bind to */
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (c, "dns2gns",
+ "BIND_TO",
+ &addr_str))
+ {
+ // No address specified
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Don't know what to bind to...\n");
+ GNUNET_free (addr_str);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (1 != inet_pton (AF_INET, addr_str, &address))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse address %s\n",
+ addr_str);
+ GNUNET_free (addr_str);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ GNUNET_free (addr_str);
+ /* Get address to bind to */
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (c, "dns2gns",
+ "BIND_TO6",
+ &addr_str))
+ {
+ // No address specified
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Don't know what to bind6 to...\n");
+ GNUNET_free (addr_str);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if (1 != inet_pton (AF_INET6, addr_str, &address6))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to parse IPv6 address %s\n",
+ addr_str);
+ GNUNET_free (addr_str);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ GNUNET_free (addr_str);
+
listen_socket4 = GNUNET_NETWORK_socket_create (PF_INET,
- SOCK_DGRAM,
- IPPROTO_UDP);
+ SOCK_DGRAM,
+ IPPROTO_UDP);
if (NULL != listen_socket4)
{
struct sockaddr_in v4;
- memset (&v4, 0, sizeof (v4));
+ memset (&v4, 0, sizeof(v4));
v4.sin_family = AF_INET;
+ v4.sin_addr.s_addr = address;
#if HAVE_SOCKADDR_IN_SIN_LEN
- v4.sin_len = sizeof (v4);
+ v4.sin_len = sizeof(v4);
#endif
v4.sin_port = htons (listen_port);
if (GNUNET_OK !=
- GNUNET_NETWORK_socket_bind (listen_socket4,
- (struct sockaddr *) &v4,
- sizeof (v4)))
+ GNUNET_NETWORK_socket_bind (listen_socket4,
+ (struct sockaddr *) &v4,
+ sizeof(v4)))
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
GNUNET_NETWORK_socket_close (listen_socket4);
}
}
listen_socket6 = GNUNET_NETWORK_socket_create (PF_INET6,
- SOCK_DGRAM,
- IPPROTO_UDP);
+ SOCK_DGRAM,
+ IPPROTO_UDP);
if (NULL != listen_socket6)
{
struct sockaddr_in6 v6;
- memset (&v6, 0, sizeof (v6));
+ memset (&v6, 0, sizeof(v6));
v6.sin6_family = AF_INET6;
+ v6.sin6_addr = address6;
#if HAVE_SOCKADDR_IN_SIN_LEN
- v6.sin6_len = sizeof (v6);
+ v6.sin6_len = sizeof(v6);
#endif
v6.sin6_port = htons (listen_port);
if (GNUNET_OK !=
- GNUNET_NETWORK_socket_bind (listen_socket6,
- (struct sockaddr *) &v6,
- sizeof (v6)))
+ GNUNET_NETWORK_socket_bind (listen_socket6,
+ (struct sockaddr *) &v6,
+ sizeof(v6)))
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
GNUNET_NETWORK_socket_close (listen_socket6);
listen_socket6 = NULL;
}
}
- if ( (NULL == listen_socket4) &&
- (NULL == listen_socket6) )
+ if ((NULL == listen_socket4) &&
+ (NULL == listen_socket6))
{
GNUNET_GNS_disconnect (gns);
gns = NULL;
}
if (NULL != listen_socket4)
t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- listen_socket4,
- &read_dns4,
- listen_socket4);
+ listen_socket4,
+ &read_dns4,
+ listen_socket4);
if (NULL != listen_socket6)
t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
- listen_socket6,
- &read_dns6,
- listen_socket6);
+ listen_socket6,
+ &read_dns6,
+ listen_socket6);
}
GNUNET_GETOPT_option_string ('d',
"dns",
"IP",
- gettext_noop ("IP of recursive DNS resolver to use (required)"),
+ gettext_noop (
+ "IP of recursive DNS resolver to use (required)"),
&dns_ip),
GNUNET_GETOPT_option_uint ('p',
- "port",
- "UDPPORT",
- gettext_noop ("UDP port to listen on for inbound DNS requests; default: 2853"),
- &listen_port),
+ "port",
+ "UDPPORT",
+ gettext_noop (
+ "UDP port to listen on for inbound DNS requests; default: 2853"),
+ &listen_port),
GNUNET_GETOPT_OPTION_END
};
int ret;
"WARNING",
NULL);
ret =
- (GNUNET_OK ==
- GNUNET_PROGRAM_run (argc, argv,
- "gnunet-dns2gns",
- _("GNUnet DNS-to-GNS proxy (a DNS server)"),
- options,
- &run, NULL)) ? 0 : 1;
- GNUNET_free ((void*) argv);
+ (GNUNET_OK ==
+ GNUNET_PROGRAM_run (argc, argv,
+ "gnunet-dns2gns",
+ _ ("GNUnet DNS-to-GNS proxy (a DNS server)"),
+ options,
+ &run, NULL)) ? 0 : 1;
+ GNUNET_free_nz ((void *) argv);
return ret;
}
+
/* end of gnunet-dns2gns.c */