30#include "../../lib/util/resolver.h"
36#define DNS_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
287 if (0 == strncmp (
line,
"nameserver ", strlen (
"nameserver ")))
289 line_len - strlen (
"nameserver "));
306 if (0 == strncmp (
line,
"search ", strlen (
"search ")))
308 line_len - strlen (
"search "));
327 unsigned int num_dns_servers;
335 "Could not open /etc/resolv.conf. "
336 "DNS resolution will not be possible.\n");
342 "Could not determine size of /etc/resolv.conf. "
343 "DNS resolution will not be possible.\n");
347 if (((
unsigned long long) bytes_read) > (
unsigned long long)
SIZE_MAX)
350 "/etc/resolv.conf file too large to mmap. "
351 "DNS resolution will not be possible.\n");
358 (
size_t) bytes_read);
359 *server_addrs = NULL;
362 while (read_offset < (
size_t) bytes_read)
368 newline = strchr (buf + read_offset,
'\n');
371 line_len = newline - buf - read_offset;
373 if (NULL != dns_server)
381 read_offset += line_len + 1;
385 return (
int) num_dns_servers;
403 struct in_addr *addr = (
struct in_addr *) ip;
404 uint32_t ip_int = addr->s_addr;
406 for (
int i = 3; i >= 0; i--)
409 GNUNET_snprintf (buf + pos, 80 - pos,
"%u.", ((uint8_t *) &ip_int)[i]);
419 else if (AF_INET6 == af)
421 struct in6_addr *addr = (
struct in6_addr *) ip;
422 for (
int i = 15; i >= 0; i--)
432 n =
GNUNET_snprintf (buf + pos, 80 - pos,
"%x.", addr->s6_addr[i] >> 4);
460 uint16_t record_type,
461 uint32_t client_request_id,
475 payload_len = strlen (
record->data.hostname) + 1;
482 payload_len = strlen (
record->data.hostname) + 1;
490 payload_len =
record->data.raw.data_len;
498 payload_len =
record->data.raw.data_len;
503 "Cannot handle DNS response type %u: not supported here\n",
510 msg->client_id = client_request_id;
532 msg->client_id = client_request_id;
553 if (now.
abs_value_us > pos->record->expiration_time.abs_value_us)
581 uint16_t record_type,
582 uint32_t client_request_id,
599 uint16_t record_type,
600 uint32_t client_request_id,
618 for (pos =
next; NULL != pos; pos =
next)
645 "Checking cache entry for '%s', record is for '%s'\n",
651 const char *hostname_tmp =
record->data.hostname;
653 process_get (hostname_tmp, record_type, client_request_id, client);
657 found |=
send_reply (rle->record, record_type, client_request_id, client);
687 query.
name = (
char *) hostname;
690 memset (&packet, 0,
sizeof(packet));
693 packet.
id = htons (dns_id);
699 "Failed to pack query for hostname `%s'\n",
711 unsigned int num_records)
717 for (
unsigned int i = 0; i != num_records; i++)
729 "Caching record for name %s under %s\n",
763 "Failed to parse DNS reply (hostname %s, request ID %u)\n",
768 if (al->
dns_id != ntohs (parsed->
id))
771 "Request ID in DNS reply does not match\n");
779 "DNS reply (hostname %s, request ID %u) contains no answers\n",
800 "Got reply for hostname %s and request ID %u\n",
907 "Failed to pack query for hostname `%s'\n",
928 "Resolving %s, client_request_id = %u, dns_id = %u\n",
996 size = ntohs (
get->header.size) -
sizeof(*get);
1003 af = ntohl (
get->af);
1007 if (
size !=
sizeof(
struct in_addr))
1015 if (
size !=
sizeof(
struct in6_addr))
1042 uint32_t client_request_id;
1046 af = ntohl (
msg->af);
1047 client_request_id =
msg->client_id;
1054 "Client asks to resolve `%s'\n",
1143 rec->
type = rec_type;
1173 c =
memrchr (
line, (
unsigned char)
'#', line_len);
1175 line_len = c -
line;
1177 while ((0 < line_len) && isspace ((
unsigned char) *
line))
1183 tok = strtok (tbuf,
" \t");
1189 if (1 == inet_pton (AF_INET, tok, &v4))
1191 while (NULL != (tok = strtok (NULL,
" \t")))
1194 else if (1 == inet_pton (AF_INET6, tok, &v6))
1196 while (NULL != (tok = strtok (NULL,
" \t")))
1226 "Could not determine size of /etc/hosts. "
1227 "DNS resolution will not be possible.\n");
1231 if (((
unsigned long long) bytes_read) > (
unsigned long long)
SIZE_MAX)
1234 "/etc/hosts file too large to mmap. "
1235 "DNS resolution will not be possible.\n");
1242 (
size_t) bytes_read);
1244 while (read_offset < (
size_t) bytes_read)
1246 const char *newline;
1249 newline = strchr (buf + read_offset,
'\n');
1250 if (NULL == newline)
1252 line_len = newline - buf - read_offset;
1254 read_offset += line_len + 1;
1274 int num_dns_servers;
1283 if (0 >= num_dns_servers)
1287 _ (
"No DNS server available. DNS resolution will not be possible.\n"));
1290 for (
int i = 0; i < num_dns_servers; i++)
1294 "Adding DNS server '%s': %s\n",
1342 if (al->client == c)
1366#if defined(__linux__) && defined(__GLIBC__)
1370GNUNET_RESOLVER_memory_init (
void);
1376GNUNET_RESOLVER_memory_init (
void)
1378 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
1379 mallopt (M_TOP_PAD, 1 * 1024);
struct GNUNET_MQ_Handle * mq
struct GNUNET_MessageHeader * msg
struct GNUNET_MQ_Envelope * env
enum GNUNET_ABD_AlgoDirectionFlags direction
API enum, filled and passed for collect/verify.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static struct GNUNET_CADET_Handle * mh
Cadet handle.
static void record(void *cls, size_t data_size, const void *data)
Process recorded audio data.
static char * line
Desired phone line (string to be converted to a hash).
static char * data
The data to insert into the dht.
static int get
Get DID Documement for DID Flag.
static struct GNUNET_IDENTITY_Handle * sh
Handle to IDENTITY service.
static char * name
Name (label) of the records to list.
static uint32_t type
Type string converted to DNS type value.
static size_t data_size
Number of bytes in data.
static int result
Global testing status.
static unsigned long long payload
How much data are we currently storing in the database?
#define MAX_CACHE
Maximum number of hostnames we cache results for.
static struct ResolveCache * cache_head
Start of the linked list of cached DNS lookup results.
static void free_cache_entry(struct ResolveCache *rc)
Remove entry from cache.
static void cache_answers(const char *name, struct GNUNET_DNSPARSER_Record *records, unsigned int num_records)
static void send_end_msg(uint32_t client_request_id, struct GNUNET_SERVICE_Client *client)
Send message to client that we transmitted all responses for client_request_id.
static void disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
Callback called when a client disconnected from the service.
static char * extract_dns_server(const char *line, size_t line_len)
Find out if the configuration file line contains a string starting with "nameserver ",...
static int send_reply(struct GNUNET_DNSPARSER_Record *record, uint16_t record_type, uint32_t client_request_id, struct GNUNET_SERVICE_Client *client)
Send DNS record back to our client.
static int remove_expired(struct ResolveCache *rc)
Remove expired entries from rc.
static int pack(const char *hostname, uint16_t type, uint16_t dns_id, char **packet_buf, size_t *packet_size)
Create DNS query for hostname of type type with DNS request ID dns_id.
static struct ResolveCache * hosts_head
Head of the linked list of DNS lookup results from /etc/hosts.
static void init_cb(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SERVICE_Handle *sh)
Service is starting, initialize everything.
static struct ActiveLookup * lookup_head
Start of the linked list of active DNS lookups.
static char * my_domain
My domain, to be appended to the hostname to get a FQDN.
static void shutdown_task(void *cls)
Service is shutting down, clean up.
static char * make_reverse_hostname(const void *ip, int af)
Compute name to use for DNS reverse lookups from ip.
static void * connect_cb(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback called when a client connects to the service.
static int resolve_and_cache(const char *hostname, uint16_t record_type, uint32_t client_request_id, struct GNUNET_SERVICE_Client *client)
Initiate an active lookup, then cache the result and try to then complete the resolution.
static void add_host(const char *hostname, uint16_t rec_type, const void *data, size_t data_size)
Add information about a host from /etc/hosts to our cache.
static unsigned int cache_size
How many entries do we have in cache_head DLL?
#define DNS_TIMEOUT
How long do we wait for DNS answers?
static void handle_resolve_timeout(void *cls)
We encountered a timeout trying to perform a DNS lookup.
static void load_etc_hosts(void)
Reads the list of hosts from /etc/hosts.
static struct ResolveCache * hosts_tail
Tail of the linked list of DNS lookup results from /etc/hosts.
static void free_hosts_entry(struct ResolveCache *rc)
Remove entry from cache.
static struct ActiveLookup * lookup_tail
Tail of the linked list of active DNS lookups.
static char * extract_search_domain(const char *line, size_t line_len)
Find out if the configuration file line contains a string starting with "search ",...
static int check_get(void *cls, const struct GNUNET_RESOLVER_GetMessage *get)
Verify well-formedness of GET-message.
static void free_active_lookup(struct ActiveLookup *al)
Release resources associated with al.
static void extract_hosts(const char *line, size_t line_len)
Extract host information from a line in /etc/hosts.
static int lookup_dns_servers(char ***server_addrs)
Reads the list of nameservers from /etc/resolve.conf.
static void handle_get(void *cls, const struct GNUNET_RESOLVER_GetMessage *msg)
Handle GET-message.
GNUNET_SERVICE_MAIN(GNUNET_OS_project_data_gnunet(), "resolver", GNUNET_SERVICE_OPTION_NONE, &init_cb, &connect_cb, &disconnect_cb, NULL, GNUNET_MQ_hd_var_size(get, GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST, struct GNUNET_RESOLVER_GetMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
static void process_get(const char *hostname, uint16_t record_type, uint32_t client_request_id, struct GNUNET_SERVICE_Client *client)
Process DNS request for hostname with request ID request_id from client demanding records of type rec...
static void handle_resolve_result(void *cls, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len)
We got a result from DNS.
static int try_cache(const char *hostname, uint16_t record_type, uint32_t client_request_id, struct GNUNET_SERVICE_Client *client)
Get an IP address as a string (works for both IPv4 and IPv6).
static struct ResolveCache * cache_tail
Tail of the linked list of cached DNS lookup results.
static struct GNUNET_DNSSTUB_Context * dnsstub_ctx
context of dnsstub library
static unsigned int records
Number of records we found.
struct GNUNET_PQ_ResultSpec __attribute__
Constants for network protocols.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
void * GNUNET_DISK_file_map(const struct GNUNET_DISK_FileHandle *h, struct GNUNET_DISK_MapHandle **m, enum GNUNET_DISK_MapType access, size_t len)
Map a file into memory.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_handle_size(struct GNUNET_DISK_FileHandle *fh, off_t *size)
Get the size of an open file.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_unmap(struct GNUNET_DISK_MapHandle *h)
Unmap a file.
@ GNUNET_DISK_OPEN_READ
Open the file for reading.
@ GNUNET_DISK_PERM_NONE
Nobody is allowed to do anything to the file.
@ GNUNET_DISK_MAP_TYPE_READ
Read-only memory map.
#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.
void GNUNET_DNSPARSER_free_packet(struct GNUNET_DNSPARSER_Packet *p)
Free memory taken by a packet.
#define GNUNET_DNSPARSER_TYPE_ALL
void GNUNET_DNSPARSER_free_record(struct GNUNET_DNSPARSER_Record *r)
Free the given DNS record.
#define GNUNET_DNSPARSER_TYPE_A
#define GNUNET_DNSPARSER_TYPE_PTR
#define GNUNET_DNSPARSER_TYPE_CNAME
#define GNUNET_DNSPARSER_TYPE_AAAA
int GNUNET_DNSPARSER_pack(const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length)
Given a DNS packet p, generate the corresponding UDP payload.
struct GNUNET_DNSPARSER_Packet * GNUNET_DNSPARSER_parse(const char *udp_payload, size_t udp_payload_length)
Parse a UDP payload of a DNS packet in to a nice struct for further processing and manipulation.
struct GNUNET_DNSPARSER_Record * GNUNET_DNSPARSER_duplicate_record(const struct GNUNET_DNSPARSER_Record *r)
Duplicate (deep-copy) the given DNS record.
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.
void GNUNET_DNSSTUB_resolve_cancel(struct GNUNET_DNSSTUB_RequestSocket *rs)
Cancel DNS resolution.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#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.
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#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.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
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_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#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_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
#define GNUNET_MQ_hd_var_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.
#define GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST
Request DNS resolution.
#define GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE
Response to a DNS resolution request.
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_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
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_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define GNUNET_TUN_DNS_CLASS_INTERNET
A few common DNS classes (ok, only one is common, but I list a couple more to make it clear what we'r...
static unsigned int size
Size of the "table".
Information about pending lookups.
char * hostname
Which hostname are we resolving?
struct GNUNET_SERVICE_Client * client
The client that queried the records contained in this cache entry.
struct GNUNET_SCHEDULER_Task * timeout_task
handle for the resolution timeout task
uint16_t record_type
type of queried DNS record
uint16_t dns_id
Unique DNS request ID of a client if a query for this hostname/record_type is currently pending,...
struct ActiveLookup * next
Stored in a DLL.
uint32_t client_request_id
Unique request ID of a client if a query for this hostname/record_type is currently pending,...
int did_aaaa
If record_type is GNUNET_DNSPARSER_TYPE_ALL, did we go again for the AAAA records yet?
struct ActiveLookup * prev
Stored in a DLL.
struct GNUNET_DNSSTUB_RequestSocket * resolve_handle
handle for cancelling a request
Handle used to access files (and pipes).
Handle for a memory-mapping operation.
Easy-to-process, parsed version of a DNS packet.
struct GNUNET_DNSPARSER_Query * queries
Array of all queries in the packet, must contain "num_queries" entries.
unsigned int num_answers
Number of answers in the packet, should be 0 for queries.
struct GNUNET_TUN_DnsFlags flags
Bitfield of DNS flags.
struct GNUNET_DNSPARSER_Record * answers
Array of all answers in the packet, must contain "num_answers" entries.
unsigned int num_additional_records
Number of additional records in the packet, should be 0 for queries.
struct GNUNET_DNSPARSER_Record * additional_records
Array of all additional answers in the packet, must contain "num_additional_records" entries.
struct GNUNET_DNSPARSER_Record * authority_records
Array of all authority records in the packet, must contain "num_authority_records" entries.
unsigned int num_authority_records
Number of authoritative answers in the packet, should be 0 for queries.
unsigned int num_queries
Number of queries in the packet.
uint16_t id
DNS ID (to match replies to requests).
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
char * name
Name of the record that the query is for (0-terminated).
void * data
Binary record data.
size_t data_len
Number of bytes in data.
uint16_t dns_traffic_class
See GNUNET_TUN_DNS_CLASS_*.
char * hostname
For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname.
uint16_t type
See GNUNET_DNSPARSER_TYPE_*.
struct GNUNET_TIME_Absolute expiration_time
When does the record expire?
char * name
Name of the record that the query is for (0-terminated).
struct GNUNET_DNSPARSER_RawRecord raw
Raw data for all other types.
union GNUNET_DNSPARSER_Record::@20 data
Payload of the record (which one of these is valid depends on the 'type').
Handle to the stub resolver.
UDP socket we are using for sending DNS requests to the Internet.
Handle to a message queue.
Request for the resolver.
Entry in list of pending tasks.
Handle to a client that is connected to a service.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
unsigned int recursion_desired
Set to 1 if recursion is desired (client -> server)
Entry in list of cached DNS records for a hostname.
struct RecordListEntry * next
This is a doubly linked list.
struct GNUNET_DNSPARSER_Record * record
Cached data.
struct RecordListEntry * prev
This is a doubly linked list.
A cached DNS lookup result.
struct RecordListEntry * records_tail
tail of a double linked list containing the lookup results
struct ResolveCache * next
This is a doubly linked list.
struct RecordListEntry * records_head
head of a double linked list containing the lookup results
char * hostname
Which hostname is this cache for?
struct ResolveCache * prev
This is a doubly linked list.