diff options
-rw-r--r-- | src/acl.c | 482 | ||||
-rw-r--r-- | src/acl.h | 3 | ||||
-rw-r--r-- | src/anonymous.c | 45 | ||||
-rw-r--r-- | src/buffer.c | 399 | ||||
-rw-r--r-- | src/child.c | 594 | ||||
-rw-r--r-- | src/child.h | 13 | ||||
-rw-r--r-- | src/conffile.c | 741 | ||||
-rw-r--r-- | src/conns.c | 171 | ||||
-rw-r--r-- | src/conns.h | 113 | ||||
-rw-r--r-- | src/daemon.c | 63 | ||||
-rw-r--r-- | src/filter.c | 296 | ||||
-rw-r--r-- | src/filter.h | 7 | ||||
-rw-r--r-- | src/hashmap.c | 597 | ||||
-rw-r--r-- | src/hashmap.h | 32 | ||||
-rw-r--r-- | src/heap.c | 143 | ||||
-rw-r--r-- | src/html-error.c | 366 | ||||
-rw-r--r-- | src/http-message.c | 343 | ||||
-rw-r--r-- | src/log.c | 220 | ||||
-rw-r--r-- | src/main.c | 644 | ||||
-rw-r--r-- | src/main.h | 96 | ||||
-rw-r--r-- | src/network.c | 463 | ||||
-rw-r--r-- | src/reqs.c | 2639 | ||||
-rw-r--r-- | src/reqs.h | 14 | ||||
-rw-r--r-- | src/reverse-proxy.c | 212 | ||||
-rw-r--r-- | src/reverse-proxy.h | 9 | ||||
-rw-r--r-- | src/sock.c | 320 | ||||
-rw-r--r-- | src/stats.c | 194 | ||||
-rw-r--r-- | src/stats.h | 13 | ||||
-rw-r--r-- | src/text.c | 85 | ||||
-rw-r--r-- | src/transparent-proxy.c | 129 | ||||
-rw-r--r-- | src/transparent-proxy.h | 1 | ||||
-rw-r--r-- | src/utils.c | 302 | ||||
-rw-r--r-- | src/vector.c | 192 | ||||
-rw-r--r-- | src/vector.h | 16 |
34 files changed, 4733 insertions, 5224 deletions
@@ -33,10 +33,9 @@ /* Define how long an IPv6 address is in bytes (128 bits, 16 bytes) */ #define IPV6_LEN 16 -enum acl_type -{ - ACL_STRING, - ACL_NUMERIC, +enum acl_type { + ACL_STRING, + ACL_NUMERIC, }; /* @@ -44,19 +43,16 @@ enum acl_type * whether it's an ALLOW or DENY entry, and also whether it's a string * entry (like a domain name) or an IP entry. */ -struct acl_s -{ - acl_access_t access; - enum acl_type type; - union - { - char *string; - struct - { - unsigned char octet[IPV6_LEN]; - unsigned char mask[IPV6_LEN]; - } ip; - } address; +struct acl_s { + acl_access_t access; + enum acl_type type; + union { + char *string; + struct { + unsigned char octet[IPV6_LEN]; + unsigned char mask[IPV6_LEN]; + } ip; + } address; }; /* @@ -64,7 +60,6 @@ struct acl_s */ static vector_t access_list = NULL; - /* * Fills in the netmask array given a numeric value. * @@ -77,45 +72,38 @@ inline static int fill_netmask_array (char *bitmask_string, unsigned char array[], unsigned int len) { - unsigned int i; - long int mask; - char *endptr; - - errno = 0; /* to distinguish success/failure after call */ - mask = strtol (bitmask_string, &endptr, 10); - - /* check for various conversion errors */ - if ((errno == ERANGE && (mask == LONG_MIN || mask == LONG_MAX)) - || (errno != 0 && mask == 0) || (endptr == bitmask_string)) - return -1; - - /* valid range for a bit mask */ - if (mask < 0 || mask > (8 * len)) - return -1; - - /* we have a valid range to fill in the array */ - for (i = 0; i != len; ++i) - { - if (mask >= 8) - { - array[i] = 0xff; - mask -= 8; - } - else if (mask > 0) - { - array[i] = (unsigned char) (0xff << (8 - mask)); - mask = 0; - } - else - { - array[i] = 0; + unsigned int i; + long int mask; + char *endptr; + + errno = 0; /* to distinguish success/failure after call */ + mask = strtol (bitmask_string, &endptr, 10); + + /* check for various conversion errors */ + if ((errno == ERANGE && (mask == LONG_MIN || mask == LONG_MAX)) + || (errno != 0 && mask == 0) || (endptr == bitmask_string)) + return -1; + + /* valid range for a bit mask */ + if (mask < 0 || mask > (8 * len)) + return -1; + + /* we have a valid range to fill in the array */ + for (i = 0; i != len; ++i) { + if (mask >= 8) { + array[i] = 0xff; + mask -= 8; + } else if (mask > 0) { + array[i] = (unsigned char) (0xff << (8 - mask)); + mask = 0; + } else { + array[i] = 0; + } } - } - return 0; + return 0; } - /* * Inserts a new access control into the list. The function will figure out * whether the location is an IP address (with optional netmask) or a @@ -125,83 +113,76 @@ fill_netmask_array (char *bitmask_string, unsigned char array[], * -1 on failure * 0 otherwise. */ -int -insert_acl (char *location, acl_access_t access_type) +int insert_acl (char *location, acl_access_t access_type) { - struct acl_s acl; - int ret; - char *p, ip_dst[IPV6_LEN]; - - assert (location != NULL); - - /* - * If the access list has not been set up, create it. - */ - if (!access_list) - { - access_list = vector_create (); - if (!access_list) - { - log_message (LOG_ERR, "Unable to allocate memory for access list"); - return -1; - } - } - - /* - * Start populating the access control structure. - */ - memset (&acl, 0, sizeof (struct acl_s)); - acl.access = access_type; - - /* - * Check for a valid IP address (the simplest case) first. - */ - if (full_inet_pton (location, ip_dst) > 0) - { - acl.type = ACL_NUMERIC; - memcpy (acl.address.ip.octet, ip_dst, IPV6_LEN); - memset (acl.address.ip.mask, 0xff, IPV6_LEN); - } - else - { - /* - * At this point we're either a hostname or an - * IP address with a slash. - */ - p = strchr (location, '/'); - if (p != NULL) - { - /* - * We have a slash, so it's intended to be an - * IP address with mask - */ - *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); - - if (fill_netmask_array (p + 1, &(acl.address.ip.mask[0]), IPV6_LEN) - < 0) - return -1; + struct acl_s acl; + int ret; + char *p, ip_dst[IPV6_LEN]; + + assert (location != NULL); + + /* + * If the access list has not been set up, create it. + */ + if (!access_list) { + access_list = vector_create (); + if (!access_list) { + log_message (LOG_ERR, + "Unable to allocate memory for access list"); + return -1; + } } - else - { - /* In all likelihood a string */ - acl.type = ACL_STRING; - acl.address.string = safestrdup (location); - if (!acl.address.string) - return -1; + + /* + * Start populating the access control structure. + */ + memset (&acl, 0, sizeof (struct acl_s)); + acl.access = access_type; + + /* + * Check for a valid IP address (the simplest case) first. + */ + if (full_inet_pton (location, ip_dst) > 0) { + acl.type = ACL_NUMERIC; + memcpy (acl.address.ip.octet, ip_dst, IPV6_LEN); + memset (acl.address.ip.mask, 0xff, IPV6_LEN); + } else { + /* + * At this point we're either a hostname or an + * IP address with a slash. + */ + p = strchr (location, '/'); + if (p != NULL) { + /* + * We have a slash, so it's intended to be an + * IP address with mask + */ + *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); + + if (fill_netmask_array + (p + 1, &(acl.address.ip.mask[0]), IPV6_LEN) + < 0) + return -1; + } else { + /* In all likelihood a string */ + acl.type = ACL_STRING; + acl.address.string = safestrdup (location); + if (!acl.address.string) + return -1; + } } - } - - /* - * Add the entry and then clean up. - */ - ret = vector_append (access_list, &acl, sizeof (struct acl_s)); - safefree (acl.address.string); - return ret; + + /* + * Add the entry and then clean up. + */ + ret = vector_append (access_list, &acl, sizeof (struct acl_s)); + safefree (acl.address.string); + return ret; } /* @@ -217,76 +198,70 @@ static int 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]; - - 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; - } + 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; + } } - 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; - } + 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; + /* Indicate that no tests succeeded, so skip to next control. */ + return -1; } /* @@ -297,30 +272,28 @@ STRING_TEST: * 0 IP address is denied * -1 neither allowed nor denied. */ -static int -check_numeric_acl (const struct acl_s *acl, const char *ip) +static int 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); + 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) - { - x = addr[i] & acl->address.ip.mask[i]; - y = acl->address.ip.octet[i] & acl->address.ip.mask[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; - } + /* 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); } /* @@ -330,52 +303,49 @@ check_numeric_acl (const struct acl_s *acl, const char *ip) * 1 if allowed * 0 if denied */ -int -check_acl (const char *ip, const char *host) +int check_acl (const char *ip, const char *host) { - struct acl_s *acl; - int perm = 0; - size_t i; - - assert (ip != NULL); - assert (host != NULL); - - /* - * If there is no access list allow everything. - */ - if (!access_list) - return 1; - - for (i = 0; i != (size_t)vector_length (access_list); ++i) - { - acl = (struct acl_s *)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; + struct acl_s *acl; + int perm = 0; + size_t i; + + assert (ip != NULL); + assert (host != NULL); + + /* + * If there is no access list allow everything. + */ + if (!access_list) + return 1; + + for (i = 0; i != (size_t) vector_length (access_list); ++i) { + acl = (struct acl_s *) 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; + } + + /* + * Check the return value too see if the IP address is + * allowed or denied. + */ + if (perm == 0) + break; + else if (perm == 1) + return perm; } - /* - * Check the return value too see if the IP address is - * 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; } @@ -21,8 +21,7 @@ #ifndef TINYPROXY_ACL_H #define TINYPROXY_ACL_H -typedef enum -{ ACL_ALLOW, ACL_DENY } acl_access_t; +typedef enum { ACL_ALLOW, ACL_DENY } acl_access_t; extern int insert_acl (char *location, acl_access_t access_type); extern int check_acl (const char *ip_address, const char *string_address); diff --git a/src/anonymous.c b/src/anonymous.c index 928abb8..fe57550 100644 --- a/src/anonymous.c +++ b/src/anonymous.c @@ -29,23 +29,21 @@ static hashmap_t anonymous_map = NULL; -short int -is_anonymous_enabled (void) +short int is_anonymous_enabled (void) { - return (anonymous_map != NULL) ? 1 : 0; + return (anonymous_map != NULL) ? 1 : 0; } /* * Search for the header. This function returns a positive value greater than * zero if the string was found, zero if it wasn't and negative upon error. */ -int -anonymous_search (const char *s) +int anonymous_search (const 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); } /* @@ -54,26 +52,23 @@ anonymous_search (const char *s) * Return -1 if there is an error, otherwise a 0 is returned if the insert was * successful. */ -int -anonymous_insert (const char *s) +int anonymous_insert (const 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 d158ca0..49216fd 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -34,23 +34,21 @@ #define BUFFER_HEAD(x) (x)->head #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 */ +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 */ }; /* * The buffer structure points to the beginning and end of the buffer list * (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 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 */ }; /* @@ -58,162 +56,152 @@ struct buffer_s * to the buffer. The data IS copied, so make sure if you allocated your * data buffer on the heap, delete it because you now have TWO copies. */ -static struct bufline_s * -makenewline (unsigned char *data, size_t length) +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); - newline = (struct bufline_s *)safemalloc (sizeof (struct bufline_s)); - if (!newline) - return NULL; + newline = (struct bufline_s *) safemalloc (sizeof (struct bufline_s)); + if (!newline) + return NULL; - newline->string = (unsigned char *)safemalloc (length); - if (!newline->string) - { - safefree (newline); - return NULL; - } + newline->string = (unsigned char *) safemalloc (length); + if (!newline->string) { + 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; } /* * Free the allocated buffer line */ -static void -free_line (struct bufline_s *line) +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); } /* * Create a new buffer */ -struct buffer_s * -new_buffer (void) +struct buffer_s *new_buffer (void) { - struct buffer_s *buffptr; + struct buffer_s *buffptr; - buffptr = (struct buffer_s *)safemalloc (sizeof (struct buffer_s)); - if (!buffptr) - return NULL; + buffptr = (struct buffer_s *) safemalloc (sizeof (struct buffer_s)); + if (!buffptr) + 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; } /* * Delete all the lines in the buffer and the buffer itself */ -void -delete_buffer (struct buffer_s *buffptr) +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; } /* * Push a new line on to the end of the buffer. */ -int -add_to_buffer (struct buffer_s *buffptr, unsigned char *data, size_t length) +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; } /* * Remove the first line from the top of the buffer */ -static struct bufline_s * -remove_from_buffer (struct buffer_s *buffptr) +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; } /* @@ -221,128 +209,115 @@ remove_from_buffer (struct buffer_s *buffptr) * Takes a connection and returns the number of bytes read. */ #define READ_BUFFER_SIZE (1024 * 2) -ssize_t -read_buffer (int fd, struct buffer_s * buffptr) +ssize_t read_buffer (int fd, struct buffer_s * buffptr) { - ssize_t bytesin; - unsigned char *buffer; - - assert (fd >= 0); - assert (buffptr != NULL); - - /* - * Don't allow the buffer to grow larger than MAXBUFFSIZE - */ - if (buffptr->size >= MAXBUFFSIZE) - return 0; - - buffer = (unsigned char *)safemalloc (READ_BUFFER_SIZE); - if (!buffer) - { - return -ENOMEM; - } - - 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."); - bytesin = -1; - } - } - else - { - if (bytesin == 0) - { - /* connection was closed by client */ - bytesin = -1; + ssize_t bytesin; + unsigned char *buffer; + + assert (fd >= 0); + assert (buffptr != NULL); + + /* + * Don't allow the buffer to grow larger than MAXBUFFSIZE + */ + if (buffptr->size >= MAXBUFFSIZE) + return 0; + + buffer = (unsigned char *) safemalloc (READ_BUFFER_SIZE); + if (!buffer) { + return -ENOMEM; } - else - { - switch (errno) - { + + 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."); + bytesin = -1; + } + } else { + if (bytesin == 0) { + /* connection was closed by client */ + bytesin = -1; + } else { + switch (errno) { #ifdef EWOULDBLOCK - case EWOULDBLOCK: + case EWOULDBLOCK: #else # ifdef EAGAIN - case EAGAIN: + case EAGAIN: # endif #endif - case EINTR: - bytesin = 0; - break; - default: - log_message (LOG_ERR, - "readbuff: recv() error \"%s\" on file descriptor %d", - strerror (errno), fd); - bytesin = -1; - break; - } + case EINTR: + bytesin = 0; + break; + default: + log_message (LOG_ERR, + "readbuff: recv() error \"%s\" on file descriptor %d", + strerror (errno), fd); + bytesin = -1; + break; + } + } } - } - safefree (buffer); - return bytesin; + safefree (buffer); + return bytesin; } /* * Write the bytes in the buffer to the socket. * Takes a connection and returns the number of bytes written. */ -ssize_t -write_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/child.c b/src/child.c index bb4110c..9e8d515 100644 --- a/src/child.c +++ b/src/child.c @@ -37,13 +37,11 @@ static socklen_t addrlen; /* * Stores the internal data needed for each child (connection) */ -enum child_status_t -{ T_EMPTY, T_WAITING, T_CONNECTED }; -struct child_s -{ - pid_t tid; - unsigned int connects; - enum child_status_t status; +enum child_status_t { T_EMPTY, T_WAITING, T_CONNECTED }; +struct child_s { + pid_t tid; + unsigned int connects; + enum child_status_t status; }; /* @@ -52,10 +50,9 @@ struct child_s */ static struct child_s *child_ptr; -static struct child_config_s -{ - unsigned int maxclients, maxrequestsperchild; - unsigned int maxspareservers, minspareservers, startservers; +static struct child_config_s { + unsigned int maxclients, maxrequestsperchild; + unsigned int maxspareservers, minspareservers, startservers; } child_config; static unsigned int *servers_waiting; /* servers waiting for a connection */ @@ -76,49 +73,45 @@ static unsigned int *servers_waiting; /* servers waiting for a connection */ static struct flock lock_it, unlock_it; static int lock_fd = -1; -static void -_child_lock_init (void) +static void _child_lock_init (void) { - char lock_file[] = "/tmp/tinyproxy.servers.lock.XXXXXX"; + char lock_file[] = "/tmp/tinyproxy.servers.lock.XXXXXX"; - /* Only allow u+rw bits. This may be required for some versions - * of glibc so that mkstemp() doesn't make us vulnerable. - */ - umask (0177); + /* Only allow u+rw bits. This may be required for some versions + * of glibc so that mkstemp() doesn't make us vulnerable. + */ + umask (0177); - 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) +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) +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 */ @@ -141,348 +134,321 @@ _child_lock_release (void) /* * Set the configuration values for the various child related settings. */ -short int -child_configure (child_config_t type, unsigned int val) +short int child_configure (child_config_t type, unsigned 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) +static void child_main (struct child_s *ptr) { - int connfd; - struct sockaddr *cliaddr; - socklen_t clilen; - - cliaddr = (struct sockaddr *)safemalloc (addrlen); - if (!cliaddr) - { - log_message (LOG_CRIT, "Could not allocate memory for child address."); - exit (0); - } + int connfd; + struct sockaddr *cliaddr; + socklen_t clilen; + + cliaddr = (struct sockaddr *) safemalloc (addrlen); + if (!cliaddr) { + log_message (LOG_CRIT, + "Could not allocate memory for child address."); + exit (0); + } - ptr->connects = 0; + ptr->connects = 0; - while (!config.quit) - { - ptr->status = T_WAITING; + while (!config.quit) { + ptr->status = T_WAITING; - clilen = addrlen; + clilen = addrlen; - connfd = accept (listenfd, cliaddr, &clilen); + connfd = accept (listenfd, cliaddr, &clilen); #ifndef NDEBUG - /* - * Enable the TINYPROXY_DEBUG environment variable if you - * want to use the GDB debugger. - */ - if (getenv ("TINYPROXY_DEBUG")) - { - /* Pause for 10 seconds to allow us to connect debugger */ - fprintf (stderr, - "Process has accepted connection: %ld\n", - (long int) ptr->tid); - sleep (10); - fprintf (stderr, "Continuing process: %ld\n", (long int) ptr->tid); - } + /* + * Enable the TINYPROXY_DEBUG environment variable if you + * want to use the GDB debugger. + */ + if (getenv ("TINYPROXY_DEBUG")) { + /* Pause for 10 seconds to allow us to connect debugger */ + fprintf (stderr, + "Process has accepted connection: %ld\n", + (long int) ptr->tid); + sleep (10); + fprintf (stderr, "Continuing process: %ld\n", + (long int) ptr->tid); + } #endif - /* - * Make sure no error occurred... - */ - if (connfd < 0) - { - log_message (LOG_ERR, - "Accept returned an error (%s) ... retrying.", - strerror (errno)); - continue; - } + /* + * Make sure no error occurred... + */ + if (connfd < 0) { + log_message (LOG_ERR, + "Accept returned an error (%s) ... retrying.", + strerror (errno)); + continue; + } - ptr->status = T_CONNECTED; + ptr->status = T_CONNECTED; - SERVER_DEC (); + SERVER_DEC (); - handle_connection (connfd); - ptr->connects++; + handle_connection (connfd); + ptr->connects++; - if (child_config.maxrequestsperchild != 0) - { - DEBUG2 ("%u connections so far...", ptr->connects); + if (child_config.maxrequestsperchild != 0) { + DEBUG2 ("%u connections so far...", ptr->connects); - if (ptr->connects == child_config.maxrequestsperchild) - { - log_message (LOG_NOTICE, - "Child has reached MaxRequestsPerChild (%u). " - "Killing child.", ptr->connects); - break; - } - } + if (ptr->connects == child_config.maxrequestsperchild) { + log_message (LOG_NOTICE, + "Child has reached MaxRequestsPerChild (%u). " + "Killing child.", ptr->connects); + break; + } + } - SERVER_COUNT_LOCK (); - if (*servers_waiting > child_config.maxspareservers) - { - /* - * There are too many spare children, kill ourself - * off. - */ - log_message (LOG_NOTICE, - "Waiting servers (%d) exceeds MaxSpareServers (%d). " - "Killing child.", - *servers_waiting, child_config.maxspareservers); - SERVER_COUNT_UNLOCK (); - - break; - } - else - { - SERVER_COUNT_UNLOCK (); - } + SERVER_COUNT_LOCK (); + if (*servers_waiting > child_config.maxspareservers) { + /* + * There are too many spare children, kill ourself + * off. + */ + log_message (LOG_NOTICE, + "Waiting servers (%d) exceeds MaxSpareServers (%d). " + "Killing child.", + *servers_waiting, + child_config.maxspareservers); + SERVER_COUNT_UNLOCK (); + + break; + } else { + SERVER_COUNT_UNLOCK (); + } - SERVER_INC (); - } + SERVER_INC (); + } - ptr->status = T_EMPTY; + ptr->status = T_EMPTY; - safefree (cliaddr); - exit (0); + safefree (cliaddr); + exit (0); } /* * Fork a child "child" (or in our case a process) and then start up the * child_main() function. */ -static pid_t -child_make (struct child_s *ptr) +static pid_t child_make (struct child_s *ptr) { - pid_t pid; + pid_t pid; - if ((pid = fork ()) > 0) - return pid; /* parent */ + 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); + /* + * 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; + child_main (ptr); /* never returns */ + return -1; } /* * Create a pool of children to handle incoming connections */ -short int -child_pool_create (void) +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 = (struct child_s *)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 = (unsigned int *)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; + 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 = + (struct child_s *) 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; } - else - { - log_message (LOG_INFO, - "Creating child number %d of %d ...", - i + 1, child_config.startservers); - SERVER_INC (); + servers_waiting = + (unsigned int *) 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; } - } - log_message (LOG_INFO, "Finished creating all children."); + for (i = 0; i != child_config.maxclients; i++) { + child_ptr[i].status = T_EMPTY; + child_ptr[i].connects = 0; + } - return 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; } /* * Keep the proper number of servers running. This is the birth of the * servers. It monitors this at least once a second. */ -void -child_main_loop (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; + 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 (); } - } - } - else - { - SERVER_COUNT_UNLOCK (); - } - sleep (5); + sleep (5); - /* Handle log rotation if it was requested */ - if (received_sighup) - { - truncate_log_file (); + /* Handle log rotation if it was requested */ + if (received_sighup) { + truncate_log_file (); #ifdef FILTER_ENABLE - if (config.filter) - { - filter_destroy (); - filter_init (); - } - log_message (LOG_NOTICE, "Re-reading filter file."); + if (config.filter) { + filter_destroy (); + filter_init (); + } + log_message (LOG_NOTICE, "Re-reading filter file."); #endif /* FILTER_ENABLE */ - received_sighup = FALSE; + received_sighup = FALSE; + } } - } } /* * Go through all the non-empty children and cancel them. */ -void -child_kill_children (void) +void child_kill_children (void) { - unsigned int i; + unsigned int i; - for (i = 0; i != child_config.maxclients; i++) - { - if (child_ptr[i].status != T_EMPTY) - kill (child_ptr[i].tid, SIGTERM); - } + 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) +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) +void child_close_sock (void) { - close (listenfd); + close (listenfd); } diff --git a/src/child.h b/src/child.h index 1085b0d..1197eb2 100644 --- a/src/child.h +++ b/src/child.h @@ -21,13 +21,12 @@ #ifndef TINYPROXY_CHILD_H #define TINYPROXY_CHILD_H -typedef enum -{ - CHILD_MAXCLIENTS, - CHILD_MAXSPARESERVERS, - CHILD_MINSPARESERVERS, - CHILD_STARTSERVERS, - CHILD_MAXREQUESTSPERCHILD +typedef enum { + CHILD_MAXCLIENTS, + CHILD_MAXSPARESERVERS, + CHILD_MINSPARESERVERS, + CHILD_STARTSERVERS, + CHILD_MAXREQUESTSPERCHILD } child_config_t; extern short int child_pool_create (void); diff --git a/src/conffile.c b/src/conffile.c index 888ddce..8e731b4 100644 --- a/src/conffile.c +++ b/src/conffile.c @@ -66,8 +66,7 @@ * 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 @@ -88,10 +87,9 @@ typedef int (*CONFFILE_HANDLER) (struct config_s *, const char *, * 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) +static HANDLE_FUNC (handle_nop) { - return 0; + return 0; } /* do nothing function */ static HANDLE_FUNC (handle_allow); @@ -159,75 +157,73 @@ static HANDLE_FUNC (handle_upstream_no); * for internal use, a pointer to the compiled regex so it only needs * to be compiled one. */ -struct -{ - const char *re; - CONFFILE_HANDLER handler; - regex_t *cre; -} directives[] = -{ - /* comments */ - { BEGIN "#", handle_nop, NULL }, - /* blank lines */ - { "^[[:space:]]+$", handle_nop, NULL }, - /* 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), +struct { + const char *re; + CONFFILE_HANDLER handler; + regex_t *cre; +} directives[] = { + /* comments */ + { + BEGIN "#", handle_nop, NULL}, + /* blank lines */ + { + "^[[:space:]]+$", handle_nop, NULL}, + /* 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), #ifdef FILTER_ENABLE - /* 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), + /* 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), #endif #ifdef REVERSE_SUPPORT - /* 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), + /* 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), #endif #ifdef UPSTREAM_SUPPORT - /* upstream is rather complicated */ - { BEGIN "(no" WS "upstream)" WS STR END, handle_upstream_no, NULL }, - { - BEGIN "(upstream)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR ")?" END, - handle_upstream, - NULL - }, + /* upstream is rather complicated */ + { + BEGIN "(no" WS "upstream)" WS STR END, handle_upstream_no, NULL}, { + BEGIN "(upstream)" WS "(" IP "|" ALNUM ")" ":" INT "(" WS STR + ")?" END, handle_upstream, NULL}, #endif - /* 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]); @@ -238,26 +234,25 @@ const unsigned int ndirectives = sizeof (directives) / sizeof (directives[0]); * * Returns 0 on success; negative upon failure. */ -int -config_compile (void) +int config_compile (void) { - unsigned int i, r; + unsigned int i, r; - for (i = 0; i != ndirectives; ++i) - { - assert (directives[i].handler); - assert (!directives[i].cre); + for (i = 0; i != ndirectives; ++i) { + assert (directives[i].handler); + assert (!directives[i].cre); - directives[i].cre = (regex_t *)safemalloc (sizeof (regex_t)); - if (!directives[i].cre) - return -1; + directives[i].cre = (regex_t *) safemalloc (sizeof (regex_t)); + if (!directives[i].cre) + return -1; - r = regcomp (directives[i].cre, - directives[i].re, REG_EXTENDED | REG_ICASE | REG_NEWLINE); - if (r) - return r; - } - return 0; + r = regcomp (directives[i].cre, + directives[i].re, + REG_EXTENDED | REG_ICASE | REG_NEWLINE); + if (r) + return r; + } + return 0; } /* @@ -268,43 +263,39 @@ config_compile (void) * Returns 0 if a match was found and successfully processed; otherwise, * a negative number is returned. */ -static int -check_match (struct config_s *conf, const char *line) +static int check_match (struct config_s *conf, const char *line) { - regmatch_t match[RE_MAX_MATCHES]; - unsigned int i; + regmatch_t match[RE_MAX_MATCHES]; + unsigned int i; - assert (ndirectives > 0); + assert (ndirectives > 0); - 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); - } + 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 -1; + return -1; } /* * Parse the previously opened configuration stream. */ -int -config_parse (struct config_s *conf, FILE * f) +int config_parse (struct config_s *conf, FILE * f) { - char buffer[1024]; /* 1KB lines should be plenty */ - unsigned long lineno = 1; + char buffer[1024]; /* 1KB lines should be plenty */ + unsigned long lineno = 1; - while (fgets (buffer, sizeof (buffer), f)) - { - if (check_match (conf, buffer)) - { - printf ("Syntax error on line %ld\n", lineno); - return 1; + while (fgets (buffer, sizeof (buffer), f)) { + if (check_match (conf, buffer)) { + printf ("Syntax error on line %ld\n", lineno); + return 1; + } + ++lineno; } - ++lineno; - } - return 0; + return 0; } /*********************************************************************** @@ -314,80 +305,77 @@ 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; + char *p; + const unsigned int len = match->rm_eo - match->rm_so; - assert (line); - assert (len > 0); + assert (line); + assert (len > 0); - p = (char *)safemalloc (len + 1); - if (!p) - return NULL; + p = (char *) safemalloc (len + 1); + if (!p) + return NULL; - memcpy (p, line + match->rm_so, len); - p[len] = '\0'; - return p; + memcpy (p, line + match->rm_so, len); + p[len] = '\0'; + return p; } -static int -set_string_arg (char **var, const char *line, regmatch_t * match) +static int 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); - safefree (arg); - return *var ? 0 : -1; + if (!arg) + return -1; + *var = safestrdup (arg); + safefree (arg); + return *var ? 0 : -1; } -static int -get_bool_arg (const char *line, regmatch_t * match) +static int 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); + assert (line); + assert (match && match->rm_so != -1); - /* "y"es or o"n" map as true, otherwise it's false. */ - if (tolower (p[0]) == 'y' || tolower (p[1]) == 'n') - return 1; - else - return 0; + /* "y"es or o"n" map as true, otherwise it's false. */ + if (tolower (p[0]) == 'y' || tolower (p[1]) == 'n') + return 1; + else + return 0; } static int set_bool_arg (unsigned int *var, const char *line, regmatch_t * match) { - assert (var); - assert (line); - assert (match && match->rm_so != -1); + assert (var); + assert (line); + assert (match && match->rm_so != -1); - *var = get_bool_arg (line, match); - return 0; + *var = get_bool_arg (line, match); + return 0; } static inline unsigned long int get_int_arg (const char *line, regmatch_t * match) { - assert (line); - assert (match && match->rm_so != -1); + assert (line); + assert (match && match->rm_so != -1); - return strtoul (line + match->rm_so, NULL, 0); + return strtoul (line + match->rm_so, NULL, 0); } static int set_int_arg (unsigned long int *var, const char *line, regmatch_t * match) { - assert (var); - assert (line); - assert (match); + assert (var); + assert (line); + assert (match); - *var = get_int_arg (line, match); - return 0; + *var = get_int_arg (line, match); + return 0; } /*********************************************************************** @@ -408,405 +396,360 @@ set_int_arg (unsigned long int *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]); + 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]); + 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]); + char *arg = get_string_arg (line, &match[2]); - if (!arg) - return -1; + if (!arg) + return -1; - anonymous_insert (arg); - safefree (arg); - return 0; + anonymous_insert (arg); + 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]); + int r = set_string_arg (&conf->via_proxy_name, line, &match[2]); - if (r) - return r; - log_message (LOG_INFO, - "Setting \"Via\" header proxy to %s", conf->via_proxy_name); - return 0; + if (r) + return r; + log_message (LOG_INFO, + "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]); + 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]); + 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]); + int r = set_string_arg (&conf->stathost, line, &match[2]); - if (r) - return r; - log_message (LOG_INFO, "Stathost set to \"%s\"", conf->stathost); - return 0; + 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 - return set_string_arg (&conf->my_domain, line, &match[2]); + return set_string_arg (&conf->my_domain, line, &match[2]); #else - fprintf (stderr, - "XTinyproxy NOT Enabled! Recompile with --enable-xtinyproxy\n"); - return 1; + fprintf (stderr, + "XTinyproxy NOT Enabled! Recompile with --enable-xtinyproxy\n"); + return 1; #endif } -static -HANDLE_FUNC (handle_syslog) +static HANDLE_FUNC (handle_syslog) { #ifdef HAVE_SYSLOG_H - return set_bool_arg (&conf->syslog, line, &match[2]); + return set_bool_arg (&conf->syslog, line, &match[2]); #else - fprintf (stderr, "Syslog support not compiled in executable.\n"); - return 1; + 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]); + int r = set_bool_arg (&conf->bindsame, line, &match[2]); - if (r) - return r; - log_message (LOG_INFO, "Binding outgoing connection to incoming IP"); - return 0; + 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 ((unsigned long int *) &conf->port, line, &match[2]); + return set_int_arg ((unsigned 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; + 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; + 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; + 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; + 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])); - return 0; + 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 ((unsigned long int *) &conf->idletimeout, line, &match[2]); + return set_int_arg ((unsigned 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; + 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->user, line, &match[2]); + return set_string_arg (&conf->user, line, &match[2]); } -static -HANDLE_FUNC (handle_group) +static HANDLE_FUNC (handle_group) { - return set_string_arg (&conf->group, line, &match[2]); + 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; + 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]); + char *arg = get_string_arg (line, &match[2]); - insert_acl (arg, ACL_DENY); - safefree (arg); - return 0; + 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]); + int r = set_string_arg (&conf->bind_address, line, &match[2]); - if (r) - return r; - log_message (LOG_INFO, - "Outgoing connections bound to IP %s", conf->bind_address); - return 0; + if (r) + return r; + log_message (LOG_INFO, + "Outgoing connections bound to IP %s", conf->bind_address); + return 0; #else - fprintf (stderr, - "\"Bind\" cannot be used with transparent support enabled.\n"); - return 1; + fprintf (stderr, + "\"Bind\" cannot be used with transparent support enabled.\n"); + return 1; #endif } -static -HANDLE_FUNC (handle_listen) +static HANDLE_FUNC (handle_listen) { - int r = set_string_arg (&conf->ipAddr, line, &match[2]); + int r = set_string_arg (&conf->ipAddr, line, &match[2]); - if (r) - return r; - log_message (LOG_INFO, "Listing on IP %s", conf->ipAddr); - return 0; + 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_ - * match places are used. match[2] matches the full digit - * string, while match[3] matches only the "0x" part if - * present. This is why the "string" is located at - * match[4] (rather than the more intuitive match[3]. - */ - unsigned long int err = get_int_arg (line, &match[2]); - char *page = get_string_arg (line, &match[4]); + /* + * Because an integer is defined as ((0x)?[[:digit:]]+) _two_ + * match places are used. match[2] matches the full digit + * string, while match[3] matches only the "0x" part if + * present. This is why the "string" is located at + * match[4] (rather than the more intuitive match[3]. + */ + unsigned 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; + add_new_errorpage (page, err); + safefree (page); + return 0; } /* * Log level's strings. */ -struct log_levels_s -{ - const char *string; - int level; +struct log_levels_s { + 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]); - unsigned int i; + static const unsigned int nlevels = + sizeof (log_levels) / sizeof (log_levels[0]); + unsigned int i; - char *arg = get_string_arg (line, &match[2]); + 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); - safefree (arg); - return 0; + for (i = 0; i != nlevels; ++i) { + if (!strcasecmp (arg, log_levels[i].string)) { + set_log_level (log_levels[i].level); + safefree (arg); + return 0; + } } - } - safefree (arg); - return -1; + safefree (arg); + return -1; } #ifdef FILTER_ENABLE -static -HANDLE_FUNC (handle_filter) +static HANDLE_FUNC (handle_filter) { - return set_string_arg (&conf->filter, line, &match[2]); + 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]); + 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]); + 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); + assert (match[2].rm_so != -1); - if (get_bool_arg (line, &match[2])) - filter_set_default_policy (FILTER_DEFAULT_DENY); - return 0; + 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]); + return set_bool_arg (&conf->filter_casesensitive, line, &match[2]); } #endif #ifdef REVERSE_SUPPORT -static -HANDLE_FUNC (handle_reverseonly) +static HANDLE_FUNC (handle_reverseonly) { - return set_bool_arg (&conf->reverseonly, line, &match[2]); + 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]); + 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]); + 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. - */ - char *arg1, *arg2; + /* + * The second string argument is optional. + */ + char *arg1, *arg2; - arg1 = get_string_arg (line, &match[2]); - if (!arg1) - return -1; + arg1 = get_string_arg (line, &match[2]); + if (!arg1) + return -1; - if (match[3].rm_so != -1) - { - arg2 = get_string_arg (line, &match[3]); - if (!arg2) - { - safefree (arg1); - return -1; + if (match[3].rm_so != -1) { + arg2 = get_string_arg (line, &match[3]); + if (!arg2) { + safefree (arg1); + return -1; + } + reversepath_add (arg1, arg2); + safefree (arg1); + safefree (arg2); + } else { + reversepath_add (NULL, arg1); + safefree (arg1); } - reversepath_add (arg1, arg2); - safefree (arg1); - safefree (arg2); - } - else - { - reversepath_add (NULL, arg1); - safefree (arg1); - } - return 0; + return 0; } #endif #ifdef UPSTREAM_SUPPORT -static -HANDLE_FUNC (handle_upstream) -{ - char *ip; - int port; - char *domain; - - ip = get_string_arg (line, &match[2]); - if (!ip) - return -1; - port = (int)get_int_arg (line, &match[7]); - - if (match[9].rm_so != -1) - { - domain = get_string_arg (line, &match[9]); - if (domain) - { - upstream_add (ip, port, domain); - safefree (domain); +static HANDLE_FUNC (handle_upstream) +{ + char *ip; + int port; + char *domain; + + ip = get_string_arg (line, &match[2]); + if (!ip) + return -1; + port = (int) get_int_arg (line, &match[7]); + + if (match[9].rm_so != -1) { + domain = get_string_arg (line, &match[9]); + if (domain) { + upstream_add (ip, port, domain); + safefree (domain); + } + } else { + upstream_add (ip, port, NULL); } - } - else - { - upstream_add (ip, port, NULL); - } - safefree (ip); + safefree (ip); - return 0; + return 0; } -static -HANDLE_FUNC (handle_upstream_no) +static HANDLE_FUNC (handle_upstream_no) { - char *domain; + char *domain; - domain = get_string_arg (line, &match[2]); - if (!domain) - return -1; + domain = get_string_arg (line, &match[2]); + if (!domain) + return -1; - upstream_add (NULL, 0, domain); - safefree (domain); + upstream_add (NULL, 0, domain); + safefree (domain); - return 0; + return 0; } #endif diff --git a/src/conns.c b/src/conns.c index 2339dd1..8796c13 100644 --- a/src/conns.c +++ b/src/conns.c @@ -30,119 +30,118 @@ #include "log.h" #include "stats.h" -struct conn_s * -initialize_conn (int client_fd, const char *ipaddr, const char *string_addr, - const char *sock_ipaddr) +struct conn_s *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 = (struct conn_s *)safemalloc (sizeof (struct conn_s)); - if (!connptr) - goto error_exit; + /* + * Allocate the space for the conn_s structure itself. + */ + connptr = (struct conn_s *) 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); - - return NULL; + /* + * If we got here, there was a problem allocating memory + */ + if (cbuffer) + delete_buffer (cbuffer); + if (sbuffer) + delete_buffer (sbuffer); + + return NULL; } -void -destroy_conn (struct conn_s *connptr) +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 f28c2c1..b63d026 100644 --- a/src/conns.h +++ b/src/conns.h @@ -27,68 +27,65 @@ /* * Connection Definition */ -struct conn_s -{ - int client_fd; - int server_fd; - - struct buffer_s *cbuffer; - struct buffer_s *sbuffer; - - /* The request line (first line) from the client */ - char *request_line; - - /* 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; +struct conn_s { + int client_fd; + int server_fd; + + struct buffer_s *cbuffer; + struct buffer_s *sbuffer; + + /* The request line (first line) from the client */ + char *request_line; + + /* 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; #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 - /* - * Pointer to upstream proxy. - */ - struct upstream *upstream_proxy; + /* + * Pointer to upstream proxy. + */ + struct upstream *upstream_proxy; }; /* diff --git a/src/daemon.c b/src/daemon.c index 17d41b5..9a87d7a 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -29,29 +29,28 @@ * Fork a child process and then kill the parent so make the calling * program a daemon process. */ -void -makedaemon (void) +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 (0177); + chdir ("/"); + umask (0177); #if NDEBUG - /* - * When not in debugging mode, close the standard file - * descriptors. - */ - close (0); - close (1); - close (2); + /* + * When not in debugging mode, close the standard file + * descriptors. + */ + close (0); + close (1); + close (2); #endif } @@ -59,29 +58,25 @@ makedaemon (void) * Pass a signal number and a signal handling function into this function * to handle signals sent to the process. */ -signal_func * -set_signal_handler (int signo, signal_func * func) +signal_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/filter.c b/src/filter.c index d74ebb7..7a34583 100644 --- a/src/filter.c +++ b/src/filter.c @@ -33,11 +33,10 @@ static int err; -struct filter_list -{ - struct filter_list *next; - char *pat; - regex_t *cpat; +struct filter_list { + struct filter_list *next; + char *pat; + regex_t *cpat; }; static struct filter_list *fl = NULL; @@ -47,179 +46,172 @@ static filter_policy_t default_policy = FILTER_DEFAULT_ALLOW; /* * Initializes a linked list of strings containing hosts/urls to be filtered */ -void -filter_init (void) +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 = (struct filter_list *)safecalloc (1, - sizeof (struct filter_list)); - else - { /* next entry */ - p->next = (struct filter_list *)safecalloc (1, - sizeof (struct filter_list)); - p = p->next; - } - - p->pat = safestrdup (s); - p->cpat = (regex_t *)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); + 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 = + (struct filter_list *) + safecalloc (1, + sizeof (struct + filter_list)); + else { /* next entry */ + p->next = + (struct filter_list *) + safecalloc (1, + sizeof (struct + filter_list)); + p = p->next; + } + + p->pat = safestrdup (s); + p->cpat = + (regex_t *) 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; } - } - if (ferror (fd)) - { - perror ("fgets"); - exit (EX_DATAERR); - } - fclose (fd); - - already_init = 1; } - } } /* unlink the list */ -void -filter_destroy (void) +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); + 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; } - fl = NULL; - already_init = 0; - } } /* Return 0 to allow, non-zero to block */ -int -filter_domain (const char *host) +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; + 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; + 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) +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; + 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; + if (default_policy == FILTER_DEFAULT_ALLOW) + return 0; + else + return 1; } /* * Set the default filtering policy */ -void -filter_set_default_policy (filter_policy_t policy) +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 17974a6..e089143 100644 --- a/src/filter.h +++ b/src/filter.h @@ -21,10 +21,9 @@ #ifndef _TINYPROXY_FILTER_H_ #define _TINYPROXY_FILTER_H_ -typedef enum -{ - FILTER_DEFAULT_ALLOW, - FILTER_DEFAULT_DENY, +typedef enum { + 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 4b16941..74eb9c1 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -37,26 +37,23 @@ * internal use. It stores the number of buckets the hashmap was created * with. */ -struct hashentry_s -{ - char *key; - void *data; - size_t len; +struct hashentry_s { + char *key; + void *data; + size_t len; - struct hashentry_s *prev, *next; + struct hashentry_s *prev, *next; }; -struct hashbucket_s -{ - struct hashentry_s *head, *tail; +struct hashbucket_s { + struct hashentry_s *head, *tail; }; -struct hashmap_s -{ - unsigned int size; - hashmap_iter end_iterator; +struct hashmap_s { + unsigned int size; + hashmap_iter end_iterator; - struct hashbucket_s *buckets; + struct hashbucket_s *buckets; }; /* @@ -68,27 +65,25 @@ struct hashmap_s * * If any of the arguments are invalid a negative number is returned. */ -static int -hashfunc (const char *key, unsigned int size) +static int hashfunc (const char *key, unsigned int size) { - uint32_t hash; + uint32_t hash; - if (key == NULL) - return -EINVAL; - if (size == 0) - return -ERANGE; + 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; + for (hash = tolower (*key++); *key != '\0'; key++) { + uint32_t bit = (hash & 1) ? (1 << (sizeof (uint32_t) - 1)) : 0; - hash >>= 1; + hash >>= 1; - hash += tolower (*key) + bit; - } + hash += tolower (*key) + bit; + } - /* Keep the hash within the table limits */ - return hash % size; + /* Keep the hash within the table limits */ + return hash % size; } /* @@ -98,31 +93,30 @@ hashfunc (const char *key, unsigned int size) * * NULLs are also returned if memory could not be allocated for hashmap. */ -hashmap_t -hashmap_create (unsigned int nbuckets) +hashmap_t hashmap_create (unsigned int nbuckets) { - struct hashmap_s *ptr; - - if (nbuckets == 0) - return NULL; - - ptr = (struct hashmap_s *)safecalloc (1, sizeof (struct hashmap_s)); - if (!ptr) - return NULL; - - ptr->size = nbuckets; - ptr->buckets = (struct hashbucket_s *)safecalloc (nbuckets, - sizeof (struct hashbucket_s)); - if (!ptr->buckets) - { - safefree (ptr); - return NULL; - } + struct hashmap_s *ptr; + + if (nbuckets == 0) + return NULL; + + ptr = (struct hashmap_s *) safecalloc (1, sizeof (struct hashmap_s)); + if (!ptr) + return NULL; + + ptr->size = nbuckets; + ptr->buckets = (struct hashbucket_s *) 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; } /* @@ -132,28 +126,26 @@ hashmap_create (unsigned int nbuckets) * Returns: 0 if the function completed successfully * negative number is returned if "entry" was NULL */ -static inline int -delete_hashbucket (struct hashbucket_s *bucket) +static inline int 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; } /* @@ -162,26 +154,23 @@ delete_hashbucket (struct hashbucket_s *bucket) * Returns: 0 on success * negative if a NULL "map" was supplied */ -int -hashmap_delete (hashmap_t map) +int hashmap_delete (hashmap_t map) { - unsigned int i; + unsigned int i; - if (map == NULL) - return -EINVAL; + 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; } /* @@ -197,67 +186,65 @@ hashmap_delete (hashmap_t map) int 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; - - data_copy = safemalloc (len); - if (!data_copy) - { - safefree (key_copy); - return -ENOMEM; - } - memcpy (data_copy, data, len); - - ptr = (struct hashentry_s *)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. - */ - ptr->next = NULL; - 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; + 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; + + data_copy = safemalloc (len); + if (!data_copy) { + safefree (key_copy); + return -ENOMEM; + } + memcpy (data_copy, data, len); + + ptr = (struct hashentry_s *) 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. + */ + ptr->next = NULL; + 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; } /* @@ -265,18 +252,17 @@ hashmap_insert (hashmap_t map, const char *key, const void *data, size_t len) * * Returns: an negative value upon error. */ -hashmap_iter -hashmap_first (hashmap_t map) +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; } /* @@ -285,19 +271,18 @@ hashmap_first (hashmap_t map) * Returns: 1 if it is the end * 0 otherwise */ -int -hashmap_is_end (hashmap_t map, hashmap_iter iter) +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; } /* @@ -308,41 +293,37 @@ 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 */ -hashmap_iter -hashmap_find (hashmap_t map, const char *key) +hashmap_iter 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; + 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; + return iter; } /* @@ -352,41 +333,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++; + 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; + return -EFAULT; } /* @@ -396,33 +373,31 @@ hashmap_return_entry (hashmap_t map, hashmap_iter iter, char **key, * zero if no key is found * count found */ -ssize_t -hashmap_search (hashmap_t map, const char *key) +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; } /* @@ -433,33 +408,30 @@ hashmap_search (hashmap_t map, const char *key) * zero if no entry is found * length of data for the entry */ -ssize_t -hashmap_entry_by_key (hashmap_t map, const char *key, void **data) +ssize_t 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; } /* @@ -470,56 +442,53 @@ hashmap_entry_by_key (hashmap_t map, const char *key, void **data) * 0 if the key was not found * positive count of entries deleted */ -ssize_t -hashmap_remove (hashmap_t map, const char *key) +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. - */ - next = ptr->next; - - if (ptr->prev) - ptr->prev->next = ptr->next; - if (ptr->next) - ptr->next->prev = ptr->prev; - - if (map->buckets[hash].head == ptr) - 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; - - ptr = next; - continue; + 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) + ptr->next->prev = ptr->prev; + + if (map->buckets[hash].head == ptr) + 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; + + ptr = next; + 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 e317f08..5095f77 100644 --- a/src/hashmap.h +++ b/src/hashmap.h @@ -26,15 +26,15 @@ * 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 @@ -45,15 +45,15 @@ * 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. @@ -61,7 +61,7 @@ * 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 @@ -71,7 +71,7 @@ * 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. @@ -81,8 +81,8 @@ * 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 @@ -92,8 +92,8 @@ * 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 @@ -103,7 +103,7 @@ * 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. @@ -113,6 +113,6 @@ * 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); -#endif /* _HASHMAP_H */ +#endif /* _HASHMAP_H */ @@ -27,73 +27,68 @@ #include "heap.h" #include "text.h" -void * -debugging_calloc (size_t nmemb, size_t size, const char *file, - unsigned long line) +void *debugging_calloc (size_t nmemb, size_t size, const char *file, + 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:%zu x %zu} %s:%lu\n", ptr, nmemb, size, file, - line); - return ptr; + ptr = calloc (nmemb, size); + fprintf (stderr, "{calloc: %p:%zu x %zu} %s:%lu\n", ptr, nmemb, size, + file, line); + return ptr; } -void * -debugging_malloc (size_t size, const char *file, unsigned long line) +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:%zu} %s:%lu\n", ptr, size, file, line); - return ptr; + ptr = malloc (size); + fprintf (stderr, "{malloc: %p:%zu} %s:%lu\n", ptr, size, file, line); + return ptr; } -void * -debugging_realloc (void *ptr, size_t size, const char *file, - unsigned long line) +void *debugging_realloc (void *ptr, size_t size, const char *file, + unsigned long line) { - void *newptr; + void *newptr; - assert (size > 0); + assert (size > 0); - newptr = realloc (ptr, size); - fprintf (stderr, "{realloc: %p -> %p:%zu} %s:%lu\n", ptr, newptr, size, - file, line); - return newptr; + newptr = realloc (ptr, size); + fprintf (stderr, "{realloc: %p -> %p:%zu} %s:%lu\n", ptr, newptr, size, + file, line); + return newptr; } -void -debugging_free (void *ptr, const char *file, unsigned long line) +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 = (char *)malloc (len); - if (!ptr) - return NULL; - memcpy (ptr, s, len); + len = strlen (s) + 1; + ptr = (char *) malloc (len); + if (!ptr) + return NULL; + memcpy (ptr, s, len); - fprintf (stderr, "{strdup: %p:%zu} %s:%lu\n", ptr, len, file, line); - return ptr; + fprintf (stderr, "{strdup: %p:%zu} %s:%lu\n", ptr, len, file, line); + return ptr; } /* @@ -104,55 +99,53 @@ 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 * -malloc_shared_memory (size_t size) +void *malloc_shared_memory (size_t size) { - int fd; - void *ptr; - char buffer[32]; + int fd; + void *ptr; + char buffer[32]; - static const char *shared_file = "/tmp/tinyproxy.shared.XXXXXX"; + static const 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)); - /* Only allow u+rw bits. This may be required for some versions - * of glibc so that mkstemp() doesn't make us vulnerable. - */ - umask (0177); + /* Only allow u+rw bits. This may be required for some versions + * of glibc so that mkstemp() doesn't make us vulnerable. + */ + umask (0177); - 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 * -calloc_shared_memory (size_t nmemb, size_t size) +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; } diff --git a/src/html-error.c b/src/html-error.c index fa6c02a..b096cc4 100644 --- a/src/html-error.c +++ b/src/html-error.c @@ -36,74 +36,71 @@ #define ERRORNUM_BUFSIZE 8 /* this is more than required */ #define ERRPAGES_BUCKETCOUNT 16 -int -add_new_errorpage (char *filepath, unsigned int errornum) +int add_new_errorpage (char *filepath, unsigned int errornum) { - char errornbuf[ERRORNUM_BUFSIZE]; + 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) +static char *get_html_file (unsigned int errornum) { - hashmap_iter result_iter; - char errornbuf[ERRORNUM_BUFSIZE]; - char *key; - static char *val; + 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, const char *varname) +static char *lookup_variable (struct conn_s *connptr, const char *varname) { - hashmap_iter result_iter; - char *key; - static char *data; + 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 @@ -111,116 +108,113 @@ lookup_variable (struct conn_s *connptr, const char *varname) /* * Send an already-opened file to the client with variable substitution. */ -int -send_html_file (FILE * infile, struct conn_s *connptr) +int send_html_file (FILE * infile, struct conn_s *connptr) { - char inbuf[HTML_BUFSIZE], *varstart = NULL, *p; - const 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'; - varval = (const char *)lookup_variable (connptr, varstart); - if (!varval) - 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); + char inbuf[HTML_BUFSIZE], *varstart = NULL, *p; + const 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'; + varval = + (const char *) + lookup_variable (connptr, varstart); + if (!varval) + 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); + } + + } } - 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); + return (0); } -int -send_http_headers (struct conn_s *connptr, int code, const char *message) +int send_http_headers (struct conn_s *connptr, int code, const char *message) { - const 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"; + const char *headers = + "HTTP/1.0 %d %s\r\n" + "Server: %s/%s\r\n" + "Content-Type: text/html\r\n" "Connection: close\r\n" "\r\n"; - return (write_message (connptr->client_fd, headers, - code, message, PACKAGE, VERSION)); + return (write_message (connptr->client_fd, headers, + code, message, PACKAGE, VERSION)); } /* * Display an error to the client. */ -int -send_http_error_message (struct conn_s *connptr) +int send_http_error_message (struct conn_s *connptr) { - char *error_file; - FILE *infile; - int ret; - const char *fallback_error = - "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" - "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" " - "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n" - "<html>\n" - "<head><title>%d %s</title></head>\n" - "<body>\n" - "<h1>%s</h1>\n" - "<p>%s</p>\n" - "<hr />\n" - "<p><em>Generated by %s version %s.</em></p>\n" "</body>\n" "</html>\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"))) - { - char *detail = lookup_variable (connptr, "detail"); - return (write_message (connptr->client_fd, fallback_error, - connptr->error_number, - connptr->error_string, - connptr->error_string, - detail, PACKAGE, VERSION)); - } - - ret = send_html_file (infile, connptr); - fclose (infile); - return (ret); + char *error_file; + FILE *infile; + int ret; + const char *fallback_error = + "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" " + "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n" + "<html>\n" + "<head><title>%d %s</title></head>\n" + "<body>\n" + "<h1>%s</h1>\n" + "<p>%s</p>\n" + "<hr />\n" + "<p><em>Generated by %s version %s.</em></p>\n" "</body>\n" + "</html>\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"))) { + char *detail = lookup_variable (connptr, "detail"); + return (write_message (connptr->client_fd, fallback_error, + connptr->error_number, + connptr->error_string, + connptr->error_string, + detail, PACKAGE, VERSION)); + } + + ret = send_html_file (infile, connptr); + fclose (infile); + return (ret); } /* @@ -232,12 +226,14 @@ send_http_error_message (struct conn_s *connptr) int add_error_variable (struct conn_s *connptr, const char *key, const char *val) { - if (!connptr->error_variables) - if (!(connptr->error_variables = hashmap_create (ERRVAR_BUCKETCOUNT))) - return (-1); - - return hashmap_insert (connptr->error_variables, key, val, - strlen (val) + 1); + if (!connptr->error_variables) + if (! + (connptr->error_variables = + hashmap_create (ERRVAR_BUCKETCOUNT))) + return (-1); + + return hashmap_insert (connptr->error_variables, key, val, + strlen (val) + 1); } #define ADD_VAR_RET(x, y) \ @@ -251,36 +247,36 @@ add_error_variable (struct conn_s *connptr, const char *key, const char *val) /* * Set some standard variables used by all HTML pages */ -int -add_standard_vars (struct conn_s *connptr) +int add_standard_vars (struct conn_s *connptr) { - char errnobuf[16]; - char timebuf[30]; - time_t global_time; - - snprintf (errnobuf, sizeof errnobuf, "%d", connptr->error_number); - ADD_VAR_RET ("errno", errnobuf); - - ADD_VAR_RET ("cause", connptr->error_string); - ADD_VAR_RET ("request", connptr->request_line); - ADD_VAR_RET ("clientip", connptr->client_ip_addr); - ADD_VAR_RET ("clienthost", connptr->client_string_addr); - - /* The following value parts are all non-NULL and will - * trigger warnings in ADD_VAR_RET(), so we use - * add_error_variable() directly. - */ - - global_time = time (NULL); - strftime (timebuf, sizeof (timebuf), "%a, %d %b %Y %H:%M:%S GMT", - gmtime (&global_time)); - add_error_variable (connptr, "date", timebuf); - - add_error_variable (connptr, "website", "http://www.banu.com/tinyproxy/"); - add_error_variable (connptr, "version", VERSION); - add_error_variable (connptr, "package", PACKAGE); - - return (0); + char errnobuf[16]; + char timebuf[30]; + time_t global_time; + + snprintf (errnobuf, sizeof errnobuf, "%d", connptr->error_number); + ADD_VAR_RET ("errno", errnobuf); + + ADD_VAR_RET ("cause", connptr->error_string); + ADD_VAR_RET ("request", connptr->request_line); + ADD_VAR_RET ("clientip", connptr->client_ip_addr); + ADD_VAR_RET ("clienthost", connptr->client_string_addr); + + /* The following value parts are all non-NULL and will + * trigger warnings in ADD_VAR_RET(), so we use + * add_error_variable() directly. + */ + + global_time = time (NULL); + strftime (timebuf, sizeof (timebuf), "%a, %d %b %Y %H:%M:%S GMT", + gmtime (&global_time)); + add_error_variable (connptr, "date", timebuf); + + add_error_variable (connptr, "website", + "http://www.banu.com/tinyproxy/"); + add_error_variable (connptr, "version", VERSION); + add_error_variable (connptr, "package", PACKAGE); + + return (0); } /* @@ -290,26 +286,24 @@ int indicate_http_error (struct conn_s *connptr, int number, const 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/http-message.c b/src/http-message.c index ad14ce7..8b94f19 100644 --- a/src/http-message.c +++ b/src/http-message.c @@ -30,33 +30,29 @@ * Also, the caller MUST NOT free the memory while the structure is * 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 - { - const 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; +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 { + const 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; }; /* @@ -64,19 +60,18 @@ struct http_message_s * function. It returns 0 if the message is invalid; otherwise, a positive * number is returned. Useful for if() tests and assert() tests. */ -static int -is_http_message_valid (http_message_t msg) +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 */ @@ -89,33 +84,34 @@ is_http_message_valid (http_message_t msg) http_message_t http_message_create (int response_code, const char *response_string) { - http_message_t msg; - int ret; - - msg = (struct http_message_s *)safecalloc (1, sizeof (struct http_message_s)); - if (msg == NULL) - return NULL; - - msg->headers.strings = (const char **)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 = + (struct http_message_s *) safecalloc (1, + sizeof (struct + http_message_s)); + if (msg == NULL) + return NULL; + + msg->headers.strings = (const char **) 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; } /* @@ -123,20 +119,19 @@ http_message_create (int response_code, const char *response_string) * This DOES NOT free the pointers stored in this structure. That memory * is the responsibility of the caller. */ -int -http_message_destroy (http_message_t msg) +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; } /* @@ -147,40 +142,39 @@ int http_message_set_response (http_message_t msg, 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) +int 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; } /* @@ -190,89 +184,88 @@ int http_message_add_headers (http_message_t msg, const char **headers, unsigned int num_headers) { - const char **new_headers; - unsigned int i; - - /* Check for valid arguments */ - if (msg == NULL) - return -EFAULT; - if (headers == NULL) - 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 = (const char **)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; + const char **new_headers; + unsigned int i; + + /* Check for valid arguments */ + if (msg == NULL) + return -EFAULT; + if (headers == NULL) + 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 = + (const char **) 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; } /* * Send the completed HTTP message via the supplied file descriptor. */ -int -http_message_send (http_message_t msg, int fd) +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; } @@ -29,15 +29,15 @@ #include "vector.h" static const 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 @@ -64,178 +64,162 @@ 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) +int 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; } /* * Close the log file */ -void -close_log_file (void) +void close_log_file (void) { - close (log_file_fd); + close (log_file_fd); } /* * Truncate log file to a zero length. */ -void -truncate_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); } /* * Set the log level for writing to the log file. */ -void -set_log_level (int level) +void set_log_level (int level) { - log_level = level; + log_level = level; } /* * This routine logs messages to either the log file or the syslog function. */ -void -log_message (int level, const char *fmt, ...) +void log_message (int level, const 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); - - /* - * 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) - goto out; - } + 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; - vsnprintf (str, STRING_LENGTH, fmt, args); + if (!log_message_storage) { + log_message_storage = vector_create (); + if (!log_message_storage) + goto out; + } - entry_buffer = (char *)safemalloc (strlen (str) + 6); - if (!entry_buffer) - goto out; + vsnprintf (str, STRING_LENGTH, fmt, args); - sprintf (entry_buffer, "%d %s", level, str); - vector_append (log_message_storage, entry_buffer, - strlen (entry_buffer) + 1); + entry_buffer = (char *) safemalloc (strlen (str) + 6); + if (!entry_buffer) + goto out; - safefree (entry_buffer); - goto out; - } + sprintf (entry_buffer, "%d %s", level, str); + vector_append (log_message_storage, entry_buffer, + strlen (entry_buffer) + 1); + + safefree (entry_buffer); + goto out; + } #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); - fsync (log_file_fd); + 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 out: - va_end (args); + va_end (args); } /* * This needs to send any stored log messages. */ -void -send_stored_logs (void) +void send_stored_logs (void) { - char *string; - char *ptr; + char *string; + char *ptr; - int level; + int level; - size_t i; + size_t i; - for (i = 0; (ssize_t)i != vector_length (log_message_storage); ++i) - { - string = (char *)vector_getentry (log_message_storage, i, NULL); + for (i = 0; (ssize_t) i != vector_length (log_message_storage); ++i) { + string = + (char *) 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; } @@ -54,48 +54,44 @@ unsigned int processed_config_file = FALSE; /* boolean */ /* * Handle a signal */ -RETSIGTYPE -takesig (int sig) +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; } /* * Display the version information for the user. */ -static void -display_version (void) +static void display_version (void) { - printf ("%s %s (%s)\n", PACKAGE, VERSION, TARGET_SYSTEM); + printf ("%s %s (%s)\n", PACKAGE, VERSION, TARGET_SYSTEM); } /* * Display the copyright and license for this program. */ -static void -display_license (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\ @@ -119,11 +115,10 @@ display_license (void) /* * Display usage to the user. */ -static void -display_usage (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\ @@ -131,346 +126,319 @@ 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"); + printf (" XTinyproxy header\n"); #endif /* XTINYPROXY */ #ifdef FILTER_ENABLE - printf (" Filtering\n"); + printf (" Filtering\n"); #endif /* FILTER_ENABLE */ #ifndef NDEBUG - printf (" Debugging code\n"); + 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"); + printf (" Reverse proxy support\n"); #endif /* REVERSE_SUPPORT */ } -static int -get_id (char *str) +static int get_id (char *str) { - char *tstr; + char *tstr; - if (str == NULL) - return -1; + if (str == NULL) + return -1; - tstr = str; - while (*tstr != 0) - { - if (!isdigit (*tstr)) - return -1; - tstr++; - } + tstr = str; + while (*tstr != 0) { + if (!isdigit (*tstr)) + return -1; + tstr++; + } - return atoi (str); + return atoi (str); } -int -main (int argc, char **argv) +int main (int argc, char **argv) { - int optch; - unsigned int godaemon = TRUE; /* boolean */ - struct passwd *thisuser = NULL; - struct group *thisgroup = NULL; - FILE *config_file; - - /* Only allow u+rw bits. This may be required for some versions - * of glibc so that mkstemp() doesn't make us vulnerable. - */ - umask (0177); - - /* 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); + int optch; + unsigned int godaemon = TRUE; /* boolean */ + struct passwd *thisuser = NULL; + struct group *thisgroup = NULL; + FILE *config_file; + + /* Only allow u+rw bits. This may be required for some versions + * of glibc so that mkstemp() doesn't make us vulnerable. + */ + umask (0177); + + /* 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); } - } - - 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); - } - if (config_compile () || config_parse (&config, config_file)) - { - fprintf (stderr, - "Unable to parse configuration file. Not starting.\n"); - exit (EX_SOFTWARE); - } - fclose (config_file); - - /* - * Write to a user supplied log file if it's defined. This - * will override using the syslog even if syslog is defined. - */ - if (config.logf_name) - { - if (open_log_file (config.logf_name) < 0) - { - fprintf (stderr, "%s: Could not create log file.\n", argv[0]); - exit (EX_SOFTWARE); + if (config_compile () || config_parse (&config, config_file)) { + fprintf (stderr, + "Unable to parse configuration file. Not starting.\n"); + exit (EX_SOFTWARE); + } + fclose (config_file); + + /* + * Write to a user supplied log file if it's defined. This + * will override using the syslog even if syslog is defined. + */ + if (config.logf_name) { + if (open_log_file (config.logf_name) < 0) { + fprintf (stderr, "%s: Could not create log file.\n", + argv[0]); + exit (EX_SOFTWARE); + } + 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 { + 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.user) { + 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); + } } - 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 - { - 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.user) - { - 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); } - } - - 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 (); + 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) - { - int gid = get_id (config.group); - if (gid < 0) - { - thisgroup = getgrnam (config.group); - if (!thisgroup) - { - fprintf (stderr, - "%s: Unable to find " - "group \"%s\".\n", argv[0], config.group); - exit (EX_NOUSER); - } - gid = thisgroup->gr_gid; - } - if (setgid (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); + /* + * 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); } - if (config.user && strlen (config.user) > 0) - { - int uid = get_id (config.user); - if (uid < 0) - { - thisuser = getpwnam (config.user); - if (!thisuser) - { - fprintf (stderr, - "%s: Unable to find " - "user \"%s\".\n", argv[0], config.user); - exit (EX_NOUSER); + + /* + * Switch to a different user. + */ + if (geteuid () == 0) { + if (config.group && strlen (config.group) > 0) { + int gid = get_id (config.group); + if (gid < 0) { + thisgroup = getgrnam (config.group); + if (!thisgroup) { + fprintf (stderr, + "%s: Unable to find " + "group \"%s\".\n", argv[0], + config.group); + exit (EX_NOUSER); + } + gid = thisgroup->gr_gid; + } + if (setgid (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.user && strlen (config.user) > 0) { + int uid = get_id (config.user); + if (uid < 0) { + thisuser = getpwnam (config.user); + if (!thisuser) { + fprintf (stderr, + "%s: Unable to find " + "user \"%s\".\n", argv[0], + config.user); + exit (EX_NOUSER); + } + uid = thisuser->pw_uid; + } + if (setuid (uid) < 0) { + fprintf (stderr, + "%s: Unable to change to user \"%s\".\n", + argv[0], config.user); + exit (EX_CANTCREAT); + } + log_message (LOG_INFO, "Now running as user \"%s\".", + config.user); } - uid = thisuser->pw_uid; - } - if (setuid (uid) < 0) - { - fprintf (stderr, - "%s: Unable to change to user \"%s\".\n", - argv[0], config.user); - exit (EX_CANTCREAT); - } - log_message (LOG_INFO, "Now running as user \"%s\".", config.user); + } 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.\n", + 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)); } - } - 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.\n", 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 (); + 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); } @@ -33,72 +33,70 @@ * 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 { + struct upstream *next; + char *domain; /* optional */ + char *host; + int port; + in_addr_t ip, mask; }; /* * Hold all the configuration time information. */ -struct config_s -{ - char *logf_name; - const char *config_file; - unsigned int syslog; /* boolean */ - int port; - char *stathost; - unsigned int quit; /* boolean */ - char *user; - char *group; - char *ipAddr; +struct config_s { + char *logf_name; + const char *config_file; + unsigned int syslog; /* boolean */ + int port; + char *stathost; + unsigned int quit; /* boolean */ + char *user; + char *group; + char *ipAddr; #ifdef FILTER_ENABLE - char *filter; - unsigned int filter_url; /* boolean */ - unsigned int filter_extended; /* boolean */ - unsigned int filter_casesensitive; /* boolean */ + 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; + struct upstream *upstream_list; #endif /* UPSTREAM_SUPPORT */ - char *pidpath; - unsigned int idletimeout; - char *bind_address; - unsigned int bindsame; + 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 */ diff --git a/src/network.c b/src/network.c index fc74e69..61dcbae 100644 --- a/src/network.c +++ b/src/network.c @@ -32,56 +32,50 @@ * Write the buffer to the socket. If an EINTR occurs, pick up and try * again. Keep sending until the buffer has been sent. */ -ssize_t -safe_write (int fd, const char *buffer, size_t count) +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 ((size_t)len == bytestosend) - break; + if ((size_t) len == bytestosend) + break; - buffer += len; - bytestosend -= len; - } + buffer += len; + bytestosend -= len; + } - return count; + return count; } /* * Matched pair for safe_write(). If an EINTR occurs, pick up and try * again. */ -ssize_t -safe_read (int fd, 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; } /* @@ -90,52 +84,47 @@ safe_read (int fd, char *buffer, size_t count) * was basically stolen from the snprintf() man page of Debian Linux * (although I did fix a memory leak. :) */ -int -write_message (int fd, const char *fmt, ...) +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 = (char *)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 && (size_t)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 = (char *)saferealloc (buf, size)) == NULL) - { - safefree (buf); - return -1; + ssize_t n; + size_t size = (1024 * 8); /* start with 8 KB and go from there */ + char *buf, *tmpbuf; + va_list ap; + + if ((buf = (char *) 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 && (size_t) 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 = (char *) saferealloc (buf, size)) == NULL) { + safefree (buf); + return -1; + } else + buf = tmpbuf; + } + + if (safe_write (fd, buf, n) < 0) { + safefree (buf); + return -1; } - else - buf = tmpbuf; - } - - if (safe_write (fd, buf, n) < 0) - { - safefree (buf); - return -1; - } - - safefree (buf); - return 0; + + safefree (buf); + return 0; } /* @@ -149,152 +138,142 @@ write_message (int fd, const char *fmt, ...) */ #define SEGMENT_LEN (512) #define MAXIMUM_BUFFER_LENGTH (128 * 1024) -ssize_t -readline (int fd, char **whole_buffer) +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 = (struct read_lines_s *)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 = (char *)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; + 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 = + (struct read_lines_s *) 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 = (char *) 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 = (char *) 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 = + (struct read_lines_s *) + safecalloc (sizeof (struct read_lines_s), 1); + if (!line_ptr->next) { + ret = -ENOMEM; + goto CLEANUP; + } + line_ptr = line_ptr->next; } - line_ptr->data = (char *)safemalloc (diff); - if (!line_ptr->data) - { - ret = -ENOMEM; - goto CLEANUP; + *whole_buffer = (char *) safemalloc (whole_buffer_len + 1); + if (!*whole_buffer) { + ret = -ENOMEM; + goto CLEANUP; } - recv (fd, line_ptr->data, diff, 0); - line_ptr->len = diff; + *(*whole_buffer + whole_buffer_len) = '\0'; - if (ptr) - { - line_ptr->next = NULL; - break; - } + 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->next = - (struct read_lines_s *)safecalloc (sizeof (struct read_lines_s), 1); - if (!line_ptr->next) - { - ret = -ENOMEM; - goto CLEANUP; + line_ptr = line_ptr->next; } - line_ptr = line_ptr->next; - } - - *whole_buffer = (char *)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; + 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; } /* @@ -304,43 +283,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) +int 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); } @@ -51,7 +51,6 @@ */ #define HTTP_LINE_LENGTH (MAXBUFFSIZE / 6) - /* * Macro to help test if the Upstream proxy supported is compiled in and * enabled. @@ -83,28 +82,25 @@ */ static vector_t ports_allowed_by_connect = NULL; - /* * Now, this routine adds a "port" to the list. It also creates the list if * it hasn't already by done. */ -void -add_connect_port_allowed (int port) +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; + 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)); + log_message (LOG_INFO, + "Adding Port [%d] to the list allowed by CONNECT", port); + vector_append (ports_allowed_by_connect, (void **) &port, + sizeof (port)); } /* @@ -113,27 +109,26 @@ add_connect_port_allowed (int port) * Returns: 1 if allowed * 0 if denied */ -static int -check_allowed_connect_ports (int port) +static int check_allowed_connect_ports (int port) { - size_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; - - for (i = 0; i != (size_t)vector_length (ports_allowed_by_connect); ++i) - { - data = (int *)vector_getentry (ports_allowed_by_connect, i, NULL); - if (data && *data == port) - return 1; - } - - return 0; + size_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; + + for (i = 0; i != (size_t) vector_length (ports_allowed_by_connect); ++i) { + data = + (int *) vector_getentry (ports_allowed_by_connect, i, NULL); + if (data && *data == port) + return 1; + } + + return 0; } /* @@ -141,365 +136,329 @@ check_allowed_connect_ports (int port) * connections. The request line is allocated from the heap, but it must * be freed in another function. */ -static int -read_request_line (struct conn_s *connptr) +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; } /* * Free all the memory allocated in a request. */ -static void -free_request_struct (struct request_s *request) +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); } /* * Take a host string and if there is a username/password part, strip * it off. */ -static void -strip_username_password (char *host) +static void strip_username_password (char *host) { - char *p; - - assert (host); - assert (strlen (host) > 0); - - if ((p = strchr (host, '@')) == NULL) - return; - - /* - * Move the pointer past the "@" and then copy from that point - * until the NUL to the beginning of the host buffer. - */ - p++; - while (*p) - *host++ = *p++; - *host = '\0'; + char *p; + + assert (host); + assert (strlen (host) > 0); + + if ((p = strchr (host, '@')) == NULL) + return; + + /* + * Move the pointer past the "@" and then copy from that point + * until the NUL to the beginning of the host buffer. + */ + p++; + while (*p) + *host++ = *p++; + *host = '\0'; } /* * Take a host string and if there is a port part, strip * it off and set proper port variable i.e. for www.host.com:8001 */ -static int -strip_return_port (char *host) +static int 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; } /* * Pull the information out of the URL line. This will handle both HTTP * and FTP (proxied) URLs. */ -static int -extract_http_url (const char *url, struct request_s *request) +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 = (char *)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; + 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 = (char *) 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); + if (request->host) + safefree (request->host); + if (request->path) + safefree (request->path); - return -1; + return -1; } /* * Extract the URL from a SSL connection. */ -static int -extract_ssl_url (const char *url, struct request_s *request) +static int extract_ssl_url (const char *url, struct request_s *request) { - request->host = (char *)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 = (char *) 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 UPSTREAM_SUPPORT /* * Add an entry to the upstream list */ -void -upstream_add (const char *host, int port, const char *domain) +void upstream_add (const char *host, int port, const char *domain) { - char *ptr; - struct upstream *up = (struct upstream *)safemalloc(sizeof (struct upstream)); - - if (!up) - { - log_message (LOG_ERR, "Unable to allocate memory in upstream_add()"); - return; - } + char *ptr; + struct upstream *up = + (struct upstream *) 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; + 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; - } + 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; + 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; - } + 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); + 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); } - else - { - up->mask = ~((1 << (32 - atoi (ptr))) - 1); + + 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; } - } - } - 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); } - up->host = safestrdup (host); - up->port = port; - up->domain = safestrdup (domain); + if (!up->domain && !up->ip) { /* always add default to end */ + struct upstream *tmp = config.upstream_list; - log_message (LOG_INFO, "Added upstream %s:%d for %s", - host, port, domain); - } + while (tmp) { + if (!tmp->domain && !tmp->ip) { + log_message (LOG_WARNING, + "Duplicate default upstream"); + goto upstream_cleanup; + } - if (!up->domain && !up->ip) - { /* always add default to end */ - struct upstream *tmp = config.upstream_list; + if (!tmp->next) { + up->next = NULL; + tmp->next = up; + return; + } - 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; + tmp = tmp->next; + } } - } - up->next = config.upstream_list; - config.upstream_list = up; + up->next = config.upstream_list; + config.upstream_list = up; - return; + return; upstream_cleanup: - safefree (up->host); - safefree (up->domain); - safefree (up); + safefree (up->host); + safefree (up->domain); + safefree (up); - return; + return; } /* * Check if a host is in the upstream list */ -static struct upstream * -upstream_get (char *host) +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 @@ -509,20 +468,20 @@ upstream_get (char *host) 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); } /* @@ -535,253 +494,234 @@ establish_http_connection (struct conn_s *connptr, struct request_s *request) * Send the appropriate response to the client to establish a SSL * connection. */ -static inline int -send_ssl_response (struct conn_s *connptr) +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); } /* * Break the request line apart and figure out where to connect and * build a new request line. Finally connect to the remote server. */ -static struct request_s * -process_request (struct conn_s *connptr, hashmap_t hashofheaders) +static struct request_s *process_request (struct conn_s *connptr, + hashmap_t hashofheaders) { - char *url; - struct request_s *request; - int ret; - size_t request_len; - - /* NULL out all the fields so frees don't cause segfaults. */ - request = (struct request_s *)safecalloc (1, sizeof (struct request_s)); - if (!request) - return NULL; - - request_len = strlen (connptr->request_line) + 1; - - request->method = (char *)safemalloc (request_len); - url = (char *)safemalloc (request_len); - request->protocol = (char *)safemalloc (request_len); - - if (!request->method || !url || !request->protocol) - { - safefree (url); - free_request_struct (request); - - return NULL; - } - - ret = sscanf (connptr->request_line, "%[^ ] %[^ ] %[^ ]", - request->method, url, request->protocol); - if (ret == 2 && !strcasecmp (request->method, "GET")) - { - request->protocol[0] = 0; - - /* Indicate that this is a HTTP/0.9 GET request */ - connptr->protocol.major = 0; - connptr->protocol.minor = 9; - } - else if (ret == 3 && !strncasecmp (request->protocol, "HTTP/", 5)) - { - /* - * Break apart the protocol and update the connection - * structure. - */ - ret = sscanf (request->protocol + 5, "%u.%u", - &connptr->protocol.major, &connptr->protocol.minor); - - /* - * If the conversion doesn't succeed, drop down below and - * send the error to the user. - */ - 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; - } -#ifdef REVERSE_SUPPORT - if (config.reversepath_list != NULL) - { - /* - * Rewrite the URL based on the reverse path. After calling - * reverse_rewrite_url "url" can be freed since we either - * have the newly rewritten URL, or something failed and - * we'll be closing anyway. - */ - char *reverse_url; - - reverse_url = reverse_rewrite_url (connptr, hashofheaders, url); - safefree (url); - - if (!reverse_url) - { - free_request_struct (request); - return NULL; - } - else - { - url = reverse_url; - } - } -#endif - - if (strncasecmp (url, "http://", 7) == 0 - || (UPSTREAM_CONFIGURED () && strncasecmp (url, "ftp://", 6) == 0)) - { - char *skipped_type = strstr (url, "//") + 2; + char *url; + struct request_s *request; + int ret; + size_t request_len; - if (extract_http_url (skipped_type, request) < 0) - { - indicate_http_error (connptr, 400, "Bad Request", - "detail", "Could not parse URL", - "url", url, NULL); + /* NULL out all the fields so frees don't cause segfaults. */ + request = + (struct request_s *) safecalloc (1, sizeof (struct request_s)); + if (!request) + return NULL; - safefree (url); - free_request_struct (request); + request_len = strlen (connptr->request_line) + 1; - 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); + request->method = (char *) safemalloc (request_len); + url = (char *) safemalloc (request_len); + request->protocol = (char *) safemalloc (request_len); - safefree (url); - free_request_struct (request); + if (!request->method || !url || !request->protocol) { + safefree (url); + free_request_struct (request); - return NULL; + 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; + ret = sscanf (connptr->request_line, "%[^ ] %[^ ] %[^ ]", + request->method, url, request->protocol); + if (ret == 2 && !strcasecmp (request->method, "GET")) { + request->protocol[0] = 0; + + /* Indicate that this is a HTTP/0.9 GET request */ + connptr->protocol.major = 0; + connptr->protocol.minor = 9; + } else if (ret == 3 && !strncasecmp (request->protocol, "HTTP/", 5)) { + /* + * Break apart the protocol and update the connection + * structure. + */ + ret = sscanf (request->protocol + 5, "%u.%u", + &connptr->protocol.major, + &connptr->protocol.minor); + + /* + * If the conversion doesn't succeed, drop down below and + * send the error to the user. + */ + 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; } - connptr->connect_method = TRUE; - } - else - { -#ifdef TRANSPARENT_PROXY - if (!do_transparent_proxy - (connptr, hashofheaders, request, &config, url)) - { - safefree (url); - free_request_struct (request); - return NULL; - } -#else - indicate_http_error (connptr, 501, "Not Implemented", - "detail", - "Unknown method or unsupported protocol.", "url", - url, NULL); - log_message (LOG_INFO, "Unknown method (%s) or protocol (%s)", - request->method, url); - 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 + if (config.reversepath_list != NULL) { + /* + * Rewrite the URL based on the reverse path. After calling + * reverse_rewrite_url "url" can be freed since we either + * have the newly rewritten URL, or something failed and + * we'll be closing anyway. + */ + char *reverse_url; + + reverse_url = reverse_rewrite_url (connptr, hashofheaders, url); + safefree (url); + + if (!reverse_url) { + free_request_struct (request); + return NULL; + } else { + url = reverse_url; + } + } #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) + if (strncasecmp (url, "http://", 7) == 0 + || (UPSTREAM_CONFIGURED () && strncasecmp (url, "ftp://", 6) == 0)) { - update_stats (STAT_DENIED); + 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); - 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); + 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); - indicate_http_error (connptr, 403, "Filtered", - "detail", - "The request you made has been filtered", - "url", url, NULL); + return NULL; + } - safefree (url); - free_request_struct (request); + /* 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; + } - return NULL; + connptr->connect_method = TRUE; + } else { +#ifdef TRANSPARENT_PROXY + if (!do_transparent_proxy + (connptr, hashofheaders, request, &config, url)) { + safefree (url); + free_request_struct (request); + return NULL; + } +#else + indicate_http_error (connptr, 501, "Not Implemented", + "detail", + "Unknown method or unsupported protocol.", + "url", url, NULL); + log_message (LOG_INFO, "Unknown method (%s) or protocol (%s)", + request->method, url); + 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; + } } - } #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; } /* @@ -790,54 +730,51 @@ process_request (struct conn_s *connptr, hashmap_t hashofheaders) * server headers can be processed. * - rjkaes */ -static int -pull_client_data (struct conn_s *connptr, long int length) +static int pull_client_data (struct conn_s *connptr, long int length) { - char *buffer; - ssize_t len; - - buffer = (char *)safemalloc (min (MAXBUFFSIZE, (unsigned long int)length)); - if (!buffer) - return -1; - - do - { - len = safe_read (connptr->client_fd, buffer, - min (MAXBUFFSIZE, (unsigned long int)length)); - if (len <= 0) - goto ERROR_EXIT; - - if (!connptr->error_variables) - { - if (safe_write (connptr->server_fd, buffer, len) < 0) - goto ERROR_EXIT; - } + char *buffer; + ssize_t len; + + buffer = + (char *) safemalloc (min (MAXBUFFSIZE, (unsigned long int) length)); + if (!buffer) + return -1; + + do { + len = safe_read (connptr->client_fd, buffer, + min (MAXBUFFSIZE, (unsigned long int) 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); + 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); + /* + * 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 < 0 && errno != EAGAIN) + goto ERROR_EXIT; - if (len == 2 && CHECK_CRLF (buffer, len)) - read (connptr->client_fd, buffer, 2); + if (len == 2 && CHECK_CRLF (buffer, len)) + read (connptr->client_fd, buffer, 2); - safefree (buffer); - return 0; + safefree (buffer); + return 0; ERROR_EXIT: - safefree (buffer); - return -1; + safefree (buffer); + return -1; } #ifdef XTINYPROXY_ENABLE @@ -846,12 +783,11 @@ ERROR_EXIT: * the server. * -rjkaes */ -static inline int -add_xtinyproxy_header (struct conn_s *connptr) +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); + assert (connptr && connptr->server_fd >= 0); + return write_message (connptr->server_fd, + "X-Tinyproxy: %s\r\n", connptr->client_ip_addr); } #endif /* XTINYPROXY */ @@ -863,186 +799,178 @@ 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); } /* * Read all the headers from the stream */ -static int -get_all_headers (int fd, hashmap_t hashofheaders) +static int get_all_headers (int fd, hashmap_t hashofheaders) { - char *line = NULL; - char *header = NULL; - char *tmp; - ssize_t linelen; - ssize_t len = 0; - unsigned int double_cgi = FALSE; /* boolean */ - - assert (fd >= 0); - assert (hashofheaders != NULL); - - for (;;) - { - if ((linelen = readline (fd, &line)) <= 0) - { - safefree (header); - safefree (line); - return -1; - } + char *line = NULL; + char *header = NULL; + char *tmp; + ssize_t linelen; + ssize_t len = 0; + unsigned int double_cgi = FALSE; /* boolean */ + + assert (fd >= 0); + assert (hashofheaders != NULL); + + for (;;) { + if ((linelen = readline (fd, &line)) <= 0) { + safefree (header); + safefree (line); + return -1; + } - /* - * If we received a CR LF or a non-continuation line, then add - * the accumulated header field, if any, to the hashmap, and - * reset it. - */ - if (CHECK_CRLF (line, linelen) || !CHECK_LWS (line, linelen)) - { - if (!double_cgi - && len > 0 - && add_header_to_connection (hashofheaders, header, len) < 0) - { - safefree (header); - safefree (line); - return -1; - } - - len = 0; - } + /* + * If we received a CR LF or a non-continuation line, then add + * the accumulated header field, if any, to the hashmap, and + * reset it. + */ + if (CHECK_CRLF (line, linelen) || !CHECK_LWS (line, linelen)) { + if (!double_cgi + && len > 0 + && add_header_to_connection (hashofheaders, header, + len) < 0) { + safefree (header); + safefree (line); + return -1; + } + + len = 0; + } - /* - * If we received just a CR LF on a line, the headers are - * finished. - */ - if (CHECK_CRLF (line, linelen)) - { - safefree (header); - safefree (line); - return 0; - } + /* + * If we received just a CR LF on a line, the headers are + * finished. + */ + if (CHECK_CRLF (line, linelen)) { + safefree (header); + safefree (line); + 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 (linelen >= 5 && strncasecmp (line, "HTTP/", 5) == 0) - { - double_cgi = TRUE; - } + /* + * 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 (linelen >= 5 && strncasecmp (line, "HTTP/", 5) == 0) { + double_cgi = TRUE; + } - /* - * Append the new line to the current header field. - */ - tmp = (char *)saferealloc (header, len + linelen); - if (tmp == NULL) - { - safefree (header); - safefree (line); - return -1; - } + /* + * Append the new line to the current header field. + */ + tmp = (char *) saferealloc (header, len + linelen); + if (tmp == NULL) { + safefree (header); + safefree (line); + return -1; + } - header = tmp; - memcpy (header + len, line, linelen); - len += linelen; + header = tmp; + memcpy (header + len, line, linelen); + len += linelen; - safefree (line); - } + safefree (line); + } } /* * Extract the headers to remove. These headers were listed in the Connection * and Proxy-Connection headers. */ -static int -remove_connection_headers (hashmap_t hashofheaders) +static int remove_connection_headers (hashmap_t hashofheaders) { - static const 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); + static const 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++; + } - /* 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]); } - /* Now remove the connection header it self. */ - hashmap_remove (hashofheaders, headers[i]); - } - - return 0; + return 0; } /* * If there is a Content-Length header, then return the value; otherwise, return * a negative number. */ -static long -get_content_length (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; } /* @@ -1056,41 +984,36 @@ static int write_via_header (int fd, hashmap_t hashofheaders, 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; } /* @@ -1107,306 +1030,296 @@ write_via_header (int fd, hashmap_t hashofheaders, static int process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders) { - static const 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 const 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; + /* 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. - */ + /* + * 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; + if (connptr->content_length.client > 0) + return pull_client_data (connptr, + connptr->content_length.client); + else + return ret; } /* * Loop through all the headers (including the response code) from the * server. */ -static int -process_server_headers (struct conn_s *connptr) +static int process_server_headers (struct conn_s *connptr) { - static const 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 const 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; - } - - /* - * At this point we've received the response line and all the - * headers. However, if this is a simple HTTP/0.9 request we - * CAN NOT send any of that information back to the client. - * Instead we'll free all the memory and return. - */ - if (connptr->protocol.major < 1) - { - hashmap_delete (hashofheaders); - safefree (response_line); - return 0; - } - - /* 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; + 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 + * headers. However, if this is a simple HTTP/0.9 request we + * CAN NOT send any of that information back to the client. + * Instead we'll free all the memory and return. + */ + if (connptr->protocol.major < 1) { + hashmap_delete (hashofheaders); + safefree (response_line); + return 0; + } + + /* 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; #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; + /* 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; } - 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"); + /* 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; + /* + * 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); + 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; + /* 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; + return 0; ERROR_EXIT: - hashmap_delete (hashofheaders); - return -1; + hashmap_delete (hashofheaders); + return -1; } /* @@ -1417,123 +1330,109 @@ ERROR_EXIT: * tinyproxy oh so long ago...) * - rjkaes */ -static void -relay_connection (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); - } + 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; + 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; + 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; + } } - if (FD_ISSET (connptr->server_fd, &wset) - && write_buffer (connptr->server_fd, connptr->cbuffer) < 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; } - if (FD_ISSET (connptr->client_fd, &wset) - && 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; } - } - - /* - * 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; + + return; } /* @@ -1543,81 +1442,78 @@ 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 = (char *)safemalloc (len); - if (!combined_string) - { - return -1; + 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; } - snprintf (combined_string, len, "%s:%d", request->host, request->port); - } - else - { - len = strlen (request->host) + strlen (request->path) + 14; - combined_string = (char *)safemalloc (len); - if (!combined_string) - { - 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; } - snprintf (combined_string, len, "http://%s:%d%s", request->host, - request->port, request->path); - } + 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 = (char *) safemalloc (len); + if (!combined_string) { + return -1; + } - if (request->path) - safefree (request->path); - request->path = combined_string; + snprintf (combined_string, len, "%s:%d", request->host, + request->port); + } else { + len = strlen (request->host) + strlen (request->path) + 14; + combined_string = (char *) safemalloc (len); + if (!combined_string) { + return -1; + } + + snprintf (combined_string, len, "http://%s:%d%s", request->host, + request->port, request->path); + } - return establish_http_connection (connptr, request); + if (request->path) + safefree (request->path); + request->path = combined_string; + + return establish_http_connection (connptr, request); #endif } @@ -1630,194 +1526,173 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request) * tinyproxy code, which was confusing, redundant. Hail progress. * - rjkaes */ -void -handle_connection (int fd) +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 (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; + 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; } - 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; + if (check_acl (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; } - } - 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; + + 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; } - log_message (LOG_CONN, - "Established connection to host \"%s\" using " - "file descriptor %d.", request->host, connptr->server_fd); + /* + * 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; + } - if (!connptr->connect_method) - establish_http_connection (connptr, request); - } + /* + * 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; + } -send_error: - free_request_struct (request); + 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; + } - if (process_client_headers (connptr, hashofheaders) < 0) - { - update_stats (STAT_BADCONN); - if (!connptr->error_variables) - { - hashmap_delete (hashofheaders); - destroy_conn (connptr); - return; + 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); } - } - 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; +send_error: + free_request_struct (request); + + if (process_client_headers (connptr, hashofheaders) < 0) { + update_stats (STAT_BADCONN); + if (!connptr->error_variables) { + hashmap_delete (hashofheaders); + 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; + 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); + 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); + 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; + /* + * All done... close everything and go home... :) + */ + destroy_conn (connptr); + return; } @@ -24,7 +24,6 @@ #include "common.h" - /* * Port constants for HTTP (80) and SSL (443) */ @@ -34,15 +33,14 @@ /* * This structure holds the information pulled from a URL request. */ -struct request_s -{ - char *method; - char *protocol; +struct request_s { + char *method; + char *protocol; - char *host; - uint16_t port; + char *host; + uint16_t port; - char *path; + char *path; }; extern void handle_connection (int fd); diff --git a/src/reverse-proxy.c b/src/reverse-proxy.c index 8d97538..6afaab2 100644 --- a/src/reverse-proxy.c +++ b/src/reverse-proxy.c @@ -29,133 +29,129 @@ /* * Add entry to the reversepath list */ -void -reversepath_add (const char *path, const char *url) +void reversepath_add (const char *path, const char *url) { - struct reversepath *reverse; - - 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 (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 (!path) - reverse->path = safestrdup ("/"); - else - reverse->path = safestrdup (path); - - reverse->url = safestrdup (url); - - reverse->next = config.reversepath_list; - config.reversepath_list = reverse; - - log_message (LOG_INFO, - "Added reverse proxy rule: %s -> %s", reverse->path, - reverse->url); + struct reversepath *reverse; + + 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 (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 (!path) + reverse->path = safestrdup ("/"); + else + reverse->path = safestrdup (path); + + reverse->url = safestrdup (url); + + reverse->next = config.reversepath_list; + config.reversepath_list = reverse; + + log_message (LOG_INFO, + "Added reverse proxy rule: %s -> %s", reverse->path, + reverse->url); } /* * Check if a request url is in the reversepath list */ -struct reversepath * -reversepath_get (char *url) +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; } /* * Rewrite the URL for reverse proxying. */ -char * -reverse_rewrite_url (struct conn_s *connptr, hashmap_t hashofheaders, - char *url) +char *reverse_rewrite_url (struct conn_s *connptr, hashmap_t hashofheaders, + char *url) { - char *rewrite_url = NULL; - char *cookie = NULL; - char *cookieval; - struct reversepath *reverse; - - /* 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); - } + char *rewrite_url = NULL; + char *cookie = NULL; + char *cookieval; + struct reversepath *reverse; + + /* 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); - return NULL; - } + /* 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); + return NULL; + } - log_message (LOG_CONN, "Rewriting URL: %s -> %s", url, rewrite_url); + log_message (LOG_CONN, "Rewriting URL: %s -> %s", url, rewrite_url); - /* Store reverse path so that the magical tracking cookie can be set */ - if (config.reversemagic) - connptr->reversepath = safestrdup (reverse->path); + /* Store reverse path so that the magical tracking cookie can be set */ + if (config.reversemagic) + connptr->reversepath = safestrdup (reverse->path); - return rewrite_url; + return rewrite_url; } diff --git a/src/reverse-proxy.h b/src/reverse-proxy.h index a96dc9a..22e0d08 100644 --- a/src/reverse-proxy.h +++ b/src/reverse-proxy.h @@ -23,11 +23,10 @@ #include "conns.h" -struct reversepath -{ - struct reversepath *next; - char *path; - char *url; +struct reversepath { + struct reversepath *next; + char *path; + char *url; }; #define REVERSE_COOKIE "yummy_magical_cookie" @@ -38,37 +38,34 @@ * returned if the bind succeeded. Otherwise, -1 is returned * to indicate an error. */ -static int -bind_socket (int sockfd, const char *addr) +static int 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; } /* @@ -76,98 +73,89 @@ bind_socket (int sockfd, const char *addr) * the getaddrinfo() library function, which allows for a protocol * independent implementation (mostly for IPv4 and IPv6 addresses.) */ -int -opensock (const char *host, int port, const char *bind_to) +int 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 */ - } - } + int sockfd, n; + struct addrinfo hints, *res, *ressave; + char portstr[6]; - if (connect (sockfd, res->ai_addr, res->ai_addrlen) == 0) - break; /* success */ + assert (host != NULL); + assert (port > 0); - close (sockfd); - } - while ((res = res->ai_next) != NULL); + memset (&hints, 0, sizeof (struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; - freeaddrinfo (ressave); - if (res == NULL) - { - log_message (LOG_ERR, - "opensock: Could not establish a connection to %s", host); - return -1; - } + snprintf (portstr, sizeof (portstr), "%d", port); - return sockfd; + 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; } /* * Set the socket to non blocking -rjkaes */ -int -socket_nonblocking (int sock) +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); } /* * Set the socket to blocking -rjkaes */ -int -socket_blocking (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); } /* @@ -176,102 +164,94 @@ socket_blocking (int sock) * the pointer, while the socket is returned as a default return. * - rjkaes */ -int -listen_sock (uint16_t port, socklen_t * addrlen) +int 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) +int 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) +int getpeer_information (int fd, char *ipaddr, char *string_addr) { - struct sockaddr_storage sa; - socklen_t salen = sizeof sa; + struct sockaddr_storage sa; + socklen_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); } diff --git a/src/stats.c b/src/stats.c index eb843fa..a614da1 100644 --- a/src/stats.c +++ b/src/stats.c @@ -33,13 +33,12 @@ #include "stats.h" #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; +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; }; static struct stat_s *stats; @@ -47,114 +46,109 @@ static struct stat_s *stats; /* * Initialize the statistics information to zero. */ -void -init_stats (void) +void init_stats (void) { - stats = (struct stat_s *)malloc_shared_memory (sizeof (struct stat_s)); - if (stats == MAP_FAILED) - return; + stats = (struct stat_s *) 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)); } /* * Display the statics of the tinyproxy server. */ -int -showstats (struct conn_s *connptr) +int showstats (struct conn_s *connptr) { - static const char *msg = - "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" - "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" " - "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n" - "<html>\n" - "<head><title>%s version %s run-time statistics</title></head>\n" - "<body>\n" - "<h1>%s version %s run-time statistics</h1>\n" - "<p>\n" - "Number of open connections: %lu<br />\n" - "Number of requests: %lu<br />\n" - "Number of bad connections: %lu<br />\n" - "Number of denied connections: %lu<br />\n" - "Number of refused connections due to high load: %lu\n" - "</p>\n" - "<hr />\n" - "<p><em>Generated by %s version %s.</em></p>\n" "</body>\n" "</html>\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 = (char *)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, PACKAGE, VERSION); - - if (send_http_message (connptr, 200, "OK", message_buffer) < 0) - { - safefree (message_buffer); - return -1; + static const char *msg = + "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" " + "\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n" + "<html>\n" + "<head><title>%s version %s run-time statistics</title></head>\n" + "<body>\n" + "<h1>%s version %s run-time statistics</h1>\n" + "<p>\n" + "Number of open connections: %lu<br />\n" + "Number of requests: %lu<br />\n" + "Number of bad connections: %lu<br />\n" + "Number of denied connections: %lu<br />\n" + "Number of refused connections due to high load: %lu\n" + "</p>\n" + "<hr />\n" + "<p><em>Generated by %s version %s.</em></p>\n" "</body>\n" + "</html>\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 = (char *) 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, PACKAGE, VERSION); + + if (send_http_message (connptr, 200, "OK", message_buffer) < 0) { + safefree (message_buffer); + return -1; + } + + safefree (message_buffer); + return 0; } - safefree (message_buffer); - return 0; - } - - add_error_variable (connptr, "opens", opens); - add_error_variable (connptr, "reqs", reqs); - add_error_variable (connptr, "badconns", badconns); - add_error_variable (connptr, "deniedconns", denied); - add_error_variable (connptr, "refusedconns", refused); - add_standard_vars (connptr); - send_http_headers (connptr, 200, "Statistic requested"); - send_html_file (statfile, connptr); - fclose (statfile); - - return 0; + add_error_variable (connptr, "opens", opens); + add_error_variable (connptr, "reqs", reqs); + add_error_variable (connptr, "badconns", badconns); + add_error_variable (connptr, "deniedconns", denied); + add_error_variable (connptr, "refusedconns", refused); + add_standard_vars (connptr); + send_http_headers (connptr, 200, "Statistic requested"); + send_html_file (statfile, connptr); + fclose (statfile); + + return 0; } /* * Update the value of the statistics. The update_level is defined in * stats.h */ -int -update_stats (status_t update_level) +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 23f44e4..b1a43c3 100644 --- a/src/stats.h +++ b/src/stats.h @@ -26,13 +26,12 @@ /* * 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 */ +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 */ } status_t; /* @@ -32,19 +32,18 @@ * buffer, and always NULL terminates the buffer. size is the size of the * destination buffer. */ -size_t -strlcpy (char *dst, const char *src, size_t size) +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 @@ -55,22 +54,20 @@ strlcpy (char *dst, const char *src, size_t size) * buffer, which should be one more than the maximum resulting string * length. */ -size_t -strlcat (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 @@ -83,32 +80,30 @@ strlcat (char *dst, const char *src, size_t size) * Returns the number of characters removed from the end of the string. A * negative return value indicates an error. */ -ssize_t -chomp (char *buffer, size_t length) +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; } diff --git a/src/transparent-proxy.c b/src/transparent-proxy.c index 7318697..81c35ef 100644 --- a/src/transparent-proxy.c +++ b/src/transparent-proxy.c @@ -35,87 +35,82 @@ /* * Build a URL from parts. */ -static int -build_url (char **url, const char *host, int port, const char *path) +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); } - int do_transparent_proxy (struct conn_s *connptr, hashmap_t hashofheaders, struct request_s *request, struct config_s *conf, char *url) { - socklen_t length; - char *data; + socklen_t length; + char *data; - length = hashmap_entry_by_key (hashofheaders, "host", (void **) &data); - if (length <= 0) - { - struct sockaddr_in dest_addr; + 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); - return 0; + 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); + return 0; + } + 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); } - 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; + if (conf->ipAddr && strcmp (request->host, conf->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); + return 0; } - 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 (conf->ipAddr && strcmp (request->host, conf->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); - return 0; - } - return 1; + return 1; } diff --git a/src/transparent-proxy.h b/src/transparent-proxy.h index f18285f..6e77d51 100644 --- a/src/transparent-proxy.h +++ b/src/transparent-proxy.h @@ -34,7 +34,6 @@ extern int do_transparent_proxy (struct conn_s *connptr, struct request_s *request, struct config_s *config, char *url); - #endif #endif diff --git a/src/utils.c b/src/utils.c index fc65af0..679d027 100644 --- a/src/utils.c +++ b/src/utils.c @@ -37,181 +37,169 @@ int send_http_message (struct conn_s *connptr, int http_code, const char *error_title, const char *message) { - static const char *headers[] = { - "Server: " PACKAGE "/" VERSION, - "Content-type: text/html", - "Connection: close" - }; + static const 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; } /* * Safely creates filename and returns the low-level file descriptor. */ -int -create_file_safely (const char *filename, unsigned int truncate_file) +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; - } + close (fildes); + if ((fildes = + open (filename, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) { + fprintf (stderr, "%s: Could not open file %s: %s.", + PACKAGE, filename, strerror (errno)); + return fildes; + } #endif /* HAVE_FTRUNCATE */ - } + } - return fildes; + return fildes; } /* * Write the PID of the program to the specified file. */ -int -pidfile_create (const char *filename) +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/vector.c b/src/vector.c index 77f3955..a80eb4e 100644 --- a/src/vector.c +++ b/src/vector.c @@ -33,19 +33,17 @@ * vector_s stores a pointer to the first vector (vector[0]) and a * count of the number of entries (or how long the vector is.) */ -struct vectorentry_s -{ - void *data; - size_t len; +struct vectorentry_s { + 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; +struct vector_s { + size_t num_entries; + struct vectorentry_s *head; + struct vectorentry_s *tail; }; /* @@ -55,19 +53,18 @@ struct vector_s * A NULL is returned if memory could not be allocated for the * vector. */ -vector_t -vector_create (void) +vector_t vector_create (void) { - vector_t vector; + vector_t vector; - vector = (vector_t)safemalloc (sizeof (struct vector_s)); - if (!vector) - return NULL; + vector = (vector_t) safemalloc (sizeof (struct vector_s)); + if (!vector) + return NULL; - vector->num_entries = 0; - vector->head = vector->tail = NULL; + vector->num_entries = 0; + vector->head = vector->tail = NULL; - return vector; + return vector; } /* @@ -76,27 +73,25 @@ vector_create (void) * Returns: 0 on success * negative if a NULL vector is supplied */ -int -vector_delete (vector_t vector) +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,49 +107,45 @@ vector_delete (vector_t vector) #define INSERT_PREPEND 0 #define INSERT_APPEND 1 -static int -vector_insert (vector_t vector, void *data, size_t len, int pos) +static int vector_insert (vector_t vector, void *data, size_t len, int pos) { - struct vectorentry_s *entry; - - if (!vector || !data || len <= 0 || - (pos != INSERT_PREPEND && pos != INSERT_APPEND)) - return -EINVAL; - - entry = (struct vectorentry_s *)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 = + (struct vectorentry_s *) 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; } /* @@ -162,16 +153,14 @@ vector_insert (vector_t vector, void *data, size_t len, int pos) * can see they simply call the vector_insert() function with appropriate * arguments. */ -int -vector_append (vector_t vector, void *data, size_t len) +int vector_append (vector_t vector, void *data, size_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, size_t len) +int vector_prepend (vector_t vector, void *data, size_t len) { - return vector_insert (vector, data, len, INSERT_PREPEND); + return vector_insert (vector, data, len, INSERT_PREPEND); } /* @@ -181,28 +170,26 @@ vector_prepend (vector_t vector, void *data, size_t len) * Returns: negative upon an error * length of data if position is valid */ -void * -vector_getentry (vector_t vector, size_t pos, size_t * size) +void *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 >= vector->num_entries) - return NULL; + if (!vector || 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; } /* @@ -211,11 +198,10 @@ vector_getentry (vector_t vector, size_t pos, size_t * size) * Returns: negative if vector is not valid * positive length of vector otherwise */ -ssize_t -vector_length (vector_t vector) +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 cdba376..ef8f953 100644 --- a/src/vector.h +++ b/src/vector.h @@ -26,14 +26,14 @@ * 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 @@ -43,8 +43,8 @@ * Returns: negative on error * 0 upon successful insert. */ - extern int vector_append (vector_t vector, void *data, size_t len); - extern int vector_prepend (vector_t vector, void *data, size_t len); +extern int vector_append (vector_t vector, void *data, size_t len); +extern int vector_prepend (vector_t vector, void *data, size_t len); /* * A pointer to the data at position "pos" (zero based) is returned and the @@ -62,7 +62,7 @@ * 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. @@ -70,6 +70,6 @@ * 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); -#endif /* _VECTOR_H */ +#endif /* _VECTOR_H */ |