* [Indent] Ran Source Through indent

I re-indented the source code using indent with the following options:

indent -kr -bad -bap -nut -i8 -l80 -psl -sob -ss -ncs

There are now _no_ tabs in the source files, and all indentation is
eight spaces.  Lines are 80 characters long, and the procedure type is
on it's own line.  Read the indent manual for more information about
what each option means.
This commit is contained in:
Robert James Kaes 2005-08-15 03:54:31 +00:00
parent 38f0b3a103
commit c0299e1868
41 changed files with 4064 additions and 3850 deletions

211
src/acl.c
View File

@ -1,4 +1,4 @@
/* $Id: acl.c,v 1.21 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: acl.c,v 1.22 2005-08-15 03:54:31 rjkaes Exp $
*
* This system handles Access Control for use of this daemon. A list of
* domains, or IP addresses (including IP blocks) are stored in a list
@ -37,15 +37,15 @@ enum acl_type { ACL_STRING, ACL_NUMERIC };
* entry (like a domain name) or an IP entry.
*/
struct acl_s {
acl_access_t access;
enum acl_type type;
union {
char* string;
acl_access_t access;
enum acl_type type;
union {
char *string;
struct {
unsigned char octet[IPV6_LEN];
unsigned char mask[IPV6_LEN];
} ip;
} address;
} address;
};
/*
@ -65,11 +65,11 @@ static vector_t access_list = NULL;
int
insert_acl(char *location, acl_access_t access_type)
{
struct acl_s acl;
int i, ret, mask;
char *p, ip_dst[IPV6_LEN];
struct acl_s acl;
int i, ret, mask;
char *p, ip_dst[IPV6_LEN];
assert(location != NULL);
assert(location != NULL);
/*
* If the access list has not been set up, create it.
@ -110,7 +110,7 @@ insert_acl(char *location, acl_access_t access_type)
*p = '\0';
if (full_inet_pton(location, ip_dst) <= 0)
return -1;
acl.type = ACL_NUMERIC;
memcpy(acl.address.ip.octet, ip_dst, IPV6_LEN);
@ -119,7 +119,8 @@ insert_acl(char *location, acl_access_t access_type)
if (mask >= ((i + 1) * 8))
acl.address.ip.mask[i] = 0xff;
else
acl.address.ip.mask[i] = 0xff << (8 - (mask - i * 8));
acl.address.ip.mask[i] =
0xff << (8 - (mask - i * 8));
}
} else {
/* In all likelihood a string */
@ -138,7 +139,6 @@ insert_acl(char *location, acl_access_t access_type)
return ret;
}
/*
* This function is called whenever a "string" access control is found in
* the ACL. From here we do both a text based string comparison, along with
@ -149,72 +149,73 @@ insert_acl(char *location, acl_access_t access_type)
* -1 if no tests match, so skip
*/
static int
acl_string_processing(struct acl_s* acl,
const char* ip_address,
const char* string_address)
acl_string_processing(struct acl_s *acl,
const char *ip_address, const char *string_address)
{
int match;
struct addrinfo hints, *res, *ressave;
size_t test_length, match_length;
char ipbuf[512];
int match;
struct addrinfo hints, *res, *ressave;
size_t test_length, match_length;
char ipbuf[512];
assert(acl && acl->type == ACL_STRING);
assert(ip_address && strlen(ip_address) > 0);
assert(string_address && strlen(string_address) > 0);
/*
* If the first character of the ACL string is a period, we need to
* do a string based test only; otherwise, we can do a reverse
* lookup test as well.
*/
if (acl->address.string[0] != '.') {
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(acl->address.string, NULL, &hints, &res) != 0)
goto STRING_TEST;
/*
* If the first character of the ACL string is a period, we need to
* do a string based test only; otherwise, we can do a reverse
* lookup test as well.
*/
if (acl->address.string[0] != '.') {
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(acl->address.string, NULL, &hints, &res) != 0)
goto STRING_TEST;
ressave = res;
ressave = res;
match = FALSE;
do {
get_ip_string(res->ai_addr, ipbuf, sizeof(ipbuf));
if (strcmp(ip_address, ipbuf) == 0) {
match = TRUE;
break;
}
} while ((res = res->ai_next) != NULL);
match = FALSE;
do {
get_ip_string(res->ai_addr, ipbuf, sizeof(ipbuf));
if (strcmp(ip_address, ipbuf) == 0) {
match = TRUE;
break;
}
} while ((res = res->ai_next) != NULL);
freeaddrinfo(ressave);
freeaddrinfo(ressave);
if (match) {
if (acl->access == ACL_DENY)
return 0;
else
return 1;
}
}
if (match) {
if (acl->access == ACL_DENY)
return 0;
else
return 1;
}
}
STRING_TEST:
test_length = strlen(string_address);
match_length = strlen(acl->address.string);
STRING_TEST:
test_length = strlen(string_address);
match_length = strlen(acl->address.string);
/*
* If the string length is shorter than AC string, return a -1 so
* that the "driver" will skip onto the next control in the list.
*/
if (test_length < match_length)
return -1;
/*
* If the string length is shorter than AC string, return a -1 so
* that the "driver" will skip onto the next control in the list.
*/
if (test_length < match_length)
return -1;
if (strcasecmp(string_address + (test_length - match_length), acl->address.string) == 0) {
if (acl->access == ACL_DENY)
return 0;
else
return 1;
}
if (strcasecmp
(string_address + (test_length - match_length),
acl->address.string) == 0) {
if (acl->access == ACL_DENY)
return 0;
else
return 1;
}
/* Indicate that no tests succeeded, so skip to next control. */
return -1;
/* Indicate that no tests succeeded, so skip to next control. */
return -1;
}
/*
@ -226,30 +227,30 @@ STRING_TEST:
* -1 neither allowed nor denied.
*/
static int
check_numeric_acl(const struct acl_s* acl, const char* ip)
check_numeric_acl(const struct acl_s *acl, const char *ip)
{
uint8_t addr[IPV6_LEN], x, y;
int i;
uint8_t addr[IPV6_LEN], x, y;
int i;
assert(acl && acl->type == ACL_NUMERIC);
assert(ip && strlen(ip) > 0);
if (full_inet_pton(ip, &addr) <= 0) return -1;
if (full_inet_pton(ip, &addr) <= 0)
return -1;
for (i = 0; i != IPV6_LEN; ++i) {
for (i = 0; i != IPV6_LEN; ++i) {
x = addr[i] & acl->address.ip.mask[i];
y = acl->address.ip.octet[i] & acl->address.ip.mask[i];
/* If x and y don't match, the IP addresses don't match */
if (x != y)
return 0;
}
}
/* The addresses match, return the permission */
return (acl->access == ACL_ALLOW);
/* The addresses match, return the permission */
return (acl->access == ACL_ALLOW);
}
/*
* Checks whether file descriptor is allowed.
*
@ -258,48 +259,50 @@ check_numeric_acl(const struct acl_s* acl, const char* ip)
* 0 if denied
*/
int
check_acl(int fd, const char* ip, const char* host)
check_acl(int fd, const char *ip, const char *host)
{
struct acl_s* acl;
int perm;
struct acl_s *acl;
int perm;
int i;
assert(fd >= 0);
assert(ip != NULL);
assert(host != NULL);
assert(fd >= 0);
assert(ip != NULL);
assert(host != NULL);
/*
* If there is no access list allow everything.
*/
if (!access_list) return 1;
/*
* If there is no access list allow everything.
*/
if (!access_list)
return 1;
for (i = 0; i != vector_length(access_list); ++i) {
acl = vector_getentry(access_list, i, NULL);
switch (acl->type) {
case ACL_STRING:
perm = acl_string_processing(acl, ip, host);
break;
case ACL_STRING:
perm = acl_string_processing(acl, ip, host);
break;
case ACL_NUMERIC:
if (ip[0] == '\0') continue;
perm = check_numeric_acl(acl, ip);
break;
}
case ACL_NUMERIC:
if (ip[0] == '\0')
continue;
perm = check_numeric_acl(acl, ip);
break;
}
/*
* Check the return value too see if the IP address is
* allowed or denied.
*/
if (perm == 0)
break;
else if (perm == 1)
return perm;
* allowed or denied.
*/
if (perm == 0)
break;
else if (perm == 1)
return perm;
}
/*
* Deny all connections by default.
*/
log_message(LOG_NOTICE, "Unauthorized connection from \"%s\" [%s].",
host, ip);
return 0;
/*
* Deny all connections by default.
*/
log_message(LOG_NOTICE, "Unauthorized connection from \"%s\" [%s].",
host, ip);
return 0;
}

View File

@ -1,4 +1,4 @@
/* $Id: acl.h,v 1.4 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: acl.h,v 1.5 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'acl.c' for detailed information.
*
@ -21,6 +21,7 @@
typedef enum { ACL_ALLOW, ACL_DENY } acl_access_t;
extern int insert_acl(char *location, acl_access_t access_type);
extern int check_acl(int fd, const char* ip_address, const char* string_address);
extern int check_acl(int fd, const char *ip_address,
const char *string_address);
#endif

View File

@ -1,4 +1,4 @@
/* $Id: anonymous.c,v 1.15 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: anonymous.c,v 1.16 2005-08-15 03:54:31 rjkaes Exp $
*
* Handles insertion and searches for headers which should be let through when
* the anonymous feature is turned on.
@ -28,7 +28,7 @@ static hashmap_t anonymous_map = NULL;
short int
is_anonymous_enabled(void)
{
return (anonymous_map != NULL) ? 1 : 0;
return (anonymous_map != NULL) ? 1 : 0;
}
/*
@ -38,10 +38,10 @@ is_anonymous_enabled(void)
int
anonymous_search(char *s)
{
assert(s != NULL);
assert(anonymous_map != NULL);
assert(s != NULL);
assert(anonymous_map != NULL);
return hashmap_search(anonymous_map, s);
return hashmap_search(anonymous_map, s);
}
/*
@ -53,21 +53,21 @@ anonymous_search(char *s)
int
anonymous_insert(char *s)
{
char data = 1;
char data = 1;
assert(s != NULL);
assert(s != NULL);
if (!anonymous_map) {
anonymous_map = hashmap_create(32);
if (!anonymous_map)
return -1;
}
if (!anonymous_map) {
anonymous_map = hashmap_create(32);
if (!anonymous_map)
return -1;
}
if (hashmap_search(anonymous_map, s) > 0) {
/* The key was already found, so return a positive number. */
return 0;
}
if (hashmap_search(anonymous_map, s) > 0) {
/* The key was already found, so return a positive number. */
return 0;
}
/* Insert the new key */
return hashmap_insert(anonymous_map, s, &data, sizeof(data));
/* Insert the new key */
return hashmap_insert(anonymous_map, s, &data, sizeof(data));
}

View File

@ -1,4 +1,4 @@
/* $Id: buffer.c,v 1.24 2004-02-13 21:27:42 rjkaes Exp $
/* $Id: buffer.c,v 1.25 2005-08-15 03:54:31 rjkaes Exp $
*
* The buffer used in each connection is a linked list of lines. As the lines
* are read in and written out the buffer expands and contracts. Basically,
@ -31,10 +31,10 @@
#define BUFFER_TAIL(x) (x)->tail
struct bufline_s {
unsigned char *string; /* the actual string of data */
struct bufline_s *next; /* pointer to next in linked list */
size_t length; /* length of the string of data */
size_t pos; /* start sending from this offset */
unsigned char *string; /* the actual string of data */
struct bufline_s *next; /* pointer to next in linked list */
size_t length; /* length of the string of data */
size_t pos; /* start sending from this offset */
};
/*
@ -42,9 +42,9 @@ struct bufline_s {
* (and includes the total size)
*/
struct buffer_s {
struct bufline_s *head; /* top of the buffer */
struct bufline_s *tail; /* bottom of the buffer */
size_t size; /* total size of the buffer */
struct bufline_s *head; /* top of the buffer */
struct bufline_s *tail; /* bottom of the buffer */
size_t size; /* total size of the buffer */
};
/*
@ -55,28 +55,28 @@ struct buffer_s {
static struct bufline_s *
makenewline(unsigned char *data, size_t length)
{
struct bufline_s *newline;
struct bufline_s *newline;
assert(data != NULL);
assert(length > 0);
assert(data != NULL);
assert(length > 0);
if (!(newline = safemalloc(sizeof(struct bufline_s))))
return NULL;
if (!(newline = safemalloc(sizeof(struct bufline_s))))
return NULL;
if (!(newline->string = safemalloc(length))) {
safefree(newline);
return NULL;
}
if (!(newline->string = safemalloc(length))) {
safefree(newline);
return NULL;
}
memcpy(newline->string, data, length);
memcpy(newline->string, data, length);
newline->next = NULL;
newline->length = length;
newline->next = NULL;
newline->length = length;
/* Position our "read" pointer at the beginning of the data */
newline->pos = 0;
/* Position our "read" pointer at the beginning of the data */
newline->pos = 0;
return newline;
return newline;
}
/*
@ -85,15 +85,15 @@ makenewline(unsigned char *data, size_t length)
static void
free_line(struct bufline_s *line)
{
assert(line != NULL);
assert(line != NULL);
if (!line)
return;
if (!line)
return;
if (line->string)
safefree(line->string);
if (line->string)
safefree(line->string);
safefree(line);
safefree(line);
}
/*
@ -102,20 +102,20 @@ free_line(struct bufline_s *line)
struct buffer_s *
new_buffer(void)
{
struct buffer_s *buffptr;
struct buffer_s *buffptr;
if (!(buffptr = safemalloc(sizeof(struct buffer_s))))
return NULL;
if (!(buffptr = safemalloc(sizeof(struct buffer_s))))
return NULL;
/*
* Since the buffer is initially empty, set the HEAD and TAIL
* pointers to NULL since they can't possibly point anywhere at the
* moment.
*/
BUFFER_HEAD(buffptr) = BUFFER_TAIL(buffptr) = NULL;
buffptr->size = 0;
/*
* Since the buffer is initially empty, set the HEAD and TAIL
* pointers to NULL since they can't possibly point anywhere at the
* moment.
*/
BUFFER_HEAD(buffptr) = BUFFER_TAIL(buffptr) = NULL;
buffptr->size = 0;
return buffptr;
return buffptr;
}
/*
@ -124,25 +124,26 @@ new_buffer(void)
void
delete_buffer(struct buffer_s *buffptr)
{
struct bufline_s *next;
struct bufline_s *next;
assert(buffptr != NULL);
assert(buffptr != NULL);
while (BUFFER_HEAD(buffptr)) {
next = BUFFER_HEAD(buffptr)->next;
free_line(BUFFER_HEAD(buffptr));
BUFFER_HEAD(buffptr) = next;
}
while (BUFFER_HEAD(buffptr)) {
next = BUFFER_HEAD(buffptr)->next;
free_line(BUFFER_HEAD(buffptr));
BUFFER_HEAD(buffptr) = next;
}
safefree(buffptr);
safefree(buffptr);
}
/*
* Return the current size of the buffer.
*/
size_t buffer_size(struct buffer_s *buffptr)
size_t
buffer_size(struct buffer_s *buffptr)
{
return buffptr->size;
return buffptr->size;
}
/*
@ -151,37 +152,37 @@ size_t buffer_size(struct buffer_s *buffptr)
int
add_to_buffer(struct buffer_s *buffptr, unsigned char *data, size_t length)
{
struct bufline_s *newline;
struct bufline_s *newline;
assert(buffptr != NULL);
assert(data != NULL);
assert(length > 0);
assert(buffptr != NULL);
assert(data != NULL);
assert(length > 0);
/*
* Sanity check here. A buffer with a non-NULL head pointer must
* have a size greater than zero, and vice-versa.
*/
if (BUFFER_HEAD(buffptr) == NULL)
assert(buffptr->size == 0);
else
assert(buffptr->size > 0);
/*
* Sanity check here. A buffer with a non-NULL head pointer must
* have a size greater than zero, and vice-versa.
*/
if (BUFFER_HEAD(buffptr) == NULL)
assert(buffptr->size == 0);
else
assert(buffptr->size > 0);
/*
* Make a new line so we can add it to the buffer.
*/
if (!(newline = makenewline(data, length)))
return -1;
/*
* Make a new line so we can add it to the buffer.
*/
if (!(newline = makenewline(data, length)))
return -1;
if (buffptr->size == 0)
BUFFER_HEAD(buffptr) = BUFFER_TAIL(buffptr) = newline;
else {
BUFFER_TAIL(buffptr)->next = newline;
BUFFER_TAIL(buffptr) = newline;
}
if (buffptr->size == 0)
BUFFER_HEAD(buffptr) = BUFFER_TAIL(buffptr) = newline;
else {
BUFFER_TAIL(buffptr)->next = newline;
BUFFER_TAIL(buffptr) = newline;
}
buffptr->size += length;
buffptr->size += length;
return 0;
return 0;
}
/*
@ -190,17 +191,17 @@ add_to_buffer(struct buffer_s *buffptr, unsigned char *data, size_t length)
static struct bufline_s *
remove_from_buffer(struct buffer_s *buffptr)
{
struct bufline_s *line;
struct bufline_s *line;
assert(buffptr != NULL);
assert(BUFFER_HEAD(buffptr) != NULL);
assert(buffptr != NULL);
assert(BUFFER_HEAD(buffptr) != NULL);
line = BUFFER_HEAD(buffptr);
BUFFER_HEAD(buffptr) = line->next;
line = BUFFER_HEAD(buffptr);
BUFFER_HEAD(buffptr) = line->next;
buffptr->size -= line->length;
buffptr->size -= line->length;
return line;
return line;
}
/*
@ -211,51 +212,51 @@ remove_from_buffer(struct buffer_s *buffptr)
ssize_t
read_buffer(int fd, struct buffer_s * buffptr)
{
ssize_t bytesin;
unsigned char buffer[READ_BUFFER_SIZE];
ssize_t bytesin;
unsigned char buffer[READ_BUFFER_SIZE];
assert(fd >= 0);
assert(buffptr != NULL);
assert(fd >= 0);
assert(buffptr != NULL);
/*
* Don't allow the buffer to grow larger than MAXBUFFSIZE
*/
if (buffptr->size >= MAXBUFFSIZE)
return 0;
/*
* Don't allow the buffer to grow larger than MAXBUFFSIZE
*/
if (buffptr->size >= MAXBUFFSIZE)
return 0;
bytesin = read(fd, buffer, READ_BUFFER_SIZE);
bytesin = read(fd, buffer, READ_BUFFER_SIZE);
if (bytesin > 0) {
if (add_to_buffer(buffptr, buffer, bytesin) < 0) {
log_message(LOG_ERR,
"readbuff: add_to_buffer() error.");
return -1;
}
if (bytesin > 0) {
if (add_to_buffer(buffptr, buffer, bytesin) < 0) {
log_message(LOG_ERR,
"readbuff: add_to_buffer() error.");
return -1;
}
return bytesin;
} else {
if (bytesin == 0) {
/* connection was closed by client */
return -1;
} else {
switch (errno) {
return bytesin;
} else {
if (bytesin == 0) {
/* connection was closed by client */
return -1;
} else {
switch (errno) {
#ifdef EWOULDBLOCK
case EWOULDBLOCK:
case EWOULDBLOCK:
#else
# ifdef EAGAIN
case EAGAIN:
case EAGAIN:
# endif
#endif
case EINTR:
return 0;
default:
log_message(LOG_ERR,
"readbuff: recv() error \"%s\" on file descriptor %d",
strerror(errno), fd);
return -1;
}
}
}
case EINTR:
return 0;
default:
log_message(LOG_ERR,
"readbuff: recv() error \"%s\" on file descriptor %d",
strerror(errno), fd);
return -1;
}
}
}
}
/*
@ -265,50 +266,51 @@ read_buffer(int fd, struct buffer_s * buffptr)
ssize_t
write_buffer(int fd, struct buffer_s * buffptr)
{
ssize_t bytessent;
struct bufline_s *line;
ssize_t bytessent;
struct bufline_s *line;
assert(fd >= 0);
assert(buffptr != NULL);
assert(fd >= 0);
assert(buffptr != NULL);
if (buffptr->size == 0)
return 0;
if (buffptr->size == 0)
return 0;
/* Sanity check. It would be bad to be using a NULL pointer! */
assert(BUFFER_HEAD(buffptr) != NULL);
line = BUFFER_HEAD(buffptr);
/* Sanity check. It would be bad to be using a NULL pointer! */
assert(BUFFER_HEAD(buffptr) != NULL);
line = BUFFER_HEAD(buffptr);
bytessent =
send(fd, line->string + line->pos, line->length - line->pos, MSG_NOSIGNAL);
bytessent =
send(fd, line->string + line->pos, line->length - line->pos,
MSG_NOSIGNAL);
if (bytessent >= 0) {
/* bytes sent, adjust buffer */
line->pos += bytessent;
if (line->pos == line->length)
free_line(remove_from_buffer(buffptr));
return bytessent;
} else {
switch (errno) {
if (bytessent >= 0) {
/* bytes sent, adjust buffer */
line->pos += bytessent;
if (line->pos == line->length)
free_line(remove_from_buffer(buffptr));
return bytessent;
} else {
switch (errno) {
#ifdef EWOULDBLOCK
case EWOULDBLOCK:
case EWOULDBLOCK:
#else
# ifdef EAGAIN
case EAGAIN:
case EAGAIN:
# endif
#endif
case EINTR:
return 0;
case ENOBUFS:
case ENOMEM:
log_message(LOG_ERR,
"writebuff: write() error [NOBUFS/NOMEM] \"%s\" on file descriptor %d",
strerror(errno), fd);
return 0;
default:
log_message(LOG_ERR,
"writebuff: write() error \"%s\" on file descriptor %d",
strerror(errno), fd);
return -1;
}
}
case EINTR:
return 0;
case ENOBUFS:
case ENOMEM:
log_message(LOG_ERR,
"writebuff: write() error [NOBUFS/NOMEM] \"%s\" on file descriptor %d",
strerror(errno), fd);
return 0;
default:
log_message(LOG_ERR,
"writebuff: write() error \"%s\" on file descriptor %d",
strerror(errno), fd);
return -1;
}
}
}

View File

@ -1,4 +1,4 @@
/* $Id: buffer.h,v 1.9 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: buffer.h,v 1.10 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'buffer.c' for a detailed description.
*
@ -29,9 +29,9 @@ extern size_t buffer_size(struct buffer_s *buffptr);
* Add a new line to the given buffer. The data IS copied into the structure.
*/
extern int add_to_buffer(struct buffer_s *buffptr, unsigned char *data,
size_t length);
size_t length);
extern ssize_t read_buffer(int fd, struct buffer_s *buffptr);
extern ssize_t write_buffer(int fd, struct buffer_s *buffptr);
#endif /* __BUFFER_H_ */
#endif /* __BUFFER_H_ */

View File

