diff options
Diffstat (limited to 'src/upstream.c')
-rw-r--r-- | src/upstream.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/src/upstream.c b/src/upstream.c new file mode 100644 index 0000000..20fb439 --- /dev/null +++ b/src/upstream.c @@ -0,0 +1,214 @@ +/* tinyproxy - A fast light-weight HTTP proxy + * Copyright (C) 1998 Steven Young <sdyoung@miranda.org> + * Copyright (C) 1999-2005 Robert James Kaes <rjkaes@users.sourceforge.net> + * Copyright (C) 2000 Chris Lightfoot <chris@ex-parrot.com> + * Copyright (C) 2002 Petr Lampa <lampa@fit.vutbr.cz> + * Copyright (C) 2009 Michael Adam <obnox@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Routines for handling the list of upstream proxies. + */ + +#include "upstream.h" +#include "heap.h" +#include "main.h" +#include "log.h" + +#ifdef UPSTREAM_SUPPORT +/** + * Construct an upstream struct from input data. + */ +static struct upstream *upstream_build (const char *host, int port, const char *domain) +{ + char *ptr; + struct upstream *up; + + up = (struct upstream *) safemalloc (sizeof (struct upstream)); + if (!up) { + log_message (LOG_ERR, + "Unable to allocate memory in upstream_build()"); + return NULL; + } + + up->host = up->domain = NULL; + up->ip = up->mask = 0; + + if (domain == NULL) { + if (!host || host[0] == '\0' || port < 1) { + log_message (LOG_WARNING, + "Nonsense upstream rule: invalid host or port"); + goto fail; + } + + up->host = safestrdup (host); + up->port = port; + + log_message (LOG_INFO, "Added upstream %s:%d for [default]", + host, port); + } else if (host == NULL) { + if (!domain || domain[0] == '\0') { + log_message (LOG_WARNING, + "Nonsense no-upstream rule: empty domain"); + goto fail; + } + + ptr = strchr (domain, '/'); + if (ptr) { + struct in_addr addrstruct; + + *ptr = '\0'; + if (inet_aton (domain, &addrstruct) != 0) { + up->ip = ntohl (addrstruct.s_addr); + *ptr++ = '/'; + + if (strchr (ptr, '.')) { + if (inet_aton (ptr, &addrstruct) != 0) + up->mask = + ntohl (addrstruct.s_addr); + } else { + up->mask = + ~((1 << (32 - atoi (ptr))) - 1); + } + } + } else { + up->domain = safestrdup (domain); + } + + log_message (LOG_INFO, "Added no-upstream for %s", domain); + } else { + if (!host || host[0] == '\0' || port < 1 || !domain + || domain == '\0') { + log_message (LOG_WARNING, + "Nonsense upstream rule: invalid parameters"); + goto fail; + } + + up->host = safestrdup (host); + up->port = port; + up->domain = safestrdup (domain); + + log_message (LOG_INFO, "Added upstream %s:%d for %s", + host, port, domain); + } + + return up; + +fail: + safefree (up->host); + safefree (up->domain); + safefree (up); + + return NULL; +} + +/* + * Add an entry to the upstream list + */ +void upstream_add (const char *host, int port, const char *domain) +{ + struct upstream *up; + + up = upstream_build (host, port, domain); + if (up == NULL) { + return; + } + + if (!up->domain && !up->ip) { /* always add default to end */ + struct upstream *tmp = config.upstream_list; + + while (tmp) { + if (!tmp->domain && !tmp->ip) { + log_message (LOG_WARNING, + "Duplicate default upstream"); + goto upstream_cleanup; + } + + if (!tmp->next) { + up->next = NULL; + tmp->next = up; + return; + } + + tmp = tmp->next; + } + } + + up->next = config.upstream_list; + config.upstream_list = up; + + return; + +upstream_cleanup: + safefree (up->host); + safefree (up->domain); + safefree (up); + + return; +} + +/* + * Check if a host is in the upstream list + */ +struct upstream *upstream_get (char *host) +{ + struct upstream *up = config.upstream_list; + + in_addr_t my_ip = INADDR_NONE; + + while (up) { + if (up->domain) { + if (strcasecmp (host, up->domain) == 0) + break; /* exact match */ + + if (up->domain[0] == '.') { + char *dot = strchr (host, '.'); + + if (!dot && !up->domain[1]) + break; /* local host matches "." */ + + while (dot && strcasecmp (dot, up->domain)) + dot = strchr (dot + 1, '.'); + + if (dot) + break; /* subdomain match */ + } + } else if (up->ip) { + if (my_ip == INADDR_NONE) + my_ip = ntohl (inet_addr (host)); + + if ((my_ip & up->mask) == up->ip) + break; + } else { + break; /* No domain or IP, default upstream */ + } + + up = up->next; + } + + if (up && (!up->host || !up->port)) + up = NULL; + + if (up) + log_message (LOG_INFO, "Found proxy %s:%d for %s", + up->host, up->port, host); + else + log_message (LOG_INFO, "No proxy for %s", host); + + return up; +} +#endif |