The following commit has been merged in the master branch: commit c0f6163617f625372d0310d594853b30281c8234 Author: Marek Lindner lindner_marek@yahoo.de Date: Mon Sep 11 17:07:55 2006 +0200
choose_gw activated and ipip tunnel fcts added
diff --git a/batman.c b/batman.c index 22124ec..b64539a 100755 --- a/batman.c +++ b/batman.c @@ -69,6 +69,13 @@ int routing_class = 0; int orginator_interval = 1000; /* orginator message interval in miliseconds */
struct gw_node *curr_gateway = NULL; +struct batman_if *curr_gateway_batman_if = NULL; +unsigned int curr_gateway_ip = 0; +char *curr_gateway_ipip_if = NULL; +pthread_t curr_gateway_thread_id = 0; +int curr_gateway_tcp_sock = 0; +int curr_gateway_ipip_fd = 0; + unsigned int pref_gateway = 0; int found_ifs = 0;
@@ -174,9 +181,10 @@ static void choose_gw()
if ( curr_gateway != NULL ) {
- if (debug_level >= 0) output( "Removing default route - no gateway in range\n" ); + if (debug_level >= 1) + output( "Removing default route - no gateway in range\n" );
- /* TODO remove default route */ + del_default_route();
curr_gateway = NULL;
@@ -215,7 +223,7 @@ static void choose_gw()
tmp_curr_gw = gw_node;
- if (debug_level >= 0) { + if (debug_level >= 1) { addr_to_string( tmp_curr_gw->orig_node->orig, orig_str, ADDR_STR_LEN ); output( "Preferred gateway found: %s (%i,%i,%i)\n", orig_str, gw_node->orig_node->gwflags, gw_node->orig_node->packet_count, ( gw_node->orig_node->packet_count * gw_node->orig_node->gwflags ) ); } @@ -231,19 +239,23 @@ static void choose_gw()
if ( curr_gateway != NULL ) {
- if (debug_level >= 0) output( "Removing default route - better gateway found\n" ); + if (debug_level >= 1) + output( "Removing default route - better gateway found\n" );
- /* TODO remove default route */ + del_default_route();
}
- if (debug_level >= 0) { + if (debug_level >= 1) { addr_to_string( tmp_curr_gw->orig_node->orig, orig_str, ADDR_STR_LEN ); output( "Adding default route to %s (%i,%i,%i)\n", orig_str, max_gw_class, max_packets, max_gw_factor ); }
- /* TODO add default route */ curr_gateway = tmp_curr_gw; + curr_gateway_ip = curr_gateway->orig_node->orig; + curr_gateway_batman_if = curr_gateway->orig_node->batman_if; + + add_default_route();
}
@@ -334,24 +346,38 @@ static void update_routes( struct orig_node *orig_node ) static void update_gw_list( struct orig_node *orig_node, unsigned char new_gwflags ) {
- struct list_head *pos; + struct list_head *gw_pos, *gw_pos_tmp; struct gw_node *gw_node; static char orig_str[ADDR_STR_LEN];
- list_for_each(pos, &gw_list) { + list_for_each_safe(gw_pos, gw_pos_tmp, &gw_list) {
- gw_node = list_entry(pos, struct gw_node, list); + gw_node = list_entry(gw_pos, struct gw_node, list);
if ( gw_node->orig_node == orig_node ) {
- if (debug_level >= 0) { + if (debug_level >= 1) {
addr_to_string( gw_node->orig_node->orig, orig_str, ADDR_STR_LEN ); output( "Gateway class of originator %s changed from %i to %i\n", orig_str, gw_node->orig_node->gwflags, new_gwflags );
}
- gw_node->orig_node->gwflags = new_gwflags; + if ( new_gwflags == 0 ) { + + list_del(gw_pos); + free_memory(gw_pos); + + if (debug_level >= 1) + output( "Gateway %s removed from gateway list\n", orig_str ); + + } else { + + gw_node->orig_node->gwflags = new_gwflags; + + } + + choose_gw(); return;
} @@ -368,6 +394,7 @@ static void update_gw_list( struct orig_node *orig_node, unsigned char new_gwfla INIT_LIST_HEAD(&gw_node->list);
gw_node->orig_node = orig_node; + choose_gw();
list_add_tail(&gw_node->list, &gw_list);
@@ -692,11 +719,12 @@ void schedule_own_packet() {
void purge() { - struct list_head *orig_pos, *neigh_pos, *pack_pos, *gw_pos, *orig_temp, *neigh_temp, *pack_temp; + struct list_head *orig_pos, *neigh_pos, *pack_pos, *gw_pos, *gw_pos_tmp, *orig_temp, *neigh_temp, *pack_temp; struct orig_node *orig_node; struct neigh_node *neigh_node; struct pack_node *pack_node; struct gw_node *gw_node; + int gw_purged = 0; static char orig_str[ADDR_STR_LEN], neigh_str[ADDR_STR_LEN];
if (debug_level >= 2) @@ -752,18 +780,21 @@ void purge() output("Removing orphaned originator %s\n", orig_str); }
- list_for_each(gw_pos, &gw_list) { + list_for_each_safe(gw_pos, gw_pos_tmp, &gw_list) {
gw_node = list_entry(gw_pos, struct gw_node, list);
if ( gw_node->orig_node == orig_node ) {
addr_to_string( gw_node->orig_node->orig, orig_str, ADDR_STR_LEN ); - if (debug_level >= 0) output( "Removing gateway %s from gateway list\n", orig_str ); + if (debug_level >= 1) + output( "Removing gateway %s from gateway list\n", orig_str );
list_del(gw_pos); free_memory(gw_pos);
+ gw_purged = 1; + break;
} @@ -784,8 +815,9 @@ void purge() } }
- /* is not needed - calculate new route with next packet - update_routes(); */ + if ( gw_purged ) + choose_gw(); + }
void send_vis_packet() diff --git a/batman.h b/batman.h index 4373e48..5122672 100755 --- a/batman.h +++ b/batman.h @@ -49,6 +49,14 @@ extern int gateway_class; extern int routing_class; extern unsigned int pref_gateway;
+extern struct gw_node *curr_gateway; +extern struct batman_if *curr_gateway_batman_if; +extern unsigned int curr_gateway_ip; +extern char *curr_gateway_ipip_if; +pthread_t curr_gateway_thread_id; +extern int curr_gateway_tcp_sock; +extern int curr_gateway_ipip_fd; + extern int found_ifs;
extern struct list_head if_list; @@ -130,6 +138,8 @@ struct gw_client struct batman_if *batman_if; int sock; unsigned int last_keep_alive; + char *tun_dev; + int tun_fd; struct sockaddr_in addr; };
@@ -147,5 +157,7 @@ static void debug(); int batman(); void usage(void); void verbose_usage(void); +void del_default_route(); +int add_default_route();
#endif diff --git a/posix.c b/posix.c index 15a77dd..07a0e8b 100644 --- a/posix.c +++ b/posix.c @@ -32,6 +32,12 @@ #include <unistd.h> #include <signal.h> #include <stdlib.h> +#include <asm/types.h> +#include <netinet/ip.h> +#include <linux/if_tun.h> +#include <linux/if_tunnel.h> +#include <sys/stat.h> +#include <fcntl.h>
#include "os.h" #include "batman.h" @@ -82,25 +88,249 @@ void output(char *format, ...) va_end(args); }
-void close_all_sockets() -{ + + +void *keep_tun_alive( void *unused ) { + + struct timeval tv; + int res; + fd_set wait_sockets, tmp_wait_sockets; + + + FD_ZERO(&wait_sockets); + FD_SET(curr_gateway_tcp_sock, &wait_sockets); + + while ( ( !is_aborted() ) && ( curr_gateway != NULL ) ) { + + tv.tv_sec = 0; + tv.tv_usec = 250; + + tmp_wait_sockets = wait_sockets; + + res = select(curr_gateway_tcp_sock + 1, &wait_sockets, NULL, NULL, &tv); + + if (res > 0) { + + /* TODO: if server sends a message (e.g. rejects) */ + + } else if ( ( res < 0 ) && (errno != EINTR) ) { + + fprintf(stderr, "Cannot select: %s\n", strerror(errno)); + del_default_route(); + return NULL; + + } + + + + } + + return NULL; + +} + + + +int del_ipip_tun( int fd ) { + + if ( ioctl( fd, TUNSETPERSIST, 0 ) < 0 ) { + + perror("TUNSETPERSIST"); + return -1; + + } + + close( fd ); + + return 1; + +} + + + +int add_ipip_tun( struct batman_if *batman_if, unsigned int dest_addr, char *tun_dev, int *fd ) { + + int tmp_fd; + struct ifreq ifr; + struct sockaddr_in addr; + + /* set up tunnel device */ + memset( &ifr, 0, sizeof(ifr) ); + ifr.ifr_flags = IFF_TUN; + + if ( ( *fd = open( "/dev/net/tun", O_RDWR ) ) < 0 ) { + + perror("/dev/net/tun"); + return -1; + + } + + if ( ( ioctl( *fd, TUNSETIFF, (void *) &ifr ) ) < 0 ) { + + perror("TUNSETIFF"); + close(*fd); + return -1; + + } + + if ( ioctl( *fd, TUNSETPERSIST, 1 ) < 0 ) { + + perror("TUNSETPERSIST"); + close(*fd); + return -1; + + } + + + tmp_fd = socket(AF_INET, SOCK_DGRAM, 0); + + if ( tmp_fd < 0 ) { + fprintf(stderr, "Cannot create send socket: %s", strerror(errno)); + del_ipip_tun( *fd ); + return -1; + } + + + /* set ip of this end point of tunnel */ + memset( &addr, 0, sizeof(addr) ); + addr.sin_addr.s_addr = batman_if->addr.sin_addr.s_addr; + addr.sin_family = AF_INET; + memcpy( &ifr.ifr_addr, &addr, sizeof(struct sockaddr) ); + + + if ( ioctl( tmp_fd, SIOCSIFADDR, &ifr) < 0 ) { + + perror("SIOCSIFADDR"); + del_ipip_tun( *fd ); + close( tmp_fd ); + return -1; + + } + + /* set ip of this remote point of tunnel */ + memset( &addr, 0, sizeof(addr) ); + addr.sin_addr.s_addr = dest_addr; + addr.sin_family = AF_INET; + memcpy( &ifr.ifr_addr, &addr, sizeof(struct sockaddr) ); + + if ( ioctl( tmp_fd, SIOCSIFDSTADDR, &ifr) < 0 ) { + + perror("SIOCSIFDSTADDR"); + del_ipip_tun( *fd ); + close( tmp_fd ); + return -1; + + } + + close( tmp_fd ); + strncpy( tun_dev, ifr.ifr_name, IFNAMSIZ ); + + return 1; + +} + + + +void del_default_route() { + + curr_gateway = NULL; + + add_del_route( 0, curr_gateway_ip, 1, curr_gateway_ipip_if, curr_gateway_ipip_fd ); + + close( curr_gateway_tcp_sock ); + del_ipip_tun( curr_gateway_ipip_fd ); + + curr_gateway_tcp_sock = 0; + curr_gateway_ipip_fd = 0; + + if ( curr_gateway_thread_id != 0 ) + pthread_join( curr_gateway_thread_id, NULL ); + +} + + + +int add_default_route() { + + struct sockaddr_in gw_addr; /* connector's address information */ + + memset( &gw_addr, 0, sizeof(struct sockaddr_in) ); + gw_addr.sin_family = AF_INET; + gw_addr.sin_port = htons(PORT); + gw_addr.sin_addr.s_addr = curr_gateway_ip; + + /* connect to server and keep alive */ + if ( ( curr_gateway_tcp_sock = socket(PF_INET, SOCK_STREAM, 0) ) < 0 ) { + + perror("socket"); + curr_gateway = NULL; + return -1; + + } + + if ( connect ( curr_gateway_tcp_sock, (struct sockaddr *)&gw_addr, sizeof(struct sockaddr) ) < 0 ) { + + perror("connect"); + curr_gateway = NULL; + close( curr_gateway_tcp_sock ); + return -1; + + } + + pthread_create( &curr_gateway_thread_id, NULL, &keep_tun_alive, NULL ); + + if ( curr_gateway_ipip_if == NULL ) + curr_gateway_ipip_if = alloc_memory( sizeof(IFNAMSIZ) ); + + if ( add_ipip_tun( curr_gateway_batman_if, curr_gateway_ip, curr_gateway_ipip_if, &curr_gateway_ipip_fd ) > 0 ) { + + add_del_route( 0, curr_gateway_ip, 0, curr_gateway_ipip_if, curr_gateway_ipip_fd ); + return 1; + + } else { + + curr_gateway = NULL; + close( curr_gateway_tcp_sock ); + + if ( curr_gateway_thread_id != 0 ) + pthread_join( curr_gateway_thread_id, NULL ); + + return -1; + + } + +} + + + + +void close_all_sockets() { + struct list_head *if_pos; struct batman_if *batman_if;
list_for_each(if_pos, &if_list) { + batman_if = list_entry(if_pos, struct batman_if, list);
- if ( gateway_class != 0 ) { + if ( batman_if->listen_thread_id != 0 ) { + pthread_join( batman_if->listen_thread_id, NULL ); close(batman_if->tcp_gw_sock); + }
close(batman_if->udp_recv_sock); close(batman_if->udp_send_sock); + }
- if(vis_if.sock) + if ( ( routing_class != 0 ) && ( curr_gateway != NULL ) ) + del_default_route(); + + if (vis_if.sock) close(vis_if.sock); + }
int is_aborted() @@ -268,8 +498,8 @@ void *gw_listen( void *arg ) { /* new client */ if ( FD_ISSET( batman_if->tcp_gw_sock, &tmp_wait_sockets ) ) {
- gw_client = alloc_memory(sizeof(struct gw_client)); - memset(gw_client, 0, sizeof(struct gw_client)); + gw_client = alloc_memory( sizeof(struct gw_client) ); + memset( gw_client, 0, sizeof(struct gw_client) );
if ( ( gw_client->sock = accept(batman_if->tcp_gw_sock, (struct sockaddr *)&gw_client->addr, &sin_size) ) == -1 ) { perror("accept"); @@ -279,18 +509,23 @@ void *gw_listen( void *arg ) { INIT_LIST_HEAD(&gw_client->list); gw_client->batman_if = batman_if; gw_client->last_keep_alive = get_time(); + gw_client->tun_dev = alloc_memory( sizeof(IFNAMSIZ) );
- FD_SET(gw_client->sock, &wait_sockets); - if ( gw_client->sock > max_sock ) - max_sock = gw_client->sock; + if ( add_ipip_tun( batman_if, gw_client->addr.sin_addr.s_addr, gw_client->tun_dev, &gw_client->tun_fd ) > 0 ) {
- if ( debug_level >= 0 ) { - addr_to_string(batman_if->addr.sin_addr.s_addr, str1, sizeof (str1)); - addr_to_string(gw_client->addr.sin_addr.s_addr, str2, sizeof (str2)); - printf( "gateway: %s got connection from %s\n", str1, str2 ); - } + FD_SET(gw_client->sock, &wait_sockets); + if ( gw_client->sock > max_sock ) + max_sock = gw_client->sock; + + list_add_tail(&gw_client->list, &batman_if->client_list);
- list_add_tail(&gw_client->list, &batman_if->client_list); + if ( debug_level >= 1 ) { + addr_to_string(batman_if->addr.sin_addr.s_addr, str1, sizeof (str1)); + addr_to_string(gw_client->addr.sin_addr.s_addr, str2, sizeof (str2)); + printf( "gateway: %s (%s) got connection from %s (internet via %s)\n", str1, batman_if->dev, str2, gw_client->tun_dev ); + } + + }
/* client sent keep alive */ } else { @@ -303,7 +538,7 @@ void *gw_listen( void *arg ) {
gw_client->last_keep_alive = get_time();
- if ( debug_level >= 0 ) { + if ( debug_level >= 2 ) { addr_to_string(gw_client->addr.sin_addr.s_addr, str2, sizeof (str2)); printf( "gateway: client %s sent keep alive on interface %s\n", str2, batman_if->dev ); } @@ -338,8 +573,9 @@ void *gw_listen( void *arg ) {
FD_CLR(gw_client->sock, &wait_sockets); close( gw_client->sock ); + del_ipip_tun( gw_client->tun_fd );
- if ( debug_level >= 0 ) { + if ( debug_level >= 1 ) { addr_to_string(gw_client->addr.sin_addr.s_addr, str2, sizeof (str2)); printf( "gateway: client %s timeout on interface %s\n", str2, batman_if->dev ); } @@ -360,16 +596,27 @@ void *gw_listen( void *arg ) {
}
+ /* delete all ipip devices on exit */ + list_for_each(client_pos, &batman_if->client_list) { + + gw_client = list_entry(client_pos, struct gw_client, list); + + del_ipip_tun( gw_client->tun_fd ); + + } + return NULL;
}
+ + int main(int argc, char *argv[]) { struct in_addr tmp_ip_holder; struct batman_if *batman_if; struct ifreq int_req; - int on = 1, res, optchar, found_args = 1; + int on = 1, res, optchar, found_args = 1, fd; char str1[16], str2[16], *dev; unsigned int vis_server = 0;
@@ -617,30 +864,45 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Error - no interface specified\n"); usage(); - return 1; + close_all_sockets(); + exit(EXIT_FAILURE); }
if ( ( gateway_class != 0 ) && ( routing_class != 0 ) ) { fprintf(stderr, "Error - routing class can't be set while gateway class is in use !\n"); usage(); - return 1; + close_all_sockets(); + exit(EXIT_FAILURE); }
if ( ( gateway_class != 0 ) && ( pref_gateway != 0 ) ) { fprintf(stderr, "Error - preferred gateway can't be set while gateway class is in use !\n"); usage(); - return 1; + close_all_sockets(); + exit(EXIT_FAILURE); }
if ( ( routing_class == 0 ) && ( pref_gateway != 0 ) ) { fprintf(stderr, "Error - preferred gateway can't be set without specifying routing class !\n"); usage(); - return 1; + close_all_sockets(); + exit(EXIT_FAILURE); + } + + if ( ( fd = open( "/dev/net/tun", O_RDWR ) ) < 0 ) { + + fprintf( stderr, "Error - could not open '/dev/net/tun' ! Is the tun kernel module loaded ?\n" ); + close_all_sockets(); + exit(EXIT_FAILURE); + }
+ close( fd ); + + if ( debug_level > 0 ) printf("debug level: %i\n", debug_level); if ( ( debug_level > 0 ) && ( orginator_interval != 1000 ) ) printf( "orginator interval: %i\n", orginator_interval ); if ( ( debug_level > 0 ) && ( gateway_class > 0 ) ) printf( "gateway class: %i\n", gateway_class ); @@ -650,6 +912,7 @@ int main(int argc, char *argv[]) printf( "preferred gateway: %s\n", str1 ); }
+ signal(SIGINT, handler);
gettimeofday(&start_time, NULL);