@ -1,4 +1,4 @@
/* $Id: child.c,v 1.17 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: child.c,v 1.18 2005-08-15 03:54:31 rjkaes Exp $
*
* Handles the creation/destruction of the various children required for
* processing incoming connections.
@ -35,9 +35,9 @@ static socklen_t addrlen;
*/
enum child_status_t { T_EMPTY, T_WAITING, T_CONNECTED };
struct child_s {
pid_t tid;
unsigned int connects;
enum child_status_t status;
pid_t tid;
unsigned int connects;
enum child_status_t status;
};
/*
@ -47,11 +47,11 @@ struct child_s {
static struct child_s *child_ptr;
static struct child_config_s {
int maxclients, maxrequestsperchild;
int maxspareservers, minspareservers, startservers;
int maxclients, maxrequestsperchild;
int maxspareservers, minspareservers, startservers;
} child_config;
static unsigned int* servers_waiting; /* servers waiting for a connection */
static unsigned int *servers_waiting; /* servers waiting for a connection */
/*
* Lock/Unlock the "servers_waiting" variable so that two children cannot
@ -72,40 +72,40 @@ static int lock_fd = -1;
static void
_child_lock_init(void)
{
char lock_file[] = "/tmp/tinyproxy.servers.lock.XXXXXX";
char lock_file[] = "/tmp/tinyproxy.servers.lock.XXXXXX";
lock_fd = mkstemp(lock_file);
unlink(lock_file);
lock_fd = mkstemp(lock_file);
unlink(lock_file);
lock_it.l_type = F_WRLCK;
lock_it.l_whence = SEEK_SET;
lock_it.l_start = 0;
lock_it.l_len = 0;
lock_it.l_type = F_WRLCK;
lock_it.l_whence = SEEK_SET;
lock_it.l_start = 0;
lock_it.l_len = 0;
unlock_it.l_type = F_UNLCK;
unlock_it.l_whence = SEEK_SET;
unlock_it.l_start = 0;
unlock_it.l_len = 0;
unlock_it.l_type = F_UNLCK;
unlock_it.l_whence = SEEK_SET;
unlock_it.l_start = 0;
unlock_it.l_len = 0;
}
static void
_child_lock_wait(void)
{
int rc;
int rc;
while ((rc = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0) {
if (errno == EINTR)
continue;
else
return;
}
while ((rc = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0) {
if (errno == EINTR)
continue;
else
return;
}
}
static void
_child_lock_release(void)
{
if (fcntl(lock_fd, F_SETLKW, &unlock_it) < 0)
return;
if (fcntl(lock_fd, F_SETLKW, &unlock_it) < 0)
return;
}
/* END OF LOCKING SECTION */
@ -131,119 +131,124 @@ _child_lock_release(void)
short int
child_configure(child_config_t type, int val)
{
switch (type) {
case CHILD_MAXCLIENTS:
child_config.maxclients = val;
break;
case CHILD_MAXSPARESERVERS:
child_config.maxspareservers = val;
break;
case CHILD_MINSPARESERVERS:
child_config.minspareservers = val;
break;
case CHILD_STARTSERVERS:
child_config.startservers = val;
break;
case CHILD_MAXREQUESTSPERCHILD:
child_config.maxrequestsperchild = val;
break;
default:
DEBUG2("Invalid type (%d)", type);
return -1;
}
switch (type) {
case CHILD_MAXCLIENTS:
child_config.maxclients = val;
break;
case CHILD_MAXSPARESERVERS:
child_config.maxspareservers = val;
break;
case CHILD_MINSPARESERVERS:
child_config.minspareservers = val;
break;
case CHILD_STARTSERVERS:
child_config.startservers = val;
break;
case CHILD_MAXREQUESTSPERCHILD:
child_config.maxrequestsperchild = val;
break;
default:
DEBUG2("Invalid type (%d)", type);
return -1;
}
return 0;
return 0;
}
/*
* This is the main (per child) loop.
*/
static void
child_main(struct child_s* ptr)
child_main(struct child_s *ptr)
{
int connfd;
struct sockaddr *cliaddr;
socklen_t clilen;
int connfd;
struct sockaddr *cliaddr;
socklen_t clilen;
cliaddr = safemalloc(addrlen);
if (!cliaddr) {
log_message(LOG_CRIT,
"Could not allocate memory for child address.");
exit(0);
}
cliaddr = safemalloc(addrlen);
if (!cliaddr) {
log_message(LOG_CRIT,
"Could not allocate memory for child address.");
exit(0);
}
ptr->connects = 0;
ptr->connects = 0;
while (!config.quit) {
ptr->status = T_WAITING;
while (!config.quit) {
ptr->status = T_WAITING;
clilen = addrlen;
clilen = addrlen;
connfd = accept(listenfd, cliaddr, &clilen);
connfd = accept(listenfd, cliaddr, &clilen);
#ifndef NDEBUG
/*
* Enable the TINYPROXY_DEBUG environment variable if you
* want to use the GDB debugger.
*/
if (getenv("TINYPROXY_DEBUG")) {
/* Pause for 10 seconds to allow us to connect debugger */
fprintf(stderr,
"Process has accepted connection: %ld\n", (long int)ptr->tid);
sleep(10);
fprintf(stderr, "Continuing process: %ld\n", (long int)ptr->tid);
}
/*
* Enable the TINYPROXY_DEBUG environment variable if you
* want to use the GDB debugger.
*/
if (getenv("TINYPROXY_DEBUG")) {
/* Pause for 10 seconds to allow us to connect debugger */
fprintf(stderr,
"Process has accepted connection: %ld\n",
(long int)ptr->tid);
sleep(10);
fprintf(stderr, "Continuing process: %ld\n",
(long int)ptr->tid);
}
#endif
/*
* Make sure no error occurred...
*/
if (connfd < 0) {
log_message(LOG_ERR, "Accept returned an error (%s) ... retrying.", strerror(errno));
continue;
}
/*
* Make sure no error occurred...
*/
if (connfd < 0) {
log_message(LOG_ERR,
"Accept returned an error (%s) ... retrying.",
strerror(errno));
continue;
}
ptr->status = T_CONNECTED;
ptr->status = T_CONNECTED;
SERVER_DEC();
SERVER_DEC();
handle_connection(connfd);
ptr->connects++;
handle_connection(connfd);
ptr->connects++;
if (child_config.maxrequestsperchild != 0) {
DEBUG2("%u connections so far...", ptr->connects);
if (child_config.maxrequestsperchild != 0) {
DEBUG2("%u connections so far...", ptr->connects);
if (ptr->connects == child_config.maxrequestsperchild) {
log_message(LOG_NOTICE,
"Child has reached MaxRequestsPerChild (%u). Killing child.",
ptr->connects);
break;
}
}
if (ptr->connects == child_config.maxrequestsperchild) {
log_message(LOG_NOTICE,
"Child has reached MaxRequestsPerChild (%u). Killing child.",
ptr->connects);
break;
}
}
SERVER_COUNT_LOCK();
if (*servers_waiting > child_config.maxspareservers) {
/*
* There are too many spare children, kill ourself
* off.
*/
log_message(LOG_NOTICE,
"Waiting servers (%d) exceeds MaxSpareServers (%d). Killing child.",
*servers_waiting, child_config.maxspareservers);
SERVER_COUNT_UNLOCK();
SERVER_COUNT_LOCK();
if (*servers_waiting > child_config.maxspareservers) {
/*
* There are too many spare children, kill ourself
* off.
*/
log_message(LOG_NOTICE,
"Waiting servers (%d) exceeds MaxSpareServers (%d). Killing child.",
*servers_waiting,
child_config.maxspareservers);
SERVER_COUNT_UNLOCK();
break;
} else {
SERVER_COUNT_UNLOCK();
}
break;
} else {
SERVER_COUNT_UNLOCK();
}
SERVER_INC();
}
SERVER_INC();
}
ptr->status = T_EMPTY;
ptr->status = T_EMPTY;
safefree(cliaddr);
exit(0);
safefree(cliaddr);
exit(0);
}
/*
@ -251,22 +256,22 @@ child_main(struct child_s* ptr)
* child_main() function.
*/
static pid_t
child_make(struct child_s* ptr)
child_make(struct child_s *ptr)
{
pid_t pid;
if ((pid = fork()) > 0)
return pid; /* parent */
pid_t pid;
/*
* Reset the SIGNALS so that the child can be reaped.
*/
set_signal_handler(SIGCHLD, SIG_DFL);
set_signal_handler(SIGTERM, SIG_DFL);
set_signal_handler(SIGHUP, SIG_DFL);
if ((pid = fork()) > 0)
return pid; /* parent */
child_main(ptr); /* never returns */
return -1;
/*
* Reset the SIGNALS so that the child can be reaped.
*/
set_signal_handler(SIGCHLD, SIG_DFL);
set_signal_handler(SIGTERM, SIG_DFL);
set_signal_handler(SIGHUP, SIG_DFL);
child_main(ptr); /* never returns */
return -1;
}
/*
@ -275,78 +280,80 @@ child_make(struct child_s* ptr)
short int
child_pool_create(void)
{
unsigned int i;
unsigned int i;
/*
* Make sure the number of MaxClients is not zero, since this
* variable determines the size of the array created for children
* later on.
*/
if (child_config.maxclients == 0) {
log_message(LOG_ERR,
"child_pool_create: \"MaxClients\" must be greater than zero.");
return -1;
}
if (child_config.startservers == 0) {
log_message(LOG_ERR,
"child_pool_create: \"StartServers\" must be greater than zero.");
return -1;
}
/*
* Make sure the number of MaxClients is not zero, since this
* variable determines the size of the array created for children
* later on.
*/
if (child_config.maxclients == 0) {
log_message(LOG_ERR,
"child_pool_create: \"MaxClients\" must be greater than zero.");
return -1;
}
if (child_config.startservers == 0) {
log_message(LOG_ERR,
"child_pool_create: \"StartServers\" must be greater than zero.");
return -1;
}
child_ptr = calloc_shared_memory(child_config.maxclients,
sizeof(struct child_s));
if (!child_ptr) {
log_message(LOG_ERR, "Could not allocate memory for children.");
return -1;
}
child_ptr = calloc_shared_memory(child_config.maxclients,
sizeof(struct child_s));
if (!child_ptr) {
log_message(LOG_ERR, "Could not allocate memory for children.");
return -1;
}
servers_waiting = malloc_shared_memory(sizeof(unsigned int));
if (servers_waiting == MAP_FAILED) {
log_message(LOG_ERR, "Could not allocate memory for child counting.");
return -1;
}
*servers_waiting = 0;
servers_waiting = malloc_shared_memory(sizeof(unsigned int));
if (servers_waiting == MAP_FAILED) {
log_message(LOG_ERR,
"Could not allocate memory for child counting.");
return -1;
}
*servers_waiting = 0;
/*
* Create a "locking" file for use around the servers_waiting
* variable.
*/
_child_lock_init();
/*
* Create a "locking" file for use around the servers_waiting
* variable.
*/
_child_lock_init();
if (child_config.startservers > child_config.maxclients) {
log_message(LOG_WARNING,
"Can not start more than \"MaxClients\" servers. Starting %u servers instead.",
child_config.maxclients);
child_config.startservers = child_config.maxclients;
}
if (child_config.startservers > child_config.maxclients) {
log_message(LOG_WARNING,
"Can not start more than \"MaxClients\" servers. Starting %u servers instead.",
child_config.maxclients);
child_config.startservers = child_config.maxclients;
}
for (i = 0; i != child_config.maxclients; i++) {
child_ptr[i].status = T_EMPTY;
child_ptr[i].connects = 0;
}
for (i = 0; i != child_config.maxclients; i++) {
child_ptr[i].status = T_EMPTY;
child_ptr[i].connects = 0;
}
for (i = 0; i != child_config.startservers; i++) {
DEBUG2("Trying to create child %d of %d", i + 1, child_config.startservers);
child_ptr[i].status = T_WAITING;
child_ptr[i].tid = child_make(&child_ptr[i]);
for (i = 0; i != child_config.startservers; i++) {
DEBUG2("Trying to create child %d of %d", i + 1,
child_config.startservers);
child_ptr[i].status = T_WAITING;
child_ptr[i].tid = child_make(&child_ptr[i]);
if (child_ptr[i].tid < 0) {
log_message(LOG_WARNING,
"Could not create child number %d of %d",
i, child_config.startservers);
return -1;
} else {
log_message(LOG_INFO,
"Creating child number %d of %d ...",
i + 1, child_config.startservers);
if (child_ptr[i].tid < 0) {
log_message(LOG_WARNING,
"Could not create child number %d of %d",
i, child_config.startservers);
return -1;
} else {
log_message(LOG_INFO,
"Creating child number %d of %d ...",
i + 1, child_config.startservers);
SERVER_INC();
}
}
SERVER_INC();
}
}
log_message(LOG_INFO, "Finished creating all children.");
log_message(LOG_INFO, "Finished creating all children.");
return 0;
return 0;
}
/*
@ -356,59 +363,61 @@ child_pool_create(void)
void
child_main_loop(void)
{
unsigned int i;
unsigned int i;
while (1) {
if (config.quit)
return;
while (1) {
if (config.quit)
return;
/* If there are not enough spare servers, create more */
SERVER_COUNT_LOCK();
if (*servers_waiting < child_config.minspareservers) {
log_message(LOG_NOTICE,
"Waiting servers (%d) is less than MinSpareServers (%d). Creating new child.",
*servers_waiting, child_config.minspareservers);
/* If there are not enough spare servers, create more */
SERVER_COUNT_LOCK();
if (*servers_waiting < child_config.minspareservers) {
log_message(LOG_NOTICE,
"Waiting servers (%d) is less than MinSpareServers (%d). Creating new child.",
*servers_waiting,
child_config.minspareservers);
SERVER_COUNT_UNLOCK();
SERVER_COUNT_UNLOCK();
for (i = 0; i != child_config.maxclients; i++) {
if (child_ptr[i].status == T_EMPTY) {
child_ptr[i].status = T_WAITING;
child_ptr[i].tid = child_make(&child_ptr[i]);
if (child_ptr[i].tid < 0) {
log_message(LOG_NOTICE,
"Could not create child");
for (i = 0; i != child_config.maxclients; i++) {
if (child_ptr[i].status == T_EMPTY) {
child_ptr[i].status = T_WAITING;
child_ptr[i].tid =
child_make(&child_ptr[i]);
if (child_ptr[i].tid < 0) {
log_message(LOG_NOTICE,
"Could not create child");
child_ptr[i].status = T_EMPTY;
break;
}
child_ptr[i].status = T_EMPTY;
break;
}
SERVER_INC();
SERVER_INC();
break;
}
}
} else {
SERVER_COUNT_UNLOCK();
}
break;
}
}
} else {
SERVER_COUNT_UNLOCK();
}
sleep(5);
sleep(5);
/* Handle log rotation if it was requested */
if (received_sighup) {
truncate_log_file();
/* Handle log rotation if it was requested */
if (received_sighup) {
truncate_log_file();
#ifdef FILTER_ENABLE
if (config.filter) {
filter_destroy();
filter_init();
}
log_message(LOG_NOTICE, "Re-reading filter file.");
#endif /* FILTER_ENABLE */
if (config.filter) {
filter_destroy();
filter_init();
}
log_message(LOG_NOTICE, "Re-reading filter file.");
#endif /* FILTER_ENABLE */
received_sighup = FALSE;
}
}
received_sighup = FALSE;
}
}
}
/*
@ -417,23 +426,23 @@ child_main_loop(void)
void
child_kill_children(void)
{
unsigned int i;
for (i = 0; i != child_config.maxclients; i++) {
if (child_ptr[i].status != T_EMPTY)
kill(child_ptr[i].tid, SIGTERM);
}
unsigned int i;
for (i = 0; i != child_config.maxclients; i++) {
if (child_ptr[i].status != T_EMPTY)
kill(child_ptr[i].tid, SIGTERM);
}
}
int
child_listening_sock(uint16_t port)
{
listenfd = listen_sock(port, &addrlen);
return listenfd;
listenfd = listen_sock(port, &addrlen);
return listenfd;
}
void
child_close_sock(void)
{
close(listenfd);
close(listenfd);
}

View File

@ -1,4 +1,4 @@
/* $Id: child.h,v 1.3 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: child.h,v 1.4 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'child.c' for more information.
*
@ -19,11 +19,11 @@
#define TINYPROXY_CHILD_H
typedef enum {
CHILD_MAXCLIENTS,
CHILD_MAXSPARESERVERS,
CHILD_MINSPARESERVERS,
CHILD_STARTSERVERS,
CHILD_MAXREQUESTSPERCHILD
CHILD_MAXCLIENTS,
CHILD_MAXSPARESERVERS,
CHILD_MINSPARESERVERS,
CHILD_STARTSERVERS,
CHILD_MAXREQUESTSPERCHILD
} child_config_t;
extern short int child_pool_create(void);

View File

@ -1,4 +1,4 @@
/* $Id: common.h,v 1.8 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: common.h,v 1.9 2005-08-15 03:54:31 rjkaes Exp $
*
* This file groups all the headers required throughout the tinyproxy
* system. All this information use to be in the "tinyproxy.h" header,
@ -166,13 +166,13 @@
# define MSG_NOSIGNAL (0)
#endif
#ifndef SHUT_RD /* these three Posix.1g names are quite new */
# define SHUT_RD 0 /* shutdown for reading */
# define SHUT_WR 1 /* shutdown for writing */
# define SHUT_RDWR 2 /* shutdown for reading and writing */
#ifndef SHUT_RD /* these three Posix.1g names are quite new */
# define SHUT_RD 0 /* shutdown for reading */
# define SHUT_WR 1 /* shutdown for writing */
# define SHUT_RDWR 2 /* shutdown for reading and writing */
#endif
#define MAXLISTEN 1024 /* Max number of connections */
#define MAXLISTEN 1024 /* Max number of connections */
/*
* SunOS doesn't have INADDR_NONE defined.

View File

@ -1,4 +1,4 @@
/* $Id: conffile.c,v 1.4 2004-08-24 16:34:22 rjkaes Exp $
/* $Id: conffile.c,v 1.5 2005-08-15 03:54:31 rjkaes Exp $
*
* Parses the configuration file and sets up the config_s structure for
* use by the application. This file replaces the old grammar.y and
@ -57,12 +57,11 @@
*/
#define RE_MAX_MATCHES 16
/*
* All configuration handling functions are REQUIRED to be defined
* 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
@ -77,12 +76,16 @@ typedef int (*CONFFILE_HANDLER)(struct config_s*, const char*, regmatch_t[]);
*/
#define HANDLE_FUNC(func) int func(struct config_s* conf, const char* line, regmatch_t match[])
/*
* List all the handling functions. These are defined later, but they need
* to be in-scope before the big structure below.
*/
static HANDLE_FUNC(handle_nop) { return 0; } /* do nothing function */
static
HANDLE_FUNC(handle_nop)
{
return 0;
} /* do nothing function */
static HANDLE_FUNC(handle_allow);
static HANDLE_FUNC(handle_anonymous);
static HANDLE_FUNC(handle_bind);
@ -115,12 +118,12 @@ static HANDLE_FUNC(handle_statfile);
static HANDLE_FUNC(handle_stathost);
static HANDLE_FUNC(handle_syslog);
static HANDLE_FUNC(handle_timeout);
//static HANDLE_FUNC(handle_upstream);
static HANDLE_FUNC(handle_user);
static HANDLE_FUNC(handle_viaproxyname);
static HANDLE_FUNC(handle_xtinyproxy);
/*
* This macro can be used to make standard directives in the form:
* directive arguments [arguments ...]
@ -134,7 +137,6 @@ static HANDLE_FUNC(handle_xtinyproxy);
*/
#define STDCONF(d, re, func) { BEGIN "(" d ")" WS re END, func, NULL }
/*
* Holds the regular expression used to match the configuration directive,
* the function pointer to the routine to handle the directive, and
@ -142,74 +144,66 @@ static HANDLE_FUNC(handle_xtinyproxy);
* to be compiled one.
*/
struct {
const char* re;
const char *re;
CONFFILE_HANDLER handler;
regex_t* cre;
regex_t *cre;
} directives[] = {
/* comments */
{ BEGIN "#", handle_nop },
/* blank lines */
{ "^[[:space:]]+$", handle_nop },
/* string arguments */
STDCONF("logfile", STR, handle_logfile),
STDCONF("pidfile", STR, handle_pidfile),
STDCONF("anonymous", STR, handle_anonymous),
STDCONF("viaproxyname", STR, handle_viaproxyname),
STDCONF("defaulterrorfile", STR, handle_defaulterrorfile),
STDCONF("statfile", STR, handle_statfile),
STDCONF("stathost", STR, handle_stathost),
STDCONF("xtinyproxy", STR, handle_xtinyproxy),
/* boolean arguments */
STDCONF("syslog", BOOL, handle_syslog),
STDCONF("bindsame", BOOL, handle_bindsame),
/* integer arguments */
STDCONF("port", INT, handle_port),
STDCONF("maxclients", INT, handle_maxclients),
STDCONF("maxspareservers", INT, handle_maxspareservers),
STDCONF("minspareservers", INT, handle_minspareservers),
STDCONF("startservers", INT, handle_startservers),
STDCONF("maxrequestsperchild", INT, handle_maxrequestsperchild),
STDCONF("timeout", INT, handle_timeout),
STDCONF("connectport", INT, handle_connectport),
/* alphanumeric arguments */
STDCONF("user", ALNUM, handle_user),
STDCONF("group", ALNUM, handle_group),
/* ip arguments */
STDCONF("listen", IP, handle_listen),
STDCONF("allow", "(" IPMASK "|" ALNUM ")", handle_allow),
STDCONF("deny", "(" IPMASK "|" ALNUM ")", handle_deny),
STDCONF("bind", IP, handle_bind),
/* error files */
STDCONF("errorfile", INT WS STR, handle_errorfile),
/* filtering */
STDCONF("filter", STR, handle_filter),
STDCONF("filterurls", BOOL, handle_filterurls),
STDCONF("filterextended", BOOL, handle_filterextended),
STDCONF("filterdefaultdeny", BOOL, handle_filterdefaultdeny),
STDCONF("filtercasesensitive", BOOL, handle_filtercasesensitive),
/* Reverse proxy arguments */
STDCONF("reversebaseurl", STR, handle_reversebaseurl),
STDCONF("reverseonly", BOOL, handle_reverseonly),
STDCONF("reversemagic", BOOL, handle_reversemagic),
STDCONF("reversepath", STR WS "(" STR ")?", handle_reversepath),
/* upstream is rather complicated */
{
BEGIN "#", handle_nop},
/* blank lines */
{
"^[[:space:]]+$", handle_nop},
/* string arguments */
STDCONF("logfile", STR, handle_logfile),
STDCONF("pidfile", STR, handle_pidfile),
STDCONF("anonymous", STR, handle_anonymous),
STDCONF("viaproxyname", STR, handle_viaproxyname),
STDCONF("defaulterrorfile", STR, handle_defaulterrorfile),
STDCONF("statfile", STR, handle_statfile),
STDCONF("stathost", STR, handle_stathost),
STDCONF("xtinyproxy", STR, handle_xtinyproxy),
/* boolean arguments */
STDCONF("syslog", BOOL, handle_syslog),
STDCONF("bindsame", BOOL, handle_bindsame),
/* integer arguments */
STDCONF("port", INT, handle_port),
STDCONF("maxclients", INT, handle_maxclients),
STDCONF("maxspareservers", INT, handle_maxspareservers),
STDCONF("minspareservers", INT, handle_minspareservers),
STDCONF("startservers", INT, handle_startservers),
STDCONF("maxrequestsperchild", INT, handle_maxrequestsperchild),
STDCONF("timeout", INT, handle_timeout),
STDCONF("connectport", INT, handle_connectport),
/* alphanumeric arguments */
STDCONF("user", ALNUM, handle_user),
STDCONF("group", ALNUM, handle_group),
/* ip arguments */
STDCONF("listen", IP, handle_listen),
STDCONF("allow", "(" IPMASK "|" ALNUM ")", handle_allow),
STDCONF("deny", "(" IPMASK "|" ALNUM ")", handle_deny),
STDCONF("bind", IP, handle_bind),
/* error files */
STDCONF("errorfile", INT WS STR, handle_errorfile),
/* filtering */
STDCONF("filter", STR, handle_filter),
STDCONF("filterurls", BOOL, handle_filterurls),
STDCONF("filterextended", BOOL, handle_filterextended),
STDCONF("filterdefaultdeny", BOOL, handle_filterdefaultdeny),
STDCONF("filtercasesensitive", BOOL, handle_filtercasesensitive),
/* Reverse proxy arguments */
STDCONF("reversebaseurl", STR, handle_reversebaseurl),
STDCONF("reverseonly", BOOL, handle_reverseonly),
STDCONF("reversemagic", BOOL, handle_reversemagic),
STDCONF("reversepath", STR WS "(" STR ")?", handle_reversepath),
/* upstream is rather complicated */
// { BEGIN "no" WS "upstream" WS STR END, handle_no_upstream },
// { BEGIN "upstream" WS IP ":" INT "(" WS STR ")" END, handle_upstream },
/* loglevel */
STDCONF("loglevel", "(critical|error|warning|notice|connect|info)", handle_loglevel)
/* loglevel */
STDCONF("loglevel", "(critical|error|warning|notice|connect|info)",
handle_loglevel)
};
const unsigned int ndirectives = sizeof(directives)/sizeof(directives[0]);
const unsigned int ndirectives = sizeof(directives) / sizeof(directives[0]);
/*
* Compiles the regular expressions used by the configuration file. This
@ -225,7 +219,7 @@ config_compile(void)
for (i = 0; i != ndirectives; ++i) {
assert(directives[i].handler);
assert(!directives[i].cre);
directives[i].cre = safemalloc(sizeof(regex_t));
if (!directives[i].cre)
return -1;
@ -233,12 +227,12 @@ config_compile(void)
r = regcomp(directives[i].cre,
directives[i].re,
REG_EXTENDED | REG_ICASE | REG_NEWLINE);
if (r) return r;
if (r)
return r;
}
return 0;
}
/*
* Attempt to match the supplied line with any of the configuration
* regexes defined above. If a match is found, call the handler
@ -248,7 +242,7 @@ config_compile(void)
* a negative number is returned.
*/
static int
check_match(struct config_s* conf, const char* line)
check_match(struct config_s *conf, const char *line)
{
regmatch_t match[RE_MAX_MATCHES];
unsigned int i;
@ -258,7 +252,7 @@ check_match(struct config_s* conf, const char* line)
for (i = 0; i != ndirectives; ++i) {
assert(directives[i].cre);
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);
}
return -1;
@ -268,9 +262,9 @@ check_match(struct config_s* conf, const char* line)
* Parse the previously opened configuration stream.
*/
int
config_parse(struct config_s* conf, FILE* f)
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;
while (fgets(buffer, sizeof(buffer), f)) {
@ -283,7 +277,6 @@ config_parse(struct config_s* conf, FILE* f)
return 0;
}
/***********************************************************************
*
* The following are basic data extraction building blocks that can
@ -291,15 +284,15 @@ config_parse(struct config_s* conf, FILE* f)
*
***********************************************************************/
static char*
get_string_arg(const char* line, regmatch_t* match)
static char *
get_string_arg(const char *line, regmatch_t * match)
{
char *p;
const unsigned int len = match->rm_eo - match->rm_so;
assert(line);
assert(len > 0);
p = safemalloc(len + 1);
if (!p)
return NULL;
@ -310,9 +303,10 @@ get_string_arg(const char* line, regmatch_t* match)
}
static int
set_string_arg(char** var, const char* line, regmatch_t* match)
set_string_arg(char **var, const char *line, regmatch_t * match)
{
char* arg = get_string_arg(line, match);
char *arg = get_string_arg(line, match);
if (!arg)
return -1;
*var = safestrdup(arg);
@ -321,9 +315,9 @@ set_string_arg(char** var, const char* line, regmatch_t* match)
}
static int
get_bool_arg(const char* line, regmatch_t* match)
get_bool_arg(const char *line, regmatch_t * match)
{
const char* p = line + match->rm_so;
const char *p = line + match->rm_so;
assert(line);
assert(match && match->rm_so != -1);
@ -336,36 +330,35 @@ get_bool_arg(const char* line, regmatch_t* match)
}
static int
set_bool_arg(unsigned int* var, const char* line, regmatch_t* match)
set_bool_arg(unsigned int *var, const char *line, regmatch_t * match)
{
assert(var);
assert(line);
assert(match && match->rm_so != -1);
*var = get_bool_arg(line, match);
return 0;
}
static inline long int
get_int_arg(const char* line, regmatch_t* match)
get_int_arg(const char *line, regmatch_t * match)
{
assert(line);
assert(match && match->rm_so != -1);
return strtol(line + match->rm_so, NULL, 0);
}
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)
{
assert(var);
assert(line);
assert(match);
*var = get_int_arg(line, match);
return 0;
}
/***********************************************************************
*
* Below are all the directive handling functions. You will notice
@ -384,17 +377,23 @@ set_int_arg(int long* var, const char* line, regmatch_t* match)
*
***********************************************************************/
static HANDLE_FUNC(handle_logfile)
static
HANDLE_FUNC(handle_logfile)
{
return set_string_arg(&conf->logf_name, line, &match[2]);
}
static HANDLE_FUNC(handle_pidfile)
static
HANDLE_FUNC(handle_pidfile)
{
return set_string_arg(&conf->pidpath, line, &match[2]);
}
static HANDLE_FUNC(handle_anonymous)
static
HANDLE_FUNC(handle_anonymous)
{
char *arg = get_string_arg(line, &match[2]);
if (!arg)
return -1;
@ -402,35 +401,46 @@ static HANDLE_FUNC(handle_anonymous)
safefree(arg);
return 0;
}
static HANDLE_FUNC(handle_viaproxyname)
static
HANDLE_FUNC(handle_viaproxyname)
{
int r = set_string_arg(&conf->via_proxy_name, line, &match[2]);
if (r) return r;
if (r)
return r;
log_message(LOG_INFO,
"Setting \"Via\" header proxy to %s",
conf->via_proxy_name);
"Setting \"Via\" header proxy to %s", conf->via_proxy_name);
return 0;
}
static HANDLE_FUNC(handle_defaulterrorfile)
static
HANDLE_FUNC(handle_defaulterrorfile)
{
return set_string_arg(&conf->errorpage_undef, line, &match[2]);
}
static HANDLE_FUNC(handle_statfile)
static
HANDLE_FUNC(handle_statfile)
{
return set_string_arg(&conf->statpage, line, &match[2]);
}
static HANDLE_FUNC(handle_stathost)
static
HANDLE_FUNC(handle_stathost)
{
int r = set_string_arg(&conf->stathost, line, &match[2]);
if (r) return r;
log_message(LOG_INFO,
"Stathost set to \"%s\"",
conf->stathost);
if (r)
return r;
log_message(LOG_INFO, "Stathost set to \"%s\"", conf->stathost);
return 0;
}
static HANDLE_FUNC(handle_xtinyproxy)
static
HANDLE_FUNC(handle_xtinyproxy)
{
#ifdef XTINYPROXY_ENABLE
#ifdef XTINYPROXY_ENABLE
return set_string_arg(&conf->my_domain, line, &match[2]);
#else
fprintf(stderr,
@ -438,91 +448,126 @@ static HANDLE_FUNC(handle_xtinyproxy)
return 1;
#endif
}
static HANDLE_FUNC(handle_syslog)
static
HANDLE_FUNC(handle_syslog)
{
#ifdef HAVE_SYSLOG_H
#ifdef HAVE_SYSLOG_H
return set_bool_arg(&conf->syslog, line, &match[2]);
#else
fprintf(stderr,
"Syslog support not compiled in executable.\n");
fprintf(stderr, "Syslog support not compiled in executable.\n");
return 1;
#endif
}
static HANDLE_FUNC(handle_bindsame)
static
HANDLE_FUNC(handle_bindsame)
{
int r = set_bool_arg(&conf->bindsame, line, &match[2]);
if (r) return r;
if (r)
return r;
log_message(LOG_INFO, "Binding outgoing connection to incoming IP");
return 0;
}
static HANDLE_FUNC(handle_port)
static
HANDLE_FUNC(handle_port)
{
return set_int_arg((long int*)&conf->port, line, &match[2]);
return set_int_arg((long int *)&conf->port, line, &match[2]);
}
static HANDLE_FUNC(handle_maxclients)
static
HANDLE_FUNC(handle_maxclients)
{
child_configure(CHILD_MAXCLIENTS, get_int_arg(line, &match[2]));
return 0;
}
static HANDLE_FUNC(handle_maxspareservers)
static
HANDLE_FUNC(handle_maxspareservers)
{
child_configure(CHILD_MAXSPARESERVERS, get_int_arg(line, &match[2]));
return 0;
}
static HANDLE_FUNC(handle_minspareservers)
static
HANDLE_FUNC(handle_minspareservers)
{
child_configure(CHILD_MINSPARESERVERS, get_int_arg(line, &match[2]));
return 0;
}
static HANDLE_FUNC(handle_startservers)
static
HANDLE_FUNC(handle_startservers)
{
child_configure(CHILD_STARTSERVERS, get_int_arg(line, &match[2]));
return 0;
}
static HANDLE_FUNC(handle_maxrequestsperchild)
static
HANDLE_FUNC(handle_maxrequestsperchild)
{
child_configure(CHILD_MAXREQUESTSPERCHILD, get_int_arg(line, &match[2]));
child_configure(CHILD_MAXREQUESTSPERCHILD,
get_int_arg(line, &match[2]));
return 0;
}
static HANDLE_FUNC(handle_timeout)
static
HANDLE_FUNC(handle_timeout)
{
return set_int_arg((long int*)&conf->idletimeout, line, &match[2]);
return set_int_arg((long int *)&conf->idletimeout, line, &match[2]);
}
static HANDLE_FUNC(handle_connectport)
static
HANDLE_FUNC(handle_connectport)
{
add_connect_port_allowed(get_int_arg(line, &match[2]));
return 0;
}
static HANDLE_FUNC(handle_user)
static
HANDLE_FUNC(handle_user)
{
return set_string_arg(&conf->username, line, &match[2]);
}
static HANDLE_FUNC(handle_group)
static
HANDLE_FUNC(handle_group)
{
return set_string_arg(&conf->group, line, &match[2]);
}
static HANDLE_FUNC(handle_allow)
static
HANDLE_FUNC(handle_allow)
{
char* arg = get_string_arg(line, &match[2]);
char *arg = get_string_arg(line, &match[2]);
insert_acl(arg, ACL_ALLOW);
safefree(arg);
return 0;
}
static HANDLE_FUNC(handle_deny)
static
HANDLE_FUNC(handle_deny)
{
char *arg = get_string_arg(line, &match[2]);
insert_acl(arg, ACL_DENY);
safefree(arg);
return 0;
}
static HANDLE_FUNC(handle_bind)
static
HANDLE_FUNC(handle_bind)
{
#ifndef TRANSPARENT_PROXY
int r = set_string_arg(&conf->bind_address, line, &match[2]);
if (r) return r;
if (r)
return r;
log_message(LOG_INFO,
"Outgoing connections bound to IP %s",
conf->bind_address);
"Outgoing connections bound to IP %s", conf->bind_address);
return 0;
#else
fprintf(stderr,
@ -530,14 +575,20 @@ static HANDLE_FUNC(handle_bind)
return 1;
#endif
}
static HANDLE_FUNC(handle_listen)
static
HANDLE_FUNC(handle_listen)
{
int r = set_string_arg(&conf->ipAddr, line, &match[2]);
if (r) return r;
if (r)
return r;
log_message(LOG_INFO, "Listing on IP %s", conf->ipAddr);
return 0;
}
static HANDLE_FUNC(handle_errorfile)
static
HANDLE_FUNC(handle_errorfile)
{
/*
* Because an integer is defined as ((0x)?[[:digit:]]+) _two_
@ -548,6 +599,7 @@ static HANDLE_FUNC(handle_errorfile)
*/
long int err = get_int_arg(line, &match[2]);
char *page = get_string_arg(line, &match[4]);
add_new_errorpage(page, err);
safefree(page);
return 0;
@ -557,24 +609,27 @@ static HANDLE_FUNC(handle_errorfile)
* Log level's strings.
*/
struct log_levels_s {
const char* string;
const char *string;
int level;
};
static struct log_levels_s log_levels[] = {
{ "critical", LOG_CRIT },
{ "error", LOG_ERR },
{ "warning", LOG_WARNING },
{ "notice", LOG_NOTICE },
{ "connect", LOG_CONN },
{ "info", LOG_INFO }
{"critical", LOG_CRIT},
{"error", LOG_ERR},
{"warning", LOG_WARNING},
{"notice", LOG_NOTICE},
{"connect", LOG_CONN},
{"info", LOG_INFO}
};
static HANDLE_FUNC(handle_loglevel)
static
HANDLE_FUNC(handle_loglevel)
{
static const unsigned int nlevels = sizeof(log_levels)/sizeof(log_levels[0]);
static const unsigned int nlevels =
sizeof(log_levels) / sizeof(log_levels[0]);
unsigned int i;
char *arg = get_string_arg(line, &match[2]);
for (i = 0; i != nlevels; ++i) {
if (!strcasecmp(arg, log_levels[i].string)) {
set_log_level(log_levels[i].level);
@ -584,29 +639,37 @@ static HANDLE_FUNC(handle_loglevel)
return -1;
}
#ifdef FILTER_ENABLE
static HANDLE_FUNC(handle_filter)
static
HANDLE_FUNC(handle_filter)
{
return set_string_arg(&conf->filter, line, &match[2]);
}
static HANDLE_FUNC(handle_filterurls)
static
HANDLE_FUNC(handle_filterurls)
{
return set_bool_arg(&conf->filter_url, line, &match[2]);
}
static HANDLE_FUNC(handle_filterextended)
static
HANDLE_FUNC(handle_filterextended)
{
return set_bool_arg(&conf->filter_extended, line, &match[2]);
}
static HANDLE_FUNC(handle_filterdefaultdeny)
static
HANDLE_FUNC(handle_filterdefaultdeny)
{
assert(match[2].rm_so != -1);
if (get_bool_arg(line, &match[2]))
filter_set_default_policy(FILTER_DEFAULT_DENY);
return 0;
}
static HANDLE_FUNC(handle_filtercasesensitive)
static
HANDLE_FUNC(handle_filtercasesensitive)
{
return set_bool_arg(&conf->filter_casesensitive, line, &match[2]);
}
@ -618,29 +681,59 @@ no_filter_support(void)
return -1;
}
static HANDLE_FUNC(handle_filter) { return no_filter_support(); }
static HANDLE_FUNC(handle_filtercasesensitive) { return no_filter_support(); }
static HANDLE_FUNC(handle_filterdefaultdeny) { return no_filter_support(); }
static HANDLE_FUNC(handle_filterextended) { return no_filter_support(); }
static HANDLE_FUNC(handle_filterurls) { return no_filter_support(); }
static
HANDLE_FUNC(handle_filter)
{
return no_filter_support();
}
static
HANDLE_FUNC(handle_filtercasesensitive)
{
return no_filter_support();
}
static
HANDLE_FUNC(handle_filterdefaultdeny)
{
return no_filter_support();
}
static
HANDLE_FUNC(handle_filterextended)
{
return no_filter_support();
}
static
HANDLE_FUNC(handle_filterurls)
{
return no_filter_support();
}
#endif
#ifdef REVERSE_SUPPORT
static HANDLE_FUNC(handle_reverseonly)
static
HANDLE_FUNC(handle_reverseonly)
{
return set_bool_arg(&conf->reverseonly, line, &match[2]);
}
static HANDLE_FUNC(handle_reversemagic)
static
HANDLE_FUNC(handle_reversemagic)
{
return set_bool_arg(&conf->reversemagic, line, &match[2]);
}
static HANDLE_FUNC(handle_reversebaseurl)
static
HANDLE_FUNC(handle_reversebaseurl)
{
return set_string_arg(&conf->reversebaseurl, line, &match[2]);
}
static HANDLE_FUNC(handle_reversepath)
static
HANDLE_FUNC(handle_reversepath)
{
/*
* The second string argument is optional.
@ -648,7 +741,8 @@ static HANDLE_FUNC(handle_reversepath)
char *arg1, *arg2;
arg1 = get_string_arg(line, &match[2]);
if (!arg1) return -1;
if (!arg1)
return -1;
if (match[3].rm_so != -1) {
arg2 = get_string_arg(line, &match[3]);
@ -674,9 +768,28 @@ no_reverse_support(void)
return -1;
}
static HANDLE_FUNC(handle_reversebaseurl) { return no_reverse_support(); }
static HANDLE_FUNC(handle_reversemagic) { return no_reverse_support(); }
static HANDLE_FUNC(handle_reverseonly) { return no_reverse_support(); }
static HANDLE_FUNC(handle_reversepath) { return no_reverse_support(); }
static
HANDLE_FUNC(handle_reversebaseurl)
{
return no_reverse_support();
}
static
HANDLE_FUNC(handle_reversemagic)
{
return no_reverse_support();
}
static
HANDLE_FUNC(handle_reverseonly)
{
return no_reverse_support();
}
static
HANDLE_FUNC(handle_reversepath)
{
return no_reverse_support();
}
#endif

View File

@ -1,4 +1,4 @@
/* $Id: conffile.h,v 1.1 2004-08-13 20:19:50 rjkaes Exp $
/* $Id: conffile.h,v 1.2 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'conffile.c' for more details.
*
@ -19,6 +19,6 @@
#define TINYPROXY_CONFFILE_H
extern int config_compile(void);
extern int config_parse(struct config_s* conf, FILE* f);
extern int config_parse(struct config_s *conf, FILE * f);
#endif

View File

@ -1,4 +1,4 @@
/* $Id: conns.c,v 1.24 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: conns.c,v 1.25 2005-08-15 03:54:31 rjkaes Exp $
*
* Create and free the connection structure. One day there could be
* other connection related tasks put here, but for now the header
@ -27,118 +27,118 @@
#include "stats.h"
struct conn_s *
initialize_conn(int client_fd, const char* ipaddr, const char* string_addr,
const char* sock_ipaddr)
initialize_conn(int client_fd, const char *ipaddr, const char *string_addr,
const char *sock_ipaddr)
{
struct conn_s *connptr;
struct buffer_s *cbuffer, *sbuffer;
struct conn_s *connptr;
struct buffer_s *cbuffer, *sbuffer;
assert(client_fd >= 0);
assert(client_fd >= 0);
/*
* Allocate the memory for all the internal components
*/
cbuffer = new_buffer();
sbuffer = new_buffer();
/*
* Allocate the memory for all the internal components
*/
cbuffer = new_buffer();
sbuffer = new_buffer();
if (!cbuffer || !sbuffer)
goto error_exit;
if (!cbuffer || !sbuffer)
goto error_exit;
/*
* Allocate the space for the conn_s structure itself.
*/
connptr = safemalloc(sizeof(struct conn_s));
if (!connptr)
goto error_exit;
/*
* Allocate the space for the conn_s structure itself.
*/
connptr = safemalloc(sizeof(struct conn_s));
if (!connptr)
goto error_exit;
connptr->client_fd = client_fd;
connptr->server_fd = -1;
connptr->client_fd = client_fd;
connptr->server_fd = -1;
connptr->cbuffer = cbuffer;
connptr->sbuffer = sbuffer;
connptr->cbuffer = cbuffer;
connptr->sbuffer = sbuffer;
connptr->request_line = NULL;
connptr->request_line = NULL;
/* These store any error strings */
connptr->error_variables = NULL;
connptr->error_string = NULL;
connptr->error_number = -1;
/* These store any error strings */
connptr->error_variables = NULL;
connptr->error_string = NULL;
connptr->error_number = -1;
connptr->connect_method = FALSE;
connptr->show_stats = FALSE;
connptr->connect_method = FALSE;
connptr->show_stats = FALSE;
connptr->protocol.major = connptr->protocol.minor = 0;
connptr->protocol.major = connptr->protocol.minor = 0;
/* There is _no_ content length initially */
connptr->content_length.server = connptr->content_length.client = -1;
/* There is _no_ content length initially */
connptr->content_length.server = connptr->content_length.client = -1;
connptr->server_ip_addr = sock_ipaddr ? safestrdup(sock_ipaddr) : 0;
connptr->client_ip_addr = safestrdup(ipaddr);
connptr->client_string_addr = safestrdup(string_addr);
connptr->server_ip_addr = sock_ipaddr ? safestrdup(sock_ipaddr) : 0;
connptr->client_ip_addr = safestrdup(ipaddr);
connptr->client_string_addr = safestrdup(string_addr);
connptr->upstream_proxy = NULL;
connptr->upstream_proxy = NULL;
update_stats(STAT_OPEN);
update_stats(STAT_OPEN);
#ifdef REVERSE_SUPPORT
connptr->reversepath = NULL;
connptr->reversepath = NULL;
#endif
return connptr;
return connptr;
error_exit:
/*
* If we got here, there was a problem allocating memory
*/
if (cbuffer)
delete_buffer(cbuffer);
if (sbuffer)
delete_buffer(sbuffer);
error_exit:
/*
* If we got here, there was a problem allocating memory
*/
if (cbuffer)
delete_buffer(cbuffer);
if (sbuffer)
delete_buffer(sbuffer);
return NULL;
return NULL;
}
void
destroy_conn(struct conn_s *connptr)
{
assert(connptr != NULL);
assert(connptr != NULL);
if (connptr->client_fd != -1)
if (close(connptr->client_fd) < 0)
log_message(LOG_INFO, "Client (%d) close message: %s",
connptr->client_fd, strerror(errno));
if (connptr->server_fd != -1)
if (close(connptr->server_fd) < 0)
log_message(LOG_INFO, "Server (%d) close message: %s",
connptr->server_fd, strerror(errno));
if (connptr->client_fd != -1)
if (close(connptr->client_fd) < 0)
log_message(LOG_INFO, "Client (%d) close message: %s",
connptr->client_fd, strerror(errno));
if (connptr->server_fd != -1)
if (close(connptr->server_fd) < 0)
log_message(LOG_INFO, "Server (%d) close message: %s",
connptr->server_fd, strerror(errno));
if (connptr->cbuffer)
delete_buffer(connptr->cbuffer);
if (connptr->sbuffer)
delete_buffer(connptr->sbuffer);
if (connptr->cbuffer)
delete_buffer(connptr->cbuffer);
if (connptr->sbuffer)
delete_buffer(connptr->sbuffer);
if (connptr->request_line)
safefree(connptr->request_line);
if (connptr->request_line)
safefree(connptr->request_line);
if (connptr->error_variables)
hashmap_delete(connptr->error_variables);
if (connptr->error_variables)
hashmap_delete(connptr->error_variables);
if (connptr->error_string)
safefree(connptr->error_string);
if (connptr->error_string)
safefree(connptr->error_string);
if (connptr->server_ip_addr)
safefree(connptr->server_ip_addr);
if (connptr->client_ip_addr)
safefree(connptr->client_ip_addr);
if (connptr->client_string_addr)
safefree(connptr->client_string_addr);
if (connptr->server_ip_addr)
safefree(connptr->server_ip_addr);
if (connptr->client_ip_addr)
safefree(connptr->client_ip_addr);
if (connptr->client_string_addr)
safefree(connptr->client_string_addr);
#ifdef REVERSE_SUPPORT
if (connptr->reversepath)
safefree(connptr->reversepath);
if (connptr->reversepath)
safefree(connptr->reversepath);
#endif
safefree(connptr);
safefree(connptr);
update_stats(STAT_CLOSE);
update_stats(STAT_CLOSE);
}

View File

@ -1,4 +1,4 @@
/* $Id: conns.h,v 1.19 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: conns.h,v 1.20 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'conns.c' for a detailed description.
*
@ -25,58 +25,58 @@
* Connection Definition
*/
struct conn_s {
int client_fd;
int server_fd;
int client_fd;
int server_fd;
struct buffer_s *cbuffer;
struct buffer_s *sbuffer;
struct buffer_s *cbuffer;
struct buffer_s *sbuffer;
/* The request line (first line) from the client */
char *request_line;
/* The request line (first line) from the client */
char *request_line;
/* Booleans */
unsigned int connect_method;
unsigned int show_stats;
/* Booleans */
unsigned int connect_method;
unsigned int show_stats;
/*
* This structure stores key -> value mappings for substitution
* in the error HTML files.
*/
hashmap_t error_variables;
* This structure stores key -> value mappings for substitution
* in the error HTML files.
*/
hashmap_t error_variables;
int error_number;
char *error_string;
int error_number;
char *error_string;
/* A Content-Length value from the remote server */
struct {
long int server;
long int client;
} content_length;
/* A Content-Length value from the remote server */
struct {
long int server;
long int client;
} content_length;
/*
* Store the server's IP (for BindSame)
*/
char* server_ip_addr;
/*
* Store the server's IP (for BindSame)
*/
char *server_ip_addr;
/*
* Store the client's IP and hostname information
*/
char* client_ip_addr;
char* client_string_addr;
/*
* Store the client's IP and hostname information
*/
char *client_ip_addr;
char *client_string_addr;
/*
* Store the incoming request's HTTP protocol.
*/
struct {
unsigned int major;
unsigned int minor;
} protocol;
/*
* Store the incoming request's HTTP protocol.
*/
struct {
unsigned int major;
unsigned int minor;
} protocol;
#ifdef REVERSE_SUPPORT
/*
* Place to store the current per-connection reverse proxy path
*/
char* reversepath;
/*
* Place to store the current per-connection reverse proxy path
*/
char *reversepath;
#endif
/*
@ -88,9 +88,9 @@ struct conn_s {
/*
* Functions for the creation and destruction of a connection structure.
*/
extern struct conn_s* initialize_conn(int client_fd, const char* ipaddr,
const char* string_addr,
const char* sock_ipaddr);
extern struct conn_s *initialize_conn(int client_fd, const char *ipaddr,
const char *string_addr,
const char *sock_ipaddr);
extern void destroy_conn(struct conn_s *connptr);
#endif

View File

@ -1,4 +1,4 @@
/* $Id: daemon.c,v 1.4 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: daemon.c,v 1.5 2005-08-15 03:54:31 rjkaes Exp $
*
* This file contains functions which are useful when writing a
* daemon process. The functions include a "makedaemon" function and
@ -28,26 +28,26 @@
void
makedaemon(void)
{
if (fork() != 0)
exit(0);
if (fork() != 0)
exit(0);
setsid();
set_signal_handler(SIGHUP, SIG_IGN);
setsid();
set_signal_handler(SIGHUP, SIG_IGN);
if (fork() != 0)
exit(0);
if (fork() != 0)
exit(0);
chdir("/");
umask(077);
chdir("/");
umask(077);
#if NDEBUG
/*
* When not in debugging mode, close the standard file
* descriptors.
*/
close(0);
close(1);
close(2);
close(0);
close(1);
close(2);
#endif
}
@ -56,25 +56,25 @@ makedaemon(void)
* to handle signals sent to the process.
*/
signal_func *
set_signal_handler(int signo, signal_func *func)
set_signal_handler(int signo, signal_func * func)
{
struct sigaction act, oact;
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo == SIGALRM) {
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo == SIGALRM) {
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
#endif
} else {
} else {
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART; /* SVR4, 4.4BSD */
act.sa_flags |= SA_RESTART; /* SVR4, 4.4BSD */
#endif
}
}
if (sigaction(signo, &act, &oact) < 0)
return SIG_ERR;
if (sigaction(signo, &act, &oact) < 0)
return SIG_ERR;
return oact.sa_handler;
return oact.sa_handler;
}

View File

@ -1,4 +1,4 @@
/* $Id: daemon.h,v 1.2 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: daemon.h,v 1.3 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'daemon.c' for a detailed description.
*
@ -23,7 +23,7 @@ typedef void signal_func(int);
/*
* Pass a singal integer and a function to handle the signal.
*/
extern signal_func *set_signal_handler(int signo, signal_func *func);
extern signal_func *set_signal_handler(int signo, signal_func * func);
/*
* Make a program a daemon process

View File

@ -1,4 +1,4 @@
/* $Id: filter.c,v 1.21 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: filter.c,v 1.22 2005-08-15 03:54:31 rjkaes Exp $
*
* Copyright (c) 1999 George Talusan (gstalusan@uwaterloo.ca)
* Copyright (c) 2002 James E. Flemer (jflemer@acm.jhu.edu)
@ -30,9 +30,9 @@
static int err;
struct filter_list {
struct filter_list *next;
char *pat;
regex_t *cpat;
struct filter_list *next;
char *pat;
regex_t *cpat;
};
static struct filter_list *fl = NULL;
@ -45,158 +45,162 @@ static filter_policy_t default_policy = FILTER_DEFAULT_ALLOW;
void
filter_init(void)
{
FILE *fd;
struct filter_list *p;
char buf[FILTER_BUFFER_LEN];
char *s;
int cflags;
FILE *fd;
struct filter_list *p;
char buf[FILTER_BUFFER_LEN];
char *s;
int cflags;
if (!fl && !already_init) {
fd = fopen(config.filter, "r");
if (fd) {
p = NULL;
if (!fl && !already_init) {
fd = fopen(config.filter, "r");
if (fd) {
p = NULL;
cflags = REG_NEWLINE | REG_NOSUB;
if (config.filter_extended)
cflags |= REG_EXTENDED;
if (!config.filter_casesensitive)
cflags |= REG_ICASE;
cflags = REG_NEWLINE | REG_NOSUB;
if (config.filter_extended)
cflags |= REG_EXTENDED;
if (!config.filter_casesensitive)
cflags |= REG_ICASE;
while (fgets(buf, FILTER_BUFFER_LEN, fd)) {
/*
* Remove any trailing white space and
* comments.
*/
s = buf;
while (*s) {
if (isspace((unsigned char)*s)) break;
if (*s == '#') {
/*
* If the '#' char is preceeded by
* an escape, it's not a comment
* string.
*/
if (s == buf || *(s - 1) != '\\')
break;
}
++s;
}
*s = '\0';
while (fgets(buf, FILTER_BUFFER_LEN, fd)) {
/*
* Remove any trailing white space and
* comments.
*/
s = buf;
while (*s) {
if (isspace((unsigned char)*s))
break;
if (*s == '#') {
/*
* If the '#' char is preceeded by
* an escape, it's not a comment
* string.
*/
if (s == buf
|| *(s - 1) != '\\')
break;
}
++s;
}
*s = '\0';
/* skip leading whitespace */
s = buf;
while (*s && isspace((unsigned char)*s))
s++;
/* skip leading whitespace */
s = buf;
while (*s && isspace((unsigned char)*s))
s++;
/* skip blank lines and comments */
if (*s == '\0')
continue;
/* skip blank lines and comments */
if (*s == '\0')
continue;
if (!p) /* head of list */
fl = p =
safecalloc(1,
sizeof(struct
filter_list));
else { /* next entry */
p->next =
safecalloc(1,
sizeof(struct
filter_list));
p = p->next;
}
if (!p) /* head of list */
fl = p =
safecalloc(1,
sizeof(struct
filter_list));
else { /* next entry */
p->next =
safecalloc(1,
sizeof(struct
filter_list));
p = p->next;
}
p->pat = safestrdup(s);
p->cpat = safemalloc(sizeof(regex_t));
if ((err = regcomp(p->cpat, p->pat, cflags)) != 0) {
fprintf(stderr, "Bad regex in %s: %s\n",
config.filter, p->pat);
exit(EX_DATAERR);
}
}
if (ferror(fd)) {
perror("fgets");
exit(EX_DATAERR);
}
fclose(fd);
p->pat = safestrdup(s);
p->cpat = safemalloc(sizeof(regex_t));
if ((err =
regcomp(p->cpat, p->pat, cflags)) != 0) {
fprintf(stderr, "Bad regex in %s: %s\n",
config.filter, p->pat);
exit(EX_DATAERR);
}
}
if (ferror(fd)) {
perror("fgets");
exit(EX_DATAERR);
}
fclose(fd);
already_init = 1;
}
}
already_init = 1;
}
}
}
/* unlink the list */
void
filter_destroy(void)
{
struct filter_list *p, *q;
struct filter_list *p, *q;
if (already_init) {
for (p = q = fl; p; p = q) {
regfree(p->cpat);
safefree(p->cpat);
safefree(p->pat);
q = p->next;
safefree(p);
}
fl = NULL;
already_init = 0;
}
if (already_init) {
for (p = q = fl; p; p = q) {
regfree(p->cpat);
safefree(p->cpat);
safefree(p->pat);
q = p->next;
safefree(p);
}
fl = NULL;
already_init = 0;
}
}
/* Return 0 to allow, non-zero to block */
int
filter_domain(const char *host)
{
struct filter_list *p;
int result;
struct filter_list *p;
int result;
if (!fl || !already_init)
goto COMMON_EXIT;
if (!fl || !already_init)
goto COMMON_EXIT;
for (p = fl; p; p = p->next) {
result = regexec(p->cpat, host, (size_t) 0, (regmatch_t *) 0, 0);
for (p = fl; p; p = p->next) {
result =
regexec(p->cpat, host, (size_t) 0, (regmatch_t *) 0, 0);
if (result == 0) {
if (default_policy == FILTER_DEFAULT_ALLOW)
return 1;
else
return 0;
}
}
if (result == 0) {
if (default_policy == FILTER_DEFAULT_ALLOW)
return 1;
else
return 0;
}
}
COMMON_EXIT:
if (default_policy == FILTER_DEFAULT_ALLOW)
return 0;
else
return 1;
COMMON_EXIT:
if (default_policy == FILTER_DEFAULT_ALLOW)
return 0;
else
return 1;
}
/* returns 0 to allow, non-zero to block */
int
filter_url(const char *url)
{
struct filter_list *p;
int result;
struct filter_list *p;
int result;
if (!fl || !already_init)
goto COMMON_EXIT;
if (!fl || !already_init)
goto COMMON_EXIT;
for (p = fl; p; p = p->next) {
result = regexec(p->cpat, url, (size_t) 0, (regmatch_t *) 0, 0);
for (p = fl; p; p = p->next) {
result = regexec(p->cpat, url, (size_t) 0, (regmatch_t *) 0, 0);
if (result == 0) {
if (default_policy == FILTER_DEFAULT_ALLOW)
return 1;
else
return 0;
}
}
if (result == 0) {
if (default_policy == FILTER_DEFAULT_ALLOW)
return 1;
else
return 0;
}
}
COMMON_EXIT:
if (default_policy == FILTER_DEFAULT_ALLOW)
return 0;
else
return 1;
COMMON_EXIT:
if (default_policy == FILTER_DEFAULT_ALLOW)
return 0;
else
return 1;
}
/*
@ -205,5 +209,5 @@ filter_url(const char *url)
void
filter_set_default_policy(filter_policy_t policy)
{
default_policy = policy;
default_policy = policy;
}

View File

@ -1,4 +1,4 @@
/* $Id: filter.h,v 1.5 2002-06-07 18:36:21 rjkaes Exp $
/* $Id: filter.h,v 1.6 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'filter.c' for a detailed description.
*
@ -19,8 +19,8 @@
#define _TINYPROXY_FILTER_H_
typedef enum {
FILTER_DEFAULT_ALLOW,
FILTER_DEFAULT_DENY,
FILTER_DEFAULT_ALLOW,
FILTER_DEFAULT_DENY,
} filter_policy_t;
extern void filter_init(void);

View File

@ -1,4 +1,4 @@
/* $Id: hashmap.c,v 1.16 2005-07-12 17:39:43 rjkaes Exp $
/* $Id: hashmap.c,v 1.17 2005-08-15 03:54:31 rjkaes Exp $
*
* A hashmap implementation. The keys are case-insensitive NULL terminated
* strings, and the data is arbitrary lumps of data. Copies of both the
@ -38,11 +38,11 @@
* with.
*/
struct hashentry_s {
char *key;
void *data;
size_t len;
char *key;
void *data;
size_t len;
struct hashentry_s *prev, *next;
struct hashentry_s *prev, *next;
};
struct hashbucket_s {
@ -50,10 +50,10 @@ struct hashbucket_s {
};
struct hashmap_s {
unsigned int size;
hashmap_iter end_iterator;
unsigned int size;
hashmap_iter end_iterator;
struct hashbucket_s *buckets;
struct hashbucket_s *buckets;
};
/*
@ -68,23 +68,23 @@ struct hashmap_s {
static int
hashfunc(const char *key, unsigned int size)
{
uint32_t hash;
uint32_t hash;
if (key == NULL)
return -EINVAL;
if (size == 0)
return -ERANGE;
for (hash = tolower(*key++); *key != '\0'; key++) {
uint32_t bit =
(hash & 1) ? (1 << (sizeof(uint32_t) - 1)) : 0;
hash >>= 1;
if (key == NULL)
return -EINVAL;
if (size == 0)
return -ERANGE;
hash += tolower(*key) + bit;
}
for (hash = tolower(*key++); *key != '\0'; key++) {
uint32_t bit = (hash & 1) ? (1 << (sizeof(uint32_t) - 1)) : 0;
/* Keep the hash within the table limits */
return hash % size;
hash >>= 1;
hash += tolower(*key) + bit;
}
/* Keep the hash within the table limits */
return hash % size;
}
/*
@ -97,26 +97,26 @@ hashfunc(const char *key, unsigned int size)
hashmap_t
hashmap_create(unsigned int nbuckets)
{
struct hashmap_s* ptr;
struct hashmap_s *ptr;
if (nbuckets == 0)
return NULL;
if (nbuckets == 0)
return NULL;
ptr = safecalloc(1, sizeof(struct hashmap_s));
if (!ptr)
return NULL;
ptr = safecalloc(1, sizeof(struct hashmap_s));
if (!ptr)
return NULL;
ptr->size = nbuckets;
ptr->buckets = safecalloc(nbuckets, sizeof(struct hashbucket_s));
if (!ptr->buckets) {
safefree(ptr);
return NULL;
}
ptr->size = nbuckets;
ptr->buckets = safecalloc(nbuckets, sizeof(struct hashbucket_s));
if (!ptr->buckets) {
safefree(ptr);
return NULL;
}
/* This points to "one" past the end of the hashmap. */
ptr->end_iterator = 0;
/* This points to "one" past the end of the hashmap. */
ptr->end_iterator = 0;
return ptr;
return ptr;
}
/*
@ -127,26 +127,26 @@ hashmap_create(unsigned int nbuckets)
* negative number is returned if "entry" was NULL
*/
static inline int
delete_hashbucket(struct hashbucket_s* bucket)
delete_hashbucket(struct hashbucket_s *bucket)
{
struct hashentry_s *nextptr;
struct hashentry_s *ptr;
struct hashentry_s *nextptr;
struct hashentry_s *ptr;
if (bucket == NULL || bucket->head == NULL)
return -EINVAL;
if (bucket == NULL || bucket->head == NULL)
return -EINVAL;
ptr = bucket->head;
while (ptr) {
nextptr = ptr->next;
safefree(ptr->key);
safefree(ptr->data);
safefree(ptr);
ptr = bucket->head;
while (ptr) {
nextptr = ptr->next;
ptr = nextptr;
}
safefree(ptr->key);
safefree(ptr->data);
safefree(ptr);
return 0;
ptr = nextptr;
}
return 0;
}
/*
@ -158,21 +158,21 @@ delete_hashbucket(struct hashbucket_s* bucket)
int
hashmap_delete(hashmap_t map)
{
unsigned int i;
if (map == NULL)
return -EINVAL;
unsigned int i;
for (i = 0; i != map->size; i++) {
if (map->buckets[i].head != NULL) {
delete_hashbucket(&map->buckets[i]);
}
}
if (map == NULL)
return -EINVAL;
safefree(map->buckets);
safefree(map);
for (i = 0; i != map->size; i++) {
if (map->buckets[i].head != NULL) {
delete_hashbucket(&map->buckets[i]);
}
}
return 0;
safefree(map->buckets);
safefree(map);
return 0;
}
/*
@ -186,57 +186,56 @@ hashmap_delete(hashmap_t map)
* negative number if there are errors
*/
int
hashmap_insert(hashmap_t map, const char *key,
const void *data, size_t len)
hashmap_insert(hashmap_t map, const char *key, const void *data, size_t len)
{
struct hashentry_s *ptr;
int hash;
char *key_copy;
void *data_copy;
struct hashentry_s *ptr;
int hash;
char *key_copy;
void *data_copy;
assert(map != NULL);
assert(key != NULL);
assert(data != NULL);
assert(len > 0);
assert(map != NULL);
assert(key != NULL);
assert(data != NULL);
assert(len > 0);
if (map == NULL || key == NULL)
return -EINVAL;
if (!data || len < 1)
return -ERANGE;
if (map == NULL || key == NULL)
return -EINVAL;
if (!data || len < 1)
return -ERANGE;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
/*
* First make copies of the key and data in case there is a memory
* problem later.
*/
key_copy = safestrdup(key);
if (!key_copy)
return -ENOMEM;
/*
* First make copies of the key and data in case there is a memory
* problem later.
*/
key_copy = safestrdup(key);
if (!key_copy)
return -ENOMEM;
if (data) {
data_copy = safemalloc(len);
if (!data_copy) {
safefree(key_copy);
return -ENOMEM;
}
memcpy(data_copy, data, len);
} else {
data_copy = NULL;
}
if (data) {
data_copy = safemalloc(len);
if (!data_copy) {
safefree(key_copy);
return -ENOMEM;
}
memcpy(data_copy, data, len);
} else {
data_copy = NULL;
}
ptr = safemalloc(sizeof(struct hashentry_s));
if (!ptr) {
safefree(key_copy);
safefree(data_copy);
return -ENOMEM;
}
ptr = safemalloc(sizeof(struct hashentry_s));
if (!ptr) {
safefree(key_copy);
safefree(data_copy);
return -ENOMEM;
}
ptr->key = key_copy;
ptr->data = data_copy;
ptr->len = len;
ptr->key = key_copy;
ptr->data = data_copy;
ptr->len = len;
/*
* Now add the entry to the end of the bucket chain.
@ -245,13 +244,13 @@ hashmap_insert(hashmap_t map, const char *key,
ptr->prev = map->buckets[hash].tail;
if (map->buckets[hash].tail)
map->buckets[hash].tail->next = ptr;
map->buckets[hash].tail = ptr;
if (!map->buckets[hash].head)
map->buckets[hash].head = ptr;
map->end_iterator++;
return 0;
map->end_iterator++;
return 0;
}
/*
@ -262,15 +261,15 @@ hashmap_insert(hashmap_t map, const char *key,
hashmap_iter
hashmap_first(hashmap_t map)
{
assert(map != NULL);
assert(map != NULL);
if (!map)
return -EINVAL;
if (!map)
return -EINVAL;
if (map->end_iterator == 0)
return -1;
else
return 0;
if (map->end_iterator == 0)
return -1;
else
return 0;
}
/*
@ -282,16 +281,16 @@ hashmap_first(hashmap_t map)
int
hashmap_is_end(hashmap_t map, hashmap_iter iter)
{
assert(map != NULL);
assert(iter >= 0);
assert(map != NULL);
assert(iter >= 0);
if (!map || iter < 0)
return -EINVAL;
if (!map || iter < 0)
return -EINVAL;
if (iter == map->end_iterator)
return 1;
else
return 0;
if (iter == map->end_iterator)
return 1;
else
return 0;
}
/*
@ -303,37 +302,37 @@ hashmap_is_end(hashmap_t map, hashmap_iter iter)
* an "end-iterator" if the key wasn't found
*/
hashmap_iter
hashmap_find(hashmap_t map, const char* key)
hashmap_find(hashmap_t map, const char *key)
{
unsigned int i;
hashmap_iter iter = 0;
struct hashentry_s* ptr;
unsigned int i;
hashmap_iter iter = 0;
struct hashentry_s *ptr;
assert(map != NULL);
assert(key != NULL);
assert(map != NULL);
assert(key != NULL);
if (!map || !key)
return -EINVAL;
if (!map || !key)
return -EINVAL;
/*
* Loop through all the keys and look for the first occurrence
* of a particular key.
*/
for (i = 0; i != map->size; i++) {
ptr = map->buckets[i].head;
/*
* Loop through all the keys and look for the first occurrence
* of a particular key.
*/
for (i = 0; i != map->size; i++) {
ptr = map->buckets[i].head;
while (ptr) {
if (strcasecmp(ptr->key, key) == 0) {
/* Found it, so return the current count */
return iter;
}
while (ptr) {
if (strcasecmp(ptr->key, key) == 0) {
/* Found it, so return the current count */
return iter;
}
iter++;
ptr = ptr->next;
}
}
iter++;
ptr = ptr->next;
}
}
return iter;
return iter;
}
/*
@ -343,38 +342,37 @@ hashmap_find(hashmap_t map, const char* key)
* negative upon error
*/
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;
struct hashentry_s* ptr;
hashmap_iter count = 0;
unsigned int i;
struct hashentry_s *ptr;
hashmap_iter count = 0;
assert(map != NULL);
assert(iter >= 0);
assert(iter != map->end_iterator);
assert(key != NULL);
assert(data != NULL);
assert(map != NULL);
assert(iter >= 0);
assert(iter != map->end_iterator);
assert(key != NULL);
assert(data != NULL);
if (!map || iter < 0 || !key || !data)
return -EINVAL;
if (!map || iter < 0 || !key || !data)
return -EINVAL;
for (i = 0; i != map->size; i++) {
ptr = map->buckets[i].head;
while (ptr) {
if (count == iter) {
/* This is the data so return it */
*key = ptr->key;
*data = ptr->data;
return ptr->len;
}
for (i = 0; i != map->size; i++) {
ptr = map->buckets[i].head;
while (ptr) {
if (count == iter) {
/* This is the data so return it */
*key = ptr->key;
*data = ptr->data;
return ptr->len;
}
ptr = ptr->next;
count++;
}
}
ptr = ptr->next;
count++;
}
}
return -EFAULT;
return -EFAULT;
}
/*
@ -387,29 +385,29 @@ hashmap_return_entry(hashmap_t map, hashmap_iter iter,
ssize_t
hashmap_search(hashmap_t map, const char *key)
{
int hash;
struct hashentry_s* ptr;
ssize_t count = 0;
int hash;
struct hashentry_s *ptr;
ssize_t count = 0;
if (map == NULL || key == NULL)
return -EINVAL;
if (map == NULL || key == NULL)
return -EINVAL;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
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 */
while (ptr) {
if (strcasecmp(ptr->key, key) == 0)
++count;
/* All right, there is an entry here, now see if it's the one we want */
while (ptr) {
if (strcasecmp(ptr->key, key) == 0)
++count;
/* This entry didn't contain the key; move to the next one */
ptr = ptr->next;
}
/* This entry didn't contain the key; move to the next one */
ptr = ptr->next;
}
return count;
return count;
}
/*
@ -421,30 +419,30 @@ hashmap_search(hashmap_t map, const char *key)
* length of data for the entry
*/
ssize_t
hashmap_entry_by_key(hashmap_t map, const char* key, void** data)
hashmap_entry_by_key(hashmap_t map, const char *key, void **data)
{
int hash;
struct hashentry_s* ptr;
int hash;
struct hashentry_s *ptr;
if (!map || !key || !data)
return -EINVAL;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
if (!map || !key || !data)
return -EINVAL;
ptr = map->buckets[hash].head;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
while (ptr) {
if (strcasecmp(ptr->key, key) == 0) {
*data = ptr->data;
return ptr->len;
}
ptr = map->buckets[hash].head;
ptr = ptr->next;
}
while (ptr) {
if (strcasecmp(ptr->key, key) == 0) {
*data = ptr->data;
return ptr->len;
}
return 0;
ptr = ptr->next;
}
return 0;
}
/*
@ -458,26 +456,26 @@ hashmap_entry_by_key(hashmap_t map, const char* key, void** data)
ssize_t
hashmap_remove(hashmap_t map, const char *key)
{
int hash;
struct hashentry_s *ptr, *next;
short int deleted = 0;
int hash;
struct hashentry_s *ptr, *next;
short int deleted = 0;
if (map == NULL || key == NULL)
return -EINVAL;
if (map == NULL || key == NULL)
return -EINVAL;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
hash = hashfunc(key, map->size);
if (hash < 0)
return hash;
ptr = map->buckets[hash].head;
while (ptr) {
if (strcasecmp(ptr->key, key) == 0) {
/*
* Found the data, now need to remove everything
* and update the hashmap.
*/
ptr = map->buckets[hash].head;
while (ptr) {
if (strcasecmp(ptr->key, key) == 0) {
/*
* Found the data, now need to remove everything
* and update the hashmap.
*/
next = ptr->next;
if (ptr->prev)
ptr->prev->next = ptr->next;
if (ptr->next)
@ -487,22 +485,22 @@ hashmap_remove(hashmap_t map, const char *key)
map->buckets[hash].head = ptr->next;
if (map->buckets[hash].tail == ptr)
map->buckets[hash].tail = ptr->prev;
safefree(ptr->key);
safefree(ptr->data);
safefree(ptr);
++deleted;
--map->end_iterator;
safefree(ptr->key);
safefree(ptr->data);
safefree(ptr);
++deleted;
--map->end_iterator;
ptr = next;
continue;
}
continue;
}
/* This entry didn't contain the key; move to the next one */
ptr = ptr->next;
}
/* This entry didn't contain the key; move to the next one */
ptr = ptr->next;
}
/* The key was not found, so return 0 */
return deleted;
/* The key was not found, so return 0 */
return deleted;
}

