save headers in an ordered dictionary

due to the usage of a hashmap to store headers, when relaying them
to the other side the order was not prevented.
even though correct from a standards point-of-view, this caused
issues with various programs, and it allows to fingerprint the use
of tinyproxy.

to implement this, i imported the MIT-licensed hsearch.[ch] from
https://github.com/rofl0r/htab which was originally taken from
musl libc. it's a simple and efficient hashtable implementation
with far better performance characteristic than the one previously
used by tinyproxy. additionally it has an API much more well-suited
for this purpose.

orderedmap.[ch] was implemented from scratch to address this issue.
behind the scenes it uses an sblist to store string values, and a htab
to store keys and the indices into the sblist.
this allows us to iterate linearly over the sblist and then find the
corresponding key in the hash table, so the headers can be reproduced
in the order they were received.

closes #73
master
rofl0r 2020-09-12 13:49:10 +01:00
parent 9d5ee85c3e
commit 34a8b28414
10 changed files with 432 additions and 96 deletions

View File

@ -49,6 +49,8 @@ tinyproxy_SOURCES = \
basicauth.c basicauth.h \
base64.c base64.h \
sblist.c sblist.h \
hsearch.c hsearch.h \
orderedmap.c orderedmap.h \
loop.c loop.h \
connect-ports.c connect-ports.h

199
src/hsearch.c Normal file
View File

@ -0,0 +1,199 @@
/*
musl license, hsearch.c originally written by Szabolcs Nagy
Copyright © 2005-2020 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include "hsearch.h"
/*
open addressing hash table with 2^n table size
quadratic probing is used in case of hash collision
tab indices and hash are size_t
after resize fails with ENOMEM the state of tab is still usable
*/
typedef struct htab_entry {
char *key;
htab_value data;
} htab_entry;
struct elem {
htab_entry item;
size_t hash;
};
struct htab {
struct elem *elems;
size_t mask;
size_t used;
};
#define MINSIZE 8
#define MAXSIZE ((size_t)-1/2 + 1)
#define CASE_INSENSITIVE
#ifdef CASE_INSENSITIVE
#include <ctype.h>
#include <strings.h>
#define LOWER_OR_NOT(X) tolower(X)
#define STRCMP(X, Y) strcasecmp(X, Y)
#else
#define LOWER_OR_NOT(X) X
#define STRCMP(X, Y) strcmp(X, Y)
#endif
static size_t keyhash(const char *k)
{
const unsigned char *p = (const void *)k;
size_t h = 0;
while (*p)
h = 31*h + LOWER_OR_NOT(*p++);
return h;
}
static int resize(struct htab *htab, size_t nel)
{
size_t newsize;
size_t i, j;
struct elem *e, *newe;
struct elem *oldtab = htab->elems;
struct elem *oldend = htab->elems + htab->mask + 1;
if (nel > MAXSIZE)
nel = MAXSIZE;
for (newsize = MINSIZE; newsize < nel; newsize *= 2);
htab->elems = calloc(newsize, sizeof *htab->elems);
if (!htab->elems) {
htab->elems = oldtab;
return 0;
}
htab->mask = newsize - 1;
if (!oldtab)
return 1;
for (e = oldtab; e < oldend; e++)
if (e->item.key) {
for (i=e->hash,j=1; ; i+=j++) {
newe = htab->elems + (i & htab->mask);
if (!newe->item.key)
break;
}
*newe = *e;
}
free(oldtab);
return 1;
}
static struct elem *lookup(struct htab *htab, const char *key, size_t hash)
{
size_t i, j;
struct elem *e;
for (i=hash,j=1; ; i+=j++) {
e = htab->elems + (i & htab->mask);
if (!e->item.key ||
(e->hash==hash && STRCMP(e->item.key, key)==0))
break;
}
return e;
}
struct htab *htab_create(size_t nel)
{
struct htab *r = calloc(1, sizeof *r);
if(r && !resize(r, nel)) {
free(r);
r = 0;
}
return r;
}
void htab_destroy(struct htab *htab)
{
free(htab->elems);
free(htab);
}
static htab_entry *htab_find_item(struct htab *htab, const char* key)
{
size_t hash = keyhash(key);
struct elem *e = lookup(htab, key, hash);
if (e->item.key) {
return &e->item;
}
return 0;
}
htab_value* htab_find(struct htab *htab, const char* key)
{
htab_entry *i = htab_find_item(htab, key);
if(i) return &i->data;
return 0;
}
int htab_delete(struct htab *htab, const char* key)
{
htab_entry *i = htab_find_item(htab, key);
if(!i) return 0;
i->key = 0;
return 1;
}
int htab_insert(struct htab *htab, char* key, htab_value value)
{
size_t hash = keyhash(key);
struct elem *e = lookup(htab, key, hash);
if(e->item.key) {
/* it's not allowed to overwrite existing data */
return 0;
}
e->item.key = key;
e->item.data = value;
e->hash = hash;
if (++htab->used > htab->mask - htab->mask/4) {
if (!resize(htab, 2*htab->used)) {
htab->used--;
e->item.key = 0;
return 0;
}
}
return 1;
}
size_t htab_next(struct htab *htab, size_t iterator, char** key, htab_value **v)
{
size_t i;
for(i=iterator;i<htab->mask+1;++i) {
struct elem *e = htab->elems + i;
if(e->item.key) {
*key = e->item.key;
*v = &e->item.data;
return i+1;
}
}
return 0;
}

