summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authornpmccallum <npmccallum@c587cffe-e639-0410-9787-d7902ae8ed56>2007-10-11 03:59:21 +0000
committernpmccallum <npmccallum@c587cffe-e639-0410-9787-d7902ae8ed56>2007-10-11 03:59:21 +0000
commitb15404b30e1ac270a40476614a7e656741c258a0 (patch)
tree102163eb50b834fbb558ec8b4759120ff0863e45 /src/lib
parentfe2c4c79d115291849cbabe09130c7ee0274a540 (diff)
downloadlibproxy-git-b15404b30e1ac270a40476614a7e656741c258a0.tar.gz
major rework of tree structure; import from libwpad
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Makefile.am8
-rw-r--r--src/lib/dhcp.c63
-rw-r--r--src/lib/dhcp.h52
-rw-r--r--src/lib/dns.c219
-rw-r--r--src/lib/dns.h59
-rw-r--r--src/lib/ip.c234
-rw-r--r--src/lib/ip.h95
-rw-r--r--src/lib/misc.c199
-rw-r--r--src/lib/misc.h89
-rw-r--r--src/lib/pac.c166
-rw-r--r--src/lib/pac.h68
-rw-r--r--src/lib/proxy.h42
-rw-r--r--src/lib/proxy_factory.c224
-rw-r--r--src/lib/proxy_factory.h54
-rw-r--r--src/lib/slp.c63
-rw-r--r--src/lib/slp.h52
-rw-r--r--src/lib/url.c257
-rw-r--r--src/lib/url.h85
-rw-r--r--src/lib/wpad.c126
-rw-r--r--src/lib/wpad.h71
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_*/