[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [gnunet] branch master updated: add support for /etc/hosts
From: |
gnunet |
Subject: |
[GNUnet-SVN] [gnunet] branch master updated: add support for /etc/hosts |
Date: |
Thu, 18 Oct 2018 15:55:32 +0200 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository gnunet.
The following commit(s) were added to refs/heads/master by this push:
new e76f4a669 add support for /etc/hosts
e76f4a669 is described below
commit e76f4a66930043ede71300fffe38ab48746ca5b5
Author: Christian Grothoff <address@hidden>
AuthorDate: Thu Oct 18 15:55:30 2018 +0200
add support for /etc/hosts
---
src/include/gnunet_disk_lib.h | 1 +
src/util/gnunet-service-resolver.c | 264 +++++++++++++++++++++++++++++++++++--
2 files changed, 254 insertions(+), 11 deletions(-)
diff --git a/src/include/gnunet_disk_lib.h b/src/include/gnunet_disk_lib.h
index b7376b99b..950df5a4e 100644
--- a/src/include/gnunet_disk_lib.h
+++ b/src/include/gnunet_disk_lib.h
@@ -781,6 +781,7 @@ GNUNET_DISK_file_change_owner (const char *filename,
*/
struct GNUNET_DISK_MapHandle;
+
/**
* Map a file into memory
* @param h open file handle
diff --git a/src/util/gnunet-service-resolver.c
b/src/util/gnunet-service-resolver.c
index 252408466..d907bd8d9 100644
--- a/src/util/gnunet-service-resolver.c
+++ b/src/util/gnunet-service-resolver.c
@@ -57,6 +57,7 @@ struct RecordListEntry
* Cached data.
*/
struct GNUNET_DNSPARSER_Record *record;
+
};
@@ -165,6 +166,16 @@ static struct ResolveCache *cache_head;
static struct ResolveCache *cache_tail;
/**
+ * Head of the linked list of DNS lookup results from /etc/hosts.
+ */
+static struct ResolveCache *hosts_head;
+
+/**
+ * Tail of the linked list of DNS lookup results from /etc/hosts.
+ */
+static struct ResolveCache *hosts_tail;
+
+/**
* Start of the linked list of active DNS lookups.
*/
static struct ActiveLookup *lookup_head;
@@ -219,6 +230,34 @@ free_cache_entry (struct ResolveCache *rc)
/**
+ * Remove @a entry from cache.
+ *
+ * @param rc entry to free
+ */
+static void
+free_hosts_entry (struct ResolveCache *rc)
+{
+ struct RecordListEntry *pos;
+
+ while (NULL != (pos = rc->records_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (rc->records_head,
+ rc->records_tail,
+ pos);
+ GNUNET_DNSPARSER_free_record (pos->record);
+ GNUNET_free (pos->record);
+ GNUNET_free (pos);
+ }
+ GNUNET_free_non_null (rc->hostname);
+ GNUNET_CONTAINER_DLL_remove (hosts_head,
+ hosts_tail,
+ rc);
+ cache_size--;
+ GNUNET_free (rc);
+}
+
+
+/**
* Release resources associated with @a al
*
* @param al an active lookup
@@ -299,8 +338,9 @@ static int
lookup_dns_servers (char ***server_addrs)
{
struct GNUNET_DISK_FileHandle *fh;
- char buf[2048];
- ssize_t bytes_read;
+ struct GNUNET_DISK_MapHandle *mh;
+ off_t bytes_read;
+ const char *buf;
size_t read_offset;
unsigned int num_dns_servers;
@@ -314,9 +354,28 @@ lookup_dns_servers (char ***server_addrs)
"DNS resolution will not be possible.\n");
return -1;
}
- bytes_read = GNUNET_DISK_file_read (fh,
- buf,
- sizeof (buf));
+ if (GNUNET_OK !=
+ GNUNET_DISK_file_handle_size (fh,
+ &bytes_read))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Could not determine size of /etc/resolv.conf. "
+ "DNS resolution will not be possible.\n");
+ GNUNET_DISK_file_close (fh);
+ return -1;
+ }
+ if (bytes_read > SIZE_MAX)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "/etc/resolv.conf file too large to mmap. "
+ "DNS resolution will not be possible.\n");
+ GNUNET_DISK_file_close (fh);
+ return -1;
+ }
+ buf = GNUNET_DISK_file_map (fh,
+ &mh,
+ GNUNET_DISK_MAP_TYPE_READ,
+ (size_t) bytes_read);
*server_addrs = NULL;
read_offset = 0;
num_dns_servers = 0;
@@ -346,6 +405,7 @@ lookup_dns_servers (char ***server_addrs)
}
read_offset += line_len + 1;
}
+ GNUNET_DISK_file_unmap (mh);
GNUNET_DISK_file_close (fh);
return (int) num_dns_servers;
}
@@ -534,9 +594,14 @@ remove_expired (struct ResolveCache *rc)
{
n = pos->next;
if (now.abs_value_us > pos->record->expiration_time.abs_value_us)
+ {
GNUNET_CONTAINER_DLL_remove (rc->records_head,
rc->records_tail,
pos);
+ GNUNET_DNSPARSER_free_record (pos->record);
+ GNUNET_free (pos->record);
+ GNUNET_free (pos);
+ }
}
if (NULL == rc->records_head)
{
@@ -584,15 +649,22 @@ try_cache (const char *hostname,
struct ResolveCache *next;
int found;
- next = cache_head;
- for (pos = next; NULL != pos; pos = next)
- {
- next = pos->next;
- if (GNUNET_YES == remove_expired (pos))
- continue;
+ for (pos = hosts_head; NULL != pos; pos = pos->next)
if (0 == strcmp (pos->hostname,
hostname))
break;
+ if (NULL == pos)
+ {
+ next = cache_head;
+ for (pos = next; NULL != pos; pos = next)
+ {
+ next = pos->next;
+ if (GNUNET_YES == remove_expired (pos))
+ continue;
+ if (0 == strcmp (pos->hostname,
+ hostname))
+ break;
+ }
}
if (NULL == pos)
{
@@ -853,6 +925,8 @@ handle_resolve_result (void *cls,
packet_size,
&handle_resolve_result,
al);
+ GNUNET_free (packet_buf);
+ GNUNET_DNSPARSER_free_packet (parsed);
return;
}
}
@@ -1169,7 +1243,174 @@ shutdown_task (void *cls)
free_active_lookup (lookup_head);
while (NULL != cache_head)
free_cache_entry (cache_head);
+ while (NULL != hosts_head)
+ free_hosts_entry (hosts_head);
GNUNET_DNSSTUB_stop (dnsstub_ctx);
+ GNUNET_free (my_domain);
+}
+
+
+/**
+ * Add information about a host from /etc/hosts
+ * to our cache.
+ *
+ * @param hostname the name of the host
+ * @param rec_type DNS record type to use
+ * @param data payload
+ * @param data_size number of bytes in @a data
+ */
+static void
+add_host (const char *hostname,
+ uint16_t rec_type,
+ const void *data,
+ size_t data_size)
+{
+ struct ResolveCache *rc;
+ struct RecordListEntry *rle;
+ struct GNUNET_DNSPARSER_Record *rec;
+
+ rec = GNUNET_malloc (sizeof (struct GNUNET_DNSPARSER_Record));
+ rec->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS;
+ rec->type = rec_type;
+ rec->dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
+ rec->name = GNUNET_strdup (hostname);
+ rec->data.raw.data = GNUNET_memdup (data,
+ data_size);
+ rec->data.raw.data_len = data_size;
+ rle = GNUNET_new (struct RecordListEntry);
+ rle->record = rec;
+ rc = GNUNET_new (struct ResolveCache);
+ rc->hostname = GNUNET_strdup (hostname);
+ GNUNET_CONTAINER_DLL_insert (rc->records_head,
+ rc->records_tail,
+ rle);
+ GNUNET_CONTAINER_DLL_insert (hosts_head,
+ hosts_tail,
+ rc);
+}
+
+
+/**
+ * Extract host information from a line in /etc/hosts
+ *
+ * @param line the line to parse
+ * @param line_len number of bytes in @a line
+ */
+static void
+extract_hosts (const char *line,
+ size_t line_len)
+{
+ const char *c;
+ struct in_addr v4;
+ struct in6_addr v6;
+ char *tbuf;
+ char *tok;
+
+ /* ignore everything after '#' */
+ c = memrchr (line,
+ (unsigned char) '#',
+ line_len);
+ if (NULL != c)
+ line_len = c - line;
+ /* ignore leading whitespace */
+ while ( (0 > line_len) &&
+ isspace ((unsigned char) *line) )
+ {
+ line++;
+ line_len--;
+ }
+ tbuf = GNUNET_strndup (line,
+ line_len);
+ tok = strtok (tbuf, " \t");
+ if (NULL == tok)
+ {
+ GNUNET_free (tbuf);
+ return;
+ }
+ if (1 == inet_pton (AF_INET,
+ tok,
+ &v4))
+ {
+ while (NULL != (tok = strtok (NULL, " \t")))
+ add_host (tok,
+ GNUNET_DNSPARSER_TYPE_A,
+ &v4,
+ sizeof (struct in_addr));
+ }
+ else if (1 == inet_pton (AF_INET6,
+ tok,
+ &v6))
+ {
+ while (NULL != (tok = strtok (NULL, " \t")))
+ add_host (tok,
+ GNUNET_DNSPARSER_TYPE_AAAA,
+ &v6,
+ sizeof (struct in6_addr));
+ }
+ GNUNET_free (tbuf);
+}
+
+
+/**
+ * Reads the list of hosts from /etc/hosts.
+ */
+static void
+load_etc_hosts (void)
+{
+ struct GNUNET_DISK_FileHandle *fh;
+ struct GNUNET_DISK_MapHandle *mh;
+ off_t bytes_read;
+ const char *buf;
+ size_t read_offset;
+
+ fh = GNUNET_DISK_file_open ("/etc/hosts",
+ GNUNET_DISK_OPEN_READ,
+ GNUNET_DISK_PERM_NONE);
+ if (NULL == fh)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Failed to open /etc/hosts");
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_DISK_file_handle_size (fh,
+ &bytes_read))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Could not determin size of /etc/hosts. "
+ "DNS resolution will not be possible.\n");
+ GNUNET_DISK_file_close (fh);
+ return;
+ }
+ if (bytes_read > SIZE_MAX)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "/etc/hosts file too large to mmap. "
+ "DNS resolution will not be possible.\n");
+ GNUNET_DISK_file_close (fh);
+ return;
+ }
+ buf = GNUNET_DISK_file_map (fh,
+ &mh,
+ GNUNET_DISK_MAP_TYPE_READ,
+ (size_t) bytes_read);
+ read_offset = 0;
+ while (read_offset < bytes_read)
+ {
+ const char *newline;
+ size_t line_len;
+
+ newline = strchr (buf + read_offset,
+ '\n');
+ if (NULL == newline)
+ break;
+ line_len = newline - buf - read_offset;
+ extract_hosts (buf + read_offset,
+ line_len);
+ read_offset += line_len + 1;
+ }
+ GNUNET_DISK_file_unmap (mh);
+ GNUNET_DISK_file_close (fh);
}
@@ -1190,6 +1431,7 @@ init_cb (void *cls,
(void) cfg;
(void) sh;
+ load_etc_hosts ();
GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
cls);
dnsstub_ctx = GNUNET_DNSSTUB_start (128);
--
To stop receiving notification emails like this one, please contact
address@hidden
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] [gnunet] branch master updated: add support for /etc/hosts,
gnunet <=