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"
44 #include "sig_handler.h"
50 #include "plain_packet.h"
51 #include "encrypted_packet.h"
53 #include "seq_window.h"
57 #include "key_derivation.h"
58 #include "auth_algo.h"
60 typedef u_int8_t auth_algo_t;
62 #include "init_crypt.h"
68 int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
70 int ret = cipher_init(c, opt->cipher_);
72 log_printf(ERROR, "could not initialize cipher of type %s", opt->cipher_);
77 ret = auth_algo_init(aa, opt->auth_algo_);
79 log_printf(ERROR, "could not initialize auth algo of type %s", opt->auth_algo_);
84 ret = key_derivation_init(kd, opt->kd_prf_, opt->role_, opt->passphrase_, opt->key_.buf_, opt->key_.length_, opt->salt_.buf_, opt->salt_.length_);
86 log_printf(ERROR, "could not initialize key derivation of type %s", opt->kd_prf_);
93 ret = seq_win_init(seq_win, opt->seq_window_size_);
95 printf("could not initialize sequence window");
99 key_derivation_close(kd);
106 int process_tun_data(tun_device_t* dev, udp_t* sock, options_t* opt, plain_packet_t* plain_packet, encrypted_packet_t* encrypted_packet,
107 cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_nr_t seq_nr)
109 plain_packet_set_payload_length(plain_packet, -1);
110 encrypted_packet_set_length(encrypted_packet, -1);
112 int len = tun_read(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
114 log_printf(ERROR, "error on reading from device: %s", strerror(errno));
118 plain_packet_set_payload_length(plain_packet, len);
120 if(dev->type_ == TYPE_TUN)
121 plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TUN);
122 else if(dev->type_ == TYPE_TAP)
123 plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TAP);
125 plain_packet_set_type(plain_packet, PAYLOAD_TYPE_UNKNOWN);
127 if(!sock->remote_end_set_)
130 cipher_encrypt(c, kd, kd_outbound, plain_packet, encrypted_packet, seq_nr, opt->sender_id_, opt->mux_);
133 auth_algo_generate(aa, kd, kd_outbound, encrypted_packet);
136 len = udp_write(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet));
138 log_printf(ERROR, "error on sending udp packet: %s", strerror(errno));
143 int process_sock_data(tun_device_t* dev, int fd, udp_t* sock, options_t* opt, plain_packet_t* plain_packet, encrypted_packet_t* encrypted_packet,
144 cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
146 plain_packet_set_payload_length(plain_packet, -1);
147 encrypted_packet_set_length(encrypted_packet, -1);
149 udp_endpoint_t remote;
150 memset(&remote, 0, sizeof(udp_endpoint_t));
151 int len = udp_read(sock, fd, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet), &remote);
153 log_printf(ERROR, "error on receiving udp packet: %s", strerror(errno));
156 else if(len < encrypted_packet_get_minimum_length(encrypted_packet)) {
157 log_printf(WARNING, "received packet is too short");
160 encrypted_packet_set_length(encrypted_packet, len);
163 if(!auth_algo_check_tag(aa, kd, kd_inbound, encrypted_packet)) {
164 log_printf(WARNING, "wrong authentication tag, discarding packet");
169 if(encrypted_packet_get_mux(encrypted_packet) != opt->mux_) {
170 log_printf(WARNING, "wrong mux value, discarding packet");
174 int result = seq_win_check_and_add(seq_win, encrypted_packet_get_sender_id(encrypted_packet), encrypted_packet_get_seq_nr(encrypted_packet));
176 log_printf(WARNING, "detected replay attack, discarding packet");
179 else if(result < 0) {
180 log_printf(ERROR, "memory error at sequence window");
184 udp_set_active_sock(sock, fd);
185 if(memcmp(&remote, &(sock->remote_end_), sizeof(remote))) {
186 memcpy(&(sock->remote_end_), &remote, sizeof(remote));
187 sock->remote_end_set_ = 1;
188 char* addrstring = udp_endpoint_to_string(remote);
189 log_printf(NOTICE, "autodetected remote host changed %s", addrstring);
193 if(encrypted_packet_get_payload_length(encrypted_packet) <= plain_packet_get_header_length()) {
194 log_printf(WARNING, "ignoring packet with zero length payload");
198 int ret = cipher_decrypt(c, kd, kd_inbound, encrypted_packet, plain_packet);
202 len = tun_write(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
204 log_printf(ERROR, "error on writing to device: %s", strerror(errno));
210 int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt)
212 log_printf(INFO, "entering main loop");
214 plain_packet_t plain_packet;
215 plain_packet_init(&plain_packet);
216 encrypted_packet_t encrypted_packet;
217 encrypted_packet_init(&encrypted_packet, opt->auth_tag_length_);
219 fd_set readfds, readyfds;
226 int ret = init_main_loop(opt, &c, &aa, &kd, &seq_win);
231 FD_SET(dev->fd_, &readfds);
232 int nfds = udp_init_fd_set(sock, &readfds);
233 nfds = dev->fd_ > nfds ? dev->fd_ : nfds;
235 int return_value = 0;
236 int sig_fd = signal_init();
240 FD_SET(sig_fd, &readfds);
241 nfds = (nfds < sig_fd) ? sig_fd : nfds;
243 while(!return_value) {
244 memcpy(&readyfds, &readfds, sizeof(readyfds));
245 int ret = select(nfds + 1, &readyfds, NULL, NULL, NULL);
246 if(ret == -1 && errno != EINTR) {
247 log_printf(ERROR, "select returned with error: %s", strerror(errno));
251 if(!ret || ret == -1)
254 if(FD_ISSET(sig_fd, &readyfds)) {
255 if(signal_handle()) {
261 if(FD_ISSET(dev->fd_, &readyfds)) {
262 return_value = process_tun_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, seq_nr);
268 udp_socket_t* s = sock->socks_;
270 if(FD_ISSET(s->fd_, &readyfds)) {
271 return_value = process_sock_data(dev, s->fd_, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, &seq_win);
281 auth_algo_close(&aa);
282 key_derivation_close(&kd);
284 seq_win_clear(&seq_win);
290 int main(int argc, char* argv[])
295 int ret = options_parse(&opt, argc, argv);
298 fprintf(stderr, "syntax error near: %s\n\n", argv[ret]);
301 fprintf(stderr, "memory error on options_parse, exitting\n");
304 fprintf(stderr, "syntax error: -4 and -6 are mutual exclusive\n\n");
307 fprintf(stderr, "syntax error: unknown role name\n\n");
310 options_print_version();
313 if(ret != -2 && ret != -5)
314 options_print_usage();
316 if(ret == -1 || ret == -5)
323 string_list_element_t* tmp = opt.log_targets_.first_;
325 ret = log_add_target(tmp->string_);
328 case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break;
329 case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break;
330 case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break;
331 default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break;
341 log_printf(NOTICE, "just started...");
342 options_parse_post(&opt);
346 if(priv_init(&priv, opt.username_, opt.groupname_)) {
354 log_printf(ERROR, "error on crpyto initialization, exitting");
361 ret = tun_init(&dev, opt.dev_name_, opt.dev_type_, opt.ifconfig_param_.net_addr_, opt.ifconfig_param_.prefix_length_);
363 log_printf(ERROR, "error on tun_init, exitting");
368 log_printf(NOTICE, "dev of type '%s' opened, actual name is '%s'", tun_get_type_string(&dev), dev.actual_name_);
370 if(opt.post_up_script_) {
371 log_printf(NOTICE, "executing post-up script '%s'", opt.post_up_script_);
372 char* const argv[] = { opt.post_up_script_, dev.actual_name_, NULL };
373 char* const evp[] = { NULL };
374 int ret = uanytun_exec(opt.post_up_script_, argv, evp);
379 ret = udp_init(&sock, opt.local_addr_, opt.local_port_, opt.resolv_addr_type_);
381 log_printf(ERROR, "error on udp_init, exitting");
388 if(opt.remote_addr_) {
389 if(!udp_set_remote(&sock, opt.remote_addr_, opt.remote_port_, opt.resolv_addr_type_)) {
390 char* remote_string = udp_get_remote_end_string(&sock);
392 log_printf(NOTICE, "set remote end to: %s", remote_string);
399 FILE* pid_file = NULL;
401 pid_file = fopen(opt.pid_file_, "w");
403 log_printf(WARNING, "unable to open pid file: %s", strerror(errno));
408 if(do_chroot(opt.chroot_dir_)) {
416 if(priv_drop(&priv)) {
425 pid_t oldpid = getpid();
427 log_printf(INFO, "running in background now (old pid: %d)", oldpid);
431 pid_t pid = getpid();
432 fprintf(pid_file, "%d", pid);
436 ret = main_loop(&dev, &sock, &opt);
443 log_printf(NOTICE, "normal shutdown");
445 log_printf(NOTICE, "shutdown after error");
447 log_printf(NOTICE, "shutdown after signal");