View File

@ -1,4 +1,4 @@
/* $Id: hashmap.h,v 1.3 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: hashmap.h,v 1.4 2005-08-15 03:54:31 rjkaes Exp $
*
* A hashmap implementation. The keys are case-insensitive NULL terminated
* strings, and the data is arbitrary lumps of data. Copies of both the
@ -38,15 +38,15 @@ extern "C" {
* hash map. Sure, it's a pointer, but the struct is hidden in the C file.
* So, just use the hashmap_t like it's a cookie. :)
*/
typedef struct hashmap_s* hashmap_t;
typedef int hashmap_iter;
typedef struct hashmap_s *hashmap_t;
typedef int hashmap_iter;
/*
* hashmap_create() takes one argument, which is the number of buckets to
* use internally. hashmap_delete() is self explanatory.
*/
extern hashmap_t hashmap_create(unsigned int nbuckets);
extern int hashmap_delete(hashmap_t map);
extern hashmap_t hashmap_create(unsigned int nbuckets);
extern int hashmap_delete(hashmap_t map);
/*
* When the you insert a key/data pair into the hashmap it will the key
@ -57,15 +57,15 @@ extern int hashmap_delete(hashmap_t map);
* Returns: negative on error
* 0 upon successful insert
*/
extern int hashmap_insert(hashmap_t map, const char *key,
const void *data, size_t len);
extern int hashmap_insert(hashmap_t map, const char *key,
const void *data, size_t len);
/*
* Get an iterator to the first entry.
*
* Returns: an negative value upon error.
*/
extern hashmap_iter hashmap_first(hashmap_t map);
extern hashmap_iter hashmap_first(hashmap_t map);
/*
* Checks to see if the iterator is pointing at the "end" of the entries.
@ -73,7 +73,7 @@ extern hashmap_iter hashmap_first(hashmap_t map);
* Returns: 1 if it is the end
* 0 otherwise
*/
extern int hashmap_is_end(hashmap_t map, hashmap_iter iter);
extern int hashmap_is_end(hashmap_t map, hashmap_iter iter);
/*
* Return a "pointer" to the first instance of the particular key. It can
@ -83,7 +83,7 @@ extern int hashmap_is_end(hashmap_t map, hashmap_iter iter);
* an "iterator" pointing at the first key
* an "end-iterator" if the key wasn't found
*/
extern hashmap_iter hashmap_find(hashmap_t map, const char* key);
extern hashmap_iter hashmap_find(hashmap_t map, const char *key);
/*
* Retrieve the key/data associated with a particular iterator.
@ -93,8 +93,8 @@ extern hashmap_iter hashmap_find(hashmap_t map, const char* key);
* Returns: the length of the data block upon success
* negative upon error
*/
extern ssize_t hashmap_return_entry(hashmap_t map, hashmap_iter iter,
char** key, void** data);
extern ssize_t hashmap_return_entry(hashmap_t map, hashmap_iter iter,
char **key, void **data);
/*
* Get the first entry (assuming there is more than one) for a particular
@ -104,7 +104,8 @@ extern ssize_t hashmap_return_entry(hashmap_t map, hashmap_iter iter,
* zero if no entry is found
* length of data for the entry
*/
extern ssize_t hashmap_entry_by_key(hashmap_t map, const char* key, void** data);
extern ssize_t hashmap_entry_by_key(hashmap_t map, const char *key,
void **data);
/*
* Searches for _any_ occurrances of "key" within the hashmap and returns the
@ -114,7 +115,7 @@ extern ssize_t hashmap_entry_by_key(hashmap_t map, const char* key, void** data)
* zero if no key is found
* count found (positive value)
*/
extern ssize_t hashmap_search(hashmap_t map, const char *key);
extern ssize_t hashmap_search(hashmap_t map, const char *key);
/*
* Go through the hashmap and remove the particular key.
@ -124,10 +125,9 @@ extern ssize_t hashmap_search(hashmap_t map, const char *key);
* 0 if the key was not found
* positive count of entries deleted
*/
extern ssize_t hashmap_remove(hashmap_t map, const char *key);
extern ssize_t hashmap_remove(hashmap_t map, const char *key);
#if defined(__cplusplus)
}
#endif /* C++ */
#endif /* _HASHMAP_H */
#endif /* C++ */
#endif /* _HASHMAP_H */

