* tunneling and relaying of packets of any protocol.
*
*
- * Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ * Copyright (C) 2007-2010 Christian Pointner <equinox@anytun.org>
*
* This file is part of uAnytun.
*
* uAnytun is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
*
* uAnytun is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
#ifndef NO_CRYPT
#include "key_derivation.h"
#include "auth_algo.h"
-
-#ifndef USE_SSL_CRYPTO
-#include <gcrypt.h>
-#endif
+#else
+typedef u_int8_t auth_algo_t;
#endif
-
+#include "init_crypt.h"
#include "daemon.h"
#include "sysexec.h"
-#ifndef NO_CRYPT
-#ifndef USE_SSL_CRYPTO
-
-#define MIN_GCRYPT_VERSION "1.2.0"
-
-int init_libgcrypt()
-{
- if(!gcry_check_version(MIN_GCRYPT_VERSION)) {
- log_printf(NOTICE, "invalid Version of libgcrypt, should be >= %s", MIN_GCRYPT_VERSION);
- return -1;
- }
-
- gcry_error_t err = gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
- if(err) {
- log_printf(ERROR, "failed to disable secure memory: %s", gcry_strerror(err));
- return -1;
- }
-
- err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED);
- if(err) {
- log_printf(ERROR, "failed to finish libgcrypt initialization: %s", gcry_strerror(err));
- return -1;
- }
-
- log_printf(NOTICE, "libgcrypt init finished");
- return 0;
-}
-#endif
-#endif
-
-#ifdef NO_CRYPT
-typedef u_int8_t auth_algo_t;
-#endif
int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
{
return 0;
}
-int process_tun_data(tun_device_t* dev, udp_socket_t* sock, options_t* opt, plain_packet_t* plain_packet, encrypted_packet_t* encrypted_packet,
+int process_tun_data(tun_device_t* dev, udp_t* sock, options_t* opt, plain_packet_t* plain_packet, encrypted_packet_t* encrypted_packet,
cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_nr_t seq_nr)
{
plain_packet_set_payload_length(plain_packet, -1);
#ifndef NO_CRYPT
auth_algo_generate(aa, kd, kd_outbound, encrypted_packet);
#endif
-
+
len = udp_write(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet));
if(len == -1)
log_printf(ERROR, "error on sending udp packet: %s", strerror(errno));
return 0;
}
-int process_sock_data(tun_device_t* dev, udp_socket_t* sock, options_t* opt, plain_packet_t* plain_packet, encrypted_packet_t* encrypted_packet,
+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,
cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
{
plain_packet_set_payload_length(plain_packet, -1);
udp_endpoint_t remote;
memset(&remote, 0, sizeof(udp_endpoint_t));
- int len = udp_read(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet), &remote);
+ int len = udp_read(sock, fd, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet), &remote);
if(len == -1) {
log_printf(ERROR, "error on receiving udp packet: %s", strerror(errno));
return 0;
}
else if(len < encrypted_packet_get_minimum_length(encrypted_packet)) {
- log_printf(WARNING, "received packet is to short");
+ log_printf(WARNING, "received packet is too short");
return 0;
}
encrypted_packet_set_length(encrypted_packet, len);
return -2;
}
+ udp_set_active_sock(sock, fd);
if(memcmp(&remote, &(sock->remote_end_), sizeof(remote))) {
memcpy(&(sock->remote_end_), &remote, sizeof(remote));
sock->remote_end_set_ = 1;
}
-int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt)
+int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt)
{
log_printf(INFO, "entering main loop");
encrypted_packet_t encrypted_packet;
encrypted_packet_init(&encrypted_packet, opt->auth_tag_length_);
seq_nr_t seq_nr = 0;
- fd_set readfds;
+ fd_set readfds, readyfds;
cipher_t c;
auth_algo_t aa;
if(ret)
return ret;
- signal_init();
+ FD_ZERO(&readfds);
+ FD_SET(dev->fd_, &readfds);
+ int nfds = udp_init_fd_set(sock, &readfds);
+ nfds = dev->fd_ > nfds ? dev->fd_ : nfds;
+
int return_value = 0;
- while(!return_value) {
- FD_ZERO(&readfds);
- FD_SET(dev->fd_, &readfds);
- FD_SET(sock->fd_, &readfds);
- int nfds = dev->fd_ > sock->fd_ ? dev->fd_+1 : sock->fd_+1;
+ int sig_fd = signal_init();
+ if(sig_fd < 0)
+ return_value -1;
+
+ FD_SET(sig_fd, &readfds);
+ nfds = (nfds < sig_fd) ? sig_fd : nfds;
- int ret = select(nfds, &readfds, NULL, NULL, NULL);
+ while(!return_value) {
+ memcpy(&readyfds, &readfds, sizeof(readyfds));
+ int ret = select(nfds + 1, &readyfds, NULL, NULL, NULL);
if(ret == -1 && errno != EINTR) {
log_printf(ERROR, "select returned with error: %s", strerror(errno));
return_value = -1;
break;
}
- if(!ret)
+ if(!ret || ret == -1)
continue;
- if(signal_exit) {
- return_value = 1;
- break;
+ if(FD_ISSET(sig_fd, &readyfds)) {
+ if(signal_handle()) {
+ return_value = 1;
+ break;
+ }
}
- if(FD_ISSET(dev->fd_, &readfds)) {
+ if(FD_ISSET(dev->fd_, &readyfds)) {
return_value = process_tun_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, seq_nr);
seq_nr++;
if(return_value)
break;
}
- if(FD_ISSET(sock->fd_, &readfds)) {
- return_value = process_sock_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, &seq_win);
- if(return_value)
- break;
+ udp_socket_t* s = sock->socks_;
+ while(s) {
+ if(FD_ISSET(s->fd_, &readyfds)) {
+ return_value = process_sock_data(dev, s->fd_, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, &seq_win);
+ if(return_value)
+ break;
+ }
+ s = s->next_;
}
}
key_derivation_close(&kd);
#endif
seq_win_clear(&seq_win);
+ signal_stop();
return return_value;
}
if(ret == -4) {
fprintf(stderr, "syntax error: unknown role name\n\n");
}
+ if(ret == -5) {
+ options_print_version();
+ }
- if(ret != -2)
+ if(ret != -2 && ret != -5)
options_print_usage();
+ if(ret == -1 || ret == -5)
+ ret = 0;
+
options_clear(&opt);
log_close();
exit(ret);
}
string_list_element_t* tmp = opt.log_targets_.first_;
- if(!tmp) {
- log_add_target("syslog:3,uanytun,daemon");
- }
- else {
- while(tmp) {
- ret = log_add_target(tmp->string_);
- if(ret) {
- switch(ret) {
- case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break;
- case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break;
- case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break;
- default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break;
- }
-
- options_clear(&opt);
- log_close();
- exit(ret);
+ while(tmp) {
+ ret = log_add_target(tmp->string_);
+ if(ret) {
+ switch(ret) {
+ case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break;
+ case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break;
+ case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break;
+ default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break;
}
- tmp = tmp->next_;
+
+ options_clear(&opt);
+ log_close();
+ exit(ret);
}
+ tmp = tmp->next_;
}
log_printf(NOTICE, "just started...");
exit(-1);
}
-#ifndef NO_CRYPT
-#ifndef USE_SSL_CRYPTO
- ret = init_libgcrypt();
+ ret = init_crypt();
if(ret) {
- log_printf(ERROR, "error on libgcrpyt initialization, exitting");
+ log_printf(ERROR, "error on crpyto initialization, exitting");
options_clear(&opt);
log_close();
exit(ret);
}
-#endif
-#endif
tun_device_t dev;
ret = tun_init(&dev, opt.dev_name_, opt.dev_type_, opt.ifconfig_param_.net_addr_, opt.ifconfig_param_.prefix_length_);
if(opt.post_up_script_) {
log_printf(NOTICE, "executing post-up script '%s'", opt.post_up_script_);
- int ret = exec_script(opt.post_up_script_, dev.actual_name_);
+ char* const argv[] = { opt.post_up_script_, dev.actual_name_, NULL };
+ char* const evp[] = { NULL };
+ int ret = uanytun_exec(opt.post_up_script_, argv, evp);
}
- udp_socket_t sock;
+ udp_t sock;
ret = udp_init(&sock, opt.local_addr_, opt.local_port_, opt.resolv_addr_type_);
if(ret) {
log_printf(ERROR, "error on udp_init, exitting");
log_close();
exit(ret);
}
- char* local_string = udp_get_local_end_string(&sock);
- if(local_string) {
- log_printf(NOTICE, "listening on: %s", local_string);
- free(local_string);
- }
-
if(opt.remote_addr_) {
if(!udp_set_remote(&sock, opt.remote_addr_, opt.remote_port_, opt.resolv_addr_type_)) {