summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2010-11-28 22:55:24 +0000
committerChristian Pointner <equinox@spreadspace.org>2010-11-28 22:55:24 +0000
commit174a9f39da1f09c6ffd9c6f0b3a6a42da5ec4163 (patch)
tree74bb2be118291b2df2ad7d18d33a6816626a32e6
parentfirst minial version working (diff)
source address to connect from can now be specified
git-svn-id: https://svn.spreadspace.org/tcpproxy/trunk@13 e61f0598-a718-4e21-a8f0-0aadfa62ad6b
-rw-r--r--src/clients.c18
-rw-r--r--src/clients.h2
-rw-r--r--src/listener.c24
-rw-r--r--src/listener.h3
-rw-r--r--src/options.c6
-rw-r--r--src/options.h1
-rw-r--r--src/tcp.c6
-rw-r--r--src/tcpproxy.c2
8 files changed, 53 insertions, 9 deletions
diff --git a/src/clients.c b/src/clients.c
index 9e5c9fc..6db10fc 100644
--- a/src/clients.c
+++ b/src/clients.c
@@ -63,7 +63,7 @@ void clients_clear(clients_t* list)
slist_clear(list);
}
-int clients_add(clients_t* list, int fd, const tcp_endpoint_t* remote_end)
+int clients_add(clients_t* list, int fd, const tcp_endpoint_t* remote_end, const tcp_endpoint_t* source_end)
{
if(!list)
@@ -87,6 +87,22 @@ int clients_add(clients_t* list, int fd, const tcp_endpoint_t* remote_end)
return -1;
}
+ if(source_end->ss_family != AF_UNSPEC) {
+ socklen_t socklen = sizeof(*source_end);
+ if(source_end->ss_family == AF_INET)
+ socklen = sizeof(struct sockaddr_in);
+ else if (source_end->ss_family == AF_INET6)
+ socklen = sizeof(struct sockaddr_in6);
+
+ if(bind(element->fd_[1], (struct sockaddr *)source_end, socklen)==-1) {
+ log_printf(INFO, "Error on bind(): %s, not adding client %d", strerror(errno), element->fd_[0]);
+ close(element->fd_[0]);
+ close(element->fd_[1]);
+ free(element);
+ return -1;
+ }
+ }
+
socklen_t socklen = sizeof(*remote_end);
if(remote_end->ss_family == AF_INET)
socklen = sizeof(struct sockaddr_in);
diff --git a/src/clients.h b/src/clients.h
index 7052161..8a78aa2 100644
--- a/src/clients.h
+++ b/src/clients.h
@@ -47,7 +47,7 @@ typedef slist_t clients_t;
int clients_init(clients_t* list);
void clients_clear(clients_t* list);
-int clients_add(clients_t* list, int fd, const tcp_endpoint_t* remote_end);
+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);
client_t* clients_find(clients_t* list, int fd);
void clients_print(clients_t* list);
diff --git a/src/listener.c b/src/listener.c
index e649bf8..5e34c3d 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -66,7 +66,7 @@ void listener_clear(listeners_t* list)
slist_clear(list);
}
-int listener_add(listeners_t* list, const char* laddr, const char* lport, const char* raddr, const char* rport)
+int listener_add(listeners_t* list, const char* laddr, const char* lport, const char* raddr, const char* rport, const char* saddr)
{
if(!list)
return -1;
@@ -76,9 +76,20 @@ int listener_add(listeners_t* list, const char* laddr, const char* lport, const
if(!re)
return -1;
+ struct addrinfo* se = NULL;
+ if(saddr) {
+ se = tcp_resolve_endpoint(saddr, NULL, ANY);
+ if(!se) {
+ freeaddrinfo(re);
+ return -1;
+ }
+ }
+
struct addrinfo* le = tcp_resolve_endpoint(laddr, lport, ANY);
if(!le) {
freeaddrinfo(re);
+ if(se)
+ freeaddrinfo(se);
return -1;
}
@@ -93,6 +104,10 @@ int listener_add(listeners_t* list, const char* laddr, const char* lport, const
memset(&(element->remote_end_), 0, sizeof(element->remote_end_));
memcpy(&(element->remote_end_), re->ai_addr, re->ai_addrlen);
+ memset(&(element->source_end_), 0, sizeof(element->source_end_));
+ if(se) memcpy(&(element->source_end_), se->ai_addr, se->ai_addrlen);
+ else element->source_end_.ss_family = AF_UNSPEC;
+
memset(&(element->local_end_), 0, sizeof(element->local_end_));
memcpy(&(element->local_end_), l->ai_addr, l->ai_addrlen);
@@ -135,9 +150,11 @@ int listener_add(listeners_t* list, const char* laddr, const char* lport, const
char* ls = tcp_endpoint_to_string(element->local_end_);
char* rs = tcp_endpoint_to_string(element->remote_end_);
- log_printf(NOTICE, "listening on: %s (remote: %s)", ls ? ls:"(null)", rs ? rs:"(null)");
+ char* ss = tcp_endpoint_to_string(element->source_end_);
+ log_printf(NOTICE, "listening on: %s (remote: %s%s%s)", ls ? ls:"(null)", rs ? rs:"(null)", ss ? " with source " : "", ss ? ss : "");
if(ls) free(ls);
if(rs) free(rs);
+ if(ss) free(ss);
if(slist_add(list, element) == NULL) {
close(element->fd_);
@@ -149,6 +166,7 @@ int listener_add(listeners_t* list, const char* laddr, const char* lport, const
l = l->ai_next;
}
freeaddrinfo(re);
+ if(se) freeaddrinfo(se);
freeaddrinfo(le);
return ret;
@@ -231,7 +249,7 @@ int listener_handle_accept(listeners_t* list, clients_t* clients, fd_set* set)
if(rs) free(rs);
FD_CLR(l->fd_, set);
- clients_add(clients, new_client, &(l->remote_end_));
+ clients_add(clients, new_client, &(l->remote_end_), &(l->source_end_));
}
tmp = tmp->next_;
}
diff --git a/src/listener.h b/src/listener.h
index 8e87e96..11d5d24 100644
--- a/src/listener.h
+++ b/src/listener.h
@@ -38,6 +38,7 @@ typedef struct {
int fd_;
tcp_endpoint_t local_end_;
tcp_endpoint_t remote_end_;
+ tcp_endpoint_t source_end_;
} listener_t;
void listener_delete_element(void* e);
@@ -46,7 +47,7 @@ typedef slist_t listeners_t;
int listener_init(listeners_t* list);
void listener_clear(listeners_t* list);
-int listener_add(listeners_t* list, const char* laddr, const char* lport, const char* raddr, const char* rport);
+int listener_add(listeners_t* list, const char* laddr, const char* lport, const char* raddr, const char* rport, const char* saddr);
void listener_remove(listeners_t* list, int fd);
listener_t* listener_find(listeners_t* list, int fd);
void listener_print(listeners_t* list);
diff --git a/src/options.c b/src/options.c
index 27c97d0..39e53ee 100644
--- a/src/options.c
+++ b/src/options.c
@@ -182,6 +182,7 @@ int options_parse(options_t* opt, int argc, char* argv[])
PARSE_STRING_PARAM("-p","--local-port", opt->local_port_)
PARSE_STRING_PARAM("-r","--remote-addr", opt->remote_addr_)
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_)
else
return i;
@@ -222,6 +223,7 @@ void options_default(options_t* opt)
opt->local_port_ = NULL;
opt->remote_addr_ = NULL;
opt->remote_port_ = NULL;
+ opt->source_addr_ = NULL;
opt->config_file_ = strdup(CONFFILE);
string_list_init(&opt->log_targets_);
opt->debug_ = 0;
@@ -251,6 +253,8 @@ void options_clear(options_t* opt)
free(opt->remote_addr_);
if(opt->remote_port_)
free(opt->remote_port_);
+ if(opt->source_addr_)
+ free(opt->source_addr_);
if(opt->config_file_)
free(opt->config_file_);
}
@@ -272,6 +276,7 @@ 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(" [-c|--config] <file> configuration file\n");
}
@@ -298,6 +303,7 @@ void options_print(options_t* opt)
printf("local_port: '%s'\n", opt->local_port_);
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("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 197d337..aa0f751 100644
--- a/src/options.h
+++ b/src/options.h
@@ -43,6 +43,7 @@ struct options_struct {
char* local_port_;
char* remote_addr_;
char* remote_port_;
+ char* source_addr_;
char* config_file_;
int debug_;
};
diff --git a/src/tcp.c b/src/tcp.c
index 0211526..cbc9134 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -60,6 +60,8 @@ char* tcp_endpoint_to_string(tcp_endpoint_t e)
addrstr_len = INET6_ADDRSTRLEN + 1;
addrport_sep = '.';
break;
+ case AF_UNSPEC:
+ return NULL;
default:
asprintf(&ret, "unknown address type");
return ret;
@@ -90,11 +92,11 @@ struct addrinfo* tcp_resolve_endpoint(const char* addr, const char* port, resolv
int errcode = getaddrinfo(addr, port, &hints, &res);
if (errcode != 0) {
- log_printf(ERROR, "Error resolving local address (%s:%s): %s", (addr) ? addr : "*", port, gai_strerror(errcode));
+ log_printf(ERROR, "Error resolving local address (%s:%s): %s", (addr) ? addr : "*", (port) ? port : "0", gai_strerror(errcode));
return NULL;
}
if(!res) {
- log_printf(ERROR, "getaddrinfo returned no address for %s:%s", addr, port);
+ log_printf(ERROR, "getaddrinfo returned no address for %s:%s", (addr) ? addr : "*", (port) ? port : "0");
return NULL;
}
diff --git a/src/tcpproxy.c b/src/tcpproxy.c
index 6a55ea1..2abf6e6 100644
--- a/src/tcpproxy.c
+++ b/src/tcpproxy.c
@@ -145,7 +145,7 @@ int main(int argc, char* argv[])
log_close();
exit(-1);
}
- ret = listener_add(&listeners, opt.local_addr_, opt.local_port_, opt.remote_addr_, opt.remote_port_);
+ ret = listener_add(&listeners, opt.local_addr_, opt.local_port_, opt.remote_addr_, opt.remote_port_, opt.source_addr_);
if(ret) {
listener_clear(&listeners);
options_clear(&opt);