View File

@ -1,4 +1,4 @@
/* $Id: heap.c,v 1.9 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: heap.c,v 1.10 2005-08-15 03:54:31 rjkaes Exp $
*
* Debugging versions of various heap related functions are combined
* here. The debugging versions include assertions and also print
@ -25,70 +25,70 @@
void *
debugging_calloc(size_t nmemb, size_t size, const char *file,
unsigned long line)
unsigned long line)
{
void *ptr;
void *ptr;
assert(nmemb > 0);
assert(size > 0);
assert(nmemb > 0);
assert(size > 0);
ptr = calloc(nmemb, size);
fprintf(stderr, "{calloc: %p:%u x %u} %s:%lu\n", ptr, nmemb, size, file,
line);
return ptr;
ptr = calloc(nmemb, size);
fprintf(stderr, "{calloc: %p:%u x %u} %s:%lu\n", ptr, nmemb, size, file,
line);
return ptr;
}
void *
debugging_malloc(size_t size, const char *file, unsigned long line)
{
void *ptr;
void *ptr;
assert(size > 0);
assert(size > 0);
ptr = malloc(size);
fprintf(stderr, "{malloc: %p:%u} %s:%lu\n", ptr, size, file, line);
return ptr;
ptr = malloc(size);
fprintf(stderr, "{malloc: %p:%u} %s:%lu\n", ptr, size, file, line);
return ptr;
}
void *
debugging_realloc(void *ptr, size_t size, const char *file, unsigned long line)
{
void *newptr;
assert(size > 0);
newptr = realloc(ptr, size);
fprintf(stderr, "{realloc: %p -> %p:%u} %s:%lu\n", ptr, newptr, size,
file, line);
return newptr;
void *newptr;
assert(size > 0);
newptr = realloc(ptr, size);
fprintf(stderr, "{realloc: %p -> %p:%u} %s:%lu\n", ptr, newptr, size,
file, line);
return newptr;
}
void
debugging_free(void *ptr, const char *file, unsigned long line)
{
fprintf(stderr, "{free: %p} %s:%lu\n", ptr, file, line);
fprintf(stderr, "{free: %p} %s:%lu\n", ptr, file, line);
if (ptr != NULL)
free(ptr);
return;
if (ptr != NULL)
free(ptr);
return;
}
char*
debugging_strdup(const char* s, const char* file, unsigned long line)
char *
debugging_strdup(const char *s, const char *file, unsigned long line)
{
char* ptr;
size_t len;
char *ptr;
size_t len;
assert(s != NULL);
assert(s != NULL);
len = strlen(s) + 1;
ptr = malloc(len);
if (!ptr)
return NULL;
memcpy(ptr, s, len);
len = strlen(s) + 1;
ptr = malloc(len);
if (!ptr)
return NULL;
memcpy(ptr, s, len);
fprintf(stderr, "{strdup: %p:%u} %s:%lu\n", ptr, len, file, line);
return ptr;
fprintf(stderr, "{strdup: %p:%u} %s:%lu\n", ptr, len, file, line);
return ptr;
}
/*
@ -99,51 +99,50 @@ debugging_strdup(const char* s, const char* file, unsigned long line)
* want to look into something like MM (Shared Memory Library) for a better
* solution.
*/
void*
void *
malloc_shared_memory(size_t size)
{
int fd;
void* ptr;
char buffer[32];
int fd;
void *ptr;
char buffer[32];
static char* shared_file = "/tmp/tinyproxy.shared.XXXXXX";
static char *shared_file = "/tmp/tinyproxy.shared.XXXXXX";
assert(size > 0);
assert(size > 0);
strlcpy(buffer, shared_file, sizeof(buffer));
strlcpy(buffer, shared_file, sizeof(buffer));
if ((fd = mkstemp(buffer)) == -1)
return MAP_FAILED;
unlink(buffer);
if ((fd = mkstemp(buffer)) == -1)
return MAP_FAILED;
unlink(buffer);
if (ftruncate(fd, size) == -1)
return MAP_FAILED;
ptr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (ftruncate(fd, size) == -1)
return MAP_FAILED;
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
return ptr;
return ptr;
}
/*
* Allocate a block of memory from the "shared" region an initialize it to
* zero.
*/
void*
void *
calloc_shared_memory(size_t nmemb, size_t size)
{
void* ptr;
long length;
void *ptr;
long length;
assert(nmemb > 0);
assert(size > 0);
assert(nmemb > 0);
assert(size > 0);
length = nmemb * size;
length = nmemb * size;
ptr = malloc_shared_memory(length);
if (ptr == MAP_FAILED)
return ptr;
ptr = malloc_shared_memory(length);
if (ptr == MAP_FAILED)
return ptr;
memset(ptr, 0, length);
memset(ptr, 0, length);
return ptr;
return ptr;
}

