Add proxy list
This commit is contained in:
parent
93e9c156e8
commit
d72ad621e5
@ -72,6 +72,11 @@ The possible keywords and their descriptions are as follows:
|
|||||||
The maximum number of seconds of inactivity a connection is
|
The maximum number of seconds of inactivity a connection is
|
||||||
allowed to have before it is closed by Tinyproxy.
|
allowed to have before it is closed by Tinyproxy.
|
||||||
|
|
||||||
|
*DeadTime*::
|
||||||
|
|
||||||
|
The maximum number of seconds of marking a proxy dead i.e. proxy
|
||||||
|
won't be used for a new connections by Tinyproxy during the deadtime.
|
||||||
|
|
||||||
*ErrorFile*::
|
*ErrorFile*::
|
||||||
|
|
||||||
This parameter controls which HTML file Tinyproxy returns when a
|
This parameter controls which HTML file Tinyproxy returns when a
|
||||||
@ -153,12 +158,16 @@ The possible keywords and their descriptions are as follows:
|
|||||||
rules exist:
|
rules exist:
|
||||||
|
|
||||||
* 'upstream type host:port' turns proxy upstream support on generally.
|
* 'upstream type host:port' turns proxy upstream support on generally.
|
||||||
|
host:port can be a list seperated by | e.g. host1:port1|host2:port2.
|
||||||
|
|
||||||
* 'upstream type user:pass@host:port' does the same, but uses the
|
* 'upstream type user:pass@host:port' does the same, but uses the
|
||||||
supplied credentials for authentication.
|
supplied credentials for authentication. host:port can be a list
|
||||||
|
seperated by | e.g. host1:port1|host2:port2. Same user:pass will be
|
||||||
|
used for the list.
|
||||||
|
|
||||||
* 'upstream type host:port "site_spec"' turns on the upstream proxy
|
* 'upstream type host:port "site_spec"' turns on the upstream proxy
|
||||||
for the sites matching `site_spec`.
|
for the sites matching `site_spec`. host:port can be a list
|
||||||
|
seperated by | e.g. host1:port1|host2:port2.
|
||||||
|
|
||||||
`type` can be one of `http`, `socks4`, `socks5`, `none`.
|
`type` can be one of `http`, `socks4`, `socks5`, `none`.
|
||||||
|
|
||||||
@ -173,6 +182,11 @@ The possible keywords and their descriptions are as follows:
|
|||||||
* '.' matches any host with no domain (in 'empty' domain)
|
* '.' matches any host with no domain (in 'empty' domain)
|
||||||
* 'IP/bits' matches network/mask
|
* 'IP/bits' matches network/mask
|
||||||
* 'IP/mask' matches network/mask
|
* 'IP/mask' matches network/mask
|
||||||
|
* 'regex(<pat>)' matches against basic case senstive regular expression
|
||||||
|
* 'regexe(<pat>)' matches against extended case senstive regular expression
|
||||||
|
* 'regexi(<pat>)' matches against basic case insenstive regular expression
|
||||||
|
* 'regexei(<pat>)' matches against extended case insenstive regular expression
|
||||||
|
* 'regexie(<pat>)' matches against extended case insenstive regular expression
|
||||||
|
|
||||||
*MaxClients*::
|
*MaxClients*::
|
||||||
|
|
||||||
|
10
src/acl.c
10
src/acl.c
@ -111,7 +111,7 @@ fill_netmask_array (char *bitmask_string, int v6,
|
|||||||
/**
|
/**
|
||||||
* If the access list has not been set up, create it.
|
* If the access list has not been set up, create it.
|
||||||
*/
|
*/
|
||||||
static int init_access_list(vector_t *access_list)
|
static int init_access_list (vector_t *access_list)
|
||||||
{
|
{
|
||||||
if (!*access_list) {
|
if (!*access_list) {
|
||||||
*access_list = vector_create ();
|
*access_list = vector_create ();
|
||||||
@ -143,7 +143,7 @@ insert_acl (char *location, acl_access_t access_type, vector_t *access_list)
|
|||||||
|
|
||||||
assert (location != NULL);
|
assert (location != NULL);
|
||||||
|
|
||||||
ret = init_access_list(access_list);
|
ret = init_access_list (access_list);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -170,7 +170,7 @@ insert_acl (char *location, acl_access_t access_type, vector_t *access_list)
|
|||||||
*/
|
*/
|
||||||
p = strchr (location, '/');
|
p = strchr (location, '/');
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
char dst[sizeof(struct in6_addr)];
|
char dst[sizeof (struct in6_addr)];
|
||||||
int v6;
|
int v6;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -185,7 +185,7 @@ insert_acl (char *location, acl_access_t access_type, vector_t *access_list)
|
|||||||
|
|
||||||
/* Check if the IP address before the netmask is
|
/* Check if the IP address before the netmask is
|
||||||
* an IPv6 address */
|
* an IPv6 address */
|
||||||
if (inet_pton(AF_INET6, location, dst) > 0)
|
if (inet_pton (AF_INET6, location, dst) > 0)
|
||||||
v6 = 1;
|
v6 = 1;
|
||||||
else
|
else
|
||||||
v6 = 0;
|
v6 = 0;
|
||||||
@ -197,7 +197,7 @@ insert_acl (char *location, acl_access_t access_type, vector_t *access_list)
|
|||||||
|
|
||||||
for (i = 0; i < IPV6_LEN; i++)
|
for (i = 0; i < IPV6_LEN; i++)
|
||||||
acl.address.ip.network[i] = ip_dst[i] &
|
acl.address.ip.network[i] = ip_dst[i] &
|
||||||
acl.address.ip.mask[i];
|
acl.address.ip.mask[i];
|
||||||
} else {
|
} else {
|
||||||
/* In all likelihood a string */
|
/* In all likelihood a string */
|
||||||
acl.type = ACL_STRING;
|
acl.type = ACL_STRING;
|
||||||
|
53
src/base64.c
53
src/base64.c
@ -19,7 +19,7 @@
|
|||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
|
||||||
static const char base64_tbl[64] =
|
static const char base64_tbl[64] =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
rofl0r's base64 impl (taken from libulz)
|
rofl0r's base64 impl (taken from libulz)
|
||||||
@ -27,31 +27,30 @@ static const char base64_tbl[64] =
|
|||||||
dst needs to be at least BASE64ENC_BYTES(count) + 1 bytes in size.
|
dst needs to be at least BASE64ENC_BYTES(count) + 1 bytes in size.
|
||||||
the string in dst will be zero-terminated.
|
the string in dst will be zero-terminated.
|
||||||
*/
|
*/
|
||||||
void base64enc(char *dst, const void* src, size_t count)
|
void base64enc (char *dst, const void *src, size_t count)
|
||||||
{
|
{
|
||||||
unsigned const char *s = src;
|
unsigned const char *s = src;
|
||||||
char* d = dst;
|
char *d = dst;
|
||||||
while(count) {
|
while (count) {
|
||||||
int i = 0, n = *s << 16;
|
int i = 0, n = *s << 16;
|
||||||
s++;
|
s++;
|
||||||
count--;
|
count--;
|
||||||
if(count) {
|
if (count) {
|
||||||
n |= *s << 8;
|
n |= *s << 8;
|
||||||
s++;
|
s++;
|
||||||
count--;
|
count--;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if(count) {
|
if (count) {
|
||||||
n |= *s;
|
n |= *s;
|
||||||
s++;
|
s++;
|
||||||
count--;
|
count--;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
*d++ = base64_tbl[(n >> 18) & 0x3f];
|
*d++ = base64_tbl[(n >> 18) & 0x3f];
|
||||||
*d++ = base64_tbl[(n >> 12) & 0x3f];
|
*d++ = base64_tbl[(n >> 12) & 0x3f];
|
||||||
*d++ = i ? base64_tbl[(n >> 6) & 0x3f] : '=';
|
*d++ = i ? base64_tbl[(n >> 6) & 0x3f] : '=';
|
||||||
*d++ = i == 2 ? base64_tbl[n & 0x3f] : '=';
|
*d++ = i == 2 ? base64_tbl[n & 0x3f] : '=';
|
||||||
}
|
}
|
||||||
*d = 0;
|
*d = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
/* calculates number of bytes base64-encoded stream of N bytes will take. */
|
/* calculates number of bytes base64-encoded stream of N bytes will take. */
|
||||||
#define BASE64ENC_BYTES(N) (((N+2)/3)*4)
|
#define BASE64ENC_BYTES(N) (((N+2)/3)*4)
|
||||||
void base64enc(char *dst, const void* src, size_t count);
|
void base64enc (char *dst, const void *src, size_t count);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -32,29 +32,31 @@
|
|||||||
* -1 if user/pass missing
|
* -1 if user/pass missing
|
||||||
* 0 if user/pass too long
|
* 0 if user/pass too long
|
||||||
*/
|
*/
|
||||||
ssize_t basicauth_string(const char *user, const char *pass,
|
ssize_t basicauth_string (const char *user, const char *pass,
|
||||||
char *buf, size_t bufsize)
|
char *buf, size_t bufsize)
|
||||||
{
|
{
|
||||||
char tmp[256+2];
|
char tmp[256 + 2];
|
||||||
int l;
|
int l;
|
||||||
if (!user || !pass) return -1;
|
if (!user || !pass)
|
||||||
l = snprintf(tmp, sizeof tmp, "%s:%s", user, pass);
|
return -1;
|
||||||
if (l < 0 || l >= (ssize_t) sizeof tmp) return 0;
|
l = snprintf (tmp, sizeof tmp, "%s:%s", user, pass);
|
||||||
if (bufsize < (BASE64ENC_BYTES((unsigned)l) + 1)) return 0;
|
if (l < 0 || l >= (ssize_t) sizeof tmp)
|
||||||
base64enc(buf, tmp, l);
|
return 0;
|
||||||
return BASE64ENC_BYTES(l);
|
if (bufsize < (BASE64ENC_BYTES ((unsigned) l) + 1))
|
||||||
|
return 0;
|
||||||
|
base64enc (buf, tmp, l);
|
||||||
|
return BASE64ENC_BYTES (l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add entry to the basicauth list
|
* Add entry to the basicauth list
|
||||||
*/
|
*/
|
||||||
void basicauth_add (vector_t authlist,
|
void basicauth_add (vector_t authlist, const char *user, const char *pass)
|
||||||
const char *user, const char *pass)
|
|
||||||
{
|
{
|
||||||
char b[BASE64ENC_BYTES((256+2)-1) + 1];
|
char b[BASE64ENC_BYTES ((256 + 2) - 1) + 1];
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
ret = basicauth_string(user, pass, b, sizeof b);
|
ret = basicauth_string (user, pass, b, sizeof b);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Illegal basicauth rule: missing user or pass");
|
"Illegal basicauth rule: missing user or pass");
|
||||||
@ -65,14 +67,13 @@ void basicauth_add (vector_t authlist,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vector_append(authlist, b, ret + 1) == -ENOMEM) {
|
if (vector_append (authlist, b, ret + 1) == -ENOMEM) {
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"Unable to allocate memory in basicauth_add()");
|
"Unable to allocate memory in basicauth_add()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_message (LOG_INFO,
|
log_message (LOG_INFO, "Added basic auth user : %s", user);
|
||||||
"Added basic auth user : %s", user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -84,15 +85,16 @@ int basicauth_check (vector_t authlist, const char *authstring)
|
|||||||
{
|
{
|
||||||
ssize_t vl, i;
|
ssize_t vl, i;
|
||||||
size_t el;
|
size_t el;
|
||||||
const char* entry;
|
const char *entry;
|
||||||
|
|
||||||
vl = vector_length (authlist);
|
vl = vector_length (authlist);
|
||||||
if (vl == -EINVAL) return 0;
|
if (vl == -EINVAL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
for (i = 0; i < vl; i++) {
|
for (i = 0; i < vl; i++) {
|
||||||
entry = vector_getentry (authlist, i, &el);
|
entry = vector_getentry (authlist, i, &el);
|
||||||
if (strcmp (authstring, entry) == 0)
|
if (strcmp (authstring, entry) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,11 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
extern ssize_t basicauth_string(const char *user, const char *pass,
|
extern ssize_t basicauth_string (const char *user, const char *pass,
|
||||||
char *buf, size_t bufsize);
|
char *buf, size_t bufsize);
|
||||||
|
|
||||||
extern void basicauth_add (vector_t authlist,
|
extern void basicauth_add (vector_t authlist,
|
||||||
const char *user, const char *pass);
|
const char *user, const char *pass);
|
||||||
|
|
||||||
extern int basicauth_check (vector_t authlist, const char *authstring);
|
extern int basicauth_check (vector_t authlist, const char *authstring);
|
||||||
|
|
||||||
|
10
src/buffer.c
10
src/buffer.c
@ -244,9 +244,9 @@ ssize_t read_buffer (int fd, struct buffer_s * buffptr)
|
|||||||
#ifdef EWOULDBLOCK
|
#ifdef EWOULDBLOCK
|
||||||
case EWOULDBLOCK:
|
case EWOULDBLOCK:
|
||||||
#else
|
#else
|
||||||
# ifdef EAGAIN
|
#ifdef EAGAIN
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
# endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
case EINTR:
|
case EINTR:
|
||||||
bytesin = 0;
|
bytesin = 0;
|
||||||
@ -254,7 +254,7 @@ ssize_t read_buffer (int fd, struct buffer_s * buffptr)
|
|||||||
default:
|
default:
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"read_buffer: read() failed on fd %d: %s",
|
"read_buffer: read() failed on fd %d: %s",
|
||||||
fd, strerror(errno));
|
fd, strerror (errno));
|
||||||
bytesin = -1;
|
bytesin = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -298,9 +298,9 @@ ssize_t write_buffer (int fd, struct buffer_s * buffptr)
|
|||||||
#ifdef EWOULDBLOCK
|
#ifdef EWOULDBLOCK
|
||||||
case EWOULDBLOCK:
|
case EWOULDBLOCK:
|
||||||
#else
|
#else
|
||||||
# ifdef EAGAIN
|
#ifdef EAGAIN
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
# endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
case EINTR:
|
case EINTR:
|
||||||
return 0;
|
return 0;
|
||||||
|
80
src/child.c
80
src/child.c
@ -192,7 +192,7 @@ static void child_main (struct child_s *ptr)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cliaddr = (struct sockaddr *)
|
cliaddr = (struct sockaddr *)
|
||||||
safemalloc (sizeof(struct sockaddr_storage));
|
safemalloc (sizeof (struct sockaddr_storage));
|
||||||
if (!cliaddr) {
|
if (!cliaddr) {
|
||||||
log_message (LOG_CRIT,
|
log_message (LOG_CRIT,
|
||||||
"Could not allocate memory for child address.");
|
"Could not allocate memory for child address.");
|
||||||
@ -200,7 +200,7 @@ static void child_main (struct child_s *ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ptr->connects = 0;
|
ptr->connects = 0;
|
||||||
srand(time(NULL));
|
srand (time (NULL));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have to wait for connections on multiple fds,
|
* We have to wait for connections on multiple fds,
|
||||||
@ -210,45 +210,46 @@ static void child_main (struct child_s *ptr)
|
|||||||
|
|
||||||
int listenfd = -1;
|
int listenfd = -1;
|
||||||
|
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO (&rfds);
|
||||||
|
|
||||||
for (i = 0; i < vector_length(listen_fds); i++) {
|
for (i = 0; i < vector_length (listen_fds); i++) {
|
||||||
int *fd = (int *) vector_getentry(listen_fds, i, NULL);
|
int *fd = (int *) vector_getentry (listen_fds, i, NULL);
|
||||||
|
|
||||||
ret = socket_nonblocking(*fd);
|
ret = socket_nonblocking (*fd);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
log_message(LOG_ERR, "Failed to set the listening "
|
log_message (LOG_ERR,
|
||||||
"socket %d to non-blocking: %s",
|
"Failed to set the listening "
|
||||||
fd, strerror(errno));
|
"socket %d to non-blocking: %s",
|
||||||
exit(1);
|
fd, strerror (errno));
|
||||||
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
FD_SET(*fd, &rfds);
|
FD_SET (*fd, &rfds);
|
||||||
maxfd = max(maxfd, *fd);
|
maxfd = max (maxfd, *fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr->status = T_WAITING;
|
ptr->status = T_WAITING;
|
||||||
|
|
||||||
clilen = sizeof(struct sockaddr_storage);
|
clilen = sizeof (struct sockaddr_storage);
|
||||||
|
|
||||||
ret = select(maxfd + 1, &rfds, NULL, NULL, NULL);
|
ret = select (maxfd + 1, &rfds, NULL, NULL, NULL);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log_message (LOG_ERR, "error calling select: %s",
|
log_message (LOG_ERR, "error calling select: %s",
|
||||||
strerror(errno));
|
strerror (errno));
|
||||||
exit(1);
|
exit (1);
|
||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
log_message (LOG_WARNING, "Strange: select returned 0 "
|
log_message (LOG_WARNING, "Strange: select returned 0 "
|
||||||
"but we did not specify a timeout...");
|
"but we did not specify a timeout...");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < vector_length(listen_fds); i++) {
|
for (i = 0; i < vector_length (listen_fds); i++) {
|
||||||
int *fd = (int *) vector_getentry(listen_fds, i, NULL);
|
int *fd = (int *) vector_getentry (listen_fds, i, NULL);
|
||||||
|
|
||||||
if (FD_ISSET(*fd, &rfds)) {
|
if (FD_ISSET (*fd, &rfds)) {
|
||||||
/*
|
/*
|
||||||
* only accept the connection on the first
|
* only accept the connection on the first
|
||||||
* fd that we find readable. - fair?
|
* fd that we find readable. - fair?
|
||||||
@ -259,17 +260,17 @@ static void child_main (struct child_s *ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (listenfd == -1) {
|
if (listenfd == -1) {
|
||||||
log_message(LOG_WARNING, "Strange: None of our listen "
|
log_message (LOG_WARNING, "Strange: None of our listen "
|
||||||
"fds was readable after select");
|
"fds was readable after select");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = socket_blocking(listenfd);
|
ret = socket_blocking (listenfd);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
log_message(LOG_ERR, "Failed to set listening "
|
log_message (LOG_ERR, "Failed to set listening "
|
||||||
"socket %d to blocking for accept: %s",
|
"socket %d to blocking for accept: %s",
|
||||||
listenfd, strerror(errno));
|
listenfd, strerror (errno));
|
||||||
exit(1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -539,11 +540,10 @@ void child_kill_children (int sig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen on the various configured interfaces
|
* Listen on the various configured interfaces
|
||||||
*/
|
*/
|
||||||
int child_listening_sockets(vector_t listen_addrs, uint16_t port)
|
int child_listening_sockets (vector_t listen_addrs, uint16_t port)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
ssize_t i;
|
ssize_t i;
|
||||||
@ -551,7 +551,7 @@ int child_listening_sockets(vector_t listen_addrs, uint16_t port)
|
|||||||
assert (port > 0);
|
assert (port > 0);
|
||||||
|
|
||||||
if (listen_fds == NULL) {
|
if (listen_fds == NULL) {
|
||||||
listen_fds = vector_create();
|
listen_fds = vector_create ();
|
||||||
if (listen_fds == NULL) {
|
if (listen_fds == NULL) {
|
||||||
log_message (LOG_ERR, "Could not create the list "
|
log_message (LOG_ERR, "Could not create the list "
|
||||||
"of listening fds");
|
"of listening fds");
|
||||||
@ -559,28 +559,26 @@ int child_listening_sockets(vector_t listen_addrs, uint16_t port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((listen_addrs == NULL) ||
|
if ((listen_addrs == NULL) || (vector_length (listen_addrs) == 0)) {
|
||||||
(vector_length(listen_addrs) == 0))
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* no Listen directive:
|
* no Listen directive:
|
||||||
* listen on the wildcard address(es)
|
* listen on the wildcard address(es)
|
||||||
*/
|
*/
|
||||||
ret = listen_sock(NULL, port, listen_fds);
|
ret = listen_sock (NULL, port, listen_fds);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < vector_length(listen_addrs); i++) {
|
for (i = 0; i < vector_length (listen_addrs); i++) {
|
||||||
const char *addr;
|
const char *addr;
|
||||||
|
|
||||||
addr = (char *)vector_getentry(listen_addrs, i, NULL);
|
addr = (char *) vector_getentry (listen_addrs, i, NULL);
|
||||||
if (addr == NULL) {
|
if (addr == NULL) {
|
||||||
log_message(LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"got NULL from listen_addrs - skipping");
|
"got NULL from listen_addrs - skipping");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = listen_sock(addr, port, listen_fds);
|
ret = listen_sock (addr, port, listen_fds);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -593,12 +591,12 @@ void child_close_sock (void)
|
|||||||
{
|
{
|
||||||
ssize_t i;
|
ssize_t i;
|
||||||
|
|
||||||
for (i = 0; i < vector_length(listen_fds); i++) {
|
for (i = 0; i < vector_length (listen_fds); i++) {
|
||||||
int *fd = (int *) vector_getentry(listen_fds, i, NULL);
|
int *fd = (int *) vector_getentry (listen_fds, i, NULL);
|
||||||
close (*fd);
|
close (*fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector_delete(listen_fds);
|
vector_delete (listen_fds);
|
||||||
|
|
||||||
listen_fds = NULL;
|
listen_fds = NULL;
|
||||||
}
|
}
|
||||||
|
86
src/common.h
86
src/common.h
@ -26,7 +26,7 @@
|
|||||||
#define COMMON_HEADER_H
|
#define COMMON_HEADER_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -42,57 +42,57 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
/* standard POSIX headers - they need to be there as well. */
|
/* standard POSIX headers - they need to be there as well. */
|
||||||
# include <errno.h>
|
#include <errno.h>
|
||||||
# include <fcntl.h>
|
#include <fcntl.h>
|
||||||
# include <netdb.h>
|
#include <netdb.h>
|
||||||
# include <signal.h>
|
#include <signal.h>
|
||||||
# include <stdarg.h>
|
#include <stdarg.h>
|
||||||
# include <strings.h>
|
#include <strings.h>
|
||||||
# include <syslog.h>
|
#include <syslog.h>
|
||||||
# include <wchar.h>
|
#include <wchar.h>
|
||||||
# include <wctype.h>
|
#include <wctype.h>
|
||||||
# include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
# include <sys/select.h>
|
#include <sys/select.h>
|
||||||
# include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
# include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
# include <sys/types.h>
|
#include <sys/types.h>
|
||||||
# include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
# include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
# include <sys/un.h>
|
#include <sys/un.h>
|
||||||
# include <sys/time.h>
|
#include <sys/time.h>
|
||||||
# include <time.h>
|
#include <time.h>
|
||||||
# include <inttypes.h>
|
#include <inttypes.h>
|
||||||
# include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
# include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
# include <assert.h>
|
#include <assert.h>
|
||||||
# include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
# include <grp.h>
|
#include <grp.h>
|
||||||
# include <pwd.h>
|
#include <pwd.h>
|
||||||
# include <regex.h>
|
#include <regex.h>
|
||||||
|
|
||||||
/* rest - some oddball headers */
|
/* rest - some oddball headers */
|
||||||
#ifdef HAVE_VALUES_H
|
#ifdef HAVE_VALUES_H
|
||||||
# include <values.h>
|
#include <values.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_IOCTL_H
|
#ifdef HAVE_SYS_IOCTL_H
|
||||||
# include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_ALLOCA_H
|
#ifdef HAVE_ALLOCA_H
|
||||||
# include <alloca.h>
|
#include <alloca.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_MEMORY_H
|
#ifdef HAVE_MEMORY_H
|
||||||
# include <memory.h>
|
#include <memory.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_MALLOC_H
|
#ifdef HAVE_MALLOC_H
|
||||||
# include <malloc.h>
|
#include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYSEXITS_H
|
#ifdef HAVE_SYSEXITS_H
|
||||||
# include <sysexits.h>
|
#include <sysexits.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -100,13 +100,13 @@
|
|||||||
* cause any problems.
|
* cause any problems.
|
||||||
*/
|
*/
|
||||||
#ifndef MSG_NOSIGNAL
|
#ifndef MSG_NOSIGNAL
|
||||||
# define MSG_NOSIGNAL (0)
|
#define MSG_NOSIGNAL (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SHUT_RD /* these three Posix.1g names are quite new */
|
#ifndef SHUT_RD /* these three Posix.1g names are quite new */
|
||||||
# define SHUT_RD 0 /* shutdown for reading */
|
#define SHUT_RD 0 /* shutdown for reading */
|
||||||
# define SHUT_WR 1 /* shutdown for writing */
|
#define SHUT_WR 1 /* shutdown for writing */
|
||||||
# define SHUT_RDWR 2 /* shutdown for reading and writing */
|
#define SHUT_RDWR 2 /* shutdown for reading and writing */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAXLISTEN 1024 /* Max number of connections */
|
#define MAXLISTEN 1024 /* Max number of connections */
|
||||||
@ -115,19 +115,19 @@
|
|||||||
* SunOS doesn't have INADDR_NONE defined.
|
* SunOS doesn't have INADDR_NONE defined.
|
||||||
*/
|
*/
|
||||||
#ifndef INADDR_NONE
|
#ifndef INADDR_NONE
|
||||||
# define INADDR_NONE -1
|
#define INADDR_NONE -1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Define boolean values */
|
/* Define boolean values */
|
||||||
#ifndef FALSE
|
#ifndef FALSE
|
||||||
# define FALSE 0
|
#define FALSE 0
|
||||||
# define TRUE (!FALSE)
|
#define TRUE (!FALSE)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Useful function macros */
|
/* Useful function macros */
|
||||||
#if !defined(min) || !defined(max)
|
#if !defined(min) || !defined(max)
|
||||||
# define min(a,b) ((a) < (b) ? (a) : (b))
|
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||||
# define max(a,b) ((a) > (b) ? (a) : (b))
|
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
312
src/conf.c
312
src/conf.c
@ -80,13 +80,14 @@
|
|||||||
#define IPV6MASK "(" IPV6 "(/[[:digit:]]+)?)"
|
#define IPV6MASK "(" IPV6 "(/[[:digit:]]+)?)"
|
||||||
#define BEGIN "^[[:space:]]*"
|
#define BEGIN "^[[:space:]]*"
|
||||||
#define END "[[:space:]]*$"
|
#define END "[[:space:]]*$"
|
||||||
|
#define PIPE "\\|"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Limit the maximum number of substring matches to a reasonably high
|
* Limit the maximum number of substring matches to a reasonably high
|
||||||
* number. Given the usual structure of the configuration file, sixteen
|
* number. Given the usual structure of the configuration file, sixteen
|
||||||
* substring matches should be plenty.
|
* substring matches should be plenty.
|
||||||
*/
|
*/
|
||||||
#define RE_MAX_MATCHES 16
|
#define RE_MAX_MATCHES 50
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All configuration handling functions are REQUIRED to be defined
|
* All configuration handling functions are REQUIRED to be defined
|
||||||
@ -163,6 +164,7 @@ static HANDLE_FUNC (handle_disableviaheader);
|
|||||||
static HANDLE_FUNC (handle_xtinyproxy);
|
static HANDLE_FUNC (handle_xtinyproxy);
|
||||||
|
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
static HANDLE_FUNC (handle_deadtime);
|
||||||
static HANDLE_FUNC (handle_upstream);
|
static HANDLE_FUNC (handle_upstream);
|
||||||
static HANDLE_FUNC (handle_upstream_no);
|
static HANDLE_FUNC (handle_upstream_no);
|
||||||
#endif
|
#endif
|
||||||
@ -195,91 +197,89 @@ struct {
|
|||||||
} directives[] = {
|
} directives[] = {
|
||||||
/* comments */
|
/* comments */
|
||||||
{
|
{
|
||||||
BEGIN "#", handle_nop, NULL
|
BEGIN "#", handle_nop, NULL},
|
||||||
},
|
/* blank lines */
|
||||||
/* blank lines */
|
|
||||||
{
|
{
|
||||||
"^[[:space:]]+$", handle_nop, NULL
|
"^[[:space:]]+$", handle_nop, NULL},
|
||||||
},
|
/* string arguments */
|
||||||
/* string arguments */
|
STDCONF ("logfile", STR, handle_logfile),
|
||||||
STDCONF ("logfile", STR, handle_logfile),
|
STDCONF ("pidfile", STR, handle_pidfile),
|
||||||
STDCONF ("pidfile", STR, handle_pidfile),
|
STDCONF ("anonymous", STR, handle_anonymous),
|
||||||
STDCONF ("anonymous", STR, handle_anonymous),
|
STDCONF ("viaproxyname", STR, handle_viaproxyname),
|
||||||
STDCONF ("viaproxyname", STR, handle_viaproxyname),
|
STDCONF ("defaulterrorfile", STR, handle_defaulterrorfile),
|
||||||
STDCONF ("defaulterrorfile", STR, handle_defaulterrorfile),
|
STDCONF ("statfile", STR, handle_statfile),
|
||||||
STDCONF ("statfile", STR, handle_statfile),
|
STDCONF ("stathost", STR, handle_stathost),
|
||||||
STDCONF ("stathost", STR, handle_stathost),
|
STDCONF ("xtinyproxy", BOOL, handle_xtinyproxy),
|
||||||
STDCONF ("xtinyproxy", BOOL, handle_xtinyproxy),
|
/* boolean arguments */
|
||||||
/* boolean arguments */
|
STDCONF ("syslog", BOOL, handle_syslog),
|
||||||
STDCONF ("syslog", BOOL, handle_syslog),
|
STDCONF ("bindsame", BOOL, handle_bindsame),
|
||||||
STDCONF ("bindsame", BOOL, handle_bindsame),
|
STDCONF ("disableviaheader", BOOL, handle_disableviaheader),
|
||||||
STDCONF ("disableviaheader", BOOL, handle_disableviaheader),
|
/* integer arguments */
|
||||||
/* integer arguments */
|
STDCONF ("port", INT, handle_port),
|
||||||
STDCONF ("port", INT, handle_port),
|
STDCONF ("maxclients", INT, handle_maxclients),
|
||||||
STDCONF ("maxclients", INT, handle_maxclients),
|
STDCONF ("maxspareservers", INT, handle_maxspareservers),
|
||||||
STDCONF ("maxspareservers", INT, handle_maxspareservers),
|
STDCONF ("minspareservers", INT, handle_minspareservers),
|
||||||
STDCONF ("minspareservers", INT, handle_minspareservers),
|
STDCONF ("startservers", INT, handle_startservers),
|
||||||
STDCONF ("startservers", INT, handle_startservers),
|
STDCONF ("maxrequestsperchild", INT, handle_maxrequestsperchild),
|
||||||
STDCONF ("maxrequestsperchild", INT, handle_maxrequestsperchild),
|
STDCONF ("timeout", INT, handle_timeout),
|
||||||
STDCONF ("timeout", INT, handle_timeout),
|
#ifdef UPSTREAM_SUPPORT
|
||||||
STDCONF ("connectport", INT, handle_connectport),
|
STDCONF ("deadtime", INT, handle_deadtime),
|
||||||
/* alphanumeric arguments */
|
#endif
|
||||||
STDCONF ("user", ALNUM, handle_user),
|
STDCONF ("connectport", INT, handle_connectport),
|
||||||
STDCONF ("group", ALNUM, handle_group),
|
/* alphanumeric arguments */
|
||||||
/* ip arguments */
|
STDCONF ("user", ALNUM, handle_user),
|
||||||
STDCONF ("listen", "(" IP "|" IPV6 ")", handle_listen),
|
STDCONF ("group", ALNUM, handle_group),
|
||||||
STDCONF ("allow", "(" "(" IPMASK "|" IPV6MASK ")" "|" ALNUM ")",
|
/* ip arguments */
|
||||||
handle_allow),
|
STDCONF ("listen", "(" IP "|" IPV6 ")", handle_listen),
|
||||||
STDCONF ("deny", "(" "(" IPMASK "|" IPV6MASK ")" "|" ALNUM ")",
|
STDCONF ("allow", "(" "(" IPMASK "|" IPV6MASK ")" "|" ALNUM ")",
|
||||||
handle_deny),
|
handle_allow),
|
||||||
STDCONF ("bind", "(" IP "|" IPV6 ")", handle_bind),
|
STDCONF ("deny", "(" "(" IPMASK "|" IPV6MASK ")" "|" ALNUM ")",
|
||||||
/* other */
|
handle_deny),
|
||||||
STDCONF ("basicauth", ALNUM WS ALNUM, handle_basicauth),
|
STDCONF ("bind", "(" IP "|" IPV6 ")", handle_bind),
|
||||||
STDCONF ("errorfile", INT WS STR, handle_errorfile),
|
/* other */
|
||||||
STDCONF ("addheader", STR WS STR, handle_addheader),
|
STDCONF ("basicauth", ALNUM WS ALNUM, handle_basicauth),
|
||||||
|
STDCONF ("errorfile", INT WS STR, handle_errorfile),
|
||||||
|
STDCONF ("addheader", STR WS STR, handle_addheader),
|
||||||
#ifdef FILTER_ENABLE
|
#ifdef FILTER_ENABLE
|
||||||
/* filtering */
|
/* filtering */
|
||||||
STDCONF ("filter", STR, handle_filter),
|
STDCONF ("filter", STR, handle_filter),
|
||||||
STDCONF ("filterurls", BOOL, handle_filterurls),
|
STDCONF ("filterurls", BOOL, handle_filterurls),
|
||||||
STDCONF ("filterextended", BOOL, handle_filterextended),
|
STDCONF ("filterextended", BOOL, handle_filterextended),
|
||||||
STDCONF ("filterdefaultdeny", BOOL, handle_filterdefaultdeny),
|
STDCONF ("filterdefaultdeny", BOOL, handle_filterdefaultdeny),
|
||||||
STDCONF ("filtercasesensitive", BOOL, handle_filtercasesensitive),
|
STDCONF ("filtercasesensitive", BOOL, handle_filtercasesensitive),
|
||||||
#endif
|
#endif
|
||||||
#ifdef REVERSE_SUPPORT
|
#ifdef REVERSE_SUPPORT
|
||||||
/* Reverse proxy arguments */
|
/* Reverse proxy arguments */
|
||||||
STDCONF ("reversebaseurl", STR, handle_reversebaseurl),
|
STDCONF ("reversebaseurl", STR, handle_reversebaseurl),
|
||||||
STDCONF ("reverseonly", BOOL, handle_reverseonly),
|
STDCONF ("reverseonly", BOOL, handle_reverseonly),
|
||||||
STDCONF ("reversemagic", BOOL, handle_reversemagic),
|
STDCONF ("reversemagic", BOOL, handle_reversemagic),
|
||||||
STDCONF ("reversepath", STR "(" WS STR ")?", handle_reversepath),
|
STDCONF ("reversepath", STR "(" WS STR ")?", handle_reversepath),
|
||||||
#endif
|
#endif
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
{
|
{
|
||||||
BEGIN "(upstream)" WS "(none)" WS STR END, handle_upstream_no, NULL
|
BEGIN "(upstream)" WS "(none)" WS STR END, handle_upstream_no, NULL},
|
||||||
},
|
|
||||||
{
|
{
|
||||||
BEGIN "(upstream)" WS "(http|socks4|socks5)" WS
|
BEGIN "(upstream)" WS "(http|socks4|socks5)" WS
|
||||||
"(" USERNAME /*username*/ ":" PASSWORD /*password*/ "@" ")?"
|
"(" USERNAME /*username */ ":" PASSWORD /*password */ "@"
|
||||||
"(" IP "|" ALNUM ")"
|
")?"
|
||||||
":" INT "(" WS STR ")?"
|
"(" IP "|" ALNUM ")" ":" INT "(" "(" PIPE "(" IP
|
||||||
END, handle_upstream, NULL
|
"|" ALNUM ")" ":" INT ")+" ")?" "(" WS STR ")?"
|
||||||
},
|
END, handle_upstream, NULL},
|
||||||
#endif
|
#endif
|
||||||
/* loglevel */
|
/* loglevel */
|
||||||
STDCONF ("loglevel", "(critical|error|warning|notice|connect|info)",
|
STDCONF ("loglevel", "(critical|error|warning|notice|connect|info)",
|
||||||
handle_loglevel)
|
handle_loglevel)
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned int ndirectives = sizeof (directives) / sizeof (directives[0]);
|
const unsigned int ndirectives = sizeof (directives) / sizeof (directives[0]);
|
||||||
|
|
||||||
static void
|
static void free_added_headers (vector_t add_headers)
|
||||||
free_added_headers (vector_t add_headers)
|
|
||||||
{
|
{
|
||||||
ssize_t i;
|
ssize_t i;
|
||||||
|
|
||||||
for (i = 0; i < vector_length (add_headers); i++) {
|
for (i = 0; i < vector_length (add_headers); i++) {
|
||||||
http_header_t *header = (http_header_t *)
|
http_header_t *header = (http_header_t *)
|
||||||
vector_getentry (add_headers, i, NULL);
|
vector_getentry (add_headers, i, NULL);
|
||||||
|
|
||||||
safefree (header->name);
|
safefree (header->name);
|
||||||
safefree (header->value);
|
safefree (header->value);
|
||||||
@ -288,25 +288,25 @@ free_added_headers (vector_t add_headers)
|
|||||||
vector_delete (add_headers);
|
vector_delete (add_headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_config (struct config_s *conf)
|
void free_config (struct config_s *conf)
|
||||||
{
|
{
|
||||||
safefree (conf->config_file);
|
safefree (conf->config_file);
|
||||||
safefree (conf->logf_name);
|
safefree (conf->logf_name);
|
||||||
safefree (conf->stathost);
|
safefree (conf->stathost);
|
||||||
safefree (conf->user);
|
safefree (conf->user);
|
||||||
safefree (conf->group);
|
safefree (conf->group);
|
||||||
vector_delete(conf->listen_addrs);
|
vector_delete (conf->listen_addrs);
|
||||||
vector_delete(conf->basicauth_list);
|
vector_delete (conf->basicauth_list);
|
||||||
#ifdef FILTER_ENABLE
|
#ifdef FILTER_ENABLE
|
||||||
safefree (conf->filter);
|
safefree (conf->filter);
|
||||||
#endif /* FILTER_ENABLE */
|
#endif /* FILTER_ENABLE */
|
||||||
#ifdef REVERSE_SUPPORT
|
#ifdef REVERSE_SUPPORT
|
||||||
free_reversepath_list(conf->reversepath_list);
|
free_reversepath_list (conf->reversepath_list);
|
||||||
safefree (conf->reversebaseurl);
|
safefree (conf->reversebaseurl);
|
||||||
#endif
|
#endif
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
free_upstream_list (conf->upstream_list);
|
free_upstream_list (conf->upstream_list);
|
||||||
#endif /* UPSTREAM_SUPPORT */
|
#endif /* UPSTREAM_SUPPORT */
|
||||||
safefree (conf->pidpath);
|
safefree (conf->pidpath);
|
||||||
safefree (conf->bind_address);
|
safefree (conf->bind_address);
|
||||||
safefree (conf->via_proxy_name);
|
safefree (conf->via_proxy_name);
|
||||||
@ -318,7 +318,7 @@ static void free_config (struct config_s *conf)
|
|||||||
free_connect_ports_list (conf->connect_ports);
|
free_connect_ports_list (conf->connect_ports);
|
||||||
hashmap_delete (conf->anonymous_map);
|
hashmap_delete (conf->anonymous_map);
|
||||||
|
|
||||||
memset (conf, 0, sizeof(*conf));
|
memset (conf, 0, sizeof (*conf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -327,8 +327,7 @@ static void free_config (struct config_s *conf)
|
|||||||
*
|
*
|
||||||
* Returns 0 on success; negative upon failure.
|
* Returns 0 on success; negative upon failure.
|
||||||
*/
|
*/
|
||||||
int
|
int config_compile_regex (void)
|
||||||
config_compile_regex (void)
|
|
||||||
{
|
{
|
||||||
unsigned int i, r;
|
unsigned int i, r;
|
||||||
|
|
||||||
@ -356,8 +355,7 @@ config_compile_regex (void)
|
|||||||
* Frees pre-compiled regular expressions used by the configuration
|
* Frees pre-compiled regular expressions used by the configuration
|
||||||
* file. This function is registered to be automatically called at exit.
|
* file. This function is registered to be automatically called at exit.
|
||||||
*/
|
*/
|
||||||
static void
|
static void config_free_regex (void)
|
||||||
config_free_regex (void)
|
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@ -384,7 +382,6 @@ static int check_match (struct config_s *conf, const char *line)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
assert (ndirectives > 0);
|
assert (ndirectives > 0);
|
||||||
|
|
||||||
for (i = 0; i != ndirectives; ++i) {
|
for (i = 0; i != ndirectives; ++i) {
|
||||||
assert (directives[i].cre);
|
assert (directives[i].cre);
|
||||||
if (!regexec
|
if (!regexec
|
||||||
@ -476,17 +473,16 @@ static void initialize_with_defaults (struct config_s *conf,
|
|||||||
if (defaults->listen_addrs) {
|
if (defaults->listen_addrs) {
|
||||||
ssize_t i;
|
ssize_t i;
|
||||||
|
|
||||||
conf->listen_addrs = vector_create();
|
conf->listen_addrs = vector_create ();
|
||||||
for (i=0; i < vector_length(defaults->listen_addrs); i++) {
|
for (i = 0; i < vector_length (defaults->listen_addrs); i++) {
|
||||||
char *addr;
|
char *addr;
|
||||||
size_t size;
|
size_t size;
|
||||||
addr = (char *)vector_getentry(defaults->listen_addrs,
|
addr = (char *) vector_getentry (defaults->listen_addrs,
|
||||||
i, &size);
|
i, &size);
|
||||||
vector_append(conf->listen_addrs, addr, size);
|
vector_append (conf->listen_addrs, addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FILTER_ENABLE
|
#ifdef FILTER_ENABLE
|
||||||
if (defaults->filter) {
|
if (defaults->filter) {
|
||||||
conf->filter = safestrdup (defaults->filter);
|
conf->filter = safestrdup (defaults->filter);
|
||||||
@ -495,7 +491,7 @@ static void initialize_with_defaults (struct config_s *conf,
|
|||||||
conf->filter_url = defaults->filter_url;
|
conf->filter_url = defaults->filter_url;
|
||||||
conf->filter_extended = defaults->filter_extended;
|
conf->filter_extended = defaults->filter_extended;
|
||||||
conf->filter_casesensitive = defaults->filter_casesensitive;
|
conf->filter_casesensitive = defaults->filter_casesensitive;
|
||||||
#endif /* FILTER_ENABLE */
|
#endif /* FILTER_ENABLE */
|
||||||
|
|
||||||
#ifdef XTINYPROXY_ENABLE
|
#ifdef XTINYPROXY_ENABLE
|
||||||
conf->add_xtinyproxy = defaults->add_xtinyproxy;
|
conf->add_xtinyproxy = defaults->add_xtinyproxy;
|
||||||
@ -513,7 +509,7 @@ static void initialize_with_defaults (struct config_s *conf,
|
|||||||
|
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
/* struct upstream *upstream_list; */
|
/* struct upstream *upstream_list; */
|
||||||
#endif /* UPSTREAM_SUPPORT */
|
#endif /* UPSTREAM_SUPPORT */
|
||||||
|
|
||||||
if (defaults->pidpath) {
|
if (defaults->pidpath) {
|
||||||
conf->pidpath = safestrdup (defaults->pidpath);
|
conf->pidpath = safestrdup (defaults->pidpath);
|
||||||
@ -521,6 +517,10 @@ static void initialize_with_defaults (struct config_s *conf,
|
|||||||
|
|
||||||
conf->idletimeout = defaults->idletimeout;
|
conf->idletimeout = defaults->idletimeout;
|
||||||
|
|
||||||
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
conf->deadtime = defaults->deadtime;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (defaults->bind_address) {
|
if (defaults->bind_address) {
|
||||||
conf->bind_address = safestrdup (defaults->bind_address);
|
conf->bind_address = safestrdup (defaults->bind_address);
|
||||||
}
|
}
|
||||||
@ -589,6 +589,15 @@ int reload_config_file (const char *config_fname, struct config_s *conf,
|
|||||||
MAX_IDLE_TIME);
|
MAX_IDLE_TIME);
|
||||||
conf->idletimeout = MAX_IDLE_TIME;
|
conf->idletimeout = MAX_IDLE_TIME;
|
||||||
}
|
}
|
||||||
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
if (conf->deadtime == 0) {
|
||||||
|
log_message (LOG_WARNING, "Invalid dead time setting. "
|
||||||
|
"Only values greater than zero are allowed. "
|
||||||
|
"Therefore setting idle timeout to %u seconds.",
|
||||||
|
MAX_DEAD_TIME);
|
||||||
|
conf->deadtime = MAX_DEAD_TIME;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
@ -659,8 +668,7 @@ set_bool_arg (unsigned int *var, const char *line, regmatch_t * match)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long get_long_arg (const char *line, regmatch_t * match)
|
||||||
get_long_arg (const char *line, regmatch_t * match)
|
|
||||||
{
|
{
|
||||||
assert (line);
|
assert (line);
|
||||||
assert (match && match->rm_so != -1);
|
assert (match && match->rm_so != -1);
|
||||||
@ -668,8 +676,7 @@ get_long_arg (const char *line, regmatch_t * match)
|
|||||||
return strtoul (line + match->rm_so, NULL, 0);
|
return strtoul (line + match->rm_so, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int set_int_arg (unsigned int *var, const char *line, regmatch_t * match)
|
||||||
set_int_arg (unsigned int *var, const char *line, regmatch_t * match)
|
|
||||||
{
|
{
|
||||||
assert (var);
|
assert (var);
|
||||||
assert (line);
|
assert (line);
|
||||||
@ -726,8 +733,7 @@ static HANDLE_FUNC (handle_viaproxyname)
|
|||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
log_message (LOG_INFO,
|
log_message (LOG_INFO,
|
||||||
"Setting \"Via\" header to '%s'",
|
"Setting \"Via\" header to '%s'", conf->via_proxy_name);
|
||||||
conf->via_proxy_name);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -739,8 +745,7 @@ static HANDLE_FUNC (handle_disableviaheader)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_message (LOG_INFO,
|
log_message (LOG_INFO, "Disabling transmission of the \"Via\" header.");
|
||||||
"Disabling transmission of the \"Via\" header.");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,15 +816,13 @@ static HANDLE_FUNC (handle_maxclients)
|
|||||||
|
|
||||||
static HANDLE_FUNC (handle_maxspareservers)
|
static HANDLE_FUNC (handle_maxspareservers)
|
||||||
{
|
{
|
||||||
child_configure (CHILD_MAXSPARESERVERS,
|
child_configure (CHILD_MAXSPARESERVERS, get_long_arg (line, &match[2]));
|
||||||
get_long_arg (line, &match[2]));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HANDLE_FUNC (handle_minspareservers)
|
static HANDLE_FUNC (handle_minspareservers)
|
||||||
{
|
{
|
||||||
child_configure (CHILD_MINSPARESERVERS,
|
child_configure (CHILD_MINSPARESERVERS, get_long_arg (line, &match[2]));
|
||||||
get_long_arg (line, &match[2]));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -841,6 +844,13 @@ static HANDLE_FUNC (handle_timeout)
|
|||||||
return set_int_arg (&conf->idletimeout, line, &match[2]);
|
return set_int_arg (&conf->idletimeout, line, &match[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
static HANDLE_FUNC (handle_deadtime)
|
||||||
|
{
|
||||||
|
return set_int_arg (&conf->deadtime, line, &match[2]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static HANDLE_FUNC (handle_connectport)
|
static HANDLE_FUNC (handle_connectport)
|
||||||
{
|
{
|
||||||
add_connect_port_allowed (get_long_arg (line, &match[2]),
|
add_connect_port_allowed (get_long_arg (line, &match[2]),
|
||||||
@ -896,18 +906,18 @@ static HANDLE_FUNC (handle_listen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (conf->listen_addrs == NULL) {
|
if (conf->listen_addrs == NULL) {
|
||||||
conf->listen_addrs = vector_create();
|
conf->listen_addrs = vector_create ();
|
||||||
if (conf->listen_addrs == NULL) {
|
if (conf->listen_addrs == NULL) {
|
||||||
log_message(LOG_WARNING, "Could not create a list "
|
log_message (LOG_WARNING, "Could not create a list "
|
||||||
"of listen addresses.");
|
"of listen addresses.");
|
||||||
safefree(arg);
|
safefree (arg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector_append (conf->listen_addrs, arg, strlen(arg) + 1);
|
vector_append (conf->listen_addrs, arg, strlen (arg) + 1);
|
||||||
|
|
||||||
log_message(LOG_INFO, "Added address [%s] to listen addresses.", arg);
|
log_message (LOG_INFO, "Added address [%s] to listen addresses.", arg);
|
||||||
|
|
||||||
safefree (arg);
|
safefree (arg);
|
||||||
return 0;
|
return 0;
|
||||||
@ -994,10 +1004,10 @@ static HANDLE_FUNC (handle_loglevel)
|
|||||||
static HANDLE_FUNC (handle_basicauth)
|
static HANDLE_FUNC (handle_basicauth)
|
||||||
{
|
{
|
||||||
char *user, *pass;
|
char *user, *pass;
|
||||||
user = get_string_arg(line, &match[2]);
|
user = get_string_arg (line, &match[2]);
|
||||||
if (!user)
|
if (!user)
|
||||||
return -1;
|
return -1;
|
||||||
pass = get_string_arg(line, &match[3]);
|
pass = get_string_arg (line, &match[3]);
|
||||||
if (!pass) {
|
if (!pass) {
|
||||||
safefree (user);
|
safefree (user);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1089,58 +1099,90 @@ static HANDLE_FUNC (handle_reversepath)
|
|||||||
|
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
|
||||||
static enum proxy_type pt_from_string(const char *s)
|
static enum proxy_type pt_from_string (const char *s)
|
||||||
{
|
{
|
||||||
static const char pt_map[][7] = {
|
static const char pt_map[][7] = {
|
||||||
[PT_NONE] = "none",
|
[PT_NONE] = "none",
|
||||||
[PT_HTTP] = "http",
|
[PT_HTTP] = "http",
|
||||||
[PT_SOCKS4] = "socks4",
|
[PT_SOCKS4] = "socks4",
|
||||||
[PT_SOCKS5] = "socks5",
|
[PT_SOCKS5] = "socks5",
|
||||||
};
|
};
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < sizeof(pt_map)/sizeof(pt_map[0]); i++)
|
for (i = 0; i < sizeof (pt_map) / sizeof (pt_map[0]); i++)
|
||||||
if (!strcmp(pt_map[i], s))
|
if (!strcmp (pt_map[i], s))
|
||||||
return i;
|
return i;
|
||||||
return PT_NONE;
|
return PT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HANDLE_FUNC (handle_upstream)
|
static HANDLE_FUNC (handle_upstream)
|
||||||
{
|
{
|
||||||
char *ip;
|
struct upstream_proxy_list *pltr, *plist;
|
||||||
int port, mi = 2;
|
int mi = 2;
|
||||||
char *domain = 0, *user = 0, *pass = 0, *tmp;
|
char *domain = 0, *user = 0, *pass = 0, *tmp;
|
||||||
enum proxy_type pt;
|
enum proxy_type pt;
|
||||||
|
|
||||||
|
pltr = plist = (upstream_proxy_list_t *)
|
||||||
|
safemalloc (sizeof (upstream_proxy_list_t));
|
||||||
tmp = get_string_arg (line, &match[mi]);
|
tmp = get_string_arg (line, &match[mi]);
|
||||||
pt = pt_from_string(tmp);
|
pt = pt_from_string (tmp);
|
||||||
safefree(tmp);
|
safefree (tmp);
|
||||||
mi += 2;
|
mi += 2;
|
||||||
|
|
||||||
if (match[mi].rm_so != -1)
|
if (match[mi].rm_so != -1)
|
||||||
user = get_string_arg (line, &match[mi]);
|
user = get_string_arg (line, &match[mi]);
|
||||||
mi++;
|
mi++;
|
||||||
|
|
||||||
if (match[mi].rm_so != -1)
|
if (match[mi].rm_so != -1)
|
||||||
pass = get_string_arg (line, &match[mi]);
|
pass = get_string_arg (line, &match[mi]);
|
||||||
mi++;
|
mi++;
|
||||||
|
plist->host = get_string_arg (line, &match[mi]);
|
||||||
ip = get_string_arg (line, &match[mi]);
|
if (!plist->host)
|
||||||
if (!ip)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
mi += 5;
|
mi += 5;
|
||||||
|
plist->port = (int) get_long_arg (line, &match[mi]);
|
||||||
|
plist->last_failed_connect = (time_t) 0;
|
||||||
|
|
||||||
port = (int) get_long_arg (line, &match[mi]);
|
mi += 2;
|
||||||
mi += 3;
|
/* if != -1 we have a list of proxy hosts seperated by |. */
|
||||||
|
if (match[mi].rm_so != -1) {
|
||||||
|
/* loop over proxy host list */
|
||||||
|
char *phl, *pptr;
|
||||||
|
|
||||||
|
phl = get_string_arg (line, &match[mi]);
|
||||||
|
if (!phl)
|
||||||
|
return -1;
|
||||||
|
pptr = strtok (phl, "|");
|
||||||
|
while (pptr) {
|
||||||
|
char *cptr;
|
||||||
|
plist->next = (upstream_proxy_list_t *)
|
||||||
|
safemalloc (sizeof (upstream_proxy_list_t));
|
||||||
|
plist = plist->next;
|
||||||
|
cptr = strchr (pptr, ':');
|
||||||
|
*cptr++ = '\0';
|
||||||
|
plist->host = strdup (pptr);
|
||||||
|
plist->port = strtoul (cptr, NULL, 0);
|
||||||
|
plist->last_failed_connect = (time_t) 0;
|
||||||
|
pptr = strtok (NULL, "|");
|
||||||
|
}
|
||||||
|
safefree (phl);
|
||||||
|
}
|
||||||
|
|
||||||
|
mi += 10;
|
||||||
if (match[mi].rm_so != -1)
|
if (match[mi].rm_so != -1)
|
||||||
domain = get_string_arg (line, &match[mi]);
|
domain = get_string_arg (line, &match[mi]);
|
||||||
|
|
||||||
upstream_add (ip, port, domain, user, pass, pt, &conf->upstream_list);
|
upstream_add (pltr, domain, user, pass, pt, &conf->upstream_list);
|
||||||
|
|
||||||
safefree (user);
|
safefree (user);
|
||||||
safefree (pass);
|
safefree (pass);
|
||||||
safefree (domain);
|
safefree (domain);
|
||||||
safefree (ip);
|
while (pltr) {
|
||||||
|
struct upstream_proxy_list *tmpp = pltr;
|
||||||
|
pltr = pltr->next;
|
||||||
|
safefree (tmpp->host);
|
||||||
|
safefree (tmpp);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1153,7 +1195,7 @@ static HANDLE_FUNC (handle_upstream_no)
|
|||||||
if (!domain)
|
if (!domain)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
upstream_add (NULL, 0, domain, 0, 0, PT_NONE, &conf->upstream_list);
|
upstream_add (NULL, domain, 0, 0, PT_NONE, &conf->upstream_list);
|
||||||
safefree (domain);
|
safefree (domain);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -55,7 +55,7 @@ struct config_s {
|
|||||||
unsigned int filter_casesensitive; /* boolean */
|
unsigned int filter_casesensitive; /* boolean */
|
||||||
#endif /* FILTER_ENABLE */
|
#endif /* FILTER_ENABLE */
|
||||||
#ifdef XTINYPROXY_ENABLE
|
#ifdef XTINYPROXY_ENABLE
|
||||||
unsigned int add_xtinyproxy; /* boolean */
|
unsigned int add_xtinyproxy; /* boolean */
|
||||||
#endif
|
#endif
|
||||||
#ifdef REVERSE_SUPPORT
|
#ifdef REVERSE_SUPPORT
|
||||||
struct reversepath *reversepath_list;
|
struct reversepath *reversepath_list;
|
||||||
@ -68,6 +68,9 @@ struct config_s {
|
|||||||
#endif /* UPSTREAM_SUPPORT */
|
#endif /* UPSTREAM_SUPPORT */
|
||||||
char *pidpath;
|
char *pidpath;
|
||||||
unsigned int idletimeout;
|
unsigned int idletimeout;
|
||||||
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
unsigned int deadtime;
|
||||||
|
#endif /* UPSTREAM_SUPPORT */
|
||||||
char *bind_address;
|
char *bind_address;
|
||||||
unsigned int bindsame;
|
unsigned int bindsame;
|
||||||
|
|
||||||
@ -116,6 +119,8 @@ struct config_s {
|
|||||||
extern int reload_config_file (const char *config_fname, struct config_s *conf,
|
extern int reload_config_file (const char *config_fname, struct config_s *conf,
|
||||||
struct config_s *defaults);
|
struct config_s *defaults);
|
||||||
|
|
||||||
|
extern void free_config (struct config_s *conf);
|
||||||
|
|
||||||
int config_compile_regex (void);
|
int config_compile_regex (void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
* Now, this routine adds a "port" to the list. It also creates the list if
|
* Now, this routine adds a "port" to the list. It also creates the list if
|
||||||
* it hasn't already by done.
|
* it hasn't already by done.
|
||||||
*/
|
*/
|
||||||
void add_connect_port_allowed (int port, vector_t *connect_ports)
|
void add_connect_port_allowed (int port, vector_t * connect_ports)
|
||||||
{
|
{
|
||||||
if (!*connect_ports) {
|
if (!*connect_ports) {
|
||||||
*connect_ports = vector_create ();
|
*connect_ports = vector_create ();
|
||||||
@ -53,8 +53,8 @@ int check_allowed_connect_ports (int port, vector_t connect_ports)
|
|||||||
int *data;
|
int *data;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The absence of ConnectPort options in the config file
|
* The absence of ConnectPort options in the config file
|
||||||
* meanas that all ports are allowed for CONNECT.
|
* meanas that all ports are allowed for CONNECT.
|
||||||
*/
|
*/
|
||||||
if (!connect_ports)
|
if (!connect_ports)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
extern void add_connect_port_allowed (int port, vector_t *connect_ports);
|
extern void add_connect_port_allowed (int port, vector_t * connect_ports);
|
||||||
int check_allowed_connect_ports (int port, vector_t connect_ports);
|
int check_allowed_connect_ports (int port, vector_t connect_ports);
|
||||||
void free_connect_ports_list (vector_t connect_ports);
|
void free_connect_ports_list (vector_t connect_ports);
|
||||||
|
|
||||||
|
@ -41,10 +41,9 @@ void makedaemon (void)
|
|||||||
if (fork () != 0)
|
if (fork () != 0)
|
||||||
exit (0);
|
exit (0);
|
||||||
|
|
||||||
if (chdir ("/") != 0) {
|
if (chdir ("/") != 0) {
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING, "Could not change directory to /");
|
||||||
"Could not change directory to /");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
umask (0177);
|
umask (0177);
|
||||||
|
|
||||||
|
10
src/filter.c
10
src/filter.c
@ -104,13 +104,11 @@ void filter_init (void)
|
|||||||
if (*s == '\0')
|
if (*s == '\0')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!p) /* head of list */
|
if (!p) /* head of list */
|
||||||
fl = p =
|
fl = p = (struct filter_list *)
|
||||||
(struct filter_list *)
|
|
||||||
safecalloc (1, sizeof (struct filter_list));
|
safecalloc (1, sizeof (struct filter_list));
|
||||||
else { /* next entry */
|
else { /* next entry */
|
||||||
p->next =
|
p->next = (struct filter_list *)
|
||||||
(struct filter_list *)
|
|
||||||
safecalloc (1, sizeof (struct filter_list));
|
safecalloc (1, sizeof (struct filter_list));
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ hashmap_t hashmap_create (unsigned int nbuckets)
|
|||||||
if (!ptr)
|
if (!ptr)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ptr->seed = (uint32_t)rand();
|
ptr->seed = (uint32_t) rand ();
|
||||||
ptr->size = nbuckets;
|
ptr->size = nbuckets;
|
||||||
ptr->buckets = (struct hashbucket_s *) safecalloc (nbuckets,
|
ptr->buckets = (struct hashbucket_s *) safecalloc (nbuckets,
|
||||||
sizeof (struct
|
sizeof (struct
|
||||||
@ -508,8 +508,7 @@ char *lookup_variable (hashmap_t map, const char *varname)
|
|||||||
if (hashmap_is_end (map, result_iter))
|
if (hashmap_is_end (map, result_iter))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
if (hashmap_return_entry (map, result_iter,
|
if (hashmap_return_entry (map, result_iter, &key, (void **) &data) < 0)
|
||||||
&key, (void **) &data) < 0)
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
return (data);
|
return (data);
|
||||||
|
20
src/heap.h
20
src/heap.h
@ -36,19 +36,19 @@ extern void *debugging_realloc (void *ptr, size_t size, const char *file,
|
|||||||
extern char *debugging_strdup (const char *s, const char *file,
|
extern char *debugging_strdup (const char *s, const char *file,
|
||||||
unsigned long line);
|
unsigned long line);
|
||||||
|
|
||||||
# define safecalloc(x, y) debugging_calloc(x, y, __FILE__, __LINE__)
|
#define safecalloc(x, y) debugging_calloc(x, y, __FILE__, __LINE__)
|
||||||
# define safemalloc(x) debugging_malloc(x, __FILE__, __LINE__)
|
#define safemalloc(x) debugging_malloc(x, __FILE__, __LINE__)
|
||||||
# define saferealloc(x, y) debugging_realloc(x, y, __FILE__, __LINE__)
|
#define saferealloc(x, y) debugging_realloc(x, y, __FILE__, __LINE__)
|
||||||
# define safestrdup(x) debugging_strdup(x, __FILE__, __LINE__)
|
#define safestrdup(x) debugging_strdup(x, __FILE__, __LINE__)
|
||||||
# define safefree(x) (debugging_free(x, __FILE__, __LINE__), *(&(x)) = NULL)
|
#define safefree(x) (debugging_free(x, __FILE__, __LINE__), *(&(x)) = NULL)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
# define safecalloc(x, y) calloc(x, y)
|
#define safecalloc(x, y) calloc(x, y)
|
||||||
# define safemalloc(x) malloc(x)
|
#define safemalloc(x) malloc(x)
|
||||||
# define saferealloc(x, y) realloc(x, y)
|
#define saferealloc(x, y) realloc(x, y)
|
||||||
# define safefree(x) (free (x), *(&(x)) = NULL)
|
#define safefree(x) (free (x), *(&(x)) = NULL)
|
||||||
# define safestrdup(x) strdup(x)
|
#define safestrdup(x) strdup(x)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -86,8 +86,7 @@ static char *get_html_file (unsigned int errornum)
|
|||||||
/*
|
/*
|
||||||
* Send an already-opened file to the client with variable substitution.
|
* Send an already-opened file to the client with variable substitution.
|
||||||
*/
|
*/
|
||||||
int
|
int send_html_file (FILE * infile, struct conn_s *connptr)
|
||||||
send_html_file (FILE *infile, struct conn_s *connptr)
|
|
||||||
{
|
{
|
||||||
char *inbuf;
|
char *inbuf;
|
||||||
char *varstart = NULL;
|
char *varstart = NULL;
|
||||||
@ -105,8 +104,9 @@ send_html_file (FILE *infile, struct conn_s *connptr)
|
|||||||
if (in_variable) {
|
if (in_variable) {
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
varval = (const char *)
|
varval = (const char *)
|
||||||
lookup_variable (connptr->error_variables,
|
lookup_variable
|
||||||
varstart);
|
(connptr->error_variables,
|
||||||
|
varstart);
|
||||||
if (!varval)
|
if (!varval)
|
||||||
varval = "(unknown)";
|
varval = "(unknown)";
|
||||||
r = write_message (connptr->client_fd,
|
r = write_message (connptr->client_fd,
|
||||||
@ -160,25 +160,21 @@ int send_http_headers (struct conn_s *connptr, int code, const char *message)
|
|||||||
const char headers[] =
|
const char headers[] =
|
||||||
"HTTP/1.0 %d %s\r\n"
|
"HTTP/1.0 %d %s\r\n"
|
||||||
"Server: %s/%s\r\n"
|
"Server: %s/%s\r\n"
|
||||||
"Content-Type: text/html\r\n"
|
"Content-Type: text/html\r\n" "%s" "Connection: close\r\n" "\r\n";
|
||||||
"%s"
|
|
||||||
"Connection: close\r\n" "\r\n";
|
|
||||||
|
|
||||||
const char p_auth_str[] =
|
const char p_auth_str[] =
|
||||||
"Proxy-Authenticate: Basic realm=\""
|
"Proxy-Authenticate: Basic realm=\"" PACKAGE_NAME "\"\r\n";
|
||||||
PACKAGE_NAME "\"\r\n";
|
|
||||||
|
|
||||||
const char w_auth_str[] =
|
const char w_auth_str[] =
|
||||||
"WWW-Authenticate: Basic realm=\""
|
"WWW-Authenticate: Basic realm=\"" PACKAGE_NAME "\"\r\n";
|
||||||
PACKAGE_NAME "\"\r\n";
|
|
||||||
|
|
||||||
/* according to rfc7235, the 407 error must be accompanied by
|
/* according to rfc7235, the 407 error must be accompanied by
|
||||||
a Proxy-Authenticate header field. */
|
* a Proxy-Authenticate header field. */
|
||||||
const char *add = code == 407 ? p_auth_str : (code == 401 ? w_auth_str : "");
|
const char *add =
|
||||||
|
code == 407 ? p_auth_str : (code == 401 ? w_auth_str : "");
|
||||||
|
|
||||||
return (write_message (connptr->client_fd, headers,
|
return (write_message (connptr->client_fd, headers,
|
||||||
code, message, PACKAGE, VERSION,
|
code, message, PACKAGE, VERSION, add));
|
||||||
add));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -207,12 +203,12 @@ int send_http_error_message (struct conn_s *connptr)
|
|||||||
|
|
||||||
error_file = get_html_file (connptr->error_number);
|
error_file = get_html_file (connptr->error_number);
|
||||||
if (!(infile = fopen (error_file, "r"))) {
|
if (!(infile = fopen (error_file, "r"))) {
|
||||||
char *detail = lookup_variable (connptr->error_variables, "detail");
|
char *detail =
|
||||||
return (write_message (connptr->client_fd, fallback_error,
|
lookup_variable (connptr->error_variables, "detail");
|
||||||
connptr->error_number,
|
return (write_message
|
||||||
connptr->error_string,
|
(connptr->client_fd, fallback_error,
|
||||||
connptr->error_string,
|
connptr->error_number, connptr->error_string,
|
||||||
detail, PACKAGE, VERSION));
|
connptr->error_string, detail, PACKAGE, VERSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = send_html_file (infile, connptr);
|
ret = send_html_file (infile, connptr);
|
||||||
@ -274,8 +270,7 @@ int add_standard_vars (struct conn_s *connptr)
|
|||||||
gmtime (&global_time));
|
gmtime (&global_time));
|
||||||
add_error_variable (connptr, "date", timebuf);
|
add_error_variable (connptr, "date", timebuf);
|
||||||
|
|
||||||
add_error_variable (connptr, "website",
|
add_error_variable (connptr, "website", "https://tinyproxy.github.io/");
|
||||||
"https://tinyproxy.github.io/");
|
|
||||||
add_error_variable (connptr, "version", VERSION);
|
add_error_variable (connptr, "version", VERSION);
|
||||||
add_error_variable (connptr, "package", PACKAGE);
|
add_error_variable (connptr, "package", PACKAGE);
|
||||||
|
|
||||||
|
32
src/log.c
32
src/log.c
@ -63,7 +63,7 @@ static int log_level = LOG_INFO;
|
|||||||
*/
|
*/
|
||||||
static vector_t log_message_storage;
|
static vector_t log_message_storage;
|
||||||
|
|
||||||
static unsigned int logging_initialized = FALSE; /* boolean */
|
static unsigned int logging_initialized = FALSE; /* boolean */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the log file and store the file descriptor in a global location.
|
* Open the log file and store the file descriptor in a global location.
|
||||||
@ -71,8 +71,8 @@ static unsigned int logging_initialized = FALSE; /* boolean */
|
|||||||
int open_log_file (const char *log_file_name)
|
int open_log_file (const char *log_file_name)
|
||||||
{
|
{
|
||||||
if (log_file_name == NULL) {
|
if (log_file_name == NULL) {
|
||||||
if(config.godaemon == FALSE)
|
if (config.godaemon == FALSE)
|
||||||
log_file_fd = fileno(stdout);
|
log_file_fd = fileno (stdout);
|
||||||
else
|
else
|
||||||
log_file_fd = -1;
|
log_file_fd = -1;
|
||||||
} else {
|
} else {
|
||||||
@ -86,7 +86,7 @@ int open_log_file (const char *log_file_name)
|
|||||||
*/
|
*/
|
||||||
void close_log_file (void)
|
void close_log_file (void)
|
||||||
{
|
{
|
||||||
if (log_file_fd < 0 || log_file_fd == fileno(stdout)) {
|
if (log_file_fd < 0 || log_file_fd == fileno (stdout)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ void log_message (int level, const char *fmt, ...)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!config.syslog && log_file_fd == -1)
|
if (!config.syslog && log_file_fd == -1)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (config.syslog) {
|
if (config.syslog) {
|
||||||
@ -187,12 +187,12 @@ void log_message (int level, const char *fmt, ...)
|
|||||||
* Overwrite the '\0' and leave room for a trailing '\n'
|
* Overwrite the '\0' and leave room for a trailing '\n'
|
||||||
* be added next.
|
* be added next.
|
||||||
*/
|
*/
|
||||||
p = str + strlen(str);
|
p = str + strlen (str);
|
||||||
vsnprintf (p, STRING_LENGTH - strlen(str) - 1, fmt, args);
|
vsnprintf (p, STRING_LENGTH - strlen (str) - 1, fmt, args);
|
||||||
|
|
||||||
p = str + strlen(str);
|
p = str + strlen (str);
|
||||||
*p = '\n';
|
*p = '\n';
|
||||||
*(p+1) = '\0';
|
*(p + 1) = '\0';
|
||||||
|
|
||||||
assert (log_file_fd >= 0);
|
assert (log_file_fd >= 0);
|
||||||
|
|
||||||
@ -200,11 +200,11 @@ void log_message (int level, const char *fmt, ...)
|
|||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
config.syslog = TRUE;
|
config.syslog = TRUE;
|
||||||
|
|
||||||
log_message(LOG_CRIT, "ERROR: Could not write to log "
|
log_message (LOG_CRIT, "ERROR: Could not write to log "
|
||||||
"file %s: %s.",
|
"file %s: %s.",
|
||||||
config.logf_name, strerror(errno));
|
config.logf_name, strerror (errno));
|
||||||
log_message(LOG_CRIT,
|
log_message (LOG_CRIT,
|
||||||
"Falling back to syslog logging");
|
"Falling back to syslog logging");
|
||||||
}
|
}
|
||||||
|
|
||||||
fsync (log_file_fd);
|
fsync (log_file_fd);
|
||||||
@ -227,7 +227,7 @@ static void send_stored_logs (void)
|
|||||||
if (log_message_storage == NULL)
|
if (log_message_storage == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
log_message(LOG_DEBUG, "sending stored logs");
|
log_message (LOG_DEBUG, "sending stored logs");
|
||||||
|
|
||||||
for (i = 0; (ssize_t) i != vector_length (log_message_storage); ++i) {
|
for (i = 0; (ssize_t) i != vector_length (log_message_storage); ++i) {
|
||||||
string =
|
string =
|
||||||
@ -252,7 +252,7 @@ static void send_stored_logs (void)
|
|||||||
vector_delete (log_message_storage);
|
vector_delete (log_message_storage);
|
||||||
log_message_storage = NULL;
|
log_message_storage = NULL;
|
||||||
|
|
||||||
log_message(LOG_DEBUG, "done sending stored logs");
|
log_message (LOG_DEBUG, "done sending stored logs");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
10
src/log.h
10
src/log.h
@ -24,7 +24,7 @@
|
|||||||
#define TINYPROXY_LOG_H
|
#define TINYPROXY_LOG_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -92,13 +92,13 @@
|
|||||||
* DEBUG2("There was a big problem: %s in connptr %p", "hello", connptr);
|
* DEBUG2("There was a big problem: %s in connptr %p", "hello", connptr);
|
||||||
*/
|
*/
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
# define DEBUG1(x) \
|
#define DEBUG1(x) \
|
||||||
log_message(LOG_DEBUG, "[%s:%d] " x, __FILE__, __LINE__)
|
log_message(LOG_DEBUG, "[%s:%d] " x, __FILE__, __LINE__)
|
||||||
# define DEBUG2(x, y...) \
|
#define DEBUG2(x, y...) \
|
||||||
log_message(LOG_DEBUG, "[%s:%d] " x, __FILE__, __LINE__, ## y)
|
log_message(LOG_DEBUG, "[%s:%d] " x, __FILE__, __LINE__, ## y)
|
||||||
#else
|
#else
|
||||||
# define DEBUG1(x) do { } while(0)
|
#define DEBUG1(x) do { } while(0)
|
||||||
# define DEBUG2(x, y...) do { } while(0)
|
#define DEBUG2(x, y...) do { } while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int open_log_file (const char *file);
|
extern int open_log_file (const char *file);
|
||||||
|
42
src/main.c
42
src/main.c
@ -54,8 +54,7 @@ unsigned int received_sighup = FALSE; /* boolean */
|
|||||||
/*
|
/*
|
||||||
* Handle a signal
|
* Handle a signal
|
||||||
*/
|
*/
|
||||||
static void
|
static void takesig (int sig)
|
||||||
takesig (int sig)
|
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int status;
|
int status;
|
||||||
@ -80,8 +79,7 @@ takesig (int sig)
|
|||||||
/*
|
/*
|
||||||
* Display the version information for the user.
|
* Display the version information for the user.
|
||||||
*/
|
*/
|
||||||
static void
|
static void display_version (void)
|
||||||
display_version (void)
|
|
||||||
{
|
{
|
||||||
printf ("%s %s\n", PACKAGE, VERSION);
|
printf ("%s %s\n", PACKAGE, VERSION);
|
||||||
}
|
}
|
||||||
@ -89,8 +87,7 @@ display_version (void)
|
|||||||
/*
|
/*
|
||||||
* Display usage to the user.
|
* Display usage to the user.
|
||||||
*/
|
*/
|
||||||
static void
|
static void display_usage (void)
|
||||||
display_usage (void)
|
|
||||||
{
|
{
|
||||||
int features = 0;
|
int features = 0;
|
||||||
|
|
||||||
@ -143,8 +140,7 @@ display_usage (void)
|
|||||||
"<https://tinyproxy.github.io/>.\n");
|
"<https://tinyproxy.github.io/>.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int get_id (char *str)
|
||||||
get_id (char *str)
|
|
||||||
{
|
{
|
||||||
char *tstr;
|
char *tstr;
|
||||||
|
|
||||||
@ -168,8 +164,7 @@ get_id (char *str)
|
|||||||
*
|
*
|
||||||
* This function parses command line arguments.
|
* This function parses command line arguments.
|
||||||
**/
|
**/
|
||||||
static void
|
static void process_cmdline (int argc, char **argv, struct config_s *conf)
|
||||||
process_cmdline (int argc, char **argv, struct config_s *conf)
|
|
||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
@ -215,8 +210,7 @@ process_cmdline (int argc, char **argv, struct config_s *conf)
|
|||||||
* the config file. This function is typically called during
|
* the config file. This function is typically called during
|
||||||
* initialization when the effective user is root.
|
* initialization when the effective user is root.
|
||||||
**/
|
**/
|
||||||
static void
|
static void change_user (const char *program)
|
||||||
change_user (const char *program)
|
|
||||||
{
|
{
|
||||||
if (config.group && strlen (config.group) > 0) {
|
if (config.group && strlen (config.group) > 0) {
|
||||||
int gid = get_id (config.group);
|
int gid = get_id (config.group);
|
||||||
@ -240,7 +234,6 @@ change_user (const char *program)
|
|||||||
program, config.group);
|
program, config.group);
|
||||||
exit (EX_NOPERM);
|
exit (EX_NOPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SETGROUPS
|
#ifdef HAVE_SETGROUPS
|
||||||
/* Drop all supplementary groups, otherwise these are inherited from the calling process */
|
/* Drop all supplementary groups, otherwise these are inherited from the calling process */
|
||||||
if (setgroups (0, NULL) < 0) {
|
if (setgroups (0, NULL) < 0) {
|
||||||
@ -285,7 +278,7 @@ change_user (const char *program)
|
|||||||
|
|
||||||
static void initialize_config_defaults (struct config_s *conf)
|
static void initialize_config_defaults (struct config_s *conf)
|
||||||
{
|
{
|
||||||
memset (conf, 0, sizeof(*conf));
|
memset (conf, 0, sizeof (*conf));
|
||||||
|
|
||||||
conf->config_file = safestrdup (SYSCONFDIR "/tinyproxy.conf");
|
conf->config_file = safestrdup (SYSCONFDIR "/tinyproxy.conf");
|
||||||
if (!conf->config_file) {
|
if (!conf->config_file) {
|
||||||
@ -300,6 +293,9 @@ static void initialize_config_defaults (struct config_s *conf)
|
|||||||
conf->errorpages = NULL;
|
conf->errorpages = NULL;
|
||||||
conf->stathost = safestrdup (TINYPROXY_STATHOST);
|
conf->stathost = safestrdup (TINYPROXY_STATHOST);
|
||||||
conf->idletimeout = MAX_IDLE_TIME;
|
conf->idletimeout = MAX_IDLE_TIME;
|
||||||
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
conf->deadtime = MAX_DEAD_TIME;
|
||||||
|
#endif
|
||||||
conf->logf_name = NULL;
|
conf->logf_name = NULL;
|
||||||
conf->pidpath = NULL;
|
conf->pidpath = NULL;
|
||||||
}
|
}
|
||||||
@ -326,8 +322,7 @@ done:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int main (int argc, char **argv)
|
||||||
main (int argc, char **argv)
|
|
||||||
{
|
{
|
||||||
/* Only allow u+rw bits. This may be required for some versions
|
/* Only allow u+rw bits. This may be required for some versions
|
||||||
* of glibc so that mkstemp() doesn't make us vulnerable.
|
* of glibc so that mkstemp() doesn't make us vulnerable.
|
||||||
@ -336,7 +331,7 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
log_message (LOG_INFO, "Initializing " PACKAGE " ...");
|
log_message (LOG_INFO, "Initializing " PACKAGE " ...");
|
||||||
|
|
||||||
if (config_compile_regex()) {
|
if (config_compile_regex ()) {
|
||||||
exit (EX_SOFTWARE);
|
exit (EX_SOFTWARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,8 +339,7 @@ main (int argc, char **argv)
|
|||||||
process_cmdline (argc, argv, &config_defaults);
|
process_cmdline (argc, argv, &config_defaults);
|
||||||
|
|
||||||
if (reload_config_file (config_defaults.config_file,
|
if (reload_config_file (config_defaults.config_file,
|
||||||
&config,
|
&config, &config_defaults)) {
|
||||||
&config_defaults)) {
|
|
||||||
exit (EX_SOFTWARE);
|
exit (EX_SOFTWARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,8 +356,8 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
if (config.godaemon == TRUE) {
|
if (config.godaemon == TRUE) {
|
||||||
if (!config.syslog && config.logf_name == NULL)
|
if (!config.syslog && config.logf_name == NULL)
|
||||||
fprintf(stderr, "WARNING: logging deactivated "
|
fprintf (stderr, "WARNING: logging deactivated "
|
||||||
"(can't log to stdout when daemonized)\n");
|
"(can't log to stdout when daemonized)\n");
|
||||||
|
|
||||||
makedaemon ();
|
makedaemon ();
|
||||||
}
|
}
|
||||||
@ -373,14 +367,13 @@ main (int argc, char **argv)
|
|||||||
argv[0]);
|
argv[0]);
|
||||||
exit (EX_OSERR);
|
exit (EX_OSERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FILTER_ENABLE
|
#ifdef FILTER_ENABLE
|
||||||
if (config.filter)
|
if (config.filter)
|
||||||
filter_init ();
|
filter_init ();
|
||||||
#endif /* FILTER_ENABLE */
|
#endif /* FILTER_ENABLE */
|
||||||
|
|
||||||
/* Start listening on the selected port. */
|
/* Start listening on the selected port. */
|
||||||
if (child_listening_sockets(config.listen_addrs, config.port) < 0) {
|
if (child_listening_sockets (config.listen_addrs, config.port) < 0) {
|
||||||
fprintf (stderr, "%s: Could not create listening sockets.\n",
|
fprintf (stderr, "%s: Could not create listening sockets.\n",
|
||||||
argv[0]);
|
argv[0]);
|
||||||
exit (EX_OSERR);
|
exit (EX_OSERR);
|
||||||
@ -451,12 +444,13 @@ main (int argc, char **argv)
|
|||||||
"Could not remove PID file \"%s\": %s.",
|
"Could not remove PID file \"%s\": %s.",
|
||||||
config.pidpath, strerror (errno));
|
config.pidpath, strerror (errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FILTER_ENABLE
|
#ifdef FILTER_ENABLE
|
||||||
if (config.filter)
|
if (config.filter)
|
||||||
filter_destroy ();
|
filter_destroy ();
|
||||||
#endif /* FILTER_ENABLE */
|
#endif /* FILTER_ENABLE */
|
||||||
|
|
||||||
|
free_config (&config);
|
||||||
|
|
||||||
shutdown_logging ();
|
shutdown_logging ();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
@ -27,6 +27,9 @@
|
|||||||
/* Global variables for the main controls of the program */
|
/* Global variables for the main controls of the program */
|
||||||
#define MAXBUFFSIZE ((size_t)(1024 * 96)) /* Max size of buffer */
|
#define MAXBUFFSIZE ((size_t)(1024 * 96)) /* Max size of buffer */
|
||||||
#define MAX_IDLE_TIME (60 * 10) /* 10 minutes of no activity */
|
#define MAX_IDLE_TIME (60 * 10) /* 10 minutes of no activity */
|
||||||
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
#define MAX_DEAD_TIME (60 * 10) /* 10 minutes of no activity */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Global Structures used in the program */
|
/* Global Structures used in the program */
|
||||||
extern struct config_s config;
|
extern struct config_s config;
|
||||||
|
@ -36,7 +36,7 @@ ssize_t safe_write (int fd, const void *buf, size_t count)
|
|||||||
{
|
{
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
size_t bytestosend;
|
size_t bytestosend;
|
||||||
const char *buffer = buf;
|
const char *buffer = buf;
|
||||||
|
|
||||||
assert (fd >= 0);
|
assert (fd >= 0);
|
||||||
assert (buffer != NULL);
|
assert (buffer != NULL);
|
||||||
@ -204,8 +204,7 @@ ssize_t readline (int fd, char **whole_buffer)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
line_ptr->next =
|
line_ptr->next = (struct read_lines_s *)
|
||||||
(struct read_lines_s *)
|
|
||||||
safecalloc (sizeof (struct read_lines_s), 1);
|
safecalloc (sizeof (struct read_lines_s), 1);
|
||||||
if (!line_ptr->next) {
|
if (!line_ptr->next) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
39
src/reqs.c
39
src/reqs.c
@ -1417,12 +1417,13 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request)
|
|||||||
*/
|
*/
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
#else
|
||||||
|
struct upstream_proxy_list *upp;
|
||||||
char *combined_string;
|
char *combined_string;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
struct upstream *cur_upstream = connptr->upstream_proxy;
|
struct upstream *cur_upstream = connptr->upstream_proxy;
|
||||||
|
|
||||||
if (!cur_upstream) {
|
if (!cur_upstream || !cur_upstream->plist) {
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"No upstream proxy defined for %s.",
|
"No upstream proxy defined for %s.",
|
||||||
request->host);
|
request->host);
|
||||||
@ -1431,11 +1432,39 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
connptr->server_fd =
|
upp = cur_upstream->plist;
|
||||||
opensock (cur_upstream->host, cur_upstream->port,
|
while (upp) {
|
||||||
connptr->server_ip_addr);
|
double tdiff;
|
||||||
|
if (upp->last_failed_connect > 0) {
|
||||||
|
tdiff =
|
||||||
|
difftime (time (NULL), upp->last_failed_connect);
|
||||||
|
if (tdiff < config.deadtime) {
|
||||||
|
log_message (LOG_INFO,
|
||||||
|
"Won't try to connect to upstream "
|
||||||
|
"proxy %s:%d during dead time.",
|
||||||
|
upp->host, upp->port);
|
||||||
|
upp = upp->next;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
upp->last_failed_connect = (time_t) 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connptr->server_fd =
|
||||||
|
opensock (upp->host, upp->port, connptr->server_ip_addr);
|
||||||
|
|
||||||
if (connptr->server_fd < 0) {
|
if (connptr->server_fd < 0) {
|
||||||
|
log_message (LOG_WARNING,
|
||||||
|
"Could not connect to upstream proxy. "
|
||||||
|
"Try next in list if available.");
|
||||||
|
upp->last_failed_connect = time (NULL);
|
||||||
|
} else {
|
||||||
|
cur_upstream->host = upp->host;
|
||||||
|
cur_upstream->port = upp->port;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
upp = upp->next;
|
||||||
|
}
|
||||||
|
if (!upp || connptr->server_fd < 0) {
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Could not connect to upstream proxy.");
|
"Could not connect to upstream proxy.");
|
||||||
indicate_http_error (connptr, 404,
|
indicate_http_error (connptr, 404,
|
||||||
|
@ -139,13 +139,10 @@ char *reverse_rewrite_url (struct conn_s *connptr, hashmap_t hashofheaders,
|
|||||||
&& (reverse =
|
&& (reverse =
|
||||||
reversepath_get (cookieval +
|
reversepath_get (cookieval +
|
||||||
strlen (REVERSE_COOKIE) + 1,
|
strlen (REVERSE_COOKIE) + 1,
|
||||||
config.reversepath_list)))
|
config.reversepath_list))) {
|
||||||
{
|
|
||||||
|
|
||||||
rewrite_url = (char *) safemalloc
|
rewrite_url = (char *) safemalloc
|
||||||
(strlen (url) +
|
(strlen (url) + strlen (reverse->url) + 1);
|
||||||
strlen (reverse->url) +
|
|
||||||
1);
|
|
||||||
strcpy (rewrite_url, reverse->url);
|
strcpy (rewrite_url, reverse->url);
|
||||||
strcat (rewrite_url, url + 1);
|
strcat (rewrite_url, url + 1);
|
||||||
|
|
||||||
|
101
src/sock.c
101
src/sock.c
@ -37,7 +37,7 @@
|
|||||||
/*
|
/*
|
||||||
* Return a human readable error for getaddrinfo() and getnameinfo().
|
* Return a human readable error for getaddrinfo() and getnameinfo().
|
||||||
*/
|
*/
|
||||||
static const char * get_gai_error (int n)
|
static const char *get_gai_error (int n)
|
||||||
{
|
{
|
||||||
if (n == EAI_SYSTEM)
|
if (n == EAI_SYSTEM)
|
||||||
return strerror (errno);
|
return strerror (errno);
|
||||||
@ -50,8 +50,7 @@ static const char * get_gai_error (int n)
|
|||||||
* returned if the bind succeeded. Otherwise, -1 is returned
|
* returned if the bind succeeded. Otherwise, -1 is returned
|
||||||
* to indicate an error.
|
* to indicate an error.
|
||||||
*/
|
*/
|
||||||
static int
|
static int bind_socket (int sockfd, const char *addr, int family)
|
||||||
bind_socket (int sockfd, const char *addr, int family)
|
|
||||||
{
|
{
|
||||||
struct addrinfo hints, *res, *ressave;
|
struct addrinfo hints, *res, *ressave;
|
||||||
int n;
|
int n;
|
||||||
@ -67,7 +66,8 @@ bind_socket (int sockfd, const char *addr, int family)
|
|||||||
n = getaddrinfo (addr, NULL, &hints, &res);
|
n = getaddrinfo (addr, NULL, &hints, &res);
|
||||||
if (n != 0) {
|
if (n != 0) {
|
||||||
log_message (LOG_INFO,
|
log_message (LOG_INFO,
|
||||||
"bind_socket: getaddrinfo failed for %s: ", addr, get_gai_error (n));
|
"bind_socket: getaddrinfo failed for %s: ", addr,
|
||||||
|
get_gai_error (n));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,8 +100,8 @@ int opensock (const char *host, int port, const char *bind_to)
|
|||||||
assert (host != NULL);
|
assert (host != NULL);
|
||||||
assert (port > 0);
|
assert (port > 0);
|
||||||
|
|
||||||
log_message(LOG_INFO,
|
log_message (LOG_INFO,
|
||||||
"opensock: opening connection to %s:%d", host, port);
|
"opensock: opening connection to %s:%d", host, port);
|
||||||
|
|
||||||
memset (&hints, 0, sizeof (struct addrinfo));
|
memset (&hints, 0, sizeof (struct addrinfo));
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
@ -112,12 +112,13 @@ int opensock (const char *host, int port, const char *bind_to)
|
|||||||
n = getaddrinfo (host, portstr, &hints, &res);
|
n = getaddrinfo (host, portstr, &hints, &res);
|
||||||
if (n != 0) {
|
if (n != 0) {
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"opensock: Could not retrieve address info for %s:%d: %s", host, port, get_gai_error (n));
|
"opensock: Could not retrieve address info for %s:%d: %s",
|
||||||
|
host, port, get_gai_error (n));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_message(LOG_INFO,
|
log_message (LOG_INFO,
|
||||||
"opensock: getaddrinfo returned for %s:%d", host, port);
|
"opensock: getaddrinfo returned for %s:%d", host, port);
|
||||||
|
|
||||||
ressave = res;
|
ressave = res;
|
||||||
do {
|
do {
|
||||||
@ -128,8 +129,7 @@ int opensock (const char *host, int port, const char *bind_to)
|
|||||||
|
|
||||||
/* Bind to the specified address */
|
/* Bind to the specified address */
|
||||||
if (bind_to) {
|
if (bind_to) {
|
||||||
if (bind_socket (sockfd, bind_to,
|
if (bind_socket (sockfd, bind_to, res->ai_family) < 0) {
|
||||||
res->ai_family) < 0) {
|
|
||||||
close (sockfd);
|
close (sockfd);
|
||||||
continue; /* can't bind, so try again */
|
continue; /* can't bind, so try again */
|
||||||
}
|
}
|
||||||
@ -151,8 +151,7 @@ int opensock (const char *host, int port, const char *bind_to)
|
|||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"opensock: Could not establish a connection to %s:%d",
|
"opensock: Could not establish a connection to %s:%d",
|
||||||
host,
|
host, port);
|
||||||
port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,14 +184,13 @@ int socket_blocking (int sock)
|
|||||||
return fcntl (sock, F_SETFL, flags & ~O_NONBLOCK);
|
return fcntl (sock, F_SETFL, flags & ~O_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to listen on one socket based on the addrinfo
|
* Try to listen on one socket based on the addrinfo
|
||||||
* as returned from getaddrinfo.
|
* as returned from getaddrinfo.
|
||||||
*
|
*
|
||||||
* Return the file descriptor upon success, -1 upon error.
|
* Return the file descriptor upon success, -1 upon error.
|
||||||
*/
|
*/
|
||||||
static int listen_on_one_socket(struct addrinfo *ad)
|
static int listen_on_one_socket (struct addrinfo *ad)
|
||||||
{
|
{
|
||||||
int listenfd;
|
int listenfd;
|
||||||
int ret;
|
int ret;
|
||||||
@ -200,59 +198,60 @@ static int listen_on_one_socket(struct addrinfo *ad)
|
|||||||
char numerichost[NI_MAXHOST];
|
char numerichost[NI_MAXHOST];
|
||||||
int flags = NI_NUMERICHOST;
|
int flags = NI_NUMERICHOST;
|
||||||
|
|
||||||
ret = getnameinfo(ad->ai_addr, ad->ai_addrlen,
|
ret = getnameinfo (ad->ai_addr, ad->ai_addrlen,
|
||||||
numerichost, NI_MAXHOST, NULL, 0, flags);
|
numerichost, NI_MAXHOST, NULL, 0, flags);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
log_message(LOG_ERR, "getnameinfo failed: %s", get_gai_error (ret));
|
log_message (LOG_ERR, "getnameinfo failed: %s",
|
||||||
|
get_gai_error (ret));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_message(LOG_INFO, "trying to listen on host[%s], family[%d], "
|
log_message (LOG_INFO, "trying to listen on host[%s], family[%d], "
|
||||||
"socktype[%d], proto[%d]", numerichost,
|
"socktype[%d], proto[%d]", numerichost,
|
||||||
ad->ai_family, ad->ai_socktype, ad->ai_protocol);
|
ad->ai_family, ad->ai_socktype, ad->ai_protocol);
|
||||||
|
|
||||||
listenfd = socket(ad->ai_family, ad->ai_socktype, ad->ai_protocol);
|
listenfd = socket (ad->ai_family, ad->ai_socktype, ad->ai_protocol);
|
||||||
if (listenfd == -1) {
|
if (listenfd == -1) {
|
||||||
log_message(LOG_ERR, "socket() failed: %s", strerror(errno));
|
log_message (LOG_ERR, "socket() failed: %s", strerror (errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
ret = setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on));
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
log_message(LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"setsockopt failed to set SO_REUSEADDR: %s",
|
"setsockopt failed to set SO_REUSEADDR: %s",
|
||||||
strerror(errno));
|
strerror (errno));
|
||||||
close(listenfd);
|
close (listenfd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ad->ai_family == AF_INET6) {
|
if (ad->ai_family == AF_INET6) {
|
||||||
ret = setsockopt(listenfd, IPPROTO_IPV6, IPV6_V6ONLY, &on,
|
ret = setsockopt (listenfd, IPPROTO_IPV6, IPV6_V6ONLY, &on,
|
||||||
sizeof(on));
|
sizeof (on));
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
log_message(LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"setsockopt failed to set IPV6_V6ONLY: %s",
|
"setsockopt failed to set IPV6_V6ONLY: %s",
|
||||||
strerror(errno));
|
strerror (errno));
|
||||||
close(listenfd);
|
close (listenfd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bind(listenfd, ad->ai_addr, ad->ai_addrlen);
|
ret = bind (listenfd, ad->ai_addr, ad->ai_addrlen);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
log_message(LOG_ERR, "bind failed: %s", strerror (errno));
|
log_message (LOG_ERR, "bind failed: %s", strerror (errno));
|
||||||
close(listenfd);
|
close (listenfd);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = listen(listenfd, MAXLISTEN);
|
|
||||||
if (ret != 0) {
|
|
||||||
log_message(LOG_ERR, "listen failed: %s", strerror(errno));
|
|
||||||
close(listenfd);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_message(LOG_INFO, "listening on fd [%d]", listenfd);
|
ret = listen (listenfd, MAXLISTEN);
|
||||||
|
if (ret != 0) {
|
||||||
|
log_message (LOG_ERR, "listen failed: %s", strerror (errno));
|
||||||
|
close (listenfd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_message (LOG_INFO, "listening on fd [%d]", listenfd);
|
||||||
|
|
||||||
return listenfd;
|
return listenfd;
|
||||||
}
|
}
|
||||||
@ -277,8 +276,8 @@ int listen_sock (const char *addr, uint16_t port, vector_t listen_fds)
|
|||||||
assert (port > 0);
|
assert (port > 0);
|
||||||
assert (listen_fds != NULL);
|
assert (listen_fds != NULL);
|
||||||
|
|
||||||
log_message(LOG_INFO, "listen_sock called with addr = '%s'",
|
log_message (LOG_INFO, "listen_sock called with addr = '%s'",
|
||||||
addr == NULL ? "(NULL)" : addr);
|
addr == NULL ? "(NULL)" : addr);
|
||||||
|
|
||||||
memset (&hints, 0, sizeof (struct addrinfo));
|
memset (&hints, 0, sizeof (struct addrinfo));
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
@ -291,21 +290,19 @@ int listen_sock (const char *addr, uint16_t port, vector_t listen_fds)
|
|||||||
if (n != 0) {
|
if (n != 0) {
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"Unable to getaddrinfo() for %s:%d because of %s",
|
"Unable to getaddrinfo() for %s:%d because of %s",
|
||||||
addr,
|
addr, port, get_gai_error (n));
|
||||||
port,
|
|
||||||
get_gai_error (n));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||||
int listenfd;
|
int listenfd;
|
||||||
|
|
||||||
listenfd = listen_on_one_socket(rp);
|
listenfd = listen_on_one_socket (rp);
|
||||||
if (listenfd == -1) {
|
if (listenfd == -1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector_append (listen_fds, &listenfd, sizeof(int));
|
vector_append (listen_fds, &listenfd, sizeof (int));
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
52
src/stats.c
52
src/stats.c
@ -59,8 +59,7 @@ void init_stats (void)
|
|||||||
/*
|
/*
|
||||||
* Display the statics of the tinyproxy server.
|
* Display the statics of the tinyproxy server.
|
||||||
*/
|
*/
|
||||||
int
|
int showstats (struct conn_s *connptr)
|
||||||
showstats (struct conn_s *connptr)
|
|
||||||
{
|
{
|
||||||
char *message_buffer;
|
char *message_buffer;
|
||||||
char opens[16], reqs[16], badconns[16], denied[16], refused[16];
|
char opens[16], reqs[16], badconns[16], denied[16], refused[16];
|
||||||
@ -78,32 +77,31 @@ showstats (struct conn_s *connptr)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
snprintf
|
snprintf
|
||||||
(message_buffer, MAXBUFFSIZE,
|
(message_buffer, MAXBUFFSIZE,
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
|
||||||
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" "
|
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" "
|
||||||
"\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
|
"\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
|
||||||
"<html>\n"
|
"<html>\n"
|
||||||
"<head><title>%s version %s run-time statistics</title></head>\n"
|
"<head><title>%s version %s run-time statistics</title></head>\n"
|
||||||
"<body>\n"
|
"<body>\n"
|
||||||
"<h1>%s version %s run-time statistics</h1>\n"
|
"<h1>%s version %s run-time statistics</h1>\n"
|
||||||
"<p>\n"
|
"<p>\n"
|
||||||
"Number of open connections: %lu<br />\n"
|
"Number of open connections: %lu<br />\n"
|
||||||
"Number of requests: %lu<br />\n"
|
"Number of requests: %lu<br />\n"
|
||||||
"Number of bad connections: %lu<br />\n"
|
"Number of bad connections: %lu<br />\n"
|
||||||
"Number of denied connections: %lu<br />\n"
|
"Number of denied connections: %lu<br />\n"
|
||||||
"Number of refused connections due to high load: %lu\n"
|
"Number of refused connections due to high load: %lu\n"
|
||||||
"</p>\n"
|
"</p>\n"
|
||||||
"<hr />\n"
|
"<hr />\n"
|
||||||
"<p><em>Generated by %s version %s.</em></p>\n" "</body>\n"
|
"<p><em>Generated by %s version %s.</em></p>\n" "</body>\n"
|
||||||
"</html>\n",
|
"</html>\n",
|
||||||
PACKAGE, VERSION, PACKAGE, VERSION,
|
PACKAGE, VERSION, PACKAGE, VERSION,
|
||||||
stats->num_open,
|
stats->num_open,
|
||||||
stats->num_reqs,
|
stats->num_reqs,
|
||||||
stats->num_badcons, stats->num_denied,
|
stats->num_badcons, stats->num_denied,
|
||||||
stats->num_refused, PACKAGE, VERSION);
|
stats->num_refused, PACKAGE, VERSION);
|
||||||
|
|
||||||
if (send_http_message (connptr, 200, "OK",
|
if (send_http_message (connptr, 200, "OK", message_buffer) < 0) {
|
||||||
message_buffer) < 0) {
|
|
||||||
safefree (message_buffer);
|
safefree (message_buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -111,21 +111,21 @@ do_transparent_proxy (struct conn_s *connptr, hashmap_t hashofheaders,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < vector_length(conf->listen_addrs); i++) {
|
for (i = 0; i < vector_length (conf->listen_addrs); i++) {
|
||||||
const char *addr;
|
const char *addr;
|
||||||
|
|
||||||
addr = (char *)vector_getentry(conf->listen_addrs, i, NULL);
|
addr = (char *) vector_getentry (conf->listen_addrs, i, NULL);
|
||||||
|
|
||||||
if (addr && strcmp(request->host, addr) == 0) {
|
if (addr && strcmp (request->host, addr) == 0) {
|
||||||
log_message(LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"transparent: destination IP %s is local "
|
"transparent: destination IP %s is local "
|
||||||
"on socket fd %d",
|
"on socket fd %d",
|
||||||
request->host, connptr->client_fd);
|
request->host, connptr->client_fd);
|
||||||
indicate_http_error(connptr, 400, "Bad Request",
|
indicate_http_error (connptr, 400, "Bad Request",
|
||||||
"detail",
|
"detail",
|
||||||
"You tried to connect to the "
|
"You tried to connect to the "
|
||||||
"machine the proxy is running on",
|
"machine the proxy is running on",
|
||||||
"url", *url, NULL);
|
"url", *url, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
136
src/upstream.c
136
src/upstream.c
@ -31,6 +31,25 @@
|
|||||||
#include "basicauth.h"
|
#include "basicauth.h"
|
||||||
|
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
|
static const char *proxy_list_name (struct upstream_proxy_list *plist)
|
||||||
|
{
|
||||||
|
#define MAXBUF ((size_t)(1024 * 96))
|
||||||
|
static char hostport[MAXBUF];
|
||||||
|
static char pbuffer[MAXBUF];
|
||||||
|
struct upstream_proxy_list *upl = plist;
|
||||||
|
|
||||||
|
bzero (&pbuffer, MAXBUF);
|
||||||
|
snprintf (pbuffer, MAXBUF, "%s:%d", upl->host, upl->port);
|
||||||
|
upl = upl->next;
|
||||||
|
while (upl) {
|
||||||
|
bzero (&hostport, MAXBUF);
|
||||||
|
snprintf (hostport, MAXBUF, "|%s:%d", upl->host, upl->port);
|
||||||
|
strncat (pbuffer, hostport, MAXBUF - strlen (hostport));
|
||||||
|
upl = upl->next;
|
||||||
|
}
|
||||||
|
return pbuffer;
|
||||||
|
}
|
||||||
|
|
||||||
const char *proxy_type_name (proxy_type type)
|
const char *proxy_type_name (proxy_type type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -47,15 +66,43 @@ const char *proxy_type_name (proxy_type type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct upstream_proxy_list *uplcpy (const struct upstream_proxy_list
|
||||||
|
*plist)
|
||||||
|
{
|
||||||
|
struct upstream_proxy_list *upr, *upp, *uptr;
|
||||||
|
|
||||||
|
if (!plist)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
upr = upp = (upstream_proxy_list_t *)
|
||||||
|
safemalloc (sizeof (upstream_proxy_list_t));
|
||||||
|
upp->host = safestrdup (plist->host);
|
||||||
|
upp->port = plist->port;
|
||||||
|
upp->last_failed_connect = plist->last_failed_connect;
|
||||||
|
upp->next = NULL;
|
||||||
|
uptr = plist->next;
|
||||||
|
while (uptr) {
|
||||||
|
upp->next = (upstream_proxy_list_t *)
|
||||||
|
safemalloc (sizeof (upstream_proxy_list_t));
|
||||||
|
upp = upp->next;
|
||||||
|
upp->host = safestrdup (uptr->host);
|
||||||
|
upp->port = uptr->port;
|
||||||
|
upp->next = NULL;
|
||||||
|
uptr = uptr->next;
|
||||||
|
}
|
||||||
|
return upr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an upstream struct from input data.
|
* Construct an upstream struct from input data.
|
||||||
*/
|
*/
|
||||||
static struct upstream *upstream_build (const char *host, int port,
|
static struct upstream *upstream_build (const struct upstream_proxy_list *plist,
|
||||||
const char *domain, const char *user,
|
const char *domain, const char *user,
|
||||||
const char *pass, proxy_type type)
|
const char *pass, proxy_type type)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
struct upstream *up;
|
struct upstream *up;
|
||||||
|
struct upstream_proxy_list *upp;
|
||||||
#ifdef UPSTREAM_REGEX
|
#ifdef UPSTREAM_REGEX
|
||||||
int cflags = REG_NEWLINE | REG_NOSUB;
|
int cflags = REG_NEWLINE | REG_NOSUB;
|
||||||
int rflag = 0;
|
int rflag = 0;
|
||||||
@ -70,7 +117,8 @@ static struct upstream *upstream_build (const char *host, int port,
|
|||||||
}
|
}
|
||||||
|
|
||||||
up->type = type;
|
up->type = type;
|
||||||
up->host = up->domain = up->ua.user = up->pass = NULL;
|
up->domain = up->ua.user = up->pass = NULL;
|
||||||
|
up->plist = NULL;
|
||||||
#ifdef UPSTREAM_REGEX
|
#ifdef UPSTREAM_REGEX
|
||||||
up->pat = NULL;
|
up->pat = NULL;
|
||||||
up->cpat = NULL;
|
up->cpat = NULL;
|
||||||
@ -124,18 +172,18 @@ static struct upstream *upstream_build (const char *host, int port,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (domain == NULL) {
|
if (domain == NULL) {
|
||||||
if (!host || host[0] == '\0' || port < 1) {
|
if (!plist || plist->host[0] == '\0' || plist->port < 1) {
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Nonsense upstream rule: invalid host or port");
|
"Nonsense upstream rule: invalid host or port");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
up->host = safestrdup (host);
|
up->plist = uplcpy (plist);
|
||||||
up->port = port;
|
|
||||||
|
|
||||||
log_message (LOG_INFO, "Added upstream %s %s:%d for [default]",
|
log_message (LOG_INFO, "Added upstream %s %s for [default]",
|
||||||
proxy_type_name (type), host, port);
|
proxy_type_name (type),
|
||||||
} else if (host == NULL || type == PT_NONE) {
|
proxy_list_name (up->plist));
|
||||||
|
} else if (plist == NULL || type == PT_NONE) {
|
||||||
if (!domain || domain[0] == '\0') {
|
if (!domain || domain[0] == '\0') {
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Nonsense no-upstream rule: empty domain");
|
"Nonsense no-upstream rule: empty domain");
|
||||||
@ -183,15 +231,14 @@ static struct upstream *upstream_build (const char *host, int port,
|
|||||||
|
|
||||||
log_message (LOG_INFO, "Added no-upstream for %s", domain);
|
log_message (LOG_INFO, "Added no-upstream for %s", domain);
|
||||||
} else {
|
} else {
|
||||||
if (!host || host[0] == '\0' || port < 1 || !domain
|
if (!plist || plist->host[0] == '\0' || plist->port < 1
|
||||||
|| domain[0] == '\0') {
|
|| !domain || domain[0] == '\0') {
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Nonsense upstream rule: invalid parameters");
|
"Nonsense upstream rule: invalid parameters");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
up->host = safestrdup (host);
|
up->plist = uplcpy (plist);
|
||||||
up->port = port;
|
|
||||||
up->domain = safestrdup (domain);
|
up->domain = safestrdup (domain);
|
||||||
#ifdef UPSTREAM_REGEX
|
#ifdef UPSTREAM_REGEX
|
||||||
if (rflag) {
|
if (rflag) {
|
||||||
@ -205,19 +252,29 @@ static struct upstream *upstream_build (const char *host, int port,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
log_message (LOG_INFO, "Added upstream %s %s:%d for %s",
|
log_message (LOG_INFO, "Added upstream %s %s for %s",
|
||||||
proxy_type_name (type), host, port, domain);
|
proxy_type_name (type),
|
||||||
|
proxy_list_name (up->plist), domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
return up;
|
return up;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
safefree (up->ua.user);
|
safefree (up->ua.user);
|
||||||
|
safefree (up->ua.authstr);
|
||||||
safefree (up->pass);
|
safefree (up->pass);
|
||||||
safefree (up->host);
|
upp = up->plist;
|
||||||
|
while (upp) {
|
||||||
|
struct upstream_proxy_list *tmpp = upp;
|
||||||
|
upp = upp->next;
|
||||||
|
safefree (tmpp->host);
|
||||||
|
safefree (tmpp);
|
||||||
|
}
|
||||||
safefree (up->domain);
|
safefree (up->domain);
|
||||||
#ifdef UPSTREAM_REGEX
|
#ifdef UPSTREAM_REGEX
|
||||||
safefree (up->pat);
|
safefree (up->pat);
|
||||||
|
if (up->cpat)
|
||||||
|
regfree (up->cpat);
|
||||||
safefree (up->cpat);
|
safefree (up->cpat);
|
||||||
#endif
|
#endif
|
||||||
safefree (up);
|
safefree (up);
|
||||||
@ -228,13 +285,14 @@ fail:
|
|||||||
/*
|
/*
|
||||||
* Add an entry to the upstream list
|
* Add an entry to the upstream list
|
||||||
*/
|
*/
|
||||||
void upstream_add (const char *host, int port, const char *domain,
|
void upstream_add (const struct upstream_proxy_list *plist, const char *domain,
|
||||||
const char *user, const char *pass,
|
const char *user, const char *pass,
|
||||||
proxy_type type, struct upstream **upstream_list)
|
proxy_type type, struct upstream **upstream_list)
|
||||||
{
|
{
|
||||||
struct upstream *up;
|
struct upstream *up;
|
||||||
|
struct upstream_proxy_list *upp;
|
||||||
|
|
||||||
up = upstream_build (host, port, domain, user, pass, type);
|
up = upstream_build (plist, domain, user, pass, type);
|
||||||
if (up == NULL) {
|
if (up == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -265,8 +323,23 @@ void upstream_add (const char *host, int port, const char *domain,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
upstream_cleanup:
|
upstream_cleanup:
|
||||||
safefree (up->host);
|
upp = up->plist;
|
||||||
|
while (upp) {
|
||||||
|
struct upstream_proxy_list *tmpp = upp;
|
||||||
|
upp = upp->next;
|
||||||
|
safefree (tmpp->host);
|
||||||
|
safefree (tmpp);
|
||||||
|
}
|
||||||
safefree (up->domain);
|
safefree (up->domain);
|
||||||
|
safefree (up->ua.user);
|
||||||
|
safefree (up->ua.authstr);
|
||||||
|
safefree (up->pass);
|
||||||
|
#ifdef UPSTREAM_REGEX
|
||||||
|
safefree (up->pat);
|
||||||
|
if (up->cpat)
|
||||||
|
regfree (up->cpat);
|
||||||
|
safefree (up->cpat);
|
||||||
|
#endif
|
||||||
safefree (up);
|
safefree (up);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -323,14 +396,14 @@ struct upstream *upstream_get (struct request_s *request, struct upstream *up)
|
|||||||
|
|
||||||
up = up->next;
|
up = up->next;
|
||||||
}
|
}
|
||||||
|
if (up && !up->plist)
|
||||||
if (up && (!up->host || !up->port))
|
|
||||||
up = NULL;
|
up = NULL;
|
||||||
|
|
||||||
if (up)
|
if (up)
|
||||||
log_message (LOG_INFO, "Found upstream proxy %s %s:%d for %s",
|
log_message (LOG_INFO,
|
||||||
proxy_type_name (up->type), up->host, up->port,
|
"Found upstream proxy/proxies %s %s for %s",
|
||||||
host);
|
proxy_type_name (up->type),
|
||||||
|
proxy_list_name (up->plist), host);
|
||||||
else
|
else
|
||||||
log_message (LOG_INFO, "No upstream proxy for %s", host);
|
log_message (LOG_INFO, "No upstream proxy for %s", host);
|
||||||
|
|
||||||
@ -341,9 +414,24 @@ void free_upstream_list (struct upstream *up)
|
|||||||
{
|
{
|
||||||
while (up) {
|
while (up) {
|
||||||
struct upstream *tmp = up;
|
struct upstream *tmp = up;
|
||||||
|
struct upstream_proxy_list *upp = up->plist;
|
||||||
up = up->next;
|
up = up->next;
|
||||||
|
while (upp) {
|
||||||
|
struct upstream_proxy_list *tmpp = upp;
|
||||||
|
upp = upp->next;
|
||||||
|
safefree (tmpp->host);
|
||||||
|
safefree (tmpp);
|
||||||
|
}
|
||||||
safefree (tmp->domain);
|
safefree (tmp->domain);
|
||||||
safefree (tmp->host);
|
safefree (tmp->ua.user);
|
||||||
|
safefree (tmp->ua.authstr);
|
||||||
|
safefree (tmp->pass);
|
||||||
|
#ifdef UPSTREAM_REGEX
|
||||||
|
safefree (tmp->pat);
|
||||||
|
if (tmp->cpat)
|
||||||
|
regfree (tmp->cpat);
|
||||||
|
safefree (tmp->cpat);
|
||||||
|
#endif
|
||||||
safefree (tmp);
|
safefree (tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,16 +39,25 @@ typedef enum proxy_type {
|
|||||||
PT_SOCKS5
|
PT_SOCKS5
|
||||||
} proxy_type;
|
} proxy_type;
|
||||||
|
|
||||||
|
typedef struct upstream_proxy_list {
|
||||||
|
struct upstream_proxy_list *next;
|
||||||
|
char *host;
|
||||||
|
int port;
|
||||||
|
time_t last_failed_connect;
|
||||||
|
|
||||||
|
} upstream_proxy_list_t;
|
||||||
|
|
||||||
struct upstream {
|
struct upstream {
|
||||||
struct upstream *next;
|
struct upstream *next;
|
||||||
char *domain; /* optional */
|
char *domain; /* optional */
|
||||||
|
struct upstream_proxy_list *plist;
|
||||||
char *host;
|
char *host;
|
||||||
|
int port;
|
||||||
union {
|
union {
|
||||||
char *user;
|
char *user;
|
||||||
char *authstr;
|
char *authstr;
|
||||||
} ua;
|
} ua;
|
||||||
char *pass;
|
char *pass;
|
||||||
int port;
|
|
||||||
in_addr_t ip, mask;
|
in_addr_t ip, mask;
|
||||||
proxy_type type;
|
proxy_type type;
|
||||||
#if defined(UPSTREAM_SUPPORT) && defined(UPSTREAM_REGEX)
|
#if defined(UPSTREAM_SUPPORT) && defined(UPSTREAM_REGEX)
|
||||||
@ -59,9 +68,10 @@ struct upstream {
|
|||||||
|
|
||||||
#ifdef UPSTREAM_SUPPORT
|
#ifdef UPSTREAM_SUPPORT
|
||||||
const char *proxy_type_name (proxy_type type);
|
const char *proxy_type_name (proxy_type type);
|
||||||
extern void upstream_add (const char *host, int port, const char *domain,
|
extern void upstream_add (const struct upstream_proxy_list *phost,
|
||||||
const char *user, const char *pass,
|
const char *domain, const char *user,
|
||||||
proxy_type type, struct upstream **upstream_list);
|
const char *pass, proxy_type type,
|
||||||
|
struct upstream **upstream_list);
|
||||||
extern struct upstream *upstream_get (struct request_s *request,
|
extern struct upstream *upstream_get (struct request_s *request,
|
||||||
struct upstream *up);
|
struct upstream *up);
|
||||||
extern void free_upstream_list (struct upstream *up);
|
extern void free_upstream_list (struct upstream *up);
|
||||||
|
@ -185,8 +185,7 @@ int create_file_safely (const char *filename, unsigned int truncate_file)
|
|||||||
*
|
*
|
||||||
* Returns: %0 on success, non-zero values on errors.
|
* Returns: %0 on success, non-zero values on errors.
|
||||||
**/
|
**/
|
||||||
int
|
int pidfile_create (const char *filename)
|
||||||
pidfile_create (const char *filename)
|
|
||||||
{
|
{
|
||||||
int fildes;
|
int fildes;
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
|
@ -111,10 +111,7 @@ typedef enum {
|
|||||||
} vector_pos_t;
|
} vector_pos_t;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vector_insert (vector_t vector,
|
vector_insert (vector_t vector, void *data, size_t len, vector_pos_t pos)
|
||||||
void *data,
|
|
||||||
size_t len,
|
|
||||||
vector_pos_t pos)
|
|
||||||
{
|
{
|
||||||
struct vectorentry_s *entry;
|
struct vectorentry_s *entry;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user