Reformat code to GNU coding style
This is a commit which simply ran all C source code files through GNU indent. No other modifications were made.
This commit is contained in:
parent
448c19077c
commit
a257703e59
83
src/acl.c
83
src/acl.c
@ -33,19 +33,23 @@
|
|||||||
/* Define how long an IPv6 address is in bytes (128 bits, 16 bytes) */
|
/* Define how long an IPv6 address is in bytes (128 bits, 16 bytes) */
|
||||||
#define IPV6_LEN 16
|
#define IPV6_LEN 16
|
||||||
|
|
||||||
enum acl_type { ACL_STRING, ACL_NUMERIC };
|
enum acl_type
|
||||||
|
{ ACL_STRING, ACL_NUMERIC };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hold the information about a particular access control. We store
|
* Hold the information about a particular access control. We store
|
||||||
* whether it's an ALLOW or DENY entry, and also whether it's a string
|
* whether it's an ALLOW or DENY entry, and also whether it's a string
|
||||||
* entry (like a domain name) or an IP entry.
|
* entry (like a domain name) or an IP entry.
|
||||||
*/
|
*/
|
||||||
struct acl_s {
|
struct acl_s
|
||||||
|
{
|
||||||
acl_access_t access;
|
acl_access_t access;
|
||||||
enum acl_type type;
|
enum acl_type type;
|
||||||
union {
|
union
|
||||||
|
{
|
||||||
char *string;
|
char *string;
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
unsigned char octet[IPV6_LEN];
|
unsigned char octet[IPV6_LEN];
|
||||||
unsigned char mask[IPV6_LEN];
|
unsigned char mask[IPV6_LEN];
|
||||||
} ip;
|
} ip;
|
||||||
@ -67,7 +71,8 @@ static vector_t access_list = NULL;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
inline static int
|
inline static int
|
||||||
fill_netmask_array(char *bitmask_string, unsigned char array[], unsigned int len)
|
fill_netmask_array (char *bitmask_string, unsigned char array[],
|
||||||
|
unsigned int len)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
long int mask;
|
long int mask;
|
||||||
@ -78,8 +83,7 @@ fill_netmask_array(char *bitmask_string, unsigned char array[], unsigned int len
|
|||||||
|
|
||||||
/* check for various conversion errors */
|
/* check for various conversion errors */
|
||||||
if ((errno == ERANGE && (mask == LONG_MIN || mask == LONG_MAX))
|
if ((errno == ERANGE && (mask == LONG_MIN || mask == LONG_MAX))
|
||||||
|| (errno != 0 && mask == 0)
|
|| (errno != 0 && mask == 0) || (endptr == bitmask_string))
|
||||||
|| (endptr == bitmask_string))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* valid range for a bit mask */
|
/* valid range for a bit mask */
|
||||||
@ -87,16 +91,20 @@ fill_netmask_array(char *bitmask_string, unsigned char array[], unsigned int len
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* we have a valid range to fill in the array */
|
/* we have a valid range to fill in the array */
|
||||||
for (i = 0; i != len; ++i) {
|
for (i = 0; i != len; ++i)
|
||||||
if (mask >= 8) {
|
{
|
||||||
|
if (mask >= 8)
|
||||||
|
{
|
||||||
array[i] = 0xff;
|
array[i] = 0xff;
|
||||||
mask -= 8;
|
mask -= 8;
|
||||||
}
|
}
|
||||||
else if (mask > 0) {
|
else if (mask > 0)
|
||||||
|
{
|
||||||
array[i] = (unsigned char) (0xff << (8 - mask));
|
array[i] = (unsigned char) (0xff << (8 - mask));
|
||||||
mask = 0;
|
mask = 0;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
array[i] = 0;
|
array[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,11 +134,12 @@ insert_acl(char *location, acl_access_t access_type)
|
|||||||
/*
|
/*
|
||||||
* If the access list has not been set up, create it.
|
* If the access list has not been set up, create it.
|
||||||
*/
|
*/
|
||||||
if (!access_list) {
|
if (!access_list)
|
||||||
|
{
|
||||||
access_list = vector_create ();
|
access_list = vector_create ();
|
||||||
if (!access_list) {
|
if (!access_list)
|
||||||
log_message(LOG_ERR,
|
{
|
||||||
"Unable to allocate memory for access list");
|
log_message (LOG_ERR, "Unable to allocate memory for access list");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,17 +153,21 @@ insert_acl(char *location, acl_access_t access_type)
|
|||||||
/*
|
/*
|
||||||
* Check for a valid IP address (the simplest case) first.
|
* Check for a valid IP address (the simplest case) first.
|
||||||
*/
|
*/
|
||||||
if (full_inet_pton(location, ip_dst) > 0) {
|
if (full_inet_pton (location, ip_dst) > 0)
|
||||||
|
{
|
||||||
acl.type = ACL_NUMERIC;
|
acl.type = ACL_NUMERIC;
|
||||||
memcpy (acl.address.ip.octet, ip_dst, IPV6_LEN);
|
memcpy (acl.address.ip.octet, ip_dst, IPV6_LEN);
|
||||||
memset (acl.address.ip.mask, 0xff, IPV6_LEN);
|
memset (acl.address.ip.mask, 0xff, IPV6_LEN);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* At this point we're either a hostname or an
|
* At this point we're either a hostname or an
|
||||||
* IP address with a slash.
|
* IP address with a slash.
|
||||||
*/
|
*/
|
||||||
p = strchr (location, '/');
|
p = strchr (location, '/');
|
||||||
if (p != NULL) {
|
if (p != NULL)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* We have a slash, so it's intended to be an
|
* We have a slash, so it's intended to be an
|
||||||
* IP address with mask
|
* IP address with mask
|
||||||
@ -166,9 +179,12 @@ insert_acl(char *location, acl_access_t access_type)
|
|||||||
acl.type = ACL_NUMERIC;
|
acl.type = ACL_NUMERIC;
|
||||||
memcpy (acl.address.ip.octet, ip_dst, IPV6_LEN);
|
memcpy (acl.address.ip.octet, ip_dst, IPV6_LEN);
|
||||||
|
|
||||||
if (fill_netmask_array(p + 1, &(acl.address.ip.mask[0]), IPV6_LEN) < 0)
|
if (fill_netmask_array (p + 1, &(acl.address.ip.mask[0]), IPV6_LEN)
|
||||||
|
< 0)
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* In all likelihood a string */
|
/* In all likelihood a string */
|
||||||
acl.type = ACL_STRING;
|
acl.type = ACL_STRING;
|
||||||
acl.address.string = safestrdup (location);
|
acl.address.string = safestrdup (location);
|
||||||
@ -212,7 +228,8 @@ acl_string_processing(struct acl_s *acl,
|
|||||||
* do a string based test only; otherwise, we can do a reverse
|
* do a string based test only; otherwise, we can do a reverse
|
||||||
* lookup test as well.
|
* lookup test as well.
|
||||||
*/
|
*/
|
||||||
if (acl->address.string[0] != '.') {
|
if (acl->address.string[0] != '.')
|
||||||
|
{
|
||||||
memset (&hints, 0, sizeof (struct addrinfo));
|
memset (&hints, 0, sizeof (struct addrinfo));
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
@ -222,17 +239,21 @@ acl_string_processing(struct acl_s *acl,
|
|||||||
ressave = res;
|
ressave = res;
|
||||||
|
|
||||||
match = FALSE;
|
match = FALSE;
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
get_ip_string (res->ai_addr, ipbuf, sizeof (ipbuf));
|
get_ip_string (res->ai_addr, ipbuf, sizeof (ipbuf));
|
||||||
if (strcmp(ip_address, ipbuf) == 0) {
|
if (strcmp (ip_address, ipbuf) == 0)
|
||||||
|
{
|
||||||
match = TRUE;
|
match = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while ((res = res->ai_next) != NULL);
|
}
|
||||||
|
while ((res = res->ai_next) != NULL);
|
||||||
|
|
||||||
freeaddrinfo (ressave);
|
freeaddrinfo (ressave);
|
||||||
|
|
||||||
if (match) {
|
if (match)
|
||||||
|
{
|
||||||
if (acl->access == ACL_DENY)
|
if (acl->access == ACL_DENY)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
@ -253,7 +274,8 @@ acl_string_processing(struct acl_s *acl,
|
|||||||
|
|
||||||
if (strcasecmp
|
if (strcasecmp
|
||||||
(string_address + (test_length - match_length),
|
(string_address + (test_length - match_length),
|
||||||
acl->address.string) == 0) {
|
acl->address.string) == 0)
|
||||||
|
{
|
||||||
if (acl->access == ACL_DENY)
|
if (acl->access == ACL_DENY)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
@ -284,7 +306,8 @@ check_numeric_acl(const struct acl_s *acl, const char *ip)
|
|||||||
if (full_inet_pton (ip, &addr) <= 0)
|
if (full_inet_pton (ip, &addr) <= 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (i = 0; i != IPV6_LEN; ++i) {
|
for (i = 0; i != IPV6_LEN; ++i)
|
||||||
|
{
|
||||||
x = addr[i] & acl->address.ip.mask[i];
|
x = addr[i] & acl->address.ip.mask[i];
|
||||||
y = acl->address.ip.octet[i] & acl->address.ip.mask[i];
|
y = acl->address.ip.octet[i] & acl->address.ip.mask[i];
|
||||||
|
|
||||||
@ -321,9 +344,11 @@ check_acl(int fd, const char *ip, const char *host)
|
|||||||
if (!access_list)
|
if (!access_list)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
for (i = 0; i != vector_length(access_list); ++i) {
|
for (i = 0; i != vector_length (access_list); ++i)
|
||||||
|
{
|
||||||
acl = vector_getentry (access_list, i, NULL);
|
acl = vector_getentry (access_list, i, NULL);
|
||||||
switch (acl->type) {
|
switch (acl->type)
|
||||||
|
{
|
||||||
case ACL_STRING:
|
case ACL_STRING:
|
||||||
perm = acl_string_processing (acl, ip, host);
|
perm = acl_string_processing (acl, ip, host);
|
||||||
break;
|
break;
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
#ifndef TINYPROXY_ACL_H
|
#ifndef TINYPROXY_ACL_H
|
||||||
#define TINYPROXY_ACL_H
|
#define TINYPROXY_ACL_H
|
||||||
|
|
||||||
typedef enum { ACL_ALLOW, ACL_DENY } acl_access_t;
|
typedef enum
|
||||||
|
{ ACL_ALLOW, ACL_DENY } acl_access_t;
|
||||||
|
|
||||||
extern int insert_acl (char *location, acl_access_t access_type);
|
extern int insert_acl (char *location, acl_access_t access_type);
|
||||||
extern int check_acl (int fd, const char *ip_address,
|
extern int check_acl (int fd, const char *ip_address,
|
||||||
|
@ -61,13 +61,15 @@ anonymous_insert(char *s)
|
|||||||
|
|
||||||
assert (s != NULL);
|
assert (s != NULL);
|
||||||
|
|
||||||
if (!anonymous_map) {
|
if (!anonymous_map)
|
||||||
|
{
|
||||||
anonymous_map = hashmap_create (32);
|
anonymous_map = hashmap_create (32);
|
||||||
if (!anonymous_map)
|
if (!anonymous_map)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hashmap_search(anonymous_map, s) > 0) {
|
if (hashmap_search (anonymous_map, s) > 0)
|
||||||
|
{
|
||||||
/* The key was already found, so return a positive number. */
|
/* The key was already found, so return a positive number. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
51
src/buffer.c
51
src/buffer.c
@ -34,7 +34,8 @@
|
|||||||
#define BUFFER_HEAD(x) (x)->head
|
#define BUFFER_HEAD(x) (x)->head
|
||||||
#define BUFFER_TAIL(x) (x)->tail
|
#define BUFFER_TAIL(x) (x)->tail
|
||||||
|
|
||||||
struct bufline_s {
|
struct bufline_s
|
||||||
|
{
|
||||||
unsigned char *string; /* the actual string of data */
|
unsigned char *string; /* the actual string of data */
|
||||||
struct bufline_s *next; /* pointer to next in linked list */
|
struct bufline_s *next; /* pointer to next in linked list */
|
||||||
size_t length; /* length of the string of data */
|
size_t length; /* length of the string of data */
|
||||||
@ -45,7 +46,8 @@ struct bufline_s {
|
|||||||
* The buffer structure points to the beginning and end of the buffer list
|
* The buffer structure points to the beginning and end of the buffer list
|
||||||
* (and includes the total size)
|
* (and includes the total size)
|
||||||
*/
|
*/
|
||||||
struct buffer_s {
|
struct buffer_s
|
||||||
|
{
|
||||||
struct bufline_s *head; /* top of the buffer */
|
struct bufline_s *head; /* top of the buffer */
|
||||||
struct bufline_s *tail; /* bottom of the buffer */
|
struct bufline_s *tail; /* bottom of the buffer */
|
||||||
size_t size; /* total size of the buffer */
|
size_t size; /* total size of the buffer */
|
||||||
@ -67,7 +69,8 @@ makenewline(unsigned char *data, size_t length)
|
|||||||
if (!(newline = safemalloc (sizeof (struct bufline_s))))
|
if (!(newline = safemalloc (sizeof (struct bufline_s))))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!(newline->string = safemalloc(length))) {
|
if (!(newline->string = safemalloc (length)))
|
||||||
|
{
|
||||||
safefree (newline);
|
safefree (newline);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -132,7 +135,8 @@ delete_buffer(struct buffer_s *buffptr)
|
|||||||
|
|
||||||
assert (buffptr != NULL);
|
assert (buffptr != NULL);
|
||||||
|
|
||||||
while (BUFFER_HEAD(buffptr)) {
|
while (BUFFER_HEAD (buffptr))
|
||||||
|
{
|
||||||
next = BUFFER_HEAD (buffptr)->next;
|
next = BUFFER_HEAD (buffptr)->next;
|
||||||
free_line (BUFFER_HEAD (buffptr));
|
free_line (BUFFER_HEAD (buffptr));
|
||||||
BUFFER_HEAD (buffptr) = next;
|
BUFFER_HEAD (buffptr) = next;
|
||||||
@ -179,7 +183,8 @@ add_to_buffer(struct buffer_s *buffptr, unsigned char *data, size_t length)
|
|||||||
|
|
||||||
if (buffptr->size == 0)
|
if (buffptr->size == 0)
|
||||||
BUFFER_HEAD (buffptr) = BUFFER_TAIL (buffptr) = newline;
|
BUFFER_HEAD (buffptr) = BUFFER_TAIL (buffptr) = newline;
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
BUFFER_TAIL (buffptr)->next = newline;
|
BUFFER_TAIL (buffptr)->next = newline;
|
||||||
BUFFER_TAIL (buffptr) = newline;
|
BUFFER_TAIL (buffptr) = newline;
|
||||||
}
|
}
|
||||||
@ -229,24 +234,32 @@ read_buffer(int fd, struct buffer_s * buffptr)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
buffer = safemalloc (READ_BUFFER_SIZE);
|
buffer = safemalloc (READ_BUFFER_SIZE);
|
||||||
if (!buffer) {
|
if (!buffer)
|
||||||
|
{
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytesin = read (fd, buffer, READ_BUFFER_SIZE);
|
bytesin = read (fd, buffer, READ_BUFFER_SIZE);
|
||||||
|
|
||||||
if (bytesin > 0) {
|
if (bytesin > 0)
|
||||||
if (add_to_buffer(buffptr, buffer, bytesin) < 0) {
|
{
|
||||||
log_message(LOG_ERR,
|
if (add_to_buffer (buffptr, buffer, bytesin) < 0)
|
||||||
"readbuff: add_to_buffer() error.");
|
{
|
||||||
|
log_message (LOG_ERR, "readbuff: add_to_buffer() error.");
|
||||||
bytesin = -1;
|
bytesin = -1;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if (bytesin == 0) {
|
else
|
||||||
|
{
|
||||||
|
if (bytesin == 0)
|
||||||
|
{
|
||||||
/* connection was closed by client */
|
/* connection was closed by client */
|
||||||
bytesin = -1;
|
bytesin = -1;
|
||||||
} else {
|
}
|
||||||
switch (errno) {
|
else
|
||||||
|
{
|
||||||
|
switch (errno)
|
||||||
|
{
|
||||||
#ifdef EWOULDBLOCK
|
#ifdef EWOULDBLOCK
|
||||||
case EWOULDBLOCK:
|
case EWOULDBLOCK:
|
||||||
#else
|
#else
|
||||||
@ -295,14 +308,18 @@ write_buffer(int fd, struct buffer_s * buffptr)
|
|||||||
send (fd, line->string + line->pos, line->length - line->pos,
|
send (fd, line->string + line->pos, line->length - line->pos,
|
||||||
MSG_NOSIGNAL);
|
MSG_NOSIGNAL);
|
||||||
|
|
||||||
if (bytessent >= 0) {
|
if (bytessent >= 0)
|
||||||
|
{
|
||||||
/* bytes sent, adjust buffer */
|
/* bytes sent, adjust buffer */
|
||||||
line->pos += bytessent;
|
line->pos += bytessent;
|
||||||
if (line->pos == line->length)
|
if (line->pos == line->length)
|
||||||
free_line (remove_from_buffer (buffptr));
|
free_line (remove_from_buffer (buffptr));
|
||||||
return bytessent;
|
return bytessent;
|
||||||
} else {
|
}
|
||||||
switch (errno) {
|
else
|
||||||
|
{
|
||||||
|
switch (errno)
|
||||||
|
{
|
||||||
#ifdef EWOULDBLOCK
|
#ifdef EWOULDBLOCK
|
||||||
case EWOULDBLOCK:
|
case EWOULDBLOCK:
|
||||||
#else
|
#else
|
||||||
|
117
src/child.c
117
src/child.c
@ -37,8 +37,10 @@ static socklen_t addrlen;
|
|||||||
/*
|
/*
|
||||||
* Stores the internal data needed for each child (connection)
|
* Stores the internal data needed for each child (connection)
|
||||||
*/
|
*/
|
||||||
enum child_status_t { T_EMPTY, T_WAITING, T_CONNECTED };
|
enum child_status_t
|
||||||
struct child_s {
|
{ T_EMPTY, T_WAITING, T_CONNECTED };
|
||||||
|
struct child_s
|
||||||
|
{
|
||||||
pid_t tid;
|
pid_t tid;
|
||||||
unsigned int connects;
|
unsigned int connects;
|
||||||
enum child_status_t status;
|
enum child_status_t status;
|
||||||
@ -50,7 +52,8 @@ struct child_s {
|
|||||||
*/
|
*/
|
||||||
static struct child_s *child_ptr;
|
static struct child_s *child_ptr;
|
||||||
|
|
||||||
static struct child_config_s {
|
static struct child_config_s
|
||||||
|
{
|
||||||
int maxclients, maxrequestsperchild;
|
int maxclients, maxrequestsperchild;
|
||||||
int maxspareservers, minspareservers, startservers;
|
int maxspareservers, minspareservers, startservers;
|
||||||
} child_config;
|
} child_config;
|
||||||
@ -102,7 +105,8 @@ _child_lock_wait(void)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
while ((rc = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0) {
|
while ((rc = fcntl (lock_fd, F_SETLKW, &lock_it)) < 0)
|
||||||
|
{
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
else
|
else
|
||||||
@ -140,7 +144,8 @@ _child_lock_release(void)
|
|||||||
short int
|
short int
|
||||||
child_configure (child_config_t type, int val)
|
child_configure (child_config_t type, int val)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type)
|
||||||
|
{
|
||||||
case CHILD_MAXCLIENTS:
|
case CHILD_MAXCLIENTS:
|
||||||
child_config.maxclients = val;
|
child_config.maxclients = val;
|
||||||
break;
|
break;
|
||||||
@ -175,15 +180,16 @@ child_main(struct child_s *ptr)
|
|||||||
socklen_t clilen;
|
socklen_t clilen;
|
||||||
|
|
||||||
cliaddr = safemalloc (addrlen);
|
cliaddr = safemalloc (addrlen);
|
||||||
if (!cliaddr) {
|
if (!cliaddr)
|
||||||
log_message(LOG_CRIT,
|
{
|
||||||
"Could not allocate memory for child address.");
|
log_message (LOG_CRIT, "Could not allocate memory for child address.");
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr->connects = 0;
|
ptr->connects = 0;
|
||||||
|
|
||||||
while (!config.quit) {
|
while (!config.quit)
|
||||||
|
{
|
||||||
ptr->status = T_WAITING;
|
ptr->status = T_WAITING;
|
||||||
|
|
||||||
clilen = addrlen;
|
clilen = addrlen;
|
||||||
@ -195,21 +201,22 @@ child_main(struct child_s *ptr)
|
|||||||
* Enable the TINYPROXY_DEBUG environment variable if you
|
* Enable the TINYPROXY_DEBUG environment variable if you
|
||||||
* want to use the GDB debugger.
|
* want to use the GDB debugger.
|
||||||
*/
|
*/
|
||||||
if (getenv("TINYPROXY_DEBUG")) {
|
if (getenv ("TINYPROXY_DEBUG"))
|
||||||
|
{
|
||||||
/* Pause for 10 seconds to allow us to connect debugger */
|
/* Pause for 10 seconds to allow us to connect debugger */
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"Process has accepted connection: %ld\n",
|
"Process has accepted connection: %ld\n",
|
||||||
(long int) ptr->tid);
|
(long int) ptr->tid);
|
||||||
sleep (10);
|
sleep (10);
|
||||||
fprintf(stderr, "Continuing process: %ld\n",
|
fprintf (stderr, "Continuing process: %ld\n", (long int) ptr->tid);
|
||||||
(long int)ptr->tid);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure no error occurred...
|
* Make sure no error occurred...
|
||||||
*/
|
*/
|
||||||
if (connfd < 0) {
|
if (connfd < 0)
|
||||||
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"Accept returned an error (%s) ... retrying.",
|
"Accept returned an error (%s) ... retrying.",
|
||||||
strerror (errno));
|
strerror (errno));
|
||||||
@ -223,10 +230,12 @@ child_main(struct child_s *ptr)
|
|||||||
handle_connection (connfd);
|
handle_connection (connfd);
|
||||||
ptr->connects++;
|
ptr->connects++;
|
||||||
|
|
||||||
if (child_config.maxrequestsperchild != 0) {
|
if (child_config.maxrequestsperchild != 0)
|
||||||
|
{
|
||||||
DEBUG2 ("%u connections so far...", ptr->connects);
|
DEBUG2 ("%u connections so far...", ptr->connects);
|
||||||
|
|
||||||
if (ptr->connects == child_config.maxrequestsperchild) {
|
if (ptr->connects == child_config.maxrequestsperchild)
|
||||||
|
{
|
||||||
log_message (LOG_NOTICE,
|
log_message (LOG_NOTICE,
|
||||||
"Child has reached MaxRequestsPerChild (%u). Killing child.",
|
"Child has reached MaxRequestsPerChild (%u). Killing child.",
|
||||||
ptr->connects);
|
ptr->connects);
|
||||||
@ -235,19 +244,21 @@ child_main(struct child_s *ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SERVER_COUNT_LOCK ();
|
SERVER_COUNT_LOCK ();
|
||||||
if (*servers_waiting > child_config.maxspareservers) {
|
if (*servers_waiting > child_config.maxspareservers)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* There are too many spare children, kill ourself
|
* There are too many spare children, kill ourself
|
||||||
* off.
|
* off.
|
||||||
*/
|
*/
|
||||||
log_message (LOG_NOTICE,
|
log_message (LOG_NOTICE,
|
||||||
"Waiting servers (%d) exceeds MaxSpareServers (%d). Killing child.",
|
"Waiting servers (%d) exceeds MaxSpareServers (%d). Killing child.",
|
||||||
*servers_waiting,
|
*servers_waiting, child_config.maxspareservers);
|
||||||
child_config.maxspareservers);
|
|
||||||
SERVER_COUNT_UNLOCK ();
|
SERVER_COUNT_UNLOCK ();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SERVER_COUNT_UNLOCK ();
|
SERVER_COUNT_UNLOCK ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,12 +307,14 @@ child_pool_create(void)
|
|||||||
* variable determines the size of the array created for children
|
* variable determines the size of the array created for children
|
||||||
* later on.
|
* later on.
|
||||||
*/
|
*/
|
||||||
if (child_config.maxclients == 0) {
|
if (child_config.maxclients == 0)
|
||||||
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"child_pool_create: \"MaxClients\" must be greater than zero.");
|
"child_pool_create: \"MaxClients\" must be greater than zero.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (child_config.startservers == 0) {
|
if (child_config.startservers == 0)
|
||||||
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"child_pool_create: \"StartServers\" must be greater than zero.");
|
"child_pool_create: \"StartServers\" must be greater than zero.");
|
||||||
return -1;
|
return -1;
|
||||||
@ -309,15 +322,16 @@ child_pool_create(void)
|
|||||||
|
|
||||||
child_ptr = calloc_shared_memory (child_config.maxclients,
|
child_ptr = calloc_shared_memory (child_config.maxclients,
|
||||||
sizeof (struct child_s));
|
sizeof (struct child_s));
|
||||||
if (!child_ptr) {
|
if (!child_ptr)
|
||||||
|
{
|
||||||
log_message (LOG_ERR, "Could not allocate memory for children.");
|
log_message (LOG_ERR, "Could not allocate memory for children.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
servers_waiting = malloc_shared_memory (sizeof (unsigned int));
|
servers_waiting = malloc_shared_memory (sizeof (unsigned int));
|
||||||
if (servers_waiting == MAP_FAILED) {
|
if (servers_waiting == MAP_FAILED)
|
||||||
log_message(LOG_ERR,
|
{
|
||||||
"Could not allocate memory for child counting.");
|
log_message (LOG_ERR, "Could not allocate memory for child counting.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*servers_waiting = 0;
|
*servers_waiting = 0;
|
||||||
@ -328,30 +342,36 @@ child_pool_create(void)
|
|||||||
*/
|
*/
|
||||||
_child_lock_init ();
|
_child_lock_init ();
|
||||||
|
|
||||||
if (child_config.startservers > child_config.maxclients) {
|
if (child_config.startservers > child_config.maxclients)
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Can not start more than \"MaxClients\" servers. Starting %u servers instead.",
|
"Can not start more than \"MaxClients\" servers. Starting %u servers instead.",
|
||||||
child_config.maxclients);
|
child_config.maxclients);
|
||||||
child_config.startservers = child_config.maxclients;
|
child_config.startservers = child_config.maxclients;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i != child_config.maxclients; i++) {
|
for (i = 0; i != child_config.maxclients; i++)
|
||||||
|
{
|
||||||
child_ptr[i].status = T_EMPTY;
|
child_ptr[i].status = T_EMPTY;
|
||||||
child_ptr[i].connects = 0;
|
child_ptr[i].connects = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i != child_config.startservers; i++) {
|
for (i = 0; i != child_config.startservers; i++)
|
||||||
|
{
|
||||||
DEBUG2 ("Trying to create child %d of %d", i + 1,
|
DEBUG2 ("Trying to create child %d of %d", i + 1,
|
||||||
child_config.startservers);
|
child_config.startservers);
|
||||||
child_ptr[i].status = T_WAITING;
|
child_ptr[i].status = T_WAITING;
|
||||||
child_ptr[i].tid = child_make (&child_ptr[i]);
|
child_ptr[i].tid = child_make (&child_ptr[i]);
|
||||||
|
|
||||||
if (child_ptr[i].tid < 0) {
|
if (child_ptr[i].tid < 0)
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Could not create child number %d of %d",
|
"Could not create child number %d of %d",
|
||||||
i, child_config.startservers);
|
i, child_config.startservers);
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
log_message (LOG_INFO,
|
log_message (LOG_INFO,
|
||||||
"Creating child number %d of %d ...",
|
"Creating child number %d of %d ...",
|
||||||
i + 1, child_config.startservers);
|
i + 1, child_config.startservers);
|
||||||
@ -374,28 +394,30 @@ child_main_loop(void)
|
|||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
while (1) {
|
while (1)
|
||||||
|
{
|
||||||
if (config.quit)
|
if (config.quit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* If there are not enough spare servers, create more */
|
/* If there are not enough spare servers, create more */
|
||||||
SERVER_COUNT_LOCK ();
|
SERVER_COUNT_LOCK ();
|
||||||
if (*servers_waiting < child_config.minspareservers) {
|
if (*servers_waiting < child_config.minspareservers)
|
||||||
|
{
|
||||||
log_message (LOG_NOTICE,
|
log_message (LOG_NOTICE,
|
||||||
"Waiting servers (%d) is less than MinSpareServers (%d). Creating new child.",
|
"Waiting servers (%d) is less than MinSpareServers (%d). Creating new child.",
|
||||||
*servers_waiting,
|
*servers_waiting, child_config.minspareservers);
|
||||||
child_config.minspareservers);
|
|
||||||
|
|
||||||
SERVER_COUNT_UNLOCK ();
|
SERVER_COUNT_UNLOCK ();
|
||||||
|
|
||||||
for (i = 0; i != child_config.maxclients; i++) {
|
for (i = 0; i != child_config.maxclients; i++)
|
||||||
if (child_ptr[i].status == T_EMPTY) {
|
{
|
||||||
|
if (child_ptr[i].status == T_EMPTY)
|
||||||
|
{
|
||||||
child_ptr[i].status = T_WAITING;
|
child_ptr[i].status = T_WAITING;
|
||||||
child_ptr[i].tid =
|
child_ptr[i].tid = child_make (&child_ptr[i]);
|
||||||
child_make(&child_ptr[i]);
|
if (child_ptr[i].tid < 0)
|
||||||
if (child_ptr[i].tid < 0) {
|
{
|
||||||
log_message(LOG_NOTICE,
|
log_message (LOG_NOTICE, "Could not create child");
|
||||||
"Could not create child");
|
|
||||||
|
|
||||||
child_ptr[i].status = T_EMPTY;
|
child_ptr[i].status = T_EMPTY;
|
||||||
break;
|
break;
|
||||||
@ -406,18 +428,22 @@ child_main_loop(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SERVER_COUNT_UNLOCK ();
|
SERVER_COUNT_UNLOCK ();
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep (5);
|
sleep (5);
|
||||||
|
|
||||||
/* Handle log rotation if it was requested */
|
/* Handle log rotation if it was requested */
|
||||||
if (received_sighup) {
|
if (received_sighup)
|
||||||
|
{
|
||||||
truncate_log_file ();
|
truncate_log_file ();
|
||||||
|
|
||||||
#ifdef FILTER_ENABLE
|
#ifdef FILTER_ENABLE
|
||||||
if (config.filter) {
|
if (config.filter)
|
||||||
|
{
|
||||||
filter_destroy ();
|
filter_destroy ();
|
||||||
filter_init ();
|
filter_init ();
|
||||||
}
|
}
|
||||||
@ -437,7 +463,8 @@ child_kill_children(void)
|
|||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i != child_config.maxclients; i++) {
|
for (i = 0; i != child_config.maxclients; i++)
|
||||||
|
{
|
||||||
if (child_ptr[i].status != T_EMPTY)
|
if (child_ptr[i].status != T_EMPTY)
|
||||||
kill (child_ptr[i].tid, SIGTERM);
|
kill (child_ptr[i].tid, SIGTERM);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
#ifndef TINYPROXY_CHILD_H
|
#ifndef TINYPROXY_CHILD_H
|
||||||
#define TINYPROXY_CHILD_H
|
#define TINYPROXY_CHILD_H
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
CHILD_MAXCLIENTS,
|
CHILD_MAXCLIENTS,
|
||||||
CHILD_MAXSPARESERVERS,
|
CHILD_MAXSPARESERVERS,
|
||||||
CHILD_MINSPARESERVERS,
|
CHILD_MINSPARESERVERS,
|
||||||
|
@ -66,7 +66,8 @@
|
|||||||
* All configuration handling functions are REQUIRED to be defined
|
* All configuration handling functions are REQUIRED to be defined
|
||||||
* with the same function template as below.
|
* with the same function template as below.
|
||||||
*/
|
*/
|
||||||
typedef int (*CONFFILE_HANDLER) (struct config_s *, const char *, regmatch_t[]);
|
typedef int (*CONFFILE_HANDLER) (struct config_s *, const char *,
|
||||||
|
regmatch_t[]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the pattern used by any directive handling function. The
|
* Define the pattern used by any directive handling function. The
|
||||||
@ -156,17 +157,19 @@ static HANDLE_FUNC(handle_upstream_no);
|
|||||||
* for internal use, a pointer to the compiled regex so it only needs
|
* for internal use, a pointer to the compiled regex so it only needs
|
||||||
* to be compiled one.
|
* to be compiled one.
|
||||||
*/
|
*/
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
const char *re;
|
const char *re;
|
||||||
CONFFILE_HANDLER handler;
|
CONFFILE_HANDLER handler;
|
||||||
regex_t *cre;
|
regex_t *cre;
|
||||||
} directives[] = {
|
} directives[] =
|
||||||
|
{
|
||||||
/* comments */
|
/* comments */
|
||||||
{ BEGIN "#", handle_nop },
|
{
|
||||||
|
BEGIN "#", handle_nop},
|
||||||
/* blank lines */
|
/* blank lines */
|
||||||
{ "^[[:space:]]+$", handle_nop },
|
{
|
||||||
|
"^[[:space:]]+$", handle_nop},
|
||||||
/* string arguments */
|
/* string arguments */
|
||||||
STDCONF ("logfile", STR, handle_logfile),
|
STDCONF ("logfile", STR, handle_logfile),
|
||||||
STDCONF ("pidfile", STR, handle_pidfile),
|
STDCONF ("pidfile", STR, handle_pidfile),
|
||||||
@ -176,11 +179,9 @@ struct {
|
|||||||
STDCONF ("statfile", STR, handle_statfile),
|
STDCONF ("statfile", STR, handle_statfile),
|
||||||
STDCONF ("stathost", STR, handle_stathost),
|
STDCONF ("stathost", STR, handle_stathost),
|
||||||
STDCONF ("xtinyproxy", STR, handle_xtinyproxy),
|
STDCONF ("xtinyproxy", STR, 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),
|
||||||
|
|
||||||
/* integer arguments */
|
/* integer arguments */
|
||||||
STDCONF ("port", INT, handle_port),
|
STDCONF ("port", INT, handle_port),
|
||||||
STDCONF ("maxclients", INT, handle_maxclients),
|
STDCONF ("maxclients", INT, handle_maxclients),
|
||||||
@ -190,20 +191,16 @@ struct {
|
|||||||
STDCONF ("maxrequestsperchild", INT, handle_maxrequestsperchild),
|
STDCONF ("maxrequestsperchild", INT, handle_maxrequestsperchild),
|
||||||
STDCONF ("timeout", INT, handle_timeout),
|
STDCONF ("timeout", INT, handle_timeout),
|
||||||
STDCONF ("connectport", INT, handle_connectport),
|
STDCONF ("connectport", INT, handle_connectport),
|
||||||
|
|
||||||
/* alphanumeric arguments */
|
/* alphanumeric arguments */
|
||||||
STDCONF ("user", ALNUM, handle_user),
|
STDCONF ("user", ALNUM, handle_user),
|
||||||
STDCONF ("group", ALNUM, handle_group),
|
STDCONF ("group", ALNUM, handle_group),
|
||||||
|
|
||||||
/* ip arguments */
|
/* ip arguments */
|
||||||
STDCONF ("listen", IP, handle_listen),
|
STDCONF ("listen", IP, handle_listen),
|
||||||
STDCONF ("allow", "(" IPMASK "|" ALNUM ")", handle_allow),
|
STDCONF ("allow", "(" IPMASK "|" ALNUM ")", handle_allow),
|
||||||
STDCONF ("deny", "(" IPMASK "|" ALNUM ")", handle_deny),
|
STDCONF ("deny", "(" IPMASK "|" ALNUM ")", handle_deny),
|
||||||
STDCONF ("bind", IP, handle_bind),
|
STDCONF ("bind", IP, handle_bind),
|
||||||
|
|
||||||
/* error files */
|
/* error files */
|
||||||
STDCONF ("errorfile", INT WS STR, handle_errorfile),
|
STDCONF ("errorfile", INT WS STR, handle_errorfile),
|
||||||
|
|
||||||
#ifdef FILTER_ENABLE
|
#ifdef FILTER_ENABLE
|
||||||
/* filtering */
|
/* filtering */
|
||||||
STDCONF ("filter", STR, handle_filter),
|
STDCONF ("filter", STR, handle_filter),
|
||||||
@ -212,7 +209,6 @@ struct {
|
|||||||
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),
|
||||||
@ -220,17 +216,17 @@ struct {
|
|||||||
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
|
||||||
/* upstream is rather complicated */
|
/* upstream is rather complicated */
|
||||||
{ BEGIN "(no" WS "upstream)" WS STR END, handle_upstream_no },
|
{
|
||||||
{ BEGIN "(upstream)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR ")?" END, handle_upstream },
|
BEGIN "(no" WS "upstream)" WS STR END, handle_upstream_no},
|
||||||
|
{
|
||||||
|
BEGIN "(upstream)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR ")?" END,
|
||||||
|
handle_upstream},
|
||||||
#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]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -244,7 +240,8 @@ config_compile(void)
|
|||||||
{
|
{
|
||||||
int i, r;
|
int i, r;
|
||||||
|
|
||||||
for (i = 0; i != ndirectives; ++i) {
|
for (i = 0; i != ndirectives; ++i)
|
||||||
|
{
|
||||||
assert (directives[i].handler);
|
assert (directives[i].handler);
|
||||||
assert (!directives[i].cre);
|
assert (!directives[i].cre);
|
||||||
|
|
||||||
@ -253,8 +250,7 @@ config_compile(void)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
r = regcomp (directives[i].cre,
|
r = regcomp (directives[i].cre,
|
||||||
directives[i].re,
|
directives[i].re, REG_EXTENDED | REG_ICASE | REG_NEWLINE);
|
||||||
REG_EXTENDED | REG_ICASE | REG_NEWLINE);
|
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -277,7 +273,8 @@ check_match(struct config_s *conf, const char *line)
|
|||||||
|
|
||||||
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 (directives[i].cre, line, RE_MAX_MATCHES, match, 0))
|
if (!regexec (directives[i].cre, line, RE_MAX_MATCHES, match, 0))
|
||||||
return (*directives[i].handler) (conf, line, match);
|
return (*directives[i].handler) (conf, line, match);
|
||||||
@ -295,8 +292,10 @@ config_parse(struct config_s *conf, FILE * f)
|
|||||||
char buffer[1024]; /* 1KB lines should be plenty */
|
char buffer[1024]; /* 1KB lines should be plenty */
|
||||||
unsigned long lineno = 1;
|
unsigned long lineno = 1;
|
||||||
|
|
||||||
while (fgets(buffer, sizeof(buffer), f)) {
|
while (fgets (buffer, sizeof (buffer), f))
|
||||||
if (check_match(conf, buffer)) {
|
{
|
||||||
|
if (check_match (conf, buffer))
|
||||||
|
{
|
||||||
printf ("Syntax error on line %ld\n", lineno);
|
printf ("Syntax error on line %ld\n", lineno);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -376,6 +375,7 @@ get_int_arg(const char *line, regmatch_t * match)
|
|||||||
|
|
||||||
return strtol (line + match->rm_so, NULL, 0);
|
return strtol (line + match->rm_so, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
set_int_arg (int long *var, const char *line, regmatch_t * match)
|
set_int_arg (int long *var, const char *line, regmatch_t * match)
|
||||||
{
|
{
|
||||||
@ -536,8 +536,7 @@ HANDLE_FUNC(handle_startservers)
|
|||||||
static
|
static
|
||||||
HANDLE_FUNC (handle_maxrequestsperchild)
|
HANDLE_FUNC (handle_maxrequestsperchild)
|
||||||
{
|
{
|
||||||
child_configure(CHILD_MAXREQUESTSPERCHILD,
|
child_configure (CHILD_MAXREQUESTSPERCHILD, get_int_arg (line, &match[2]));
|
||||||
get_int_arg(line, &match[2]));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,7 +635,8 @@ HANDLE_FUNC(handle_errorfile)
|
|||||||
/*
|
/*
|
||||||
* Log level's strings.
|
* Log level's strings.
|
||||||
*/
|
*/
|
||||||
struct log_levels_s {
|
struct log_levels_s
|
||||||
|
{
|
||||||
const char *string;
|
const char *string;
|
||||||
int level;
|
int level;
|
||||||
};
|
};
|
||||||
@ -658,8 +658,10 @@ HANDLE_FUNC(handle_loglevel)
|
|||||||
|
|
||||||
char *arg = get_string_arg (line, &match[2]);
|
char *arg = get_string_arg (line, &match[2]);
|
||||||
|
|
||||||
for (i = 0; i != nlevels; ++i) {
|
for (i = 0; i != nlevels; ++i)
|
||||||
if (!strcasecmp(arg, log_levels[i].string)) {
|
{
|
||||||
|
if (!strcasecmp (arg, log_levels[i].string))
|
||||||
|
{
|
||||||
set_log_level (log_levels[i].level);
|
set_log_level (log_levels[i].level);
|
||||||
safefree (arg);
|
safefree (arg);
|
||||||
return 0;
|
return 0;
|
||||||
@ -737,16 +739,20 @@ HANDLE_FUNC(handle_reversepath)
|
|||||||
if (!arg1)
|
if (!arg1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (match[3].rm_so != -1) {
|
if (match[3].rm_so != -1)
|
||||||
|
{
|
||||||
arg2 = get_string_arg (line, &match[3]);
|
arg2 = get_string_arg (line, &match[3]);
|
||||||
if (!arg2) {
|
if (!arg2)
|
||||||
|
{
|
||||||
safefree (arg1);
|
safefree (arg1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
reversepath_add (arg1, arg2);
|
reversepath_add (arg1, arg2);
|
||||||
safefree (arg1);
|
safefree (arg1);
|
||||||
safefree (arg2);
|
safefree (arg2);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
reversepath_add (NULL, arg1);
|
reversepath_add (NULL, arg1);
|
||||||
safefree (arg1);
|
safefree (arg1);
|
||||||
}
|
}
|
||||||
@ -763,16 +769,21 @@ HANDLE_FUNC(handle_upstream)
|
|||||||
char *domain;
|
char *domain;
|
||||||
|
|
||||||
ip = get_string_arg (line, &match[2]);
|
ip = get_string_arg (line, &match[2]);
|
||||||
if (!ip) return -1;
|
if (!ip)
|
||||||
|
return -1;
|
||||||
port = get_int_arg (line, &match[7]);
|
port = get_int_arg (line, &match[7]);
|
||||||
|
|
||||||
if (match[9].rm_so != -1) {
|
if (match[9].rm_so != -1)
|
||||||
|
{
|
||||||
domain = get_string_arg (line, &match[9]);
|
domain = get_string_arg (line, &match[9]);
|
||||||
if (domain) {
|
if (domain)
|
||||||
|
{
|
||||||
upstream_add (ip, port, domain);
|
upstream_add (ip, port, domain);
|
||||||
safefree (domain);
|
safefree (domain);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
upstream_add (ip, port, NULL);
|
upstream_add (ip, port, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,7 +798,8 @@ HANDLE_FUNC(handle_upstream_no)
|
|||||||
char *domain;
|
char *domain;
|
||||||
|
|
||||||
domain = get_string_arg (line, &match[2]);
|
domain = get_string_arg (line, &match[2]);
|
||||||
if (!domain) return -1;
|
if (!domain)
|
||||||
|
return -1;
|
||||||
|
|
||||||
upstream_add (NULL, 0, domain);
|
upstream_add (NULL, 0, domain);
|
||||||
safefree (domain);
|
safefree (domain);
|
||||||
|
@ -27,7 +27,8 @@
|
|||||||
/*
|
/*
|
||||||
* Connection Definition
|
* Connection Definition
|
||||||
*/
|
*/
|
||||||
struct conn_s {
|
struct conn_s
|
||||||
|
{
|
||||||
int client_fd;
|
int client_fd;
|
||||||
int server_fd;
|
int server_fd;
|
||||||
|
|
||||||
@ -51,7 +52,8 @@ struct conn_s {
|
|||||||
char *error_string;
|
char *error_string;
|
||||||
|
|
||||||
/* A Content-Length value from the remote server */
|
/* A Content-Length value from the remote server */
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
long int server;
|
long int server;
|
||||||
long int client;
|
long int client;
|
||||||
} content_length;
|
} content_length;
|
||||||
@ -70,7 +72,8 @@ struct conn_s {
|
|||||||
/*
|
/*
|
||||||
* Store the incoming request's HTTP protocol.
|
* Store the incoming request's HTTP protocol.
|
||||||
*/
|
*/
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
unsigned int major;
|
unsigned int major;
|
||||||
unsigned int minor;
|
unsigned int minor;
|
||||||
} protocol;
|
} protocol;
|
||||||
|
@ -67,11 +67,14 @@ set_signal_handler(int signo, signal_func *func)
|
|||||||
act.sa_handler = func;
|
act.sa_handler = func;
|
||||||
sigemptyset (&act.sa_mask);
|
sigemptyset (&act.sa_mask);
|
||||||
act.sa_flags = 0;
|
act.sa_flags = 0;
|
||||||
if (signo == SIGALRM) {
|
if (signo == SIGALRM)
|
||||||
|
{
|
||||||
#ifdef SA_INTERRUPT
|
#ifdef SA_INTERRUPT
|
||||||
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
|
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
|
||||||
#endif
|
#endif
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
#ifdef SA_RESTART
|
#ifdef SA_RESTART
|
||||||
act.sa_flags |= SA_RESTART; /* SVR4, 4.4BSD */
|
act.sa_flags |= SA_RESTART; /* SVR4, 4.4BSD */
|
||||||
#endif
|
#endif
|
||||||
|
62
src/filter.c
62
src/filter.c
@ -33,7 +33,8 @@
|
|||||||
|
|
||||||
static int err;
|
static int err;
|
||||||
|
|
||||||
struct filter_list {
|
struct filter_list
|
||||||
|
{
|
||||||
struct filter_list *next;
|
struct filter_list *next;
|
||||||
char *pat;
|
char *pat;
|
||||||
regex_t *cpat;
|
regex_t *cpat;
|
||||||
@ -55,9 +56,11 @@ filter_init(void)
|
|||||||
char *s;
|
char *s;
|
||||||
int cflags;
|
int cflags;
|
||||||
|
|
||||||
if (!fl && !already_init) {
|
if (!fl && !already_init)
|
||||||
|
{
|
||||||
fd = fopen (config.filter, "r");
|
fd = fopen (config.filter, "r");
|
||||||
if (fd) {
|
if (fd)
|
||||||
|
{
|
||||||
p = NULL;
|
p = NULL;
|
||||||
|
|
||||||
cflags = REG_NEWLINE | REG_NOSUB;
|
cflags = REG_NEWLINE | REG_NOSUB;
|
||||||
@ -66,23 +69,25 @@ filter_init(void)
|
|||||||
if (!config.filter_casesensitive)
|
if (!config.filter_casesensitive)
|
||||||
cflags |= REG_ICASE;
|
cflags |= REG_ICASE;
|
||||||
|
|
||||||
while (fgets(buf, FILTER_BUFFER_LEN, fd)) {
|
while (fgets (buf, FILTER_BUFFER_LEN, fd))
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Remove any trailing white space and
|
* Remove any trailing white space and
|
||||||
* comments.
|
* comments.
|
||||||
*/
|
*/
|
||||||
s = buf;
|
s = buf;
|
||||||
while (*s) {
|
while (*s)
|
||||||
|
{
|
||||||
if (isspace ((unsigned char) *s))
|
if (isspace ((unsigned char) *s))
|
||||||
break;
|
break;
|
||||||
if (*s == '#') {
|
if (*s == '#')
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* If the '#' char is preceeded by
|
* If the '#' char is preceeded by
|
||||||
* an escape, it's not a comment
|
* an escape, it's not a comment
|
||||||
* string.
|
* string.
|
||||||
*/
|
*/
|
||||||
if (s == buf
|
if (s == buf || *(s - 1) != '\\')
|
||||||
|| *(s - 1) != '\\')
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++s;
|
++s;
|
||||||
@ -99,28 +104,24 @@ filter_init(void)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!p) /* head of list */
|
if (!p) /* head of list */
|
||||||
fl = p =
|
fl = p = safecalloc (1, sizeof (struct filter_list));
|
||||||
safecalloc(1,
|
else
|
||||||
sizeof(struct
|
{ /* next entry */
|
||||||
filter_list));
|
p->next = safecalloc (1, sizeof (struct filter_list));
|
||||||
else { /* next entry */
|
|
||||||
p->next =
|
|
||||||
safecalloc(1,
|
|
||||||
sizeof(struct
|
|
||||||
filter_list));
|
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->pat = safestrdup (s);
|
p->pat = safestrdup (s);
|
||||||
p->cpat = safemalloc (sizeof (regex_t));
|
p->cpat = safemalloc (sizeof (regex_t));
|
||||||
if ((err =
|
if ((err = regcomp (p->cpat, p->pat, cflags)) != 0)
|
||||||
regcomp(p->cpat, p->pat, cflags)) != 0) {
|
{
|
||||||
fprintf (stderr, "Bad regex in %s: %s\n",
|
fprintf (stderr, "Bad regex in %s: %s\n",
|
||||||
config.filter, p->pat);
|
config.filter, p->pat);
|
||||||
exit (EX_DATAERR);
|
exit (EX_DATAERR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ferror(fd)) {
|
if (ferror (fd))
|
||||||
|
{
|
||||||
perror ("fgets");
|
perror ("fgets");
|
||||||
exit (EX_DATAERR);
|
exit (EX_DATAERR);
|
||||||
}
|
}
|
||||||
@ -137,8 +138,10 @@ filter_destroy(void)
|
|||||||
{
|
{
|
||||||
struct filter_list *p, *q;
|
struct filter_list *p, *q;
|
||||||
|
|
||||||
if (already_init) {
|
if (already_init)
|
||||||
for (p = q = fl; p; p = q) {
|
{
|
||||||
|
for (p = q = fl; p; p = q)
|
||||||
|
{
|
||||||
regfree (p->cpat);
|
regfree (p->cpat);
|
||||||
safefree (p->cpat);
|
safefree (p->cpat);
|
||||||
safefree (p->pat);
|
safefree (p->pat);
|
||||||
@ -160,11 +163,12 @@ filter_domain(const char *host)
|
|||||||
if (!fl || !already_init)
|
if (!fl || !already_init)
|
||||||
goto COMMON_EXIT;
|
goto COMMON_EXIT;
|
||||||
|
|
||||||
for (p = fl; p; p = p->next) {
|
for (p = fl; p; p = p->next)
|
||||||
result =
|
{
|
||||||
regexec(p->cpat, host, (size_t) 0, (regmatch_t *) 0, 0);
|
result = regexec (p->cpat, host, (size_t) 0, (regmatch_t *) 0, 0);
|
||||||
|
|
||||||
if (result == 0) {
|
if (result == 0)
|
||||||
|
{
|
||||||
if (default_policy == FILTER_DEFAULT_ALLOW)
|
if (default_policy == FILTER_DEFAULT_ALLOW)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
@ -189,10 +193,12 @@ filter_url(const char *url)
|
|||||||
if (!fl || !already_init)
|
if (!fl || !already_init)
|
||||||
goto COMMON_EXIT;
|
goto COMMON_EXIT;
|
||||||
|
|
||||||
for (p = fl; p; p = p->next) {
|
for (p = fl; p; p = p->next)
|
||||||
|
{
|
||||||
result = regexec (p->cpat, url, (size_t) 0, (regmatch_t *) 0, 0);
|
result = regexec (p->cpat, url, (size_t) 0, (regmatch_t *) 0, 0);
|
||||||
|
|
||||||
if (result == 0) {
|
if (result == 0)
|
||||||
|
{
|
||||||
if (default_policy == FILTER_DEFAULT_ALLOW)
|
if (default_policy == FILTER_DEFAULT_ALLOW)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
#ifndef _TINYPROXY_FILTER_H_
|
#ifndef _TINYPROXY_FILTER_H_
|
||||||
#define _TINYPROXY_FILTER_H_
|
#define _TINYPROXY_FILTER_H_
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
FILTER_DEFAULT_ALLOW,
|
FILTER_DEFAULT_ALLOW,
|
||||||
FILTER_DEFAULT_DENY,
|
FILTER_DEFAULT_DENY,
|
||||||
} filter_policy_t;
|
} filter_policy_t;
|
||||||
|
@ -37,7 +37,8 @@
|
|||||||
* internal use. It stores the number of buckets the hashmap was created
|
* internal use. It stores the number of buckets the hashmap was created
|
||||||
* with.
|
* with.
|
||||||
*/
|
*/
|
||||||
struct hashentry_s {
|
struct hashentry_s
|
||||||
|
{
|
||||||
char *key;
|
char *key;
|
||||||
void *data;
|
void *data;
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -45,11 +46,13 @@ struct hashentry_s {
|
|||||||
struct hashentry_s *prev, *next;
|
struct hashentry_s *prev, *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hashbucket_s {
|
struct hashbucket_s
|
||||||
|
{
|
||||||
struct hashentry_s *head, *tail;
|
struct hashentry_s *head, *tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hashmap_s {
|
struct hashmap_s
|
||||||
|
{
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
hashmap_iter end_iterator;
|
hashmap_iter end_iterator;
|
||||||
|
|
||||||
@ -75,7 +78,8 @@ hashfunc(const char *key, unsigned int size)
|
|||||||
if (size == 0)
|
if (size == 0)
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
|
|
||||||
for (hash = tolower(*key++); *key != '\0'; key++) {
|
for (hash = tolower (*key++); *key != '\0'; key++)
|
||||||
|
{
|
||||||
uint32_t bit = (hash & 1) ? (1 << (sizeof (uint32_t) - 1)) : 0;
|
uint32_t bit = (hash & 1) ? (1 << (sizeof (uint32_t) - 1)) : 0;
|
||||||
|
|
||||||
hash >>= 1;
|
hash >>= 1;
|
||||||
@ -108,7 +112,8 @@ hashmap_create(unsigned int nbuckets)
|
|||||||
|
|
||||||
ptr->size = nbuckets;
|
ptr->size = nbuckets;
|
||||||
ptr->buckets = safecalloc (nbuckets, sizeof (struct hashbucket_s));
|
ptr->buckets = safecalloc (nbuckets, sizeof (struct hashbucket_s));
|
||||||
if (!ptr->buckets) {
|
if (!ptr->buckets)
|
||||||
|
{
|
||||||
safefree (ptr);
|
safefree (ptr);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -136,7 +141,8 @@ delete_hashbucket(struct hashbucket_s *bucket)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ptr = bucket->head;
|
ptr = bucket->head;
|
||||||
while (ptr) {
|
while (ptr)
|
||||||
|
{
|
||||||
nextptr = ptr->next;
|
nextptr = ptr->next;
|
||||||
|
|
||||||
safefree (ptr->key);
|
safefree (ptr->key);
|
||||||
@ -163,8 +169,10 @@ hashmap_delete(hashmap_t map)
|
|||||||
if (map == NULL)
|
if (map == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i != map->size; i++) {
|
for (i = 0; i != map->size; i++)
|
||||||
if (map->buckets[i].head != NULL) {
|
{
|
||||||
|
if (map->buckets[i].head != NULL)
|
||||||
|
{
|
||||||
delete_hashbucket (&map->buckets[i]);
|
delete_hashbucket (&map->buckets[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,14 +224,16 @@ hashmap_insert(hashmap_t map, const char *key, const void *data, size_t len)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
data_copy = safemalloc (len);
|
data_copy = safemalloc (len);
|
||||||
if (!data_copy) {
|
if (!data_copy)
|
||||||
|
{
|
||||||
safefree (key_copy);
|
safefree (key_copy);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
memcpy (data_copy, data, len);
|
memcpy (data_copy, data, len);
|
||||||
|
|
||||||
ptr = safemalloc (sizeof (struct hashentry_s));
|
ptr = safemalloc (sizeof (struct hashentry_s));
|
||||||
if (!ptr) {
|
if (!ptr)
|
||||||
|
{
|
||||||
safefree (key_copy);
|
safefree (key_copy);
|
||||||
safefree (data_copy);
|
safefree (data_copy);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -314,11 +324,14 @@ hashmap_find(hashmap_t map, const char *key)
|
|||||||
* Loop through all the keys and look for the first occurrence
|
* Loop through all the keys and look for the first occurrence
|
||||||
* of a particular key.
|
* of a particular key.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i != map->size; i++) {
|
for (i = 0; i != map->size; i++)
|
||||||
|
{
|
||||||
ptr = map->buckets[i].head;
|
ptr = map->buckets[i].head;
|
||||||
|
|
||||||
while (ptr) {
|
while (ptr)
|
||||||
if (strcasecmp(ptr->key, key) == 0) {
|
{
|
||||||
|
if (strcasecmp (ptr->key, key) == 0)
|
||||||
|
{
|
||||||
/* Found it, so return the current count */
|
/* Found it, so return the current count */
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
@ -338,7 +351,8 @@ hashmap_find(hashmap_t map, const char *key)
|
|||||||
* negative upon error
|
* negative upon error
|
||||||
*/
|
*/
|
||||||
ssize_t
|
ssize_t
|
||||||
hashmap_return_entry(hashmap_t map, hashmap_iter iter, char **key, void **data)
|
hashmap_return_entry (hashmap_t map, hashmap_iter iter, char **key,
|
||||||
|
void **data)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct hashentry_s *ptr;
|
struct hashentry_s *ptr;
|
||||||
@ -353,10 +367,13 @@ hashmap_return_entry(hashmap_t map, hashmap_iter iter, char **key, void **data)
|
|||||||
if (!map || iter < 0 || !key || !data)
|
if (!map || iter < 0 || !key || !data)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i != map->size; i++) {
|
for (i = 0; i != map->size; i++)
|
||||||
|
{
|
||||||
ptr = map->buckets[i].head;
|
ptr = map->buckets[i].head;
|
||||||
while (ptr) {
|
while (ptr)
|
||||||
if (count == iter) {
|
{
|
||||||
|
if (count == iter)
|
||||||
|
{
|
||||||
/* This is the data so return it */
|
/* This is the data so return it */
|
||||||
*key = ptr->key;
|
*key = ptr->key;
|
||||||
*data = ptr->data;
|
*data = ptr->data;
|
||||||
@ -395,7 +412,8 @@ hashmap_search(hashmap_t map, const char *key)
|
|||||||
ptr = map->buckets[hash].head;
|
ptr = map->buckets[hash].head;
|
||||||
|
|
||||||
/* All right, there is an entry here, now see if it's the one we want */
|
/* All right, there is an entry here, now see if it's the one we want */
|
||||||
while (ptr) {
|
while (ptr)
|
||||||
|
{
|
||||||
if (strcasecmp (ptr->key, key) == 0)
|
if (strcasecmp (ptr->key, key) == 0)
|
||||||
++count;
|
++count;
|
||||||
|
|
||||||
@ -429,8 +447,10 @@ hashmap_entry_by_key(hashmap_t map, const char *key, void **data)
|
|||||||
|
|
||||||
ptr = map->buckets[hash].head;
|
ptr = map->buckets[hash].head;
|
||||||
|
|
||||||
while (ptr) {
|
while (ptr)
|
||||||
if (strcasecmp(ptr->key, key) == 0) {
|
{
|
||||||
|
if (strcasecmp (ptr->key, key) == 0)
|
||||||
|
{
|
||||||
*data = ptr->data;
|
*data = ptr->data;
|
||||||
return ptr->len;
|
return ptr->len;
|
||||||
}
|
}
|
||||||
@ -464,8 +484,10 @@ hashmap_remove(hashmap_t map, const char *key)
|
|||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
ptr = map->buckets[hash].head;
|
ptr = map->buckets[hash].head;
|
||||||
while (ptr) {
|
while (ptr)
|
||||||
if (strcasecmp(ptr->key, key) == 0) {
|
{
|
||||||
|
if (strcasecmp (ptr->key, key) == 0)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Found the data, now need to remove everything
|
* Found the data, now need to remove everything
|
||||||
* and update the hashmap.
|
* and update the hashmap.
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
|
|
||||||
/* Allow the use in C++ code. */
|
/* Allow the use in C++ code. */
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" {
|
extern "C"
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -55,7 +55,8 @@ debugging_malloc(size_t size, const char *file, unsigned long line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
debugging_realloc(void *ptr, size_t size, const char *file, unsigned long line)
|
debugging_realloc (void *ptr, size_t size, const char *file,
|
||||||
|
unsigned long line)
|
||||||
{
|
{
|
||||||
void *newptr;
|
void *newptr;
|
||||||
|
|
||||||
|
@ -118,27 +118,26 @@ send_html_file(FILE * infile, struct conn_s *connptr)
|
|||||||
char *varval;
|
char *varval;
|
||||||
int in_variable = 0, writeret;
|
int in_variable = 0, writeret;
|
||||||
|
|
||||||
while (fgets(inbuf, HTML_BUFSIZE, infile) != NULL) {
|
while (fgets (inbuf, HTML_BUFSIZE, infile) != NULL)
|
||||||
for (p = inbuf; *p; p++) {
|
{
|
||||||
switch (*p) {
|
for (p = inbuf; *p; p++)
|
||||||
|
{
|
||||||
|
switch (*p)
|
||||||
|
{
|
||||||
case '}':
|
case '}':
|
||||||
if (in_variable) {
|
if (in_variable)
|
||||||
|
{
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
if (!
|
if (!(varval = lookup_variable (connptr, varstart)))
|
||||||
(varval =
|
|
||||||
lookup_variable(connptr,
|
|
||||||
varstart)))
|
|
||||||
varval = "(unknown)";
|
varval = "(unknown)";
|
||||||
writeret =
|
writeret = write_message (connptr->client_fd, "%s", varval);
|
||||||
write_message(connptr->client_fd,
|
|
||||||
"%s", varval);
|
|
||||||
if (writeret)
|
if (writeret)
|
||||||
return (writeret);
|
return (writeret);
|
||||||
in_variable = 0;
|
in_variable = 0;
|
||||||
} else {
|
}
|
||||||
writeret =
|
else
|
||||||
write_message(connptr->client_fd,
|
{
|
||||||
"%c", *p);
|
writeret = write_message (connptr->client_fd, "%c", *p);
|
||||||
if (writeret)
|
if (writeret)
|
||||||
return (writeret);
|
return (writeret);
|
||||||
}
|
}
|
||||||
@ -150,16 +149,17 @@ send_html_file(FILE * infile, struct conn_s *connptr)
|
|||||||
* this code will fallthrough to the code that
|
* this code will fallthrough to the code that
|
||||||
* just dumps a character to the client fd.
|
* just dumps a character to the client fd.
|
||||||
*/
|
*/
|
||||||
if (!in_variable) {
|
if (!in_variable)
|
||||||
|
{
|
||||||
varstart = p + 1;
|
varstart = p + 1;
|
||||||
in_variable++;
|
in_variable++;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
in_variable = 0;
|
in_variable = 0;
|
||||||
default:
|
default:
|
||||||
if (!in_variable) {
|
if (!in_variable)
|
||||||
writeret =
|
{
|
||||||
write_message(connptr->client_fd,
|
writeret = write_message (connptr->client_fd, "%c", *p);
|
||||||
"%c", *p);
|
|
||||||
if (writeret)
|
if (writeret)
|
||||||
return (writeret);
|
return (writeret);
|
||||||
}
|
}
|
||||||
@ -201,22 +201,19 @@ send_http_error_message(struct conn_s *connptr)
|
|||||||
"<h1>%s</h1>\n"
|
"<h1>%s</h1>\n"
|
||||||
"<p>%s</p>\n"
|
"<p>%s</p>\n"
|
||||||
"<hr />\n"
|
"<hr />\n"
|
||||||
"<p><em>Generated by %s version %s.</em></p>\n"
|
"<p><em>Generated by %s version %s.</em></p>\n" "</body>\n" "</html>\n";
|
||||||
"</body>\n"
|
|
||||||
"</html>\n";
|
|
||||||
|
|
||||||
send_http_headers(connptr, connptr->error_number,
|
send_http_headers (connptr, connptr->error_number, connptr->error_string);
|
||||||
connptr->error_string);
|
|
||||||
|
|
||||||
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, "detail");
|
char *detail = lookup_variable (connptr, "detail");
|
||||||
return (write_message (connptr->client_fd, fallback_error,
|
return (write_message (connptr->client_fd, fallback_error,
|
||||||
connptr->error_number,
|
connptr->error_number,
|
||||||
connptr->error_string,
|
connptr->error_string,
|
||||||
connptr->error_string,
|
connptr->error_string,
|
||||||
detail,
|
detail, PACKAGE, VERSION));
|
||||||
PACKAGE, VERSION));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = send_html_file (infile, connptr);
|
ret = send_html_file (infile, connptr);
|
||||||
@ -234,9 +231,7 @@ int
|
|||||||
add_error_variable (struct conn_s *connptr, char *key, char *val)
|
add_error_variable (struct conn_s *connptr, char *key, char *val)
|
||||||
{
|
{
|
||||||
if (!connptr->error_variables)
|
if (!connptr->error_variables)
|
||||||
if (!
|
if (!(connptr->error_variables = hashmap_create (ERRVAR_BUCKETCOUNT)))
|
||||||
(connptr->error_variables =
|
|
||||||
hashmap_create(ERRVAR_BUCKETCOUNT)))
|
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
return hashmap_insert (connptr->error_variables, key, val,
|
return hashmap_insert (connptr->error_variables, key, val,
|
||||||
@ -297,10 +292,12 @@ indicate_http_error(struct conn_s *connptr, int number, char *message, ...)
|
|||||||
|
|
||||||
va_start (ap, message);
|
va_start (ap, message);
|
||||||
|
|
||||||
while ((key = va_arg(ap, char *))) {
|
while ((key = va_arg (ap, char *)))
|
||||||
|
{
|
||||||
val = va_arg (ap, char *);
|
val = va_arg (ap, char *);
|
||||||
|
|
||||||
if (add_error_variable(connptr, key, val) == -1) {
|
if (add_error_variable (connptr, key, val) == -1)
|
||||||
|
{
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,8 @@ extern int indicate_http_error(struct conn_s *connptr, int number,
|
|||||||
char *message, ...);
|
char *message, ...);
|
||||||
extern int add_error_variable (struct conn_s *connptr, char *key, char *val);
|
extern int add_error_variable (struct conn_s *connptr, char *key, char *val);
|
||||||
extern int send_html_file (FILE * infile, struct conn_s *connptr);
|
extern int send_html_file (FILE * infile, struct conn_s *connptr);
|
||||||
extern int send_http_headers(struct conn_s *connptr, int code, char *message);
|
extern int send_http_headers (struct conn_s *connptr, int code,
|
||||||
|
char *message);
|
||||||
extern int add_standard_vars (struct conn_s *connptr);
|
extern int add_standard_vars (struct conn_s *connptr);
|
||||||
|
|
||||||
#endif /* !TINYPROXY_HTML_ERROR_H */
|
#endif /* !TINYPROXY_HTML_ERROR_H */
|
||||||
|
@ -30,9 +30,11 @@
|
|||||||
* Also, the caller MUST NOT free the memory while the structure is
|
* Also, the caller MUST NOT free the memory while the structure is
|
||||||
* still in use---bad things would happen.
|
* still in use---bad things would happen.
|
||||||
*/
|
*/
|
||||||
struct http_message_s {
|
struct http_message_s
|
||||||
|
{
|
||||||
/* Response string and code supplied on the HTTP status line */
|
/* Response string and code supplied on the HTTP status line */
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
const char *string;
|
const char *string;
|
||||||
int code;
|
int code;
|
||||||
} response;
|
} response;
|
||||||
@ -42,14 +44,16 @@ struct http_message_s {
|
|||||||
* the strings are referenced through pointers in an array.
|
* the strings are referenced through pointers in an array.
|
||||||
* I might change this to a vector in the future.
|
* I might change this to a vector in the future.
|
||||||
*/
|
*/
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
char **strings;
|
char **strings;
|
||||||
unsigned int total;
|
unsigned int total;
|
||||||
unsigned int used;
|
unsigned int used;
|
||||||
} headers;
|
} headers;
|
||||||
|
|
||||||
/* Body of the message (most likely an HTML message) */
|
/* Body of the message (most likely an HTML message) */
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
const char *text;
|
const char *text;
|
||||||
size_t length;
|
size_t length;
|
||||||
} body;
|
} body;
|
||||||
@ -93,7 +97,8 @@ http_message_create(int response_code, const char *response_string)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
msg->headers.strings = safecalloc (NUMBER_OF_HEADERS, sizeof (char *));
|
msg->headers.strings = safecalloc (NUMBER_OF_HEADERS, sizeof (char *));
|
||||||
if (msg->headers.strings == NULL) {
|
if (msg->headers.strings == NULL)
|
||||||
|
{
|
||||||
safefree (msg);
|
safefree (msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -102,7 +107,8 @@ http_message_create(int response_code, const char *response_string)
|
|||||||
|
|
||||||
/* Store the HTTP response information in the structure */
|
/* Store the HTTP response information in the structure */
|
||||||
ret = http_message_set_response (msg, response_code, response_string);
|
ret = http_message_set_response (msg, response_code, response_string);
|
||||||
if (IS_HTTP_MSG_ERROR(ret)) {
|
if (IS_HTTP_MSG_ERROR (ret))
|
||||||
|
{
|
||||||
safefree (msg->headers.strings);
|
safefree (msg->headers.strings);
|
||||||
safefree (msg);
|
safefree (msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -197,9 +203,9 @@ http_message_add_headers(http_message_t msg, char **headers, int num_headers)
|
|||||||
* If the number of headers to add is greater than the space
|
* If the number of headers to add is greater than the space
|
||||||
* available, reallocate the memory.
|
* available, reallocate the memory.
|
||||||
*/
|
*/
|
||||||
if (msg->headers.used + num_headers > msg->headers.total) {
|
if (msg->headers.used + num_headers > msg->headers.total)
|
||||||
new_headers = safecalloc(msg->headers.total * 2,
|
{
|
||||||
sizeof(char *));
|
new_headers = safecalloc (msg->headers.total * 2, sizeof (char *));
|
||||||
if (new_headers == NULL)
|
if (new_headers == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
32
src/log.c
32
src/log.c
@ -115,13 +115,17 @@ log_message(int level, char *fmt, ...)
|
|||||||
/*
|
/*
|
||||||
* Figure out if we should write the message or not.
|
* Figure out if we should write the message or not.
|
||||||
*/
|
*/
|
||||||
if (log_level == LOG_CONN) {
|
if (log_level == LOG_CONN)
|
||||||
|
{
|
||||||
if (level == LOG_INFO)
|
if (level == LOG_INFO)
|
||||||
return;
|
return;
|
||||||
} else if (log_level == LOG_INFO) {
|
}
|
||||||
|
else if (log_level == LOG_INFO)
|
||||||
|
{
|
||||||
if (level > LOG_INFO && level != LOG_CONN)
|
if (level > LOG_INFO && level != LOG_CONN)
|
||||||
return;
|
return;
|
||||||
} else if (level > log_level)
|
}
|
||||||
|
else if (level > log_level)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -136,10 +140,12 @@ log_message(int level, char *fmt, ...)
|
|||||||
* If the config file hasn't been processed, then we need to store
|
* If the config file hasn't been processed, then we need to store
|
||||||
* the messages for later processing.
|
* the messages for later processing.
|
||||||
*/
|
*/
|
||||||
if (!processed_config_file) {
|
if (!processed_config_file)
|
||||||
|
{
|
||||||
char *entry_buffer;
|
char *entry_buffer;
|
||||||
|
|
||||||
if (!log_message_storage) {
|
if (!log_message_storage)
|
||||||
|
{
|
||||||
log_message_storage = vector_create ();
|
log_message_storage = vector_create ();
|
||||||
if (!log_message_storage)
|
if (!log_message_storage)
|
||||||
goto out;
|
goto out;
|
||||||
@ -159,14 +165,17 @@ log_message(int level, char *fmt, ...)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_SYSLOG_H
|
#ifdef HAVE_SYSLOG_H
|
||||||
if (config.syslog) {
|
if (config.syslog)
|
||||||
|
{
|
||||||
# ifdef HAVE_VSYSLOG_H
|
# ifdef HAVE_VSYSLOG_H
|
||||||
vsyslog (level, fmt, args);
|
vsyslog (level, fmt, args);
|
||||||
# else
|
# else
|
||||||
vsnprintf (str, STRING_LENGTH, fmt, args);
|
vsnprintf (str, STRING_LENGTH, fmt, args);
|
||||||
syslog (level, "%s", str);
|
syslog (level, "%s", str);
|
||||||
# endif
|
# endif
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
nowtime = time (NULL);
|
nowtime = time (NULL);
|
||||||
/* Format is month day hour:minute:second (24 time) */
|
/* Format is month day hour:minute:second (24 time) */
|
||||||
@ -205,7 +214,8 @@ send_stored_logs(void)
|
|||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i != vector_length(log_message_storage); ++i) {
|
for (i = 0; i != vector_length (log_message_storage); ++i)
|
||||||
|
{
|
||||||
string = vector_getentry (log_message_storage, i, NULL);
|
string = vector_getentry (log_message_storage, i, NULL);
|
||||||
|
|
||||||
ptr = strchr (string, ' ') + 1;
|
ptr = strchr (string, ' ') + 1;
|
||||||
@ -214,10 +224,12 @@ send_stored_logs(void)
|
|||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
if (log_level == LOG_CONN && level == LOG_INFO)
|
if (log_level == LOG_CONN && level == LOG_INFO)
|
||||||
continue;
|
continue;
|
||||||
else if (log_level == LOG_INFO) {
|
else if (log_level == LOG_INFO)
|
||||||
|
{
|
||||||
if (level > LOG_INFO && level != LOG_CONN)
|
if (level > LOG_INFO && level != LOG_CONN)
|
||||||
continue;
|
continue;
|
||||||
} else if (level > log_level)
|
}
|
||||||
|
else if (level > log_level)
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -44,10 +44,12 @@ safe_write(int fd, const char *buffer, size_t count)
|
|||||||
|
|
||||||
bytestosend = count;
|
bytestosend = count;
|
||||||
|
|
||||||
while (1) {
|
while (1)
|
||||||
|
{
|
||||||
len = send (fd, buffer, bytestosend, MSG_NOSIGNAL);
|
len = send (fd, buffer, bytestosend, MSG_NOSIGNAL);
|
||||||
|
|
||||||
if (len < 0) {
|
if (len < 0)
|
||||||
|
{
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
else
|
else
|
||||||
@ -73,9 +75,11 @@ safe_read(int fd, char *buffer, size_t count)
|
|||||||
{
|
{
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
len = read (fd, buffer, count);
|
len = read (fd, buffer, count);
|
||||||
} while (len < 0 && errno == EINTR);
|
}
|
||||||
|
while (len < 0 && errno == EINTR);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -97,7 +101,8 @@ write_message(int fd, const char *fmt, ...)
|
|||||||
if ((buf = safemalloc (size)) == NULL)
|
if ((buf = safemalloc (size)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while (1) {
|
while (1)
|
||||||
|
{
|
||||||
va_start (ap, fmt);
|
va_start (ap, fmt);
|
||||||
n = vsnprintf (buf, size, fmt, ap);
|
n = vsnprintf (buf, size, fmt, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
@ -114,14 +119,17 @@ write_message(int fd, const char *fmt, ...)
|
|||||||
/* twice the old size (glibc2.0) */
|
/* twice the old size (glibc2.0) */
|
||||||
size *= 2;
|
size *= 2;
|
||||||
|
|
||||||
if ((tmpbuf = saferealloc(buf, size)) == NULL) {
|
if ((tmpbuf = saferealloc (buf, size)) == NULL)
|
||||||
|
{
|
||||||
safefree (buf);
|
safefree (buf);
|
||||||
return -1;
|
return -1;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
buf = tmpbuf;
|
buf = tmpbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (safe_write(fd, buf, n) < 0) {
|
if (safe_write (fd, buf, n) < 0)
|
||||||
|
{
|
||||||
safefree (buf);
|
safefree (buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -151,7 +159,8 @@ readline(int fd, char **whole_buffer)
|
|||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
ssize_t diff;
|
ssize_t diff;
|
||||||
|
|
||||||
struct read_lines_s {
|
struct read_lines_s
|
||||||
|
{
|
||||||
char *data;
|
char *data;
|
||||||
size_t len;
|
size_t len;
|
||||||
struct read_lines_s *next;
|
struct read_lines_s *next;
|
||||||
@ -165,7 +174,8 @@ readline(int fd, char **whole_buffer)
|
|||||||
line_ptr = first_line;
|
line_ptr = first_line;
|
||||||
|
|
||||||
whole_buffer_len = 0;
|
whole_buffer_len = 0;
|
||||||
for (;;) {
|
for (;;)
|
||||||
|
{
|
||||||
ret = recv (fd, buffer, SEGMENT_LEN, MSG_PEEK);
|
ret = recv (fd, buffer, SEGMENT_LEN, MSG_PEEK);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
goto CLEANUP;
|
goto CLEANUP;
|
||||||
@ -182,13 +192,15 @@ readline(int fd, char **whole_buffer)
|
|||||||
* Don't allow the buffer to grow without bound. If we
|
* Don't allow the buffer to grow without bound. If we
|
||||||
* get to more than MAXIMUM_BUFFER_LENGTH close.
|
* get to more than MAXIMUM_BUFFER_LENGTH close.
|
||||||
*/
|
*/
|
||||||
if (whole_buffer_len > MAXIMUM_BUFFER_LENGTH) {
|
if (whole_buffer_len > MAXIMUM_BUFFER_LENGTH)
|
||||||
|
{
|
||||||
ret = -ERANGE;
|
ret = -ERANGE;
|
||||||
goto CLEANUP;
|
goto CLEANUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
line_ptr->data = safemalloc (diff);
|
line_ptr->data = safemalloc (diff);
|
||||||
if (!line_ptr->data) {
|
if (!line_ptr->data)
|
||||||
|
{
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto CLEANUP;
|
goto CLEANUP;
|
||||||
}
|
}
|
||||||
@ -196,13 +208,15 @@ readline(int fd, char **whole_buffer)
|
|||||||
recv (fd, line_ptr->data, diff, 0);
|
recv (fd, line_ptr->data, diff, 0);
|
||||||
line_ptr->len = diff;
|
line_ptr->len = diff;
|
||||||
|
|
||||||
if (ptr) {
|
if (ptr)
|
||||||
|
{
|
||||||
line_ptr->next = NULL;
|
line_ptr->next = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
line_ptr->next = safecalloc (sizeof (struct read_lines_s), 1);
|
line_ptr->next = safecalloc (sizeof (struct read_lines_s), 1);
|
||||||
if (!line_ptr->next) {
|
if (!line_ptr->next)
|
||||||
|
{
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto CLEANUP;
|
goto CLEANUP;
|
||||||
}
|
}
|
||||||
@ -210,7 +224,8 @@ readline(int fd, char **whole_buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*whole_buffer = safemalloc (whole_buffer_len + 1);
|
*whole_buffer = safemalloc (whole_buffer_len + 1);
|
||||||
if (!*whole_buffer) {
|
if (!*whole_buffer)
|
||||||
|
{
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto CLEANUP;
|
goto CLEANUP;
|
||||||
}
|
}
|
||||||
@ -219,7 +234,8 @@ readline(int fd, char **whole_buffer)
|
|||||||
|
|
||||||
whole_buffer_len = 0;
|
whole_buffer_len = 0;
|
||||||
line_ptr = first_line;
|
line_ptr = first_line;
|
||||||
while (line_ptr) {
|
while (line_ptr)
|
||||||
|
{
|
||||||
memcpy (*whole_buffer + whole_buffer_len, line_ptr->data,
|
memcpy (*whole_buffer + whole_buffer_len, line_ptr->data,
|
||||||
line_ptr->len);
|
line_ptr->len);
|
||||||
whole_buffer_len += line_ptr->len;
|
whole_buffer_len += line_ptr->len;
|
||||||
@ -230,13 +246,15 @@ readline(int fd, char **whole_buffer)
|
|||||||
ret = whole_buffer_len;
|
ret = whole_buffer_len;
|
||||||
|
|
||||||
CLEANUP:
|
CLEANUP:
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
line_ptr = first_line->next;
|
line_ptr = first_line->next;
|
||||||
if (first_line->data)
|
if (first_line->data)
|
||||||
safefree (first_line->data);
|
safefree (first_line->data);
|
||||||
safefree (first_line);
|
safefree (first_line);
|
||||||
first_line = line_ptr;
|
first_line = line_ptr;
|
||||||
} while (first_line);
|
}
|
||||||
|
while (first_line);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -253,14 +271,17 @@ get_ip_string(struct sockaddr *sa, char *buf, size_t buflen)
|
|||||||
assert (buflen != 0);
|
assert (buflen != 0);
|
||||||
buf[0] = '\0'; /* start with an empty string */
|
buf[0] = '\0'; /* start with an empty string */
|
||||||
|
|
||||||
switch (sa->sa_family) {
|
switch (sa->sa_family)
|
||||||
case AF_INET:{
|
{
|
||||||
|
case AF_INET:
|
||||||
|
{
|
||||||
struct sockaddr_in *sa_in = (struct sockaddr_in *) sa;
|
struct sockaddr_in *sa_in = (struct sockaddr_in *) sa;
|
||||||
|
|
||||||
inet_ntop (AF_INET, &sa_in->sin_addr, buf, buflen);
|
inet_ntop (AF_INET, &sa_in->sin_addr, buf, buflen);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AF_INET6:{
|
case AF_INET6:
|
||||||
|
{
|
||||||
struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *) sa;
|
struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *) sa;
|
||||||
|
|
||||||
inet_ntop (AF_INET6, &sa_in6->sin6_addr, buf, buflen);
|
inet_ntop (AF_INET6, &sa_in6->sin6_addr, buf, buflen);
|
||||||
@ -296,7 +317,8 @@ full_inet_pton(const char *ip, void *dst)
|
|||||||
* address formats.
|
* address formats.
|
||||||
*/
|
*/
|
||||||
n = inet_aton (ip, (struct in_addr *) dst);
|
n = inet_aton (ip, (struct in_addr *) dst);
|
||||||
if (n == 0) {
|
if (n == 0)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Simple case: "ip" wasn't an IPv4 numeric address, so
|
* Simple case: "ip" wasn't an IPv4 numeric address, so
|
||||||
* try doing the conversion as an IPv6 address. This
|
* try doing the conversion as an IPv6 address. This
|
||||||
|
443
src/reqs.c
443
src/reqs.c
@ -83,9 +83,11 @@ static vector_t ports_allowed_by_connect = NULL;
|
|||||||
void
|
void
|
||||||
add_connect_port_allowed (int port)
|
add_connect_port_allowed (int port)
|
||||||
{
|
{
|
||||||
if (!ports_allowed_by_connect) {
|
if (!ports_allowed_by_connect)
|
||||||
|
{
|
||||||
ports_allowed_by_connect = vector_create ();
|
ports_allowed_by_connect = vector_create ();
|
||||||
if (!ports_allowed_by_connect) {
|
if (!ports_allowed_by_connect)
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Could not create a list of allowed CONNECT ports");
|
"Could not create a list of allowed CONNECT ports");
|
||||||
return;
|
return;
|
||||||
@ -116,7 +118,8 @@ check_allowed_connect_ports(int port)
|
|||||||
if (!ports_allowed_by_connect)
|
if (!ports_allowed_by_connect)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (i = 0; i != vector_length(ports_allowed_by_connect); ++i) {
|
for (i = 0; i != vector_length (ports_allowed_by_connect); ++i)
|
||||||
|
{
|
||||||
data = vector_getentry (ports_allowed_by_connect, i, NULL);
|
data = vector_getentry (ports_allowed_by_connect, i, NULL);
|
||||||
if (data && *data == port)
|
if (data && *data == port)
|
||||||
return 1;
|
return 1;
|
||||||
@ -137,7 +140,8 @@ read_request_line(struct conn_s *connptr)
|
|||||||
|
|
||||||
retry:
|
retry:
|
||||||
len = readline (connptr->client_fd, &connptr->request_line);
|
len = readline (connptr->client_fd, &connptr->request_line);
|
||||||
if (len <= 0) {
|
if (len <= 0)
|
||||||
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"read_request_line: Client (file descriptor: %d) closed socket before read.",
|
"read_request_line: Client (file descriptor: %d) closed socket before read.",
|
||||||
connptr->client_fd);
|
connptr->client_fd);
|
||||||
@ -148,7 +152,8 @@ read_request_line(struct conn_s *connptr)
|
|||||||
/*
|
/*
|
||||||
* Strip the new line and carriage return from the string.
|
* Strip the new line and carriage return from the string.
|
||||||
*/
|
*/
|
||||||
if (chomp(connptr->request_line, len) == len) {
|
if (chomp (connptr->request_line, len) == len)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* If the number of characters removed is the same as the
|
* If the number of characters removed is the same as the
|
||||||
* length then it was a blank line. Free the buffer and
|
* length then it was a blank line. Free the buffer and
|
||||||
@ -242,13 +247,16 @@ extract_http_url(const char *url, struct request_s *request)
|
|||||||
|
|
||||||
/* Split the URL on the slash to separate host from path */
|
/* Split the URL on the slash to separate host from path */
|
||||||
p = strchr (url, '/');
|
p = strchr (url, '/');
|
||||||
if (p != NULL) {
|
if (p != NULL)
|
||||||
|
{
|
||||||
len = p - url;
|
len = p - url;
|
||||||
request->host = safemalloc (len + 1);
|
request->host = safemalloc (len + 1);
|
||||||
memcpy (request->host, url, len);
|
memcpy (request->host, url, len);
|
||||||
request->host[len] = '\0';
|
request->host[len] = '\0';
|
||||||
request->path = safestrdup (p);
|
request->path = safestrdup (p);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
request->host = safestrdup (url);
|
request->host = safestrdup (url);
|
||||||
request->path = safestrdup ("/");
|
request->path = safestrdup ("/");
|
||||||
}
|
}
|
||||||
@ -287,7 +295,8 @@ extract_ssl_url(const char *url, struct request_s *request)
|
|||||||
if (sscanf (url, "%[^:]:%hu", request->host, &request->port) == 2);
|
if (sscanf (url, "%[^:]:%hu", request->host, &request->port) == 2);
|
||||||
else if (sscanf (url, "%s", request->host) == 1)
|
else if (sscanf (url, "%s", request->host) == 1)
|
||||||
request->port = HTTP_PORT_SSL;
|
request->port = HTTP_PORT_SSL;
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
log_message (LOG_ERR, "extract_ssl_url: Can't parse URL.");
|
log_message (LOG_ERR, "extract_ssl_url: Can't parse URL.");
|
||||||
|
|
||||||
safefree (request->host);
|
safefree (request->host);
|
||||||
@ -311,17 +320,19 @@ upstream_add(const char *host, int port, const char *domain)
|
|||||||
char *ptr;
|
char *ptr;
|
||||||
struct upstream *up = safemalloc (sizeof (struct upstream));
|
struct upstream *up = safemalloc (sizeof (struct upstream));
|
||||||
|
|
||||||
if (!up) {
|
if (!up)
|
||||||
log_message(LOG_ERR,
|
{
|
||||||
"Unable to allocate memory in upstream_add()");
|
log_message (LOG_ERR, "Unable to allocate memory in upstream_add()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
up->host = up->domain = NULL;
|
up->host = up->domain = NULL;
|
||||||
up->ip = up->mask = 0;
|
up->ip = up->mask = 0;
|
||||||
|
|
||||||
if (domain == NULL) {
|
if (domain == NULL)
|
||||||
if (!host || host[0] == '\0' || port < 1) {
|
{
|
||||||
|
if (!host || host[0] == '\0' || 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 upstream_cleanup;
|
goto upstream_cleanup;
|
||||||
@ -332,39 +343,49 @@ upstream_add(const char *host, int port, const char *domain)
|
|||||||
|
|
||||||
log_message (LOG_INFO, "Added upstream %s:%d for [default]",
|
log_message (LOG_INFO, "Added upstream %s:%d for [default]",
|
||||||
host, port);
|
host, port);
|
||||||
} else if (host == NULL) {
|
}
|
||||||
if (!domain || domain[0] == '\0') {
|
else if (host == NULL)
|
||||||
|
{
|
||||||
|
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");
|
||||||
goto upstream_cleanup;
|
goto upstream_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = strchr (domain, '/');
|
ptr = strchr (domain, '/');
|
||||||
if (ptr) {
|
if (ptr)
|
||||||
|
{
|
||||||
struct in_addr addrstruct;
|
struct in_addr addrstruct;
|
||||||
|
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
if (inet_aton(domain, &addrstruct) != 0) {
|
if (inet_aton (domain, &addrstruct) != 0)
|
||||||
|
{
|
||||||
up->ip = ntohl (addrstruct.s_addr);
|
up->ip = ntohl (addrstruct.s_addr);
|
||||||
*ptr++ = '/';
|
*ptr++ = '/';
|
||||||
|
|
||||||
if (strchr(ptr, '.')) {
|
if (strchr (ptr, '.'))
|
||||||
|
{
|
||||||
if (inet_aton (ptr, &addrstruct) != 0)
|
if (inet_aton (ptr, &addrstruct) != 0)
|
||||||
up->mask =
|
up->mask = ntohl (addrstruct.s_addr);
|
||||||
ntohl(addrstruct.s_addr);
|
}
|
||||||
} else {
|
else
|
||||||
up->mask =
|
{
|
||||||
~((1 << (32 - atoi(ptr))) - 1);
|
up->mask = ~((1 << (32 - atoi (ptr))) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
up->domain = safestrdup (domain);
|
up->domain = safestrdup (domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_message (LOG_INFO, "Added no-upstream for %s", domain);
|
log_message (LOG_INFO, "Added no-upstream for %s", domain);
|
||||||
} else {
|
}
|
||||||
if (!host || host[0] == '\0' || port < 1 || !domain
|
else
|
||||||
|| domain == '\0') {
|
{
|
||||||
|
if (!host || host[0] == '\0' || port < 1 || !domain || domain == '\0')
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Nonsense upstream rule: invalid parameters");
|
"Nonsense upstream rule: invalid parameters");
|
||||||
goto upstream_cleanup;
|
goto upstream_cleanup;
|
||||||
@ -378,17 +399,20 @@ upstream_add(const char *host, int port, const char *domain)
|
|||||||
host, port, domain);
|
host, port, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!up->domain && !up->ip) { /* always add default to end */
|
if (!up->domain && !up->ip)
|
||||||
|
{ /* always add default to end */
|
||||||
struct upstream *tmp = config.upstream_list;
|
struct upstream *tmp = config.upstream_list;
|
||||||
|
|
||||||
while (tmp) {
|
while (tmp)
|
||||||
if (!tmp->domain && !tmp->ip) {
|
{
|
||||||
log_message(LOG_WARNING,
|
if (!tmp->domain && !tmp->ip)
|
||||||
"Duplicate default upstream");
|
{
|
||||||
|
log_message (LOG_WARNING, "Duplicate default upstream");
|
||||||
goto upstream_cleanup;
|
goto upstream_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tmp->next) {
|
if (!tmp->next)
|
||||||
|
{
|
||||||
up->next = NULL;
|
up->next = NULL;
|
||||||
tmp->next = up;
|
tmp->next = up;
|
||||||
return;
|
return;
|
||||||
@ -421,12 +445,15 @@ upstream_get(char *host)
|
|||||||
|
|
||||||
in_addr_t my_ip = INADDR_NONE;
|
in_addr_t my_ip = INADDR_NONE;
|
||||||
|
|
||||||
while (up) {
|
while (up)
|
||||||
if (up->domain) {
|
{
|
||||||
|
if (up->domain)
|
||||||
|
{
|
||||||
if (strcasecmp (host, up->domain) == 0)
|
if (strcasecmp (host, up->domain) == 0)
|
||||||
break; /* exact match */
|
break; /* exact match */
|
||||||
|
|
||||||
if (up->domain[0] == '.') {
|
if (up->domain[0] == '.')
|
||||||
|
{
|
||||||
char *dot = strchr (host, '.');
|
char *dot = strchr (host, '.');
|
||||||
|
|
||||||
if (!dot && !up->domain[1])
|
if (!dot && !up->domain[1])
|
||||||
@ -438,13 +465,17 @@ upstream_get(char *host)
|
|||||||
if (dot)
|
if (dot)
|
||||||
break; /* subdomain match */
|
break; /* subdomain match */
|
||||||
}
|
}
|
||||||
} else if (up->ip) {
|
}
|
||||||
|
else if (up->ip)
|
||||||
|
{
|
||||||
if (my_ip == INADDR_NONE)
|
if (my_ip == INADDR_NONE)
|
||||||
my_ip = ntohl (inet_addr (host));
|
my_ip = ntohl (inet_addr (host));
|
||||||
|
|
||||||
if ((my_ip & up->mask) == up->ip)
|
if ((my_ip & up->mask) == up->ip)
|
||||||
break;
|
break;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
break; /* No domain or IP, default upstream */
|
break; /* No domain or IP, default upstream */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,7 +559,8 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
url = safemalloc (request_len);
|
url = safemalloc (request_len);
|
||||||
request->protocol = safemalloc (request_len);
|
request->protocol = safemalloc (request_len);
|
||||||
|
|
||||||
if (!request->method || !url || !request->protocol) {
|
if (!request->method || !url || !request->protocol)
|
||||||
|
{
|
||||||
safefree (url);
|
safefree (url);
|
||||||
free_request_struct (request);
|
free_request_struct (request);
|
||||||
|
|
||||||
@ -537,20 +569,22 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
|
|
||||||
ret = sscanf (connptr->request_line, "%[^ ] %[^ ] %[^ ]",
|
ret = sscanf (connptr->request_line, "%[^ ] %[^ ] %[^ ]",
|
||||||
request->method, url, request->protocol);
|
request->method, url, request->protocol);
|
||||||
if (ret == 2 && !strcasecmp(request->method, "GET")) {
|
if (ret == 2 && !strcasecmp (request->method, "GET"))
|
||||||
|
{
|
||||||
request->protocol[0] = 0;
|
request->protocol[0] = 0;
|
||||||
|
|
||||||
/* Indicate that this is a HTTP/0.9 GET request */
|
/* Indicate that this is a HTTP/0.9 GET request */
|
||||||
connptr->protocol.major = 0;
|
connptr->protocol.major = 0;
|
||||||
connptr->protocol.minor = 9;
|
connptr->protocol.minor = 9;
|
||||||
} else if (ret == 3 && !strncasecmp(request->protocol, "HTTP/", 5)) {
|
}
|
||||||
|
else if (ret == 3 && !strncasecmp (request->protocol, "HTTP/", 5))
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Break apart the protocol and update the connection
|
* Break apart the protocol and update the connection
|
||||||
* structure.
|
* structure.
|
||||||
*/
|
*/
|
||||||
ret = sscanf (request->protocol + 5, "%u.%u",
|
ret = sscanf (request->protocol + 5, "%u.%u",
|
||||||
&connptr->protocol.major,
|
&connptr->protocol.major, &connptr->protocol.minor);
|
||||||
&connptr->protocol.minor);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the conversion doesn't succeed, drop down below and
|
* If the conversion doesn't succeed, drop down below and
|
||||||
@ -558,7 +592,9 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
*/
|
*/
|
||||||
if (ret != 2)
|
if (ret != 2)
|
||||||
goto BAD_REQUEST_ERROR;
|
goto BAD_REQUEST_ERROR;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
BAD_REQUEST_ERROR:
|
BAD_REQUEST_ERROR:
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"process_request: Bad Request on file descriptor %d",
|
"process_request: Bad Request on file descriptor %d",
|
||||||
@ -573,7 +609,8 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!url) {
|
if (!url)
|
||||||
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"process_request: Null URL on file descriptor %d",
|
"process_request: Null URL on file descriptor %d",
|
||||||
connptr->client_fd);
|
connptr->client_fd);
|
||||||
@ -587,7 +624,8 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#ifdef REVERSE_SUPPORT
|
#ifdef REVERSE_SUPPORT
|
||||||
if (config.reversepath_list != NULL) {
|
if (config.reversepath_list != NULL)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Rewrite the URL based on the reverse path. After calling
|
* Rewrite the URL based on the reverse path. After calling
|
||||||
* reverse_rewrite_url "url" can be freed since we either
|
* reverse_rewrite_url "url" can be freed since we either
|
||||||
@ -599,20 +637,25 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
reverse_url = reverse_rewrite_url (connptr, hashofheaders, url);
|
reverse_url = reverse_rewrite_url (connptr, hashofheaders, url);
|
||||||
safefree (url);
|
safefree (url);
|
||||||
|
|
||||||
if (!reverse_url) {
|
if (!reverse_url)
|
||||||
|
{
|
||||||
free_request_struct (request);
|
free_request_struct (request);
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
url = reverse_url;
|
url = reverse_url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (strncasecmp (url, "http://", 7) == 0
|
if (strncasecmp (url, "http://", 7) == 0
|
||||||
|| (UPSTREAM_CONFIGURED() && strncasecmp(url, "ftp://", 6) == 0)) {
|
|| (UPSTREAM_CONFIGURED () && strncasecmp (url, "ftp://", 6) == 0))
|
||||||
|
{
|
||||||
char *skipped_type = strstr (url, "//") + 2;
|
char *skipped_type = strstr (url, "//") + 2;
|
||||||
|
|
||||||
if (extract_http_url(skipped_type, request) < 0) {
|
if (extract_http_url (skipped_type, request) < 0)
|
||||||
|
{
|
||||||
indicate_http_error (connptr, 400, "Bad Request",
|
indicate_http_error (connptr, 400, "Bad Request",
|
||||||
"detail", "Could not parse URL",
|
"detail", "Could not parse URL",
|
||||||
"url", url, NULL);
|
"url", url, NULL);
|
||||||
@ -622,8 +665,11 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else if (strcmp(request->method, "CONNECT") == 0) {
|
}
|
||||||
if (extract_ssl_url(url, request) < 0) {
|
else if (strcmp (request->method, "CONNECT") == 0)
|
||||||
|
{
|
||||||
|
if (extract_ssl_url (url, request) < 0)
|
||||||
|
{
|
||||||
indicate_http_error (connptr, 400, "Bad Request",
|
indicate_http_error (connptr, 400, "Bad Request",
|
||||||
"detail", "Could not parse URL",
|
"detail", "Could not parse URL",
|
||||||
"url", url, NULL);
|
"url", url, NULL);
|
||||||
@ -635,15 +681,15 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Verify that the port in the CONNECT method is allowed */
|
/* Verify that the port in the CONNECT method is allowed */
|
||||||
if (!check_allowed_connect_ports(request->port)) {
|
if (!check_allowed_connect_ports (request->port))
|
||||||
|
{
|
||||||
indicate_http_error (connptr, 403, "Access violation",
|
indicate_http_error (connptr, 403, "Access violation",
|
||||||
"detail",
|
"detail",
|
||||||
"The CONNECT method not allowed "
|
"The CONNECT method not allowed "
|
||||||
"with the port you tried to use.",
|
"with the port you tried to use.",
|
||||||
"url", url, NULL);
|
"url", url, NULL);
|
||||||
log_message (LOG_INFO,
|
log_message (LOG_INFO,
|
||||||
"Refused CONNECT method on port %d",
|
"Refused CONNECT method on port %d", request->port);
|
||||||
request->port);
|
|
||||||
|
|
||||||
safefree (url);
|
safefree (url);
|
||||||
free_request_struct (request);
|
free_request_struct (request);
|
||||||
@ -652,19 +698,23 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
}
|
}
|
||||||
|
|
||||||
connptr->connect_method = TRUE;
|
connptr->connect_method = TRUE;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
#ifdef TRANSPARENT_PROXY
|
#ifdef TRANSPARENT_PROXY
|
||||||
if (!do_transparent_proxy(connptr, hashofheaders, request, &config, url)) {
|
if (!do_transparent_proxy
|
||||||
|
(connptr, hashofheaders, request, &config, url))
|
||||||
|
{
|
||||||
safefree (url);
|
safefree (url);
|
||||||
free_request_struct (request);
|
free_request_struct (request);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
indicate_http_error (connptr, 501, "Not Implemented",
|
indicate_http_error (connptr, 501, "Not Implemented",
|
||||||
"detail", "Unknown method or unsupported protocol.",
|
"detail",
|
||||||
"url", url, NULL);
|
"Unknown method or unsupported protocol.", "url",
|
||||||
log_message(LOG_INFO,
|
url, NULL);
|
||||||
"Unknown method (%s) or protocol (%s)",
|
log_message (LOG_INFO, "Unknown method (%s) or protocol (%s)",
|
||||||
request->method, url);
|
request->method, url);
|
||||||
safefree (url);
|
safefree (url);
|
||||||
free_request_struct (request);
|
free_request_struct (request);
|
||||||
@ -677,19 +727,20 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
/*
|
/*
|
||||||
* Filter restricted domains/urls
|
* Filter restricted domains/urls
|
||||||
*/
|
*/
|
||||||
if (config.filter) {
|
if (config.filter)
|
||||||
|
{
|
||||||
if (config.filter_url)
|
if (config.filter_url)
|
||||||
ret = filter_url (url);
|
ret = filter_url (url);
|
||||||
else
|
else
|
||||||
ret = filter_domain (request->host);
|
ret = filter_domain (request->host);
|
||||||
|
|
||||||
if (ret) {
|
if (ret)
|
||||||
|
{
|
||||||
update_stats (STAT_DENIED);
|
update_stats (STAT_DENIED);
|
||||||
|
|
||||||
if (config.filter_url)
|
if (config.filter_url)
|
||||||
log_message (LOG_NOTICE,
|
log_message (LOG_NOTICE,
|
||||||
"Proxying refused on filtered url \"%s\"",
|
"Proxying refused on filtered url \"%s\"", url);
|
||||||
url);
|
|
||||||
else
|
else
|
||||||
log_message (LOG_NOTICE,
|
log_message (LOG_NOTICE,
|
||||||
"Proxying refused on filtered domain \"%s\"",
|
"Proxying refused on filtered domain \"%s\"",
|
||||||
@ -713,7 +764,8 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
/*
|
/*
|
||||||
* Check to see if they're requesting the stat host
|
* Check to see if they're requesting the stat host
|
||||||
*/
|
*/
|
||||||
if (config.stathost && strcmp(config.stathost, request->host) == 0) {
|
if (config.stathost && strcmp (config.stathost, request->host) == 0)
|
||||||
|
{
|
||||||
log_message (LOG_NOTICE, "Request for the stathost.");
|
log_message (LOG_NOTICE, "Request for the stathost.");
|
||||||
connptr->show_stats = TRUE;
|
connptr->show_stats = TRUE;
|
||||||
|
|
||||||
@ -740,19 +792,21 @@ pull_client_data(struct conn_s *connptr, long int length)
|
|||||||
if (!buffer)
|
if (!buffer)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
do {
|
do
|
||||||
len = safe_read(connptr->client_fd, buffer,
|
{
|
||||||
min(MAXBUFFSIZE, length));
|
len = safe_read (connptr->client_fd, buffer, min (MAXBUFFSIZE, length));
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
goto ERROR_EXIT;
|
goto ERROR_EXIT;
|
||||||
|
|
||||||
if (!connptr->error_variables) {
|
if (!connptr->error_variables)
|
||||||
|
{
|
||||||
if (safe_write (connptr->server_fd, buffer, len) < 0)
|
if (safe_write (connptr->server_fd, buffer, len) < 0)
|
||||||
goto ERROR_EXIT;
|
goto ERROR_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
length -= len;
|
length -= len;
|
||||||
} while (length > 0);
|
}
|
||||||
|
while (length > 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BUG FIX: Internet Explorer will leave two bytes (carriage
|
* BUG FIX: Internet Explorer will leave two bytes (carriage
|
||||||
@ -832,8 +886,10 @@ get_all_headers(int fd, hashmap_t hashofheaders)
|
|||||||
assert (fd >= 0);
|
assert (fd >= 0);
|
||||||
assert (hashofheaders != NULL);
|
assert (hashofheaders != NULL);
|
||||||
|
|
||||||
for (;;) {
|
for (;;)
|
||||||
if ((len = readline(fd, &header)) <= 0) {
|
{
|
||||||
|
if ((len = readline (fd, &header)) <= 0)
|
||||||
|
{
|
||||||
safefree (header);
|
safefree (header);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -842,7 +898,8 @@ get_all_headers(int fd, hashmap_t hashofheaders)
|
|||||||
* If we received just a CR LF on a line, the headers are
|
* If we received just a CR LF on a line, the headers are
|
||||||
* finished.
|
* finished.
|
||||||
*/
|
*/
|
||||||
if (CHECK_CRLF(header, len)) {
|
if (CHECK_CRLF (header, len))
|
||||||
|
{
|
||||||
safefree (header);
|
safefree (header);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -858,7 +915,8 @@ get_all_headers(int fd, hashmap_t hashofheaders)
|
|||||||
*
|
*
|
||||||
* FIXME: Might need to change this to a more robust check.
|
* FIXME: Might need to change this to a more robust check.
|
||||||
*/
|
*/
|
||||||
if (strncasecmp(header, "HTTP/", 5) == 0) {
|
if (strncasecmp (header, "HTTP/", 5) == 0)
|
||||||
|
{
|
||||||
double_cgi = TRUE;
|
double_cgi = TRUE;
|
||||||
|
|
||||||
safefree (header);
|
safefree (header);
|
||||||
@ -866,8 +924,8 @@ get_all_headers(int fd, hashmap_t hashofheaders)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!double_cgi
|
if (!double_cgi
|
||||||
&& add_header_to_connection(hashofheaders, header,
|
&& add_header_to_connection (hashofheaders, header, len) < 0)
|
||||||
len) < 0) {
|
{
|
||||||
safefree (header);
|
safefree (header);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -893,11 +951,10 @@ remove_connection_headers(hashmap_t hashofheaders)
|
|||||||
ssize_t len;
|
ssize_t len;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i != (sizeof(headers) / sizeof(char *)); ++i) {
|
for (i = 0; i != (sizeof (headers) / sizeof (char *)); ++i)
|
||||||
|
{
|
||||||
/* Look for the connection header. If it's not found, return. */
|
/* Look for the connection header. If it's not found, return. */
|
||||||
len =
|
len = hashmap_entry_by_key (hashofheaders, headers[i], (void **) &data);
|
||||||
hashmap_entry_by_key(hashofheaders, headers[i],
|
|
||||||
(void **)&data);
|
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -914,7 +971,8 @@ remove_connection_headers(hashmap_t hashofheaders)
|
|||||||
* token and remove them from the hashofheaders.
|
* token and remove them from the hashofheaders.
|
||||||
*/
|
*/
|
||||||
ptr = data;
|
ptr = data;
|
||||||
while (ptr < data + len) {
|
while (ptr < data + len)
|
||||||
|
{
|
||||||
hashmap_remove (hashofheaders, ptr);
|
hashmap_remove (hashofheaders, ptr);
|
||||||
|
|
||||||
/* Advance ptr to the next token */
|
/* Advance ptr to the next token */
|
||||||
@ -942,8 +1000,7 @@ get_content_length(hashmap_t hashofheaders)
|
|||||||
long content_length = -1;
|
long content_length = -1;
|
||||||
|
|
||||||
len =
|
len =
|
||||||
hashmap_entry_by_key(hashofheaders, "content-length",
|
hashmap_entry_by_key (hashofheaders, "content-length", (void **) &data);
|
||||||
(void **)&data);
|
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
content_length = atol (data);
|
content_length = atol (data);
|
||||||
|
|
||||||
@ -966,9 +1023,12 @@ write_via_header(int fd, hashmap_t hashofheaders,
|
|||||||
char *data;
|
char *data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (config.via_proxy_name) {
|
if (config.via_proxy_name)
|
||||||
|
{
|
||||||
strlcpy (hostname, config.via_proxy_name, sizeof (hostname));
|
strlcpy (hostname, config.via_proxy_name, sizeof (hostname));
|
||||||
} else if (gethostname(hostname, sizeof(hostname)) < 0) {
|
}
|
||||||
|
else if (gethostname (hostname, sizeof (hostname)) < 0)
|
||||||
|
{
|
||||||
strcpy (hostname, "unknown");
|
strcpy (hostname, "unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -977,14 +1037,16 @@ write_via_header(int fd, hashmap_t hashofheaders,
|
|||||||
* of processing.
|
* of processing.
|
||||||
*/
|
*/
|
||||||
len = hashmap_entry_by_key (hashofheaders, "via", (void **) &data);
|
len = hashmap_entry_by_key (hashofheaders, "via", (void **) &data);
|
||||||
if (len > 0) {
|
if (len > 0)
|
||||||
|
{
|
||||||
ret = write_message (fd,
|
ret = write_message (fd,
|
||||||
"Via: %s, %hu.%hu %s (%s/%s)\r\n",
|
"Via: %s, %hu.%hu %s (%s/%s)\r\n",
|
||||||
data,
|
data, major, minor, hostname, PACKAGE, VERSION);
|
||||||
major, minor, hostname, PACKAGE, VERSION);
|
|
||||||
|
|
||||||
hashmap_remove (hashofheaders, "via");
|
hashmap_remove (hashofheaders, "via");
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ret = write_message (fd,
|
ret = write_message (fd,
|
||||||
"Via: %hu.%hu %s (%s/%s)\r\n",
|
"Via: %hu.%hu %s (%s/%s)\r\n",
|
||||||
major, minor, hostname, PACKAGE, VERSION);
|
major, minor, hostname, PACKAGE, VERSION);
|
||||||
@ -1028,9 +1090,9 @@ process_client_headers(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
* proxy is in use.)
|
* proxy is in use.)
|
||||||
*/
|
*/
|
||||||
if (connptr->server_fd == -1 || connptr->show_stats
|
if (connptr->server_fd == -1 || connptr->show_stats
|
||||||
|| (connptr->connect_method && (connptr->upstream_proxy == NULL))) {
|
|| (connptr->connect_method && (connptr->upstream_proxy == NULL)))
|
||||||
log_message(LOG_INFO,
|
{
|
||||||
"Not sending client headers to remote machine");
|
log_message (LOG_INFO, "Not sending client headers to remote machine");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1049,15 +1111,16 @@ process_client_headers(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
/*
|
/*
|
||||||
* Delete the headers listed in the skipheaders list
|
* Delete the headers listed in the skipheaders list
|
||||||
*/
|
*/
|
||||||
for (i = 0; i != (sizeof(skipheaders) / sizeof(char *)); i++) {
|
for (i = 0; i != (sizeof (skipheaders) / sizeof (char *)); i++)
|
||||||
|
{
|
||||||
hashmap_remove (hashofheaders, skipheaders[i]);
|
hashmap_remove (hashofheaders, skipheaders[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send, or add the Via header */
|
/* Send, or add the Via header */
|
||||||
ret = write_via_header (connptr->server_fd, hashofheaders,
|
ret = write_via_header (connptr->server_fd, hashofheaders,
|
||||||
connptr->protocol.major,
|
connptr->protocol.major, connptr->protocol.minor);
|
||||||
connptr->protocol.minor);
|
if (ret < 0)
|
||||||
if (ret < 0) {
|
{
|
||||||
indicate_http_error (connptr, 503,
|
indicate_http_error (connptr, 503,
|
||||||
"Could not send data to remote server",
|
"Could not send data to remote server",
|
||||||
"detail",
|
"detail",
|
||||||
@ -1070,17 +1133,20 @@ process_client_headers(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
* Output all the remaining headers to the remote machine.
|
* Output all the remaining headers to the remote machine.
|
||||||
*/
|
*/
|
||||||
iter = hashmap_first (hashofheaders);
|
iter = hashmap_first (hashofheaders);
|
||||||
if (iter >= 0) {
|
if (iter >= 0)
|
||||||
for (; !hashmap_is_end(hashofheaders, iter); ++iter) {
|
{
|
||||||
|
for (; !hashmap_is_end (hashofheaders, iter); ++iter)
|
||||||
|
{
|
||||||
hashmap_return_entry (hashofheaders,
|
hashmap_return_entry (hashofheaders,
|
||||||
iter, &data, (void **) &header);
|
iter, &data, (void **) &header);
|
||||||
|
|
||||||
if (!is_anonymous_enabled()
|
if (!is_anonymous_enabled () || anonymous_search (data) > 0)
|
||||||
|| anonymous_search(data) > 0) {
|
{
|
||||||
ret =
|
ret =
|
||||||
write_message (connptr->server_fd,
|
write_message (connptr->server_fd,
|
||||||
"%s: %s\r\n", data, header);
|
"%s: %s\r\n", data, header);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
|
{
|
||||||
indicate_http_error (connptr, 503,
|
indicate_http_error (connptr, 503,
|
||||||
"Could not send data to remote server",
|
"Could not send data to remote server",
|
||||||
"detail",
|
"detail",
|
||||||
@ -1105,8 +1171,7 @@ process_client_headers(struct conn_s *connptr, hashmap_t hashofheaders)
|
|||||||
*/
|
*/
|
||||||
PULL_CLIENT_DATA:
|
PULL_CLIENT_DATA:
|
||||||
if (connptr->content_length.client > 0)
|
if (connptr->content_length.client > 0)
|
||||||
return pull_client_data(connptr,
|
return pull_client_data (connptr, connptr->content_length.client);
|
||||||
connptr->content_length.client);
|
|
||||||
else
|
else
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1148,7 +1213,8 @@ process_server_headers(struct conn_s *connptr)
|
|||||||
/*
|
/*
|
||||||
* Strip the new line and character return from the string.
|
* Strip the new line and character return from the string.
|
||||||
*/
|
*/
|
||||||
if (chomp(response_line, len) == len) {
|
if (chomp (response_line, len) == len)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* If the number of characters removed is the same as the
|
* If the number of characters removed is the same as the
|
||||||
* length then it was a blank line. Free the buffer and
|
* length then it was a blank line. Free the buffer and
|
||||||
@ -1159,7 +1225,8 @@ process_server_headers(struct conn_s *connptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
hashofheaders = hashmap_create (HEADER_BUCKETS);
|
hashofheaders = hashmap_create (HEADER_BUCKETS);
|
||||||
if (!hashofheaders) {
|
if (!hashofheaders)
|
||||||
|
{
|
||||||
safefree (response_line);
|
safefree (response_line);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1167,7 +1234,8 @@ process_server_headers(struct conn_s *connptr)
|
|||||||
/*
|
/*
|
||||||
* Get all the headers from the remote server in a big hash
|
* Get all the headers from the remote server in a big hash
|
||||||
*/
|
*/
|
||||||
if (get_all_headers(connptr->server_fd, hashofheaders) < 0) {
|
if (get_all_headers (connptr->server_fd, hashofheaders) < 0)
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Could not retrieve all the headers from the remote server.");
|
"Could not retrieve all the headers from the remote server.");
|
||||||
hashmap_delete (hashofheaders);
|
hashmap_delete (hashofheaders);
|
||||||
@ -1188,7 +1256,8 @@ process_server_headers(struct conn_s *connptr)
|
|||||||
* CAN NOT send any of that information back to the client.
|
* CAN NOT send any of that information back to the client.
|
||||||
* Instead we'll free all the memory and return.
|
* Instead we'll free all the memory and return.
|
||||||
*/
|
*/
|
||||||
if (connptr->protocol.major < 1) {
|
if (connptr->protocol.major < 1)
|
||||||
|
{
|
||||||
hashmap_delete (hashofheaders);
|
hashmap_delete (hashofheaders);
|
||||||
safefree (response_line);
|
safefree (response_line);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1215,20 +1284,21 @@ process_server_headers(struct conn_s *connptr)
|
|||||||
/*
|
/*
|
||||||
* Delete the headers listed in the skipheaders list
|
* Delete the headers listed in the skipheaders list
|
||||||
*/
|
*/
|
||||||
for (i = 0; i != (sizeof(skipheaders) / sizeof(char *)); i++) {
|
for (i = 0; i != (sizeof (skipheaders) / sizeof (char *)); i++)
|
||||||
|
{
|
||||||
hashmap_remove (hashofheaders, skipheaders[i]);
|
hashmap_remove (hashofheaders, skipheaders[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send, or add the Via header */
|
/* Send, or add the Via header */
|
||||||
ret = write_via_header (connptr->client_fd, hashofheaders,
|
ret = write_via_header (connptr->client_fd, hashofheaders,
|
||||||
connptr->protocol.major,
|
connptr->protocol.major, connptr->protocol.minor);
|
||||||
connptr->protocol.minor);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto ERROR_EXIT;
|
goto ERROR_EXIT;
|
||||||
|
|
||||||
#ifdef REVERSE_SUPPORT
|
#ifdef REVERSE_SUPPORT
|
||||||
/* Write tracking cookie for the magical reverse proxy path hack */
|
/* Write tracking cookie for the magical reverse proxy path hack */
|
||||||
if (config.reversemagic && connptr->reversepath) {
|
if (config.reversemagic && connptr->reversepath)
|
||||||
|
{
|
||||||
ret = write_message (connptr->client_fd,
|
ret = write_message (connptr->client_fd,
|
||||||
"Set-Cookie: " REVERSE_COOKIE
|
"Set-Cookie: " REVERSE_COOKIE
|
||||||
"=%s; path=/\r\n", connptr->reversepath);
|
"=%s; path=/\r\n", connptr->reversepath);
|
||||||
@ -1238,19 +1308,20 @@ process_server_headers(struct conn_s *connptr)
|
|||||||
|
|
||||||
/* Rewrite the HTTP redirect if needed */
|
/* Rewrite the HTTP redirect if needed */
|
||||||
if (config.reversebaseurl &&
|
if (config.reversebaseurl &&
|
||||||
hashmap_entry_by_key(hashofheaders, "location",
|
hashmap_entry_by_key (hashofheaders, "location", (void **) &header) > 0)
|
||||||
(void **)&header) > 0) {
|
{
|
||||||
|
|
||||||
/* Look for a matching entry in the reversepath list */
|
/* Look for a matching entry in the reversepath list */
|
||||||
while (reverse) {
|
while (reverse)
|
||||||
|
{
|
||||||
if (strncasecmp (header,
|
if (strncasecmp (header,
|
||||||
reverse->url,
|
reverse->url, (len = strlen (reverse->url))) == 0)
|
||||||
(len = strlen(reverse->url))) == 0)
|
|
||||||
break;
|
break;
|
||||||
reverse = reverse->next;
|
reverse = reverse->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reverse) {
|
if (reverse)
|
||||||
|
{
|
||||||
ret =
|
ret =
|
||||||
write_message (connptr->client_fd,
|
write_message (connptr->client_fd,
|
||||||
"Location: %s%s%s\r\n",
|
"Location: %s%s%s\r\n",
|
||||||
@ -1272,8 +1343,10 @@ process_server_headers(struct conn_s *connptr)
|
|||||||
* All right, output all the remaining headers to the client.
|
* All right, output all the remaining headers to the client.
|
||||||
*/
|
*/
|
||||||
iter = hashmap_first (hashofheaders);
|
iter = hashmap_first (hashofheaders);
|
||||||
if (iter >= 0) {
|
if (iter >= 0)
|
||||||
for (; !hashmap_is_end(hashofheaders, iter); ++iter) {
|
{
|
||||||
|
for (; !hashmap_is_end (hashofheaders, iter); ++iter)
|
||||||
|
{
|
||||||
hashmap_return_entry (hashofheaders,
|
hashmap_return_entry (hashofheaders,
|
||||||
iter, &data, (void **) &header);
|
iter, &data, (void **) &header);
|
||||||
|
|
||||||
@ -1320,12 +1393,12 @@ relay_connection(struct conn_s *connptr)
|
|||||||
|
|
||||||
last_access = time (NULL);
|
last_access = time (NULL);
|
||||||
|
|
||||||
for (;;) {
|
for (;;)
|
||||||
|
{
|
||||||
FD_ZERO (&rset);
|
FD_ZERO (&rset);
|
||||||
FD_ZERO (&wset);
|
FD_ZERO (&wset);
|
||||||
|
|
||||||
tv.tv_sec =
|
tv.tv_sec = config.idletimeout - difftime (time (NULL), last_access);
|
||||||
config.idletimeout - difftime(time(NULL), last_access);
|
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
if (buffer_size (connptr->sbuffer) > 0)
|
if (buffer_size (connptr->sbuffer) > 0)
|
||||||
@ -1339,32 +1412,40 @@ relay_connection(struct conn_s *connptr)
|
|||||||
|
|
||||||
ret = select (maxfd, &rset, &wset, NULL, &tv);
|
ret = select (maxfd, &rset, &wset, NULL, &tv);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0)
|
||||||
|
{
|
||||||
tdiff = difftime (time (NULL), last_access);
|
tdiff = difftime (time (NULL), last_access);
|
||||||
if (tdiff > config.idletimeout) {
|
if (tdiff > config.idletimeout)
|
||||||
|
{
|
||||||
log_message (LOG_INFO,
|
log_message (LOG_INFO,
|
||||||
"Idle Timeout (after select) as %g > %u.",
|
"Idle Timeout (after select) as %g > %u.",
|
||||||
tdiff, config.idletimeout);
|
tdiff, config.idletimeout);
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (ret < 0) {
|
}
|
||||||
|
else if (ret < 0)
|
||||||
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"relay_connection: select() error \"%s\". Closing connection (client_fd:%d, server_fd:%d)",
|
"relay_connection: select() error \"%s\". Closing connection (client_fd:%d, server_fd:%d)",
|
||||||
strerror (errno), connptr->client_fd,
|
strerror (errno), connptr->client_fd,
|
||||||
connptr->server_fd);
|
connptr->server_fd);
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* All right, something was actually selected so mark it.
|
* All right, something was actually selected so mark it.
|
||||||
*/
|
*/
|
||||||
last_access = time (NULL);
|
last_access = time (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FD_ISSET(connptr->server_fd, &rset)) {
|
if (FD_ISSET (connptr->server_fd, &rset))
|
||||||
bytes_received =
|
{
|
||||||
read_buffer(connptr->server_fd, connptr->sbuffer);
|
bytes_received = read_buffer (connptr->server_fd, connptr->sbuffer);
|
||||||
if (bytes_received < 0)
|
if (bytes_received < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1373,15 +1454,18 @@ relay_connection(struct conn_s *connptr)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (FD_ISSET (connptr->client_fd, &rset)
|
if (FD_ISSET (connptr->client_fd, &rset)
|
||||||
&& read_buffer(connptr->client_fd, connptr->cbuffer) < 0) {
|
&& read_buffer (connptr->client_fd, connptr->cbuffer) < 0)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (FD_ISSET (connptr->server_fd, &wset)
|
if (FD_ISSET (connptr->server_fd, &wset)
|
||||||
&& write_buffer(connptr->server_fd, connptr->cbuffer) < 0) {
|
&& write_buffer (connptr->server_fd, connptr->cbuffer) < 0)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (FD_ISSET (connptr->client_fd, &wset)
|
if (FD_ISSET (connptr->client_fd, &wset)
|
||||||
&& write_buffer(connptr->client_fd, connptr->sbuffer) < 0) {
|
&& write_buffer (connptr->client_fd, connptr->sbuffer) < 0)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1391,7 +1475,8 @@ relay_connection(struct conn_s *connptr)
|
|||||||
* remainder to the client and then exit.
|
* remainder to the client and then exit.
|
||||||
*/
|
*/
|
||||||
socket_blocking (connptr->client_fd);
|
socket_blocking (connptr->client_fd);
|
||||||
while (buffer_size(connptr->sbuffer) > 0) {
|
while (buffer_size (connptr->sbuffer) > 0)
|
||||||
|
{
|
||||||
if (write_buffer (connptr->client_fd, connptr->sbuffer) < 0)
|
if (write_buffer (connptr->client_fd, connptr->sbuffer) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1401,7 +1486,8 @@ relay_connection(struct conn_s *connptr)
|
|||||||
* Try to send any remaining data to the server if we can.
|
* Try to send any remaining data to the server if we can.
|
||||||
*/
|
*/
|
||||||
socket_blocking (connptr->server_fd);
|
socket_blocking (connptr->server_fd);
|
||||||
while (buffer_size(connptr->cbuffer) > 0) {
|
while (buffer_size (connptr->cbuffer) > 0)
|
||||||
|
{
|
||||||
if (write_buffer (connptr->server_fd, connptr->cbuffer) < 0)
|
if (write_buffer (connptr->server_fd, connptr->cbuffer) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1427,7 +1513,8 @@ connect_to_upstream(struct conn_s *connptr, struct request_s *request)
|
|||||||
|
|
||||||
struct upstream *cur_upstream = connptr->upstream_proxy;
|
struct upstream *cur_upstream = connptr->upstream_proxy;
|
||||||
|
|
||||||
if (!cur_upstream) {
|
if (!cur_upstream)
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"No upstream proxy defined for %s.", request->host);
|
"No upstream proxy defined for %s.", request->host);
|
||||||
indicate_http_error (connptr, 404,
|
indicate_http_error (connptr, 404,
|
||||||
@ -1439,9 +1526,9 @@ connect_to_upstream(struct conn_s *connptr, struct request_s *request)
|
|||||||
opensock (cur_upstream->host, cur_upstream->port,
|
opensock (cur_upstream->host, cur_upstream->port,
|
||||||
connptr->server_ip_addr);
|
connptr->server_ip_addr);
|
||||||
|
|
||||||
if (connptr->server_fd < 0) {
|
if (connptr->server_fd < 0)
|
||||||
log_message(LOG_WARNING,
|
{
|
||||||
"Could not connect to upstream proxy.");
|
log_message (LOG_WARNING, "Could not connect to upstream proxy.");
|
||||||
indicate_http_error (connptr, 404,
|
indicate_http_error (connptr, 404,
|
||||||
"Unable to connect to upstream proxy",
|
"Unable to connect to upstream proxy",
|
||||||
"detail",
|
"detail",
|
||||||
@ -1459,20 +1546,24 @@ connect_to_upstream(struct conn_s *connptr, struct request_s *request)
|
|||||||
* can reuse the establish_http_connection() function. It expects a
|
* can reuse the establish_http_connection() function. It expects a
|
||||||
* method and path.
|
* method and path.
|
||||||
*/
|
*/
|
||||||
if (connptr->connect_method) {
|
if (connptr->connect_method)
|
||||||
|
{
|
||||||
len = strlen (request->host) + 7;
|
len = strlen (request->host) + 7;
|
||||||
|
|
||||||
combined_string = safemalloc (len);
|
combined_string = safemalloc (len);
|
||||||
if (!combined_string) {
|
if (!combined_string)
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(combined_string, len, "%s:%d", request->host,
|
snprintf (combined_string, len, "%s:%d", request->host, request->port);
|
||||||
request->port);
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
len = strlen (request->host) + strlen (request->path) + 14;
|
len = strlen (request->host) + strlen (request->path) + 14;
|
||||||
combined_string = safemalloc (len);
|
combined_string = safemalloc (len);
|
||||||
if (!combined_string) {
|
if (!combined_string)
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1520,12 +1611,14 @@ handle_connection(int fd)
|
|||||||
|
|
||||||
connptr = initialize_conn (fd, peer_ipaddr, peer_string,
|
connptr = initialize_conn (fd, peer_ipaddr, peer_string,
|
||||||
config.bindsame ? sock_ipaddr : 0);
|
config.bindsame ? sock_ipaddr : 0);
|
||||||
if (!connptr) {
|
if (!connptr)
|
||||||
|
{
|
||||||
close (fd);
|
close (fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_acl(fd, peer_ipaddr, peer_string) <= 0) {
|
if (check_acl (fd, peer_ipaddr, peer_string) <= 0)
|
||||||
|
{
|
||||||
update_stats (STAT_DENIED);
|
update_stats (STAT_DENIED);
|
||||||
indicate_http_error (connptr, 403, "Access denied",
|
indicate_http_error (connptr, 403, "Access denied",
|
||||||
"detail",
|
"detail",
|
||||||
@ -1536,7 +1629,8 @@ handle_connection(int fd)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_request_line(connptr) < 0) {
|
if (read_request_line (connptr) < 0)
|
||||||
|
{
|
||||||
update_stats (STAT_BADCONN);
|
update_stats (STAT_BADCONN);
|
||||||
indicate_http_error (connptr, 408, "Timeout",
|
indicate_http_error (connptr, 408, "Timeout",
|
||||||
"detail",
|
"detail",
|
||||||
@ -1550,7 +1644,8 @@ handle_connection(int fd)
|
|||||||
/*
|
/*
|
||||||
* The "hashofheaders" store the client's headers.
|
* The "hashofheaders" store the client's headers.
|
||||||
*/
|
*/
|
||||||
if (!(hashofheaders = hashmap_create(HEADER_BUCKETS))) {
|
if (!(hashofheaders = hashmap_create (HEADER_BUCKETS)))
|
||||||
|
{
|
||||||
update_stats (STAT_BADCONN);
|
update_stats (STAT_BADCONN);
|
||||||
indicate_http_error (connptr, 503, "Internal error",
|
indicate_http_error (connptr, 503, "Internal error",
|
||||||
"detail",
|
"detail",
|
||||||
@ -1564,7 +1659,8 @@ handle_connection(int fd)
|
|||||||
/*
|
/*
|
||||||
* Get all the headers from the client in a big hash.
|
* Get all the headers from the client in a big hash.
|
||||||
*/
|
*/
|
||||||
if (get_all_headers(connptr->client_fd, hashofheaders) < 0) {
|
if (get_all_headers (connptr->client_fd, hashofheaders) < 0)
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Could not retrieve all the headers from the client");
|
"Could not retrieve all the headers from the client");
|
||||||
hashmap_delete (hashofheaders);
|
hashmap_delete (hashofheaders);
|
||||||
@ -1574,8 +1670,10 @@ handle_connection(int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
request = process_request (connptr, hashofheaders);
|
request = process_request (connptr, hashofheaders);
|
||||||
if (!request) {
|
if (!request)
|
||||||
if (!connptr->error_variables && !connptr->show_stats) {
|
{
|
||||||
|
if (!connptr->error_variables && !connptr->show_stats)
|
||||||
|
{
|
||||||
update_stats (STAT_BADCONN);
|
update_stats (STAT_BADCONN);
|
||||||
destroy_conn (connptr);
|
destroy_conn (connptr);
|
||||||
hashmap_delete (hashofheaders);
|
hashmap_delete (hashofheaders);
|
||||||
@ -1585,14 +1683,19 @@ handle_connection(int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
connptr->upstream_proxy = UPSTREAM_HOST (request->host);
|
connptr->upstream_proxy = UPSTREAM_HOST (request->host);
|
||||||
if (connptr->upstream_proxy != NULL) {
|
if (connptr->upstream_proxy != NULL)
|
||||||
if (connect_to_upstream(connptr, request) < 0) {
|
{
|
||||||
|
if (connect_to_upstream (connptr, request) < 0)
|
||||||
|
{
|
||||||
goto send_error;
|
goto send_error;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
connptr->server_fd = opensock (request->host, request->port,
|
connptr->server_fd = opensock (request->host, request->port,
|
||||||
connptr->server_ip_addr);
|
connptr->server_ip_addr);
|
||||||
if (connptr->server_fd < 0) {
|
if (connptr->server_fd < 0)
|
||||||
|
{
|
||||||
indicate_http_error (connptr, 500, "Unable to connect",
|
indicate_http_error (connptr, 500, "Unable to connect",
|
||||||
"detail",
|
"detail",
|
||||||
PACKAGE
|
PACKAGE
|
||||||
@ -1612,9 +1715,11 @@ handle_connection(int fd)
|
|||||||
send_error:
|
send_error:
|
||||||
free_request_struct (request);
|
free_request_struct (request);
|
||||||
|
|
||||||
if (process_client_headers(connptr, hashofheaders) < 0) {
|
if (process_client_headers (connptr, hashofheaders) < 0)
|
||||||
|
{
|
||||||
update_stats (STAT_BADCONN);
|
update_stats (STAT_BADCONN);
|
||||||
if (!connptr->error_variables) {
|
if (!connptr->error_variables)
|
||||||
|
{
|
||||||
hashmap_delete (hashofheaders);
|
hashmap_delete (hashofheaders);
|
||||||
destroy_conn (connptr);
|
destroy_conn (connptr);
|
||||||
return;
|
return;
|
||||||
@ -1622,18 +1727,23 @@ handle_connection(int fd)
|
|||||||
}
|
}
|
||||||
hashmap_delete (hashofheaders);
|
hashmap_delete (hashofheaders);
|
||||||
|
|
||||||
if (connptr->error_variables) {
|
if (connptr->error_variables)
|
||||||
|
{
|
||||||
send_http_error_message (connptr);
|
send_http_error_message (connptr);
|
||||||
destroy_conn (connptr);
|
destroy_conn (connptr);
|
||||||
return;
|
return;
|
||||||
} else if (connptr->show_stats) {
|
}
|
||||||
|
else if (connptr->show_stats)
|
||||||
|
{
|
||||||
showstats (connptr);
|
showstats (connptr);
|
||||||
destroy_conn (connptr);
|
destroy_conn (connptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!connptr->connect_method || (connptr->upstream_proxy != NULL)) {
|
if (!connptr->connect_method || (connptr->upstream_proxy != NULL))
|
||||||
if (process_server_headers(connptr) < 0) {
|
{
|
||||||
|
if (process_server_headers (connptr) < 0)
|
||||||
|
{
|
||||||
if (connptr->error_variables)
|
if (connptr->error_variables)
|
||||||
send_http_error_message (connptr);
|
send_http_error_message (connptr);
|
||||||
|
|
||||||
@ -1641,8 +1751,11 @@ handle_connection(int fd)
|
|||||||
destroy_conn (connptr);
|
destroy_conn (connptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if (send_ssl_response(connptr) < 0) {
|
else
|
||||||
|
{
|
||||||
|
if (send_ssl_response (connptr) < 0)
|
||||||
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"handle_connection: Could not send SSL greeting to client.");
|
"handle_connection: Could not send SSL greeting to client.");
|
||||||
update_stats (STAT_BADCONN);
|
update_stats (STAT_BADCONN);
|
||||||
|
@ -34,7 +34,8 @@
|
|||||||
/*
|
/*
|
||||||
* This structure holds the information pulled from a URL request.
|
* This structure holds the information pulled from a URL request.
|
||||||
*/
|
*/
|
||||||
struct request_s {
|
struct request_s
|
||||||
|
{
|
||||||
char *method;
|
char *method;
|
||||||
char *protocol;
|
char *protocol;
|
||||||
|
|
||||||
|
@ -34,29 +34,31 @@ reversepath_add(const char *path, const char *url)
|
|||||||
{
|
{
|
||||||
struct reversepath *reverse;
|
struct reversepath *reverse;
|
||||||
|
|
||||||
if (url == NULL) {
|
if (url == NULL)
|
||||||
log_message(LOG_WARNING,
|
{
|
||||||
"Illegal reverse proxy rule: missing url");
|
log_message (LOG_WARNING, "Illegal reverse proxy rule: missing url");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strstr(url, "://")) {
|
if (!strstr (url, "://"))
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Skipping reverse proxy rule: '%s' is not a valid url",
|
"Skipping reverse proxy rule: '%s' is not a valid url",
|
||||||
url);
|
url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path && *path != '/') {
|
if (path && *path != '/')
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Skipping reverse proxy rule: path '%s' doesn't start with a /",
|
"Skipping reverse proxy rule: path '%s' doesn't start with a /",
|
||||||
path);
|
path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(reverse = safemalloc(sizeof(struct reversepath)))) {
|
if (!(reverse = safemalloc (sizeof (struct reversepath))))
|
||||||
log_message(LOG_ERR,
|
{
|
||||||
"Unable to allocate memory in reversepath_add()");
|
log_message (LOG_ERR, "Unable to allocate memory in reversepath_add()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +85,8 @@ reversepath_get(char *url)
|
|||||||
{
|
{
|
||||||
struct reversepath *reverse = config.reversepath_list;
|
struct reversepath *reverse = config.reversepath_list;
|
||||||
|
|
||||||
while (reverse) {
|
while (reverse)
|
||||||
|
{
|
||||||
if (strstr (url, reverse->path) == url)
|
if (strstr (url, reverse->path) == url)
|
||||||
return reverse;
|
return reverse;
|
||||||
|
|
||||||
@ -97,7 +100,8 @@ reversepath_get(char *url)
|
|||||||
* Rewrite the URL for reverse proxying.
|
* Rewrite the URL for reverse proxying.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
reverse_rewrite_url(struct conn_s *connptr, hashmap_t hashofheaders, char *url)
|
reverse_rewrite_url (struct conn_s *connptr, hashmap_t hashofheaders,
|
||||||
|
char *url)
|
||||||
{
|
{
|
||||||
char *rewrite_url = NULL;
|
char *rewrite_url = NULL;
|
||||||
char *cookie = NULL;
|
char *cookie = NULL;
|
||||||
@ -105,45 +109,45 @@ reverse_rewrite_url(struct conn_s *connptr, hashmap_t hashofheaders, char *url)
|
|||||||
struct reversepath *reverse;
|
struct reversepath *reverse;
|
||||||
|
|
||||||
/* Reverse requests always start with a slash */
|
/* Reverse requests always start with a slash */
|
||||||
if (*url == '/') {
|
if (*url == '/')
|
||||||
|
{
|
||||||
/* First try locating the reverse mapping by request url */
|
/* First try locating the reverse mapping by request url */
|
||||||
reverse = reversepath_get (url);
|
reverse = reversepath_get (url);
|
||||||
if (reverse) {
|
if (reverse)
|
||||||
rewrite_url = safemalloc(strlen(url) +
|
{
|
||||||
strlen(reverse->url) + 1);
|
rewrite_url = safemalloc (strlen (url) + strlen (reverse->url) + 1);
|
||||||
strcpy (rewrite_url, reverse->url);
|
strcpy (rewrite_url, reverse->url);
|
||||||
strcat (rewrite_url, url + strlen (reverse->path));
|
strcat (rewrite_url, url + strlen (reverse->path));
|
||||||
} else if (config.reversemagic
|
}
|
||||||
|
else if (config.reversemagic
|
||||||
&& hashmap_entry_by_key (hashofheaders,
|
&& hashmap_entry_by_key (hashofheaders,
|
||||||
"cookie",
|
"cookie", (void **) &cookie) > 0)
|
||||||
(void **)&cookie) > 0) {
|
{
|
||||||
|
|
||||||
/* No match - try the magical tracking cookie next */
|
/* No match - try the magical tracking cookie next */
|
||||||
if ((cookieval = strstr (cookie, REVERSE_COOKIE "="))
|
if ((cookieval = strstr (cookie, REVERSE_COOKIE "="))
|
||||||
&& (reverse =
|
&& (reverse =
|
||||||
reversepath_get(cookieval +
|
reversepath_get (cookieval + strlen (REVERSE_COOKIE) + 1)))
|
||||||
strlen(REVERSE_COOKIE) + 1))) {
|
{
|
||||||
|
|
||||||
rewrite_url = safemalloc (strlen (url) +
|
rewrite_url = safemalloc (strlen (url) +
|
||||||
strlen
|
strlen (reverse->url) + 1);
|
||||||
(reverse->url) + 1);
|
|
||||||
strcpy (rewrite_url, reverse->url);
|
strcpy (rewrite_url, reverse->url);
|
||||||
strcat (rewrite_url, url + 1);
|
strcat (rewrite_url, url + 1);
|
||||||
|
|
||||||
log_message (LOG_INFO,
|
log_message (LOG_INFO,
|
||||||
"Magical tracking cookie says: %s",
|
"Magical tracking cookie says: %s", reverse->path);
|
||||||
reverse->path);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Forward proxy support off and no reverse path match found */
|
/* Forward proxy support off and no reverse path match found */
|
||||||
if (config.reverseonly && !rewrite_url) {
|
if (config.reverseonly && !rewrite_url)
|
||||||
|
{
|
||||||
log_message (LOG_ERR, "Bad request");
|
log_message (LOG_ERR, "Bad request");
|
||||||
indicate_http_error (connptr, 400, "Bad Request",
|
indicate_http_error (connptr, 400, "Bad Request",
|
||||||
"detail",
|
"detail",
|
||||||
"Request has an invalid URL", "url",
|
"Request has an invalid URL", "url", url, NULL);
|
||||||
url, NULL);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
|
|
||||||
#include "conns.h"
|
#include "conns.h"
|
||||||
|
|
||||||
struct reversepath {
|
struct reversepath
|
||||||
|
{
|
||||||
struct reversepath *next;
|
struct reversepath *next;
|
||||||
char *path;
|
char *path;
|
||||||
char *url;
|
char *url;
|
||||||
|
56
src/sock.c
56
src/sock.c
@ -57,10 +57,12 @@ bind_socket(int sockfd, const char *addr)
|
|||||||
ressave = res;
|
ressave = res;
|
||||||
|
|
||||||
/* Loop through the addresses and try to bind to each */
|
/* Loop through the addresses and try to bind to each */
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
if (bind (sockfd, res->ai_addr, res->ai_addrlen) == 0)
|
if (bind (sockfd, res->ai_addr, res->ai_addrlen) == 0)
|
||||||
break; /* success */
|
break; /* success */
|
||||||
} while ((res = res->ai_next) != NULL);
|
}
|
||||||
|
while ((res = res->ai_next) != NULL);
|
||||||
|
|
||||||
freeaddrinfo (ressave);
|
freeaddrinfo (ressave);
|
||||||
if (res == NULL) /* was not able to bind to any address */
|
if (res == NULL) /* was not able to bind to any address */
|
||||||
@ -91,27 +93,32 @@ opensock(const char *host, int port, const char *bind_to)
|
|||||||
snprintf (portstr, sizeof (portstr), "%d", port);
|
snprintf (portstr, sizeof (portstr), "%d", port);
|
||||||
|
|
||||||
n = getaddrinfo (host, portstr, &hints, &res);
|
n = getaddrinfo (host, portstr, &hints, &res);
|
||||||
if (n != 0) {
|
if (n != 0)
|
||||||
log_message(LOG_ERR, "opensock: Could not retrieve info for %s",
|
{
|
||||||
host);
|
log_message (LOG_ERR, "opensock: Could not retrieve info for %s", host);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ressave = res;
|
ressave = res;
|
||||||
do {
|
do
|
||||||
sockfd =
|
{
|
||||||
socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
sockfd = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||||
if (sockfd < 0)
|
if (sockfd < 0)
|
||||||
continue; /* ignore this one */
|
continue; /* ignore this one */
|
||||||
|
|
||||||
/* Bind to the specified address */
|
/* Bind to the specified address */
|
||||||
if (bind_to) {
|
if (bind_to)
|
||||||
if (bind_socket(sockfd, bind_to) < 0) {
|
{
|
||||||
|
if (bind_socket (sockfd, bind_to) < 0)
|
||||||
|
{
|
||||||
close (sockfd);
|
close (sockfd);
|
||||||
continue; /* can't bind, so try again */
|
continue; /* can't bind, so try again */
|
||||||
}
|
}
|
||||||
} else if (config.bind_address) {
|
}
|
||||||
if (bind_socket(sockfd, config.bind_address) < 0) {
|
else if (config.bind_address)
|
||||||
|
{
|
||||||
|
if (bind_socket (sockfd, config.bind_address) < 0)
|
||||||
|
{
|
||||||
close (sockfd);
|
close (sockfd);
|
||||||
continue; /* can't bind, so try again */
|
continue; /* can't bind, so try again */
|
||||||
}
|
}
|
||||||
@ -121,13 +128,14 @@ opensock(const char *host, int port, const char *bind_to)
|
|||||||
break; /* success */
|
break; /* success */
|
||||||
|
|
||||||
close (sockfd);
|
close (sockfd);
|
||||||
} while ((res = res->ai_next) != NULL);
|
}
|
||||||
|
while ((res = res->ai_next) != NULL);
|
||||||
|
|
||||||
freeaddrinfo (ressave);
|
freeaddrinfo (ressave);
|
||||||
if (res == NULL) {
|
if (res == NULL)
|
||||||
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"opensock: Could not establish a connection to %s",
|
"opensock: Could not establish a connection to %s", host);
|
||||||
host);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,20 +193,25 @@ listen_sock(uint16_t port, socklen_t * addrlen)
|
|||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons (port);
|
addr.sin_port = htons (port);
|
||||||
|
|
||||||
if (config.ipAddr) {
|
if (config.ipAddr)
|
||||||
|
{
|
||||||
addr.sin_addr.s_addr = inet_addr (config.ipAddr);
|
addr.sin_addr.s_addr = inet_addr (config.ipAddr);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
addr.sin_addr.s_addr = inet_addr ("0.0.0.0");
|
addr.sin_addr.s_addr = inet_addr ("0.0.0.0");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind(listenfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if (bind (listenfd, (struct sockaddr *) &addr, sizeof (addr)) < 0)
|
||||||
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"Unable to bind listening socket because of %s",
|
"Unable to bind listening socket because of %s",
|
||||||
strerror (errno));
|
strerror (errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen(listenfd, MAXLISTEN) < 0) {
|
if (listen (listenfd, MAXLISTEN) < 0)
|
||||||
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"Unable to start listening socket because of %s",
|
"Unable to start listening socket because of %s",
|
||||||
strerror (errno));
|
strerror (errno));
|
||||||
@ -221,7 +234,8 @@ getsock_ip(int fd, char *ipaddr)
|
|||||||
|
|
||||||
assert (fd >= 0);
|
assert (fd >= 0);
|
||||||
|
|
||||||
if (getsockname(fd, (struct sockaddr *)&name, &namelen) != 0) {
|
if (getsockname (fd, (struct sockaddr *) &name, &namelen) != 0)
|
||||||
|
{
|
||||||
log_message (LOG_ERR, "getsock_ip: getsockname() error: %s",
|
log_message (LOG_ERR, "getsock_ip: getsockname() error: %s",
|
||||||
strerror (errno));
|
strerror (errno));
|
||||||
return -1;
|
return -1;
|
||||||
|
19
src/stats.c
19
src/stats.c
@ -33,7 +33,8 @@
|
|||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
struct stat_s {
|
struct stat_s
|
||||||
|
{
|
||||||
unsigned long int num_reqs;
|
unsigned long int num_reqs;
|
||||||
unsigned long int num_badcons;
|
unsigned long int num_badcons;
|
||||||
unsigned long int num_open;
|
unsigned long int num_open;
|
||||||
@ -77,9 +78,7 @@ showstats(struct conn_s *connptr)
|
|||||||
"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"
|
"<p><em>Generated by %s version %s.</em></p>\n" "</body>\n" "</html>\n";
|
||||||
"</body>\n"
|
|
||||||
"</html>\n";
|
|
||||||
|
|
||||||
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];
|
||||||
@ -91,7 +90,8 @@ showstats(struct conn_s *connptr)
|
|||||||
snprintf (denied, sizeof (denied), "%lu", stats->num_denied);
|
snprintf (denied, sizeof (denied), "%lu", stats->num_denied);
|
||||||
snprintf (refused, sizeof (refused), "%lu", stats->num_refused);
|
snprintf (refused, sizeof (refused), "%lu", stats->num_refused);
|
||||||
|
|
||||||
if (!config.statpage || (!(statfile = fopen(config.statpage, "r")))) {
|
if (!config.statpage || (!(statfile = fopen (config.statpage, "r"))))
|
||||||
|
{
|
||||||
message_buffer = safemalloc (MAXBUFFSIZE);
|
message_buffer = safemalloc (MAXBUFFSIZE);
|
||||||
if (!message_buffer)
|
if (!message_buffer)
|
||||||
return -1;
|
return -1;
|
||||||
@ -101,10 +101,10 @@ showstats(struct conn_s *connptr)
|
|||||||
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,
|
stats->num_refused, PACKAGE, VERSION);
|
||||||
PACKAGE, VERSION);
|
|
||||||
|
|
||||||
if (send_http_message(connptr, 200, "OK", message_buffer) < 0) {
|
if (send_http_message (connptr, 200, "OK", message_buffer) < 0)
|
||||||
|
{
|
||||||
safefree (message_buffer);
|
safefree (message_buffer);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -133,7 +133,8 @@ showstats(struct conn_s *connptr)
|
|||||||
int
|
int
|
||||||
update_stats (status_t update_level)
|
update_stats (status_t update_level)
|
||||||
{
|
{
|
||||||
switch (update_level) {
|
switch (update_level)
|
||||||
|
{
|
||||||
case STAT_BADCONN:
|
case STAT_BADCONN:
|
||||||
++stats->num_badcons;
|
++stats->num_badcons;
|
||||||
break;
|
break;
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
/*
|
/*
|
||||||
* Various logable statistics
|
* Various logable statistics
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
STAT_BADCONN, /* bad connection, for unknown reason */
|
STAT_BADCONN, /* bad connection, for unknown reason */
|
||||||
STAT_OPEN, /* connection opened */
|
STAT_OPEN, /* connection opened */
|
||||||
STAT_CLOSE, /* connection closed */
|
STAT_CLOSE, /* connection closed */
|
||||||
|
@ -64,7 +64,8 @@ strlcat(char *dst, const char *src, size_t size)
|
|||||||
|
|
||||||
if (len1 + len2 >= size)
|
if (len1 + len2 >= size)
|
||||||
len2 = size - len1 - 1;
|
len2 = size - len1 - 1;
|
||||||
if (len2 > 0) {
|
if (len2 > 0)
|
||||||
|
{
|
||||||
memcpy (dst + len1, src, len2);
|
memcpy (dst + len1, src, len2);
|
||||||
dst[len1 + len2] = '\0';
|
dst[len1 + len2] = '\0';
|
||||||
}
|
}
|
||||||
@ -99,7 +100,8 @@ chomp(char *buffer, size_t length)
|
|||||||
chars = 0;
|
chars = 0;
|
||||||
|
|
||||||
--length;
|
--length;
|
||||||
while (buffer[length] == '\r' || buffer[length] == '\n') {
|
while (buffer[length] == '\r' || buffer[length] == '\n')
|
||||||
|
{
|
||||||
buffer[length] = '\0';
|
buffer[length] = '\0';
|
||||||
chars++;
|
chars++;
|
||||||
|
|
||||||
|
142
src/tinyproxy.c
142
src/tinyproxy.c
@ -60,7 +60,8 @@ takesig(int sig)
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
switch (sig) {
|
switch (sig)
|
||||||
|
{
|
||||||
case SIGHUP:
|
case SIGHUP:
|
||||||
received_sighup = TRUE;
|
received_sighup = TRUE;
|
||||||
break;
|
break;
|
||||||
@ -158,7 +159,8 @@ get_id (char *str)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
tstr = str;
|
tstr = str;
|
||||||
while (*tstr != 0) {
|
while (*tstr != 0)
|
||||||
|
{
|
||||||
if (!isdigit (*tstr))
|
if (!isdigit (*tstr))
|
||||||
return -1;
|
return -1;
|
||||||
tstr++;
|
tstr++;
|
||||||
@ -187,8 +189,10 @@ main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Process the various options
|
* Process the various options
|
||||||
*/
|
*/
|
||||||
while ((optch = getopt(argc, argv, "c:vldh")) != EOF) {
|
while ((optch = getopt (argc, argv, "c:vldh")) != EOF)
|
||||||
switch (optch) {
|
{
|
||||||
|
switch (optch)
|
||||||
|
{
|
||||||
case 'v':
|
case 'v':
|
||||||
display_version ();
|
display_version ();
|
||||||
exit (EX_OK);
|
exit (EX_OK);
|
||||||
@ -200,10 +204,9 @@ main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
config.config_file = safestrdup (optarg);
|
config.config_file = safestrdup (optarg);
|
||||||
if (!config.config_file) {
|
if (!config.config_file)
|
||||||
fprintf(stderr,
|
{
|
||||||
"%s: Could not allocate memory.\n",
|
fprintf (stderr, "%s: Could not allocate memory.\n", argv[0]);
|
||||||
argv[0]);
|
|
||||||
exit (EX_SOFTWARE);
|
exit (EX_SOFTWARE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -226,13 +229,15 @@ main(int argc, char **argv)
|
|||||||
* Read in the settings from the config file.
|
* Read in the settings from the config file.
|
||||||
*/
|
*/
|
||||||
config_file = fopen (config.config_file, "r");
|
config_file = fopen (config.config_file, "r");
|
||||||
if (!config_file) {
|
if (!config_file)
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: Could not open configuration file \"%s\".\n",
|
"%s: Could not open configuration file \"%s\".\n",
|
||||||
argv[0], config.config_file);
|
argv[0], config.config_file);
|
||||||
exit (EX_SOFTWARE);
|
exit (EX_SOFTWARE);
|
||||||
}
|
}
|
||||||
if (config_compile() || config_parse(&config, config_file)) {
|
if (config_compile () || config_parse (&config, config_file))
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"Unable to parse configuration file. Not starting.\n");
|
"Unable to parse configuration file. Not starting.\n");
|
||||||
exit (EX_SOFTWARE);
|
exit (EX_SOFTWARE);
|
||||||
@ -243,19 +248,24 @@ main(int argc, char **argv)
|
|||||||
* Write to a user supplied log file if it's defined. This
|
* Write to a user supplied log file if it's defined. This
|
||||||
* will override using the syslog even if syslog is defined.
|
* will override using the syslog even if syslog is defined.
|
||||||
*/
|
*/
|
||||||
if (config.logf_name) {
|
if (config.logf_name)
|
||||||
if (open_log_file(config.logf_name) < 0) {
|
{
|
||||||
fprintf(stderr,
|
if (open_log_file (config.logf_name) < 0)
|
||||||
"%s: Could not create log file.\n", argv[0]);
|
{
|
||||||
|
fprintf (stderr, "%s: Could not create log file.\n", argv[0]);
|
||||||
exit (EX_SOFTWARE);
|
exit (EX_SOFTWARE);
|
||||||
}
|
}
|
||||||
config.syslog = FALSE; /* disable syslog */
|
config.syslog = FALSE; /* disable syslog */
|
||||||
} else if (config.syslog) {
|
}
|
||||||
|
else if (config.syslog)
|
||||||
|
{
|
||||||
if (godaemon == TRUE)
|
if (godaemon == TRUE)
|
||||||
openlog ("tinyproxy", LOG_PID, LOG_DAEMON);
|
openlog ("tinyproxy", LOG_PID, LOG_DAEMON);
|
||||||
else
|
else
|
||||||
openlog ("tinyproxy", LOG_PID, LOG_USER);
|
openlog ("tinyproxy", LOG_PID, LOG_USER);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: Either define a logfile or enable syslog logging\n",
|
"%s: Either define a logfile or enable syslog logging\n",
|
||||||
argv[0]);
|
argv[0]);
|
||||||
@ -268,22 +278,25 @@ main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Set the default values if they were not set in the config file.
|
* Set the default values if they were not set in the config file.
|
||||||
*/
|
*/
|
||||||
if (config.port == 0) {
|
if (config.port == 0)
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: You MUST set a Port in the configuration file.\n",
|
"%s: You MUST set a Port in the configuration file.\n",
|
||||||
argv[0]);
|
argv[0]);
|
||||||
exit (EX_SOFTWARE);
|
exit (EX_SOFTWARE);
|
||||||
}
|
}
|
||||||
if (!config.stathost) {
|
if (!config.stathost)
|
||||||
log_message(LOG_INFO, "Setting stathost to \"%s\".",
|
{
|
||||||
DEFAULT_STATHOST);
|
log_message (LOG_INFO, "Setting stathost to \"%s\".", DEFAULT_STATHOST);
|
||||||
config.stathost = DEFAULT_STATHOST;
|
config.stathost = DEFAULT_STATHOST;
|
||||||
}
|
}
|
||||||
if (!config.user) {
|
if (!config.user)
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"You SHOULD set a UserName in the configuration file. Using current user instead.");
|
"You SHOULD set a UserName in the configuration file. Using current user instead.");
|
||||||
}
|
}
|
||||||
if (config.idletimeout == 0) {
|
if (config.idletimeout == 0)
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Invalid idle time setting. Only values greater than zero allowed; therefore setting idle timeout to %u seconds.",
|
"Invalid idle time setting. Only values greater than zero allowed; therefore setting idle timeout to %u seconds.",
|
||||||
MAX_IDLE_TIME);
|
MAX_IDLE_TIME);
|
||||||
@ -299,7 +312,8 @@ main(int argc, char **argv)
|
|||||||
* hand in hand with Content-Length.
|
* hand in hand with Content-Length.
|
||||||
* - rjkaes
|
* - rjkaes
|
||||||
*/
|
*/
|
||||||
if (is_anonymous_enabled()) {
|
if (is_anonymous_enabled ())
|
||||||
|
{
|
||||||
anonymous_insert ("Content-Length");
|
anonymous_insert ("Content-Length");
|
||||||
anonymous_insert ("Content-Type");
|
anonymous_insert ("Content-Type");
|
||||||
}
|
}
|
||||||
@ -307,15 +321,17 @@ main(int argc, char **argv)
|
|||||||
if (godaemon == TRUE)
|
if (godaemon == TRUE)
|
||||||
makedaemon ();
|
makedaemon ();
|
||||||
|
|
||||||
if (config.pidpath) {
|
if (config.pidpath)
|
||||||
if (pidfile_create(config.pidpath) < 0) {
|
{
|
||||||
fprintf(stderr, "%s: Could not create PID file.\n",
|
if (pidfile_create (config.pidpath) < 0)
|
||||||
argv[0]);
|
{
|
||||||
|
fprintf (stderr, "%s: Could not create PID file.\n", argv[0]);
|
||||||
exit (EX_OSERR);
|
exit (EX_OSERR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set_signal_handler(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
if (set_signal_handler (SIGPIPE, SIG_IGN) == SIG_ERR)
|
||||||
|
{
|
||||||
fprintf (stderr, "%s: Could not set the \"SIGPIPE\" signal.\n",
|
fprintf (stderr, "%s: Could not set the \"SIGPIPE\" signal.\n",
|
||||||
argv[0]);
|
argv[0]);
|
||||||
exit (EX_OSERR);
|
exit (EX_OSERR);
|
||||||
@ -328,69 +344,76 @@ main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Start listening on the selected port.
|
* Start listening on the selected port.
|
||||||
*/
|
*/
|
||||||
if (child_listening_sock(config.port) < 0) {
|
if (child_listening_sock (config.port) < 0)
|
||||||
fprintf(stderr, "%s: Could not create listening socket.\n",
|
{
|
||||||
argv[0]);
|
fprintf (stderr, "%s: Could not create listening socket.\n", argv[0]);
|
||||||
exit (EX_OSERR);
|
exit (EX_OSERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Switch to a different user.
|
* Switch to a different user.
|
||||||
*/
|
*/
|
||||||
if (geteuid() == 0) {
|
if (geteuid () == 0)
|
||||||
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);
|
||||||
if (gid < 0) {
|
if (gid < 0)
|
||||||
|
{
|
||||||
thisgroup = getgrnam (config.group);
|
thisgroup = getgrnam (config.group);
|
||||||
if (!thisgroup) {
|
if (!thisgroup)
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: Unable to find "
|
"%s: Unable to find "
|
||||||
"group \"%s\".\n",
|
"group \"%s\".\n", argv[0], config.group);
|
||||||
argv[0], config.group);
|
|
||||||
exit (EX_NOUSER);
|
exit (EX_NOUSER);
|
||||||
}
|
}
|
||||||
gid = thisgroup->gr_gid;
|
gid = thisgroup->gr_gid;
|
||||||
}
|
}
|
||||||
if (setgid(gid) < 0) {
|
if (setgid (gid) < 0)
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: Unable to change to "
|
"%s: Unable to change to "
|
||||||
"group \"%s\".\n",
|
"group \"%s\".\n", argv[0], config.group);
|
||||||
argv[0], config.group);
|
|
||||||
exit (EX_CANTCREAT);
|
exit (EX_CANTCREAT);
|
||||||
}
|
}
|
||||||
log_message (LOG_INFO, "Now running as group \"%s\".",
|
log_message (LOG_INFO, "Now running as group \"%s\".",
|
||||||
config.group);
|
config.group);
|
||||||
}
|
}
|
||||||
if (config.user && strlen(config.user) > 0) {
|
if (config.user && strlen (config.user) > 0)
|
||||||
|
{
|
||||||
int uid = get_id (config.user);
|
int uid = get_id (config.user);
|
||||||
if (uid < 0) {
|
if (uid < 0)
|
||||||
|
{
|
||||||
thisuser = getpwnam (config.user);
|
thisuser = getpwnam (config.user);
|
||||||
if (!thisuser) {
|
if (!thisuser)
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: Unable to find "
|
"%s: Unable to find "
|
||||||
"user \"%s\".",
|
"user \"%s\".", argv[0], config.user);
|
||||||
argv[0], config.user);
|
|
||||||
exit (EX_NOUSER);
|
exit (EX_NOUSER);
|
||||||
}
|
}
|
||||||
uid = thisuser->pw_uid;
|
uid = thisuser->pw_uid;
|
||||||
}
|
}
|
||||||
if (setuid(uid) < 0) {
|
if (setuid (uid) < 0)
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: Unable to change to user \"%s\".",
|
"%s: Unable to change to user \"%s\".",
|
||||||
argv[0], config.user);
|
argv[0], config.user);
|
||||||
exit (EX_CANTCREAT);
|
exit (EX_CANTCREAT);
|
||||||
}
|
}
|
||||||
log_message(LOG_INFO, "Now running as user \"%s\".",
|
log_message (LOG_INFO, "Now running as user \"%s\".", config.user);
|
||||||
config.user);
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Not running as root, so not changing UID/GID.");
|
"Not running as root, so not changing UID/GID.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child_pool_create() < 0) {
|
if (child_pool_create () < 0)
|
||||||
fprintf(stderr, "%s: Could not create the pool of children.",
|
{
|
||||||
argv[0]);
|
fprintf (stderr, "%s: Could not create the pool of children.", argv[0]);
|
||||||
exit (EX_SOFTWARE);
|
exit (EX_SOFTWARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,19 +421,21 @@ main(int argc, char **argv)
|
|||||||
* These signals are only for the parent process.
|
* These signals are only for the parent process.
|
||||||
*/
|
*/
|
||||||
log_message (LOG_INFO, "Setting the various signals.");
|
log_message (LOG_INFO, "Setting the various signals.");
|
||||||
if (set_signal_handler(SIGCHLD, takesig) == SIG_ERR) {
|
if (set_signal_handler (SIGCHLD, takesig) == SIG_ERR)
|
||||||
|
{
|
||||||
fprintf (stderr, "%s: Could not set the \"SIGCHLD\" signal.\n",
|
fprintf (stderr, "%s: Could not set the \"SIGCHLD\" signal.\n",
|
||||||
argv[0]);
|
argv[0]);
|
||||||
exit (EX_OSERR);
|
exit (EX_OSERR);
|
||||||
}
|
}
|
||||||
if (set_signal_handler(SIGTERM, takesig) == SIG_ERR) {
|
if (set_signal_handler (SIGTERM, takesig) == SIG_ERR)
|
||||||
|
{
|
||||||
fprintf (stderr, "%s: Could not set the \"SIGTERM\" signal.\n",
|
fprintf (stderr, "%s: Could not set the \"SIGTERM\" signal.\n",
|
||||||
argv[0]);
|
argv[0]);
|
||||||
exit (EX_OSERR);
|
exit (EX_OSERR);
|
||||||
}
|
}
|
||||||
if (set_signal_handler(SIGHUP, takesig) == SIG_ERR) {
|
if (set_signal_handler (SIGHUP, takesig) == SIG_ERR)
|
||||||
fprintf(stderr, "%s: Could not set the \"SIGHUP\" signal.\n",
|
{
|
||||||
argv[0]);
|
fprintf (stderr, "%s: Could not set the \"SIGHUP\" signal.\n", argv[0]);
|
||||||
exit (EX_OSERR);
|
exit (EX_OSERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,7 +454,8 @@ main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Remove the PID file.
|
* Remove the PID file.
|
||||||
*/
|
*/
|
||||||
if (unlink(config.pidpath) < 0) {
|
if (unlink (config.pidpath) < 0)
|
||||||
|
{
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Could not remove PID file \"%s\": %s.",
|
"Could not remove PID file \"%s\": %s.",
|
||||||
config.pidpath, strerror (errno));
|
config.pidpath, strerror (errno));
|
||||||
|
@ -33,7 +33,8 @@
|
|||||||
* Even if upstream support is not compiled into tinyproxy, this
|
* Even if upstream support is not compiled into tinyproxy, this
|
||||||
* structure still needs to be defined.
|
* structure still needs to be defined.
|
||||||
*/
|
*/
|
||||||
struct upstream {
|
struct upstream
|
||||||
|
{
|
||||||
struct upstream *next;
|
struct upstream *next;
|
||||||
char *domain; /* optional */
|
char *domain; /* optional */
|
||||||
char *host;
|
char *host;
|
||||||
@ -44,7 +45,8 @@ struct upstream {
|
|||||||
/*
|
/*
|
||||||
* Hold all the configuration time information.
|
* Hold all the configuration time information.
|
||||||
*/
|
*/
|
||||||
struct config_s {
|
struct config_s
|
||||||
|
{
|
||||||
char *logf_name;
|
char *logf_name;
|
||||||
char *config_file;
|
char *config_file;
|
||||||
unsigned int syslog; /* boolean */
|
unsigned int syslog; /* boolean */
|
||||||
|
@ -56,26 +56,26 @@ build_url(char **url, const char *host, int port, const char *path)
|
|||||||
|
|
||||||
int
|
int
|
||||||
do_transparent_proxy (struct conn_s *connptr, hashmap_t hashofheaders,
|
do_transparent_proxy (struct conn_s *connptr, hashmap_t hashofheaders,
|
||||||
struct request_s *request, struct config_s *conf, char *url)
|
struct request_s *request, struct config_s *conf,
|
||||||
|
char *url)
|
||||||
{
|
{
|
||||||
socklen_t length;
|
socklen_t length;
|
||||||
char *data;
|
char *data;
|
||||||
|
|
||||||
length =
|
length = hashmap_entry_by_key (hashofheaders, "host", (void **) &data);
|
||||||
hashmap_entry_by_key(hashofheaders, "host", (void **)&data);
|
if (length <= 0)
|
||||||
if (length <= 0) {
|
{
|
||||||
struct sockaddr_in dest_addr;
|
struct sockaddr_in dest_addr;
|
||||||
|
|
||||||
if (getsockname
|
if (getsockname
|
||||||
(connptr->client_fd, (struct sockaddr *)&dest_addr,
|
(connptr->client_fd, (struct sockaddr *) &dest_addr, &length) < 0)
|
||||||
&length) < 0) {
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"process_request: cannot get destination IP for %d",
|
"process_request: cannot get destination IP for %d",
|
||||||
connptr->client_fd);
|
connptr->client_fd);
|
||||||
indicate_http_error (connptr, 400, "Bad Request",
|
indicate_http_error (connptr, 400, "Bad Request",
|
||||||
"detail",
|
"detail",
|
||||||
"Unknown destination",
|
"Unknown destination", "url", url, NULL);
|
||||||
"url", url, NULL);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
request->host = safemalloc (17);
|
request->host = safemalloc (17);
|
||||||
@ -84,29 +84,29 @@ do_transparent_proxy(struct conn_s *connptr, hashmap_t hashofheaders,
|
|||||||
request->path = safemalloc (strlen (url) + 1);
|
request->path = safemalloc (strlen (url) + 1);
|
||||||
strcpy (request->path, url);
|
strcpy (request->path, url);
|
||||||
safefree (url);
|
safefree (url);
|
||||||
build_url(&url, request->host, request->port,
|
build_url (&url, request->host, request->port, request->path);
|
||||||
request->path);
|
|
||||||
log_message (LOG_INFO,
|
log_message (LOG_INFO,
|
||||||
"process_request: trans IP %s %s for %d",
|
"process_request: trans IP %s %s for %d",
|
||||||
request->method, url, connptr->client_fd);
|
request->method, url, connptr->client_fd);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
request->host = safemalloc (length + 1);
|
request->host = safemalloc (length + 1);
|
||||||
if (sscanf
|
if (sscanf (data, "%[^:]:%hu", request->host, &request->port) != 2)
|
||||||
(data, "%[^:]:%hu", request->host,
|
{
|
||||||
&request->port) != 2) {
|
|
||||||
strcpy (request->host, data);
|
strcpy (request->host, data);
|
||||||
request->port = HTTP_PORT;
|
request->port = HTTP_PORT;
|
||||||
}
|
}
|
||||||
request->path = safemalloc (strlen (url) + 1);
|
request->path = safemalloc (strlen (url) + 1);
|
||||||
strcpy (request->path, url);
|
strcpy (request->path, url);
|
||||||
safefree (url);
|
safefree (url);
|
||||||
build_url(&url, request->host, request->port,
|
build_url (&url, request->host, request->port, request->path);
|
||||||
request->path);
|
|
||||||
log_message (LOG_INFO,
|
log_message (LOG_INFO,
|
||||||
"process_request: trans Host %s %s for %d",
|
"process_request: trans Host %s %s for %d",
|
||||||
request->method, url, connptr->client_fd);
|
request->method, url, connptr->client_fd);
|
||||||
}
|
}
|
||||||
if (conf->ipAddr && strcmp(request->host, conf->ipAddr) == 0) {
|
if (conf->ipAddr && strcmp (request->host, conf->ipAddr) == 0)
|
||||||
|
{
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
"process_request: destination IP is localhost %d",
|
"process_request: destination IP is localhost %d",
|
||||||
connptr->client_fd);
|
connptr->client_fd);
|
||||||
|
@ -30,7 +30,8 @@
|
|||||||
#include "reqs.h"
|
#include "reqs.h"
|
||||||
|
|
||||||
extern int do_transparent_proxy (struct conn_s *connptr,
|
extern int do_transparent_proxy (struct conn_s *connptr,
|
||||||
hashmap_t hashofheaders, struct request_s *request,
|
hashmap_t hashofheaders,
|
||||||
|
struct request_s *request,
|
||||||
struct config_s *config, char *url);
|
struct config_s *config, char *url);
|
||||||
|
|
||||||
|
|
||||||
|
30
src/utils.c
30
src/utils.c
@ -71,12 +71,14 @@ create_file_safely(const char *filename, unsigned int truncate_file)
|
|||||||
* If it does exist, open it for writing and perform the fstat()
|
* If it does exist, open it for writing and perform the fstat()
|
||||||
* check.
|
* check.
|
||||||
*/
|
*/
|
||||||
if (lstat(filename, &lstatinfo) < 0) {
|
if (lstat (filename, &lstatinfo) < 0)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* If lstat() failed for any reason other than "file not
|
* If lstat() failed for any reason other than "file not
|
||||||
* existing", exit.
|
* existing", exit.
|
||||||
*/
|
*/
|
||||||
if (errno != ENOENT) {
|
if (errno != ENOENT)
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: Error checking file %s: %s\n",
|
"%s: Error checking file %s: %s\n",
|
||||||
PACKAGE, filename, strerror (errno));
|
PACKAGE, filename, strerror (errno));
|
||||||
@ -88,14 +90,16 @@ create_file_safely(const char *filename, unsigned int truncate_file)
|
|||||||
* sure an attacker can't slip in a file between the lstat()
|
* sure an attacker can't slip in a file between the lstat()
|
||||||
* and open()
|
* and open()
|
||||||
*/
|
*/
|
||||||
if ((fildes =
|
if ((fildes = open (filename, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0)
|
||||||
open(filename, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) {
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: Could not create file %s: %s\n",
|
"%s: Could not create file %s: %s\n",
|
||||||
PACKAGE, filename, strerror (errno));
|
PACKAGE, filename, strerror (errno));
|
||||||
return fildes;
|
return fildes;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
struct stat fstatinfo;
|
struct stat fstatinfo;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
@ -106,7 +110,8 @@ create_file_safely(const char *filename, unsigned int truncate_file)
|
|||||||
/*
|
/*
|
||||||
* Open an existing file.
|
* Open an existing file.
|
||||||
*/
|
*/
|
||||||
if ((fildes = open(filename, flags)) < 0) {
|
if ((fildes = open (filename, flags)) < 0)
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: Could not open file %s: %s\n",
|
"%s: Could not open file %s: %s\n",
|
||||||
PACKAGE, filename, strerror (errno));
|
PACKAGE, filename, strerror (errno));
|
||||||
@ -120,7 +125,8 @@ create_file_safely(const char *filename, unsigned int truncate_file)
|
|||||||
if (fstat (fildes, &fstatinfo) < 0
|
if (fstat (fildes, &fstatinfo) < 0
|
||||||
|| lstatinfo.st_mode != fstatinfo.st_mode
|
|| lstatinfo.st_mode != fstatinfo.st_mode
|
||||||
|| lstatinfo.st_ino != fstatinfo.st_ino
|
|| lstatinfo.st_ino != fstatinfo.st_ino
|
||||||
|| lstatinfo.st_dev != fstatinfo.st_dev) {
|
|| lstatinfo.st_dev != fstatinfo.st_dev)
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: The file %s has been changed before it could be opened\n",
|
"%s: The file %s has been changed before it could be opened\n",
|
||||||
PACKAGE, filename);
|
PACKAGE, filename);
|
||||||
@ -135,7 +141,8 @@ create_file_safely(const char *filename, unsigned int truncate_file)
|
|||||||
* isn't strictly necessary because the fstat() vs lstat()
|
* isn't strictly necessary because the fstat() vs lstat()
|
||||||
* st_mode check would also find this)
|
* st_mode check would also find this)
|
||||||
*/
|
*/
|
||||||
if (fstatinfo.st_nlink > 1 || !S_ISREG(lstatinfo.st_mode)) {
|
if (fstatinfo.st_nlink > 1 || !S_ISREG (lstatinfo.st_mode))
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: The file %s has too many links, or is not a regular file: %s\n",
|
"%s: The file %s has too many links, or is not a regular file: %s\n",
|
||||||
PACKAGE, filename, strerror (errno));
|
PACKAGE, filename, strerror (errno));
|
||||||
@ -162,8 +169,8 @@ create_file_safely(const char *filename, unsigned int truncate_file)
|
|||||||
ftruncate (fildes, 0);
|
ftruncate (fildes, 0);
|
||||||
#else
|
#else
|
||||||
close (fildes);
|
close (fildes);
|
||||||
if ((fildes =
|
if ((fildes = open (filename, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0)
|
||||||
open(filename, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) {
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: Could not open file %s: %s.",
|
"%s: Could not open file %s: %s.",
|
||||||
PACKAGE, filename, strerror (errno));
|
PACKAGE, filename, strerror (errno));
|
||||||
@ -193,7 +200,8 @@ pidfile_create(const char *filename)
|
|||||||
/*
|
/*
|
||||||
* Open a stdio file over the low-level one.
|
* Open a stdio file over the low-level one.
|
||||||
*/
|
*/
|
||||||
if ((fd = fdopen(fildes, "w")) == NULL) {
|
if ((fd = fdopen (fildes, "w")) == NULL)
|
||||||
|
{
|
||||||
fprintf (stderr,
|
fprintf (stderr,
|
||||||
"%s: Could not write PID file %s: %s.",
|
"%s: Could not write PID file %s: %s.",
|
||||||
PACKAGE, filename, strerror (errno));
|
PACKAGE, filename, strerror (errno));
|
||||||
|
@ -31,6 +31,7 @@ extern int send_http_message(struct conn_s *connptr, int http_code,
|
|||||||
const char *error_title, const char *message);
|
const char *error_title, const char *message);
|
||||||
|
|
||||||
extern int pidfile_create (const char *path);
|
extern int pidfile_create (const char *path);
|
||||||
extern int create_file_safely(const char *filename, unsigned int truncate_file);
|
extern int create_file_safely (const char *filename,
|
||||||
|
unsigned int truncate_file);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
22
src/vector.c
22
src/vector.c
@ -33,14 +33,16 @@
|
|||||||
* vector_s stores a pointer to the first vector (vector[0]) and a
|
* vector_s stores a pointer to the first vector (vector[0]) and a
|
||||||
* count of the number of entries (or how long the vector is.)
|
* count of the number of entries (or how long the vector is.)
|
||||||
*/
|
*/
|
||||||
struct vectorentry_s {
|
struct vectorentry_s
|
||||||
|
{
|
||||||
void *data;
|
void *data;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
struct vectorentry_s *next;
|
struct vectorentry_s *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vector_s {
|
struct vector_s
|
||||||
|
{
|
||||||
size_t num_entries;
|
size_t num_entries;
|
||||||
struct vectorentry_s *head;
|
struct vectorentry_s *head;
|
||||||
struct vectorentry_s *tail;
|
struct vectorentry_s *tail;
|
||||||
@ -83,7 +85,8 @@ vector_delete(vector_t vector)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ptr = vector->head;
|
ptr = vector->head;
|
||||||
while (ptr) {
|
while (ptr)
|
||||||
|
{
|
||||||
next = ptr->next;
|
next = ptr->next;
|
||||||
safefree (ptr->data);
|
safefree (ptr->data);
|
||||||
safefree (ptr);
|
safefree (ptr);
|
||||||
@ -123,7 +126,8 @@ vector_insert(vector_t vector, void *data, ssize_t len, int pos)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
entry->data = safemalloc (len);
|
entry->data = safemalloc (len);
|
||||||
if (!entry->data) {
|
if (!entry->data)
|
||||||
|
{
|
||||||
safefree (entry);
|
safefree (entry);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
@ -135,11 +139,14 @@ vector_insert(vector_t vector, void *data, ssize_t len, int pos)
|
|||||||
/* If there is no head or tail, create them */
|
/* If there is no head or tail, create them */
|
||||||
if (!vector->head && !vector->tail)
|
if (!vector->head && !vector->tail)
|
||||||
vector->head = vector->tail = entry;
|
vector->head = vector->tail = entry;
|
||||||
else if (pos == 0) {
|
else if (pos == 0)
|
||||||
|
{
|
||||||
/* prepend the entry */
|
/* prepend the entry */
|
||||||
entry->next = vector->head;
|
entry->next = vector->head;
|
||||||
vector->head = entry;
|
vector->head = entry;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* append the entry */
|
/* append the entry */
|
||||||
vector->tail->next = entry;
|
vector->tail->next = entry;
|
||||||
vector->tail = entry;
|
vector->tail = entry;
|
||||||
@ -186,7 +193,8 @@ vector_getentry(vector_t vector, size_t pos, size_t * size)
|
|||||||
loc = 0;
|
loc = 0;
|
||||||
ptr = vector->head;
|
ptr = vector->head;
|
||||||
|
|
||||||
while (loc != pos) {
|
while (loc != pos)
|
||||||
|
{
|
||||||
ptr = ptr->next;
|
ptr = ptr->next;
|
||||||
loc++;
|
loc++;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
|
|
||||||
/* Allow the use in C++ code. */
|
/* Allow the use in C++ code. */
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" {
|
extern "C"
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -67,8 +68,7 @@ extern "C" {
|
|||||||
* Returns: NULL on error
|
* Returns: NULL on error
|
||||||
* valid pointer to data
|
* valid pointer to data
|
||||||
*/
|
*/
|
||||||
extern void *vector_getentry(vector_t vector, size_t pos,
|
extern void *vector_getentry (vector_t vector, size_t pos, size_t * size);
|
||||||
size_t * size);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the number of enteries (or the length) of the vector.
|
* Returns the number of enteries (or the length) of the vector.
|
||||||
|
Loading…
Reference in New Issue
Block a user