View File

@ -1,4 +1,4 @@
/* $Id: heap.h,v 1.5 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: heap.h,v 1.6 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'heap.c' for a detailed description.
*
@ -24,14 +24,14 @@
#ifndef NDEBUG
extern void *debugging_calloc(size_t nmemb, size_t size, const char *file,
unsigned long line);
unsigned long line);
extern void *debugging_malloc(size_t size, const char *file,
unsigned long line);
unsigned long line);
extern void debugging_free(void *ptr, const char *file, unsigned long line);
extern void *debugging_realloc(void *ptr, size_t size, const char *file,
unsigned long line);
extern char *debugging_strdup(const char* s, const char* file,
unsigned long line);
unsigned long line);
extern char *debugging_strdup(const char *s, const char *file,
unsigned long line);
# define safecalloc(x, y) debugging_calloc(x, y, __FILE__, __LINE__)
# define safemalloc(x) debugging_malloc(x, __FILE__, __LINE__)
@ -57,7 +57,7 @@ free(*__safefree_tmp); \
/*
* Allocate memory from the "shared" region of memory.
*/
extern void* malloc_shared_memory(size_t size);
extern void* calloc_shared_memory(size_t nmemb, size_t size);
extern void *malloc_shared_memory(size_t size);
extern void *calloc_shared_memory(size_t nmemb, size_t size);
#endif

View File

@ -1,4 +1,4 @@
/* $Id: htmlerror.c,v 1.7 2003-08-01 00:14:34 rjkaes Exp $
/* $Id: htmlerror.c,v 1.8 2005-08-15 03:54:31 rjkaes Exp $
*
* This file contains source code for the handling and display of
* HTML error pages with variable substitution.
@ -29,73 +29,77 @@
/*
* Add an error number -> filename mapping to the errorpages list.
*/
#define ERRORNUM_BUFSIZE 8 /* this is more than required */
#define ERRORNUM_BUFSIZE 8 /* this is more than required */
#define ERRPAGES_BUCKETCOUNT 16
int
add_new_errorpage(char *filepath, unsigned int errornum) {
char errornbuf[ERRORNUM_BUFSIZE];
add_new_errorpage(char *filepath, unsigned int errornum)
{
char errornbuf[ERRORNUM_BUFSIZE];
config.errorpages = hashmap_create(ERRPAGES_BUCKETCOUNT);
if (!config.errorpages)
return(-1);
config.errorpages = hashmap_create(ERRPAGES_BUCKETCOUNT);
if (!config.errorpages)
return (-1);
snprintf(errornbuf, ERRORNUM_BUFSIZE, "%u", errornum);
snprintf(errornbuf, ERRORNUM_BUFSIZE, "%u", errornum);
if (hashmap_insert(config.errorpages, errornbuf,
filepath, strlen(filepath) + 1) < 0)
return(-1);
if (hashmap_insert(config.errorpages, errornbuf,
filepath, strlen(filepath) + 1) < 0)
return (-1);
return(0);
return (0);
}
/*
* Get the file appropriate for a given error.
*/
static char*
get_html_file(unsigned int errornum) {
hashmap_iter result_iter;
char errornbuf[ERRORNUM_BUFSIZE];
char *key;
static char *val;
static char *
get_html_file(unsigned int errornum)
{
hashmap_iter result_iter;
char errornbuf[ERRORNUM_BUFSIZE];
char *key;
static char *val;
assert(errornum >= 100 && errornum < 1000);
assert(errornum >= 100 && errornum < 1000);
if (!config.errorpages) return(config.errorpage_undef);
if (!config.errorpages)
return (config.errorpage_undef);
snprintf(errornbuf, ERRORNUM_BUFSIZE, "%u", errornum);
snprintf(errornbuf, ERRORNUM_BUFSIZE, "%u", errornum);
result_iter = hashmap_find(config.errorpages, errornbuf);
result_iter = hashmap_find(config.errorpages, errornbuf);
if (hashmap_is_end(config.errorpages, result_iter))
return(config.errorpage_undef);
if (hashmap_is_end(config.errorpages, result_iter))
return (config.errorpage_undef);
if (hashmap_return_entry(config.errorpages, result_iter,
&key, (void **)&val) < 0)
return(config.errorpage_undef);
if (hashmap_return_entry(config.errorpages, result_iter,
&key, (void **)&val) < 0)
return (config.errorpage_undef);
return(val);
return (val);
}
/*
* Look up the value for a variable.
*/
static char*
lookup_variable(struct conn_s *connptr, char *varname) {
hashmap_iter result_iter;
char *key;
static char *data;
static char *
lookup_variable(struct conn_s *connptr, char *varname)
{
hashmap_iter result_iter;
char *key;
static char *data;
result_iter = hashmap_find(connptr->error_variables, varname);
result_iter = hashmap_find(connptr->error_variables, varname);
if (hashmap_is_end(connptr->error_variables, result_iter))
return(NULL);
if (hashmap_is_end(connptr->error_variables, result_iter))
return (NULL);
if (hashmap_return_entry(connptr->error_variables, result_iter,
&key, (void **)&data) < 0)
return(NULL);
if (hashmap_return_entry(connptr->error_variables, result_iter,
&key, (void **)&data) < 0)
return (NULL);
return(data);
return (data);
}
#define HTML_BUFSIZE 4096
@ -104,66 +108,75 @@ lookup_variable(struct conn_s *connptr, char *varname) {
* Send an already-opened file to the client with variable substitution.
*/
int
send_html_file(FILE *infile, struct conn_s *connptr) {
char inbuf[HTML_BUFSIZE], *varstart = NULL, *p;
char *varval;
int in_variable = 0, writeret;
send_html_file(FILE * infile, struct conn_s *connptr)
{
char inbuf[HTML_BUFSIZE], *varstart = NULL, *p;
char *varval;
int in_variable = 0, writeret;
while(fgets(inbuf, HTML_BUFSIZE, infile) != NULL) {
for (p = inbuf; *p; p++) {
switch(*p) {
case '}':
if(in_variable) {
*p = '\0';
if(!(varval = lookup_variable(connptr, varstart)))
varval = "(unknown)";
writeret = write_message(connptr->client_fd, "%s",
varval);
if(writeret) return(writeret);
in_variable = 0;
} else {
writeret = write_message(connptr->client_fd, "%c", *p);
if (writeret) return(writeret);
}
break;
case '{':
/* a {{ will print a single {. If we are NOT
* already in a { variable, then proceed with
* setup. If we ARE already in a { variable,
* this code will fallthrough to the code that
* just dumps a character to the client fd.
*/
if(!in_variable) {
varstart = p+1;
in_variable++;
} else
in_variable = 0;
default:
if(!in_variable) {
writeret = write_message(connptr->client_fd, "%c",
*p);
if(writeret) return(writeret);
}
}
}
in_variable = 0;
}
return(0);
while (fgets(inbuf, HTML_BUFSIZE, infile) != NULL) {
for (p = inbuf; *p; p++) {
switch (*p) {
case '}':
if (in_variable) {
*p = '\0';
if (!
(varval =
lookup_variable(connptr,
varstart)))
varval = "(unknown)";
writeret =
write_message(connptr->client_fd,
"%s", varval);
if (writeret)
return (writeret);
in_variable = 0;
} else {
writeret =
write_message(connptr->client_fd,
"%c", *p);
if (writeret)
return (writeret);
}
break;
case '{':
/* a {{ will print a single {. If we are NOT
* already in a { variable, then proceed with
* setup. If we ARE already in a { variable,
* this code will fallthrough to the code that
* just dumps a character to the client fd.
*/
if (!in_variable) {
varstart = p + 1;
in_variable++;
} else
in_variable = 0;
default:
if (!in_variable) {
writeret =
write_message(connptr->client_fd,
"%c", *p);
if (writeret)
return (writeret);
}
}
}
in_variable = 0;
}
return (0);
}
int
send_http_headers(struct conn_s *connptr, int code, char *message) {
char *headers = \
"HTTP/1.0 %d %s\r\n" \
"Server: %s/%s\r\n" \
"Content-Type: text/html\r\n" \
"Connection: close\r\n" \
"\r\n";
send_http_headers(struct conn_s *connptr, int code, char *message)
{
char *headers =
"HTTP/1.0 %d %s\r\n"
"Server: %s/%s\r\n"
"Content-Type: text/html\r\n" "Connection: close\r\n" "\r\n";
return(write_message(connptr->client_fd, headers,
code, message,
PACKAGE, VERSION));
return (write_message(connptr->client_fd, headers,
code, message, PACKAGE, VERSION));
}
/*
@ -172,33 +185,32 @@ send_http_headers(struct conn_s *connptr, int code, char *message) {
int
send_http_error_message(struct conn_s *connptr)
{
char *error_file;
FILE *infile;
int ret;
char *fallback_error = \
"<html><head><title>%s</title></head>" \
"<body><blockquote><i>%s %s</i><br>" \
"The page you requested was unavailable. The error code is listed " \
"below. In addition, the HTML file which has been configured as the " \
"page to be displayed when an error of this type was unavailable, " \
"with the error code %d (%s). Please contact your administrator." \
"<center>%s</center>" \
"</body></html>" \
"\r\n";
char *error_file;
FILE *infile;
int ret;
char *fallback_error =
"<html><head><title>%s</title></head>"
"<body><blockquote><i>%s %s</i><br>"
"The page you requested was unavailable. The error code is listed "
"below. In addition, the HTML file which has been configured as the "
"page to be displayed when an error of this type was unavailable, "
"with the error code %d (%s). Please contact your administrator."
"<center>%s</center>" "</body></html>" "\r\n";
send_http_headers(connptr, connptr->error_number, connptr->error_string);
send_http_headers(connptr, connptr->error_number,
connptr->error_string);
error_file = get_html_file(connptr->error_number);
if(!(infile = fopen(error_file, "r")))
return(write_message(connptr->client_fd, fallback_error,
connptr->error_string,
PACKAGE, VERSION,
errno, strerror(errno),
connptr->error_string));
error_file = get_html_file(connptr->error_number);
if (!(infile = fopen(error_file, "r")))
return (write_message(connptr->client_fd, fallback_error,
connptr->error_string,
PACKAGE, VERSION,
errno, strerror(errno),
connptr->error_string));
ret = send_html_file(infile, connptr);
fclose(infile);
return(ret);
ret = send_html_file(infile, connptr);
fclose(infile);
return (ret);
}
/*
@ -207,18 +219,20 @@ send_http_error_message(struct conn_s *connptr)
#define ERRVAR_BUCKETCOUNT 16
int
add_error_variable(struct conn_s *connptr, char *key, char *val)
int
add_error_variable(struct conn_s *connptr, char *key, char *val)
{
if(!connptr->error_variables)
if (!(connptr->error_variables = hashmap_create(ERRVAR_BUCKETCOUNT)))
return(-1);
if (!connptr->error_variables)
if (!
(connptr->error_variables =
hashmap_create(ERRVAR_BUCKETCOUNT)))
return (-1);
if (hashmap_insert(connptr->error_variables, key, val,
strlen(val) + 1) < 0)
return(-1);
if (hashmap_insert(connptr->error_variables, key, val,
strlen(val) + 1) < 0)
return (-1);
return(0);
return (0);
}
#define ADD_VAR_RET(x, y) if(y) { if(add_error_variable(connptr, x, y) == -1) return(-1); }
@ -227,46 +241,48 @@ add_error_variable(struct conn_s *connptr, char *key, char *val)
* Set some standard variables used by all HTML pages
*/
int
add_standard_vars(struct conn_s *connptr) {
char timebuf[30];
time_t global_time = time(NULL);
add_standard_vars(struct conn_s *connptr)
{
char timebuf[30];
time_t global_time = time(NULL);
strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT",
gmtime(&global_time));
strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT",
gmtime(&global_time));
ADD_VAR_RET("request", connptr->request_line);
ADD_VAR_RET("cause", connptr->error_string);
ADD_VAR_RET("clientip", connptr->client_ip_addr);
ADD_VAR_RET("clienthost", connptr->client_string_addr);
ADD_VAR_RET("version", VERSION);
ADD_VAR_RET("package", PACKAGE);
ADD_VAR_RET("date", timebuf);
return(0);
ADD_VAR_RET("request", connptr->request_line);
ADD_VAR_RET("cause", connptr->error_string);
ADD_VAR_RET("clientip", connptr->client_ip_addr);
ADD_VAR_RET("clienthost", connptr->client_string_addr);
ADD_VAR_RET("version", VERSION);
ADD_VAR_RET("package", PACKAGE);
ADD_VAR_RET("date", timebuf);
return (0);
}
/*
* Add the error information to the conn structure.
*/
int
indicate_http_error(struct conn_s* connptr, int number, char *message, ...)
indicate_http_error(struct conn_s *connptr, int number, char *message, ...)
{
va_list ap;
char *key, *val;
va_list ap;
char *key, *val;
va_start(ap, message);
va_start(ap, message);
while((key = va_arg(ap, char *))) {
val = va_arg(ap, char *);
if(add_error_variable(connptr, key, val) == -1) {
va_end(ap);
return(-1);
}
}
while ((key = va_arg(ap, char *))) {
val = va_arg(ap, char *);
connptr->error_number = number;
connptr->error_string = safestrdup(message);
if (add_error_variable(connptr, key, val) == -1) {
va_end(ap);
return (-1);
}
}
va_end(ap);
connptr->error_number = number;
connptr->error_string = safestrdup(message);
return(add_standard_vars(connptr));
va_end(ap);
return (add_standard_vars(connptr));
}

View File

@ -1,4 +1,4 @@
/* $Id: htmlerror.h,v 1.2 2003-03-14 22:45:59 rjkaes Exp $
/* $Id: htmlerror.h,v 1.3 2005-08-15 03:54:31 rjkaes Exp $
*
* Contains header declarations for the HTML error functions in
* htmlerror.c
@ -24,10 +24,11 @@ struct conn_s;
extern int add_new_errorpage(char *filepath, unsigned int errornum);
extern int send_http_error_message(struct conn_s *connptr);
extern int indicate_http_error(struct conn_s *connptr, int number, char *message, ...);
extern int indicate_http_error(struct conn_s *connptr, int number,
char *message, ...);
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 add_standard_vars(struct conn_s *connptr);
#endif /* !TINYPROXY_HTMLERROR_H */
#endif /* !TINYPROXY_HTMLERROR_H */

View File

@ -1,4 +1,4 @@
/* $Id: http_message.c,v 1.5 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: http_message.c,v 1.6 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'http_message.h' for a detailed description.
*
@ -28,28 +28,28 @@
* still in use---bad things would happen.
*/
struct http_message_s {
/* Response string and code supplied on the HTTP status line */
struct {
const char* string;
int code;
} response;
/*
* A group of headers to be sent with this message. Right now
* the strings are referenced through pointers in an array.
* I might change this to a vector in the future.
*/
struct {
char** strings;
unsigned int total;
unsigned int used;
} headers;
/* Response string and code supplied on the HTTP status line */
struct {
const char *string;
int code;
} response;
/* Body of the message (most likely an HTML message) */
struct {
const char* text;
size_t length;
} body;
/*
* A group of headers to be sent with this message. Right now
* the strings are referenced through pointers in an array.
* I might change this to a vector in the future.
*/
struct {
char **strings;
unsigned int total;
unsigned int used;
} headers;
/* Body of the message (most likely an HTML message) */
struct {
const char *text;
size_t length;
} body;
};
/*
@ -60,12 +60,16 @@ struct http_message_s {
static int
is_http_message_valid(http_message_t msg)
{
if (msg == NULL) return 0;
if (msg->headers.strings == NULL) return 0;
if (msg->response.string == NULL) return 0;
if (msg->response.code < 1 || msg->response.code > 999) return 0;
if (msg == NULL)
return 0;
if (msg->headers.strings == NULL)
return 0;
if (msg->response.string == NULL)
return 0;
if (msg->response.code < 1 || msg->response.code > 999)
return 0;
return 1;
return 1;
}
/* Initially allocate space for 128 headers */
@ -76,32 +80,32 @@ is_http_message_valid(http_message_t msg)
* If memory could not be allocated, return a NULL.
*/
http_message_t
http_message_create(int response_code, const char* response_string)
http_message_create(int response_code, const char *response_string)
{
http_message_t msg;
int ret;
http_message_t msg;
int ret;
msg = safecalloc(1, sizeof(struct http_message_s));
if (msg == NULL)
return NULL;
msg = safecalloc(1, sizeof(struct http_message_s));
if (msg == NULL)
return NULL;
msg->headers.strings = safecalloc(NUMBER_OF_HEADERS, sizeof(char*));
if (msg->headers.strings == NULL) {
safefree(msg);
return NULL;
}
msg->headers.strings = safecalloc(NUMBER_OF_HEADERS, sizeof(char *));
if (msg->headers.strings == NULL) {
safefree(msg);
return NULL;
}
msg->headers.total = NUMBER_OF_HEADERS;
msg->headers.total = NUMBER_OF_HEADERS;
/* Store the HTTP response information in the structure */
ret = http_message_set_response(msg, response_code, response_string);
if (IS_HTTP_MSG_ERROR(ret)) {
safefree(msg->headers.strings);
safefree(msg);
return NULL;
}
/* Store the HTTP response information in the structure */
ret = http_message_set_response(msg, response_code, response_string);
if (IS_HTTP_MSG_ERROR(ret)) {
safefree(msg->headers.strings);
safefree(msg);
return NULL;
}
return msg;
return msg;
}
/*
@ -112,16 +116,17 @@ http_message_create(int response_code, const char* response_string)
int
http_message_destroy(http_message_t msg)
{
assert(msg != NULL);
assert(msg->headers.strings != NULL);
assert(msg != NULL);
assert(msg->headers.strings != NULL);
/* Check for valid arguments */
if (msg == NULL) return -EFAULT;
/* Check for valid arguments */
if (msg == NULL)
return -EFAULT;
if (msg->headers.strings != NULL)
safefree(msg->headers.strings);
safefree(msg);
return 0;
if (msg->headers.strings != NULL)
safefree(msg->headers.strings);
safefree(msg);
return 0;
}
/*
@ -130,81 +135,89 @@ http_message_destroy(http_message_t msg)
*/
int
http_message_set_response(http_message_t msg,
int response_code,
const char* response_string)
int response_code, const char *response_string)
{
/* Check for valid arguments */
if (msg == NULL) return -EFAULT;
if (response_code < 1 || response_code > 999) return -EINVAL;
if (response_string == NULL) return -EINVAL;
if (strlen(response_string) == 0) return -EINVAL;
/* Check for valid arguments */
if (msg == NULL)
return -EFAULT;
if (response_code < 1 || response_code > 999)
return -EINVAL;
if (response_string == NULL)
return -EINVAL;
if (strlen(response_string) == 0)
return -EINVAL;
msg->response.code = response_code;
msg->response.string = response_string;
msg->response.code = response_code;
msg->response.string = response_string;
return 0;
return 0;
}
/*
* Set the HTTP message body.
*/
int
http_message_set_body(http_message_t msg, const char* body, size_t len)
http_message_set_body(http_message_t msg, const char *body, size_t len)
{
/* Check for valid arguments */
if (msg == NULL) return -EFAULT;
if (body == NULL) return -EINVAL;
if (len == 0) return -EINVAL;
/* Check for valid arguments */
if (msg == NULL)
return -EFAULT;
if (body == NULL)
return -EINVAL;
if (len == 0)
return -EINVAL;
msg->body.text = body;
msg->body.length = len;
msg->body.text = body;
msg->body.length = len;
return 0;
return 0;
}
/*
* Add headers to the structure.
*/
int
http_message_add_headers(http_message_t msg, char** headers,
int num_headers)
http_message_add_headers(http_message_t msg, char **headers, int num_headers)
{
char** new_headers;
int i;
char **new_headers;
int i;
/* Check for valid arguments */
if (msg == NULL) return -EFAULT;
if (headers == NULL) return -EINVAL;
if (num_headers < 1) return -EINVAL;
/* Check for valid arguments */
if (msg == NULL)
return -EFAULT;
if (headers == NULL)
return -EINVAL;
if (num_headers < 1)
return -EINVAL;
/*
* If the number of headers to add is greater than the space
* available, reallocate the memory.
*/
if (msg->headers.used + num_headers > msg->headers.total) {
new_headers = safecalloc(msg->headers.total * 2,
sizeof(char*));
if (new_headers == NULL)
return -ENOMEM;
/*
* If the number of headers to add is greater than the space
* available, reallocate the memory.
*/
if (msg->headers.used + num_headers > msg->headers.total) {
new_headers = safecalloc(msg->headers.total * 2,
sizeof(char *));
if (new_headers == NULL)
return -ENOMEM;
/* Copy the array */
for (i = 0; i != msg->headers.used; ++i)
new_headers[i] = msg->headers.strings[i];
/* Copy the array */
for (i = 0; i != msg->headers.used; ++i)
new_headers[i] = msg->headers.strings[i];
/* Remove the old array and replace it with the new array */
safefree(msg->headers.strings);
msg->headers.strings = new_headers;
msg->headers.total *= 2;
}
/* Remove the old array and replace it with the new array */
safefree(msg->headers.strings);
msg->headers.strings = new_headers;
msg->headers.total *= 2;
}
/*
* Add the new headers to the structure
*/
for (i = 0; i != num_headers; ++i)
msg->headers.strings[i + msg->headers.used] = headers[i];
msg->headers.used += num_headers;
/*
* Add the new headers to the structure
*/
for (i = 0; i != num_headers; ++i)
msg->headers.strings[i + msg->headers.used] = headers[i];
msg->headers.used += num_headers;
return 0;
return 0;
}
/*
@ -213,40 +226,43 @@ http_message_add_headers(http_message_t msg, char** headers,
int
http_message_send(http_message_t msg, int fd)
{
char timebuf[30];
time_t global_time;
unsigned int i;
char timebuf[30];
time_t global_time;
unsigned int i;
assert(is_http_message_valid(msg));
assert(is_http_message_valid(msg));
/* Check for valid arguments */
if (msg == NULL) return -EFAULT;
if (fd < 1) return -EBADF;
if (!is_http_message_valid(msg)) return -EINVAL;
/* Check for valid arguments */
if (msg == NULL)
return -EFAULT;
if (fd < 1)
return -EBADF;
if (!is_http_message_valid(msg))
return -EINVAL;
/* Write the response line */
write_message(fd, "HTTP/1.0 %d %s\r\n",
msg->response.code, msg->response.string);
/* Write the response line */
write_message(fd, "HTTP/1.0 %d %s\r\n",
msg->response.code, msg->response.string);
/* Go through all the headers */
for (i = 0; i != msg->headers.used; ++i)
write_message(fd, "%s\r\n", msg->headers.strings[i]);
/* Go through all the headers */
for (i = 0; i != msg->headers.used; ++i)
write_message(fd, "%s\r\n", msg->headers.strings[i]);
/* Output the date */
global_time = time(NULL);
strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT",
gmtime(&global_time));
write_message(fd, "Date: %s\r\n", timebuf);
/* Output the date */
global_time = time(NULL);
strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT",
gmtime(&global_time));
write_message(fd, "Date: %s\r\n", timebuf);
/* Output the content-length */
write_message(fd, "Content-length: %u\r\n", msg->body.length);
/* Output the content-length */
write_message(fd, "Content-length: %u\r\n", msg->body.length);
/* Write the separator between the headers and body */
safe_write(fd, "\r\n", 2);
/* Write the separator between the headers and body */
safe_write(fd, "\r\n", 2);
/* If there's a body, send it! */
if (msg->body.length > 0)
safe_write(fd, msg->body.text, msg->body.length);
/* If there's a body, send it! */
if (msg->body.length > 0)
safe_write(fd, msg->body.text, msg->body.length);
return 0;
return 0;
}

View File

@ -1,4 +1,4 @@
/* $Id: http_message.h,v 1.2 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: http_message.h,v 1.3 2005-08-15 03:54:31 rjkaes Exp $
*
* HTTP Message API
* ----------------
@ -55,7 +55,7 @@ typedef struct http_message_s *http_message_t;
/* Initialize the internal structure of the HTTP message */
extern http_message_t http_message_create(int response_code,
const char* response_string);
const char *response_string);
/* Free up an _internal_ resources */
extern int http_message_destroy(http_message_t msg);
@ -72,10 +72,10 @@ extern int http_message_send(http_message_t msg, int fd);
* add a new set of headers.
*/
extern int http_message_set_body(http_message_t msg,
const char* body, size_t len);
const char *body, size_t len);
extern int http_message_set_response(http_message_t msg,
int response_code,
const char* response_string);
int response_code,
const char *response_string);
/*
* Set the headers for this HTTP message. Each string must be NUL ('\0')
@ -84,7 +84,6 @@ extern int http_message_set_response(http_message_t msg,
* sent.
*/
extern int http_message_add_headers(http_message_t msg,
char** headers,
int num_headers);
char **headers, int num_headers);
#endif /* _TINYPROXY_HTTP_MESSAGE_H_ */
#endif /* _TINYPROXY_HTTP_MESSAGE_H_ */

