diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/acl.c | 229 | ||||
-rw-r--r-- | src/acl.h | 5 | ||||
-rw-r--r-- | src/anonymous.c | 36 | ||||
-rw-r--r-- | src/buffer.c | 340 | ||||
-rw-r--r-- | src/buffer.h | 6 | ||||
-rw-r--r-- | src/child.c | 553 | ||||
-rw-r--r-- | src/child.h | 12 | ||||
-rw-r--r-- | src/common.h | 12 | ||||
-rw-r--r-- | src/conffile.c | 449 | ||||
-rw-r--r-- | src/conffile.h | 4 | ||||
-rw-r--r-- | src/conns.c | 168 | ||||
-rw-r--r-- | src/conns.h | 98 | ||||
-rw-r--r-- | src/daemon.c | 50 | ||||
-rw-r--r-- | src/daemon.h | 4 | ||||
-rw-r--r-- | src/filter.c | 282 | ||||
-rw-r--r-- | src/filter.h | 6 | ||||
-rw-r--r-- | src/hashmap.c | 526 | ||||
-rw-r--r-- | src/hashmap.h | 36 | ||||
-rw-r--r-- | src/heap.c | 127 | ||||
-rw-r--r-- | src/heap.h | 16 | ||||
-rw-r--r-- | src/htmlerror.c | 342 | ||||
-rw-r--r-- | src/htmlerror.h | 9 | ||||
-rw-r--r-- | src/http_message.c | 314 | ||||
-rw-r--r-- | src/http_message.h | 15 | ||||
-rw-r--r-- | src/log.c | 187 | ||||
-rw-r--r-- | src/log.h | 6 | ||||
-rw-r--r-- | src/network.c | 438 | ||||
-rw-r--r-- | src/network.h | 6 | ||||
-rw-r--r-- | src/reqs.c | 2697 | ||||
-rw-r--r-- | src/sock.c | 302 | ||||
-rw-r--r-- | src/sock.h | 10 | ||||
-rw-r--r-- | src/stats.c | 171 | ||||
-rw-r--r-- | src/stats.h | 12 | ||||
-rw-r--r-- | src/text.c | 73 | ||||
-rw-r--r-- | src/text.h | 6 | ||||
-rw-r--r-- | src/tinyproxy.c | 547 | ||||
-rw-r--r-- | src/tinyproxy.h | 108 | ||||
-rw-r--r-- | src/utils.c | 296 | ||||
-rw-r--r-- | src/utils.h | 4 | ||||
-rw-r--r-- | src/vector.c | 166 | ||||
-rw-r--r-- | src/vector.h | 22 |
41 files changed, 4452 insertions, 4238 deletions
@@ -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; - - 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); - - freeaddrinfo(ressave); - - 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); - - /* - * 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; - } - - /* Indicate that no tests succeeded, so skip to next control. */ - return -1; + /* + * 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; + + 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); + + 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); + + /* + * 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; + } + + /* 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_NUMERIC: - if (ip[0] == '\0') continue; - perm = check_numeric_acl(acl, ip); - 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; + } /* * 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; } @@ -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 diff --git a/src/anonymous.c b/src/anonymous.c index 82ae41e..3c40a3a 100644 --- a/src/anonymous.c +++ b/src/anonymous.c @@ -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)); } diff --git a/src/buffer.c b/src/buffer.c index 0497fbc..a29cfbc 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -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; - - 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); - - /* - * 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; - } - - buffptr->size += length; - - return 0; + struct bufline_s *newline; + + 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); + + /* + * 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; + } + + buffptr->size += length; + + 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]; - - assert(fd >= 0); - assert(buffptr != NULL); - - /* - * Don't allow the buffer to grow larger than MAXBUFFSIZE - */ - if (buffptr->size >= MAXBUFFSIZE) - return 0; - - 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; - } - - return bytesin; - } else { - if (bytesin == 0) { - /* connection was closed by client */ - return -1; - } else { - switch (errno) { + ssize_t bytesin; + unsigned char buffer[READ_BUFFER_SIZE]; + + assert(fd >= 0); + assert(buffptr != NULL); + + /* + * Don't allow the buffer to grow larger than MAXBUFFSIZE + */ + if (buffptr->size >= MAXBUFFSIZE) + return 0; + + 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; + } + + 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; - - assert(fd >= 0); - assert(buffptr != NULL); - - 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); - - 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) { + ssize_t bytessent; + struct bufline_s *line; + + assert(fd >= 0); + assert(buffptr != NULL); + + 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); + + 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) { #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; + } + } } diff --git a/src/buffer.h b/src/buffer.h index bb43d72..706743e 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -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_ */ diff --git a/src/child.c b/src/child.c index c4a19b2..eb29a78 100644 --- a/src/child.c +++ b/src/child.c @@ -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; - - while ((rc = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0) { - if (errno == EINTR) - continue; - else - return; - } + int rc; + + 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; - } - - return 0; + 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; } /* * 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; - } - - ptr->status = T_CONNECTED; - - SERVER_DEC(); - - handle_connection(connfd); - 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; - } - } - - 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(); - } - - SERVER_INC(); - } - - ptr->status = T_EMPTY; - - safefree(cliaddr); - exit(0); + /* + * 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; + + SERVER_DEC(); + + handle_connection(connfd); + 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; + } + } + + 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(); + } + + SERVER_INC(); + } + + ptr->status = T_EMPTY; + + 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 */ - - /* - * 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; + pid_t pid; + + if ((pid = fork()) > 0) + return pid; /* parent */ + + /* + * 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; - - /* - * 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; - } - - 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(); - - 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.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); - - SERVER_INC(); - } - } - - log_message(LOG_INFO, "Finished creating all children."); - - return 0; + 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; + } + + 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; + + /* + * 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; + } + + 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]); + + 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(); + } + } + + log_message(LOG_INFO, "Finished creating all children."); + + return 0; } /* @@ -356,59 +363,61 @@ child_pool_create(void) void child_main_loop(void) { - unsigned int i; - - 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); - - 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"); - - child_ptr[i].status = T_EMPTY; - break; - } - - SERVER_INC(); - - break; - } - } - } else { - SERVER_COUNT_UNLOCK(); - } - - sleep(5); - - /* Handle log rotation if it was requested */ - if (received_sighup) { - truncate_log_file(); + unsigned int i; + + 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); + + 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"); + + child_ptr[i].status = T_EMPTY; + break; + } + + SERVER_INC(); + + break; + } + } + } else { + SERVER_COUNT_UNLOCK(); + } + + sleep(5); + + /* 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 */ - - received_sighup = FALSE; - } - } + if (config.filter) { + filter_destroy(); + filter_init(); + } + log_message(LOG_NOTICE, "Re-reading filter file."); +#endif /* FILTER_ENABLE */ + + 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); } diff --git a/src/child.h b/src/child.h index d2f195f..41210f3 100644 --- a/src/child.h +++ b/src/child.h @@ -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); diff --git a/src/common.h b/src/common.h index b1cd452..5100bcc 100644 --- a/src/common.h +++ b/src/common.h @@ -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. diff --git a/src/conffile.c b/src/conffile.c index 54c5c50..453942f 100644 --- a/src/conffile.c +++ b/src/conffile.c @@ -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(); +} -#endif +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 diff --git a/src/conffile.h b/src/conffile.h index 518bf3b..5aef2ca 100644 --- a/src/conffile.h +++ b/src/conffile.h @@ -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 diff --git a/src/conns.c b/src/conns.c index 82cb457..627a00c 100644 --- a/src/conns.c +++ b/src/conns.c @@ -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); - - 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->request_line) - safefree(connptr->request_line); - - if (connptr->error_variables) - hashmap_delete(connptr->error_variables); - - 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); + 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->cbuffer) + delete_buffer(connptr->cbuffer); + if (connptr->sbuffer) + delete_buffer(connptr->sbuffer); + + if (connptr->request_line) + safefree(connptr->request_line); + + if (connptr->error_variables) + hashmap_delete(connptr->error_variables); + + 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); #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); } diff --git a/src/conns.h b/src/conns.h index 0f6a9e1..1c4c9a1 100644 --- a/src/conns.h +++ b/src/conns.h @@ -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; - - int error_number; - char *error_string; - - /* 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 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; + * This structure stores key -> value mappings for substitution + * in the error HTML files. + */ + hashmap_t error_variables; + + int error_number; + char *error_string; + + /* 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 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; #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 diff --git a/src/daemon.c b/src/daemon.c index f917283..9d4379a 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -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; } diff --git a/src/daemon.h b/src/daemon.h index a7e0944..2b7432e 100644 --- a/src/daemon.h +++ b/src/daemon.h @@ -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 diff --git a/src/filter.c b/src/filter.c index 161cc66..4f25c74 100644 --- a/src/filter.c +++ b/src/filter.c @@ -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; - - 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; - - 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 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; - } - - 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; - } - } + 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; + + 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'; + + /* skip leading whitespace */ + s = buf; + while (*s && isspace((unsigned char)*s)) + s++; + + /* 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; + } + + 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; + } + } } /* unlink the list */ void filter_destroy(void) { - 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; - } + 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; + } } /* Return 0 to allow, non-zero to block */ int filter_domain(const char *host) { - struct filter_list *p; - int result; - - 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); - - 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; + struct filter_list *p; + int result; + + 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); + + 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; } /* returns 0 to allow, non-zero to block */ int filter_url(const char *url) { - struct filter_list *p; - int result; - - 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); - - 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; + struct filter_list *p; + int result; + + 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); + + 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; } /* @@ -205,5 +209,5 @@ filter_url(const char *url) void filter_set_default_policy(filter_policy_t policy) { - default_policy = policy; + default_policy = policy; } diff --git a/src/filter.h b/src/filter.h index 6785b08..6db806f 100644 --- a/src/filter.h +++ b/src/filter.h @@ -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); diff --git a/src/hashmap.c b/src/hashmap.c index 15e5ffe..c060c60 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -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; - - 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; - - hash += tolower(*key) + bit; - } - - /* Keep the hash within the table limits */ - return hash % size; + 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; + + 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; - ptr = bucket->head; - while (ptr) { - nextptr = ptr->next; - - safefree(ptr->key); - safefree(ptr->data); - safefree(ptr); + safefree(ptr->key); + safefree(ptr->data); + safefree(ptr); - ptr = nextptr; - } + ptr = nextptr; + } - return 0; + 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; + + if (map == NULL) + return -EINVAL; - for (i = 0; i != map->size; i++) { - if (map->buckets[i].head != NULL) { - delete_hashbucket(&map->buckets[i]); - } - } + for (i = 0; i != map->size; i++) { + if (map->buckets[i].head != NULL) { + delete_hashbucket(&map->buckets[i]); + } + } - safefree(map->buckets); - safefree(map); + safefree(map->buckets); + safefree(map); - return 0; + 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; - - 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; - - 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; - - 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->key = key_copy; - ptr->data = data_copy; - ptr->len = len; + struct hashentry_s *ptr; + int hash; + char *key_copy; + void *data_copy; + + 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; + + 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; + + 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->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; - - assert(map != NULL); - assert(key != NULL); - - 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; - - while (ptr) { - if (strcasecmp(ptr->key, key) == 0) { - /* Found it, so return the current count */ - return iter; - } - - iter++; - ptr = ptr->next; - } - } - - return iter; + unsigned int i; + hashmap_iter iter = 0; + struct hashentry_s *ptr; + + assert(map != NULL); + assert(key != NULL); + + 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; + + while (ptr) { + if (strcasecmp(ptr->key, key) == 0) { + /* Found it, so return the current count */ + return iter; + } + + iter++; + ptr = ptr->next; + } + } + + 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; - - 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; - - 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++; - } - } - - return -EFAULT; + 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); + + 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; + } + + ptr = ptr->next; + count++; + } + } + + 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; - if (!map || !key || !data) - 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; - while (ptr) { - if (strcasecmp(ptr->key, key) == 0) { - *data = ptr->data; - return ptr->len; - } + while (ptr) { + if (strcasecmp(ptr->key, key) == 0) { + *data = ptr->data; + return ptr->len; + } - ptr = ptr->next; - } + ptr = ptr->next; + } - return 0; + 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; - - if (map == NULL || key == NULL) - return -EINVAL; - - 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. - */ + int hash; + struct hashentry_s *ptr, *next; + short int deleted = 0; + + if (map == NULL || key == NULL) + return -EINVAL; + + 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. + */ 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; } diff --git a/src/hashmap.h b/src/hashmap.h index 69fe21a..aa376d4 100644 --- a/src/hashmap.h +++ b/src/hashmap.h @@ -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 */ @@ -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; } - @@ -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 diff --git a/src/htmlerror.c b/src/htmlerror.c index d02eae8..afc1e63 100644 --- a/src/htmlerror.c +++ b/src/htmlerror.c @@ -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; - - 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); +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); } 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"; - - return(write_message(connptr->client_fd, headers, - code, message, - PACKAGE, VERSION)); +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)); } /* @@ -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"; - - 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)); - - ret = send_html_file(infile, connptr); - fclose(infile); - return(ret); + 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); + + 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); } /* @@ -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); - - 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_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)); + + 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 *); - while((key = va_arg(ap, char *))) { - val = va_arg(ap, char *); - if(add_error_variable(connptr, key, val) == -1) { - va_end(ap); - return(-1); - } - } + if (add_error_variable(connptr, key, val) == -1) { + va_end(ap); + return (-1); + } + } - connptr->error_number = number; - connptr->error_string = safestrdup(message); + connptr->error_number = number; + connptr->error_string = safestrdup(message); - va_end(ap); + va_end(ap); - return(add_standard_vars(connptr)); + return (add_standard_vars(connptr)); } diff --git a/src/htmlerror.h b/src/htmlerror.h index 63202b4..1dca430 100644 --- a/src/htmlerror.h +++ b/src/htmlerror.h @@ -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 */ diff --git a/src/http_message.c b/src/http_message.c index 8e454fb..35bfa1c 100644 --- a/src/http_message.c +++ b/src/http_message.c @@ -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; - - /* Body of the message (most likely an HTML message) */ - struct { - const char* text; - size_t length; - } body; + /* 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; + + /* 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; - - return 1; + 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; } /* 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; - - 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.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; - } - - return msg; + http_message_t msg; + int ret; + + 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.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; + } + + 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; - - msg->response.code = response_code; - msg->response.string = response_string; - - return 0; + /* 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; + + 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; - - msg->body.text = body; - msg->body.length = len; - - return 0; + /* 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; + + 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; - - /* 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; - - /* 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; - } - - /* - * 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; + 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; + + /* + * 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]; + + /* 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; + + 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; } diff --git a/src/http_message.h b/src/http_message.h index deaf9d5..fe8c798 100644 --- a/src/http_message.h +++ b/src/http_message.h @@ -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_ */ @@ -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; } @@ -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); diff --git a/src/network.c b/src/network.c index 733a2b6..5a78a42 100644 --- a/src/network.c +++ b/src/network.c @@ -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; - - if ((buf = safemalloc(size)) == NULL) - return -1; - - 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; - - /* 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 (safe_write(fd, buf, n) < 0) { - safefree(buf); - return -1; - } - - safefree(buf); - return 0; + 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; + + 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; + + /* 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 (safe_write(fd, buf, n) < 0) { + safefree(buf); + return -1; + } + + 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 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; - - first_line = safecalloc(sizeof(struct read_lines_s), 1); - if (!first_line) - return -ENOMEM; - - line_ptr = first_line; - - 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; - - 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; - } - - line_ptr->data = safemalloc(diff); - if (!line_ptr->data) { - ret = -ENOMEM; - goto CLEANUP; - } - - recv(fd, line_ptr->data, diff, 0); - line_ptr->len = diff; - - 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; - } - - *whole_buffer = safemalloc(whole_buffer_len + 1); - if (!*whole_buffer) { - ret = -ENOMEM; - goto CLEANUP; - } - - *(*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; - - line_ptr = line_ptr->next; - } - - ret = whole_buffer_len; + ssize_t whole_buffer_len; + char buffer[SEGMENT_LEN]; + char *ptr; + + 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; + + first_line = safecalloc(sizeof(struct read_lines_s), 1); + if (!first_line) + return -ENOMEM; + + line_ptr = first_line; + + 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; + + 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; + } + + line_ptr->data = safemalloc(diff); + if (!line_ptr->data) { + ret = -ENOMEM; + goto CLEANUP; + } + + recv(fd, line_ptr->data, diff, 0); + line_ptr->len = diff; + + 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; + } + + *whole_buffer = safemalloc(whole_buffer_len + 1); + if (!*whole_buffer) { + ret = -ENOMEM; + goto CLEANUP; + } + + *(*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; + + line_ptr = line_ptr->next; + } + + 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); - - return ret; + 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; } /* * 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 */ - - 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; - } - - return buf; + 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; + } + + 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; - - 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); - } - - /* - * "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); + char buf[24], tmp[24]; /* IPv4->IPv6 = ::FFFF:xxx.xxx.xxx.xxx\0 */ + int n; + + 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); + } + + /* + * "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); } diff --git a/src/network.h b/src/network.h index 68b5381..a1d44bd 100644 --- a/src/network.h +++ b/src/network.h @@ -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 @@ -1,4 +1,4 @@ -/* $Id: reqs.c,v 1.119 2005-07-12 17:39:44 rjkaes Exp $ +/* $Id: reqs.c,v 1.120 2005-08-15 03:54:31 rjkaes Exp $ * * This is where all the work in tinyproxy is actually done. Incoming * connections have a new child created for them. The child then @@ -78,13 +78,13 @@ static vector_t ports_allowed_by_connect = NULL; * This structure holds the information pulled from a URL request. */ struct request_s { - char *method; - char *protocol; + char *method; + char *protocol; - char *host; - uint16_t port; + char *host; + uint16_t port; - char *path; + char *path; }; /* @@ -94,16 +94,18 @@ struct request_s { void add_connect_port_allowed(int port) { - if (!ports_allowed_by_connect) { - ports_allowed_by_connect = vector_create(); - if (!ports_allowed_by_connect) { - log_message(LOG_WARNING, "Could not create a list of allowed CONNECT ports"); - return; - } - } - - log_message(LOG_INFO, "Adding Port [%d] to the list allowed by CONNECT", port); - vector_append(ports_allowed_by_connect, (void **)&port, sizeof(port)); + if (!ports_allowed_by_connect) { + ports_allowed_by_connect = vector_create(); + if (!ports_allowed_by_connect) { + log_message(LOG_WARNING, + "Could not create a list of allowed CONNECT ports"); + return; + } + } + + log_message(LOG_INFO, "Adding Port [%d] to the list allowed by CONNECT", + port); + vector_append(ports_allowed_by_connect, (void **)&port, sizeof(port)); } /* @@ -115,23 +117,23 @@ add_connect_port_allowed(int port) static int check_allowed_connect_ports(int port) { - ssize_t i; - int *data; + ssize_t i; + int *data; /* * A port list is REQUIRED for a CONNECT request to function * properly. This closes a potential security hole. */ - if (!ports_allowed_by_connect) - return 0; + if (!ports_allowed_by_connect) + return 0; - for (i = 0; i != vector_length(ports_allowed_by_connect); ++i) { - data = vector_getentry(ports_allowed_by_connect, i, NULL); + for (i = 0; i != vector_length(ports_allowed_by_connect); ++i) { + data = vector_getentry(ports_allowed_by_connect, i, NULL); if (data && *data == port) - return 1; - } + return 1; + } - return 0; + return 0; } /* @@ -142,35 +144,35 @@ check_allowed_connect_ports(int port) static int read_request_line(struct conn_s *connptr) { - ssize_t len; + ssize_t len; retry: - len = readline(connptr->client_fd, &connptr->request_line); - if (len <= 0) { - log_message(LOG_ERR, - "read_request_line: Client (file descriptor: %d) closed socket before read.", - connptr->client_fd); - - return -1; - } - - /* - * Strip the new line and carriage return from the string. - */ - if (chomp(connptr->request_line, len) == len) { - /* - * If the number of characters removed is the same as the - * length then it was a blank line. Free the buffer and - * try again (since we're looking for a request line.) - */ - safefree(connptr->request_line); - goto retry; - } - - log_message(LOG_CONN, "Request (file descriptor %d): %s", - connptr->client_fd, connptr->request_line); - - return 0; + len = readline(connptr->client_fd, &connptr->request_line); + if (len <= 0) { + log_message(LOG_ERR, + "read_request_line: Client (file descriptor: %d) closed socket before read.", + connptr->client_fd); + + return -1; + } + + /* + * Strip the new line and carriage return from the string. + */ + if (chomp(connptr->request_line, len) == len) { + /* + * If the number of characters removed is the same as the + * length then it was a blank line. Free the buffer and + * try again (since we're looking for a request line.) + */ + safefree(connptr->request_line); + goto retry; + } + + log_message(LOG_CONN, "Request (file descriptor %d): %s", + connptr->client_fd, connptr->request_line); + + return 0; } /* @@ -179,18 +181,18 @@ read_request_line(struct conn_s *connptr) static void free_request_struct(struct request_s *request) { - if (!request) - return; + if (!request) + return; - safefree(request->method); - safefree(request->protocol); + safefree(request->method); + safefree(request->protocol); - if (request->host) - safefree(request->host); - if (request->path) - safefree(request->path); + if (request->host) + safefree(request->host); + if (request->path) + safefree(request->path); - safefree(request); + safefree(request); } /* @@ -198,9 +200,9 @@ free_request_struct(struct request_s *request) * it off. */ static void -strip_username_password(char* host) +strip_username_password(char *host) { - char *p; + char *p; assert(host); assert(strlen(host) > 0); @@ -213,7 +215,7 @@ strip_username_password(char* host) * until the NUL to the beginning of the host buffer. */ p++; - while (*p) + while (*p) *host++ = *p++; *host = '\0'; } @@ -223,19 +225,19 @@ strip_username_password(char* host) * it off and set proper port variable i.e. for www.host.com:8001 */ static int -strip_return_port(char* host) +strip_return_port(char *host) { - char *ptr1; - int port; + char *ptr1; + int port; - ptr1 = strchr(host, ':'); - if (ptr1 == NULL) - return 0; + ptr1 = strchr(host, ':'); + if (ptr1 == NULL) + return 0; - *ptr1++ = '\0'; - if (sscanf(ptr1, "%d", &port) != 1) /* one conversion required */ - return 0; - return port; + *ptr1++ = '\0'; + if (sscanf(ptr1, "%d", &port) != 1) /* one conversion required */ + return 0; + return port; } /* @@ -245,42 +247,42 @@ strip_return_port(char* host) static int extract_http_url(const char *url, struct request_s *request) { - char *p; - int len; - int port; - - /* Split the URL on the slash to separate host from path */ - p = strchr(url, '/'); - if (p != NULL) { - len = p - url; - request->host = safemalloc(len + 1); - memcpy(request->host, url, len); - request->host[len] = '\0'; - request->path = safestrdup(p); - } else { - request->host = safestrdup(url); - request->path = safestrdup("/"); - } - - if (!request->host || !request->path) - goto ERROR_EXIT; - - /* Remove the username/password if they're present */ - strip_username_password(request->host); - - /* Find a proper port in www.site.com:8001 URLs */ - port = strip_return_port(request->host); - request->port = (port != 0) ? port : HTTP_PORT; - - return 0; - - ERROR_EXIT: - if (request->host) - safefree(request->host); - if (request->path) - safefree(request->path); - - return -1; + char *p; + int len; + int port; + + /* Split the URL on the slash to separate host from path */ + p = strchr(url, '/'); + if (p != NULL) { + len = p - url; + request->host = safemalloc(len + 1); + memcpy(request->host, url, len); + request->host[len] = '\0'; + request->path = safestrdup(p); + } else { + request->host = safestrdup(url); + request->path = safestrdup("/"); + } + + if (!request->host || !request->path) + goto ERROR_EXIT; + + /* Remove the username/password if they're present */ + strip_username_password(request->host); + + /* Find a proper port in www.site.com:8001 URLs */ + port = strip_return_port(request->host); + request->port = (port != 0) ? port : HTTP_PORT; + + return 0; + + ERROR_EXIT: + if (request->host) + safefree(request->host); + if (request->path) + safefree(request->path); + + return -1; } /* @@ -289,24 +291,24 @@ extract_http_url(const char *url, struct request_s *request) static int extract_ssl_url(const char *url, struct request_s *request) { - request->host = safemalloc(strlen(url) + 1); - if (!request->host) - return -1; - - if (sscanf(url, "%[^:]:%hu", request->host, &request->port) == 2) ; - else if (sscanf(url, "%s", request->host) == 1) - request->port = HTTP_PORT_SSL; - else { - log_message(LOG_ERR, "extract_ssl_url: Can't parse URL."); - - safefree(request->host); - return -1; - } + request->host = safemalloc(strlen(url) + 1); + if (!request->host) + return -1; + + if (sscanf(url, "%[^:]:%hu", request->host, &request->port) == 2) ; + else if (sscanf(url, "%s", request->host) == 1) + request->port = HTTP_PORT_SSL; + else { + log_message(LOG_ERR, "extract_ssl_url: Can't parse URL."); + + safefree(request->host); + return -1; + } - /* Remove the username/password if they're present */ - strip_username_password(request->host); + /* Remove the username/password if they're present */ + strip_username_password(request->host); - return 0; + return 0; } #ifdef TRANSPARENT_PROXY @@ -316,21 +318,21 @@ extract_ssl_url(const char *url, struct request_s *request) static int build_url(char **url, const char *host, int port, const char *path) { - int len; + int len; - assert(url != NULL); - assert(host != NULL); - assert(port > 0 && port < 32768); - assert(path != NULL); + assert(url != NULL); + assert(host != NULL); + assert(port > 0 && port < 32768); + assert(path != NULL); - len = strlen(host) + strlen(path) + 14; - *url = safemalloc(len); - if (*url == NULL) - return -1; + len = strlen(host) + strlen(path) + 14; + *url = safemalloc(len); + if (*url == NULL) + return -1; - return snprintf(*url, len, "http://%s:%d%s", host, port, path); + return snprintf(*url, len, "http://%s:%d%s", host, port, path); } -#endif /* TRANSPARENT_PROXY */ +#endif /* TRANSPARENT_PROXY */ #ifdef UPSTREAM_SUPPORT /* @@ -339,99 +341,107 @@ build_url(char **url, const char *host, int port, const char *path) void upstream_add(const char *host, int port, const char *domain) { - char *ptr; - struct upstream *up = safemalloc(sizeof (struct upstream)); - - if (!up) { - log_message(LOG_ERR, "Unable to allocate memory in upstream_add()"); - return; - } - - up->host = up->domain = NULL; - up->ip = up->mask = 0; - - if (domain == NULL) { - if (!host || host[0] == '\0' || port < 1) { - log_message(LOG_WARNING, "Nonsense upstream rule: invalid host or port"); - goto upstream_cleanup; - } - - up->host = safestrdup(host); - up->port = port; - - log_message(LOG_INFO, "Added upstream %s:%d for [default]", host, port); - } else if (host == NULL) { - if (!domain || domain[0] == '\0') { - log_message(LOG_WARNING, "Nonsense no-upstream rule: empty domain"); - goto upstream_cleanup; - } - - ptr = strchr(domain, '/'); - if (ptr) { - struct in_addr addrstruct; - - *ptr = '\0'; - if (inet_aton(domain, &addrstruct) != 0) { - up->ip = ntohl(addrstruct.s_addr); - *ptr++ = '/'; - - if (strchr(ptr, '.')) { - if (inet_aton(ptr, &addrstruct) != 0) - up->mask = ntohl(addrstruct.s_addr); - } else { - up->mask = ~((1 << (32 - atoi(ptr))) - 1); - } - } - } else { - up->domain = safestrdup(domain); - } - - log_message(LOG_INFO, "Added no-upstream for %s", domain); - } else { - if (!host || host[0] == '\0' || port < 1 || !domain || domain == '\0') { - log_message(LOG_WARNING, "Nonsense upstream rule: invalid parameters"); - goto upstream_cleanup; - } - - up->host = safestrdup(host); - up->port = port; - up->domain = safestrdup(domain); - - log_message(LOG_INFO, "Added upstream %s:%d for %s", - host, port, domain); - } - - if (!up->domain && !up->ip) { /* always add default to end */ - struct upstream *tmp = config.upstream_list; - - while (tmp) { - if (!tmp->domain && !tmp->ip) { - log_message(LOG_WARNING, - "Duplicate default upstream"); - goto upstream_cleanup; - } - - if (!tmp->next) { - up->next = NULL; - tmp->next = up; - return; - } - - tmp = tmp->next; - } - } - - up->next = config.upstream_list; - config.upstream_list = up; - - return; - -upstream_cleanup: - safefree(up->host); - safefree(up->domain); - safefree(up); - - return; + char *ptr; + struct upstream *up = safemalloc(sizeof(struct upstream)); + + if (!up) { + log_message(LOG_ERR, + "Unable to allocate memory in upstream_add()"); + return; + } + + up->host = up->domain = NULL; + up->ip = up->mask = 0; + + if (domain == NULL) { + if (!host || host[0] == '\0' || port < 1) { + log_message(LOG_WARNING, + "Nonsense upstream rule: invalid host or port"); + goto upstream_cleanup; + } + + up->host = safestrdup(host); + up->port = port; + + log_message(LOG_INFO, "Added upstream %s:%d for [default]", + host, port); + } else if (host == NULL) { + if (!domain || domain[0] == '\0') { + log_message(LOG_WARNING, + "Nonsense no-upstream rule: empty domain"); + goto upstream_cleanup; + } + + ptr = strchr(domain, '/'); + if (ptr) { + struct in_addr addrstruct; + + *ptr = '\0'; + if (inet_aton(domain, &addrstruct) != 0) { + up->ip = ntohl(addrstruct.s_addr); + *ptr++ = '/'; + + if (strchr(ptr, '.')) { + if (inet_aton(ptr, &addrstruct) != 0) + up->mask = + ntohl(addrstruct.s_addr); + } else { + up->mask = + ~((1 << (32 - atoi(ptr))) - 1); + } + } + } else { + up->domain = safestrdup(domain); + } + + log_message(LOG_INFO, "Added no-upstream for %s", domain); + } else { + if (!host || host[0] == '\0' || port < 1 || !domain + || domain == '\0') { + log_message(LOG_WARNING, + "Nonsense upstream rule: invalid parameters"); + goto upstream_cleanup; + } + + up->host = safestrdup(host); + up->port = port; + up->domain = safestrdup(domain); + + log_message(LOG_INFO, "Added upstream %s:%d for %s", + host, port, domain); + } + + if (!up->domain && !up->ip) { /* always add default to end */ + struct upstream *tmp = config.upstream_list; + + while (tmp) { + if (!tmp->domain && !tmp->ip) { + log_message(LOG_WARNING, + "Duplicate default upstream"); + goto upstream_cleanup; + } + + if (!tmp->next) { + up->next = NULL; + tmp->next = up; + return; + } + + tmp = tmp->next; + } + } + + up->next = config.upstream_list; + config.upstream_list = up; + + return; + + upstream_cleanup: + safefree(up->host); + safefree(up->domain); + safefree(up); + + return; } /* @@ -440,50 +450,50 @@ upstream_cleanup: static struct upstream * upstream_get(char *host) { - struct upstream *up = config.upstream_list; + struct upstream *up = config.upstream_list; - in_addr_t my_ip = INADDR_NONE; + in_addr_t my_ip = INADDR_NONE; - while (up) { - if (up->domain) { - if (strcasecmp(host, up->domain) == 0) - break; /* exact match */ + while (up) { + if (up->domain) { + if (strcasecmp(host, up->domain) == 0) + break; /* exact match */ - if (up->domain[0] == '.') { - char *dot = strchr(host, '.'); + if (up->domain[0] == '.') { + char *dot = strchr(host, '.'); - if (!dot && !up->domain[1]) - break; /* local host matches "." */ + if (!dot && !up->domain[1]) + break; /* local host matches "." */ - while (dot && strcasecmp(dot, up->domain)) - dot = strchr(dot+1, '.'); + while (dot && strcasecmp(dot, up->domain)) + dot = strchr(dot + 1, '.'); - if (dot) - break; /* subdomain match */ - } - } else if (up->ip) { - if (my_ip == INADDR_NONE) - my_ip = ntohl(inet_addr(host)); + if (dot) + break; /* subdomain match */ + } + } else if (up->ip) { + if (my_ip == INADDR_NONE) + my_ip = ntohl(inet_addr(host)); - if ((my_ip & up->mask) == up->ip) - break; - } else { - break; /* No domain or IP, default upstream */ - } + if ((my_ip & up->mask) == up->ip) + break; + } else { + break; /* No domain or IP, default upstream */ + } - up = up->next; - } + up = up->next; + } - if (up && (!up->host || !up->port)) - up = NULL; + if (up && (!up->host || !up->port)) + up = NULL; - if (up) - log_message(LOG_INFO, "Found proxy %s:%d for %s", - up->host, up->port, host); - else - log_message(LOG_INFO, "No proxy for %s", host); + if (up) + log_message(LOG_INFO, "Found proxy %s:%d for %s", + up->host, up->port, host); + else + log_message(LOG_INFO, "No proxy for %s", host); - return up; + return up; } #endif @@ -494,40 +504,47 @@ upstream_get(char *host) void reversepath_add(const char *path, const char *url) { - struct reversepath *reverse; + struct reversepath *reverse; - if (url == NULL) { - log_message(LOG_WARNING, "Illegal reverse proxy rule: missing url"); - return; - } + if (url == NULL) { + log_message(LOG_WARNING, + "Illegal reverse proxy rule: missing url"); + return; + } - if (!strstr(url, "://")) { - log_message(LOG_WARNING, - "Skipping reverse proxy rule: '%s' is not a valid url", url); - return; - } + if (!strstr(url, "://")) { + log_message(LOG_WARNING, + "Skipping reverse proxy rule: '%s' is not a valid url", + url); + return; + } - if (path && *path != '/') { - log_message(LOG_WARNING, - "Skipping reverse proxy rule: path '%s' doesn't start with a /", path); - return; - } + if (path && *path != '/') { + log_message(LOG_WARNING, + "Skipping reverse proxy rule: path '%s' doesn't start with a /", + path); + return; + } - if (!(reverse = safemalloc(sizeof (struct reversepath)))) { - log_message(LOG_ERR, "Unable to allocate memory in reversepath_add()"); - return; - } + if (!(reverse = safemalloc(sizeof(struct reversepath)))) { + log_message(LOG_ERR, + "Unable to allocate memory in reversepath_add()"); + return; + } - if (!path) reverse->path = safestrdup("/"); - else reverse->path = safestrdup(path); + if (!path) + reverse->path = safestrdup("/"); + else + reverse->path = safestrdup(path); - reverse->url = safestrdup(url); + reverse->url = safestrdup(url); - reverse->next = config.reversepath_list; - config.reversepath_list = reverse; + reverse->next = config.reversepath_list; + config.reversepath_list = reverse; - log_message(LOG_INFO, - "Added reverse proxy rule: %s -> %s", reverse->path, reverse->url); + log_message(LOG_INFO, + "Added reverse proxy rule: %s -> %s", reverse->path, + reverse->url); } /* @@ -536,16 +553,16 @@ reversepath_add(const char *path, const char *url) static struct reversepath * reversepath_get(char *url) { - struct reversepath *reverse = config.reversepath_list; + struct reversepath *reverse = config.reversepath_list; - while (reverse) { - if (strstr(url, reverse->path) == url) - return reverse; + while (reverse) { + if (strstr(url, reverse->path) == url) + return reverse; - reverse = reverse->next; - } + reverse = reverse->next; + } - return NULL; + return NULL; } #endif @@ -555,20 +572,20 @@ reversepath_get(char *url) static int establish_http_connection(struct conn_s *connptr, struct request_s *request) { - char portbuff[7]; - - /* Build a port string if it's not a standard port */ - if (request->port != HTTP_PORT && request->port != HTTP_PORT_SSL) - snprintf(portbuff, 7, ":%u", request->port); - else - portbuff[0] = '\0'; - - return write_message(connptr->server_fd, - "%s %s HTTP/1.0\r\n" \ - "Host: %s%s\r\n" \ - "Connection: close\r\n", - request->method, request->path, - request->host, portbuff); + char portbuff[7]; + + /* Build a port string if it's not a standard port */ + if (request->port != HTTP_PORT && request->port != HTTP_PORT_SSL) + snprintf(portbuff, 7, ":%u", request->port); + else + portbuff[0] = '\0'; + + return write_message(connptr->server_fd, + "%s %s HTTP/1.0\r\n" + "Host: %s%s\r\n" + "Connection: close\r\n", + request->method, request->path, + request->host, portbuff); } /* @@ -584,11 +601,10 @@ establish_http_connection(struct conn_s *connptr, struct request_s *request) static inline int send_ssl_response(struct conn_s *connptr) { - return write_message(connptr->client_fd, - "%s\r\n" \ - "%s\r\n" \ - "\r\n", - SSL_CONNECTION_RESPONSE, PROXY_AGENT); + return write_message(connptr->client_fd, + "%s\r\n" + "%s\r\n" + "\r\n", SSL_CONNECTION_RESPONSE, PROXY_AGENT); } /* @@ -598,42 +614,42 @@ send_ssl_response(struct conn_s *connptr) static struct request_s * process_request(struct conn_s *connptr, hashmap_t hashofheaders) { - char *url; - struct request_s *request; + char *url; + struct request_s *request; #ifdef REVERSE_SUPPORT - char *rewrite_url = NULL; - char *cookie = NULL; - char *cookieval; - struct reversepath *reverse; + char *rewrite_url = NULL; + char *cookie = NULL; + char *cookieval; + struct reversepath *reverse; #endif - int ret; + int ret; - size_t request_len; + size_t request_len; - /* NULL out all the fields so frees don't cause segfaults. */ - request = safecalloc(1, sizeof(struct request_s)); - if (!request) - return NULL; + /* NULL out all the fields so frees don't cause segfaults. */ + request = safecalloc(1, sizeof(struct request_s)); + if (!request) + return NULL; - request_len = strlen(connptr->request_line) + 1; + request_len = strlen(connptr->request_line) + 1; - request->method = safemalloc(request_len); - url = safemalloc(request_len); - request->protocol = safemalloc(request_len); + request->method = safemalloc(request_len); + url = safemalloc(request_len); + request->protocol = safemalloc(request_len); - if (!request->method || !url || !request->protocol) { - safefree(url); - free_request_struct(request); + if (!request->method || !url || !request->protocol) { + safefree(url); + free_request_struct(request); - return NULL; - } + return NULL; + } - ret = sscanf(connptr->request_line, "%[^ ] %[^ ] %[^ ]", + ret = sscanf(connptr->request_line, "%[^ ] %[^ ] %[^ ]", request->method, url, request->protocol); if (ret == 2 && !strcasecmp(request->method, "GET")) { - request->protocol[0] = 0; + request->protocol[0] = 0; /* Indicate that this is a HTTP/0.9 GET request */ connptr->protocol.major = 0; @@ -654,271 +670,283 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders) if (ret != 2) goto BAD_REQUEST_ERROR; } else { - BAD_REQUEST_ERROR: - log_message(LOG_ERR, - "process_request: Bad Request on file descriptor %d", - connptr->client_fd); - indicate_http_error(connptr, 400, "Bad Request", - "detail", "Request has an invalid format", - "url", url, - NULL); - - safefree(url); - free_request_struct(request); - - return NULL; - } - - if (!url) { - log_message(LOG_ERR, - "process_request: Null URL on file descriptor %d", - connptr->client_fd); - indicate_http_error(connptr, 400, "Bad Request", - "detail", "Request has an empty URL", - "url", url, - NULL); - - safefree(url); - free_request_struct(request); - - return NULL; - } + BAD_REQUEST_ERROR: + log_message(LOG_ERR, + "process_request: Bad Request on file descriptor %d", + connptr->client_fd); + indicate_http_error(connptr, 400, "Bad Request", + "detail", "Request has an invalid format", + "url", url, NULL); + + safefree(url); + free_request_struct(request); + + return NULL; + } + if (!url) { + log_message(LOG_ERR, + "process_request: Null URL on file descriptor %d", + connptr->client_fd); + indicate_http_error(connptr, 400, "Bad Request", + "detail", "Request has an empty URL", + "url", url, NULL); + + safefree(url); + free_request_struct(request); + + return NULL; + } #ifdef REVERSE_SUPPORT - /* - * Reverse proxy URL rewriting. - */ - if (config.reversepath_list != NULL) { - /* Reverse requests always start with a slash */ - if (*url == '/') { - /* First try locating the reverse mapping by request url */ - reverse = reversepath_get(url); - if (reverse) { - rewrite_url = safemalloc(strlen(url) + - strlen(reverse->url) + 1); - strcpy(rewrite_url, reverse->url); - strcat(rewrite_url, url + strlen(reverse->path)); - } else if (config.reversemagic && - hashmap_entry_by_key(hashofheaders, "cookie", - (void **)&cookie) > 0) { - - /* No match - try the magical tracking cookie next */ - if ((cookieval = strstr(cookie, REVERSE_COOKIE "=")) && - (reverse = reversepath_get(cookieval + - strlen(REVERSE_COOKIE) + 1))) { - - rewrite_url = safemalloc(strlen(url) + - strlen(reverse->url) + 1); - strcpy(rewrite_url, reverse->url); - strcat(rewrite_url, url + 1); - - log_message(LOG_INFO, - "Magical tracking cookie says: %s", - reverse->path); - } - } - } - - /* Forward proxy support off and no reverse path match found */ - if (config.reverseonly && !rewrite_url) { - log_message(LOG_ERR, "Bad request"); - indicate_http_error(connptr, 400, "Bad Request", - "detail", "Request has an invalid URL", - "url", url, - NULL); - - safefree(url); - free_request_struct(request); - - return NULL; - } - - log_message(LOG_CONN, "Rewriting URL: %s -> %s", - url, rewrite_url); - - safefree(url); - url = rewrite_url; - - /* Store reverse path so that the magical tracking cookie can be set */ - if (config.reversemagic) connptr->reversepath = safestrdup(reverse->path); - } + /* + * Reverse proxy URL rewriting. + */ + if (config.reversepath_list != NULL) { + /* Reverse requests always start with a slash */ + if (*url == '/') { + /* First try locating the reverse mapping by request url */ + reverse = reversepath_get(url); + if (reverse) { + rewrite_url = safemalloc(strlen(url) + + strlen(reverse->url) + + 1); + strcpy(rewrite_url, reverse->url); + strcat(rewrite_url, + url + strlen(reverse->path)); + } else if (config.reversemagic + && hashmap_entry_by_key(hashofheaders, + "cookie", + (void **)&cookie) > + 0) { + + /* No match - try the magical tracking cookie next */ + if ((cookieval = + strstr(cookie, REVERSE_COOKIE "=")) + && (reverse = + reversepath_get(cookieval + + strlen(REVERSE_COOKIE) + + 1))) { + + rewrite_url = safemalloc(strlen(url) + + strlen + (reverse-> + url) + 1); + strcpy(rewrite_url, reverse->url); + strcat(rewrite_url, url + 1); + + log_message(LOG_INFO, + "Magical tracking cookie says: %s", + reverse->path); + } + } + } + + /* Forward proxy support off and no reverse path match found */ + if (config.reverseonly && !rewrite_url) { + log_message(LOG_ERR, "Bad request"); + indicate_http_error(connptr, 400, "Bad Request", + "detail", + "Request has an invalid URL", "url", + url, NULL); + + safefree(url); + free_request_struct(request); + + return NULL; + } + + log_message(LOG_CONN, "Rewriting URL: %s -> %s", + url, rewrite_url); + + safefree(url); + url = rewrite_url; + + /* Store reverse path so that the magical tracking cookie can be set */ + if (config.reversemagic) + connptr->reversepath = safestrdup(reverse->path); + } #endif - if (strncasecmp(url, "http://", 7) == 0 - || (UPSTREAM_CONFIGURED() && strncasecmp(url, "ftp://", 6) == 0)) { - char *skipped_type = strstr(url, "//") + 2; - - if (extract_http_url(skipped_type, request) < 0) { - indicate_http_error(connptr, 400, "Bad Request", - "detail", "Could not parse URL", - "url", url, - NULL); - - safefree(url); - free_request_struct(request); - - return NULL; - } - } else if (strcmp(request->method, "CONNECT") == 0) { - if (extract_ssl_url(url, request) < 0) { - indicate_http_error(connptr, 400, "Bad Request", - "detail", "Could not parse URL", - "url", url, - NULL); - - safefree(url); - free_request_struct(request); - - return NULL; - } - - /* Verify that the port in the CONNECT method is allowed */ - if (!check_allowed_connect_ports(request->port)) { - indicate_http_error(connptr, 403, "Access violation", - "detail", "The CONNECT method not allowed " \ - "with the port you tried to use.", - "url", url, - NULL); - log_message(LOG_INFO, "Refused CONNECT method on port %d", - request->port); - - safefree(url); - free_request_struct(request); - - return NULL; - } - - connptr->connect_method = TRUE; - } else { + if (strncasecmp(url, "http://", 7) == 0 + || (UPSTREAM_CONFIGURED() && strncasecmp(url, "ftp://", 6) == 0)) { + char *skipped_type = strstr(url, "//") + 2; + + if (extract_http_url(skipped_type, request) < 0) { + indicate_http_error(connptr, 400, "Bad Request", + "detail", "Could not parse URL", + "url", url, NULL); + + safefree(url); + free_request_struct(request); + + return NULL; + } + } else if (strcmp(request->method, "CONNECT") == 0) { + if (extract_ssl_url(url, request) < 0) { + indicate_http_error(connptr, 400, "Bad Request", + "detail", "Could not parse URL", + "url", url, NULL); + + safefree(url); + free_request_struct(request); + + return NULL; + } + + /* Verify that the port in the CONNECT method is allowed */ + if (!check_allowed_connect_ports(request->port)) { + indicate_http_error(connptr, 403, "Access violation", + "detail", + "The CONNECT method not allowed " + "with the port you tried to use.", + "url", url, NULL); + log_message(LOG_INFO, + "Refused CONNECT method on port %d", + request->port); + + safefree(url); + free_request_struct(request); + + return NULL; + } + + connptr->connect_method = TRUE; + } else { #ifdef TRANSPARENT_PROXY - /* - * This section of code is used for the transparent proxy - * option. You will need to configure your firewall to - * redirect all connections for HTTP traffic to tinyproxy - * for this to work properly. - * - * This code was written by Petr Lampa <lampa@fit.vutbr.cz> - */ - int length; - char *data; - length = hashmap_entry_by_key(hashofheaders, "host", (void **)&data); - if (length <= 0) { - struct sockaddr_in dest_addr; - - if (getsockname(connptr->client_fd, (struct sockaddr *)&dest_addr, &length) < 0) { - log_message(LOG_ERR, - "process_request: cannot get destination IP for %d", - connptr->client_fd); - indicate_http_error(connptr, 400, "Bad Request", - "detail", "Unknown destination", - "url", url, - NULL); - safefree(url); - free_request_struct(request); - return NULL; - } - request->host = safemalloc(17); - strcpy(request->host, inet_ntoa(dest_addr.sin_addr)); - request->port = ntohs(dest_addr.sin_port); - request->path = safemalloc(strlen(url) + 1); - strcpy(request->path, url); - safefree(url); - build_url(&url, request->host, request->port, request->path); - log_message(LOG_INFO, - "process_request: trans IP %s %s for %d", - request->method, url, connptr->client_fd); - } else { - request->host = safemalloc(length+1); - if (sscanf(data, "%[^:]:%hu", request->host, &request->port) != 2) { - strcpy(request->host, data); - request->port = HTTP_PORT; - } - request->path = safemalloc(strlen(url) + 1); - strcpy(request->path, url); - safefree(url); - build_url(&url, request->host, request->port, request->path); - log_message(LOG_INFO, - "process_request: trans Host %s %s for %d", - request->method, url, connptr->client_fd); - } - if (config.ipAddr && - strcmp(request->host, config.ipAddr) == 0) { - log_message(LOG_ERR, - "process_request: destination IP is localhost %d", - connptr->client_fd); - indicate_http_error(connptr, 400, "Bad Request", - "detail", "You tried to connect to the machine the proxy is running on", - "url", url, - NULL); - safefree(url); - free_request_struct(request); - return NULL; - } + /* + * This section of code is used for the transparent proxy + * option. You will need to configure your firewall to + * redirect all connections for HTTP traffic to tinyproxy + * for this to work properly. + * + * This code was written by Petr Lampa <lampa@fit.vutbr.cz> + */ + int length; + char *data; + + length = + hashmap_entry_by_key(hashofheaders, "host", (void **)&data); + if (length <= 0) { + struct sockaddr_in dest_addr; + + if (getsockname + (connptr->client_fd, (struct sockaddr *)&dest_addr, + &length) < 0) { + log_message(LOG_ERR, + "process_request: cannot get destination IP for %d", + connptr->client_fd); + indicate_http_error(connptr, 400, "Bad Request", + "detail", + "Unknown destination", + "url", url, NULL); + safefree(url); + free_request_struct(request); + return NULL; + } + request->host = safemalloc(17); + strcpy(request->host, inet_ntoa(dest_addr.sin_addr)); + request->port = ntohs(dest_addr.sin_port); + request->path = safemalloc(strlen(url) + 1); + strcpy(request->path, url); + safefree(url); + build_url(&url, request->host, request->port, + request->path); + log_message(LOG_INFO, + "process_request: trans IP %s %s for %d", + request->method, url, connptr->client_fd); + } else { + request->host = safemalloc(length + 1); + if (sscanf + (data, "%[^:]:%hu", request->host, + &request->port) != 2) { + strcpy(request->host, data); + request->port = HTTP_PORT; + } + request->path = safemalloc(strlen(url) + 1); + strcpy(request->path, url); + safefree(url); + build_url(&url, request->host, request->port, + request->path); + log_message(LOG_INFO, + "process_request: trans Host %s %s for %d", + request->method, url, connptr->client_fd); + } + if (config.ipAddr && strcmp(request->host, config.ipAddr) == 0) { + log_message(LOG_ERR, + "process_request: destination IP is localhost %d", + connptr->client_fd); + indicate_http_error(connptr, 400, "Bad Request", + "detail", + "You tried to connect to the machine the proxy is running on", + "url", url, NULL); + safefree(url); + free_request_struct(request); + return NULL; + } #else - log_message(LOG_ERR, - "process_request: Unknown URL type on file descriptor %d", - connptr->client_fd); - indicate_http_error(connptr, 400, "Bad Request", - "detail", "Unknown URL type", - "url", url, - NULL); - - safefree(url); - free_request_struct(request); - - return NULL; + log_message(LOG_ERR, + "process_request: Unknown URL type on file descriptor %d", + connptr->client_fd); + indicate_http_error(connptr, 400, "Bad Request", + "detail", "Unknown URL type", + "url", url, NULL); + + safefree(url); + free_request_struct(request); + + return NULL; #endif - } + } #ifdef FILTER_ENABLE - /* - * Filter restricted domains/urls - */ - if (config.filter) { - if (config.filter_url) - ret = filter_url(url); - else - ret = filter_domain(request->host); - - if (ret) { - update_stats(STAT_DENIED); - - if (config.filter_url) - log_message(LOG_NOTICE, - "Proxying refused on filtered url \"%s\"", - url); - else - log_message(LOG_NOTICE, - "Proxying refused on filtered domain \"%s\"", - request->host); - - indicate_http_error(connptr, 403, "Filtered", - "detail", "The request you made has been filtered", - "url", url, - NULL); - - safefree(url); - free_request_struct(request); - - return NULL; - } - } + /* + * Filter restricted domains/urls + */ + if (config.filter) { + if (config.filter_url) + ret = filter_url(url); + else + ret = filter_domain(request->host); + + if (ret) { + update_stats(STAT_DENIED); + + if (config.filter_url) + log_message(LOG_NOTICE, + "Proxying refused on filtered url \"%s\"", + url); + else + log_message(LOG_NOTICE, + "Proxying refused on filtered domain \"%s\"", + request->host); + + indicate_http_error(connptr, 403, "Filtered", + "detail", + "The request you made has been filtered", + "url", url, NULL); + + safefree(url); + free_request_struct(request); + + return NULL; + } + } #endif - safefree(url); + safefree(url); - /* - * Check to see if they're requesting the stat host - */ - if (config.stathost && strcmp(config.stathost, request->host) == 0) { - log_message(LOG_NOTICE, "Request for the stathost."); - connptr->show_stats = TRUE; + /* + * Check to see if they're requesting the stat host + */ + if (config.stathost && strcmp(config.stathost, request->host) == 0) { + log_message(LOG_NOTICE, "Request for the stathost."); + connptr->show_stats = TRUE; - free_request_struct(request); - return NULL; - } + free_request_struct(request); + return NULL; + } - return request; + return request; } /* @@ -930,48 +958,48 @@ process_request(struct conn_s *connptr, hashmap_t hashofheaders) static int pull_client_data(struct conn_s *connptr, long int length) { - char *buffer; - ssize_t len; - - buffer = safemalloc(min(MAXBUFFSIZE, length)); - if (!buffer) - return -1; - - do { - len = safe_read(connptr->client_fd, buffer, - min(MAXBUFFSIZE, length)); - if (len <= 0) - goto ERROR_EXIT; - - if (!connptr->error_variables) { - if (safe_write(connptr->server_fd, buffer, len) < 0) - goto ERROR_EXIT; - } - - length -= len; - } while (length > 0); - - /* - * BUG FIX: Internet Explorer will leave two bytes (carriage - * return and line feed) at the end of a POST message. These - * need to be eaten for tinyproxy to work correctly. - */ - socket_nonblocking(connptr->client_fd); - len = recv(connptr->client_fd, buffer, 2, MSG_PEEK); - socket_blocking(connptr->client_fd); - - if (len < 0 && errno != EAGAIN) - goto ERROR_EXIT; - - if (len == 2 && CHECK_CRLF(buffer, len)) - read(connptr->client_fd, buffer, 2); - - safefree(buffer); - return 0; - - ERROR_EXIT: - safefree(buffer); - return -1; + char *buffer; + ssize_t len; + + buffer = safemalloc(min(MAXBUFFSIZE, length)); + if (!buffer) + return -1; + + do { + len = safe_read(connptr->client_fd, buffer, + min(MAXBUFFSIZE, length)); + if (len <= 0) + goto ERROR_EXIT; + + if (!connptr->error_variables) { + if (safe_write(connptr->server_fd, buffer, len) < 0) + goto ERROR_EXIT; + } + + length -= len; + } while (length > 0); + + /* + * BUG FIX: Internet Explorer will leave two bytes (carriage + * return and line feed) at the end of a POST message. These + * need to be eaten for tinyproxy to work correctly. + */ + socket_nonblocking(connptr->client_fd); + len = recv(connptr->client_fd, buffer, 2, MSG_PEEK); + socket_blocking(connptr->client_fd); + + if (len < 0 && errno != EAGAIN) + goto ERROR_EXIT; + + if (len == 2 && CHECK_CRLF(buffer, len)) + read(connptr->client_fd, buffer, 2); + + safefree(buffer); + return 0; + + ERROR_EXIT: + safefree(buffer); + return -1; } #ifdef XTINYPROXY_ENABLE @@ -984,11 +1012,10 @@ static inline int add_xtinyproxy_header(struct conn_s *connptr) { assert(connptr && connptr->server_fd >= 0); - return write_message(connptr->server_fd, - "X-Tinyproxy: %s\r\n", - connptr->client_ip_addr); + return write_message(connptr->server_fd, + "X-Tinyproxy: %s\r\n", connptr->client_ip_addr); } -#endif /* XTINYPROXY */ +#endif /* XTINYPROXY */ /* * Take a complete header line and break it apart (into a key and the data.) @@ -998,23 +1025,23 @@ add_xtinyproxy_header(struct conn_s *connptr) static inline int add_header_to_connection(hashmap_t hashofheaders, char *header, size_t len) { - char *sep; + char *sep; - /* Get rid of the new line and return at the end */ - len -= chomp(header, len); + /* Get rid of the new line and return at the end */ + len -= chomp(header, len); - sep = strchr(header, ':'); - if (!sep) - return -1; + sep = strchr(header, ':'); + if (!sep) + return -1; - /* Blank out colons, spaces, and tabs. */ - while (*sep == ':' || *sep == ' ' || *sep == '\t') - *sep++ = '\0'; + /* Blank out colons, spaces, and tabs. */ + while (*sep == ':' || *sep == ' ' || *sep == '\t') + *sep++ = '\0'; - /* Calculate the new length of just the data */ - len -= sep - header - 1; + /* Calculate the new length of just the data */ + len -= sep - header - 1; - return hashmap_insert(hashofheaders, header, sep, len); + return hashmap_insert(hashofheaders, header, sep, len); } /* @@ -1023,54 +1050,55 @@ add_header_to_connection(hashmap_t hashofheaders, char *header, size_t len) static int get_all_headers(int fd, hashmap_t hashofheaders) { - char *header; - ssize_t len; - unsigned int double_cgi = FALSE; /* boolean */ - - assert(fd >= 0); - assert(hashofheaders != NULL); - - for (;;) { - if ((len = readline(fd, &header)) <= 0) { - safefree(header); - return -1; - } - - /* - * If we received just a CR LF on a line, the headers are - * finished. - */ - if (CHECK_CRLF(header, len)) { - safefree(header); - return 0; - } - - /* - * BUG FIX: The following code detects a "Double CGI" - * situation so that we can handle the nonconforming system. - * This problem was found when accessing cgi.ebay.com, and it - * turns out to be a wider spread problem as well. - * - * If "Double CGI" is in effect, duplicate headers are - * ignored. - * - * FIXME: Might need to change this to a more robust check. - */ - if (strncasecmp(header, "HTTP/", 5) == 0) { - double_cgi = TRUE; - - safefree(header); - continue; - } - - if (!double_cgi - && add_header_to_connection(hashofheaders, header, len) < 0) { - safefree(header); - return -1; - } - - safefree(header); - } + char *header; + ssize_t len; + unsigned int double_cgi = FALSE; /* boolean */ + + assert(fd >= 0); + assert(hashofheaders != NULL); + + for (;;) { + if ((len = readline(fd, &header)) <= 0) { + safefree(header); + return -1; + } + + /* + * If we received just a CR LF on a line, the headers are + * finished. + */ + if (CHECK_CRLF(header, len)) { + safefree(header); + return 0; + } + + /* + * BUG FIX: The following code detects a "Double CGI" + * situation so that we can handle the nonconforming system. + * This problem was found when accessing cgi.ebay.com, and it + * turns out to be a wider spread problem as well. + * + * If "Double CGI" is in effect, duplicate headers are + * ignored. + * + * FIXME: Might need to change this to a more robust check. + */ + if (strncasecmp(header, "HTTP/", 5) == 0) { + double_cgi = TRUE; + + safefree(header); + continue; + } + + if (!double_cgi + && add_header_to_connection(hashofheaders, header, + len) < 0) { + safefree(header); + return -1; + } + + safefree(header); + } } /* @@ -1080,49 +1108,51 @@ get_all_headers(int fd, hashmap_t hashofheaders) static int remove_connection_headers(hashmap_t hashofheaders) { - static char* headers[] = { - "connection", - "proxy-connection" - }; - - char *data; - char* ptr; - ssize_t len; - int i; - - for (i = 0; i != (sizeof(headers) / sizeof(char *)); ++i) { - /* Look for the connection header. If it's not found, return. */ - len = hashmap_entry_by_key(hashofheaders, headers[i], (void **)&data); - if (len <= 0) - return 0; - - /* - * Go through the data line and replace any special characters - * with a NULL. - */ - ptr = data; - while ((ptr = strpbrk(ptr, "()<>@,;:\\\"/[]?={} \t"))) - *ptr++ = '\0'; - - /* - * All the tokens are separated by NULLs. Now go through the - * token and remove them from the hashofheaders. - */ - ptr = data; - while (ptr < data + len) { - hashmap_remove(hashofheaders, ptr); - - /* Advance ptr to the next token */ - ptr += strlen(ptr) + 1; - while (ptr < data + len && *ptr == '\0') - ptr++; - } - - /* Now remove the connection header it self. */ - hashmap_remove(hashofheaders, headers[i]); - } - - return 0; + static char *headers[] = { + "connection", + "proxy-connection" + }; + + char *data; + char *ptr; + ssize_t len; + int i; + + for (i = 0; i != (sizeof(headers) / sizeof(char *)); ++i) { + /* Look for the connection header. If it's not found, return. */ + len = + hashmap_entry_by_key(hashofheaders, headers[i], + (void **)&data); + if (len <= 0) + return 0; + + /* + * Go through the data line and replace any special characters + * with a NULL. + */ + ptr = data; + while ((ptr = strpbrk(ptr, "()<>@,;:\\\"/[]?={} \t"))) + *ptr++ = '\0'; + + /* + * All the tokens are separated by NULLs. Now go through the + * token and remove them from the hashofheaders. + */ + ptr = data; + while (ptr < data + len) { + hashmap_remove(hashofheaders, ptr); + + /* Advance ptr to the next token */ + ptr += strlen(ptr) + 1; + while (ptr < data + len && *ptr == '\0') + ptr++; + } + + /* Now remove the connection header it self. */ + hashmap_remove(hashofheaders, headers[i]); + } + + return 0; } /* @@ -1132,15 +1162,17 @@ remove_connection_headers(hashmap_t hashofheaders) static long get_content_length(hashmap_t hashofheaders) { - ssize_t len; - char *data; - long content_length = -1; + ssize_t len; + char *data; + long content_length = -1; - len = hashmap_entry_by_key(hashofheaders, "content-length", (void **)&data); - if (len > 0) - content_length = atol(data); + len = + hashmap_entry_by_key(hashofheaders, "content-length", + (void **)&data); + if (len > 0) + content_length = atol(data); - return content_length; + return content_length; } /* @@ -1152,40 +1184,38 @@ get_content_length(hashmap_t hashofheaders) */ static int write_via_header(int fd, hashmap_t hashofheaders, - unsigned int major, unsigned int minor) + unsigned int major, unsigned int minor) { - ssize_t len; - char hostname[512]; - char *data; - int ret; - - if (config.via_proxy_name) { - strlcpy(hostname, config.via_proxy_name, sizeof(hostname)); - } else if (gethostname(hostname, sizeof(hostname)) < 0) { - strcpy(hostname, "unknown"); - } - - /* - * See if there is a "Via" header. If so, again we need to do a bit - * of processing. - */ - len = hashmap_entry_by_key(hashofheaders, "via", (void **)&data); - if (len > 0) { - ret = write_message(fd, - "Via: %s, %hu.%hu %s (%s/%s)\r\n", - data, - major, minor, - hostname, PACKAGE, VERSION); - - hashmap_remove(hashofheaders, "via"); - } else { - ret = write_message(fd, - "Via: %hu.%hu %s (%s/%s)\r\n", - major, minor, - hostname, PACKAGE, VERSION); - } - - return ret; + ssize_t len; + char hostname[512]; + char *data; + int ret; + + if (config.via_proxy_name) { + strlcpy(hostname, config.via_proxy_name, sizeof(hostname)); + } else if (gethostname(hostname, sizeof(hostname)) < 0) { + strcpy(hostname, "unknown"); + } + + /* + * See if there is a "Via" header. If so, again we need to do a bit + * of processing. + */ + len = hashmap_entry_by_key(hashofheaders, "via", (void **)&data); + if (len > 0) { + ret = write_message(fd, + "Via: %s, %hu.%hu %s (%s/%s)\r\n", + data, + major, minor, hostname, PACKAGE, VERSION); + + hashmap_remove(hashofheaders, "via"); + } else { + ret = write_message(fd, + "Via: %hu.%hu %s (%s/%s)\r\n", + major, minor, hostname, PACKAGE, VERSION); + } + + return ret; } /* @@ -1202,107 +1232,108 @@ write_via_header(int fd, hashmap_t hashofheaders, static int process_client_headers(struct conn_s *connptr, hashmap_t hashofheaders) { - static char *skipheaders[] = { - "host", - "keep-alive", - "proxy-connection", - "te", - "trailers", - "transfer-encoding", - "upgrade" - }; - int i; - hashmap_iter iter; - int ret = 0; - - char *data, *header; - - /* - * Don't send headers if there's already an error, if the request was - * a stats request, or if this was a CONNECT method (unless upstream - * proxy is in use.) - */ - if (connptr->server_fd == -1 || connptr->show_stats - || (connptr->connect_method && (connptr->upstream_proxy == NULL))) { - log_message(LOG_INFO, "Not sending client headers to remote machine"); - return 0; - } - - /* - * See if there is a "Content-Length" header. If so, again we need - * to do a bit of processing. - */ - connptr->content_length.client = get_content_length(hashofheaders); - - /* - * See if there is a "Connection" header. If so, we need to do a bit - * of processing. :) - */ - remove_connection_headers(hashofheaders); - - /* - * Delete the headers listed in the skipheaders list - */ - for (i = 0; i != (sizeof(skipheaders) / sizeof(char *)); i++) { - hashmap_remove(hashofheaders, skipheaders[i]); - } - - /* Send, or add the Via header */ - ret = write_via_header(connptr->server_fd, hashofheaders, - connptr->protocol.major, - connptr->protocol.minor); - if (ret < 0) { - indicate_http_error(connptr, 503, - "Could not send data to remote server", - "detail", "A network error occurred while trying to write data to the remote web server.", - NULL); - goto PULL_CLIENT_DATA; - } - - /* - * Output all the remaining headers to the remote machine. - */ - iter = hashmap_first(hashofheaders); - if (iter >= 0) { - for ( ; !hashmap_is_end(hashofheaders, iter); ++iter) { - hashmap_return_entry(hashofheaders, - iter, - &data, - (void**)&header); - - if (!is_anonymous_enabled() || anonymous_search(data) > 0) { - ret = write_message(connptr->server_fd, - "%s: %s\r\n", - data, header); - if (ret < 0) { - indicate_http_error(connptr, 503, - "Could not send data to remote server", - "detail", "A network error occurred while trying to write data to the remote web server.", - NULL); - goto PULL_CLIENT_DATA; - } - } - } - } + static char *skipheaders[] = { + "host", + "keep-alive", + "proxy-connection", + "te", + "trailers", + "transfer-encoding", + "upgrade" + }; + int i; + hashmap_iter iter; + int ret = 0; + + char *data, *header; + + /* + * Don't send headers if there's already an error, if the request was + * a stats request, or if this was a CONNECT method (unless upstream + * proxy is in use.) + */ + if (connptr->server_fd == -1 || connptr->show_stats + || (connptr->connect_method && (connptr->upstream_proxy == NULL))) { + log_message(LOG_INFO, + "Not sending client headers to remote machine"); + return 0; + } + + /* + * See if there is a "Content-Length" header. If so, again we need + * to do a bit of processing. + */ + connptr->content_length.client = get_content_length(hashofheaders); + + /* + * See if there is a "Connection" header. If so, we need to do a bit + * of processing. :) + */ + remove_connection_headers(hashofheaders); + + /* + * Delete the headers listed in the skipheaders list + */ + for (i = 0; i != (sizeof(skipheaders) / sizeof(char *)); i++) { + hashmap_remove(hashofheaders, skipheaders[i]); + } + /* Send, or add the Via header */ + ret = write_via_header(connptr->server_fd, hashofheaders, + connptr->protocol.major, + connptr->protocol.minor); + if (ret < 0) { + indicate_http_error(connptr, 503, + "Could not send data to remote server", + "detail", + "A network error occurred while trying to write data to the remote web server.", + NULL); + goto PULL_CLIENT_DATA; + } + + /* + * Output all the remaining headers to the remote machine. + */ + iter = hashmap_first(hashofheaders); + if (iter >= 0) { + for (; !hashmap_is_end(hashofheaders, iter); ++iter) { + hashmap_return_entry(hashofheaders, + iter, &data, (void **)&header); + + if (!is_anonymous_enabled() + || anonymous_search(data) > 0) { + ret = + write_message(connptr->server_fd, + "%s: %s\r\n", data, header); + if (ret < 0) { + indicate_http_error(connptr, 503, + "Could not send data to remote server", + "detail", + "A network error occurred while trying to write data to the remote web server.", + NULL); + goto PULL_CLIENT_DATA; + } + } + } + } #if defined(XTINYPROXY_ENABLE) - if (config.my_domain) - add_xtinyproxy_header(connptr); + if (config.my_domain) + add_xtinyproxy_header(connptr); #endif - - /* Write the final "blank" line to signify the end of the headers */ - if (safe_write(connptr->server_fd, "\r\n", 2) < 0) - return -1; - - /* - * Spin here pulling the data from the client. - */ - PULL_CLIENT_DATA: - if (connptr->content_length.client > 0) - return pull_client_data(connptr, - connptr->content_length.client); - else - return ret; + + /* Write the final "blank" line to signify the end of the headers */ + if (safe_write(connptr->server_fd, "\r\n", 2) < 0) + return -1; + + /* + * Spin here pulling the data from the client. + */ + PULL_CLIENT_DATA: + if (connptr->content_length.client > 0) + return pull_client_data(connptr, + connptr->content_length.client); + else + return ret; } /* @@ -1312,65 +1343,69 @@ process_client_headers(struct conn_s *connptr, hashmap_t hashofheaders) static int process_server_headers(struct conn_s *connptr) { - static char *skipheaders[] = { - "keep-alive", - "proxy-authenticate", - "proxy-authorization", - "proxy-connection", - "transfer-encoding", - }; - - char *response_line; - - hashmap_t hashofheaders; - hashmap_iter iter; - char *data, *header; - ssize_t len; - int i; - int ret; + static char *skipheaders[] = { + "keep-alive", + "proxy-authenticate", + "proxy-authorization", + "proxy-connection", + "transfer-encoding", + }; + + char *response_line; + + hashmap_t hashofheaders; + hashmap_iter iter; + char *data, *header; + ssize_t len; + int i; + int ret; #ifdef REVERSE_SUPPORT - struct reversepath *reverse = config.reversepath_list; + struct reversepath *reverse = config.reversepath_list; #endif - /* Get the response line from the remote server. */ + /* Get the response line from the remote server. */ retry: - len = readline(connptr->server_fd, &response_line); - if (len <= 0) - return -1; - - /* - * Strip the new line and character return from the string. - */ - if (chomp(response_line, len) == len) { - /* - * If the number of characters removed is the same as the - * length then it was a blank line. Free the buffer and - * try again (since we're looking for a request line.) - */ - safefree(response_line); - goto retry; - } - - hashofheaders = hashmap_create(HEADER_BUCKETS); - if (!hashofheaders) { - safefree(response_line); - return -1; - } - - /* - * Get all the headers from the remote server in a big hash - */ - if (get_all_headers(connptr->server_fd, hashofheaders) < 0) { - log_message(LOG_WARNING, "Could not retrieve all the headers from the remote server."); - hashmap_delete(hashofheaders); - safefree(response_line); - - indicate_http_error(connptr, 503, "Could not retrieve all the headers", - "detail", PACKAGE " was unable to retrieve and process headers from the remote web server.", - NULL); - return -1; - } + len = readline(connptr->server_fd, &response_line); + if (len <= 0) + return -1; + + /* + * Strip the new line and character return from the string. + */ + if (chomp(response_line, len) == len) { + /* + * If the number of characters removed is the same as the + * length then it was a blank line. Free the buffer and + * try again (since we're looking for a request line.) + */ + safefree(response_line); + goto retry; + } + + hashofheaders = hashmap_create(HEADER_BUCKETS); + if (!hashofheaders) { + safefree(response_line); + return -1; + } + + /* + * Get all the headers from the remote server in a big hash + */ + if (get_all_headers(connptr->server_fd, hashofheaders) < 0) { + log_message(LOG_WARNING, + "Could not retrieve all the headers from the remote server."); + hashmap_delete(hashofheaders); + safefree(response_line); + + indicate_http_error(connptr, 503, + "Could not retrieve all the headers", + "detail", + PACKAGE + " was unable to retrieve and process headers from the remote web server.", + NULL); + return -1; + } /* * At this point we've received the response line and all the @@ -1384,103 +1419,106 @@ process_server_headers(struct conn_s *connptr) return 0; } - - /* Send the saved response line first */ + /* Send the saved response line first */ ret = write_message(connptr->client_fd, "%s\r\n", response_line); safefree(response_line); if (ret < 0) goto ERROR_EXIT; - /* - * If there is a "Content-Length" header, retrieve the information - * from it for later use. - */ - connptr->content_length.server = get_content_length(hashofheaders); - - /* - * See if there is a connection header. If so, we need to to a bit of - * processing. - */ - remove_connection_headers(hashofheaders); - - /* - * Delete the headers listed in the skipheaders list - */ - for (i = 0; i != (sizeof(skipheaders) / sizeof(char *)); i++) { - hashmap_remove(hashofheaders, skipheaders[i]); - } - - /* Send, or add the Via header */ - ret = write_via_header(connptr->client_fd, hashofheaders, - connptr->protocol.major, - connptr->protocol.minor); - if (ret < 0) - goto ERROR_EXIT; + /* + * If there is a "Content-Length" header, retrieve the information + * from it for later use. + */ + connptr->content_length.server = get_content_length(hashofheaders); + + /* + * See if there is a connection header. If so, we need to to a bit of + * processing. + */ + remove_connection_headers(hashofheaders); + + /* + * Delete the headers listed in the skipheaders list + */ + for (i = 0; i != (sizeof(skipheaders) / sizeof(char *)); i++) { + hashmap_remove(hashofheaders, skipheaders[i]); + } + + /* Send, or add the Via header */ + ret = write_via_header(connptr->client_fd, hashofheaders, + connptr->protocol.major, + connptr->protocol.minor); + if (ret < 0) + goto ERROR_EXIT; #ifdef REVERSE_SUPPORT - /* Write tracking cookie for the magical reverse proxy path hack */ - if (config.reversemagic && connptr->reversepath) { - ret = write_message(connptr->client_fd, - "Set-Cookie: " REVERSE_COOKIE "=%s; path=/\r\n", - connptr->reversepath); - if (ret < 0) goto ERROR_EXIT; - } - - /* Rewrite the HTTP redirect if needed */ - if (config.reversebaseurl && - hashmap_entry_by_key(hashofheaders, "location", (void **)&header) > 0) { - - /* Look for a matching entry in the reversepath list */ - while (reverse) { - if (strncasecmp(header, - reverse->url, - (len = strlen(reverse->url))) == 0) break; - reverse = reverse->next; - } - - if (reverse) { - ret = write_message(connptr->client_fd, "Location: %s%s%s\r\n", - config.reversebaseurl, (reverse->path + 1), - (header + len)); - if (ret < 0) goto ERROR_EXIT; - - log_message(LOG_INFO, - "Rewriting HTTP redirect: %s -> %s%s%s", header, - config.reversebaseurl, (reverse->path + 1), (header + len)); - hashmap_remove(hashofheaders, "location"); - } - } + /* Write tracking cookie for the magical reverse proxy path hack */ + if (config.reversemagic && connptr->reversepath) { + ret = write_message(connptr->client_fd, + "Set-Cookie: " REVERSE_COOKIE + "=%s; path=/\r\n", connptr->reversepath); + if (ret < 0) + goto ERROR_EXIT; + } + + /* Rewrite the HTTP redirect if needed */ + if (config.reversebaseurl && + hashmap_entry_by_key(hashofheaders, "location", + (void **)&header) > 0) { + + /* Look for a matching entry in the reversepath list */ + while (reverse) { + if (strncasecmp(header, + reverse->url, + (len = strlen(reverse->url))) == 0) + break; + reverse = reverse->next; + } + + if (reverse) { + ret = + write_message(connptr->client_fd, + "Location: %s%s%s\r\n", + config.reversebaseurl, + (reverse->path + 1), (header + len)); + if (ret < 0) + goto ERROR_EXIT; + + log_message(LOG_INFO, + "Rewriting HTTP redirect: %s -> %s%s%s", + header, config.reversebaseurl, + (reverse->path + 1), (header + len)); + hashmap_remove(hashofheaders, "location"); + } + } #endif - /* - * All right, output all the remaining headers to the client. - */ - iter = hashmap_first(hashofheaders); - if (iter >= 0) { - for ( ; !hashmap_is_end(hashofheaders, iter); ++iter) { - hashmap_return_entry(hashofheaders, - iter, - &data, - (void **)&header); - - ret = write_message(connptr->client_fd, - "%s: %s\r\n", - data, header); - if (ret < 0) - goto ERROR_EXIT; - } - } - hashmap_delete(hashofheaders); - - /* Write the final blank line to signify the end of the headers */ - if (safe_write(connptr->client_fd, "\r\n", 2) < 0) - return -1; - - return 0; - - ERROR_EXIT: - hashmap_delete(hashofheaders); - return -1; + /* + * All right, output all the remaining headers to the client. + */ + iter = hashmap_first(hashofheaders); + if (iter >= 0) { + for (; !hashmap_is_end(hashofheaders, iter); ++iter) { + hashmap_return_entry(hashofheaders, + iter, &data, (void **)&header); + + ret = write_message(connptr->client_fd, + "%s: %s\r\n", data, header); + if (ret < 0) + goto ERROR_EXIT; + } + } + hashmap_delete(hashofheaders); + + /* Write the final blank line to signify the end of the headers */ + if (safe_write(connptr->client_fd, "\r\n", 2) < 0) + return -1; + + return 0; + + ERROR_EXIT: + hashmap_delete(hashofheaders); + return -1; } /* @@ -1494,105 +1532,106 @@ process_server_headers(struct conn_s *connptr) static void relay_connection(struct conn_s *connptr) { - fd_set rset, wset; - struct timeval tv; - time_t last_access; - int ret; - double tdiff; - int maxfd = max(connptr->client_fd, connptr->server_fd) + 1; - ssize_t bytes_received; - - socket_nonblocking(connptr->client_fd); - socket_nonblocking(connptr->server_fd); - - last_access = time(NULL); - - for (;;) { - FD_ZERO(&rset); - FD_ZERO(&wset); - - tv.tv_sec = - config.idletimeout - difftime(time(NULL), last_access); - tv.tv_usec = 0; - - if (buffer_size(connptr->sbuffer) > 0) - FD_SET(connptr->client_fd, &wset); - if (buffer_size(connptr->cbuffer) > 0) - FD_SET(connptr->server_fd, &wset); - if (buffer_size(connptr->sbuffer) < MAXBUFFSIZE) - FD_SET(connptr->server_fd, &rset); - if (buffer_size(connptr->cbuffer) < MAXBUFFSIZE) - FD_SET(connptr->client_fd, &rset); - - ret = select(maxfd, &rset, &wset, NULL, &tv); - - if (ret == 0) { - tdiff = difftime(time(NULL), last_access); - if (tdiff > config.idletimeout) { - log_message(LOG_INFO, - "Idle Timeout (after select) as %g > %u.", - tdiff, config.idletimeout); - return; - } else { - continue; - } - } else if (ret < 0) { - log_message(LOG_ERR, - "relay_connection: select() error \"%s\". Closing connection (client_fd:%d, server_fd:%d)", - strerror(errno), connptr->client_fd, - connptr->server_fd); - return; - } else { - /* - * All right, something was actually selected so mark it. - */ - last_access = time(NULL); - } - - if (FD_ISSET(connptr->server_fd, &rset)) { - bytes_received = read_buffer(connptr->server_fd, connptr->sbuffer); - if (bytes_received < 0) - break; - - connptr->content_length.server -= bytes_received; - if (connptr->content_length.server == 0) - break; - } - if (FD_ISSET(connptr->client_fd, &rset) - && read_buffer(connptr->client_fd, connptr->cbuffer) < 0) { - break; - } - if (FD_ISSET(connptr->server_fd, &wset) - && write_buffer(connptr->server_fd, connptr->cbuffer) < 0) { - break; - } - if (FD_ISSET(connptr->client_fd, &wset) - && write_buffer(connptr->client_fd, connptr->sbuffer) < 0) { - break; - } - } - - /* - * Here the server has closed the connection... write the - * remainder to the client and then exit. - */ - socket_blocking(connptr->client_fd); - while (buffer_size(connptr->sbuffer) > 0) { - if (write_buffer(connptr->client_fd, connptr->sbuffer) < 0) - break; - } - shutdown(connptr->client_fd, SHUT_WR); - - /* - * Try to send any remaining data to the server if we can. - */ - socket_blocking(connptr->server_fd); - while (buffer_size(connptr->cbuffer) > 0) { - if (write_buffer(connptr->server_fd, connptr->cbuffer) < 0) - break; - } - - return; + fd_set rset, wset; + struct timeval tv; + time_t last_access; + int ret; + double tdiff; + int maxfd = max(connptr->client_fd, connptr->server_fd) + 1; + ssize_t bytes_received; + + socket_nonblocking(connptr->client_fd); + socket_nonblocking(connptr->server_fd); + + last_access = time(NULL); + + for (;;) { + FD_ZERO(&rset); + FD_ZERO(&wset); + + tv.tv_sec = + config.idletimeout - difftime(time(NULL), last_access); + tv.tv_usec = 0; + + if (buffer_size(connptr->sbuffer) > 0) + FD_SET(connptr->client_fd, &wset); + if (buffer_size(connptr->cbuffer) > 0) + FD_SET(connptr->server_fd, &wset); + if (buffer_size(connptr->sbuffer) < MAXBUFFSIZE) + FD_SET(connptr->server_fd, &rset); + if (buffer_size(connptr->cbuffer) < MAXBUFFSIZE) + FD_SET(connptr->client_fd, &rset); + + ret = select(maxfd, &rset, &wset, NULL, &tv); + + if (ret == 0) { + tdiff = difftime(time(NULL), last_access); + if (tdiff > config.idletimeout) { + log_message(LOG_INFO, + "Idle Timeout (after select) as %g > %u.", + tdiff, config.idletimeout); + return; + } else { + continue; + } + } else if (ret < 0) { + log_message(LOG_ERR, + "relay_connection: select() error \"%s\". Closing connection (client_fd:%d, server_fd:%d)", + strerror(errno), connptr->client_fd, + connptr->server_fd); + return; + } else { + /* + * All right, something was actually selected so mark it. + */ + last_access = time(NULL); + } + + if (FD_ISSET(connptr->server_fd, &rset)) { + bytes_received = + read_buffer(connptr->server_fd, connptr->sbuffer); + if (bytes_received < 0) + break; + + connptr->content_length.server -= bytes_received; + if (connptr->content_length.server == 0) + break; + } + if (FD_ISSET(connptr->client_fd, &rset) + && read_buffer(connptr->client_fd, connptr->cbuffer) < 0) { + break; + } + if (FD_ISSET(connptr->server_fd, &wset) + && write_buffer(connptr->server_fd, connptr->cbuffer) < 0) { + break; + } + if (FD_ISSET(connptr->client_fd, &wset) + && write_buffer(connptr->client_fd, connptr->sbuffer) < 0) { + break; + } + } + + /* + * Here the server has closed the connection... write the + * remainder to the client and then exit. + */ + socket_blocking(connptr->client_fd); + while (buffer_size(connptr->sbuffer) > 0) { + if (write_buffer(connptr->client_fd, connptr->sbuffer) < 0) + break; + } + shutdown(connptr->client_fd, SHUT_WR); + + /* + * Try to send any remaining data to the server if we can. + */ + socket_blocking(connptr->server_fd); + while (buffer_size(connptr->cbuffer) > 0) { + if (write_buffer(connptr->server_fd, connptr->cbuffer) < 0) + break; + } + + return; } /* @@ -1602,71 +1641,75 @@ static int connect_to_upstream(struct conn_s *connptr, struct request_s *request) { #ifndef UPSTREAM_SUPPORT - /* - * This function does nothing if upstream support was not compiled - * into tinyproxy. - */ - return -1; + /* + * This function does nothing if upstream support was not compiled + * into tinyproxy. + */ + return -1; #else - char *combined_string; - int len; - - struct upstream *cur_upstream = connptr->upstream_proxy; - if(!cur_upstream) { - log_message(LOG_WARNING, - "No upstream proxy defined for %s.", - request->host); - indicate_http_error(connptr, 404, "Unable to connect to upstream proxy."); - return -1; - } - - connptr->server_fd = - opensock(cur_upstream->host, cur_upstream->port, connptr->server_ip_addr); - - if (connptr->server_fd < 0) { - log_message(LOG_WARNING, - "Could not connect to upstream proxy."); - indicate_http_error(connptr, 404, "Unable to connect to upstream proxy", - "detail", "A network error occurred while trying to connect to the upstream web proxy.", - NULL); - return -1; - } - - log_message(LOG_CONN, - "Established connection to upstream proxy \"%s\" using file descriptor %d.", - cur_upstream->host, connptr->server_fd); - - /* - * We need to re-write the "path" part of the request so that we - * can reuse the establish_http_connection() function. It expects a - * method and path. - */ - if (connptr->connect_method) { - len = strlen(request->host) + 7; - - combined_string = safemalloc(len); - if (!combined_string) { - return -1; - } - - snprintf(combined_string, len, "%s:%d", request->host, - request->port); - } else { - len = strlen(request->host) + strlen(request->path) + 14; - combined_string = safemalloc(len); - if (!combined_string) { - return -1; - } - - snprintf(combined_string, len, "http://%s:%d%s", request->host, - request->port, request->path); - } - - if (request->path) - safefree(request->path); - request->path = combined_string; - - return establish_http_connection(connptr, request); + char *combined_string; + int len; + + struct upstream *cur_upstream = connptr->upstream_proxy; + + if (!cur_upstream) { + log_message(LOG_WARNING, + "No upstream proxy defined for %s.", request->host); + indicate_http_error(connptr, 404, + "Unable to connect to upstream proxy."); + return -1; + } + + connptr->server_fd = + opensock(cur_upstream->host, cur_upstream->port, + connptr->server_ip_addr); + + if (connptr->server_fd < 0) { + log_message(LOG_WARNING, + "Could not connect to upstream proxy."); + indicate_http_error(connptr, 404, + "Unable to connect to upstream proxy", + "detail", + "A network error occurred while trying to connect to the upstream web proxy.", + NULL); + return -1; + } + + log_message(LOG_CONN, + "Established connection to upstream proxy \"%s\" using file descriptor %d.", + cur_upstream->host, connptr->server_fd); + + /* + * We need to re-write the "path" part of the request so that we + * can reuse the establish_http_connection() function. It expects a + * method and path. + */ + if (connptr->connect_method) { + len = strlen(request->host) + 7; + + combined_string = safemalloc(len); + if (!combined_string) { + return -1; + } + + snprintf(combined_string, len, "%s:%d", request->host, + request->port); + } else { + len = strlen(request->host) + strlen(request->path) + 14; + combined_string = safemalloc(len); + if (!combined_string) { + return -1; + } + + snprintf(combined_string, len, "http://%s:%d%s", request->host, + request->port, request->path); + } + + if (request->path) + safefree(request->path); + request->path = combined_string; + + return establish_http_connection(connptr, request); #endif } @@ -1682,112 +1725,117 @@ connect_to_upstream(struct conn_s *connptr, struct request_s *request) void handle_connection(int fd) { - struct conn_s *connptr; - struct request_s *request = NULL; - hashmap_t hashofheaders = NULL; - - char sock_ipaddr[IP_LENGTH]; - char peer_ipaddr[IP_LENGTH]; - char peer_string[HOSTNAME_LENGTH]; - - getpeer_information(fd, peer_ipaddr, peer_string); - - if (config.bindsame) - getsock_ip(fd, sock_ipaddr); - - log_message(LOG_CONN, config.bindsame ? - "Connect (file descriptor %d): %s [%s] at [%s]" : - "Connect (file descriptor %d): %s [%s]", - fd, peer_string, peer_ipaddr, sock_ipaddr); - - connptr = initialize_conn(fd, peer_ipaddr, peer_string, - config.bindsame ? sock_ipaddr : 0); - if (!connptr) { - close(fd); - return; - } - - if (check_acl(fd, peer_ipaddr, peer_string) <= 0) { - update_stats(STAT_DENIED); - indicate_http_error(connptr, 403, "Access denied", - "detail", "The administrator of this proxy has not configured it to service requests from your host.", - NULL); - send_http_error_message(connptr); - destroy_conn(connptr); - return; - } - - if (read_request_line(connptr) < 0) { - update_stats(STAT_BADCONN); - indicate_http_error(connptr, 408, "Timeout", - "detail", "Server timeout waiting for the HTTP request from the client.", - NULL); - send_http_error_message(connptr); - destroy_conn(connptr); - return; - } - - /* - * The "hashofheaders" store the client's headers. - */ - if (!(hashofheaders = hashmap_create(HEADER_BUCKETS))) { - update_stats(STAT_BADCONN); - indicate_http_error(connptr, 503, "Internal error", - "detail", "An internal server error occurred while processing your request. Please contact the administrator.", - NULL); - send_http_error_message(connptr); - destroy_conn(connptr); - return; - } - - /* - * Get all the headers from the client in a big hash. - */ - if (get_all_headers(connptr->client_fd, hashofheaders) < 0) { - log_message(LOG_WARNING, "Could not retrieve all the headers from the client"); - hashmap_delete(hashofheaders); - update_stats(STAT_BADCONN); - destroy_conn(connptr); - return; - } - - request = process_request(connptr, hashofheaders); - if (!request) { - if (!connptr->error_variables && !connptr->show_stats) { - update_stats(STAT_BADCONN); - destroy_conn(connptr); - hashmap_delete(hashofheaders); - return; - } - goto send_error; - } - - connptr->upstream_proxy = UPSTREAM_HOST(request->host); - if (connptr->upstream_proxy != NULL) { - if (connect_to_upstream(connptr, request) < 0) { - goto send_error; - } - } else { - connptr->server_fd = opensock(request->host, request->port, - connptr->server_ip_addr); - if (connptr->server_fd < 0) { - indicate_http_error(connptr, 500, "Unable to connect", - "detail", PACKAGE " was unable to connect to the remote web server.", - "error", strerror(errno), - NULL); - goto send_error; - } - - log_message(LOG_CONN, - "Established connection to host \"%s\" using file descriptor %d.", - request->host, connptr->server_fd); - - if (!connptr->connect_method) - establish_http_connection(connptr, request); - } + struct conn_s *connptr; + struct request_s *request = NULL; + hashmap_t hashofheaders = NULL; + + char sock_ipaddr[IP_LENGTH]; + char peer_ipaddr[IP_LENGTH]; + char peer_string[HOSTNAME_LENGTH]; + + getpeer_information(fd, peer_ipaddr, peer_string); + + if (config.bindsame) + getsock_ip(fd, sock_ipaddr); + + log_message(LOG_CONN, config.bindsame ? + "Connect (file descriptor %d): %s [%s] at [%s]" : + "Connect (file descriptor %d): %s [%s]", + fd, peer_string, peer_ipaddr, sock_ipaddr); + + connptr = initialize_conn(fd, peer_ipaddr, peer_string, + config.bindsame ? sock_ipaddr : 0); + if (!connptr) { + close(fd); + return; + } + + if (check_acl(fd, peer_ipaddr, peer_string) <= 0) { + update_stats(STAT_DENIED); + indicate_http_error(connptr, 403, "Access denied", + "detail", + "The administrator of this proxy has not configured it to service requests from your host.", + NULL); + send_http_error_message(connptr); + destroy_conn(connptr); + return; + } + + if (read_request_line(connptr) < 0) { + update_stats(STAT_BADCONN); + indicate_http_error(connptr, 408, "Timeout", + "detail", + "Server timeout waiting for the HTTP request from the client.", + NULL); + send_http_error_message(connptr); + destroy_conn(connptr); + return; + } + + /* + * The "hashofheaders" store the client's headers. + */ + if (!(hashofheaders = hashmap_create(HEADER_BUCKETS))) { + update_stats(STAT_BADCONN); + indicate_http_error(connptr, 503, "Internal error", + "detail", + "An internal server error occurred while processing your request. Please contact the administrator.", + NULL); + send_http_error_message(connptr); + destroy_conn(connptr); + return; + } + + /* + * Get all the headers from the client in a big hash. + */ + if (get_all_headers(connptr->client_fd, hashofheaders) < 0) { + log_message(LOG_WARNING, + "Could not retrieve all the headers from the client"); + hashmap_delete(hashofheaders); + update_stats(STAT_BADCONN); + destroy_conn(connptr); + return; + } + + request = process_request(connptr, hashofheaders); + if (!request) { + if (!connptr->error_variables && !connptr->show_stats) { + update_stats(STAT_BADCONN); + destroy_conn(connptr); + hashmap_delete(hashofheaders); + return; + } + goto send_error; + } + + connptr->upstream_proxy = UPSTREAM_HOST(request->host); + if (connptr->upstream_proxy != NULL) { + if (connect_to_upstream(connptr, request) < 0) { + goto send_error; + } + } else { + connptr->server_fd = opensock(request->host, request->port, + connptr->server_ip_addr); + if (connptr->server_fd < 0) { + indicate_http_error(connptr, 500, "Unable to connect", + "detail", + PACKAGE + " was unable to connect to the remote web server.", + "error", strerror(errno), NULL); + goto send_error; + } + + log_message(LOG_CONN, + "Established connection to host \"%s\" using file descriptor %d.", + request->host, connptr->server_fd); + + if (!connptr->connect_method) + establish_http_connection(connptr, request); + } send_error: - free_request_struct(request); + free_request_struct(request); if (process_client_headers(connptr, hashofheaders) < 0) { update_stats(STAT_BADCONN); @@ -1799,43 +1847,44 @@ handle_connection(int fd) } hashmap_delete(hashofheaders); - if (connptr->error_variables) { - send_http_error_message(connptr); - destroy_conn(connptr); - return; - } else if (connptr->show_stats) { - showstats(connptr); - destroy_conn(connptr); - return; - } - - if (!connptr->connect_method || (connptr->upstream_proxy != NULL)) { - if (process_server_headers(connptr) < 0) { - if (connptr->error_variables) - send_http_error_message(connptr); - - update_stats(STAT_BADCONN); - destroy_conn(connptr); - return; - } - } else { - if (send_ssl_response(connptr) < 0) { - log_message(LOG_ERR, - "handle_connection: Could not send SSL greeting to client."); - update_stats(STAT_BADCONN); - destroy_conn(connptr); - return; - } - } - - relay_connection(connptr); - - log_message(LOG_INFO, "Closed connection between local client (fd:%d) and remote client (fd:%d)", - connptr->client_fd, connptr->server_fd); - - /* - * All done... close everything and go home... :) - */ - destroy_conn(connptr); - return; + if (connptr->error_variables) { + send_http_error_message(connptr); + destroy_conn(connptr); + return; + } else if (connptr->show_stats) { + showstats(connptr); + destroy_conn(connptr); + return; + } + + if (!connptr->connect_method || (connptr->upstream_proxy != NULL)) { + if (process_server_headers(connptr) < 0) { + if (connptr->error_variables) + send_http_error_message(connptr); + + update_stats(STAT_BADCONN); + destroy_conn(connptr); + return; + } + } else { + if (send_ssl_response(connptr) < 0) { + log_message(LOG_ERR, + "handle_connection: Could not send SSL greeting to client."); + update_stats(STAT_BADCONN); + destroy_conn(connptr); + return; + } + } + + relay_connection(connptr); + + log_message(LOG_INFO, + "Closed connection between local client (fd:%d) and remote client (fd:%d)", + connptr->client_fd, connptr->server_fd); + + /* + * All done... close everything and go home... :) + */ + destroy_conn(connptr); + return; } @@ -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]; - - assert(host != NULL); - assert(port > 0); - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - 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; - } - - 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 */ - } - } - - if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0) - break; /* success */ - - 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; - } - - return sockfd; + int sockfd, n; + struct addrinfo hints, *res, *ressave; + char portstr[6]; + + assert(host != NULL); + assert(port > 0); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + 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; + } + + 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 */ + } + } + + if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0) + break; /* success */ + + 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; + } + + 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; - - assert(port > 0); - assert(addrlen != NULL); - - 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); - - 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 (listen(listenfd, MAXLISTEN) < 0) { - log_message(LOG_ERR, "Unable to start listening socket because of %s", - strerror(errno)); - return -1; - } - - *addrlen = sizeof(addr); - - return listenfd; + int listenfd; + const int on = 1; + struct sockaddr_in addr; + + assert(port > 0); + assert(addrlen != NULL); + + 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); + + 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 (listen(listenfd, MAXLISTEN) < 0) { + log_message(LOG_ERR, + "Unable to start listening socket because of %s", + strerror(errno)); + return -1; + } + + *addrlen = sizeof(addr); + + 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); } @@ -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 diff --git a/src/stats.c b/src/stats.c index e863521..1ffeaff 100644 --- a/src/stats.c +++ b/src/stats.c @@ -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"; - - 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); - - 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); - - if (send_http_message(connptr, 200, "OK", message_buffer) < 0) { - safefree(message_buffer); - return -1; - } - - 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); - - return 0; + 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; + + 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; + + 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; + } + + 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); + + 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; - } - - return 0; + 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; } diff --git a/src/stats.h b/src/stats.h index 6d191f9..773f30a 100644 --- a/src/stats.h +++ b/src/stats.h @@ -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; /* @@ -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; - - if (len1 + len2 >= size) - len2 = size - len1 - 1; - if (len2 > 0) { - memcpy(dst + len1, src, len2); - dst[len1 + len2] = '\0'; - } - - return ret; + 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'; + } + + 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; } @@ -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); diff --git a/src/tinyproxy.c b/src/tinyproxy.c index d1f8777..1d4cff0 100644 --- a/src/tinyproxy.c +++ b/src/tinyproxy.c @@ -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; - - /* - * Disable the creation of CORE files right up front. - */ + 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. + */ #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 */ - - /* 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); - } - } - - 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; - - /* - * Read in the settings from the config file. - */ + 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; + + /* + * 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 " ..."); + + /* + * 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. + */ 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(); - - /* - * 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(); - - /* - * 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 (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); - } + 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; + } + + 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 (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); + } #ifdef 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); - } - - /* - * 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); - } - - /* - * 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."); - - child_main_loop(); - - 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)); - } + 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); + } + + /* + * 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); + } + + /* + * 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."); + + child_main_loop(); + + 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)); + } #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); } diff --git a/src/tinyproxy.h b/src/tinyproxy.h index f967b36..4cb091c 100644 --- a/src/tinyproxy.h +++ b/src/tinyproxy.h @@ -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 diff --git a/src/utils.c b/src/utils.c index 167d9e3..7201e9e 100644 --- a/src/utils.c +++ b/src/utils.c @@ -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; - - /* - * 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; - - 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; - } - - /* - * 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; - } - - /* - * 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") - */ + 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; + } + + /* + * 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; + + /* + * 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; + } + + /* + * 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; + + /* + * 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 */ - } - - return fildes; + 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; } /* @@ -177,28 +177,28 @@ create_file_safely(const char *filename, unsigned int truncate_file) int pidfile_create(const char *filename) { - int fildes; - FILE *fd; - - /* - * 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; - } - - fprintf(fd, "%ld\n", (long) getpid()); - fclose(fd); - return 0; + int fildes; + FILE *fd; + + /* + * 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; + } + + fprintf(fd, "%ld\n", (long)getpid()); + fclose(fd); + return 0; } diff --git a/src/utils.h b/src/utils.h index 86bd617..395c46e 100644 --- a/src/utils.h +++ b/src/utils.h @@ -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); diff --git a/src/vector.c b/src/vector.c index b938fc5..984198f 100644 --- a/src/vector.c +++ b/src/vector.c @@ -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; - if (!vector) - return -EINVAL; - - ptr = vector->head; - while (ptr) { - next = ptr->next; - safefree(ptr->data); - safefree(ptr); + ptr = vector->head; + while (ptr) { + next = ptr->next; + safefree(ptr->data); + safefree(ptr); - ptr = next; - } + ptr = next; + } - safefree(vector); + safefree(vector); - return 0; + 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; - - if (!vector || !data || len <= 0 || - (pos != INSERT_PREPEND && pos != INSERT_APPEND)) - return -EINVAL; - - entry = safemalloc(sizeof(struct vectorentry_s)); - if (!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; - - /* 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++; - - return 0; + struct vectorentry_s *entry; + + if (!vector || !data || len <= 0 || + (pos != INSERT_PREPEND && pos != INSERT_APPEND)) + return -EINVAL; + + entry = safemalloc(sizeof(struct vectorentry_s)); + if (!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; + + /* 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++; + + 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; } diff --git a/src/vector.h b/src/vector.h index 3c8e8bb..3db694d 100644 --- a/src/vector.h +++ b/src/vector.h @@ -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 */ |