55#define LOG(kind, ...) \
56 GNUNET_log_from (kind, "dns", __VA_ARGS__);
276 for (
unsigned int i = 0; i < 8; i++)
278 for (
unsigned int i = 0; i <= UINT16_MAX; i++)
304 uint16_t source_port;
305 uint16_t destination_port;
314 "Got no response for request %llu, dropping\n",
321 "Transmitting response for request %llu\n",
359 hdr->size = htons ((uint16_t) reply_len);
366 tun.
flags = htons (0);
367 if (rr->
src_addr.ss_family == AF_INET)
382 struct sockaddr_in *src = (
struct sockaddr_in *) &rr->
src_addr;
383 struct sockaddr_in *dst = (
struct sockaddr_in *) &rr->
dst_addr;
385 source_port = dst->sin_port;
386 destination_port = src->sin_port;
389 reply_len - off -
sizeof(
struct
402 struct sockaddr_in6 *src = (
struct sockaddr_in6 *) &rr->
src_addr;
403 struct sockaddr_in6 *dst = (
struct sockaddr_in6 *) &rr->
dst_addr;
405 source_port = dst->sin6_port;
406 destination_port = src->sin6_port;
409 reply_len - off -
sizeof(
struct
430 udp.len = htons (reply_len - off);
431 if (AF_INET == rr->
src_addr.ss_family)
460 "# DNS requests answered via TUN interface"),
490 "Sending information about request %llu to local client\n",
553 "Request %llu now in phase %d\n",
591 salen =
sizeof(
struct sockaddr_in);
592 sa = (
const struct sockaddr *) &rr->
dst_addr;
596 salen =
sizeof(
struct sockaddr_in6);
597 sa = (
const struct sockaddr *) &rr->
dst_addr;
614 "# DNS exit failed (failed to open socket)"),
705 for (
unsigned int i = 0; i < UINT16_MAX; i++)
739 "Processing DNS result from stub resolver\n");
750 "# External DNS response discarded (no matching request)"),
753 "Received DNS reply that does not match any pending request. Dropping.\n");
757 "Got a response from the stub resolver for DNS request %llu intercepted locally!\n",
820 "Received DNS response with ID %llu from local client!\n",
826 "# Client response discarded (no matching request)"),
861 "Changing DNS reply according to client specifications\n");
878 query_or_response == 1) )
916 struct sockaddr_in *srca4;
917 struct sockaddr_in6 *srca6;
918 struct sockaddr_in *dsta4;
919 struct sockaddr_in6 *dsta6;
922 "Intercepted message via DNS hijacker\n");
923 msize = ntohs (message->
size);
935 switch (ntohs (tun->
proto))
948 _ (
"Received malformed IPv4-UDP packet on TUN interface.\n"));
967 _ (
"Received malformed IPv6-UDP packet on TUN interface.\n"));
978 "Got non-IP packet with %u bytes and protocol %u from TUN\n"),
979 (
unsigned int) msize,
990 _ (
"DNS interceptor got non-DNS packet (dropped)\n"));
993 "# Non-DNS UDP packet received via TUN interface"),
1010 switch (ntohs (tun->
proto))
1014 srca4 = (
struct sockaddr_in*) &rr->
src_addr;
1015 dsta4 = (
struct sockaddr_in*) &rr->
dst_addr;
1016 memset (srca4, 0,
sizeof(
struct sockaddr_in));
1017 memset (dsta4, 0,
sizeof(
struct sockaddr_in));
1018 srca4->sin_family = AF_INET;
1019 dsta4->sin_family = AF_INET;
1022 srca4->sin_port =
udp->source_port;
1023 dsta4->sin_port =
udp->destination_port;
1024#if HAVE_SOCKADDR_IN_SIN_LEN
1025 srca4->sin_len =
sizeof(
struct sockaddr_in);
1026 dsta4->sin_len =
sizeof(
struct sockaddr_in);
1033 srca6 = (
struct sockaddr_in6*) &rr->
src_addr;
1034 dsta6 = (
struct sockaddr_in6*) &rr->
dst_addr;
1035 memset (srca6, 0,
sizeof(
struct sockaddr_in6));
1036 memset (dsta6, 0,
sizeof(
struct sockaddr_in6));
1037 srca6->sin6_family = AF_INET6;
1038 dsta6->sin6_family = AF_INET6;
1041 srca6->sin6_port =
udp->source_port;
1042 dsta6->sin6_port =
udp->destination_port;
1043#if HAVE_SOCKADDR_IN_SIN_LEN
1044 srca6->sin6_len =
sizeof(
struct sockaddr_in6);
1045 dsta6->sin6_len =
sizeof(
struct sockaddr_in6);
1059 "Creating new DNS request %llu\n",
1063 "# DNS requests received via TUN interface"),
1111 _ (
"need a valid IPv4 or IPv6 address\n"));
1116 "gnunet-helper-dns");
1124 _ (
"`%s' is not SUID or the path is invalid, "
1125 "will not run DNS interceptor\n"),
1141 "No entry 'IFNAME' in configuration!\n");
1154 "No entry 'IPV6ADDR' in configuration!\n");
1167 "No entry 'IPV6PREFIX' in configuration!\n");
1181 "No entry 'IPV4ADDR' in configuration!\n");
1192 "No entry 'IPV4MASK' in configuration!\n");
1200 "SKIP_ROUTING_SETUP");
1247GNUNET_DNS_init (
void)
1253 if (-1 == getresgid (&rgid,
1258 "getresgid failed: %s\n",
1261 else if (sgid != rgid)
1263 if (-1 == setregid (sgid,
1266 "setregid failed: %s\n",
struct GNUNET_MQ_Handle * mq
struct GNUNET_MQ_Envelope * env
IPC messages between DNS API and DNS service.
#define gettext_noop(String)
static unsigned long long ipv6prefix
IPv6 prefix (0..127) from configuration file.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static unsigned long long payload
How much data are we currently storing in the database?
static void next_phase(struct RequestRecord *rr)
A client has completed its processing for this request.
static int process_helper_messages(void *cls, const struct GNUNET_MessageHeader *message)
Functions with this signature are called whenever a complete message is received by the tokenizer fro...
static void handle_client_response(void *cls, const struct GNUNET_DNS_Response *resp)
Handle a response from a client.
static int global_ret
Global return value from 'main'.
RequestPhase
Phases each request goes through.
@ RP_REQUEST_MONITOR
Showing the request to all monitor clients.
@ RP_QUERY
Showing the request to PRE-RESOLUTION clients to find an answer.
@ RP_MODIFY
Client (or global DNS request) has resulted in a response.
@ RP_DROP
Some client has told us to drop the request.
@ RP_INTERNET_DNS
Global Internet query is now pending.
@ RP_INIT
Request has just been received.
@ RP_RESPONSE_MONITOR
Showing the request to all monitor clients.
static void process_dns_result(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t r)
Callback called from DNSSTUB resolver when a resolution succeeded.
static struct GNUNET_STATISTICS_Handle * stats
Statistics.
static const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration to use.
static struct GNUNET_HELPER_Handle * hijacker
Handle to DNS hijacker helper process ("gnunet-helper-dns").
static struct GNUNET_DNSSTUB_Context * dnsstub
Handle to the DNS Stub resolver.
static void cleanup_task(void *cls)
Task run during shutdown.
static void request_done(struct RequestRecord *rr)
We're done with some request, finish processing.
static char * helper_argv[8]
Command-line arguments we are giving to the hijacker process.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client connected, setup our data structures.
static struct ClientRecord * clients_head
Head of DLL of clients we consult.
static uint64_t request_id_gen
Generator for unique request IDs.
#define DNS_PORT
Port number for DNS.
static void handle_client_init(void *cls, const struct GNUNET_DNS_Register *reg)
We got a new client.
static int check_client_response(void *cls, const struct GNUNET_DNS_Response *resp)
Check a response from a client.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, struct GNUNET_SERVICE_Handle *service)
static struct RequestRecord requests[UINT16_MAX+1]
Array of all open requests.
#define LOG(kind,...)
Generic logging shorthand.
static void cleanup_rr(struct RequestRecord *rr)
We're done processing a DNS request, free associated memory.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
A client disconnected, clean up after it.
static void send_request_to_client(struct RequestRecord *rr, struct ClientRecord *cr)
Show the payload of the given request record to the client (and wait for a response).
GNUNET_SERVICE_MAIN(GNUNET_OS_project_data_gnunet(), "dns", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_fixed_size(client_init, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT, struct GNUNET_DNS_Register, NULL), GNUNET_MQ_hd_var_size(client_response, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, struct GNUNET_DNS_Response, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
static struct ClientRecord * clients_tail
Tail of DLL of clients we consult.
static int udp
Option -u: UDP requested.
API to access the DNS service.
struct GNUNET_PQ_ResultSpec __attribute__
Constants for network protocols.
API to create, modify and access statistics.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start(unsigned int num_sockets)
Start a DNS stub resolver.
int GNUNET_DNSSTUB_add_dns_ip(struct GNUNET_DNSSTUB_Context *ctx, const char *dns_ip)
Add nameserver for use by the DNSSTUB.
void GNUNET_DNSSTUB_stop(struct GNUNET_DNSSTUB_Context *ctx)
Cleanup DNSSTUB resolver.
struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve(struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls)
Perform DNS resolution using our default IP from init.
GNUNET_DNS_Flags
Flags that specify when to call the client's handler.
@ GNUNET_DNS_FLAG_RESPONSE_MONITOR
Set this flag to see all requests just before they are returned to the network.
@ GNUNET_DNS_FLAG_REQUEST_MONITOR
Set this flag to see all requests first prior to resolution (for monitoring).
@ GNUNET_DNS_FLAG_PRE_RESOLUTION
This client should be called on requests that have not yet been resolved as this client provides a re...
@ GNUNET_DNS_FLAG_POST_RESOLUTION
This client wants to be called on the results of a DNS resolution (either resolved by PRE-RESOLUTION ...
struct GNUNET_HELPER_SendHandle * GNUNET_HELPER_send(struct GNUNET_HELPER_Handle *h, const struct GNUNET_MessageHeader *msg, bool can_drop, GNUNET_HELPER_Continuation cont, void *cont_cls)
Send an message to the helper.
struct GNUNET_HELPER_Handle * GNUNET_HELPER_start(const struct GNUNET_OS_ProjectData *pd, int with_control_pipe, const char *binary_name, char *const binary_argv[], GNUNET_MessageTokenizerCallback cb, GNUNET_HELPER_ExceptionCallback exp_cb, void *cb_cls)
Starts a helper and begins reading from it.
void GNUNET_HELPER_stop(struct GNUNET_HELPER_Handle *h, int soft_kill)
Kills the helper, closes the pipe, frees the handle and calls wait() on the helper process.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_UNUSED
gcc-ism to document unused arguments
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
enum GNUNET_GenericReturnValue GNUNET_OS_check_helper_binary(const char *binary, bool check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
char * GNUNET_OS_get_suid_binary_path(const struct GNUNET_OS_ProjectData *pd, const struct GNUNET_CONFIGURATION_Handle *cfg, const char *progname)
Given the name of a helper, service or daemon binary construct the full path to the binary using the ...
#define GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST
Type of messages between the gnunet-helper-dns and the service.
#define GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE
Type of messages between the gnunet-helper-dns and the service.
#define GNUNET_MESSAGE_TYPE_DNS_HELPER
Type of messages between the gnunet-helper-dns and the service.
#define GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT
Initial message from client to DNS service for registration.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_TUN_initialize_ipv6_header(struct GNUNET_TUN_IPv6Header *ip, uint8_t protocol, uint16_t payload_length, const struct in6_addr *src, const struct in6_addr *dst)
Initialize an IPv6 header.
void GNUNET_TUN_calculate_udp4_checksum(const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length)
Calculate IPv4 UDP checksum.
GNUNET_NETWORK_STRUCT_END void GNUNET_TUN_initialize_ipv4_header(struct GNUNET_TUN_IPv4Header *ip, uint8_t protocol, uint16_t payload_length, const struct in_addr *src, const struct in_addr *dst)
Initialize an IPv4 header.
#define ETH_P_IPV6
Number for IPv6.
#define ETH_P_IPV4
Number for IPv4.
void GNUNET_TUN_calculate_udp6_checksum(const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length)
Calculate IPv6 UDP checksum.
Entry we keep for each client.
struct ClientRecord * prev
Kept in doubly-linked list.
struct GNUNET_MQ_Handle * mq
Message queue to talk to client.
enum GNUNET_DNS_Flags flags
Flags for the client.
struct GNUNET_SERVICE_Client * client
Handle to the client.
struct ClientRecord * next
Kept in doubly-linked list.
Handle to the stub resolver.
UDP socket we are using for sending DNS requests to the Internet.
Message from client to DNS service to register itself.
uint32_t flags
NBO encoding of enum GNUNET_DNS_Flags for the client.
Message from DNS service to client: please handle a request.
uint32_t reserved
Always zero.
uint64_t request_id
Unique request ID.
Message from client to DNS service: here is my reply.
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE.
uint32_t drop_flag
Zero to drop, 1 for no change (no payload), 2 for update (message has payload).
uint64_t request_id
Unique request ID.
The handle to a helper process.
Handle to a message queue.
Handle to a client that is connected to a service.
DNS flags (largely RFC 1035 / RFC 2136).
Entry we keep for each active request.
struct sockaddr_storage src_addr
Source address of the original request (for sending response).
char * payload
Payload of the UDP packet (the UDP payload), can be either query or already the response.
uint64_t request_id
ID of this request, also basis for hashing.
unsigned int client_wait_list_length
Length of the client_wait_list.
struct sockaddr_storage dst_addr
Destination address of the original request (for potential use as exit).
size_t payload_length
Number of bytes in payload.
struct ClientRecord ** client_wait_list
List of clients that still need to see this request (each entry is set to NULL when the client is don...
struct GNUNET_DNSSTUB_RequestSocket * rs
Socket we are using to transmit this request (must match if we receive a response).
enum RequestPhase phase
In which phase this this request?