4 * uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
5 * featured implementation uAnytun has no support for multiple connections
6 * or synchronisation. It is a small single threaded implementation intended
7 * to act as a client on small platforms.
8 * The secure anycast tunneling protocol (satp) defines a protocol used
9 * for communication between any combination of unicast and anycast
10 * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
11 * mode and allows tunneling of every ETHER TYPE protocol (e.g.
12 * ethernet, ip, arp ...). satp directly includes cryptography and
13 * message authentication based on the methodes used by SRTP. It is
14 * intended to deliver a generic, scaleable and secure solution for
15 * tunneling and relaying of packets of any protocol.
18 * Copyright (C) 2007-2010 Christian Pointner <equinox@anytun.org>
20 * This file is part of uAnytun.
22 * uAnytun is free software: you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation, either version 3 of the License, or
27 * uAnytun is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
36 #include "datatypes.h"
47 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <arpa/inet.h>
50 #include <netinet/in.h>
52 int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type)
58 sock->active_sock_ = NULL;
59 memset(&(sock->remote_end_), 0, sizeof(sock->remote_end_));
60 sock->remote_end_set_ = 0;
62 struct addrinfo hints, *res;
65 memset (&hints, 0, sizeof (hints));
66 hints.ai_socktype = SOCK_DGRAM;
67 hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
70 case IPV4_ONLY: hints.ai_family = AF_INET; break;
71 case IPV6_ONLY: hints.ai_family = AF_INET6; break;
72 default: hints.ai_family = AF_UNSPEC; break;
75 int errcode = getaddrinfo(local_addr, port, &hints, &res);
77 log_printf(ERROR, "Error resolving local address (%s:%s): %s", (local_addr) ? local_addr : "*", port, gai_strerror(errcode));
83 log_printf(ERROR, "getaddrinfo returned no address for %s:%s", local_addr, port);
87 struct addrinfo* r = res;
88 udp_socket_t* prev_sock = NULL;
90 udp_socket_t* new_sock = malloc(sizeof(udp_socket_t));
92 log_printf(ERROR, "memory error at udp_init");
97 memset(&(new_sock->local_end_), 0, sizeof(new_sock->local_end_));
98 new_sock->next_ = NULL;
101 sock->socks_ = new_sock;
102 prev_sock = new_sock;
105 prev_sock->next_ = new_sock;
106 prev_sock = new_sock;
109 memcpy(&(new_sock->local_end_), r->ai_addr, r->ai_addrlen);
110 new_sock->fd_ = socket(r->ai_family, SOCK_DGRAM, 0);
111 if(new_sock->fd_ < 0) {
112 log_printf(ERROR, "Error on opening udp socket: %s", strerror(errno));
118 if(r->ai_family == AF_INET6) {
120 if(setsockopt(new_sock->fd_, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)))
121 log_printf(ERROR, "Error on setting IPV6_V6ONLY socket option: %s", strerror(errno));
124 errcode = bind(new_sock->fd_, r->ai_addr, r->ai_addrlen);
126 log_printf(ERROR, "Error on binding udp socket: %s", strerror(errno));
132 char* local_string = udp_endpoint_to_string(new_sock->local_end_);
134 log_printf(NOTICE, "listening on: %s", local_string);
146 int udp_init_fd_set(udp_t* sock, fd_set* set)
150 udp_socket_t* s = sock->socks_;
153 max_fd = s->fd_ > max_fd ? s->fd_ : max_fd;
160 int udp_set_remote(udp_t* sock, const char* remote_addr, const char* port, resolv_addr_type_t resolv_type)
162 if(!sock || !remote_addr || !port)
165 struct addrinfo hints, *res;
168 memset (&hints, 0, sizeof (hints));
169 hints.ai_socktype = SOCK_DGRAM;
171 switch(resolv_type) {
172 case IPV4_ONLY: hints.ai_family = PF_INET; break;
173 case IPV6_ONLY: hints.ai_family = PF_INET6; break;
174 default: hints.ai_family = PF_UNSPEC; break;
177 int errcode = getaddrinfo(remote_addr, port, &hints, &res);
179 log_printf(ERROR, "Error resolving remote address (%s:%s): %s", (remote_addr) ? remote_addr : "*", port, gai_strerror(errcode));
183 log_printf(ERROR, "getaddrinfo returned no address for %s:%s", remote_addr, port);
186 memcpy(&(sock->remote_end_), res->ai_addr, res->ai_addrlen);
187 sock->remote_end_set_ = 1;
189 if(!sock->active_sock_) {
190 udp_socket_t* s = sock->socks_;
192 if((((struct sockaddr *)&s->local_end_)->sa_family) == res->ai_family) {
193 sock->active_sock_ = s;
205 void udp_set_active_sock(udp_t* sock, int fd)
207 if(!sock || (sock->active_sock_ && sock->active_sock_->fd_ == fd))
210 udp_socket_t* s = sock->socks_;
213 sock->active_sock_ = s;
220 void udp_close(udp_t* sock)
225 while(sock->socks_) {
226 if(sock->socks_->fd_ > 0)
227 close(sock->socks_->fd_);
229 udp_socket_t*s = sock->socks_;
230 sock->socks_ = sock->socks_->next_;
237 char* udp_endpoint_to_string(udp_endpoint_t e)
241 size_t addrstr_len = 0;
243 char addrport_sep = ':';
245 switch (((struct sockaddr *)&e)->sa_family)
248 ptr = &((struct sockaddr_in *)&e)->sin_addr;
249 port = ntohs(((struct sockaddr_in *)&e)->sin_port);
250 addrstr_len = INET_ADDRSTRLEN + 1;
254 ptr = &((struct sockaddr_in6 *)&e)->sin6_addr;
255 port = ntohs(((struct sockaddr_in6 *)&e)->sin6_port);
256 addrstr_len = INET6_ADDRSTRLEN + 1;
260 asprintf(&ret, "unknown address type");
263 addrstr = malloc(addrstr_len);
266 inet_ntop (((struct sockaddr *)&e)->sa_family, ptr, addrstr, addrstr_len);
267 asprintf(&ret, "%s%c%d", addrstr, addrport_sep ,port);
272 char* udp_get_remote_end_string(udp_t* sock)
274 if(!sock || !sock->remote_end_set_)
277 return udp_endpoint_to_string(sock->remote_end_);
280 int udp_read(udp_t* sock, int fd, u_int8_t* buf, u_int32_t len, udp_endpoint_t* remote_end)
282 if(!sock || !remote_end)
285 socklen_t socklen = sizeof(*remote_end);
286 return recvfrom(fd, buf, len, 0, (struct sockaddr *)remote_end, &socklen);
289 int udp_write(udp_t* sock, u_int8_t* buf, u_int32_t len)
291 if(!sock || !sock->remote_end_set_ || !sock->active_sock_)
294 socklen_t socklen = sizeof(sock->remote_end_);
295 if((((struct sockaddr *)&sock->active_sock_->local_end_)->sa_family) == AF_INET)
296 socklen = sizeof(struct sockaddr_in);
297 else if ((((struct sockaddr *)&sock->active_sock_->local_end_)->sa_family) == AF_INET6)
298 socklen = sizeof(struct sockaddr_in6);
300 return sendto(sock->active_sock_->fd_, buf, len, 0, (struct sockaddr *)&(sock->remote_end_), socklen);