diff options
Diffstat (limited to 'src/lib/dns.c')
-rw-r--r-- | src/lib/dns.c | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/src/lib/dns.c b/src/lib/dns.c new file mode 100644 index 0000000..6861fdc --- /dev/null +++ b/src/lib/dns.c @@ -0,0 +1,238 @@ +/******************************************************************************* + * libproxy - A library for proxy configuration + * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ******************************************************************************/ + +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include <netdb.h> +#define __USE_BSD +#include <unistd.h> + +#include "misc.h" +#include "pac.h" +#include "dns.h" + +struct _pxDNS { + pxURL **urls; + int next; + char *domain; +}; + +// The top-level domain blacklist +static char *tld[] = { + // General top-level domains + "arpa", "root", "aero", "biz", "cat", "com", "coop", "edu", "gov", "info", + "int", "jobs", "mil", "mobi", "museum", "name", "net", "org", "pro", "travel", + + // Country codes + "ac", "ad", "ae", "af", "ag", "ai", "al", "am", "an", "ao", "aq", "ar", + "as", "at", "au", "aw", "ax", "az", "ba", "bb", "bd", "be", "bf", "bg", + "bh", "bi", "bj", "bm", "bn", "bo", "br", "bs", "bt", "bv", "bw", "by", + "bz", "ca", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl", "cm", "cn", + "co", "cr", "cu", "cv", "cx", "cy", "cz", "de", "dj", "dk", "dm", "do", + "dz", "ec", "ee", "eg", "er", "es", "et", "eu", "fi", "fj", "fk", "fm", + "fo", "fr", "ga", "gb", "gd", "ge", "gf", "gg", "gh", "gi", "gl", "gm", + "gn", "gp", "gq", "gr", "gs", "gt", "gu", "gw", "gy", "hk", "hm", "hn", + "hr", "ht", "hu", "id", "ie", "il", "im", "in", "io", "iq", "ir", "is", + "it", "je", "jm", "jo", "jp", "ke", "kg", "kh", "ki", "km", "kn", "kr", + "kw", "ky", "kz", "la", "lb", "lc", "li", "lk", "lr", "ls", "lt", "lu", + "lv", "ly", "ma", "mc", "md", "mg", "mh", "mk", "ml", "mm", "mn", "mo", + "mp", "mq", "mr", "ms", "mt", "mu", "mv", "mw", "mx", "my", "mz", "na", + "nc", "ne", "nf", "ng", "ni", "nl", "no", "np", "nr", "nu", "nz", "om", + "pa", "pe", "pf", "pg", "ph", "pk", "pl", "pm", "pn", "pr", "ps", "pt", + "pw", "py", "qa", "re", "ro", "ru", "rw", "sa", "sb", "sc", "sd", "se", + "sg", "sh", "si", "sj", "sk", "sl", "sm", "sn", "sr", "st", "su", "sv", + "sy", "sz", "tc", "td", "tf", "tg", "th", "tj", "tk", "tl", "tm", "tn", + "to", "tp", "tr", "tt", "tv", "tw", "tz", "ua", "ug", "uk", "um", "us", + "uy", "uz", "va", "vc", "ve", "vg", "vi", "vn", "vu", "wf", "ws", "ye", + "yt", "yu", "za", "zm", "zw", + + // Other domains to blacklist + "co.uk", "com.au", + + // Terminator + NULL +}; + +static char * +get_domain_name() +{ + // Get the hostname + char *hostname = px_malloc0(128); + for (int i = 0 ; gethostname(hostname, (i + 1) * 128) && errno == ENAMETOOLONG ; ) + hostname = px_malloc0((++i + 1) * 128); + + // Lookup the hostname + // TODO: Make this whole process not suck + struct hostent *host_info = gethostbyname(hostname); + if (host_info) + { + px_free(hostname); + hostname = px_strdup(host_info->h_name); + } + + // Get domain portion + if (!strchr(hostname, '.')) return NULL; + if (!strcmp(".", strchr(hostname, '.'))) return NULL; + char *tmp = px_strdup(strchr(hostname, '.') + 1); + px_free(hostname); + return tmp; +} + +static pxURL ** +get_urls(const char *domain) +{ + pxURL **urls; + + if (!domain) + { + urls = px_malloc0(sizeof(pxURL *) * 2); + urls[0] = px_url_new("http://wpad/wpad.dat"); + return urls; + } + + // Split up the domain + char **domainv = px_strsplit(domain, "."); + if (!domainv) return NULL; + + // Count the number of domain blocks + int count = 0; + for (int i=0 ; *(domainv + i) ; i++) + count++; + + // Allocate our URL array + urls = px_malloc0(sizeof(pxURL *) * (count + 2)); + + // Create the URLs + urls[0] = px_url_new("http://wpad/wpad.dat"); + char *url = px_malloc0(strlen("http://wpad./wpad.dat") + strlen(domain) + 1); + for (int i=0, j=1 ; domainv[i] ; i++) { + // Check the domain against the blacklist + char *tmp = px_strjoin((const char **) (domainv + i), "."); + for (int k=0; tld[k] ; k++) + if (!strcmp(tmp, tld[k])) { px_free(tmp); tmp = NULL; break; } + if (!tmp) continue; + + // Create the URL + sprintf(url, "http://wpad.%s/wpad.dat", tmp); + px_free(tmp); tmp = NULL; + urls[j] = px_url_new(url); + if (urls[j]) j++; + } + px_free(url); + px_strfreev(domainv); + + return urls; +} + +/** + * Creates a new pxDNS PAC detector. + * @return New pxDNS PAD detector + */ +pxDNS * +px_dns_new() +{ + return px_dns_new_full(NULL); +} + +/** + * Creates a new pxDNS PAC detector with more options. + * @domain The domain name to use when detecting or NULL to use the default + * @return New pxDNS PAD detector + */ +pxDNS * +px_dns_new_full(const char *domain) +{ + pxDNS *self = px_malloc0(sizeof(pxDNS)); + self->domain = px_strdup(domain); + return self; +} + +/** + * Detect the next PAC in the chain. + * @return Detected PAC or NULL if none is found + */ +pxPAC * +px_dns_next(pxDNS *self) +{ + if (!self) return NULL; + + if (!self->urls) { + char *domain; + + // Reset the counter + self->next = 0; + + // Get the domain name + if (self->domain) + domain = px_strdup(self->domain); + else + domain = get_domain_name(); + + // Get the URLs + self->urls = get_urls(domain); + px_free(domain); + + // Make sure we have more than one URL + if (!self->urls || !self->urls[0]) + return NULL; + } + + // Try to find a PAC at each URL + for (pxPAC *pac = NULL ; self->urls[self->next] ; ) + if ((pac = px_pac_new(self->urls[self->next++]))) + return pac; + + return NULL; +} + +/** + * Restarts the detection chain at the beginning. + */ +void +px_dns_rewind(pxDNS *self) +{ + if (!self) return; + + if (self->urls) { + for (int i = 0 ; self->urls[i] ; i++) + px_url_free(self->urls[i]); + px_free(self->urls); + self->urls = NULL; + } + self->next = 0; + return; +} + +/** + * Frees a pxDNS object. + */ +void +px_dns_free(pxDNS *self) +{ + if (!self) return; + + if (self->urls) { + for (int i = 0 ; self->urls[i] ; i++) + px_url_free(self->urls[i]); + px_free(self->urls); self->urls = NULL; + } + px_free(self->domain); + px_free(self); +} |