summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2010-11-30 01:05:03 +0000
committerChristian Pointner <equinox@spreadspace.org>2010-11-30 01:05:03 +0000
commite2d68ee657d35f062d1794de5d5ce852d478d746 (patch)
treecbb8a243a8a311b73ee68caf2a365ac00da3aa49
parentonly recv if buffer is not full (diff)
buffer size can now be configured
git-svn-id: https://svn.spreadspace.org/tcpproxy/trunk@18 e61f0598-a718-4e21-a8f0-0aadfa62ad6b
-rw-r--r--doc/tcpproxy.810
-rw-r--r--doc/tcpproxy.8.txt4
-rw-r--r--src/clients.c84
-rw-r--r--src/clients.h11
-rw-r--r--src/listener.c4
-rw-r--r--src/options.c12
-rw-r--r--src/options.h1
-rw-r--r--src/tcpproxy.c2
8 files changed, 90 insertions, 38 deletions
diff --git a/doc/tcpproxy.8 b/doc/tcpproxy.8
index 71efd53..6739750 100644
--- a/doc/tcpproxy.8
+++ b/doc/tcpproxy.8
@@ -2,12 +2,12 @@
.\" Title: tcpproxy
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\" Date: 11/29/2010
+.\" Date: 11/30/2010
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
-.TH "TCPPROXY" "8" "11/29/2010" "\ \&" "\ \&"
+.TH "TCPPROXY" "8" "11/30/2010" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -46,6 +46,7 @@ tcpproxy \- IPv4/IPv6 tcp connection proxy
[ \fB\-r|\-\-remote\-addr\fR <host> ]
[ \fB\-o|\-\-remote\-port\fR <service> ]
[ \fB\-s|\-\-source\-addr\fR <host> ]
+ [ \fB\-b|\-\-buffer\-size\fR <size> ]
[ \fB\-c|\-\-config\fR <file> ]
.fi
.SH "DESCRIPTION"
@@ -153,6 +154,11 @@ tba
tba
.RE
.PP
+\fB\-b, \-\-buffer\-size <size>\fR
+.RS 4
+tba
+.RE
+.PP
\fB\-c, \-\-config <file>\fR
.RS 4
tba
diff --git a/doc/tcpproxy.8.txt b/doc/tcpproxy.8.txt
index 96b7733..ebbac12 100644
--- a/doc/tcpproxy.8.txt
+++ b/doc/tcpproxy.8.txt
@@ -25,6 +25,7 @@ tcpproxy
[ -r|--remote-addr <host> ]
[ -o|--remote-port <service> ]
[ -s|--source-addr <host> ]
+ [ -b|--buffer-size <size> ]
[ -c|--config <file> ]
....
@@ -98,6 +99,9 @@ The following options can be passed to the *tcpproxy* daemon:
*-s, --source-addr <host>*::
tba
+*-b, --buffer-size <size>*::
+ tba
+
*-c, --config <file>*::
tba
diff --git a/src/clients.c b/src/clients.c
index 2433e62..1f15573 100644
--- a/src/clients.c
+++ b/src/clients.c
@@ -49,18 +49,23 @@ void clients_delete_element(void* e)
client_t* element = (client_t*)e;
close(element->fd_[0]);
close(element->fd_[1]);
+ if(element->write_buf_[0].buf_)
+ free(element->write_buf_[0].buf_);
+ if(element->write_buf_[1].buf_)
+ free(element->write_buf_[1].buf_);
free(e);
}
-int clients_init(clients_t* list)
+int clients_init(clients_t* list, int32_t buffer_size)
{
- return slist_init(list, &clients_delete_element);
+ list->buffer_size_ = buffer_size;
+ return slist_init(&(list->list_), &clients_delete_element);
}
void clients_clear(clients_t* list)
{
- slist_clear(list);
+ slist_clear(&(list->list_));
}
int clients_add(clients_t* list, int fd, const tcp_endpoint_t remote_end, const tcp_endpoint_t source_end)
@@ -75,13 +80,32 @@ int clients_add(clients_t* list, int fd, const tcp_endpoint_t remote_end, const
return -2;
}
- element->write_buf_len_[0] = 0;
- element->write_buf_len_[1] = 0;
element->fd_[0] = fd;
+ element->write_buf_[0].buf_ = malloc(list->buffer_size_);
+ if(!element->write_buf_[0].buf_) {
+ free(element);
+ close(fd);
+ return -2;
+ }
+ element->write_buf_[0].length_ = list->buffer_size_;
+ element->write_buf_offset_[0] = 0;
+
+ element->write_buf_[1].buf_ = malloc(list->buffer_size_);
+ if(!element->write_buf_[1].buf_) {
+ free(element->write_buf_[0].buf_);
+ free(element);
+ close(fd);
+ return -2;
+ }
+ element->write_buf_[1].length_ = list->buffer_size_;
+ element->write_buf_offset_[1] = 0;
+
element->fd_[1] = socket(remote_end.addr_.ss_family, SOCK_STREAM, 0);
if(element->fd_[1] < 0) {
log_printf(INFO, "Error on socket(): %s, not adding client %d", strerror(errno), element->fd_[0]);
+ free(element->write_buf_[0].buf_);
+ free(element->write_buf_[1].buf_);
close(element->fd_[0]);
free(element);
return -1;
@@ -90,6 +114,8 @@ int clients_add(clients_t* list, int fd, const tcp_endpoint_t remote_end, const
if(source_end.addr_.ss_family != AF_UNSPEC) {
if(bind(element->fd_[1], (struct sockaddr *)&(source_end.addr_), source_end.len_)==-1) {
log_printf(INFO, "Error on bind(): %s, not adding client %d", strerror(errno), element->fd_[0]);
+ free(element->write_buf_[0].buf_);
+ free(element->write_buf_[1].buf_);
close(element->fd_[0]);
close(element->fd_[1]);
free(element);
@@ -99,13 +125,17 @@ int clients_add(clients_t* list, int fd, const tcp_endpoint_t remote_end, const
if(connect(element->fd_[1], (struct sockaddr *)&(remote_end.addr_), remote_end.len_)==-1) {
log_printf(INFO, "Error on connect(): %s, not adding client %d", strerror(errno), element->fd_[0]);
+ free(element->write_buf_[0].buf_);
+ free(element->write_buf_[1].buf_);
close(element->fd_[0]);
close(element->fd_[1]);
free(element);
return -1;
}
- if(slist_add(list, element) == NULL) {
+ if(slist_add(&(list->list_), element) == NULL) {
+ free(element->write_buf_[0].buf_);
+ free(element->write_buf_[1].buf_);
close(element->fd_[0]);
close(element->fd_[1]);
free(element);
@@ -117,7 +147,7 @@ int clients_add(clients_t* list, int fd, const tcp_endpoint_t remote_end, const
void clients_remove(clients_t* list, int fd)
{
- slist_remove(list, clients_find(list, fd));
+ slist_remove(&(list->list_), clients_find(list, fd));
}
client_t* clients_find(clients_t* list, int fd)
@@ -125,7 +155,7 @@ client_t* clients_find(clients_t* list, int fd)
if(!list)
return NULL;
- slist_element_t* tmp = list->first_;
+ slist_element_t* tmp = list->list_.first_;
while(tmp) {
client_t* c = (client_t*)tmp->data_;
if(c && (c->fd_[0] == fd || c->fd_[1] == fd))
@@ -141,7 +171,7 @@ void clients_print(clients_t* list)
if(!list)
return;
- slist_element_t* tmp = list->first_;
+ slist_element_t* tmp = list->list_.first_;
while(tmp) {
client_t* c = (client_t*)tmp->data_;
if(c) {
@@ -157,15 +187,15 @@ void clients_read_fds(clients_t* list, fd_set* set, int* max_fd)
if(!list)
return;
- slist_element_t* tmp = list->first_;
+ slist_element_t* tmp = list->list_.first_;
while(tmp) {
client_t* c = (client_t*)tmp->data_;
if(c) {
- if(c->write_buf_len_[1] < BUFFER_LENGTH) {
+ if(c->write_buf_offset_[1] < c->write_buf_[1].length_) {
FD_SET(c->fd_[0], set);
*max_fd = *max_fd > c->fd_[0] ? *max_fd : c->fd_[0];
}
- if(c->write_buf_len_[0] < BUFFER_LENGTH) {
+ if(c->write_buf_offset_[0] < c->write_buf_[0].length_) {
FD_SET(c->fd_[1], set);
*max_fd = *max_fd > c->fd_[1] ? *max_fd : c->fd_[1];
}
@@ -179,15 +209,15 @@ void clients_write_fds(clients_t* list, fd_set* set, int* max_fd)
if(!list)
return;
- slist_element_t* tmp = list->first_;
+ slist_element_t* tmp = list->list_.first_;
while(tmp) {
client_t* c = (client_t*)tmp->data_;
if(c) {
- if(c->write_buf_len_[0]) {
+ if(c->write_buf_offset_[0]) {
FD_SET(c->fd_[0], set);
*max_fd = *max_fd > c->fd_[0] ? *max_fd : c->fd_[0];
}
- if(c->write_buf_len_[1]) {
+ if(c->write_buf_offset_[1]) {
FD_SET(c->fd_[1], set);
*max_fd = *max_fd > c->fd_[1] ? *max_fd : c->fd_[1];
}
@@ -201,7 +231,7 @@ int clients_read(clients_t* list, fd_set* set)
if(!list)
return -1;
- slist_element_t* tmp = list->first_;
+ slist_element_t* tmp = list->list_.first_;
while(tmp) {
client_t* c = (client_t*)tmp->data_;
tmp = tmp->next_;
@@ -217,17 +247,17 @@ int clients_read(clients_t* list, fd_set* set)
}
else continue;
- int len = recv(c->fd_[in], &(c->write_buf_[out][c->write_buf_len_[out]]), BUFFER_LENGTH - c->write_buf_len_[out], 0);
+ int len = recv(c->fd_[in], &(c->write_buf_[out].buf_[c->write_buf_offset_[out]]), c->write_buf_[out].length_ - c->write_buf_offset_[out], 0);
if(len < 0) {
log_printf(INFO, "Error on recv(): %s, removing client %d", strerror(errno), c->fd_[0]);
- slist_remove(list, c);
+ slist_remove(&(list->list_), c);
}
else if(!len) {
log_printf(INFO, "client %d closed connection, removing it", c->fd_[0]);
- slist_remove(list, c);
+ slist_remove(&(list->list_), c);
}
else
- c->write_buf_len_[out] += len;
+ c->write_buf_offset_[out] += len;
}
}
@@ -239,7 +269,7 @@ int clients_write(clients_t* list, fd_set* set)
if(!list)
return -1;
- slist_element_t* tmp = list->first_;
+ slist_element_t* tmp = list->list_.first_;
while(tmp) {
client_t* c = (client_t*)tmp->data_;
tmp = tmp->next_;
@@ -247,18 +277,18 @@ int clients_write(clients_t* list, fd_set* set)
int i;
for(i=0; i<2; ++i) {
if(FD_ISSET(c->fd_[i], set)) {
- int len = send(c->fd_[i], c->write_buf_[i], c->write_buf_len_[i], 0);
+ int len = send(c->fd_[i], c->write_buf_[i].buf_, c->write_buf_offset_[i], 0);
if(len < 0) {
log_printf(INFO, "Error on send(): %s, removing client %d", strerror(errno), c->fd_[0]);
- slist_remove(list, c);
+ slist_remove(&(list->list_), c);
}
else {
- if(c->write_buf_len_[i] > len) {
- memmove(c->write_buf_[i], &c->write_buf_[i][len], c->write_buf_len_[i] - len);
- c->write_buf_len_[i] -= len;
+ if(c->write_buf_offset_[i] > len) {
+ memmove(c->write_buf_[i].buf_, &c->write_buf_[i].buf_[len], c->write_buf_offset_[i] - len);
+ c->write_buf_offset_[i] -= len;
}
else
- c->write_buf_len_[i] = 0;
+ c->write_buf_offset_[i] = 0;
}
}
}
diff --git a/src/clients.h b/src/clients.h
index 5253b35..a6337c3 100644
--- a/src/clients.h
+++ b/src/clients.h
@@ -37,15 +37,18 @@
typedef struct {
int fd_[2];
- u_int8_t write_buf_[2][BUFFER_LENGTH];
- u_int32_t write_buf_len_[2];
+ buffer_t write_buf_[2];
+ u_int32_t write_buf_offset_[2];
} client_t;
void clients_delete_element(void* e);
-typedef slist_t clients_t;
+typedef struct {
+ slist_t list_;
+ int32_t buffer_size_;
+} clients_t;
-int clients_init(clients_t* list);
+int clients_init(clients_t* list, int32_t buffer_size);
void clients_clear(clients_t* list);
int clients_add(clients_t* list, int fd, const tcp_endpoint_t remote_end, const tcp_endpoint_t source_end);
void clients_remove(clients_t* list, int fd);
diff --git a/src/listener.c b/src/listener.c
index 0f7f937..bea19e4 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -243,8 +243,8 @@ int listener_handle_accept(listeners_t* list, clients_t* clients, fd_set* set)
listener_t* l = (listener_t*)tmp->data_;
if(l && FD_ISSET(l->fd_, set)) {
tcp_endpoint_t remote_addr;
- int alen = sizeof(remote_addr);
- int new_client = accept(l->fd_, (struct sockaddr *)&remote_addr, &alen);
+ remote_addr.len_ = sizeof(remote_addr.addr_);
+ int new_client = accept(l->fd_, (struct sockaddr *)&(remote_addr.addr_), &remote_addr.len_);
if(new_client == -1) {
log_printf(ERROR, "Error on accept(): %s", strerror(errno));
return -1;
diff --git a/src/options.c b/src/options.c
index 39e53ee..30361d4 100644
--- a/src/options.c
+++ b/src/options.c
@@ -29,6 +29,7 @@
#include "config.h"
#include "options.h"
+#include "log.h"
#include <stdlib.h>
#include <stdio.h>
@@ -184,6 +185,7 @@ int options_parse(options_t* opt, int argc, char* argv[])
PARSE_STRING_PARAM("-o","--remote-port", opt->remote_port_)
PARSE_STRING_PARAM("-s","--source-addr", opt->source_addr_)
PARSE_STRING_PARAM("-c","--config", opt->config_file_)
+ PARSE_INT_PARAM("-b","--buffer-size", opt->buffer_size_)
else
return i;
}
@@ -205,7 +207,10 @@ void options_parse_post(options_t* opt)
if(!opt)
return;
- // nothing yet
+ if(opt->buffer_size_ <= 0) {
+ log_printf(WARNING, "illegal buffer size %d using default buffer size", opt->buffer_size_);
+ opt->buffer_size_ = 10 * 1024;
+ }
}
void options_default(options_t* opt)
@@ -226,6 +231,7 @@ void options_default(options_t* opt)
opt->source_addr_ = NULL;
opt->config_file_ = strdup(CONFFILE);
string_list_init(&opt->log_targets_);
+ opt->buffer_size_ = 10 * 1024;
opt->debug_ = 0;
}
@@ -276,7 +282,8 @@ void options_print_usage()
printf(" [-p|--local-port] <service> local port to listen on\n");
printf(" [-r|--remote-addr] <host> remote address to connect to\n");
printf(" [-o|--remote-port] <service> remote port to connect to\n");
- printf(" [-r|--source-addr] <host> source address to connect from\n");
+ printf(" [-s|--source-addr] <host> source address to connect from\n");
+ printf(" [-b|--buffer-size] <size> size of transmit buffers\n");
printf(" [-c|--config] <file> configuration file\n");
}
@@ -304,6 +311,7 @@ void options_print(options_t* opt)
printf("remote_addr: '%s'\n", opt->remote_addr_);
printf("remote_port: '%s'\n", opt->remote_port_);
printf("source_addr: '%s'\n", opt->source_addr_);
+ printf("buffer-size: %d\n", opt->buffer_size_);
printf("config_file: '%s'\n", opt->config_file_);
printf("debug: %s\n", !opt->debug_ ? "false" : "true");
}
diff --git a/src/options.h b/src/options.h
index aa0f751..c48412d 100644
--- a/src/options.h
+++ b/src/options.h
@@ -45,6 +45,7 @@ struct options_struct {
char* remote_port_;
char* source_addr_;
char* config_file_;
+ int32_t buffer_size_;
int debug_;
};
typedef struct options_struct options_t;
diff --git a/src/tcpproxy.c b/src/tcpproxy.c
index 2abf6e6..d708770 100644
--- a/src/tcpproxy.c
+++ b/src/tcpproxy.c
@@ -49,7 +49,7 @@ int main_loop(options_t* opt, listeners_t* listeners)
return -1;
clients_t clients;
- int return_value = clients_init(&clients);
+ int return_value = clients_init(&clients, opt->buffer_size_);
while(!return_value) {
fd_set readfds, writefds;