187
src/log.c
View File

@ -1,4 +1,4 @@
/* $Id: log.c,v 1.30 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: log.c,v 1.31 2005-08-15 03:54:31 rjkaes Exp $
*
* Logs the various messages which tinyproxy produces to either a log file or
* the syslog daemon. Not much to it...
@ -25,15 +25,15 @@
#include "vector.h"
static char *syslog_level[] = {
NULL,
NULL,
"CRITICAL",
"ERROR",
"WARNING",
"NOTICE",
"INFO",
"DEBUG",
"CONNECT"
NULL,
NULL,
"CRITICAL",
"ERROR",
"WARNING",
"NOTICE",
"INFO",
"DEBUG",
"CONNECT"
};
#define TIME_LENGTH 16
@ -61,10 +61,10 @@ static vector_t log_message_storage;
* Open the log file and store the file descriptor in a global location.
*/
int
open_log_file(const char* log_file_name)
open_log_file(const char *log_file_name)
{
log_file_fd = create_file_safely(log_file_name, FALSE);
return log_file_fd;
log_file_fd = create_file_safely(log_file_name, FALSE);
return log_file_fd;
}
/*
@ -73,7 +73,7 @@ open_log_file(const char* log_file_name)
void
close_log_file(void)
{
close(log_file_fd);
close(log_file_fd);
}
/*
@ -82,8 +82,8 @@ close_log_file(void)
void
truncate_log_file(void)
{
lseek(log_file_fd, 0, SEEK_SET);
ftruncate(log_file_fd, 0);
lseek(log_file_fd, 0, SEEK_SET);
ftruncate(log_file_fd, 0);
}
/*
@ -92,7 +92,7 @@ truncate_log_file(void)
void
set_log_level(int level)
{
log_level = level;
log_level = level;
}
/*
@ -101,92 +101,91 @@ set_log_level(int level)
void
log_message(int level, char *fmt, ...)
{
va_list args;
time_t nowtime;
va_list args;
time_t nowtime;
char time_string[TIME_LENGTH];
char str[STRING_LENGTH];
char time_string[TIME_LENGTH];
char str[STRING_LENGTH];
#ifdef NDEBUG
/*
* Figure out if we should write the message or not.
*/
if (log_level == LOG_CONN) {
if (level == LOG_INFO)
return;
} else if (log_level == LOG_INFO) {
if (level > LOG_INFO && level != LOG_CONN)
return;
} else if (level > log_level)
return;
/*
* Figure out if we should write the message or not.
*/
if (log_level == LOG_CONN) {
if (level == LOG_INFO)
return;
} else if (log_level == LOG_INFO) {
if (level > LOG_INFO && level != LOG_CONN)
return;
} else if (level > log_level)
return;
#endif
#ifdef HAVE_SYSLOG_H
if (config.syslog && level == LOG_CONN)
level = LOG_INFO;
if (config.syslog && level == LOG_CONN)
level = LOG_INFO;
#endif
va_start(args, fmt);
va_start(args, fmt);
/*
* If the config file hasn't been processed, then we need to store
* the messages for later processing.
*/
if (!processed_config_file) {
char* entry_buffer;
/*
* If the config file hasn't been processed, then we need to store
* the messages for later processing.
*/
if (!processed_config_file) {
char *entry_buffer;
if (!log_message_storage) {
log_message_storage = vector_create();
if (!log_message_storage)
return;
}
if (!log_message_storage) {
log_message_storage = vector_create();
if (!log_message_storage)
return;
}
vsnprintf(str, STRING_LENGTH, fmt, args);
vsnprintf(str, STRING_LENGTH, fmt, args);
entry_buffer = safemalloc(strlen(str) + 6);
if (!entry_buffer)
return;
sprintf(entry_buffer, "%d %s", level, str);
vector_append(log_message_storage, entry_buffer,
strlen(entry_buffer) + 1);
entry_buffer = safemalloc(strlen(str) + 6);
if (!entry_buffer)
return;
va_end(args);
sprintf(entry_buffer, "%d %s", level, str);
vector_append(log_message_storage, entry_buffer,
strlen(entry_buffer) + 1);
return;
}
va_end(args);
return;
}
#ifdef HAVE_SYSLOG_H
if (config.syslog) {
if (config.syslog) {
# ifdef HAVE_VSYSLOG_H
vsyslog(level, fmt, args);
vsyslog(level, fmt, args);
# else
vsnprintf(str, STRING_LENGTH, fmt, args);
syslog(level, "%s", str);
vsnprintf(str, STRING_LENGTH, fmt, args);
syslog(level, "%s", str);
# endif
} else {
} else {
#endif
nowtime = time(NULL);
/* Format is month day hour:minute:second (24 time) */
strftime(time_string, TIME_LENGTH, "%b %d %H:%M:%S",
localtime(&nowtime));
nowtime = time(NULL);
/* Format is month day hour:minute:second (24 time) */
strftime(time_string, TIME_LENGTH, "%b %d %H:%M:%S",
localtime(&nowtime));
snprintf(str, STRING_LENGTH, "%-9s %s [%ld]: ", syslog_level[level],
time_string, (long int) getpid());
snprintf(str, STRING_LENGTH, "%-9s %s [%ld]: ",
syslog_level[level], time_string, (long int)getpid());
assert(log_file_fd >= 0);
assert(log_file_fd >= 0);
write(log_file_fd, str, strlen(str));
vsnprintf(str, STRING_LENGTH, fmt, args);
write(log_file_fd, str, strlen(str));
write(log_file_fd, "\n", 1);
write(log_file_fd, str, strlen(str));
vsnprintf(str, STRING_LENGTH, fmt, args);
write(log_file_fd, str, strlen(str));
write(log_file_fd, "\n", 1);
fsync(log_file_fd);
#ifdef HAVE_SYSLOG_H
}
}
#endif
va_end(args);
va_end(args);
}
/*
@ -195,32 +194,32 @@ log_message(int level, char *fmt, ...)
void
send_stored_logs(void)
{
char *string;
char *ptr;
char *string;
char *ptr;
int level;
int level;
int i;
int i;
for (i = 0; i != vector_length(log_message_storage); ++i) {
string = vector_getentry(log_message_storage, i, NULL);
for (i = 0; i != vector_length(log_message_storage); ++i) {
string = vector_getentry(log_message_storage, i, NULL);
ptr = strchr(string, ' ') + 1;
level = atoi(string);
ptr = strchr(string, ' ') + 1;
level = atoi(string);
#ifdef NDEBUG
if (log_level == LOG_CONN && level == LOG_INFO)
continue;
else if (log_level == LOG_INFO) {
if (level > LOG_INFO && level != LOG_CONN)
continue;
} else if (level > log_level)
continue;
if (log_level == LOG_CONN && level == LOG_INFO)
continue;
else if (log_level == LOG_INFO) {
if (level > LOG_INFO && level != LOG_CONN)
continue;
} else if (level > log_level)
continue;
#endif
log_message(level, ptr);
}
log_message(level, ptr);
}
vector_delete(log_message_storage);
log_message_storage = NULL;
vector_delete(log_message_storage);
log_message_storage = NULL;
}

View File

@ -1,4 +1,4 @@
/* $Id: log.h,v 1.12 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: log.h,v 1.13 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'log.c' for a detailed description.
*
@ -84,7 +84,7 @@
# define LOG_DEBUG 7
#endif
#define LOG_CONN 8 /* extra to log connections without the INFO stuff */
#define LOG_CONN 8 /* extra to log connections without the INFO stuff */
/*
* Use this for debugging. The format is specific:
@ -99,7 +99,7 @@
# define DEBUG2(x, y...) do { } while(0)
#endif
extern int open_log_file(const char* file);
extern int open_log_file(const char *file);
extern void close_log_file(void);
extern void truncate_log_file(void);

View File

@ -1,4 +1,4 @@
/* $Id: network.c,v 1.4 2004-02-18 20:17:18 rjkaes Exp $
/* $Id: network.c,v 1.5 2005-08-15 03:54:31 rjkaes Exp $
*
* The functions found here are used for communicating across a
* network. They include both safe reading and writing (which are
@ -31,33 +31,33 @@
ssize_t
safe_write(int fd, const char *buffer, size_t count)
{
ssize_t len;
size_t bytestosend;
ssize_t len;
size_t bytestosend;
assert(fd >= 0);
assert(buffer != NULL);
assert(count > 0);
assert(fd >= 0);
assert(buffer != NULL);
assert(count > 0);
bytestosend = count;
bytestosend = count;
while (1) {
len = send(fd, buffer, bytestosend, MSG_NOSIGNAL);
while (1) {
len = send(fd, buffer, bytestosend, MSG_NOSIGNAL);
if (len < 0) {
if (errno == EINTR)
continue;
else
return -errno;
}
if (len < 0) {
if (errno == EINTR)
continue;
else
return -errno;
}
if (len == bytestosend)
break;
if (len == bytestosend)
break;
buffer += len;
bytestosend -= len;
}
buffer += len;
bytestosend -= len;
}
return count;
return count;
}
/*
@ -67,13 +67,13 @@ safe_write(int fd, const char *buffer, size_t count)
ssize_t
safe_read(int fd, char *buffer, size_t count)
{
ssize_t len;
ssize_t len;
do {
len = read(fd, buffer, count);
} while (len < 0 && errno == EINTR);
do {
len = read(fd, buffer, count);
} while (len < 0 && errno == EINTR);
return len;
return len;
}
/*
@ -85,45 +85,45 @@ safe_read(int fd, char *buffer, size_t count)
int
write_message(int fd, const char *fmt, ...)
{
ssize_t n;
size_t size = (1024 * 8); /* start with 8 KB and go from there */
char *buf, *tmpbuf;
va_list ap;
ssize_t n;
size_t size = (1024 * 8); /* start with 8 KB and go from there */
char *buf, *tmpbuf;
va_list ap;
if ((buf = safemalloc(size)) == NULL)
return -1;
if ((buf = safemalloc(size)) == NULL)
return -1;
while (1) {
va_start(ap, fmt);
n = vsnprintf(buf, size, fmt, ap);
va_end(ap);
while (1) {
va_start(ap, fmt);
n = vsnprintf(buf, size, fmt, ap);
va_end(ap);
/* If that worked, break out so we can send the buffer */
if (n > -1 && n < size)
break;
/* If that worked, break out so we can send the buffer */
if (n > -1 && n < size)
break;
/* Else, try again with more space */
if (n > -1)
/* precisely what is needed (glibc2.1) */
size = n + 1;
else
/* twice the old size (glibc2.0) */
size *= 2;
/* Else, try again with more space */
if (n > -1)
/* precisely what is needed (glibc2.1) */
size = n + 1;
else
/* twice the old size (glibc2.0) */
size *= 2;
if ((tmpbuf = saferealloc(buf, size)) == NULL) {
safefree(buf);
return -1;
} else
buf = tmpbuf;
}
if ((tmpbuf = saferealloc(buf, size)) == NULL) {
safefree(buf);
return -1;
} else
buf = tmpbuf;
}
if (safe_write(fd, buf, n) < 0) {
safefree(buf);
return -1;
}
if (safe_write(fd, buf, n) < 0) {
safefree(buf);
return -1;
}
safefree(buf);
return 0;
safefree(buf);
return 0;
}
/*
@ -140,132 +140,134 @@ write_message(int fd, const char *fmt, ...)
ssize_t
readline(int fd, char **whole_buffer)
{
ssize_t whole_buffer_len;
char buffer[SEGMENT_LEN];
char *ptr;
ssize_t whole_buffer_len;
char buffer[SEGMENT_LEN];
char *ptr;
ssize_t ret;
ssize_t diff;
ssize_t ret;
ssize_t diff;
struct read_lines_s {
char *data;
size_t len;
struct read_lines_s *next;
};
struct read_lines_s *first_line, *line_ptr;
struct read_lines_s {
char *data;
size_t len;
struct read_lines_s *next;
};
struct read_lines_s *first_line, *line_ptr;
first_line = safecalloc(sizeof(struct read_lines_s), 1);
if (!first_line)
return -ENOMEM;
first_line = safecalloc(sizeof(struct read_lines_s), 1);
if (!first_line)
return -ENOMEM;
line_ptr = first_line;
line_ptr = first_line;
whole_buffer_len = 0;
for (;;) {
ret = recv(fd, buffer, SEGMENT_LEN, MSG_PEEK);
if (ret <= 0)
goto CLEANUP;
whole_buffer_len = 0;
for (;;) {
ret = recv(fd, buffer, SEGMENT_LEN, MSG_PEEK);
if (ret <= 0)
goto CLEANUP;
ptr = memchr(buffer, '\n', ret);
if (ptr)
diff = ptr - buffer + 1;
else
diff = ret;
ptr = memchr(buffer, '\n', ret);
if (ptr)
diff = ptr - buffer + 1;
else
diff = ret;
whole_buffer_len += diff;
whole_buffer_len += diff;
/*
* Don't allow the buffer to grow without bound. If we
* get to more than MAXIMUM_BUFFER_LENGTH close.
*/
if (whole_buffer_len > MAXIMUM_BUFFER_LENGTH) {
ret = -ERANGE;
goto CLEANUP;
}
/*
* Don't allow the buffer to grow without bound. If we
* get to more than MAXIMUM_BUFFER_LENGTH close.
*/
if (whole_buffer_len > MAXIMUM_BUFFER_LENGTH) {
ret = -ERANGE;
goto CLEANUP;
}
line_ptr->data = safemalloc(diff);
if (!line_ptr->data) {
ret = -ENOMEM;
goto CLEANUP;
}
line_ptr->data = safemalloc(diff);
if (!line_ptr->data) {
ret = -ENOMEM;
goto CLEANUP;
}
recv(fd, line_ptr->data, diff, 0);
line_ptr->len = diff;
recv(fd, line_ptr->data, diff, 0);
line_ptr->len = diff;
if (ptr) {
line_ptr->next = NULL;
break;
}
if (ptr) {
line_ptr->next = NULL;
break;
}
line_ptr->next = safecalloc(sizeof(struct read_lines_s), 1);
if (!line_ptr->next) {
ret = -ENOMEM;
goto CLEANUP;
}
line_ptr = line_ptr->next;
}
line_ptr->next = safecalloc(sizeof(struct read_lines_s), 1);
if (!line_ptr->next) {
ret = -ENOMEM;
goto CLEANUP;
}
line_ptr = line_ptr->next;
}
*whole_buffer = safemalloc(whole_buffer_len + 1);
if (!*whole_buffer) {
ret = -ENOMEM;
goto CLEANUP;
}
*whole_buffer = safemalloc(whole_buffer_len + 1);
if (!*whole_buffer) {
ret = -ENOMEM;
goto CLEANUP;
}
*(*whole_buffer + whole_buffer_len) = '\0';
*(*whole_buffer + whole_buffer_len) = '\0';
whole_buffer_len = 0;
line_ptr = first_line;
while (line_ptr) {
memcpy(*whole_buffer + whole_buffer_len, line_ptr->data,
line_ptr->len);
whole_buffer_len += line_ptr->len;
whole_buffer_len = 0;
line_ptr = first_line;
while (line_ptr) {
memcpy(*whole_buffer + whole_buffer_len, line_ptr->data,
line_ptr->len);
whole_buffer_len += line_ptr->len;
line_ptr = line_ptr->next;
}
line_ptr = line_ptr->next;
}
ret = whole_buffer_len;
ret = whole_buffer_len;
CLEANUP:
do {
line_ptr = first_line->next;
if (first_line->data)
safefree(first_line->data);
safefree(first_line);
first_line = line_ptr;
} while (first_line);
do {
line_ptr = first_line->next;
if (first_line->data)
safefree(first_line->data);
safefree(first_line);
first_line = line_ptr;
} while (first_line);
return ret;
return ret;
}
/*
* Convert the network address into either a dotted-decimal or an IPv6
* hex string.
*/
char*
get_ip_string(struct sockaddr* sa, char* buf, size_t buflen)
char *
get_ip_string(struct sockaddr *sa, char *buf, size_t buflen)
{
assert(sa != NULL);
assert(buf != NULL);
assert(buflen != 0);
buf[0] = '\0'; /* start with an empty string */
assert(sa != NULL);
assert(buf != NULL);
assert(buflen != 0);
buf[0] = '\0'; /* start with an empty string */
switch (sa->sa_family) {
case AF_INET: {
struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
inet_ntop(AF_INET, &sa_in->sin_addr, buf, buflen);
break;
}
case AF_INET6: {
struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa;
inet_ntop(AF_INET6, &sa_in6->sin6_addr, buf, buflen);
break;
}
default:
/* no valid family */
return NULL;
}
switch (sa->sa_family) {
case AF_INET:{
struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
return buf;
inet_ntop(AF_INET, &sa_in->sin_addr, buf, buflen);
break;
}
case AF_INET6:{
struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa;
inet_ntop(AF_INET6, &sa_in6->sin6_addr, buf, buflen);
break;
}
default:
/* no valid family */
return NULL;
}
return buf;
}
/*
@ -276,41 +278,41 @@ get_ip_string(struct sockaddr* sa, char* buf, size_t buflen)
* Returns the same as inet_pton().
*/
int
full_inet_pton(const char* ip, void* dst)
full_inet_pton(const char *ip, void *dst)
{
char buf[24], tmp[24]; /* IPv4->IPv6 = ::FFFF:xxx.xxx.xxx.xxx\0 */
int n;
char buf[24], tmp[24]; /* IPv4->IPv6 = ::FFFF:xxx.xxx.xxx.xxx\0 */
int n;
assert(ip != NULL && strlen(ip) != 0);
assert(dst != NULL);
assert(ip != NULL && strlen(ip) != 0);
assert(dst != NULL);
/*
* Check if the string is an IPv4 numeric address. We use the
* older inet_aton() call since it handles more IPv4 numeric
* address formats.
*/
n = inet_aton(ip, (struct in_addr*)dst);
if (n == 0) {
/*
* Simple case: "ip" wasn't an IPv4 numeric address, so
* try doing the conversion as an IPv6 address. This
* will either succeed or fail, but we can't do any
* more processing anyway.
*/
return inet_pton(AF_INET6, ip, dst);
}
/*
* Check if the string is an IPv4 numeric address. We use the
* older inet_aton() call since it handles more IPv4 numeric
* address formats.
*/
n = inet_aton(ip, (struct in_addr *)dst);
if (n == 0) {
/*
* Simple case: "ip" wasn't an IPv4 numeric address, so
* try doing the conversion as an IPv6 address. This
* will either succeed or fail, but we can't do any
* more processing anyway.
*/
return inet_pton(AF_INET6, ip, dst);
}
/*
* "ip" was an IPv4 address, so we need to convert it to
* an IPv4-mapped IPv6 address and do the conversion
* again to get the IPv6 network structure.
*
* We convert the IPv4 binary address back into the
* standard dotted-decimal format using inet_ntop()
* so we can be sure that inet_pton will accept the
* full string.
*/
snprintf(buf, sizeof(buf), "::ffff:%s",
inet_ntop(AF_INET, dst, tmp, sizeof(tmp)));
return inet_pton(AF_INET6, buf, dst);
/*
* "ip" was an IPv4 address, so we need to convert it to
* an IPv4-mapped IPv6 address and do the conversion
* again to get the IPv6 network structure.
*
* We convert the IPv4 binary address back into the
* standard dotted-decimal format using inet_ntop()
* so we can be sure that inet_pton will accept the
* full string.
*/
snprintf(buf, sizeof(buf), "::ffff:%s",
inet_ntop(AF_INET, dst, tmp, sizeof(tmp)));
return inet_pton(AF_INET6, buf, dst);
}

View File

