From 4793dc0638330ef5296c126d136489228d9521b0 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Sat, 27 Nov 2010 03:31:35 +0000 Subject: listening on tcp sockets works now git-svn-id: https://svn.spreadspace.org/tcpproxy/trunk@8 e61f0598-a718-4e21-a8f0-0aadfa62ad6b --- src/listener.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 81 insertions(+), 16 deletions(-) (limited to 'src/listener.c') diff --git a/src/listener.c b/src/listener.c index 4025b26..07428bc 100644 --- a/src/listener.c +++ b/src/listener.c @@ -25,13 +25,20 @@ * along with tcpproxy. If not, see . */ -#include +#include #include -#include +#include #include +#include +#include +#include +#include +#include +#include #include "listener.h" #include "tcp.h" +#include "log.h" void listener_delete_element(void* e) { @@ -54,27 +61,85 @@ void listener_clear(listeners_t* list) slist_clear(list); } -int listener_add(listeners_t* list, char* laddr, char* lport, char* raddr, char* rport) +int listener_add(listeners_t* list, const char* laddr, const char* lport, const char* raddr, const char* rport) { if(!list) return -1; - - listener_t* element = malloc(sizeof(listener_t)); - if(!element) - return -2; - -// TODO: open listen socket and resolv local and remote address - static int fds = 6; +// TODO: what if more than one address is returned here? + struct addrinfo* re = tcp_resolve_endpoint(raddr, rport, ANY); + if(!re) + return -1; + + struct addrinfo* le = tcp_resolve_endpoint(laddr, lport, ANY); + if(!le) { + freeaddrinfo(re); + return -1; + } + + struct addrinfo* l = le; + int ret = 0; + while(l) { + listener_t* element = malloc(sizeof(listener_t)); + if(!element) { + ret = -2; + break; + } + memset(&(element->remote_end_), 0, sizeof(element->remote_end_)); + memcpy(&(element->remote_end_), re->ai_addr, re->ai_addrlen); + + memset(&(element->local_end_), 0, sizeof(element->local_end_)); + memcpy(&(element->local_end_), l->ai_addr, l->ai_addrlen); + + element->fd_ = socket(l->ai_family, SOCK_STREAM, 0); + if(element->fd_ < 0) { + log_printf(ERROR, "Error on opening tcp socket: %s", strerror(errno)); + free(element); + ret = -1; + break; + } + + if(l->ai_family == AF_INET6) { + int on = 1; + if(setsockopt(element->fd_, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on))) + log_printf(WARNING, "failed to set IPV6_V6ONLY socket option: %s", strerror(errno)); + } + + ret = bind(element->fd_, l->ai_addr, l->ai_addrlen); + if(ret) { + log_printf(ERROR, "Error on bind(): %s", strerror(errno)); + close(element->fd_); + free(element); + break; + } - element->fd_ = fds++; - memset(&(element->local_end_), 0, sizeof(element->local_end_)); - memset(&(element->remote_end_), 0, sizeof(element->remote_end_)); + ret = listen(element->fd_, 0); + if(ret) { + log_printf(ERROR, "Error on listen(): %s", strerror(errno)); + close(element->fd_); + free(element); + break; + } + + 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)"); + if(ls) free(ls); + if(rs) free(rs); + + if(slist_add(list, element) == NULL) { + close(element->fd_); + free(element); + ret = -2; + break; + } - if(slist_add(list, element) == NULL) - return -2; + l = l->ai_next; + } + freeaddrinfo(re); + freeaddrinfo(le); - return 0; + return ret; } void listener_remove(listeners_t* list, int fd) -- cgit v1.2.3