/*
This file is part of GNUnet.
- (C) 2012 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2012 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
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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
*/
/**
* each request will be given one of 128 random source ports, and the
* 128 random source ports will also change "often" (less often if the
* system is very busy, each time if we are mostly idle). At the same
- * time, the system will never use more than 256 UDP sockets.
+ * time, the system will never use more than 256 UDP sockets.
*/
#include "platform.h"
#include "gnunet_util_lib.h"
* Global Internet query is now pending.
*/
RP_INTERNET_DNS,
-
+
/**
* Client (or global DNS request) has resulted in a response.
* Forward to all POST-RESOLUTION clients. If client list is empty,
/**
* Entry we keep for each client.
- */
+ */
struct ClientRecord
{
/**
* Kept in doubly-linked list.
- */
+ */
struct ClientRecord *next;
/**
* Kept in doubly-linked list.
- */
+ */
struct ClientRecord *prev;
/**
* Handle to the client.
- */
+ */
struct GNUNET_SERVER_Client *client;
/**
/**
* Entry we keep for each active request.
- */
+ */
struct RequestRecord
{
/**
* Number of bytes in payload.
- */
+ */
size_t payload_length;
/**
/**
* Command-line arguments we are giving to the hijacker process.
*/
-static char *helper_argv[7];
+static char *helper_argv[8];
/**
* Head of DLL of clients we consult.
* Task run during shutdown.
*
* @param cls unused
- * @param tc unused
*/
static void
-cleanup_task (void *cls GNUNET_UNUSED,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+cleanup_task (void *cls GNUNET_UNUSED)
{
unsigned int i;
- GNUNET_HELPER_stop (hijacker, GNUNET_NO);
- hijacker = NULL;
- for (i=0;i<7;i++)
+ if (NULL != hijacker)
+ {
+ GNUNET_HELPER_stop (hijacker, GNUNET_NO);
+ hijacker = NULL;
+ }
+ for (i=0;i<8;i++)
GNUNET_free_non_null (helper_argv[i]);
for (i=0;i<=UINT16_MAX;i++)
cleanup_rr (&requests[i]);
GNUNET_array_grow (rr->client_wait_list,
rr->client_wait_list_length,
- 0);
+ 0);
if (RP_RESPONSE_MONITOR != rr->phase)
{
/* no response, drop */
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Transmitting response for request %llu\n",
- (unsigned long long) rr->request_id);
+ (unsigned long long) rr->request_id);
/* send response via hijacker */
reply_len = sizeof (struct GNUNET_MessageHeader);
reply_len += sizeof (struct GNUNET_TUN_Layer2PacketHeader);
default:
GNUNET_break (0);
cleanup_rr (rr);
- return;
+ return;
}
reply_len += sizeof (struct GNUNET_TUN_UdpHeader);
reply_len += rr->payload_length;
/* response too big, drop */
GNUNET_break (0); /* how can this be? */
cleanup_rr(rr);
- return;
+ return;
}
{
char buf[reply_len] GNUNET_ALIGN;
tun.flags = htons (0);
if (rr->src_addr.ss_family == AF_INET)
- tun.proto = htons (ETH_P_IPV4);
+ tun.proto = htons (ETH_P_IPV4);
else
tun.proto = htons (ETH_P_IPV6);
memcpy (&buf[off], &tun, sizeof (struct GNUNET_TUN_Layer2PacketHeader));
{
struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr;
struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr;
-
+
source_port = dst->sin_port;
destination_port = src->sin_port;
GNUNET_TUN_initialize_ipv4_header (&ip4,
}
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Sending information about request %llu to local client\n",
- (unsigned long long) rr->request_id);
+ (unsigned long long) rr->request_id);
req = (struct GNUNET_DNS_Request*) buf;
req->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST);
req->header.size = htons (sizeof (buf));
req->reserved = htonl (0);
req->request_id = rr->request_id;
memcpy (&req[1], rr->payload, rr->payload_length);
- GNUNET_SERVER_notification_context_unicast (nc,
+ GNUNET_SERVER_notification_context_unicast (nc,
client,
&req->header,
GNUNET_NO);
nz = (int) j;
break;
}
- }
- if (-1 != nz)
+ }
+ if (-1 != nz)
{
send_request_to_client (rr, rr->client_wait_list[nz]->client);
return;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Request %llu now in phase %d\n",
rr->request_id,
- rr->phase);
+ rr->phase);
switch (rr->phase)
{
case RP_INIT:
*
* @param cls unused
* @param client handle of client that disconnected
- */
+ */
static void
client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
{
if (rr->client_wait_list[j] == cr)
{
rr->client_wait_list[j] = NULL;
- next_phase (rr);
+ next_phase (rr);
}
}
}
gettext_noop ("# External DNS response discarded (no matching request)"),
1, GNUNET_NO);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received DNS reply that does not match any pending request. Dropping.\n");
- return;
+ "Received DNS reply that does not match any pending request. Dropping.\n");
+ return;
}
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Got a response from the stub resolver for DNS request %llu intercepted locally!\n",
* @param message the init message (unused)
*/
static void
-handle_client_init (void *cls GNUNET_UNUSED,
+handle_client_init (void *cls GNUNET_UNUSED,
struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message)
{
struct ClientRecord *cr;
const struct GNUNET_DNS_Register *reg = (const struct GNUNET_DNS_Register*) message;
- cr = GNUNET_malloc (sizeof (struct ClientRecord));
+ cr = GNUNET_new (struct ClientRecord);
cr->client = client;
- cr->flags = (enum GNUNET_DNS_Flags) ntohl (reg->flags);
+ cr->flags = (enum GNUNET_DNS_Flags) ntohl (reg->flags);
GNUNET_SERVER_client_keep (client);
GNUNET_CONTAINER_DLL_insert (clients_head,
clients_tail,
* @param message the response
*/
static void
-handle_client_response (void *cls GNUNET_UNUSED,
+handle_client_response (void *cls GNUNET_UNUSED,
struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message)
{
{
GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- next_phase (rr);
+ next_phase (rr);
return;
}
GNUNET_free_non_null (rr->payload);
}
break;
}
- next_phase (rr);
+ next_phase (rr);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
- return;
+ return;
}
/* odd, client was not on our list for the request, that ought
to be an error */
}
if ( (msize <= sizeof (struct GNUNET_TUN_UdpHeader) + sizeof (struct GNUNET_TUN_DnsHeader)) ||
(DNS_PORT != ntohs (udp->destination_port)) )
- {
+ {
/* non-DNS packet received on TUN, ignore */
GNUNET_STATISTICS_update (stats,
gettext_noop ("# Non-DNS UDP packet received via TUN interface"),
{
static const struct GNUNET_SERVER_MessageHandler handlers[] = {
/* callback, cls, type, size */
- {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT,
+ {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT,
sizeof (struct GNUNET_DNS_Register)},
{&handle_client_response, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, 0},
{NULL, NULL, 0, 0}
struct in6_addr dns_exit6;
char *dns_exit;
char *binary;
+ int nortsetup;
cfg = cfg_;
- binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-dns");
- if (GNUNET_YES !=
- GNUNET_OS_check_helper_binary (binary, GNUNET_YES, NULL)) // TODO: once we have a windows-testcase, add test parameters here
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("`%s' must be installed SUID, refusing to run\n"),
- binary);
- global_ret = 1;
- GNUNET_free (binary);
- return;
- }
- GNUNET_free (binary);
stats = GNUNET_STATISTICS_create ("dns", cfg);
nc = GNUNET_SERVER_notification_context_create (server, 1);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
- cls);
+ GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
+ cls);
dns_exit = NULL;
if ( ( (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg, "dns",
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "dns",
"DNS_EXIT",
&dns_exit)) ||
( (1 != inet_pton (AF_INET, dns_exit, &dns_exit4)) &&
(1 != inet_pton (AF_INET6, dns_exit, &dns_exit6)) ) ) )
{
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "dns", "DNS_EXIT",
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "dns",
+ "DNS_EXIT",
_("need a valid IPv4 or IPv6 address\n"));
GNUNET_free_non_null (dns_exit);
dns_exit = NULL;
}
dnsstub = GNUNET_DNSSTUB_start (dns_exit);
+ GNUNET_free_non_null (dns_exit);
+ GNUNET_SERVER_add_handlers (server,
+ handlers);
+ GNUNET_SERVER_disconnect_notify (server,
+ &client_disconnect,
+ NULL);
+ binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-dns");
+ if (GNUNET_YES !=
+ GNUNET_OS_check_helper_binary (binary,
+ GNUNET_YES,
+ NULL)) // TODO: once we have a windows-testcase, add test parameters here
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("`%s' must be installed SUID, will not run DNS interceptor\n"),
+ binary);
+ global_ret = 1;
+ GNUNET_free (binary);
+ return;
+ }
+ GNUNET_free (binary);
+
helper_argv[0] = GNUNET_strdup ("gnunet-dns");
if (GNUNET_SYSERR ==
GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IFNAME", &ifc_name))
return;
}
helper_argv[5] = ipv4mask;
- helper_argv[6] = NULL;
+
+ nortsetup = GNUNET_CONFIGURATION_get_value_yesno (cfg, "dns",
+ "SKIP_ROUTING_SETUP");
+ if (GNUNET_YES == nortsetup)
+ helper_argv[6] = GNUNET_strdup("1");
+ else
+ helper_argv[6] = GNUNET_strdup("0");
+
+ helper_argv[7] = NULL;
hijacker = GNUNET_HELPER_start (GNUNET_NO,
"gnunet-helper-dns",
helper_argv,
&process_helper_messages,
NULL, NULL);
- GNUNET_SERVER_add_handlers (server, handlers);
- GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
}
strerror (errno));
}
else if (sgid != rgid)
- {
- if (-1 == setregid (sgid, sgid))
+ {
+ if (-1 == setregid (sgid, sgid))
fprintf (stderr, "setregid failed: %s\n", strerror (errno));
}
#endif