From fd987e97f035e3567e9db18ad233e604c9d78ed1 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Sun, 6 Dec 2009 12:40:31 +0100 Subject: [PATCH] move handling of upstream list to new module upstream.{c,h} Michael --- src/Makefile.am | 3 +- src/conf.c | 1 + src/main.h | 12 --- src/reqs.c | 185 +---------------------------------------- src/reqs.h | 1 - src/upstream.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++ src/upstream.h | 47 +++++++++++ 7 files changed, 265 insertions(+), 198 deletions(-) create mode 100644 src/upstream.c create mode 100644 src/upstream.h diff --git a/src/Makefile.am b/src/Makefile.am index b306c8b..27f85dd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,7 +41,8 @@ tinyproxy_SOURCES = \ text.c text.h \ main.c main.h \ utils.c utils.h \ - vector.c vector.h + vector.c vector.h \ + upstream.c upstream.h EXTRA_tinyproxy_SOURCES = filter.c filter.h \ reverse-proxy.c reverse-proxy.h \ diff --git a/src/conf.c b/src/conf.c index 7201b8c..973dc84 100644 --- a/src/conf.c +++ b/src/conf.c @@ -35,6 +35,7 @@ #include "log.h" #include "reqs.h" #include "reverse-proxy.h" +#include "upstream.h" /* * The configuration directives are defined in the structure below. Each diff --git a/src/main.h b/src/main.h index 16c3352..bb7ea46 100644 --- a/src/main.h +++ b/src/main.h @@ -29,18 +29,6 @@ #define MAXBUFFSIZE ((size_t)(1024 * 96)) /* Max size of buffer */ #define MAX_IDLE_TIME (60 * 10) /* 10 minutes of no activity */ -/* - * Even if upstream support is not compiled into tinyproxy, this - * structure still needs to be defined. - */ -struct upstream { - struct upstream *next; - char *domain; /* optional */ - char *host; - int port; - in_addr_t ip, mask; -}; - /* * Hold all the configuration time information. */ diff --git a/src/reqs.c b/src/reqs.c index a956ce8..2ff7ac6 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -45,6 +45,7 @@ #include "vector.h" #include "reverse-proxy.h" #include "transparent-proxy.h" +#include "upstream.h" /* * Maximum length of a HTTP line @@ -300,190 +301,6 @@ static int extract_ssl_url (const char *url, struct request_s *request) return 0; } -#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 - */ -static 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 - /* * Create a connection for HTTP connections. */ diff --git a/src/reqs.h b/src/reqs.h index bffd6ca..cf40e46 100644 --- a/src/reqs.h +++ b/src/reqs.h @@ -45,6 +45,5 @@ struct request_s { extern void handle_connection (int fd); extern void add_connect_port_allowed (int port); -extern void upstream_add (const char *host, int port, const char *domain); #endif 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 + * Copyright (C) 1999-2005 Robert James Kaes + * Copyright (C) 2000 Chris Lightfoot + * Copyright (C) 2002 Petr Lampa + * Copyright (C) 2009 Michael Adam + * + * 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 diff --git a/src/upstream.h b/src/upstream.h new file mode 100644 index 0000000..327a114 --- /dev/null +++ b/src/upstream.h @@ -0,0 +1,47 @@ +/* tinyproxy - A fast light-weight HTTP proxy + * Copyright (C) 1998 Steven Young + * Copyright (C) 1999 Robert James Kaes + * Copyright (C) 2009 Michael Adam + * + * 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. + */ + +#ifndef _TINYPROXY_UPSTREAM_H_ +#define _TINYPROXY_UPSTREAM_H_ + +#include "common.h" + +/* + * Even if upstream support is not compiled into tinyproxy, this + * structure still needs to be defined. + */ +struct upstream { + struct upstream *next; + char *domain; /* optional */ + char *host; + int port; + in_addr_t ip, mask; +}; + +#ifdef UPSTREAM_SUPPORT +extern void upstream_add (const char *host, int port, const char *domain); +struct upstream *upstream_get (char *host); +#endif /* UPSTREAM_SUPPORT */ + +#endif /* _TINYPROXY_UPSTREAM_H_ */