diff options
author | Christian Pointner <equinox@anytun.org> | 2014-06-08 18:41:58 +0000 |
---|---|---|
committer | Christian Pointner <equinox@anytun.org> | 2014-06-08 18:41:58 +0000 |
commit | 1604cea7467a76866dcf4efc067d910712a869a0 (patch) | |
tree | 1aabbd79088761c025a0e45a7acfee96caff2e13 /src/udp.c | |
parent | fixed errnous copy of remote end (diff) |
merged most changes from rail branch to trunk
Diffstat (limited to 'src/udp.c')
-rw-r--r-- | src/udp.c | 162 |
1 files changed, 109 insertions, 53 deletions
@@ -13,9 +13,9 @@ * message authentication based on the methodes used by SRTP. It is * intended to deliver a generic, scaleable and secure solution for * tunneling and relaying of packets of any protocol. - * * - * Copyright (C) 2007-2010 Christian Pointner <equinox@anytun.org> + * + * Copyright (C) 2007-2014 Christian Pointner <equinox@anytun.org> * * This file is part of uAnytun. * @@ -52,17 +52,8 @@ #include <arpa/inet.h> #include <netinet/in.h> -int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type) +static int udp_resolv_local(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type, unsigned int* idx) { - if(!sock || !port) - return -1; - - sock->socks_ = NULL; - sock->active_sock_ = NULL; - memset(&(sock->remote_end_.addr_), 0, sizeof(sock->remote_end_.addr_)); - sock->remote_end_.len_ = sizeof(sock->remote_end_.addr_); - sock->remote_end_set_ = 0; - struct addrinfo hints, *res; res = NULL; @@ -89,7 +80,8 @@ int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_ } struct addrinfo* r = res; - udp_socket_t* prev_sock = NULL; + udp_socket_t* prev_sock = sock->socks_; + while(prev_sock && prev_sock->next_) prev_sock = prev_sock->next_; while(r) { udp_socket_t* new_sock = malloc(sizeof(udp_socket_t)); if(!new_sock) { @@ -100,7 +92,11 @@ int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_ } memset(&(new_sock->local_end_.addr_), 0, sizeof(new_sock->local_end_.addr_)); new_sock->local_end_.len_ = sizeof(new_sock->local_end_.addr_); + memset(&(new_sock->remote_end_.addr_), 0, sizeof(new_sock->remote_end_.addr_)); + new_sock->remote_end_.len_ = sizeof(new_sock->remote_end_.addr_); + new_sock->remote_end_set_ = 0; new_sock->next_ = NULL; + new_sock->idx_ = (*idx)++; if(!sock->socks_) { sock->socks_ = new_sock; @@ -110,7 +106,7 @@ int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_ prev_sock->next_ = new_sock; prev_sock = new_sock; } - + memcpy(&(new_sock->local_end_.addr_), r->ai_addr, r->ai_addrlen); new_sock->local_end_.len_ = r->ai_addrlen; new_sock->fd_ = socket(new_sock->local_end_.addr_.ss_family, SOCK_DGRAM, 0); @@ -134,10 +130,10 @@ int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_ udp_close(sock); return -1; } - - char* local_string = udp_endpoint_to_string(new_sock->local_end_); + + char* local_string = udp_endpoint_to_string(&(new_sock->local_end_)); if(local_string) { - log_printf(NOTICE, "listening on: %s", local_string); + log_printf(NOTICE, "socket[%d] listening on: %s", new_sock->idx_, local_string); free(local_string); } @@ -145,11 +141,26 @@ int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_ } freeaddrinfo(res); + return 0; +} + +int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type) +{ + if(!sock || !port) + return -1; + + sock->socks_ = NULL; + sock->active_sock_ = NULL; + + unsigned int idx = 0; + int ret = udp_resolv_local(sock, local_addr, port, resolv_type, &idx); + if(ret) + return ret; return 0; } -int udp_init_fd_set(udp_t* sock, fd_set* set) +int udp_fill_fd_set(udp_t* sock, fd_set* set) { int max_fd = 0; @@ -163,13 +174,28 @@ int udp_init_fd_set(udp_t* sock, fd_set* set) return max_fd; } -int udp_set_remote(udp_t* sock, const char* remote_addr, const char* port, resolv_addr_type_t resolv_type) +int udp_has_remote(udp_t* sock) { - if(!sock || !remote_addr || !port) - return -1; + if(!sock->active_sock_ || !sock->active_sock_->remote_end_set_) + return 0; + + udp_socket_t* s = sock->socks_; + while(s) { + if(s->remote_end_set_) + return 1; + s = s->next_; + } + + return 0; +} +int udp_resolv_remote(udp_t* sock, const char* remote_addr, const char* port, resolv_addr_type_t resolv_type) +{ struct addrinfo hints, *res; + if(!sock || !remote_addr || !port) + return -1; + res = NULL; memset (&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_DGRAM; @@ -189,38 +215,71 @@ int udp_set_remote(udp_t* sock, const char* remote_addr, const char* port, resol log_printf(ERROR, "getaddrinfo returned no address for %s:%s", remote_addr, port); return -1; } - memcpy(&(sock->remote_end_.addr_), res->ai_addr, res->ai_addrlen); - sock->remote_end_.len_ = res->ai_addrlen; - sock->remote_end_set_ = 1; - if(!sock->active_sock_) { + int found = 0; + struct addrinfo* r = res; + while(r) { udp_socket_t* s = sock->socks_; while(s) { - if(s->local_end_.addr_.ss_family == res->ai_family) { + if(s->local_end_.addr_.ss_family == r->ai_family && !(s->remote_end_set_)) { sock->active_sock_ = s; break; } s = s->next_; } - } + if(s) { + memcpy(&(s->remote_end_.addr_), r->ai_addr, r->ai_addrlen); + s->remote_end_.len_ = r->ai_addrlen; + s->remote_end_set_ = 1; + found = 1; + char* remote_string = udp_endpoint_to_string(&(s->remote_end_)); + if(remote_string) { + log_printf(NOTICE, "socket[%d] set remote end to: %s", s->idx_, remote_string); + free(remote_string); + } + break; + } + + r = r->ai_next; + } freeaddrinfo(res); + if(!found) + log_printf(WARNING, "no remote address for '%s' found that fits any of the local address families", remote_addr); + return 0; } -void udp_set_active_sock(udp_t* sock, int fd) +void udp_update_remote(udp_t* sock, int fd, udp_endpoint_t* remote) { - if(!sock || (sock->active_sock_ && sock->active_sock_->fd_ == fd)) + if(!sock) return; - udp_socket_t* s = sock->socks_; - while(s) { - if(s->fd_ == fd) { - sock->active_sock_ = s; - return; + if(!(sock->active_sock_) || sock->active_sock_->fd_ != fd) { + udp_socket_t* s = sock->socks_; + while(s) { + if(s->fd_ == fd) { + sock->active_sock_ = s; + break; + } + s = s->next_; + } + } + + if(!remote) + return; + + if(sock->active_sock_) { + if(remote->len_ != sock->active_sock_->remote_end_.len_ || + memcmp(&(remote->addr_), &(sock->active_sock_->remote_end_.addr_), remote->len_)) { + memcpy(&(sock->active_sock_->remote_end_.addr_), &(remote->addr_), remote->len_); + sock->active_sock_->remote_end_.len_ = remote->len_; + sock->active_sock_->remote_end_set_ = 1; + char* addrstring = udp_endpoint_to_string(remote); + log_printf(NOTICE, "socket[%d] autodetected remote host changed %s", sock->active_sock_->idx_, addrstring); + free(addrstring); } - s = s->next_; } } @@ -232,56 +291,53 @@ void udp_close(udp_t* sock) while(sock->socks_) { if(sock->socks_->fd_ > 0) close(sock->socks_->fd_); - + udp_socket_t*s = sock->socks_; sock->socks_ = sock->socks_->next_; - + free(s); } sock->socks_ = NULL; + sock->active_sock_ = NULL; } -char* udp_endpoint_to_string(udp_endpoint_t e) +char* udp_endpoint_to_string(udp_endpoint_t* e) { + if(!e) + return strdup("<null>"); + char addrstr[INET6_ADDRSTRLEN + 1], portstr[6], *ret; char addrport_sep = ':'; - - switch(e.addr_.ss_family) + + switch(e->addr_.ss_family) { case AF_INET: addrport_sep = ':'; break; case AF_INET6: addrport_sep = '.'; break; case AF_UNSPEC: return NULL; - default: return strdup("unknown address type"); + default: return strdup("<unknown address type>"); } - int errcode = getnameinfo((struct sockaddr *)&(e.addr_), e.len_, addrstr, sizeof(addrstr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); + int errcode = getnameinfo((struct sockaddr *)&(e->addr_), e->len_, addrstr, sizeof(addrstr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV); if (errcode != 0) return NULL; int len = asprintf(&ret, "%s%c%s", addrstr, addrport_sep ,portstr); if(len == -1) return NULL; return ret; } -char* udp_get_remote_end_string(udp_t* sock) -{ - if(!sock || !sock->remote_end_set_) - return NULL; - return udp_endpoint_to_string(sock->remote_end_); -} - int udp_read(udp_t* sock, int fd, u_int8_t* buf, u_int32_t len, udp_endpoint_t* remote_end) { - if(!sock || !remote_end) + if(!sock || !buf || !remote_end) return -1; return recvfrom(fd, buf, len, 0, (struct sockaddr *)&(remote_end->addr_), &(remote_end->len_)); } + int udp_write(udp_t* sock, u_int8_t* buf, u_int32_t len) { - if(!sock || !sock->remote_end_set_ || !sock->active_sock_) + if(!sock || !buf || !sock->active_sock_ || !sock->active_sock_->remote_end_set_) return 0; - return sendto(sock->active_sock_->fd_, buf, len, 0, (struct sockaddr *)&(sock->remote_end_.addr_), sock->remote_end_.len_); + return sendto(sock->active_sock_->fd_, buf, len, 0, (struct sockaddr *)&(sock->active_sock_->remote_end_.addr_), sock->active_sock_->remote_end_.len_); } - |