21
src/hsearch.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef HSEARCH_H
#define HSEARCH_H
#include <stdlib.h>
typedef union htab_value {
void *p;
size_t n;
} htab_value;
#define HTV_N(N) (htab_value) {.n = N}
#define HTV_P(P) (htab_value) {.p = P}
struct htab * htab_create(size_t);
void htab_destroy(struct htab *);
htab_value* htab_find(struct htab *, const char* key);
int htab_insert(struct htab *, char*, htab_value);
int htab_delete(struct htab *htab, const char* key);
size_t htab_next(struct htab *, size_t iterator, char** key, htab_value **v);
#endif

110
src/orderedmap.c Normal file
View File

@ -0,0 +1,110 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#else
# define _ALL_SOURCE
# define _GNU_SOURCE
#endif
#include <string.h>
#include "sblist.h"
#include "orderedmap.h"
static void orderedmap_destroy_contents(struct orderedmap *o) {
char **p, *q;
size_t i;
htab_value *v;
if(!o) return;
if(o->values) {
while(sblist_getsize(o->values)) {
p = sblist_get(o->values, 0);
if(p) free(*p);
sblist_delete(o->values, 0);
}
sblist_free(o->values);
}
if(o->map) {
i = 0;
while((i = htab_next(o->map, i, &q, &v)))
free(q);
htab_destroy(o->map);
}
}
struct orderedmap *orderedmap_create(size_t nbuckets) {
struct orderedmap o = {0}, *new;
o.values = sblist_new(sizeof(void*), 32);
if(!o.values) goto oom;
o.map = htab_create(nbuckets);
if(!o.map) goto oom;
new = malloc(sizeof o);
if(!new) goto oom;
memcpy(new, &o, sizeof o);
return new;
oom:;
orderedmap_destroy_contents(&o);
return 0;
}
void* orderedmap_destroy(struct orderedmap *o) {
orderedmap_destroy_contents(o);
free(o);
return 0;
}
int orderedmap_append(struct orderedmap *o, const char *key, char *value) {
size_t index;
char *nk, *nv;
nk = nv = 0;
nk = strdup(key);
nv = strdup(value);
if(!nk || !nv) goto oom;
index = sblist_getsize(o->values);
if(!sblist_add(o->values, &nv)) goto oom;
if(!htab_insert(o->map, nk, HTV_N(index))) {
sblist_delete(o->values, index);
goto oom;
}
return 1;
oom:;
free(nk);
free(nv);
return 0;
}
char* orderedmap_find(struct orderedmap *o, const char *key) {
char **p;
htab_value *v = htab_find(o->map, key);
if(!v) return 0;
p = sblist_get(o->values, v->n);
return p?*p:0;
}
int orderedmap_remove(struct orderedmap *o, const char *key) {
size_t i;
char *lk;
htab_value *lv, *v = htab_find(o->map, key);
if(!v) return 0;
htab_delete(o->map, key);
sblist_delete(o->values, v->n);
i = 0;
while((i = htab_next(o->map, i, &lk, &lv))) {
if(lv->n > v->n) lv->n--;
}
return 1;
}
size_t orderedmap_next(struct orderedmap *o, size_t iter, char** key, char** value) {
size_t h_iter;
htab_value* hval;
char **p;
if(iter < sblist_getsize(o->values)) {
h_iter = 0;
while((h_iter = htab_next(o->map, h_iter, key, &hval))) {
if(hval->n == iter) {
p = sblist_get(o->values, iter);
*value = p?*p:0;
return iter+1;
}
}
}
return 0;
}

