diff options
Diffstat (limited to 'src')
| -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 */ | 