@ -1,4 +1,4 @@
/* $Id: network.h,v 1.2 2004-02-18 20:17:18 rjkaes Exp $
/* $Id: network.h,v 1.3 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'network.c' for a detailed description.
*
@ -24,7 +24,7 @@ extern ssize_t safe_read(int fd, char *buffer, size_t count);
extern int write_message(int fd, const char *fmt, ...);
extern ssize_t readline(int fd, char **whole_buffer);
extern char* get_ip_string(struct sockaddr* sa, char* buf, size_t len);
extern int full_inet_pton(const char* ip, void* dst);
extern char *get_ip_string(struct sockaddr *sa, char *buf, size_t len);
extern int full_inet_pton(const char *ip, void *dst);
#endif

2385
src/reqs.c

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $Id: sock.c,v 1.42 2005-07-12 20:34:26 rjkaes Exp $
/* $Id: sock.c,v 1.43 2005-08-15 03:54:31 rjkaes Exp $
*
* Sockets are created and destroyed here. When a new connection comes in from
* a client, we need to copy the socket and the create a second socket to the
@ -35,34 +35,34 @@
* to indicate an error.
*/
static int
bind_socket(int sockfd, const char* addr)
bind_socket(int sockfd, const char *addr)
{
struct addrinfo hints, *res, *ressave;
struct addrinfo hints, *res, *ressave;
assert(sockfd >= 0);
assert(addr != NULL && strlen(addr) != 0);
assert(sockfd >= 0);
assert(addr != NULL && strlen(addr) != 0);
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
/* The local port it not important */
if (getaddrinfo(addr, NULL, &hints, &res) != 0)
return -1;
/* The local port it not important */
if (getaddrinfo(addr, NULL, &hints, &res) != 0)
return -1;
ressave = res;
ressave = res;
/* Loop through the addresses and try to bind to each */
do {
if (bind(sockfd, res->ai_addr, res->ai_addrlen) == 0)
break; /* success */
} while ((res = res->ai_next) != NULL);
/* Loop through the addresses and try to bind to each */
do {
if (bind(sockfd, res->ai_addr, res->ai_addrlen) == 0)
break; /* success */
} while ((res = res->ai_next) != NULL);
freeaddrinfo(ressave);
if (res == NULL) /* was not able to bind to any address */
return -1;
freeaddrinfo(ressave);
if (res == NULL) /* was not able to bind to any address */
return -1;
return sockfd;
return sockfd;
}
/*
@ -71,62 +71,63 @@ bind_socket(int sockfd, const char* addr)
* independent implementation (mostly for IPv4 and IPv6 addresses.)
*/
int
opensock(const char* host, int port, const char* bind_to)
opensock(const char *host, int port, const char *bind_to)
{
int sockfd, n;
struct addrinfo hints, *res, *ressave;
char portstr[6];
int sockfd, n;
struct addrinfo hints, *res, *ressave;
char portstr[6];
assert(host != NULL);
assert(port > 0);
assert(host != NULL);
assert(port > 0);
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
snprintf(portstr, sizeof(portstr), "%d", port);
snprintf(portstr, sizeof(portstr), "%d", port);
n = getaddrinfo(host, portstr, &hints, &res);
if (n != 0) {
log_message(LOG_ERR, "opensock: Could not retrieve info for %s",
host);
return -1;
}
n = getaddrinfo(host, portstr, &hints, &res);
if (n != 0) {
log_message(LOG_ERR, "opensock: Could not retrieve info for %s",
host);
return -1;
}
ressave = res;
do {
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < 0)
continue; /* ignore this one */
ressave = res;
do {
sockfd =
socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < 0)
continue; /* ignore this one */
/* Bind to the specified address */
if (bind_to) {
if (bind_socket(sockfd, bind_to) < 0) {
close(sockfd);
continue; /* can't bind, so try again */
}
} else if (config.bind_address) {
if (bind_socket(sockfd, config.bind_address) < 0) {
close(sockfd);
continue; /* can't bind, so try again */
}
}
/* Bind to the specified address */
if (bind_to) {
if (bind_socket(sockfd, bind_to) < 0) {
close(sockfd);
continue; /* can't bind, so try again */
}
} else if (config.bind_address) {
if (bind_socket(sockfd, config.bind_address) < 0) {
close(sockfd);
continue; /* can't bind, so try again */
}
}
if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
break; /* success */
if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
break; /* success */
close(sockfd);
} while ((res = res->ai_next) != NULL);
close(sockfd);
} while ((res = res->ai_next) != NULL);
freeaddrinfo(ressave);
if (res == NULL) {
log_message(LOG_ERR,
"opensock: Could not establish a connection to %s",
host);
return -1;
}
freeaddrinfo(ressave);
if (res == NULL) {
log_message(LOG_ERR,
"opensock: Could not establish a connection to %s",
host);
return -1;
}
return sockfd;
return sockfd;
}
/*
@ -135,12 +136,12 @@ opensock(const char* host, int port, const char* bind_to)
int
socket_nonblocking(int sock)
{
int flags;
int flags;
assert(sock >= 0);
assert(sock >= 0);
flags = fcntl(sock, F_GETFL, 0);
return fcntl(sock, F_SETFL, flags | O_NONBLOCK);
flags = fcntl(sock, F_GETFL, 0);
return fcntl(sock, F_SETFL, flags | O_NONBLOCK);
}
/*
@ -149,12 +150,12 @@ socket_nonblocking(int sock)
int
socket_blocking(int sock)
{
int flags;
int flags;
assert(sock >= 0);
assert(sock >= 0);
flags = fcntl(sock, F_GETFL, 0);
return fcntl(sock, F_SETFL, flags & ~O_NONBLOCK);
flags = fcntl(sock, F_GETFL, 0);
return fcntl(sock, F_SETFL, flags & ~O_NONBLOCK);
}
/*
@ -164,94 +165,95 @@ socket_blocking(int sock)
* - rjkaes
*/
int
listen_sock(uint16_t port, socklen_t* addrlen)
listen_sock(uint16_t port, socklen_t * addrlen)
{
int listenfd;
const int on = 1;
struct sockaddr_in addr;
int listenfd;
const int on = 1;
struct sockaddr_in addr;
assert(port > 0);
assert(addrlen != NULL);
assert(port > 0);
assert(addrlen != NULL);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
listenfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (config.ipAddr) {
addr.sin_addr.s_addr = inet_addr(config.ipAddr);
} else {
addr.sin_addr.s_addr = inet_addr("0.0.0.0");
}
if (config.ipAddr) {
addr.sin_addr.s_addr = inet_addr(config.ipAddr);
} else {
addr.sin_addr.s_addr = inet_addr("0.0.0.0");
}
if (bind(listenfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
log_message(LOG_ERR, "Unable to bind listening socket because of %s",
strerror(errno));
return -1;
}
if (bind(listenfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
log_message(LOG_ERR,
"Unable to bind listening socket because of %s",
strerror(errno));
return -1;
}
if (listen(listenfd, MAXLISTEN) < 0) {
log_message(LOG_ERR, "Unable to start listening socket because of %s",
strerror(errno));
return -1;
}
if (listen(listenfd, MAXLISTEN) < 0) {
log_message(LOG_ERR,
"Unable to start listening socket because of %s",
strerror(errno));
return -1;
}
*addrlen = sizeof(addr);
*addrlen = sizeof(addr);
return listenfd;
return listenfd;
}
/*
* Takes a socket descriptor and returns the socket's IP address.
*/
int
getsock_ip(int fd, char* ipaddr)
getsock_ip(int fd, char *ipaddr)
{
struct sockaddr_storage name;
socklen_t namelen = sizeof(name);
struct sockaddr_storage name;
socklen_t namelen = sizeof(name);
assert(fd >= 0);
assert(fd >= 0);
if (getsockname(fd, (struct sockaddr *) &name, &namelen) != 0) {
log_message(LOG_ERR, "getsock_ip: getsockname() error: %s",
strerror(errno));
return -1;
}
if (getsockname(fd, (struct sockaddr *)&name, &namelen) != 0) {
log_message(LOG_ERR, "getsock_ip: getsockname() error: %s",
strerror(errno));
return -1;
}
if (get_ip_string((struct sockaddr *)&name, ipaddr, IP_LENGTH) == NULL)
return -1;
if (get_ip_string((struct sockaddr *)&name, ipaddr, IP_LENGTH) == NULL)
return -1;
return 0;
return 0;
}
/*
* Return the peer's socket information.
*/
int
getpeer_information(int fd, char* ipaddr, char* string_addr)
getpeer_information(int fd, char *ipaddr, char *string_addr)
{
struct sockaddr_storage sa;
size_t salen = sizeof(sa);
struct sockaddr_storage sa;
size_t salen = sizeof(sa);
assert(fd >= 0);
assert(ipaddr != NULL);
assert(string_addr != NULL);
assert(fd >= 0);
assert(ipaddr != NULL);
assert(string_addr != NULL);
/* Set the strings to default values */
ipaddr[0] = '\0';
strlcpy(string_addr, "[unknown]", HOSTNAME_LENGTH);
/* Set the strings to default values */
ipaddr[0] = '\0';
strlcpy(string_addr, "[unknown]", HOSTNAME_LENGTH);
/* Look up the IP address */
if (getpeername(fd, (struct sockaddr *)&sa, &salen) != 0)
return -1;
/* Look up the IP address */
if (getpeername(fd, (struct sockaddr *)&sa, &salen) != 0)
return -1;
if (get_ip_string((struct sockaddr *)&sa, ipaddr, IP_LENGTH) == NULL)
return -1;
if (get_ip_string((struct sockaddr *)&sa, ipaddr, IP_LENGTH) == NULL)
return -1;
/* Get the full host name */
return getnameinfo((struct sockaddr *)&sa, salen,
string_addr, HOSTNAME_LENGTH,
NULL, 0, 0);
/* Get the full host name */
return getnameinfo((struct sockaddr *)&sa, salen,
string_addr, HOSTNAME_LENGTH, NULL, 0, 0);
}

View File

@ -1,4 +1,4 @@
/* $Id: sock.h,v 1.13 2004-04-27 18:53:14 rjkaes Exp $
/* $Id: sock.h,v 1.14 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'sock.c' for a detailed description.
*
@ -25,13 +25,13 @@
#define MAXLINE (1024 * 4)
extern int opensock(const char* host, int port, const char* bind_to);
extern int listen_sock(uint16_t port, socklen_t* addrlen);
extern int opensock(const char *host, int port, const char *bind_to);
extern int listen_sock(uint16_t port, socklen_t * addrlen);
extern int socket_nonblocking(int sock);
extern int socket_blocking(int sock);
extern int getsock_ip(int fd, char* ipaddr);
extern int getpeer_information(int fd, char* ipaddr, char* string_addr);
extern int getsock_ip(int fd, char *ipaddr);
extern int getpeer_information(int fd, char *ipaddr, char *string_addr);
#endif

View File

@ -1,4 +1,4 @@
/* $Id: stats.c,v 1.17 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: stats.c,v 1.18 2005-08-15 03:54:31 rjkaes Exp $
*
* This module handles the statistics for tinyproxy. There are only two
* public API functions. The reason for the functions, rather than just a
@ -30,11 +30,11 @@
#include "utils.h"
struct stat_s {
unsigned long int num_reqs;
unsigned long int num_badcons;
unsigned long int num_open;
unsigned long int num_refused;
unsigned long int num_denied;
unsigned long int num_reqs;
unsigned long int num_badcons;
unsigned long int num_open;
unsigned long int num_refused;
unsigned long int num_denied;
};
static struct stat_s *stats;
@ -45,11 +45,11 @@ static struct stat_s *stats;
void
init_stats(void)
{
stats = malloc_shared_memory(sizeof(struct stat_s));
if (stats == MAP_FAILED)
return;
stats = malloc_shared_memory(sizeof(struct stat_s));
if (stats == MAP_FAILED)
return;
memset(stats, 0, sizeof(struct stat_s));
memset(stats, 0, sizeof(struct stat_s));
}
/*
@ -58,59 +58,60 @@ init_stats(void)
int
showstats(struct conn_s *connptr)
{
static char *msg =
"<html><head><title>%s (%s) stats</title></head>\r\n"
"<body>\r\n"
"<center><h2>%s (%s) run-time statistics</h2></center><hr>\r\n"
"<blockquote>\r\n"
"Number of open connections: %lu<br>\r\n"
"Number of requests: %lu<br>\r\n"
"Number of bad connections: %lu<br>\r\n"
"Number of denied connections: %lu<br>\r\n"
"Number of refused connections due to high load: %lu\r\n"
"</blockquote>\r\n</body></html>\r\n";
static char *msg =
"<html><head><title>%s (%s) stats</title></head>\r\n"
"<body>\r\n"
"<center><h2>%s (%s) run-time statistics</h2></center><hr>\r\n"
"<blockquote>\r\n"
"Number of open connections: %lu<br>\r\n"
"Number of requests: %lu<br>\r\n"
"Number of bad connections: %lu<br>\r\n"
"Number of denied connections: %lu<br>\r\n"
"Number of refused connections due to high load: %lu\r\n"
"</blockquote>\r\n</body></html>\r\n";
char *message_buffer;
char opens[16], reqs[16], badconns[16], denied[16], refused[16];
FILE *statfile;
char *message_buffer;
char opens[16], reqs[16], badconns[16], denied[16], refused[16];
FILE *statfile;
snprintf(opens, sizeof(opens), "%lu", stats->num_open);
snprintf(reqs, sizeof(reqs), "%lu", stats->num_reqs);
snprintf(badconns, sizeof(badconns), "%lu", stats->num_badcons);
snprintf(denied, sizeof(denied), "%lu", stats->num_denied);
snprintf(refused, sizeof(refused), "%lu", stats->num_refused);
snprintf(opens, sizeof(opens), "%lu", stats->num_open);
snprintf(reqs, sizeof(reqs), "%lu", stats->num_reqs);
snprintf(badconns, sizeof(badconns), "%lu", stats->num_badcons);
snprintf(denied, sizeof(denied), "%lu", stats->num_denied);
snprintf(refused, sizeof(refused), "%lu", stats->num_refused);
if (!config.statpage || (!(statfile = fopen(config.statpage, "r")))) {
message_buffer = safemalloc(MAXBUFFSIZE);
if (!message_buffer)
return -1;
if (!config.statpage || (!(statfile = fopen(config.statpage, "r")))) {
message_buffer = safemalloc(MAXBUFFSIZE);
if (!message_buffer)
return -1;
snprintf(message_buffer, MAXBUFFSIZE, msg,
PACKAGE, VERSION, PACKAGE, VERSION,
stats->num_open,
stats->num_reqs,
stats->num_badcons, stats->num_denied, stats->num_refused);
snprintf(message_buffer, MAXBUFFSIZE, msg,
PACKAGE, VERSION, PACKAGE, VERSION,
stats->num_open,
stats->num_reqs,
stats->num_badcons, stats->num_denied,
stats->num_refused);
if (send_http_message(connptr, 200, "OK", message_buffer) < 0) {
safefree(message_buffer);
return -1;
}
if (send_http_message(connptr, 200, "OK", message_buffer) < 0) {
safefree(message_buffer);
return -1;
}
safefree(message_buffer);
return 0;
}
safefree(message_buffer);
return 0;
}
add_error_variable(connptr, "opens", opens);
add_error_variable(connptr, "reqs", reqs);
add_error_variable(connptr, "badconns", badconns);
add_error_variable(connptr, "denied", denied);
add_error_variable(connptr, "refused", refused);
add_standard_vars(connptr);
send_http_headers(connptr, 200, "Statistic requested");
send_html_file(statfile, connptr);
fclose(statfile);
add_error_variable(connptr, "opens", opens);
add_error_variable(connptr, "reqs", reqs);
add_error_variable(connptr, "badconns", badconns);
add_error_variable(connptr, "denied", denied);
add_error_variable(connptr, "refused", refused);
add_standard_vars(connptr);
send_http_headers(connptr, 200, "Statistic requested");
send_html_file(statfile, connptr);
fclose(statfile);
return 0;
return 0;
}
/*
@ -120,26 +121,26 @@ showstats(struct conn_s *connptr)
int
update_stats(status_t update_level)
{
switch (update_level) {
case STAT_BADCONN:
++stats->num_badcons;
break;
case STAT_OPEN:
++stats->num_open;
++stats->num_reqs;
break;
case STAT_CLOSE:
--stats->num_open;
break;
case STAT_REFUSE:
++stats->num_refused;
break;
case STAT_DENIED:
++stats->num_denied;
break;
default:
return -1;
}
switch (update_level) {
case STAT_BADCONN:
++stats->num_badcons;
break;
case STAT_OPEN:
++stats->num_open;
++stats->num_reqs;
break;
case STAT_CLOSE:
--stats->num_open;
break;
case STAT_REFUSE:
++stats->num_refused;
break;
case STAT_DENIED:
++stats->num_denied;
break;
default:
return -1;
}
return 0;
return 0;
}

View File

@ -1,4 +1,4 @@
/* $Id: stats.h,v 1.5 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: stats.h,v 1.6 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'stats.h' for a detailed description.
*
@ -24,11 +24,11 @@
* Various logable statistics
*/
typedef enum {
STAT_BADCONN, /* bad connection, for unknown reason */
STAT_OPEN, /* connection opened */
STAT_CLOSE, /* connection closed */
STAT_REFUSE, /* connection refused (to outside world) */
STAT_DENIED /* connection denied to tinyproxy itself */
STAT_BADCONN, /* bad connection, for unknown reason */
STAT_OPEN, /* connection opened */
STAT_CLOSE, /* connection closed */
STAT_REFUSE, /* connection refused (to outside world) */
STAT_DENIED /* connection denied to tinyproxy itself */
} status_t;
/*

View File

@ -1,4 +1,4 @@
/* $Id: text.c,v 1.4 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: text.c,v 1.5 2005-08-15 03:54:31 rjkaes Exp $
*
* The functions included here are useful for text manipulation. They
* replace or augment the standard C string library. These functions
@ -31,16 +31,16 @@
size_t
strlcpy(char *dst, const char *src, size_t size)
{
size_t len = strlen(src);
size_t ret = len;
size_t len = strlen(src);
size_t ret = len;
if (len >= size)
len = size - 1;
if (len >= size)
len = size - 1;
memcpy(dst, src, len);
dst[len] = '\0';
memcpy(dst, src, len);
dst[len] = '\0';
return ret;
return ret;
}
#endif
@ -54,18 +54,18 @@ strlcpy(char *dst, const char *src, size_t size)
size_t
strlcat(char *dst, const char *src, size_t size)
{
size_t len1 = strlen(dst);
size_t len2 = strlen(src);
size_t ret = len1 + len2;
size_t len1 = strlen(dst);
size_t len2 = strlen(src);
size_t ret = len1 + len2;
if (len1 + len2 >= size)
len2 = size - len1 - 1;
if (len2 > 0) {
memcpy(dst + len1, src, len2);
dst[len1 + len2] = '\0';
}
if (len1 + len2 >= size)
len2 = size - len1 - 1;
if (len2 > 0) {
memcpy(dst + len1, src, len2);
dst[len1 + len2] = '\0';
}
return ret;
return ret;
}
#endif
@ -81,25 +81,28 @@ strlcat(char *dst, const char *src, size_t size)
ssize_t
chomp(char *buffer, size_t length)
{
size_t chars;
size_t chars;
assert(buffer != NULL);
assert(length > 0);
assert(buffer != NULL);
assert(length > 0);
/* Make sure the arguments are valid */
if (buffer == NULL) return -EFAULT;
if (length < 1) return -ERANGE;
/* Make sure the arguments are valid */
if (buffer == NULL)
return -EFAULT;
if (length < 1)
return -ERANGE;
chars = 0;
chars = 0;
--length;
while (buffer[length] == '\r' || buffer[length] == '\n') {
buffer[length] = '\0';
chars++;
--length;
while (buffer[length] == '\r' || buffer[length] == '\n') {
buffer[length] = '\0';
chars++;
/* Stop once we get to zero to prevent wrap-around */
if (length-- == 0) break;
}
/* Stop once we get to zero to prevent wrap-around */
if (length-- == 0)
break;
}
return chars;
return chars;
}

View File

@ -1,4 +1,4 @@
/* $Id: text.h,v 1.3 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: text.h,v 1.4 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'text.c' for a detailed description.
*
@ -20,11 +20,11 @@
#ifndef HAVE_STRLCAT
extern size_t strlcat(char *dst, const char *src, size_t size);
#endif /* HAVE_STRLCAT */
#endif /* HAVE_STRLCAT */
#ifndef HAVE_STRLCPY
extern size_t strlcpy(char *dst, const char *src, size_t size);
#endif /* HAVE_STRLCPY */
#endif /* HAVE_STRLCPY */
extern ssize_t chomp(char *buffer, size_t length);

View File

@ -1,4 +1,4 @@
/* $Id: tinyproxy.c,v 1.51 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: tinyproxy.c,v 1.52 2005-08-15 03:54:31 rjkaes Exp $
*
* The initialize routine. Basically sets up all the initial stuff (logfile,
* listening socket, config options, etc.) and then sits there and loops
@ -44,8 +44,8 @@ RETSIGTYPE takesig(int sig);
*/
struct config_s config;
float load = 0.00;
unsigned int received_sighup = FALSE; /* boolean */
unsigned int processed_config_file = FALSE; /* boolean */
unsigned int received_sighup = FALSE; /* boolean */
unsigned int processed_config_file = FALSE; /* boolean */
/*
* Handle a signal
@ -53,25 +53,24 @@ unsigned int processed_config_file = FALSE; /* boolean */
RETSIGTYPE
takesig(int sig)
{
pid_t pid;
int status;
pid_t pid;
int status;
switch (sig) {
case SIGHUP:
received_sighup = TRUE;
break;
switch (sig) {
case SIGHUP:
received_sighup = TRUE;
break;
case SIGTERM:
config.quit = TRUE;
break;
case SIGTERM:
config.quit = TRUE;
break;
case SIGCHLD:
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
;
break;
}
case SIGCHLD:
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) ;
break;
}
return;
return;
}
/*
@ -80,7 +79,7 @@ takesig(int sig)
static void
display_version(void)
{
printf("%s %s (%s)\n", PACKAGE, VERSION, TARGET_SYSTEM);
printf("%s %s (%s)\n", PACKAGE, VERSION, TARGET_SYSTEM);
}
/*
@ -89,9 +88,9 @@ display_version(void)
static void
display_license(void)
{
display_version();
display_version();
printf("\
printf("\
Copyright 1998 Steven Young (sdyoung@well.com)\n\
Copyright 1998-2002 Robert James Kaes (rjkaes@users.sourceforge.net)\n\
Copyright 1999 George Talusan (gstalusan@uwaterloo.ca)\n\
@ -118,8 +117,8 @@ display_license(void)
static void
display_usage(void)
{
printf("Usage: %s [options]\n", PACKAGE);
printf("\
printf("Usage: %s [options]\n", PACKAGE);
printf("\
Options:\n\
-d Operate in DEBUG mode.\n\
-c FILE Use an alternate configuration file.\n\
@ -127,97 +126,97 @@ Options:\n\
-l Display the license.\n\
-v Display the version number.\n");
/* Display the modes compiled into tinyproxy */
printf("\nFeatures compiled in:\n");
/* Display the modes compiled into tinyproxy */
printf("\nFeatures compiled in:\n");
#ifdef XTINYPROXY_ENABLE
printf(" XTinyproxy header\n");
#endif /* XTINYPROXY */
printf(" XTinyproxy header\n");
#endif /* XTINYPROXY */
#ifdef FILTER_ENABLE
printf(" Filtering\n");
#endif /* FILTER_ENABLE */
printf(" Filtering\n");
#endif /* FILTER_ENABLE */
#ifndef NDEBUG
printf(" Debugging code\n");
#endif /* NDEBUG */
printf(" Debugging code\n");
#endif /* NDEBUG */
#ifdef TRANSPARENT_PROXY
printf(" Transparent proxy support\n");
printf(" Transparent proxy support\n");
#endif /* TRANSPARENT_PROXY */
#ifdef REVERSE_SUPPORT
printf(" Reverse proxy support\n");
#endif /* REVERSE_SUPPORT */
printf(" Reverse proxy support\n");
#endif /* REVERSE_SUPPORT */
}
int
main(int argc, char **argv)
{
int optch;
unsigned int godaemon = TRUE; /* boolean */
struct passwd *thisuser = NULL;
struct group *thisgroup = NULL;
FILE* config_file;
int optch;
unsigned int godaemon = TRUE; /* boolean */
struct passwd *thisuser = NULL;
struct group *thisgroup = NULL;
FILE *config_file;
/*
* Disable the creation of CORE files right up front.
*/
/*
* Disable the creation of CORE files right up front.
*/
#if defined(HAVE_SETRLIMIT) && defined(NDEBUG)
struct rlimit core_limit = { 0, 0 };
if (setrlimit(RLIMIT_CORE, &core_limit) < 0) {
fprintf(stderr, "%s: Could not set the core limit to zero.\n",
argv[0]);
exit(EX_SOFTWARE);
}
#endif /* HAVE_SETRLIMIT */
struct rlimit core_limit = { 0, 0 };
if (setrlimit(RLIMIT_CORE, &core_limit) < 0) {
fprintf(stderr, "%s: Could not set the core limit to zero.\n",
argv[0]);
exit(EX_SOFTWARE);
}
#endif /* HAVE_SETRLIMIT */
/* Default configuration file location */
config.config_file = DEFAULT_CONF_FILE;
/* Default configuration file location */
config.config_file = DEFAULT_CONF_FILE;
/*
* Process the various options
*/
while ((optch = getopt(argc, argv, "c:vldh")) != EOF) {
switch (optch) {
case 'v':
display_version();
exit(EX_OK);
case 'l':
display_license();
exit(EX_OK);
case 'd':
godaemon = FALSE;
break;
case 'c':
config.config_file = safestrdup(optarg);
if (!config.config_file) {
fprintf(stderr,
"%s: Could not allocate memory.\n",
argv[0]);
exit(EX_SOFTWARE);
}
break;
case 'h':
default:
display_usage();
exit(EX_OK);
}
}
/*
* Process the various options
*/
while ((optch = getopt(argc, argv, "c:vldh")) != EOF) {
switch (optch) {
case 'v':
display_version();
exit(EX_OK);
case 'l':
display_license();
exit(EX_OK);
case 'd':
godaemon = FALSE;
break;
case 'c':
config.config_file = safestrdup(optarg);
if (!config.config_file) {
fprintf(stderr,
"%s: Could not allocate memory.\n",
argv[0]);
exit(EX_SOFTWARE);
}
break;
case 'h':
default:
display_usage();
exit(EX_OK);
}
}
log_message(LOG_INFO, "Initializing " PACKAGE " ...");
log_message(LOG_INFO, "Initializing " PACKAGE " ...");
/*
* Make sure the HTML error pages array is NULL to begin with.
* (FIXME: Should have a better API for all this)
*/
config.errorpages = NULL;
/*
* Make sure the HTML error pages array is NULL to begin with.
* (FIXME: Should have a better API for all this)
*/
config.errorpages = NULL;
/*
* Read in the settings from the config file.
*/
/*
* Read in the settings from the config file.
*/
config_file = fopen(config.config_file, "r");
if (!config_file) {
fprintf(stderr,
"%s: Could not open configuration file \"%s\".\n",
argv[0], config.config_file);
exit(EX_SOFTWARE);
}
fprintf(stderr,
"%s: Could not open configuration file \"%s\".\n",
argv[0], config.config_file);
exit(EX_SOFTWARE);
}
if (config_compile() || config_parse(&config, config_file)) {
fprintf(stderr,
"Unable to parse configuration file. Not starting.\n");
@ -232,194 +231,192 @@ main(int argc, char **argv)
if (config.logf_name) {
if (open_log_file(config.logf_name) < 0) {
fprintf(stderr,
"%s: Could not create log file.\n",
argv[0]);
"%s: Could not create log file.\n", argv[0]);
exit(EX_SOFTWARE);
}
config.syslog = FALSE; /* disable syslog */
config.syslog = FALSE; /* disable syslog */
} else if (config.syslog) {
if (godaemon == TRUE)
openlog("tinyproxy", LOG_PID, LOG_DAEMON);
else
openlog("tinyproxy", LOG_PID, LOG_USER);
} else {
if (godaemon == TRUE)
openlog("tinyproxy", LOG_PID, LOG_DAEMON);
else
openlog("tinyproxy", LOG_PID, LOG_USER);
} else {
fprintf(stderr,
"%s: Either define a logfile or enable syslog logging\n",
argv[0]);
exit(EX_SOFTWARE);
}
processed_config_file = TRUE;
send_stored_logs();
processed_config_file = TRUE;
send_stored_logs();
/*
* Set the default values if they were not set in the config file.
*/
if (config.port == 0) {
fprintf(stderr,
"%s: You MUST set a Port in the configuration file.\n",
argv[0]);
exit(EX_SOFTWARE);
}
if (!config.stathost) {
log_message(LOG_INFO, "Setting stathost to \"%s\".",
DEFAULT_STATHOST);
config.stathost = DEFAULT_STATHOST;
}
if (!config.username) {
log_message(LOG_WARNING,
"You SHOULD set a UserName in the configuration file. Using current user instead.");
}
if (config.idletimeout == 0) {
log_message(LOG_WARNING, "Invalid idle time setting. Only values greater than zero allowed; therefore setting idle timeout to %u seconds.",
MAX_IDLE_TIME);
config.idletimeout = MAX_IDLE_TIME;
}
/*
* Set the default values if they were not set in the config file.
*/
if (config.port == 0) {
fprintf(stderr,
"%s: You MUST set a Port in the configuration file.\n",
argv[0]);
exit(EX_SOFTWARE);
}
if (!config.stathost) {
log_message(LOG_INFO, "Setting stathost to \"%s\".",
DEFAULT_STATHOST);
config.stathost = DEFAULT_STATHOST;
}
if (!config.username) {
log_message(LOG_WARNING,
"You SHOULD set a UserName in the configuration file. Using current user instead.");
}
if (config.idletimeout == 0) {
log_message(LOG_WARNING,
"Invalid idle time setting. Only values greater than zero allowed; therefore setting idle timeout to %u seconds.",
MAX_IDLE_TIME);
config.idletimeout = MAX_IDLE_TIME;
}
init_stats();
init_stats();
/*
* If ANONYMOUS is turned on, make sure that Content-Length is
* in the list of allowed headers, since it is required in a
* HTTP/1.0 request. Also add the Content-Type header since it goes
* hand in hand with Content-Length.
* - rjkaes
*/
if (is_anonymous_enabled()) {
anonymous_insert("Content-Length");
anonymous_insert("Content-Type");
}
/*
* If ANONYMOUS is turned on, make sure that Content-Length is
* in the list of allowed headers, since it is required in a
* HTTP/1.0 request. Also add the Content-Type header since it goes
* hand in hand with Content-Length.
* - rjkaes
*/
if (is_anonymous_enabled()) {
anonymous_insert("Content-Length");
anonymous_insert("Content-Type");
}
if (godaemon == TRUE)
makedaemon();
if (godaemon == TRUE)
makedaemon();
if (config.pidpath) {
if (pidfile_create(config.pidpath) < 0) {
fprintf(stderr, "%s: Could not create PID file.\n",
argv[0]);
exit(EX_OSERR);
}
}
if (set_signal_handler(SIGPIPE, SIG_IGN) == SIG_ERR) {
fprintf(stderr, "%s: Could not set the \"SIGPIPE\" signal.\n",
argv[0]);
exit(EX_OSERR);
}
if (config.pidpath) {
if (pidfile_create(config.pidpath) < 0) {
fprintf(stderr, "%s: Could not create PID file.\n",
argv[0]);
exit(EX_OSERR);
}
}
if (set_signal_handler(SIGPIPE, SIG_IGN) == SIG_ERR) {
fprintf(stderr, "%s: Could not set the \"SIGPIPE\" signal.\n",
argv[0]);
exit(EX_OSERR);
}
#ifdef FILTER_ENABLE
if (config.filter)
filter_init();
#endif /* FILTER_ENABLE */
if (config.filter)
filter_init();
#endif /* FILTER_ENABLE */
/*
* Start listening on the selected port.
*/
if (child_listening_sock(config.port) < 0) {
fprintf(stderr, "%s: Could not create listening socket.\n",
argv[0]);
exit(EX_OSERR);
}
/*
* Start listening on the selected port.
*/
if (child_listening_sock(config.port) < 0) {
fprintf(stderr, "%s: Could not create listening socket.\n",
argv[0]);
exit(EX_OSERR);
}
/*
* Switch to a different user.
*/
if (geteuid() == 0) {
if (config.group && strlen(config.group) > 0) {
thisgroup = getgrnam(config.group);
if (!thisgroup) {
fprintf(stderr,
"%s: Unable to find group \"%s\".\n",
argv[0], config.group);
exit(EX_NOUSER);
}
if (setgid(thisgroup->gr_gid) < 0) {
fprintf(stderr,
"%s: Unable to change to group \"%s\".\n",
argv[0], config.group);
exit(EX_CANTCREAT);
}
log_message(LOG_INFO, "Now running as group \"%s\".",
config.group);
}
if (config.username && strlen(config.username) > 0) {
thisuser = getpwnam(config.username);
if (!thisuser) {
fprintf(stderr,
"%s: Unable to find user \"%s\".",
argv[0], config.username);
exit(EX_NOUSER);
}
if (setuid(thisuser->pw_uid) < 0) {
fprintf(stderr,
"%s: Unable to change to user \"%s\".",
argv[0], config.username);
exit(EX_CANTCREAT);
}
log_message(LOG_INFO, "Now running as user \"%s\".",
config.username);
}
} else {
log_message(LOG_WARNING,
"Not running as root, so not changing UID/GID.");
}
/*
* Switch to a different user.
*/
if (geteuid() == 0) {
if (config.group && strlen(config.group) > 0) {
thisgroup = getgrnam(config.group);
if (!thisgroup) {
fprintf(stderr,
"%s: Unable to find group \"%s\".\n",
argv[0], config.group);
exit(EX_NOUSER);
}
if (setgid(thisgroup->gr_gid) < 0) {
fprintf(stderr,
"%s: Unable to change to group \"%s\".\n",
argv[0], config.group);
exit(EX_CANTCREAT);
}
log_message(LOG_INFO, "Now running as group \"%s\".",
config.group);
}
if (config.username && strlen(config.username) > 0) {
thisuser = getpwnam(config.username);
if (!thisuser) {
fprintf(stderr,
"%s: Unable to find user \"%s\".",
argv[0], config.username);
exit(EX_NOUSER);
}
if (setuid(thisuser->pw_uid) < 0) {
fprintf(stderr,
"%s: Unable to change to user \"%s\".",
argv[0], config.username);
exit(EX_CANTCREAT);
}
log_message(LOG_INFO, "Now running as user \"%s\".",
config.username);
}
} else {
log_message(LOG_WARNING,
"Not running as root, so not changing UID/GID.");
}
if (child_pool_create() < 0) {
fprintf(stderr, "%s: Could not create the pool of children.",
argv[0]);
exit(EX_SOFTWARE);
}
if (child_pool_create() < 0) {
fprintf(stderr, "%s: Could not create the pool of children.",
argv[0]);
exit(EX_SOFTWARE);
}
/*
* These signals are only for the parent process.
*/
log_message(LOG_INFO, "Setting the various signals.");
if (set_signal_handler(SIGCHLD, takesig) == SIG_ERR) {
fprintf(stderr, "%s: Could not set the \"SIGCHLD\" signal.\n",
argv[0]);
exit(EX_OSERR);
}
if (set_signal_handler(SIGTERM, takesig) == SIG_ERR) {
fprintf(stderr, "%s: Could not set the \"SIGTERM\" signal.\n",
argv[0]);
exit(EX_OSERR);
}
if (set_signal_handler(SIGHUP, takesig) == SIG_ERR) {
fprintf(stderr, "%s: Could not set the \"SIGHUP\" signal.\n",
argv[0]);
exit(EX_OSERR);
}
/*
* These signals are only for the parent process.
*/
log_message(LOG_INFO, "Setting the various signals.");
if (set_signal_handler(SIGCHLD, takesig) == SIG_ERR) {
fprintf(stderr, "%s: Could not set the \"SIGCHLD\" signal.\n",
argv[0]);
exit(EX_OSERR);
}
if (set_signal_handler(SIGTERM, takesig) == SIG_ERR) {
fprintf(stderr, "%s: Could not set the \"SIGTERM\" signal.\n",
argv[0]);
exit(EX_OSERR);
}
if (set_signal_handler(SIGHUP, takesig) == SIG_ERR) {
fprintf(stderr, "%s: Could not set the \"SIGHUP\" signal.\n",
argv[0]);
exit(EX_OSERR);
}
/*
* Start the main loop.
*/
log_message(LOG_INFO, "Starting main loop. Accepting connections.");
/*
* Start the main loop.
*/
log_message(LOG_INFO, "Starting main loop. Accepting connections.");
child_main_loop();
child_main_loop();
log_message(LOG_INFO, "Shutting down.");
log_message(LOG_INFO, "Shutting down.");
child_kill_children();
child_close_sock();
/*
* Remove the PID file.
*/
if (unlink(config.pidpath) < 0) {
log_message(LOG_WARNING,
"Could not remove PID file \"%s\": %s.",
config.pidpath, strerror(errno));
}
child_kill_children();
child_close_sock();
/*
* Remove the PID file.
*/
if (unlink(config.pidpath) < 0) {
log_message(LOG_WARNING,
"Could not remove PID file \"%s\": %s.",
config.pidpath, strerror(errno));
}
#ifdef FILTER_ENABLE
if (config.filter)
filter_destroy();
#endif /* FILTER_ENABLE */
if (config.filter)
filter_destroy();
#endif /* FILTER_ENABLE */
if (config.syslog)
closelog();
else
close_log_file();
if (config.syslog)
closelog();
else
close_log_file();
exit(EX_OK);
exit(EX_OK);
}