20
src/orderedmap.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef ORDEREDMAP_H
#define ORDEREDMAP_H
#include <stdlib.h>
#include "sblist.h"
#include "hsearch.h"
typedef struct orderedmap {
sblist* values;
struct htab *map;
} *orderedmap;
struct orderedmap *orderedmap_create(size_t nbuckets);
void* orderedmap_destroy(struct orderedmap *o);
int orderedmap_append(struct orderedmap *o, const char *key, char *value );
char* orderedmap_find(struct orderedmap *o, const char *key);
int orderedmap_remove(struct orderedmap *o, const char *key);
size_t orderedmap_next(struct orderedmap *o, size_t iter, char** key, char** value);
#endif

View File

@ -33,6 +33,7 @@
#include "conns.h"
#include "filter.h"
#include "hashmap.h"
#include "orderedmap.h"
#include "heap.h"
#include "html-error.h"
#include "log.h"
@ -315,7 +316,7 @@ static int send_ssl_response (struct conn_s *connptr)
* build a new request line. Finally connect to the remote server.
*/
static struct request_s *process_request (struct conn_s *connptr,
hashmap_t hashofheaders)
orderedmap hashofheaders)
{
char *url;
struct request_s *request;
@ -596,7 +597,7 @@ static int add_xtinyproxy_header (struct conn_s *connptr)
* can be retrieved and manipulated later.
*/
static int
add_header_to_connection (hashmap_t hashofheaders, char *header, size_t len)
add_header_to_connection (orderedmap hashofheaders, char *header, size_t len)
{
char *sep;
@ -614,7 +615,7 @@ add_header_to_connection (hashmap_t hashofheaders, char *header, size_t len)
/* Calculate the new length of just the data */
len -= sep - header - 1;
return hashmap_insert (hashofheaders, header, sep, len);
return orderedmap_append (hashofheaders, header, sep);
}
/*
@ -627,7 +628,7 @@ add_header_to_connection (hashmap_t hashofheaders, char *header, size_t 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, orderedmap hashofheaders)
{
char *line = NULL;
char *header = NULL;
@ -720,7 +721,7 @@ static int get_all_headers (int fd, hashmap_t hashofheaders)
* 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 (orderedmap hashofheaders)
{
static const char *headers[] = {
"connection",
@ -734,12 +735,13 @@ static int remove_connection_headers (hashmap_t hashofheaders)
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)
data = orderedmap_find(hashofheaders, headers[i]);
if (!data)
return 0;
len = strlen(data);
/*
* Go through the data line and replace any special characters
* with a NULL.
@ -754,7 +756,7 @@ static int remove_connection_headers (hashmap_t hashofheaders)
*/
ptr = data;
while (ptr < data + len) {
hashmap_remove (hashofheaders, ptr);
orderedmap_remove (hashofheaders, ptr);
/* Advance ptr to the next token */
ptr += strlen (ptr) + 1;
@ -763,7 +765,7 @@ static int remove_connection_headers (hashmap_t hashofheaders)
}
/* Now remove the connection header it self. */
hashmap_remove (hashofheaders, headers[i]);
orderedmap_remove (hashofheaders, headers[i]);
}
return 0;
@ -773,16 +775,14 @@ static int remove_connection_headers (hashmap_t hashofheaders)
* 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 (orderedmap hashofheaders)
{
ssize_t len;
char *data;
long content_length = -1;
len =
hashmap_entry_by_key (hashofheaders, "content-length",
(void **) &data);
if (len > 0)
data = orderedmap_find (hashofheaders, "content-length");
if (data)
content_length = atol (data);
return content_length;
@ -796,10 +796,9 @@ static long get_content_length (hashmap_t hashofheaders)
* purposes.
*/
static int
write_via_header (int fd, hashmap_t hashofheaders,
write_via_header (int fd, orderedmap hashofheaders,
unsigned int major, unsigned int minor)
{
ssize_t len;
char hostname[512];
char *data;
int ret;
@ -819,14 +818,14 @@ write_via_header (int fd, hashmap_t hashofheaders,
* 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) {
data = orderedmap_find (hashofheaders, "via");
if (data) {
ret = write_message (fd,
"Via: %s, %hu.%hu %s (%s/%s)\r\n",
data, major, minor, hostname, PACKAGE,
VERSION);
hashmap_remove (hashofheaders, "via");
orderedmap_remove (hashofheaders, "via");
} else {
ret = write_message (fd,
"Via: %hu.%hu %s (%s/%s)\r\n",
@ -840,7 +839,7 @@ done:
/*
* Number of buckets to use internally in the hashmap.
*/
#define HEADER_BUCKETS 256
#define HEADER_BUCKETS 32
/*
* Here we loop through all the headers the client is sending. If we
@ -849,7 +848,7 @@ done:
* - rjkaes
*/
static int
process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders)
process_client_headers (struct conn_s *connptr, orderedmap hashofheaders)
{
static const char *skipheaders[] = {
"host",
@ -860,7 +859,7 @@ process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders)
"upgrade"
};
int i;
hashmap_iter iter;
size_t iter;
int ret = 0;
char *data, *header;
@ -893,7 +892,7 @@ process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders)
* Delete the headers listed in the skipheaders list
*/
for (i = 0; i != (sizeof (skipheaders) / sizeof (char *)); i++) {
hashmap_remove (hashofheaders, skipheaders[i]);
orderedmap_remove (hashofheaders, skipheaders[i]);
}
/* Send, or add the Via header */
@ -913,27 +912,22 @@ process_client_headers (struct conn_s *connptr, hashmap_t hashofheaders)
/*
* 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 (config)
|| anonymous_search (config, 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;
}
iter = 0;
while((iter = orderedmap_next(hashofheaders, iter, &data, &header))) {
if (!is_anonymous_enabled (config)
|| anonymous_search (config, 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;
}
}
}
@ -973,8 +967,8 @@ static int process_server_headers (struct conn_s *connptr)
char *response_line;
hashmap_t hashofheaders;
hashmap_iter iter;
orderedmap hashofheaders;
size_t iter;
char *data, *header;
ssize_t len;
int i;
@ -1003,7 +997,7 @@ retry:
goto retry;
}
hashofheaders = hashmap_create (HEADER_BUCKETS);
hashofheaders = orderedmap_create (HEADER_BUCKETS);
if (!hashofheaders) {
safefree (response_line);
return -1;
@ -1015,7 +1009,7 @@ retry:
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);
orderedmap_destroy (hashofheaders);
safefree (response_line);
indicate_http_error (connptr, 503,
@ -1034,7 +1028,7 @@ retry:
* Instead we'll free all the memory and return.
*/
if (connptr->protocol.major < 1) {
hashmap_delete (hashofheaders);
orderedmap_destroy (hashofheaders);
safefree (response_line);
return 0;
}
@ -1061,7 +1055,7 @@ retry:
* Delete the headers listed in the skipheaders list
*/
for (i = 0; i != (sizeof (skipheaders) / sizeof (char *)); i++) {
hashmap_remove (hashofheaders, skipheaders[i]);
orderedmap_remove (hashofheaders, skipheaders[i]);
}
/* Send, or add the Via header */
@ -1083,8 +1077,7 @@ retry:
/* Rewrite the HTTP redirect if needed */
if (config->reversebaseurl &&
hashmap_entry_by_key (hashofheaders, "location",
(void **) &header) > 0) {
(header = orderedmap_find (hashofheaders, "location"))) {
/* Look for a matching entry in the reversepath list */
while (reverse) {
@ -1109,7 +1102,7 @@ retry:
"Rewriting HTTP redirect: %s -> %s%s%s",
header, config->reversebaseurl,
(reverse->path + 1), (header + len));
hashmap_remove (hashofheaders, "location");
orderedmap_remove (hashofheaders, "location");
}
}
#endif
@ -1117,19 +1110,15 @@ retry:
/*
* 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);
iter = 0;
while ((iter = orderedmap_next(hashofheaders, iter, &data, &header))) {
ret = write_message (connptr->client_fd,
"%s: %s\r\n", data, header);
if (ret < 0)
goto ERROR_EXIT;
}
ret = write_message (connptr->client_fd,
"%s: %s\r\n", data, header);
if (ret < 0)
goto ERROR_EXIT;
}
hashmap_delete (hashofheaders);
orderedmap_destroy (hashofheaders);
/* Write the final blank line to signify the end of the headers */
if (safe_write (connptr->client_fd, "\r\n", 2) < 0)
@ -1138,7 +1127,7 @@ retry:
return 0;
ERROR_EXIT:
hashmap_delete (hashofheaders);
orderedmap_destroy (hashofheaders);
return -1;
}
@ -1532,7 +1521,7 @@ void handle_connection (int fd, union sockaddr_union* addr)
struct conn_s *connptr;
struct request_s *request = NULL;
struct timeval tv;
hashmap_t hashofheaders = NULL;
orderedmap hashofheaders = NULL;
char sock_ipaddr[IP_LENGTH];
char peer_ipaddr[IP_LENGTH];
@ -1597,7 +1586,7 @@ void handle_connection (int fd, union sockaddr_union* addr)
/*
* The "hashofheaders" store the client's headers.
*/
hashofheaders = hashmap_create (HEADER_BUCKETS);
hashofheaders = orderedmap_create (HEADER_BUCKETS);
if (hashofheaders == NULL) {
update_stats (STAT_BADCONN);
indicate_http_error (connptr, 503, "Internal error",
@ -1624,23 +1613,19 @@ void handle_connection (int fd, union sockaddr_union* addr)
got_headers = 1;
if (config->basicauth_list != NULL) {
ssize_t len;
char *authstring;
int failure = 1, stathost_connect = 0;
len = hashmap_entry_by_key (hashofheaders, "proxy-authorization",
(void **) &authstring);
authstring = orderedmap_find (hashofheaders, "proxy-authorization");
if (len == 0 && config->stathost) {
len = hashmap_entry_by_key (hashofheaders, "host",
(void **) &authstring);
if (len && !strncmp(authstring, config->stathost, strlen(config->stathost))) {
len = hashmap_entry_by_key (hashofheaders, "authorization",
(void **) &authstring);
if (!authstring && config->stathost) {
authstring = orderedmap_find (hashofheaders, "host");
if (authstring && !strncmp(authstring, config->stathost, strlen(config->stathost))) {
authstring = orderedmap_find (hashofheaders, "authorization");
stathost_connect = 1;
} else len = 0;
} else authstring = 0;
}
if (len == 0) {
if (!authstring) {
if (stathost_connect) goto e401;
update_stats (STAT_DENIED);
indicate_http_error (connptr, 407, "Proxy Authentication Required",
@ -1664,7 +1649,7 @@ e401:
NULL);
HC_FAIL();
}
hashmap_remove (hashofheaders, "proxy-authorization");
orderedmap_remove (hashofheaders, "proxy-authorization");
}
/*
@ -1675,9 +1660,7 @@ e401:
http_header_t *header = (http_header_t *)
vector_getentry (config->add_headers, i, NULL);
hashmap_insert (hashofheaders,
header->name,
header->value, strlen (header->value) + 1);
orderedmap_append (hashofheaders, header->name, header->value);
}
request = process_request (connptr, hashofheaders);
@ -1755,7 +1738,7 @@ e401:
done:
free_request_struct (request);
hashmap_delete (hashofheaders);
orderedmap_destroy (hashofheaders);
destroy_conn (connptr);
return;
#undef HC_FAIL

View File

@ -111,7 +111,7 @@ void free_reversepath_list (struct reversepath *reverse)
/*
* Rewrite the URL for reverse proxying.
*/
char *reverse_rewrite_url (struct conn_s *connptr, hashmap_t hashofheaders,
char *reverse_rewrite_url (struct conn_s *connptr, orderedmap hashofheaders,
char *url)
{
char *rewrite_url = NULL;
@ -130,9 +130,8 @@ char *reverse_rewrite_url (struct conn_s *connptr, hashmap_t hashofheaders,
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) {
&& (cookie = orderedmap_find (hashofheaders,
"cookie"))) {
/* No match - try the magical tracking cookie next */
if ((cookieval = strstr (cookie, REVERSE_COOKIE "="))

View File

@ -22,6 +22,7 @@
#define TINYPROXY_REVERSE_PROXY_H
#include "conns.h"
#include "orderedmap.h"
struct reversepath {
struct reversepath *next;
@ -37,6 +38,6 @@ extern struct reversepath *reversepath_get (char *url,
struct reversepath *reverse);
void free_reversepath_list (struct reversepath *reverse);
extern char *reverse_rewrite_url (struct conn_s *connptr,
hashmap_t hashofheaders, char *url);
orderedmap hashofheaders, char *url);
#endif

View File

@ -53,7 +53,7 @@ static int build_url (char **url, const char *host, int port, const char *path)
}
int
do_transparent_proxy (struct conn_s *connptr, hashmap_t hashofheaders,
do_transparent_proxy (struct conn_s *connptr, orderedmap hashofheaders,
struct request_s *request, struct config_s *conf,
char **url)
{
@ -62,8 +62,8 @@ do_transparent_proxy (struct conn_s *connptr, hashmap_t hashofheaders,
size_t ulen = strlen (*url);
ssize_t i;
length = hashmap_entry_by_key (hashofheaders, "host", (void **) &data);
if (length <= 0) {
data = orderedmap_find (hashofheaders, "host");
if (!data) {
union sockaddr_union dest_addr;
const void *dest_inaddr;
char namebuf[INET6_ADDRSTRLEN+1];
@ -102,6 +102,7 @@ do_transparent_proxy (struct conn_s *connptr, hashmap_t hashofheaders,
"process_request: trans IP %s %s for %d",
request->method, *url, connptr->client_fd);
} else {
length = strlen (data);
request->host = (char *) safemalloc (length + 1);
if (sscanf (data, "%[^:]:%hu", request->host, &request->port) !=
2) {

View File

@ -26,11 +26,11 @@
#ifdef TRANSPARENT_PROXY
#include "conns.h"
#include "hashmap.h"
#include "orderedmap.h"
#include "reqs.h"
extern int do_transparent_proxy (struct conn_s *connptr,
hashmap_t hashofheaders,
orderedmap hashofheaders,
struct request_s *request,
struct config_s *config, char **url);