The following commit has been merged in the master branch:
commit c0f6163617f625372d0310d594853b30281c8234
Author: Marek Lindner <lindner_marek(a)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);
--
batman; test conversation