diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/options.c | 8 | ||||
-rw-r--r-- | src/options.h | 1 | ||||
-rw-r--r-- | src/uanytun.c | 11 | ||||
-rw-r--r-- | src/udp.c | 111 | ||||
-rw-r--r-- | src/udp.h | 3 |
5 files changed, 117 insertions, 17 deletions
diff --git a/src/options.c b/src/options.c index c3038bb..015a9a5 100644 --- a/src/options.c +++ b/src/options.c @@ -260,6 +260,7 @@ int options_parse(options_t* opt, int argc, char* argv[]) PARSE_INT_PARAM("-s","--sender-id", opt->sender_id_) PARSE_STRING_LIST("-L","--log", opt->log_targets_) PARSE_BOOL_PARAM("-U", "--debug", opt->debug_) + PARSE_BOOL_PARAM("-Y", "--rail-mode", opt->rail_mode_) PARSE_STRING_PARAM("-r","--remote-host", opt->remote_addr_) PARSE_STRING_PARAM("-o","--remote-port", opt->remote_port_) PARSE_BOOL_PARAM("-4","--ipv4-only", ipv4_only) @@ -361,6 +362,7 @@ void options_default(options_t* opt) opt->local_addr_ = NULL; opt->local_port_ = strdup("4444"); opt->sender_id_ = 0; + opt->rail_mode_ = 0; opt->remote_addr_ = NULL; opt->remote_port_ = strdup("4444"); opt->resolv_addr_type_ = ANY; @@ -447,14 +449,15 @@ void options_print_usage() printf(" [-C|--chroot] <path> chroot to this directory\n"); printf(" [-P|--write-pid] <path> write pid to this file\n"); printf(" [-i|--interface] <ip-address> local ip address to bind to\n"); - printf(" [-p|--port] <port> local port to bind to\n"); + printf(" [-p|--port] <port>[:<port>] local port to bind to (use port:port for range - RAIL)\n"); printf(" [-s|--sender-id ] <sender id> the sender id to use\n"); printf(" [-L|--log] <target>:<level>[,<param1>[,<param2>..]]\n"); printf(" add a log target, can be invoked several times\n"); printf(" [-U|--debug] don't daemonize and log to stdout with maximum log level\n"); + printf(" [-Y|--rail-mode] enable RAIL mode\n"); printf(" [-r|--remote-host] <hostname|ip> remote host\n"); - printf(" [-o|--remote-port] <port> remote port\n"); + printf(" [-o|--remote-port] <port>[:<port>] remote port (use port:port for range - RAIL)\n"); printf(" [-4|--ipv4-only] always resolv IPv4 addresses\n"); printf(" [-6|--ipv6-only] always resolv IPv6 addresses\n"); printf(" [-d|--dev] <name> device name\n"); @@ -507,6 +510,7 @@ void options_print(options_t* opt) printf("local_addr: '%s'\n", opt->local_addr_); printf("local_port: '%s'\n", opt->local_port_); printf("sender_id: %d\n", opt->sender_id_); + printf("rail-mode: %s\n", !opt->rail_mode_ ? "false" : "true"); printf("remote_addr: '%s'\n", opt->remote_addr_); printf("remote_port: '%s'\n", opt->remote_port_); printf("resolv_addr_type: "); diff --git a/src/options.h b/src/options.h index 8f3593f..fa4d554 100644 --- a/src/options.h +++ b/src/options.h @@ -75,6 +75,7 @@ struct options_struct { char* local_addr_; char* local_port_; sender_id_t sender_id_; + int rail_mode_; char* remote_addr_; char* remote_port_; resolv_addr_type_t resolv_addr_type_; diff --git a/src/uanytun.c b/src/uanytun.c index da90eda..c5d6291 100644 --- a/src/uanytun.c +++ b/src/uanytun.c @@ -188,16 +188,21 @@ int process_sock_data(tun_device_t* dev, int fd, udp_t* sock, options_t* opt, pl } #endif + if(sock->rail_mode_) + udp_update_remote(sock, fd, &remote); + int result = seq_win_check_and_add(seq_win, encrypted_packet_get_sender_id(encrypted_packet), encrypted_packet_get_seq_nr(encrypted_packet)); if(result > 0) { - log_printf(WARNING, "detected replay attack, discarding packet"); + if(!(sock->rail_mode_)) + log_printf(WARNING, "detected replay attack, discarding packet"); return 0; } else if(result < 0) { log_printf(ERROR, "memory error at sequence window"); return -2; } - udp_update_remote(sock, fd, &remote); + if(!sock->rail_mode_) + udp_update_remote(sock, fd, &remote); if(encrypted_packet_get_payload_length(encrypted_packet) <= plain_packet_get_header_length()) { log_printf(WARNING, "ignoring packet with zero length payload"); @@ -390,7 +395,7 @@ int main(int argc, char* argv[]) udp_t sock; - ret = udp_init(&sock, opt.local_addr_, opt.local_port_, opt.resolv_addr_type_); + ret = udp_init(&sock, opt.local_addr_, opt.local_port_, opt.resolv_addr_type_, opt.rail_mode_); if(ret) { log_printf(ERROR, "error on udp_init, exitting"); tun_close(&dev); @@ -161,18 +161,53 @@ static int udp_resolv_local(udp_t* sock, const char* local_addr, const char* por return 0; } -int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type) +static int udp_split_port_range(const char* port, const char* colon, u_int32_t* low, u_int32_t* high) +{ + *low = atoi(port); + *high = atoi(colon+1); + if(*low < 1 || *low > 65535 || *high < 1 || *high > 65535 || *high < *low) { + log_printf(ERROR, "illegal port range"); + return -1; + } + return 0; +} + +int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type, int rail_mode) { if(!sock || !port) return -1; sock->socks_ = NULL; sock->active_sock_ = NULL; + sock->rail_mode_ = rail_mode; unsigned int idx = 0; - int ret = udp_resolv_local(sock, local_addr, port, resolv_type, &idx); - if(ret) - return ret; + const char* colon = strchr(port, ':'); + if(!colon) { + int ret = udp_resolv_local(sock, local_addr, port, resolv_type, &idx); + if(ret) + return ret; + } else { + if(!rail_mode) + log_printf(WARNING, "A port range has been defined - enabling RAIL mode"); + sock->rail_mode_ = 1; + + u_int32_t port_num, port_end; + if(udp_split_port_range(port, colon, &port_num, &port_end)) + return -1; + do { + char port_str[10]; + snprintf(port_str, sizeof(port_str), "%d", port_num); + int ret = udp_resolv_local(sock, local_addr, port_str, resolv_type, &idx); + if(ret) + return ret; + + port_num++; + } while(port_num <= port_end); + } + + if(sock->rail_mode_) + log_printf(NOTICE, "RAIL mode enabled"); return 0; } @@ -193,7 +228,7 @@ int udp_fill_fd_set(udp_t* sock, fd_set* set) int udp_has_remote(udp_t* sock) { - if(!sock->active_sock_ || !sock->active_sock_->remote_end_set_) + if(!sock->rail_mode_ && (!sock->active_sock_ || !sock->active_sock_->remote_end_set_)) return 0; udp_socket_t* s = sock->socks_; @@ -206,13 +241,10 @@ int udp_has_remote(udp_t* sock) return 0; } -int udp_resolv_remote(udp_t* sock, const char* remote_addr, const char* port, resolv_addr_type_t resolv_type) +static int udp_resolv_remote__(udp_t* sock, const char* remote_addr, const char* port, resolv_addr_type_t resolv_type) { struct addrinfo hints, *res; - if(!sock || !remote_addr || !port) - return -1; - res = NULL; memset (&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_DGRAM; @@ -268,6 +300,36 @@ int udp_resolv_remote(udp_t* sock, const char* remote_addr, const char* port, re return 0; } +int udp_resolv_remote(udp_t* sock, const char* remote_addr, const char* port, resolv_addr_type_t resolv_type) +{ + if(!sock || !remote_addr || !port) + return -1; + + const char* colon = strchr(port, ':'); + if(!colon) { + return udp_resolv_remote__(sock, remote_addr, port, resolv_type); + } else { + if(!sock->rail_mode_) + log_printf(WARNING, "A port range has been defined - enabling RAIL mode"); + sock->rail_mode_ = 1; + + u_int32_t port_num, port_end; + if(udp_split_port_range(port, colon, &port_num, &port_end)) + return -1; + do { + char port_str[10]; + snprintf(port_str, sizeof(port_str), "%d", port_num); + int ret = udp_resolv_remote__(sock, remote_addr, port_str, resolv_type); + if(ret) + return ret; + + port_num++; + } while(port_num <= port_end); + } + + return 0; +} + void udp_update_remote(udp_t* sock, int fd, udp_endpoint_t* remote) { if(!sock) @@ -351,10 +413,37 @@ int udp_read(udp_t* sock, int fd, u_int8_t* buf, u_int32_t len, udp_endpoint_t* } -int udp_write(udp_t* sock, u_int8_t* buf, u_int32_t len) +static int udp_write_active_sock(udp_t* sock, u_int8_t* buf, u_int32_t len) { - if(!sock || !buf || !sock->active_sock_ || !sock->active_sock_->remote_end_set_) + if(!sock->active_sock_ || !sock->active_sock_->remote_end_set_) return 0; return sendto(sock->active_sock_->fd_, buf, len, 0, (struct sockaddr *)&(sock->active_sock_->remote_end_.addr_), sock->active_sock_->remote_end_.len_); } + +static int udp_write_rail(udp_t* sock, u_int8_t* buf, u_int32_t len) +{ + int i=0; + + udp_socket_t* s = sock->socks_; + while(s) { + if(s->remote_end_set_) { + sendto(s->fd_, buf, len, 0, (struct sockaddr *)&(s->remote_end_.addr_), s->remote_end_.len_); + i++; + } + s = s->next_; + } + + return len; +} + +int udp_write(udp_t* sock, u_int8_t* buf, u_int32_t len) +{ + if(!sock || !buf) + return 0; + + if(sock->rail_mode_) + return udp_write_rail(sock, buf, len); + + return udp_write_active_sock(sock, buf, len); +} @@ -72,10 +72,11 @@ typedef struct udp_socket_struct udp_socket_t; struct udp_struct { udp_socket_t* socks_; udp_socket_t* active_sock_; + int rail_mode_; }; typedef struct udp_struct udp_t; -int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type); +int udp_init(udp_t* sock, const char* local_addr, const char* port, resolv_addr_type_t resolv_type, int rail_mode); int udp_fill_fd_set(udp_t* sock, fd_set* set); int udp_has_remote(udp_t* sock); int udp_resolv_remote(udp_t* sock, const char* remote_addr, const char* port, resolv_addr_type_t resolv_type); |