diff options
| author | npmccallum <npmccallum@c587cffe-e639-0410-9787-d7902ae8ed56> | 2007-10-11 03:59:21 +0000 |
|---|---|---|
| committer | npmccallum <npmccallum@c587cffe-e639-0410-9787-d7902ae8ed56> | 2007-10-11 03:59:21 +0000 |
| commit | b15404b30e1ac270a40476614a7e656741c258a0 (patch) | |
| tree | 102163eb50b834fbb558ec8b4759120ff0863e45 /src/lib | |
| parent | fe2c4c79d115291849cbabe09130c7ee0274a540 (diff) | |
| download | libproxy-git-b15404b30e1ac270a40476614a7e656741c258a0.tar.gz | |
major rework of tree structure; import from libwpad
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/Makefile.am | 8 | ||||
| -rw-r--r-- | src/lib/dhcp.c | 63 | ||||
| -rw-r--r-- | src/lib/dhcp.h | 52 | ||||
| -rw-r--r-- | src/lib/dns.c | 219 | ||||
| -rw-r--r-- | src/lib/dns.h | 59 | ||||
| -rw-r--r-- | src/lib/ip.c | 234 | ||||
| -rw-r--r-- | src/lib/ip.h | 95 | ||||
| -rw-r--r-- | src/lib/misc.c | 199 | ||||
| -rw-r--r-- | src/lib/misc.h | 89 | ||||
| -rw-r--r-- | src/lib/pac.c | 166 | ||||
| -rw-r--r-- | src/lib/pac.h | 68 | ||||
| -rw-r--r-- | src/lib/proxy.h | 42 | ||||
| -rw-r--r-- | src/lib/proxy_factory.c | 224 | ||||
| -rw-r--r-- | src/lib/proxy_factory.h | 54 | ||||
| -rw-r--r-- | src/lib/slp.c | 63 | ||||
| -rw-r--r-- | src/lib/slp.h | 52 | ||||
| -rw-r--r-- | src/lib/url.c | 257 | ||||
| -rw-r--r-- | src/lib/url.h | 85 | ||||
| -rw-r--r-- | src/lib/wpad.c | 126 | ||||
| -rw-r--r-- | src/lib/wpad.h | 71 |
20 files changed, 2226 insertions, 0 deletions
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am new file mode 100644 index 0000000..3badb67 --- /dev/null +++ b/src/lib/Makefile.am @@ -0,0 +1,8 @@ +lib_LTLIBRARIES = libproxy.la +libproxy_la_SOURCES = misc.c ip.c url.c pac.c dhcp.c dns.c slp.c wpad.c proxy_factory.c \ + misc.h ip.h url.h pac.h dhcp.h dns.h slp.h wpad.h proxy_factory.h proxy.h +libproxy_la_CFLAGS = -Wall +libproxy_la_LDFLAGS = -lm + +include_HEADERS = proxy.h + diff --git a/src/lib/dhcp.c b/src/lib/dhcp.c new file mode 100644 index 0000000..1afe13d --- /dev/null +++ b/src/lib/dhcp.c @@ -0,0 +1,63 @@ +/******************************************************************************* + * 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 <stdlib.h> + +#include "pac.h" +#include "dhcp.h" + +struct _pxDHCP { }; + +/** + * Creates a new pxDHCP PAC detector. + * @return New pxDHCP PAD detector + */ +pxDHCP * +px_dhcp_new() +{ + return NULL; +} + +/** + * Detect the next PAC in the chain. + * @return Detected PAC or NULL if none is found + */ +pxPAC * +px_dhcp_next(pxDHCP *self) +{ + return NULL; +} + +/** + * Restarts the detection chain at the beginning. + */ +void +px_dhcp_rewind(pxDHCP *self) +{ + return; +} + +/** + * Frees a pxDHCP object. + */ +void +px_dhcp_free(pxDHCP *self) +{ + return; +} diff --git a/src/lib/dhcp.h b/src/lib/dhcp.h new file mode 100644 index 0000000..2e83e67 --- /dev/null +++ b/src/lib/dhcp.h @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ + +#ifndef DHCP_H_ +#define DHCP_H_ + +#include "pac.h" + +/** + * A DHCP PAC detector. All fields are private. + */ +typedef struct _pxDHCP pxDHCP; + +/** + * Creates a new DHCP PAC detector. + * @return New DHCP PAD detector + */ +pxDHCP *px_dhcp_new(); + +/** + * Detect the next PAC in the chain. + * @return Detected PAC or NULL if none is found + */ +pxPAC *px_dhcp_next(pxDHCP *self); + +/** + * Restarts the detection chain at the beginning. + */ +void px_dhcp_rewind(pxDHCP *self); + +/** + * Frees a pxDHCP object. + */ +void px_dhcp_free(pxDHCP *self); + +#endif /*DHCP_H_*/ diff --git a/src/lib/dns.c b/src/lib/dns.c new file mode 100644 index 0000000..a3ee1a7 --- /dev/null +++ b/src/lib/dns.c @@ -0,0 +1,219 @@ +/******************************************************************************* + * 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> +#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 *tmp = px_malloc0(128); + for (int i = 0 ; gethostname(tmp, (i + 1) * 128) && errno == ENAMETOOLONG ; ) + tmp = px_malloc0((++i + 1) * 128); + + // Lookup the hostname + struct hostent *host_info = gethostbyname(tmp); + px_free(tmp); tmp = NULL; + if (!host_info) return NULL; + + // Get domain portion + if (!strchr(host_info->h_name, '.')) return NULL; + if (!strcmp(".", strchr(host_info->h_name, '.'))) return NULL; + return px_strdup(strchr(host_info->h_name, '.') + 1); +} + +static pxURL ** +get_urls(const char *domain) +{ + // 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 + pxURL **urls = px_malloc0(sizeof(pxURL *) * count); + + // Create the URLs + char *url = px_malloc0(strlen("http://wpad./wpad.dat") + strlen(domain) + 1); + for (int i=0, j=0 ; 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); + + 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->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(); + if (!domain) return NULL; + + // 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); +} diff --git a/src/lib/dns.h b/src/lib/dns.h new file mode 100644 index 0000000..f3deac7 --- /dev/null +++ b/src/lib/dns.h @@ -0,0 +1,59 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ + +#ifndef DNS_H_ +#define DNS_H_ + +#include "pac.h" + +/** + * A pxDNS PAC detector. All fields are private. + */ +typedef struct _pxDNS pxDNS; + +/** + * Creates a new pxDNS PAC detector. + * @return New pxDNS PAD detector + */ +pxDNS *px_dns_new(); + +/** + * 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); + +/** + * Detect the next PAC in the chain. + * @return Detected PAC or NULL if none is found + */ +pxPAC *px_dns_next(pxDNS *self); + +/** + * Restarts the detection chain at the beginning. + */ +void px_dns_rewind(pxDNS *self); + +/** + * Frees a pxDNS object. + */ +void px_dns_free(pxDNS *self); + +#endif /*DNS_H_*/ diff --git a/src/lib/ip.c b/src/lib/ip.c new file mode 100644 index 0000000..35c1819 --- /dev/null +++ b/src/lib/ip.c @@ -0,0 +1,234 @@ +/******************************************************************************* + * 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 <stdint.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <netdb.h> +#include <stdio.h> + +#include "misc.h" +#include "ip.h" + +/** + * pxIP object. All fields are private. + */ +struct _IP { + pxIPVersion version; + int length; + char data[16]; +}; + +/** + * Opens an IP connection to the IP address at the specified port and connection type. + * @conntype The type of connection to create (TCP or UDP) + * @port The port to connect to + * @return The open socket from the connection + */ +int +px_ip_connect(pxIP *self, pxIPConnectionType conntype, int port) +{ + struct sockaddr *dest_addr; + int addr_len = 0, domain = 0; + + if (self->version == pxIPv4) // Create IPv4 dest_addr + { + struct sockaddr_in *tmp = px_malloc0(sizeof(struct sockaddr_in)); + tmp->sin_family = AF_INET; + memcpy(&(tmp->sin_addr.s_addr), self->data, self->length); + tmp->sin_port = htons(port); + dest_addr = (struct sockaddr *) tmp; + addr_len = sizeof(struct sockaddr_in); + domain = PF_INET; + } + else if (self->version == pxIPv6) // Create IPv6 dest_addr + { + struct sockaddr_in6 *tmp = px_malloc0(sizeof(struct sockaddr_in6)); + tmp->sin6_family = AF_INET6; + memcpy(&(tmp->sin6_addr.in6_u), self->data, self->length); + tmp->sin6_port = htons(port); + dest_addr = (struct sockaddr *) tmp; + addr_len = sizeof(struct sockaddr_in6); + domain = PF_INET6; + } + else + return -1; + + // Create socket + int sock = -1; + if (conntype == TCP) sock = socket(domain, SOCK_STREAM, 0); + else if (conntype == UDP) sock = socket(domain, SOCK_DGRAM, 0); + + // Make sure we have a valid socket + if (sock < 0) { px_free(dest_addr); return sock; } + + // Connect + if (connect(sock, dest_addr, addr_len)) + { + close(sock); + px_free(dest_addr); + return -1; + } + + px_free(dest_addr); + return sock; +} + +/** + * Frees an pxIP object + */ +void +px_ip_free(pxIP *self) +{ + px_free(self); +} + +/** + * Returns the version of the IP address (pxIPv4 or pxIPv6) + * @return pxIPv4 or pxIPv6 + */ +pxIPVersion +px_ip_get_version(pxIP *self) +{ + return self->version; +} + +/** + * Creates a new pxIP from raw data. + * @version The version of the IP address (pxIPv4 or pxIPv6) + * @data The raw data to use (correct byte order is assumed) + * @return New pxIP from the raw data + */ +pxIP * +px_ip_new_from_data(pxIPVersion version, char *data) +{ + if (!data) return NULL; + + // Create the pxIP object + pxIP *self = px_malloc0(sizeof(pxIP)); + + // Set the version and length + self->version = version; + if (version == pxIPv4) self->length = 4; + else if (version == pxIPv6) self->length = 16; + else { px_free(self); return NULL; } + + // Copy the byte data + memcpy(self->data, data, self->length); + return self; +} + +/** + * Creates a new pxIP from a hostent struct + * @host The hostent struct to use + * @return The first pxIP from the hostent struct + */ +pxIP * +px_ip_new_from_hostent(const struct hostent *host) +{ + if (!host) return NULL; + + if (host->h_addrtype == AF_INET) + return px_ip_new_from_data(pxIPv4, host->h_addr); + else if (host->h_addrtype == AF_INET6) + return px_ip_new_from_data(pxIPv6, host->h_addr); + + return NULL; +} + +/** + * Creates all possible new pxIPs from a hostent struct + * @host The hostent struct to use + * @return NULL-terminated array of all possible pxIPs + */ +pxIP ** +px_ip_new_from_hostent_all(const struct hostent *host) +{ + int version, count; + if (!host) return NULL; + + // Get the version + if (host->h_addrtype == AF_INET) version = pxIPv4; + else if (host->h_addrtype == AF_INET6) version = pxIPv6; + else return NULL; + + // Count the total ip addresses + for (count = 0 ; host->h_addr_list[count] ; count++); + + // Allocate + pxIP **ips = px_malloc0(sizeof(pxIP *) * (count + 1)); + + // Create + for (count = 0 ; host->h_addr_list[count] ; count++) + { + ips[count] = px_ip_new_from_data(version, host->h_addr_list[count]); + if (!ips[count]) goto error; + } + + return ips; + + error: + for (count = 0 ; host->h_addr_list[count] ; count++) + px_free(ips[count]); + px_free(ips); + return NULL; +} + +/** + * Creates a string representation of the IP address. + * @return Newly allocated string representing the IP address + */ +char * +px_ip_to_string(pxIP *self) +{ + if (self->version != pxIPv4 && self->version != pxIPv6) return NULL; + + char *string = px_malloc0(40); + if (self->version == pxIPv4) + sprintf(string, "%hhu.%hhu.%hhu.%hhu", self->data[0], + self->data[1], + self->data[2], + self->data[3]); + else if (self->version == pxIPv6) + sprintf(string, "%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx", + self->data[0], + self->data[1], + self->data[2], + self->data[3], + self->data[4], + self->data[5], + self->data[6], + self->data[7], + self->data[8], + self->data[9], + self->data[10], + self->data[11], + self->data[12], + self->data[13], + self->data[14], + self->data[15]); + + return string; +} + + diff --git a/src/lib/ip.h b/src/lib/ip.h new file mode 100644 index 0000000..ec2a5fc --- /dev/null +++ b/src/lib/ip.h @@ -0,0 +1,95 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ + +#ifndef IP_H_ +#define IP_H_ + +#include <netdb.h> // For struct hostent + +/** + * Version of the pxIP protocol to use + */ +enum _pxIPVersion { + pxIPv4 = 4, + pxIPv6 = 6, +}; +typedef enum _pxIPVersion pxIPVersion; + +/** + * Types of pxIP connections + */ +enum _pxIPConnectionType { + TCP = 0, + UDP = 1, +}; +typedef enum _pxIPConnectionType pxIPConnectionType; + +/** + * pxIP object. All fields are private. + */ +typedef struct _IP pxIP; + +/** + * Opens an IP connection to the IP address at the specified port and connection type. + * @conntype The type of connection to create (TCP or UDP) + * @port The port to connect to + * @return The open socket from the connection + */ +int px_ip_connect(pxIP *self, pxIPConnectionType conntype, int port); + +/** + * Frees an pxIP object + */ +void px_ip_free(pxIP *self); + +/** + * Returns the version of the IP address (pxIPv4 or pxIPv6) + * @return pxIPv4 or pxIPv6 + */ +pxIPVersion px_ip_get_version(pxIP *self); + +/** + * Creates a new pxIP from raw data. + * @version The version of the IP address (pxIPv4 or pxIPv6) + * @data The raw data to use (correct byte order is assumed) + * @return New pxIP from the raw data + */ +pxIP *px_ip_new_from_data(pxIPVersion version, char *data); + +/** + * Creates a new pxIP from a hostent struct + * @host The hostent struct to use + * @return The first pxIP from the hostent struct + */ +pxIP *px_ip_new_from_hostent(const struct hostent *host); + +/** + * Creates all possible new pxIPs from a hostent struct + * @host The hostent struct to use + * @return NULL-terminated array of all possible pxIPs + */ +pxIP **px_ip_new_from_hostent_all(const struct hostent *host); + +/** + * Creates a string representation of the IP address. + * @return Newly allocated string representing the IP address + */ +char *px_ip_to_string(pxIP *self); + +#endif /*IP_H_*/ diff --git a/src/lib/misc.c b/src/lib/misc.c new file mode 100644 index 0000000..9b3699b --- /dev/null +++ b/src/lib/misc.c @@ -0,0 +1,199 @@ +/******************************************************************************* + * 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 <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "misc.h" + +/** + * Allocates memory and always returns valid memory. + * @size Amount of memory to allocate in bytes + * @return Pointer to the allocated memory + */ +void * +px_malloc0(size_t size) +{ + void *mem = malloc(size); + assert(mem != NULL); + memset(mem, 0, size); + return mem; +} + +/** + * Frees memory and doesn't crash if that memory is NULL + * @mem Memory to free or NULL + */ +void +px_free(void *mem) +{ + if (!mem) return; + free(mem); +} + +/** + * Duplicates the first n characters of the string s + * @s String to duplicate + * @n Number of characters of the string to duplicate + * @return Newly allocated string + */ +char * +px_strndup(const char *s, size_t n) +{ + if (!s) return NULL; + char *tmp = px_malloc0(n+1); + strncpy(tmp, s, n); + return tmp; +} + +/** + * Duplicates a string + * @s String to duplicate + * @return Newly allocated string + */ +char * +px_strdup(const char *s) +{ + if (!s) return NULL; + return px_strndup(s, strlen(s)); +} + +/** + * Joins NULL terminated array of strings into one string separated by delimiter + * @strv NULL terminated array of string to join + * @delimiter The string to use in between each string in the array + * @return Newly allocated string + */ +char * +px_strjoin(const char **strv, const char *delimiter) +{ + if (!strv) return NULL; + if (!delimiter) return NULL; + + // Count up the length we need + size_t length = 0; + for (int i=0 ; strv[i]; i++) + length += strlen(strv[i]) + strlen(delimiter); + if (!length) return NULL; + + // Do the join + char *str = px_malloc0(length); + for (int i=0 ; strv[i]; i++) + sprintf(str, "%s%s%s", str, strv[i], delimiter); + str[strlen(str) - strlen(delimiter)] = 0; + return str; +} + +/** + * Splits a string into a NULL terminated array based on delimiter + * @string The string to split + * @delimiter The delimiter to split on + * @return The NULL terminated array (free with px_strfreev()) + */ +char ** +px_strsplit(const char *string, const char *delimiter) +{ + // Count how many times the delimiter appears + int count = 1; + for (const char *tmp = string ; (tmp = strstr(tmp, delimiter)) ; tmp += strlen(delimiter)) + count++; + + // Allocate the vector + char **strv = px_malloc0(sizeof(char *) * (count + 1)); + + // Fill the vector + const char *last = string; + for (int i=0 ; i < count ; i++) + { + char *tmp = strstr(last, delimiter); + if (!tmp) + strv[i] = px_strdup(last); + else + { + strv[i] = px_strndup(last, tmp - last); + last = tmp + strlen(delimiter); + } + } + + return strv; +} + +/** + * Frees the memory used by a NULL terminated string array + * @strv The NULL terminated string array + */ +void +px_strfreev(char **strv) +{ + if (!strv) return; + for (int i=0 ; *(strv + i) ; i++) + px_free(*(strv + i)); + px_free(strv); +} + +/** + * Reads a single line of text from the specified file descriptor + * @fd File descriptor to read from + * @return Newly allocated string containing one line only + */ +char * +px_readline(int fd) +{ + // Verify we have an open socket + if (fd < 0) return NULL; + + // For each character received add it to the buffer unless it is a newline + char *buffer = NULL; + for (int i=1; i > 0 ; i++) + { + char c; + + // Receive a single character, check for newline or EOF + if (read(fd, &c, 1) != 1 || c == '\n') break; + + // Allocate new buffer if we need + if (i % 1024 == 1) + { + char *tmp = buffer; + buffer = px_malloc0(1024+i); + if (tmp) { strcpy(buffer, tmp); px_free(tmp); } + } + + // Add new character + buffer[i-1] = c; + } + return buffer; +} + +/** + * Trims off all the leading whitespace characters + * @string The string to strip + * @return A newly allocated copy of string without all the leading whitespace + */ +char * +px_lstrip(char *string) +{ + for (int i=0 ; string[i] ; i++) + if (string[i] != ' ' && string [i] != '\t') + return px_strdup(string + i); + return px_strdup(""); +} diff --git a/src/lib/misc.h b/src/lib/misc.h new file mode 100644 index 0000000..388b1bc --- /dev/null +++ b/src/lib/misc.h @@ -0,0 +1,89 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ + +#ifndef MISC_H_ +#define MISC_H_ + +#include <stdlib.h> // For type size_t + +/** + * Allocates memory and always returns valid memory. + * @size Amount of memory to allocate in bytes + * @return Pointer to the allocated memory + */ +void *px_malloc0(size_t size); + +/** + * Frees memory and doesn't crash if that memory is NULL + * @mem Memory to free or NULL + */ +void px_free(void *mem); + +/** + * Duplicates the first n characters of the string s + * @s String to duplicate + * @n Number of characters of the string to duplicate + * @return Newly allocated string + */ +char *px_strndup(const char *s, size_t n); + +/** + * Duplicates a string + * @s String to duplicate + * @return Newly allocated string + */ +char *px_strdup(const char *s); + +/** + * Joins NULL terminated array of strings into one string separated by delimiter + * @strv NULL terminated array of string to join + * @delimiter The string to use in between each string in the array + * @return Newly allocated string + */ +char *px_strjoin(const char **strv, const char *delimiter); + +/** + * Splits a string into a NULL terminated array based on delimiter + * @string The string to split + * @delimiter The delimiter to split on + * @return The NULL terminated array (free with px_strfreev()) + */ +char **px_strsplit(const char *string, const char *delimiter); + +/** + * Frees the memory used by a NULL terminated string array + * @strv The NULL terminated string array + */ +void px_strfreev(char **strv); + +/** + * Reads a single line of text from the specified file descriptor + * @fd File descriptor to read from + * @return Newly allocated string containing one line only + */ +char *px_readline(int fd); + +/** + * Trims off all the leading whitespace characters + * @string The string to strip + * @return A newly allocated copy of string without all the leading whitespace + */ +char *px_lstrip(char *string); + +#endif /*MISC_H_*/ diff --git a/src/lib/pac.c b/src/lib/pac.c new file mode 100644 index 0000000..df1c174 --- /dev/null +++ b/src/lib/pac.c @@ -0,0 +1,166 @@ +/******************************************************************************* + * 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 <unistd.h> +#include <string.h> + +#include "url.h" +#include "misc.h" +#include "pac.h" + +#define PAC_MIME_TYPE "application/x-ns-proxy-autoconfig" + +/** + * ProxyAutoConfig object. All fields are private. + */ +struct _pxPAC { + pxURL *url; + char *cache; + time_t expires; +}; + +/** + * Frees memory used by the ProxyAutoConfig. + */ +void +px_pac_free(pxPAC *self) +{ + if (!self) return; + px_url_free(self->url); + px_free(self->cache); + px_free(self); +} + +/** + * Get the URL which the pxPAC uses. + * @return The URL that the pxPAC came from + */ +const pxURL * +px_pac_get_url(pxPAC *self) +{ + return self->url; +} + +/** + * Create a new ProxyAutoConfig. + * @url The URL where the PAC file is found + * @return A new ProxyAutoConfig or NULL on error + */ +pxPAC * +px_pac_new(pxURL *url) +{ + if (!url) return NULL; + + // Allocate the object + pxPAC *self = px_malloc0(sizeof(pxPAC)); + + // Copy the given URL + self->url = px_url_new(px_url_to_string(url)); // Always returns valid value + + // Make sure we have a real pxPAC + if (!px_pac_reload(self)) { px_pac_free(self); return NULL; } + + return self; +} + +/** + * Create a new ProxyAutoConfig (from a string for convenience). + * @url The url (string) where the PAC file is found + * @return A new ProxyAutoConfig or NULL on error + */ +pxPAC * +px_pac_new_from_string(char *url) +{ + // Create temporary URL + pxURL *tmpurl = px_url_new(url); + if (!tmpurl) return NULL; + + // Create pac + pxPAC *self = px_pac_new(tmpurl); + px_url_free(tmpurl); // Free no longer used URL + if (!self) return NULL; + return self; +} + +/** + * Returns the Javascript code which the pxPAC uses. + * @return The Javascript code used by the pxPAC + */ +const char * +px_pac_to_string(pxPAC *self) +{ + return self->cache; +} + +/** + * Download the latest version of the pxPAC file + * @return Whether the download was successful or not + */ +bool +px_pac_reload(pxPAC *self) +{ + int sock; + char *line = NULL; + const char *headers[3] = { "Accept: " PAC_MIME_TYPE, "Connection: close", NULL }; + bool correct_mime_type; + unsigned long int content_length = 0; + + // Get the pxPAC + sock = px_url_open(self->url, headers); + if (sock < 0) return false; + + // Verify status line + line = px_readline(sock); + if (!line) goto error; + if (strncmp(line, "HTTP", strlen("HTTP"))) goto error; // Check valid HTTP response + if (!strchr(line, ' ') || atoi(strchr(line, ' ') + 1) != 200) goto error; // Check status code + + // Check for correct mime type and content length + while (strcmp(line, "\r")) { + // Check for content type + if (strstr(line, "Content-Type: ") == line && strstr(line, PAC_MIME_TYPE)) + correct_mime_type = true; + + // Check for content length + else if (strstr(line, "Content-Length: ") == line) + content_length = atoi(line + strlen("Content-Length: ")); + + // Get new line + px_free(line); + line = px_readline(sock); + if (!line) goto error; + } + + // Get content + if (!content_length || !correct_mime_type) goto error; + px_free(line); + px_free(self->cache); + self->cache = px_malloc0(content_length+1); + if (recv(sock, self->cache, content_length, 0) != content_length) goto error; + + // Clean up + close(sock); + return true; + + error: + px_free(self->cache); self->cache = NULL; + if (sock >= 0) close(sock); + px_free(line); + return false; +} diff --git a/src/lib/pac.h b/src/lib/pac.h new file mode 100644 index 0000000..e8a76c5 --- /dev/null +++ b/src/lib/pac.h @@ -0,0 +1,68 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ + + +#ifndef PAC_H_ +#define PAC_H_ + +#include "url.h" + +/** + * pxPAC object. All fields are private. + */ +typedef struct _pxPAC pxPAC; + +/** + * Frees memory used by the ProxyAutoConfig. + */ +void px_pac_free(pxPAC *self); + +/** + * Get the URL which the pxPAC uses. + * @return The URL that the pxPAC came from + */ +const pxURL *px_pac_get_url(pxPAC *self); + +/** + * Create a new ProxyAutoConfig. + * @url The URL where the PAC file is found + * @return A new ProxyAutoConfig or NULL on error + */ +pxPAC *px_pac_new(pxURL *url); + +/** + * Create a new ProxyAutoConfig (from a string for convenience). + * @url The url (string) where the PAC file is found + * @return A new ProxyAutoConfig or NULL on error + */ +pxPAC *px_pac_new_from_string(char *url); + +/** + * Returns the Javascript code which the pxPAC uses. + * @return The Javascript code used by the pxPAC + */ +const char *px_pac_to_string(pxPAC *self); + +/** + * Download the latest version of the pxPAC file + * @return Whether the download was successful or not + */ +bool px_pac_reload(pxPAC *self); + +#endif /*PAC_H_*/ diff --git a/src/lib/proxy.h b/src/lib/proxy.h new file mode 100644 index 0000000..4b30ca8 --- /dev/null +++ b/src/lib/proxy.h @@ -0,0 +1,42 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ + +#ifndef PROXY_H_ +#define PROXY_H_ + +enum _pxConfigBackend { + PX_CONFIG_BACKEND_AUTO = 0, + PX_CONFIG_BACKEND_NONE = 0, + PX_CONFIG_BACKEND_WIN32 = (1 << 0), + PX_CONFIG_BACKEND_KCONFIG = (1 << 1), + PX_CONFIG_BACKEND_GCONF = (1 << 2), + PX_CONFIG_BACKEND_USER = (1 << 3), + PX_CONFIG_BACKEND_SYSTEM = (1 << 4), + PX_CONFIG_BACKEND_ENVVAR = (1 << 5), + PX_CONFIG_BACKEND__LAST = PX_CONFIG_BACKEND_ENVVAR +}; + +typedef struct _pxProxyFactory pxProxyFactory; +typedef enum _pxConfigBackend pxConfigBackend; + +pxProxyFactory *px_proxy_factory_new (pxConfigBackend config); +char *px_proxy_factory_get_proxy(pxProxyFactory *self, char *url); +void px_proxy_factory_free (pxProxyFactory *self); + +#endif /*PROXY_H_*/ diff --git a/src/lib/proxy_factory.c b/src/lib/proxy_factory.c new file mode 100644 index 0000000..6de28bb --- /dev/null +++ b/src/lib/proxy_factory.c @@ -0,0 +1,224 @@ +/******************************************************************************* + * 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 <stdlib.h> +#include <assert.h> +#include <string.h> +#include <sys/types.h> +#include <dirent.h> +#include <stdio.h> +#include <dlfcn.h> +#include <math.h> + +#include "misc.h" +#include "proxy_factory.h" + +#define PLUGIN_DIR "/usr/lib/proxy/" VERSION "/plugins" + +struct _pxProxyFactory { + pxConfigBackend mask; + void **plugins; + PXProxyFactoryPtrCallback *configs; + PXProxyFactoryVoidCallback *on_get_proxy; + PXPACRunnerCallback pac_runner; +}; + +pxProxyFactory * +px_proxy_factory_new (pxConfigBackend config) +{ + pxProxyFactory *self = px_malloc0(sizeof(pxProxyFactory)); + self->configs = px_malloc0(sizeof(PXProxyFactoryPtrCallback) * (((int) log2(PX_CONFIG_BACKEND__LAST)) + 1)); + self->mask = config; + unsigned int i; + + // Open the plugin dir + DIR *plugindir = opendir(PLUGIN_DIR); + if (!plugindir) + { + px_proxy_factory_free(self); + return NULL; + } + + // Count the number of plugins + for (i=0 ; readdir(plugindir) ; i++); + self->plugins = (void **) px_malloc0(sizeof(void *) * (i + 1)); + rewinddir(plugindir); + + // For each plugin... + struct dirent *ent; + for (i=0 ; (ent = readdir(plugindir)) ; i++) + { + // Load the plugin + char *tmp = px_malloc0(strlen(PLUGIN_DIR) + strlen(ent->d_name) + 2); + sprintf(tmp, PLUGIN_DIR "/%s", ent->d_name); + self->plugins[i] = dlopen(tmp, RTLD_LOCAL); + px_free(tmp); + if (!(self->plugins[i])) + { + i--; + continue; + } + + // Call the instantiation hook + PXProxyFactoryBoolCallback instantiate; + instantiate = dlsym(self->plugins[i], "on_proxy_factory_instantiate"); + if (instantiate && !instantiate(self)) + { + dlclose(self->plugins[i]); + self->plugins[i--] = NULL; + continue; + } + } + closedir(plugindir); + + // Make sure we have at least one config + if (px_proxy_factory_config_get_active(self) == PX_CONFIG_BACKEND_NONE) + { + px_proxy_factory_free(self); + return NULL; + } + + return self; +} + +bool +px_proxy_factory_config_set (pxProxyFactory *self, pxConfigBackend config, PXProxyFactoryPtrCallback callback) +{ + if ((config ^ self->mask) != config || self->mask == PX_CONFIG_BACKEND_AUTO) return false; + if (self->configs[((int) log2(config))] && callback && self->configs[((int) log2(config))] != callback) return false; + self->configs[((int) log2(config))] = callback; + return true; +} + +pxConfigBackend +px_proxy_factory_config_get_active (pxProxyFactory *self) +{ + // Find the first provided config + for (unsigned int i=0 ; i <= ((int) log2(PX_CONFIG_BACKEND__LAST)) ; i++) + if (self->configs[i]) + return (1 << i); + + // No valid config found! + return PX_CONFIG_BACKEND_NONE; +} + +char * +px_proxy_factory_get_proxy (pxProxyFactory *self, char *url) +{ + return NULL; +} + +void +px_proxy_factory_on_get_proxy_add (pxProxyFactory *self, PXProxyFactoryVoidCallback callback) +{ + unsigned int length = 0; + PXProxyFactoryVoidCallback *tmp = NULL; + + // Backup our current callbacks (NULL if none) + tmp = self->on_get_proxy; + + // If we have any callbacks, count them + // If user is trying to add an already existing callback, just ignore it + if (self->on_get_proxy) + for (length=0 ; self->on_get_proxy[length] ; length++) + if (callback == self->on_get_proxy[length]) + return; + + // Allocate enough space for the old + new callbacks + self->on_get_proxy = px_malloc0(sizeof(PXProxyFactoryVoidCallback) * (length + 2)); + + // Copy old callbacks into new memory (if any) + if (tmp) + memcpy(self->on_get_proxy, tmp, length); + + // Add the new callback + self->on_get_proxy[length] = callback; + + // Free old memory (if any) + px_free(tmp); +} + +void +px_proxy_factory_on_get_proxy_del (pxProxyFactory *self, PXProxyFactoryVoidCallback callback) +{ + unsigned int length = 0, count = 0; + PXProxyFactoryVoidCallback *tmp = NULL; + + // Sanity checks, get length and count + if (!self->on_get_proxy) return; + for (length=0,count=0 ; self->on_get_proxy[length] ; length++) + if (self->on_get_proxy[length] == callback) + count++; + if (length < 1 || count < 1) return; + + // Backup current callbacks + tmp = self->on_get_proxy; + + // Allocate new array + self->on_get_proxy = px_malloc0(sizeof(PXProxyFactoryVoidCallback) * (length - count + 1)); + + // Copy in new values + int i,j; + for (i=0,j=0 ; tmp[i] ; i++) + if (tmp[i] != callback) + self->on_get_proxy[j++] = tmp[i]; + + // Free old memory + px_free(tmp); +} + +bool +px_proxy_factory_pac_runner_set (pxProxyFactory *self, PXPACRunnerCallback callback) +{ + if (self->pac_runner && callback && self->pac_runner != callback) return false; + self->pac_runner = callback; + return true; +} + +void +px_proxy_factory_free (pxProxyFactory *self) +{ + unsigned int i; + + if (!self) return; + + // Free the plugins + if (self->plugins) + { + for (i=0 ; self->plugins[i] ; i++) + { + // Call the destantiation hook + PXProxyFactoryVoidCallback destantiate; + destantiate = dlsym(self->plugins[i], "on_proxy_factory_destantiate"); + if (destantiate) + destantiate(self); + + // Unload the plugin + dlclose(self->plugins[i]); + self->plugins[i] = NULL; + } + px_free(self->plugins); + } + + // Free everything else + if (self->configs) px_free(self->configs); + if (self->on_get_proxy) px_free(self->on_get_proxy); + px_free(self); +} + diff --git a/src/lib/proxy_factory.h b/src/lib/proxy_factory.h new file mode 100644 index 0000000..c7420ea --- /dev/null +++ b/src/lib/proxy_factory.h @@ -0,0 +1,54 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ + +#ifndef PROXY_FACTORY_H_ +#define PROXY_FACTORY_H_ + +#include <stdbool.h> + +#include "proxy.h" + +// URLs look like this: +// http://host:port +// socks://host:port +// pac+http://pac_host:port/path/to/pac +// wpad:// +// direct:// +// TODO: ignore syntax TBD +struct _PXConfig { + char *url; + char *ignore; +}; +typedef struct _PXConfig PXConfig; + +typedef void (*PXProxyFactoryVoidCallback) (pxProxyFactory *self); +typedef bool (*PXProxyFactoryBoolCallback) (pxProxyFactory *self); +typedef void *(*PXProxyFactoryPtrCallback) (pxProxyFactory *self); + +typedef char *(*PXPACRunnerCallback) (pxProxyFactory *self, const char *pac, const char *url, const char *hostname); + +bool px_proxy_factory_config_set (pxProxyFactory *self, pxConfigBackend config, PXProxyFactoryPtrCallback callback); +pxConfigBackend px_proxy_factory_config_get_active(pxProxyFactory *self); +void px_proxy_factory_wpad_restart (pxProxyFactory *self); +void px_proxy_factory_on_get_proxy_add (pxProxyFactory *self, PXProxyFactoryVoidCallback callback); +void px_proxy_factory_on_get_proxy_del (pxProxyFactory *self, PXProxyFactoryVoidCallback callback); +bool px_proxy_factory_pac_runner_set (pxProxyFactory *self, PXPACRunnerCallback callback); + +#endif /*PROXY_FACTORY_H_*/ + diff --git a/src/lib/slp.c b/src/lib/slp.c new file mode 100644 index 0000000..1e65013 --- /dev/null +++ b/src/lib/slp.c @@ -0,0 +1,63 @@ +/******************************************************************************* + * 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 <stdlib.h> + +#include "pac.h" +#include "slp.h" + +struct _pxSLP { }; + +/** + * Creates a new SLP PAC detector. + * @return New SLP PAD detector + */ +pxSLP * +px_slp_new() +{ + return NULL; +} + +/** + * Detect the next PAC in the chain. + * @return Detected PAC or NULL if none is found + */ +pxPAC * +px_slp_next(pxSLP *self) +{ + return NULL; +} + +/** + * Restarts the detection chain at the beginning. + */ +void +px_slp_rewind(pxSLP *self) +{ + return; +} + +/** + * Frees a SLP object. + */ +void +px_slp_free(pxSLP *self) +{ + return; +} diff --git a/src/lib/slp.h b/src/lib/slp.h new file mode 100644 index 0000000..9f3b5bf --- /dev/null +++ b/src/lib/slp.h @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ + +#ifndef SLP_H_ +#define SLP_H_ + +#include "pac.h" + +/** + * A SLP PAC detector. All fields are private. + */ +typedef struct _pxSLP pxSLP; + +/** + * Creates a new SLP PAC detector. + * @return New SLP PAD detector + */ +pxSLP *px_slp_new(); + +/** + * Detect the next PAC in the chain. + * @return Detected PAC or NULL if none is found + */ +pxPAC *px_slp_next(pxSLP *self); + +/** + * Restarts the detection chain at the beginning. + */ +void px_slp_rewind(pxSLP *self); + +/** + * Frees a SLP object. + */ +void px_slp_free(pxSLP *self); + +#endif /*SLP_H_*/ diff --git a/src/lib/url.c b/src/lib/url.c new file mode 100644 index 0000000..7601bba --- /dev/null +++ b/src/lib/url.c @@ -0,0 +1,257 @@ +/******************************************************************************* + * 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 <netdb.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "misc.h" +#include "url.h" + +/** + * pxURL object. All fields are private. + */ +struct _pxURL { + char *url; + char *scheme; + char *host; + int port; + char *path; + pxIP **ips; +}; + +/** + * @return Frees the pxURL + */ +void +px_url_free(pxURL *self) +{ + if (!self) return; + px_free(self->url); + px_free(self->scheme); + px_free(self->host); + px_free(self->path); + if (self->ips) + { + for (int i=0 ; self->ips[i] ; i++) + px_ip_free(self->ips[i]); + px_free(self->ips); + } + px_free(self); +} + +/** + * Tells whether or not a pxURL string has valid syntax + * @return true if the pxURL is valid, otherwise false + */ +bool +px_url_is_valid(const char *url) +{ + pxURL *tmp = px_url_new(url); + if (!tmp) return false; + px_url_free(tmp); + return true; +} + +/** + * Sends a get request for the pxURL. + * @headers A list of headers to be included in the request. + * @return Socket to read the response on. + */ +int +px_url_open(pxURL *self, const char **headers) +{ + char *request_template = "GET %s HTTP/1.1\r\nHost: %s\r\n%s\r\n\r\n"; + char *request = NULL; + char *joined_headers = NULL; + int sock = -1; + + // DNS lookup of host + if (!px_url_get_ips(self)) goto error; + + // Iterate through each pxIP trying to make a connection + px_url_get_ips(self); // Do lookup + for (int i = 0 ; self->ips && self->ips[i] && sock < 0 ; i++) + sock = px_ip_connect(self->ips[i], TCP, px_url_get_port(self)); + if (sock < 0) goto error; + + // Merge optional headers + if (headers) + { + joined_headers = px_strjoin(headers, "\r\n"); + if (!joined_headers) goto error; + } + else + joined_headers = px_strdup(""); + + // Create request header + request = px_malloc0(strlen(px_url_get_path(self)) + + strlen(px_url_get_host(self)) + + strlen(joined_headers) + + strlen(request_template)); + sprintf(request, request_template, + px_url_get_path(self), + px_url_get_host(self), + joined_headers); + px_free(joined_headers); + + // Send HTTP request + if (send(sock, request, strlen(request), 0) != strlen(request)) goto error; + px_free(request); request = NULL; + + // Return the socket, which is ready for reading the response + return sock; + + error: + if (sock >= 0) close(sock); + px_free(request); + return -1; +} + +/** + * @return The default port for this type of pxURL + */ +static int +px_url_get_default_port(pxURL *self) +{ + struct servent *serv; + if ((serv = getservbyname(self->scheme, NULL))) return ntohl(serv->s_port); + return 0; +} + +/** + * @return Host portion of the pxURL + */ +const char * +px_url_get_host(pxURL *self) +{ + if (!self) return NULL; + return self->host; +} + +/** + * @return pxIP address of the host in the pxURL + */ +const pxIP ** +px_url_get_ips(pxURL *self) +{ + if (!self) return NULL; + + // Check the cache + if (self->ips) return (const pxIP **) self->ips; + + self->ips = px_ip_new_from_hostent_all(gethostbyname(self->host)); + return (const pxIP **) self->ips; +} + +/** + * @return Path portion of the pxURL + */ +const char * +px_url_get_path(pxURL *self) +{ + if (!self) return NULL; + return self->path; +} + +/** + * @return Port portion of the pxURL + */ +int +px_url_get_port(pxURL *self) +{ + if (!self) return 0; + return self->port; +} + +/** + * @return Scheme portion of the pxURL + */ +const char * +px_url_get_scheme(pxURL *self) +{ + if (!self) return NULL; + return self->scheme; +} + +/** + * @url String used to create the new pxURL object + * @return New pxURL object + */ +pxURL * +px_url_new(const char *url) +{ + // Allocate pxURL + pxURL *self = px_malloc0(sizeof(pxURL)); + + // Get scheme + if (!strstr(url, "://")) goto error; + self->scheme = px_strndup(url, strstr(url, "://") - url); + + // Get host + self->host = px_strdup(strstr(url, "://") + strlen("://")); + + // Get path + self->path = px_strdup(strchr(self->host, '/')); + if (self->path) + self->host[strlen(self->host) - strlen(self->path)] = 0; + else + self->path = px_strdup(""); + + // Get the port + bool port_specified = false; + if (strchr(self->host, ':')) { + if (!atoi(strchr(self->host, ':')+1)) goto error; + self->port = atoi(strchr(self->host, ':')+1); + *(strchr(self->host, ':')) = 0; + port_specified = true; + } + else + self->port = px_url_get_default_port(self); + + // Make sure we have a real host + if (!strcmp(self->host, "")) goto error; + + // Verify by re-assembly + self->url = px_malloc0(strlen(url) + 1); + if (!port_specified) + snprintf(self->url, strlen(url) + 1, "%s://%s%s", self->scheme, self->host, self->path); + else + snprintf(self->url, strlen(url) + 1, "%s://%s:%d%s", self->scheme, self->host, self->port, self->path); + if (strcmp(self->url, url)) goto error; + + return self; + + error: + px_url_free(self); + return NULL; +} + +/** + * @return String representation of the pxURL + */ +const char * +px_url_to_string(pxURL *self) +{ + if (!self) return NULL; + return self->url; +} diff --git a/src/lib/url.h b/src/lib/url.h new file mode 100644 index 0000000..0bfc47a --- /dev/null +++ b/src/lib/url.h @@ -0,0 +1,85 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ + +#ifndef URL_H_ +#define URL_H_ + +#include "ip.h" // For class pxURL +#include "stdbool.h" // For type bool + +/** + * WPAD object. All fields are private. + */ +typedef struct _pxURL pxURL; + +/** + * @return Frees the pxURL + */ +void px_url_free(pxURL *self); + +/** + * Tells whether or not a pxURL string has valid syntax + * @return true if the pxURL is valid, otherwise false + */ +bool px_url_is_valid(const char *url); + +/** + * Sends a get request for the pxURL. + * @headers A list of headers to be included in the request. + * @return Socket to read the response on. + */ +int px_url_open(pxURL *self, const char **headers); + +/** + * @return Host portion of the pxURL + */ +const char *px_url_get_host(pxURL *self); + +/** + * @return pxIP address of the host in the pxURL + */ +const pxIP **px_url_get_ips(pxURL *self); + +/** + * @return Path portion of the pxURL + */ +const char *px_url_get_path(pxURL *self); + +/** + * @return Port portion of the pxURL + */ +int px_url_get_port(pxURL *self); + +/** + * @return Scheme portion of the pxURL + */ +const char *px_url_get_scheme(pxURL *self); + +/** + * @url String used to create the new pxURL object + * @return New pxURL object + */ +pxURL *px_url_new(const char *url); + +/** + * @return String representation of the pxURL + */ +const char *px_url_to_string(pxURL *self); + +#endif /*URL_H_*/ diff --git a/src/lib/wpad.c b/src/lib/wpad.c new file mode 100644 index 0000000..65fffad --- /dev/null +++ b/src/lib/wpad.c @@ -0,0 +1,126 @@ +/******************************************************************************* + * 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 "misc.h" +#include "dhcp.h" +#include "dns.h" +#include "slp.h" +#include "wpad.h" + +struct _pxWPAD { + pxDHCP *dhcp; + pxDNS *dns; + pxSLP *slp; + bool found; +}; + +/** + * Create a new WPAD object (for detecting PAC locations) + * @return A New WPAD object + */ +pxWPAD * +px_wpad_new() +{ + return px_wpad_new_full(NULL, NULL, NULL); +} + +/** + * Creates a new WPAD object with more options. + * For all options, ownership is stolen by the new WPAD object. + * In other words, don't pass a detector to this function and then use it + * later (or free it). + * @dhcp The DHCP detector to use (or NULL for the default detector) + * @dns The DNS detector to use (or NULL for the default detector) + * @slp The SLP detector to use (or NULL for the default detector) + * @return New DNS PAD detector + */ +pxWPAD * +px_wpad_new_full(pxDHCP *dhcp, pxDNS *dns, pxSLP *slp) +{ + if (!dhcp) dhcp = px_dhcp_new(); + if (!dns) dns = px_dns_new(); + if (!slp) slp = px_slp_new(); + + pxWPAD *self = px_malloc0(sizeof(pxWPAD)); + self->dhcp = dhcp; + self->dns = dns; + self->slp = slp; + + return self; +} + +/** + * Detect the next PAC in the chain. + * @return Detected PAC or NULL if none is found + */ +pxPAC * +px_wpad_next(pxWPAD *self) +{ + if (!self) return NULL; + + // Check all the detectors for a PAC + pxPAC *pac = NULL; + if (!(pac = px_dhcp_next(self->dhcp))) + if (!(pac = px_slp_next(self->slp))) + pac = px_dns_next(self->dns); + + if (pac) self->found = true; + return pac; +} + +/** + * Restarts the detection chain at the beginning. + */ +void +px_wpad_rewind(pxWPAD *self) +{ + if (!self) return; + + px_dhcp_rewind(self->dhcp); + px_dns_rewind(self->dns); + px_slp_rewind(self->slp); + self->found = false; +} + +/** + * Frees a WPAD object. + */ +void +px_wpad_free(pxWPAD *self) +{ + if (!self) return; + + px_dhcp_free(self->dhcp); + px_dns_free(self->dns); + px_slp_free(self->slp); + px_free(self); +} + +/** + * Returns whether or not a PAC was found during this detection cycle. + * Always returns false if called directly after wpad_wpad_rewind(). + * @return Whether or not a PAC was found + */ +bool +px_wpad_pac_found(pxWPAD *self) +{ + if (!self) return false; + return self->found; +} + diff --git a/src/lib/wpad.h b/src/lib/wpad.h new file mode 100644 index 0000000..26e6436 --- /dev/null +++ b/src/lib/wpad.h @@ -0,0 +1,71 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ + +#ifndef WPAD_H_ +#define WPAD_H_ + +#include "pac.h" + +/** + * WPAD object. All fields are private. + */ +typedef struct _pxWPAD pxWPAD; + +/** + * Create a new WPAD object (for detecting PAC locations) + * @return A New WPAD object + */ +pxWPAD *px_wpad_new(); + +/** + * Creates a new WPAD object with more options. + * For all options, ownership is stolen by the new WPAD object. + * In other words, don't pass a detector to this function and then use it + * later (or free it). + * @dhcp The DHCP detector to use (or NULL for the default detector) + * @dns The DNS detector to use (or NULL for the default detector) + * @slp The SLP detector to use (or NULL for the default detector) + * @return New DNS PAD detector + */ +pxWPAD *px_wpad_new_full(pxDHCP *dhcp, pxDNS *dns, pxSLP *slp); + +/** + * Detect the next PAC in the chain. + * @return Detected PAC or NULL if none is found + */ +pxPAC *px_wpad_next(pxWPAD *self); + +/** + * Restarts the detection chain at the beginning. + */ +void px_wpad_rewind(pxWPAD *self); + +/** + * Frees a WPAD object. + */ +void px_wpad_free(pxWPAD *self); + +/** + * Returns whether or not a PAC was found during this detection cycle. + * Always returns false if called directly after wpad_wpad_rewind(). + * @return Whether or not a PAC was found + */ +bool px_wpad_pac_found(pxWPAD *self); + +#endif /*WPAD_H_*/ |