View File

@ -1,4 +1,4 @@
/* $Id: tinyproxy.h,v 1.46 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: tinyproxy.h,v 1.47 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'tinyproxy.c' for a detailed description.
*
@ -23,26 +23,26 @@
#include "hashmap.h"
/* Global variables for the main controls of the program */
#define MAXBUFFSIZE ((size_t)(1024 * 96)) /* Max size of buffer */
#define MAX_IDLE_TIME (60 * 10) /* 10 minutes of no activity */
#define MAXBUFFSIZE ((size_t)(1024 * 96)) /* Max size of buffer */
#define MAX_IDLE_TIME (60 * 10) /* 10 minutes of no activity */
/*
* Even if upstream support is not compiled into tinyproxy, this
* structure still needs to be defined.
*/
struct upstream {
struct upstream *next;
char *domain; /* optional */
char *host;
int port;
in_addr_t ip, mask;
struct upstream *next;
char *domain; /* optional */
char *host;
int port;
in_addr_t ip, mask;
};
#ifdef REVERSE_SUPPORT
struct reversepath {
struct reversepath *next;
char *path;
char *url;
struct reversepath *next;
char *path;
char *url;
};
#define REVERSE_COOKIE "yummy_magical_cookie"
@ -52,63 +52,63 @@ struct reversepath {
* Hold all the configuration time information.
*/
struct config_s {
char *logf_name;
char *config_file;
unsigned int syslog; /* boolean */
int port;
char *stathost;
unsigned int quit; /* boolean */
char *username;
char *group;
char *ipAddr;
char *logf_name;
char *config_file;
unsigned int syslog; /* boolean */
int port;
char *stathost;
unsigned int quit; /* boolean */
char *username;
char *group;
char *ipAddr;
#ifdef FILTER_ENABLE
char *filter;
unsigned int filter_url; /* boolean */
unsigned int filter_extended; /* boolean */
unsigned int filter_casesensitive; /* boolean */
#endif /* FILTER_ENABLE */
char *filter;
unsigned int filter_url; /* boolean */
unsigned int filter_extended; /* boolean */
unsigned int filter_casesensitive; /* boolean */
#endif /* FILTER_ENABLE */
#ifdef XTINYPROXY_ENABLE
char *my_domain;
char *my_domain;
#endif
#ifdef REVERSE_SUPPORT
struct reversepath *reversepath_list;
unsigned int reverseonly; /* boolean */
unsigned int reversemagic; /* boolean */
char *reversebaseurl;
struct reversepath *reversepath_list;
unsigned int reverseonly; /* boolean */
unsigned int reversemagic; /* boolean */
char *reversebaseurl;
#endif
#ifdef UPSTREAM_SUPPORT
struct upstream *upstream_list;
#endif /* UPSTREAM_SUPPORT */
char *pidpath;
unsigned int idletimeout;
char* bind_address;
unsigned int bindsame;
struct upstream *upstream_list;
#endif /* UPSTREAM_SUPPORT */
char *pidpath;
unsigned int idletimeout;
char *bind_address;
unsigned int bindsame;
/*
* The configured name to use in the HTTP "Via" header field.
*/
char* via_proxy_name;
/*
* The configured name to use in the HTTP "Via" header field.
*/
char *via_proxy_name;
/*
* Error page support. Map error numbers to file paths.
*/
hashmap_t errorpages;
* Error page support. Map error numbers to file paths.
*/
hashmap_t errorpages;
/*
* Error page to be displayed if appropriate page cannot be located
* in the errorpages structure.
*/
char *errorpage_undef;
/*
* Error page to be displayed if appropriate page cannot be located
* in the errorpages structure.
*/
char *errorpage_undef;
/*
* The HTML statistics page.
*/
char *statpage;
/*
* The HTML statistics page.
*/
char *statpage;
};
/* Global Structures used in the program */
extern struct config_s config;
extern unsigned int received_sighup; /* boolean */
extern unsigned int processed_config_file; /* boolean */
extern unsigned int received_sighup; /* boolean */
extern unsigned int processed_config_file; /* boolean */
#endif

View File

@ -1,4 +1,4 @@
/* $Id: utils.c,v 1.39 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: utils.c,v 1.40 2005-08-15 03:54:31 rjkaes Exp $
*
* Misc. routines which are used by the various functions to handle strings
* and memory allocation and pretty much anything else we can think of. Also,
@ -31,26 +31,26 @@
*/
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)
{
static char* headers[] = {
"Server: " PACKAGE "/" VERSION,
"Content-type: text/html",
"Connection: close"
};
static char *headers[] = {
"Server: " PACKAGE "/" VERSION,
"Content-type: text/html",
"Connection: close"
};
http_message_t msg;
http_message_t msg;
msg = http_message_create(http_code, error_title);
if (msg == NULL)
return -1;
msg = http_message_create(http_code, error_title);
if (msg == NULL)
return -1;
http_message_add_headers(msg, headers, 3);
http_message_set_body(msg, message, strlen(message));
http_message_send(msg, connptr->client_fd);
http_message_destroy(msg);
http_message_add_headers(msg, headers, 3);
http_message_set_body(msg, message, strlen(message));
http_message_send(msg, connptr->client_fd);
http_message_destroy(msg);
return 0;
return 0;
}
/*
@ -59,116 +59,116 @@ send_http_message(struct conn_s *connptr, int http_code,
int
create_file_safely(const char *filename, unsigned int truncate_file)
{
struct stat lstatinfo;
int fildes;
struct stat lstatinfo;
int fildes;
/*
* lstat() the file. If it doesn't exist, create it with O_EXCL.
* If it does exist, open it for writing and perform the fstat()
* check.
*/
if (lstat(filename, &lstatinfo) < 0) {
/*
* If lstat() failed for any reason other than "file not
* existing", exit.
*/
if (errno != ENOENT) {
fprintf(stderr,
"%s: Error checking file %s: %s\n",
PACKAGE, filename, strerror(errno));
return -EACCES;
}
/*
* lstat() the file. If it doesn't exist, create it with O_EXCL.
* If it does exist, open it for writing and perform the fstat()
* check.
*/
if (lstat(filename, &lstatinfo) < 0) {
/*
* If lstat() failed for any reason other than "file not
* existing", exit.
*/
if (errno != ENOENT) {
fprintf(stderr,
"%s: Error checking file %s: %s\n",
PACKAGE, filename, strerror(errno));
return -EACCES;
}
/*
* The file doesn't exist, so create it with O_EXCL to make
* sure an attacker can't slip in a file between the lstat()
* and open()
*/
if ((fildes =
open(filename, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) {
fprintf(stderr,
"%s: Could not create file %s: %s\n",
PACKAGE, filename, strerror(errno));
return fildes;
}
} else {
struct stat fstatinfo;
int flags;
/*
* The file doesn't exist, so create it with O_EXCL to make
* sure an attacker can't slip in a file between the lstat()
* and open()
*/
if ((fildes =
open(filename, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) {
fprintf(stderr,
"%s: Could not create file %s: %s\n",
PACKAGE, filename, strerror(errno));
return fildes;
}
} else {
struct stat fstatinfo;
int flags;
flags = O_RDWR;
if (!truncate_file)
flags |= O_APPEND;
flags = O_RDWR;
if (!truncate_file)
flags |= O_APPEND;
/*
* Open an existing file.
*/
if ((fildes = open(filename, flags)) < 0) {
fprintf(stderr,
"%s: Could not open file %s: %s\n",
PACKAGE, filename, strerror(errno));
return fildes;
}
/*
* Open an existing file.
*/
if ((fildes = open(filename, flags)) < 0) {
fprintf(stderr,
"%s: Could not open file %s: %s\n",
PACKAGE, filename, strerror(errno));
return fildes;
}
/*
* fstat() the opened file and check that the file mode bits,
* inode, and device match.
*/
if (fstat(fildes, &fstatinfo) < 0
|| lstatinfo.st_mode != fstatinfo.st_mode
|| lstatinfo.st_ino != fstatinfo.st_ino
|| lstatinfo.st_dev != fstatinfo.st_dev) {
fprintf(stderr,
"%s: The file %s has been changed before it could be opened\n",
PACKAGE, filename);
close(fildes);
return -EIO;
}
/*
* fstat() the opened file and check that the file mode bits,
* inode, and device match.
*/
if (fstat(fildes, &fstatinfo) < 0
|| lstatinfo.st_mode != fstatinfo.st_mode
|| lstatinfo.st_ino != fstatinfo.st_ino
|| lstatinfo.st_dev != fstatinfo.st_dev) {
fprintf(stderr,
"%s: The file %s has been changed before it could be opened\n",
PACKAGE, filename);
close(fildes);
return -EIO;
}
/*
* If the above check was passed, we know that the lstat()
* and fstat() were done on the same file. Now we check that
* there's only one link, and that it's a normal file (this
* isn't strictly necessary because the fstat() vs lstat()
* st_mode check would also find this)
*/
if (fstatinfo.st_nlink > 1 || !S_ISREG(lstatinfo.st_mode)) {
fprintf(stderr,
"%s: The file %s has too many links, or is not a regular file: %s\n",
PACKAGE, filename, strerror(errno));
close(fildes);
return -EMLINK;
}
/*
* If the above check was passed, we know that the lstat()
* and fstat() were done on the same file. Now we check that
* there's only one link, and that it's a normal file (this
* isn't strictly necessary because the fstat() vs lstat()
* st_mode check would also find this)
*/
if (fstatinfo.st_nlink > 1 || !S_ISREG(lstatinfo.st_mode)) {
fprintf(stderr,
"%s: The file %s has too many links, or is not a regular file: %s\n",
PACKAGE, filename, strerror(errno));
close(fildes);
return -EMLINK;
}
/*
* Just return the file descriptor if we _don't_ want the file
* truncated.
*/
if (!truncate_file)
return fildes;
/*
* Just return the file descriptor if we _don't_ want the file
* truncated.
*/
if (!truncate_file)
return fildes;
/*
* On systems which don't support ftruncate() the best we can
* do is to close the file and reopen it in create mode, which
* unfortunately leads to a race condition, however "systems
* which don't support ftruncate()" is pretty much SCO only,
* and if you're using that you deserve what you get.
* ("Little sympathy has been extended")
*/
/*
* On systems which don't support ftruncate() the best we can
* do is to close the file and reopen it in create mode, which
* unfortunately leads to a race condition, however "systems
* which don't support ftruncate()" is pretty much SCO only,
* and if you're using that you deserve what you get.
* ("Little sympathy has been extended")
*/
#ifdef HAVE_FTRUNCATE
ftruncate(fildes, 0);
ftruncate(fildes, 0);
#else
close(fildes);
if ((fildes =
open(filename, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) {
fprintf(stderr,
"%s: Could not open file %s: %s.",
PACKAGE, filename, strerror(errno));
return fildes;
}
#endif /* HAVE_FTRUNCATE */
}
close(fildes);
if ((fildes =
open(filename, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) {
fprintf(stderr,
"%s: Could not open file %s: %s.",
PACKAGE, filename, strerror(errno));
return fildes;
}
#endif /* HAVE_FTRUNCATE */
}
return fildes;
return fildes;
}
/*
@ -177,28 +177,28 @@ create_file_safely(const char *filename, unsigned int truncate_file)
int
pidfile_create(const char *filename)
{
int fildes;
FILE *fd;
int fildes;
FILE *fd;
/*
* Create a new file
*/
if ((fildes = create_file_safely(filename, TRUE)) < 0)
return fildes;
/*
* Create a new file
*/
if ((fildes = create_file_safely(filename, TRUE)) < 0)
return fildes;
/*
* Open a stdio file over the low-level one.
*/
if ((fd = fdopen(fildes, "w")) == NULL) {
fprintf(stderr,
"%s: Could not write PID file %s: %s.",
PACKAGE, filename, strerror(errno));
close(fildes);
unlink(filename);
return -EIO;
}
/*
* Open a stdio file over the low-level one.
*/
if ((fd = fdopen(fildes, "w")) == NULL) {
fprintf(stderr,
"%s: Could not write PID file %s: %s.",
PACKAGE, filename, strerror(errno));
close(fildes);
unlink(filename);
return -EIO;
}
fprintf(fd, "%ld\n", (long) getpid());
fclose(fd);
return 0;
fprintf(fd, "%ld\n", (long)getpid());
fclose(fd);
return 0;
}

View File

@ -1,4 +1,4 @@
/* $Id: utils.h,v 1.24 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: utils.h,v 1.25 2005-08-15 03:54:31 rjkaes Exp $
*
* See 'utils.h' for a detailed description.
*
@ -25,7 +25,7 @@
struct conn_s;
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 create_file_safely(const char *filename, unsigned int truncate_file);

View File

@ -1,4 +1,4 @@
/* $Id: vector.c,v 1.12 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: vector.c,v 1.13 2005-08-15 03:54:31 rjkaes Exp $
*
* A vector implementation. The vector can be of an arbitrary length, and
* the data for each entry is an lump of data (the size is stored in the
@ -34,16 +34,16 @@
* count of the number of entries (or how long the vector is.)
*/
struct vectorentry_s {
void *data;
size_t len;
void *data;
size_t len;
struct vectorentry_s *next;
struct vectorentry_s *next;
};
struct vector_s {
size_t num_entries;
struct vectorentry_s *head;
struct vectorentry_s *tail;
size_t num_entries;
struct vectorentry_s *head;
struct vectorentry_s *tail;
};
/*
@ -56,16 +56,16 @@ struct vector_s {
vector_t
vector_create(void)
{
vector_t vector;
vector_t vector;
vector = safemalloc(sizeof(struct vector_s));
if (!vector)
return NULL;
vector = safemalloc(sizeof(struct vector_s));
if (!vector)
return NULL;
vector->num_entries = 0;
vector->head = vector->tail = NULL;
return vector;
vector->num_entries = 0;
vector->head = vector->tail = NULL;
return vector;
}
/*
@ -77,23 +77,23 @@ vector_create(void)
int
vector_delete(vector_t vector)
{
struct vectorentry_s *ptr, *next;
struct vectorentry_s *ptr, *next;
if (!vector)
return -EINVAL;
ptr = vector->head;
while (ptr) {
next = ptr->next;
safefree(ptr->data);
safefree(ptr);
if (!vector)
return -EINVAL;
ptr = next;
}
ptr = vector->head;
while (ptr) {
next = ptr->next;
safefree(ptr->data);
safefree(ptr);
safefree(vector);
ptr = next;
}
return 0;
safefree(vector);
return 0;
}
/*
@ -112,42 +112,42 @@ vector_delete(vector_t vector)
static int
vector_insert(vector_t vector, void *data, ssize_t len, int pos)
{
struct vectorentry_s *entry;
struct vectorentry_s *entry;
if (!vector || !data || len <= 0 ||
(pos != INSERT_PREPEND && pos != INSERT_APPEND))
return -EINVAL;
if (!vector || !data || len <= 0 ||
(pos != INSERT_PREPEND && pos != INSERT_APPEND))
return -EINVAL;
entry = safemalloc(sizeof(struct vectorentry_s));
if (!entry)
return -ENOMEM;
entry = safemalloc(sizeof(struct vectorentry_s));
if (!entry)
return -ENOMEM;
entry->data = safemalloc(len);
if (!entry->data) {
safefree(entry);
return -ENOMEM;
}
entry->data = safemalloc(len);
if (!entry->data) {
safefree(entry);
return -ENOMEM;
}
memcpy(entry->data, data, len);
entry->len = len;
entry->next = NULL;
memcpy(entry->data, data, len);
entry->len = len;
entry->next = NULL;
/* If there is no head or tail, create them */
if (!vector->head && !vector->tail)
vector->head = vector->tail = entry;
else if (pos == 0) {
/* prepend the entry */
entry->next = vector->head;
vector->head = entry;
} else {
/* append the entry */
vector->tail->next = entry;
vector->tail = entry;
}
vector->num_entries++;
/* If there is no head or tail, create them */
if (!vector->head && !vector->tail)
vector->head = vector->tail = entry;
else if (pos == 0) {
/* prepend the entry */
entry->next = vector->head;
vector->head = entry;
} else {
/* append the entry */
vector->tail->next = entry;
vector->tail = entry;
}
return 0;
vector->num_entries++;
return 0;
}
/*
@ -158,13 +158,13 @@ vector_insert(vector_t vector, void *data, ssize_t len, int pos)
int
vector_append(vector_t vector, void *data, ssize_t len)
{
return vector_insert(vector, data, len, INSERT_APPEND);
return vector_insert(vector, data, len, INSERT_APPEND);
}
int
vector_prepend(vector_t vector, void *data, ssize_t len)
{
return vector_insert(vector, data, len, INSERT_PREPEND);
return vector_insert(vector, data, len, INSERT_PREPEND);
}
/*
@ -175,26 +175,26 @@ vector_prepend(vector_t vector, void *data, ssize_t len)
* length of data if position is valid
*/
void *
vector_getentry(vector_t vector, size_t pos, size_t* size)
vector_getentry(vector_t vector, size_t pos, size_t * size)
{
struct vectorentry_s *ptr;
size_t loc;
struct vectorentry_s *ptr;
size_t loc;
if (!vector || pos < 0 || pos >= vector->num_entries)
return NULL;
if (!vector || pos < 0 || pos >= vector->num_entries)
return NULL;
loc = 0;
ptr = vector->head;
loc = 0;
ptr = vector->head;
while (loc != pos) {
ptr = ptr->next;
loc++;
}
while (loc != pos) {
ptr = ptr->next;
loc++;
}
if (size)
*size = ptr->len;
if (size)
*size = ptr->len;
return ptr->data;
return ptr->data;
}
/*
@ -206,8 +206,8 @@ vector_getentry(vector_t vector, size_t pos, size_t* size)
ssize_t
vector_length(vector_t vector)
{
if (!vector)
return -EINVAL;
if (!vector)
return -EINVAL;
return vector->num_entries;
return vector->num_entries;
}

View File

@ -1,4 +1,4 @@
/* $Id: vector.h,v 1.6 2005-07-12 17:39:44 rjkaes Exp $
/* $Id: vector.h,v 1.7 2005-08-15 03:54:31 rjkaes Exp $
*
* A vector implementation. The vector can be of an arbritrary length, and
* the data for each entry is an lump of data (the size is stored in the
@ -34,14 +34,14 @@ extern "C" {
* vector. Sure, it's a pointer, but the struct is hidden in the C file.
* So, just use the vector_t like it's a cookie. :)
*/
typedef struct vector_s *vector_t;
typedef struct vector_s *vector_t;
/*
* vector_create() takes no arguments.
* vector_delete() is self explanatory.
*/
extern vector_t vector_create(void);
extern int vector_delete(vector_t vector);
extern vector_t vector_create(void);
extern int vector_delete(vector_t vector);
/*
* When you insert a piece of data into the vector, the data will be
@ -51,8 +51,8 @@ extern int vector_delete(vector_t vector);
* Returns: negative on error
* 0 upon successful insert.
*/
extern int vector_append(vector_t vector, void *data, ssize_t len);
extern int vector_prepend(vector_t vector, void *data, ssize_t len);
extern int vector_append(vector_t vector, void *data, ssize_t len);
extern int vector_prepend(vector_t vector, void *data, ssize_t len);
/*
* A pointer to the data at position "pos" (zero based) is returned and the
@ -70,7 +70,8 @@ extern int vector_prepend(vector_t vector, void *data, ssize_t len);
* Returns: NULL on error
* valid pointer to data
*/
extern void* vector_getentry(vector_t vector, size_t pos, size_t* size);
extern void *vector_getentry(vector_t vector, size_t pos,
size_t * size);
/*
* Returns the number of enteries (or the length) of the vector.
@ -78,10 +79,9 @@ extern void* vector_getentry(vector_t vector, size_t pos, size_t* size);
* Returns: negative if vector is not valid
* positive length of vector otherwise
*/
extern ssize_t vector_length(vector_t vector);
extern ssize_t vector_length(vector_t vector);
#if defined(__cplusplus)
}
#endif /* C++ */
#endif /* _VECTOR_H */
#endif /* C++ */
#endif /* _VECTOR_H */