summaryrefslogtreecommitdiff
path: root/src/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/udp.c')
-rw-r--r--src/udp.c162
1 files changed, 109 insertions, 53 deletions
diff --git a/src/udp.c b/src/udp.c
index 1491d75..9ef4fba 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -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_);
}
-