9217688105718aef3d463b3c1b82649ceda8954c
[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 static int udp_resolv_local(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type, unsigned int* idx)
69 {
70   struct addrinfo hints, *res;
71
72   res = NULL;
73   memset (&hints, 0, sizeof (hints));
74   hints.ai_socktype = SOCK_DGRAM;
75   hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
76
77   switch(resolv_type) {
78   case IPV4_ONLY: hints.ai_family = AF_INET; break;
79   case IPV6_ONLY: hints.ai_family = AF_INET6; break;
80   default: hints.ai_family = AF_UNSPEC; break;
81   }
82
83   int errcode = getaddrinfo(local_addr, port, &hints, &res);
84   if (errcode != 0) {
85     log_printf(ERROR, "Error resolving local address (%s:%s): %s", (local_addr) ? local_addr : "*", port, gai_strerror(errcode));
86     udp_close(sock);
87     return -1;
88   }
89   if(!res) {
90     udp_close(sock);
91     log_printf(ERROR, "getaddrinfo returned no address for %s:%s", local_addr, port);
92     return -1;
93   }
94
95   struct addrinfo* r = res;
96   udp_socket_t* prev_sock = sock->socks_;
97   while(prev_sock && prev_sock->next_) prev_sock = prev_sock->next_;
98   while(r) {
99     udp_socket_t* new_sock = malloc(sizeof(udp_socket_t));
100     if(!new_sock) {
101       log_printf(ERROR, "memory error at udp_init");
102       freeaddrinfo(res);
103       udp_close(sock);
104       return -2;
105     }
106     memset(&(new_sock->local_end_.addr_), 0, sizeof(new_sock->local_end_.addr_));
107     new_sock->local_end_.len_ = sizeof(new_sock->local_end_.addr_);
108     memset(&(new_sock->remote_end_.addr_), 0, sizeof(new_sock->remote_end_.addr_));
109     new_sock->remote_end_.len_ = sizeof(new_sock->remote_end_.addr_);
110     new_sock->remote_end_set_ = 0;
111     new_sock->next_ = NULL;
112     new_sock->idx_ = (*idx)++;
113
114     if(!sock->socks_) {
115       sock->socks_ = new_sock;
116       prev_sock = new_sock;
117     }
118     else {
119       prev_sock->next_ = new_sock;
120       prev_sock = new_sock;
121     }
122
123     memcpy(&(new_sock->local_end_.addr_), r->ai_addr, r->ai_addrlen);
124     new_sock->local_end_.len_ = r->ai_addrlen;
125     new_sock->fd_ = socket(new_sock->local_end_.addr_.ss_family, SOCK_DGRAM, 0);
126     if(new_sock->fd_ < 0) {
127       log_printf(ERROR, "Error on opening udp socket: %s", strerror(errno));
128       freeaddrinfo(res);
129       udp_close(sock);
130       return -1;
131     }
132
133     if(r->ai_family == AF_INET6) {
134       int on = 1;
135       if(setsockopt(new_sock->fd_, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)))
136         log_printf(ERROR, "Error on setting IPV6_V6ONLY socket option: %s", strerror(errno));
137     }
138
139     errcode = bind(new_sock->fd_, (struct sockaddr*)&(new_sock->local_end_.addr_), new_sock->local_end_.len_);
140     if(errcode) {
141       log_printf(ERROR, "Error on binding udp socket: %s", strerror(errno));
142       freeaddrinfo(res);
143       udp_close(sock);
144       return -1;
145     }
146
147     char* local_string = udp_endpoint_to_string(&(new_sock->local_end_));
148     if(local_string) {
149       log_printf(NOTICE, "socket[%d] listening on: %s", new_sock->idx_, local_string);
150       free(local_string);
151     }
152
153     r = r->ai_next;
154   }
155
156   freeaddrinfo(res);
157   return 0;
158 }
159
160 int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type)
161 {
162   if(!sock || !port)
163     return -1;
164
165   sock->socks_ = NULL;
166   sock->active_sock_ = NULL;
167
168   unsigned int idx = 0;
169   int ret = udp_resolv_local(sock, local_addr, port, resolv_type, &idx);
170   if(ret)
171     return ret;
172
173   return 0;
174 }
175
176 int udp_fill_fd_set(udp_t* sock, fd_set* set)
177 {
178   int max_fd = 0;
179
180   udp_socket_t* s = sock->socks_;
181   while(s) {
182     FD_SET(s->fd_, set);
183     max_fd = s->fd_ > max_fd ? s->fd_ : max_fd;
184     s = s->next_;
185   }
186
187   return max_fd;
188 }
189
190 int udp_has_remote(udp_t* sock)
191 {
192   if(!sock->active_sock_ || !sock->active_sock_->remote_end_set_)
193     return 0;
194
195   udp_socket_t* s = sock->socks_;
196   while(s) {
197     if(s->remote_end_set_)
198       return 1;
199     s = s->next_;
200   }
201
202   return 0;
203 }
204
205 int udp_resolv_remote(udp_t* sock, const char* remote_addr, const char* port, resolv_addr_type_t resolv_type)
206 {
207   struct addrinfo hints, *res;
208
209   if(!sock || !remote_addr || !port)
210     return -1;
211
212   res = NULL;
213   memset (&hints, 0, sizeof (hints));
214   hints.ai_socktype = SOCK_DGRAM;
215
216   switch(resolv_type) {
217   case IPV4_ONLY: hints.ai_family = PF_INET; break;
218   case IPV6_ONLY: hints.ai_family = PF_INET6; break;
219   default: hints.ai_family = PF_UNSPEC; break;
220   }
221
222   int errcode = getaddrinfo(remote_addr, port, &hints, &res);
223   if (errcode != 0) {
224     log_printf(ERROR, "Error resolving remote address (%s:%s): %s", (remote_addr) ? remote_addr : "*", port, gai_strerror(errcode));
225     return -1;
226   }
227   if(!res) {
228     log_printf(ERROR, "getaddrinfo returned no address for %s:%s", remote_addr, port);
229     return -1;
230   }
231
232   int found = 0;
233   struct addrinfo* r = res;
234   while(r) {
235     udp_socket_t* s = sock->socks_;
236     while(s) {
237       if(s->local_end_.addr_.ss_family == r->ai_family && !(s->remote_end_set_)) {
238         sock->active_sock_ = s;
239         break;
240       }
241       s = s->next_;
242     }
243
244     if(s) {
245       memcpy(&(s->remote_end_.addr_), r->ai_addr, r->ai_addrlen);
246       s->remote_end_.len_ = r->ai_addrlen;
247       s->remote_end_set_ = 1;
248       found = 1;
249       char* remote_string = udp_endpoint_to_string(&(s->remote_end_));
250       if(remote_string) {
251         log_printf(NOTICE, "socket[%d] set remote end to: %s", s->idx_, remote_string);
252         free(remote_string);
253       }
254       break;
255     }
256
257     r = r->ai_next;
258   }
259   freeaddrinfo(res);
260
261   if(!found)
262     log_printf(WARNING, "no remote address for '%s' found that fits any of the local address families", remote_addr);
263
264   return 0;
265 }
266
267 void udp_update_remote(udp_t* sock, int fd, udp_endpoint_t* remote)
268 {
269   if(!sock)
270     return;
271
272   if(!(sock->active_sock_) || sock->active_sock_->fd_ != fd) {
273     udp_socket_t* s = sock->socks_;
274     while(s) {
275       if(s->fd_ == fd) {
276         sock->active_sock_ = s;
277         break;
278       }
279       s = s->next_;
280     }
281   }
282
283   if(!remote)
284     return;
285
286   if(sock->active_sock_) {
287     if(remote->len_ != sock->active_sock_->remote_end_.len_ ||
288        memcmp(&(remote->addr_), &(sock->active_sock_->remote_end_.addr_), remote->len_)) {
289       memcpy(&(sock->active_sock_->remote_end_.addr_), &(remote->addr_), remote->len_);
290       sock->active_sock_->remote_end_.len_ = remote->len_;
291       sock->active_sock_->remote_end_set_ = 1;
292       char* addrstring = udp_endpoint_to_string(remote);
293       log_printf(NOTICE, "socket[%d] autodetected remote host changed %s", sock->active_sock_->idx_, addrstring);
294       free(addrstring);
295     }
296   }
297 }
298
299 void udp_close(udp_t* sock)
300 {
301   if(!sock)
302     return;
303
304   while(sock->socks_) {
305     if(sock->socks_->fd_ > 0)
306       close(sock->socks_->fd_);
307
308     udp_socket_t*s = sock->socks_;
309     sock->socks_ = sock->socks_->next_;
310
311     free(s);
312   }
313   sock->socks_ = NULL;
314   sock->active_sock_ = NULL;
315 }
316
317 char* udp_endpoint_to_string(udp_endpoint_t* e)
318 {
319   if(!e)
320     return strdup("<null>");
321
322   char addrstr[INET6_ADDRSTRLEN + 1], portstr[6], *ret;
323   char addrport_sep = ':';
324
325   switch(e->addr_.ss_family)
326   {
327   case AF_INET: addrport_sep = ':'; break;
328   case AF_INET6: addrport_sep = '.'; break;
329   case AF_UNSPEC: return NULL;
330   default: return strdup("<unknown address type>");
331   }
332
333   int errcode  = getnameinfo((struct sockaddr *)&(e->addr_), e->len_, addrstr, sizeof(addrstr), portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
334   if (errcode != 0) return NULL;
335   int len = asprintf(&ret, "%s%c%s", addrstr, addrport_sep ,portstr);
336   if(len == -1) return NULL;
337   return ret;
338 }
339
340
341 int udp_read(udp_t* sock, int fd, u_int8_t* buf, u_int32_t len, udp_endpoint_t* remote_end)
342 {
343   if(!sock || !buf || !remote_end)
344     return -1;
345
346   return recvfrom(fd, buf, len, 0, (struct sockaddr *)&(remote_end->addr_), &(remote_end->len_));
347 }
348
349
350 int udp_write(udp_t* sock, u_int8_t* buf, u_int32_t len)
351 {
352   if(!sock || !buf || !sock->active_sock_ || !sock->active_sock_->remote_end_set_)
353     return 0;
354
355   return sendto(sock->active_sock_->fd_, buf, len, 0, (struct sockaddr *)&(sock->active_sock_->remote_end_.addr_), sock->active_sock_->remote_end_.len_);
356 }