239e074c35b0d672cb4e8d0c48ad7fb73b4aa23c
[debian/uanytun.git] / src / udp.c
1 /*
2  *  uAnytun
3  *
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 methods 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.
16  *
17  *
18  *  Copyright (C) 2007-2014 Christian Pointner <equinox@anytun.org>
19  *
20  *  This file is part of uAnytun.
21  *
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
25  *  any later version.
26  *
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.
31  *
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/>.
34  *
35  *  In addition, as a special exception, the copyright holders give
36  *  permission to link the code of portions of this program with the
37  *  OpenSSL library under certain conditions as described in each
38  *  individual source file, and distribute linked combinations
39  *  including the two.
40  *  You must obey the GNU General Public License in all respects
41  *  for all of the code used other than OpenSSL.  If you modify
42  *  file(s) with this exception, you may extend this exception to your
43  *  version of the file(s), but you are not obligated to do so.  If you
44  *  do not wish to do so, delete this exception statement from your
45  *  version.  If you delete this exception statement from all source
46  *  files in the program, then also delete it here.
47  */
48
49 #define _GNU_SOURCE
50 #include <stdio.h>
51
52 #include "datatypes.h"
53
54 #include "udp.h"
55
56 #include "log.h"
57
58 #include <errno.h>
59 #include <stdlib.h>
60 #include <unistd.h>
61 #include <string.h>
62 #include <netdb.h>
63 #include <sys/types.h>
64 #include <sys/socket.h>
65 #include <arpa/inet.h>
66 #include <netinet/in.h>
67
68 #ifndef AI_ADDRCONFIG 
69 #define AI_ADDRCONFIG 0 
70 #endif
71
72 static int udp_resolv_local(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type, unsigned int* idx)
73 {
74   struct addrinfo hints, *res;
75
76   res = NULL;
77   memset (&hints, 0, sizeof (hints));
78   hints.ai_socktype = SOCK_DGRAM;
79   hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
80
81   switch(resolv_type) {
82   case IPV4_ONLY: hints.ai_family = AF_INET; break;
83   case IPV6_ONLY: hints.ai_family = AF_INET6; break;
84   default: hints.ai_family = AF_UNSPEC; break;
85   }
86
87   int errcode = getaddrinfo(local_addr, port, &hints, &res);
88   if (errcode != 0) {
89     log_printf(ERROR, "Error resolving local address (%s:%s): %s", (local_addr) ? local_addr : "*", port, gai_strerror(errcode));
90     udp_close(sock);
91     return -1;
92   }
93   if(!res) {
94     udp_close(sock);
95     log_printf(ERROR, "getaddrinfo returned no address for %s:%s", local_addr, port);
96     return -1;
97   }
98
99   struct addrinfo* r = res;
100   udp_socket_t* prev_sock = sock->socks_;
101   while(prev_sock && prev_sock->next_) prev_sock = prev_sock->next_;
102   while(r) {
103     udp_socket_t* new_sock = malloc(sizeof(udp_socket_t));
104     if(!new_sock) {
105       log_printf(ERROR, "memory error at udp_init");
106       freeaddrinfo(res);
107       udp_close(sock);
108       return -2;
109     }
110     memset(&(new_sock->local_end_.addr_), 0, sizeof(new_sock->local_end_.addr_));
111     new_sock->local_end_.len_ = sizeof(new_sock->local_end_.addr_);
112     memset(&(new_sock->remote_end_.addr_), 0, sizeof(new_sock->remote_end_.addr_));
113     new_sock->remote_end_.len_ = sizeof(new_sock->remote_end_.addr_);
114     new_sock->remote_end_set_ = 0;
115     new_sock->next_ = NULL;
116     new_sock->idx_ = (*idx)++;
117
118     if(!sock->socks_) {
119       sock->socks_ = new_sock;
120       prev_sock = new_sock;
121     }
122     else {
123       prev_sock->next_ = new_sock;
124       prev_sock = new_sock;
125     }
126
127     memcpy(&(new_sock->local_end_.addr_), r->ai_addr, r->ai_addrlen);
128     new_sock->local_end_.len_ = r->ai_addrlen;
129     new_sock->fd_ = socket(new_sock->local_end_.addr_.ss_family, SOCK_DGRAM, 0);
130     if(new_sock->fd_ < 0) {
131       log_printf(ERROR, "Error on opening udp socket: %s", strerror(errno));
132       freeaddrinfo(res);
133       udp_close(sock);
134       return -1;
135     }
136
137     if(r->ai_family == AF_INET6) {
138       int on = 1;
139       if(setsockopt(new_sock->fd_, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)))
140         log_printf(ERROR, "Error on setting IPV6_V6ONLY socket option: %s", strerror(errno));
141     }
142
143     errcode = bind(new_sock->fd_, (struct sockaddr*)&(new_sock->local_end_.addr_), new_sock->local_end_.len_);
144     if(errcode) {
145       log_printf(ERROR, "Error on binding udp socket: %s", strerror(errno));
146       freeaddrinfo(res);
147       udp_close(sock);
148       return -1;
149     }
150
151     char* local_string = udp_endpoint_to_string(&(new_sock->local_end_));
152     if(local_string) {
153       log_printf(NOTICE, "socket[%d] listening on: %s", new_sock->idx_, local_string);
154       free(local_string);
155     }
156
157     r = r->ai_next;
158   }
159
160   freeaddrinfo(res);
161   return 0;
162 }
163
164 int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type)
165 {
166   if(!sock || !port)
167     return -1;
168
169   sock->socks_ = NULL;
170   sock->active_sock_ = NULL;
171
172   unsigned int idx = 0;
173   int ret = udp_resolv_local(sock, local_addr, port, resolv_type, &idx);
174   if(ret)
175     return ret;
176
177   return 0;
178 }
179
180 int udp_fill_fd_set(udp_t* sock, fd_set* set)
181 {
182   int max_fd = 0;
183
184   udp_socket_t* s = sock->socks_;
185   while(s) {
186     FD_SET(s->fd_, set);
187     max_fd = s->fd_ > max_fd ? s->fd_ : max_fd;
188     s = s->next_;
189   }
190
191   return max_fd;
192 }
193
194 int udp_has_remote(udp_t* sock)
195 {
196   if(!sock->active_sock_ || !sock->active_sock_->remote_end_set_)
197     return 0;
198
199   udp_socket_t* s = sock->socks_;
200   while(s) {
201     if(s->remote_end_set_)
202       return 1;
203     s = s->next_;
204   }
205
206   return 0;
207 }
208
209 int udp_resolv_remote(udp_t* sock, const char* remote_addr, const char* port, resolv_addr_type_t resolv_type)
210 {
211   struct addrinfo hints, *res;
212
213   if(!sock || !remote_addr || !port)
214     return -1;
215
216   res = NULL;
217   memset (&hints, 0, sizeof (hints));
218   hints.ai_socktype = SOCK_DGRAM;
219
220   switch(resolv_type) {
221   case IPV4_ONLY: hints.ai_family = PF_INET; break;
222   case IPV6_ONLY: hints.ai_family = PF_INET6; break;
223   default: hints.ai_family = PF_UNSPEC; break;
224   }
225
226   int errcode = getaddrinfo(remote_addr, port, &hints, &res);
227   if (errcode != 0) {
228     log_printf(ERROR, "Error resolving remote address (%s:%s): %s", (remote_addr) ? remote_addr : "*", port, gai_strerror(errcode));
229     return -1;
230   }
231   if(!res) {
232     log_printf(ERROR, "getaddrinfo returned no address for %s:%s", remote_addr, port);
233     return -1;
234   }
235
236   int found = 0;
237   struct addrinfo* r = res;
238   while(r) {
239     udp_socket_t* s = sock->socks_;
240     while(s) {
241       if(s->local_end_.addr_.ss_family == r->ai_family && !(s->remote_end_set_)) {
242         sock->active_sock_ = s;
243         break;
244       }
245       s = s->next_;
246     }
247
248     if(s) {
249       memcpy(&(s->remote_end_.addr_), r->ai_addr, r->ai_addrlen);
250       s->remote_end_.len_ = r->ai_addrlen;
251       s->remote_end_set_ = 1;
252       found = 1;
253       char* remote_string = udp_endpoint_to_string(&(s->remote_end_));
254       if(remote_string) {
255         log_printf(NOTICE, "socket[%d] set remote end to: %s", s->idx_, remote_string);
256         free(remote_string);
257       }
258       break;
259     }
260
261     r = r->ai_next;
262   }
263   freeaddrinfo(res);
264
265   if(!found)
266     log_printf(WARNING, "no remote address for '%s' found that fits any of the local address families", remote_addr);
267
268   return 0;
269 }
270
271 void udp_update_remote(udp_t* sock, int fd, udp_endpoint_t* remote)
272 {
273   if(!sock)
274     return;
275
276   if(!(sock->active_sock_) || sock->active_sock_->fd_ != fd) {
277     udp_socket_t* s = sock->socks_;
278     while(s) {
279       if(s->fd_ == fd) {
280         sock->active_sock_ = s;
281         break;
282       }
283       s = s->next_;
284     }
285   }
286
287   if(!remote)
288     return;
289
290   if(sock->active_sock_) {
291     if(remote->len_ != sock->active_sock_->remote_end_.len_ ||
292        memcmp(&(remote->addr_), &(sock->active_sock_->remote_end_.addr_), remote->len_)) {
293       memcpy(&(sock->active_sock_->remote_end_.addr_), &(remote->addr_), remote->len_);
294       sock->active_sock_->remote_end_.len_ = remote->len_;
295       sock->active_sock_->remote_end_set_ = 1;
296       char* addrstring = udp_endpoint_to_string(remote);
297       log_printf(NOTICE, "socket[%d] autodetected remote host changed %s", sock->active_sock_->idx_, addrstring);
298       free(addrstring);
299     }
300   }
301 }
302
303 void udp_close(udp_t* sock)
304 {
305   if(!sock)
306     return;
307
308   while(sock->socks_) {
309     if(sock->socks_->fd_ > 0)
310       close(sock->socks_->fd_);
311
312     udp_socket_t*s = sock->socks_;
313     sock->socks_ = sock->socks_->next_;
314
315     free(s);
316   }
317   sock->socks_ = NULL;
318   sock->active_sock_ = NULL;
319 }
320
321 char* udp_endpoint_to_string(udp_endpoint_t* e)
322 {
323   if(!e)
324     return strdup("<null>");
325
326   char addrstr[INET6_ADDRSTRLEN + 1], portstr[6], *ret;
327   char addrport_sep = ':';
328
329   switch(e->addr_.ss_family)
330   {
331   case AF_INET: addrport_sep = ':'; break;
332   case AF_INET6: addrport_sep = '.'; break;
333   case AF_UNSPEC: return NULL;
334   default: return strdup("<unknown address type>");
335   }
336
337   int errcode  = getnameinfo((struct sockaddr *)&(e->addr_), e->len_, addrstr, sizeof(addrstr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
338   if (errcode != 0) return NULL;
339   int len = asprintf(&ret, "%s%c%s", addrstr, addrport_sep ,portstr);
340   if(len == -1) return NULL;
341   return ret;
342 }
343
344
345 int udp_read(udp_t* sock, int fd, u_int8_t* buf, u_int32_t len, udp_endpoint_t* remote_end)
346 {
347   if(!sock || !buf || !remote_end)
348     return -1;
349
350   return recvfrom(fd, buf, len, 0, (struct sockaddr *)&(remote_end->addr_), &(remote_end->len_));
351 }
352
353
354 int udp_write(udp_t* sock, u_int8_t* buf, u_int32_t len)
355 {
356   if(!sock || !buf || !sock->active_sock_ || !sock->active_sock_->remote_end_set_)
357     return 0;
358
359   return sendto(sock->active_sock_->fd_, buf, len, 0, (struct sockaddr *)&(sock->active_sock_->remote_end_.addr_), sock->active_sock_->remote_end_.len_);
360 }