The following commit has been merged in the master branch: commit 4f08b9f896164ddb622fbfc0508ad3616cc1a3ad Author: Marek Lindner lindner_marek@yahoo.de Date: Fri Feb 9 16:43:33 2007 +0100
fix race condition in client_to_gw_tun() - code merge from branch-0.1.x
diff --git a/batman.c b/batman.c index 0fe1a8a..b873903 100644 --- a/batman.c +++ b/batman.c @@ -279,6 +279,9 @@ static void choose_gw() { if ( gw_node->orig_node->router == NULL ) continue;
+ if ( gw_node->deleted ) + continue; + switch ( routing_class ) {
case 1: /* fast connection */ @@ -457,13 +460,13 @@ static void update_gw_list( struct orig_node *orig_node, uint8_t new_gwflags ) {
if ( new_gwflags == 0 ) {
- list_del( gw_pos ); - debugFree( gw_pos, 102 ); + gw_node->deleted = get_time();
debug_output( 3, "Gateway %s removed from gateway list\n", orig_str );
} else {
+ gw_node->deleted = 0; gw_node->orig_node->gwflags = new_gwflags;
} @@ -515,8 +518,12 @@ void debug() {
} else {
- list_for_each(orig_pos, &gw_list) { - gw_node = list_entry(orig_pos, struct gw_node, list); + list_for_each( orig_pos, &gw_list ) { + + gw_node = list_entry( orig_pos, struct gw_node, list ); + + if ( gw_node->deleted ) + continue;
addr_to_string( gw_node->orig_node->orig, str, sizeof (str) ); addr_to_string( gw_node->orig_node->router->addr, str2, sizeof (str2) ); @@ -529,6 +536,9 @@ void debug() {
}
+ if ( batman_count == 0 ) + debug_output( 2, "No gateways in range ...\n" ); + }
} @@ -986,17 +996,19 @@ void purge( uint32_t curr_time ) {
}
- list_for_each_safe(gw_pos, gw_pos_tmp, &gw_list) { + list_for_each_safe( gw_pos, gw_pos_tmp, &gw_list ) { + + gw_node = list_entry( gw_pos, struct gw_node, list );
- gw_node = list_entry(gw_pos, struct gw_node, list); + if ( gw_node->deleted ) + continue;
if ( gw_node->orig_node == orig_node ) {
addr_to_string( gw_node->orig_node->orig, orig_str, ADDR_STR_LEN ); debug_output( 3, "Removing gateway %s from gateway list\n", orig_str );
- list_del( gw_pos ); - debugFree( gw_pos, 107 ); + gw_node->deleted = get_time();
gw_purged = 1;
@@ -1033,6 +1045,19 @@ void purge( uint32_t curr_time ) {
}
+ list_for_each_safe(gw_pos, gw_pos_tmp, &gw_list) { + + gw_node = list_entry(gw_pos, struct gw_node, list); + + if ( ( gw_node->deleted ) && ( (int)((gw_node->deleted + 3 * TIMEOUT) < curr_time) ) ) { + + list_del( gw_pos ); + debugFree( gw_pos, 107 ); + + } + + } + if ( gw_purged ) choose_gw();
@@ -1382,7 +1407,7 @@ int8_t batman() { if ( debug_level > 0 ) printf( "Deleting all BATMAN routes\n" );
- purge( get_time() + ( 2 * TIMEOUT ) + orginator_interval ); + purge( get_time() + ( 5 * TIMEOUT ) + orginator_interval );
list_for_each_safe( hna_pos, hna_pos_tmp, &hna_list ) { diff --git a/batman.h b/batman.h index ea4cf83..5a03e31 100644 --- a/batman.h +++ b/batman.h @@ -142,6 +142,7 @@ struct gw_node struct orig_node *orig_node; uint16_t unavail_factor; uint32_t last_failure; + uint32_t deleted; };
struct batman_if @@ -199,6 +200,12 @@ struct debug_level_info { int32_t fd; };
+struct curr_gw_data { + unsigned int orig; + struct gw_node *gw_node; + struct batman_if *batman_if; +}; +
int8_t batman( void ); void usage( void ); diff --git a/posix-specific.c b/posix-specific.c index f69788b..149bcfc 100644 --- a/posix-specific.c +++ b/posix-specific.c @@ -1000,19 +1000,16 @@ void init_interface_gw ( struct batman_if *batman_if )
void *client_to_gw_tun( void *arg ) {
- struct gw_node *gw_node = (struct gw_node *)arg; - struct batman_if *curr_gateway_batman_if; + struct curr_gw_data *curr_gw_data = (struct curr_gw_data *)arg; struct sockaddr_in gw_addr, my_addr, sender_addr; struct timeval tv; int res, max_sock, status, buff_len, curr_gateway_tcp_sock, curr_gateway_tun_sock, curr_gateway_tun_fd, server_keep_alive_timeout; - unsigned int addr_len, curr_gateway_ip; + unsigned int addr_len; char curr_gateway_tun_if[IFNAMSIZ], keep_alive_string[] = "ping\0"; unsigned char buff[1500]; fd_set wait_sockets, tmp_wait_sockets;
- curr_gateway_ip = gw_node->orig_node->orig; - curr_gateway_batman_if = gw_node->orig_node->batman_if; addr_len = sizeof (struct sockaddr_in);
memset( &gw_addr, 0, sizeof(struct sockaddr_in) ); @@ -1020,11 +1017,11 @@ void *client_to_gw_tun( void *arg ) {
gw_addr.sin_family = AF_INET; gw_addr.sin_port = htons(PORT + 1); - gw_addr.sin_addr.s_addr = curr_gateway_ip; + gw_addr.sin_addr.s_addr = curr_gw_data->orig;
my_addr.sin_family = AF_INET; my_addr.sin_port = htons(PORT + 1); - my_addr.sin_addr.s_addr = curr_gateway_batman_if->addr.sin_addr.s_addr; + my_addr.sin_addr.s_addr = curr_gw_data->batman_if->addr.sin_addr.s_addr;
/* connect to server (ask permission) */ @@ -1032,6 +1029,7 @@ void *client_to_gw_tun( void *arg ) {
debug_output( 0, "Error - can't create tcp socket: %s\n", strerror(errno) ); curr_gateway = NULL; + debugFree( arg, 248 ); return NULL;
} @@ -1041,10 +1039,11 @@ void *client_to_gw_tun( void *arg ) { debug_output( 0, "Error - can't connect to gateway: %s\n", strerror(errno) ); close( curr_gateway_tcp_sock );
- gw_node->last_failure = get_time(); - gw_node->unavail_factor++; + curr_gw_data->gw_node->last_failure = get_time(); + curr_gw_data->gw_node->unavail_factor++;
curr_gateway = NULL; + debugFree( arg, 248 ); return NULL;
} @@ -1058,6 +1057,7 @@ void *client_to_gw_tun( void *arg ) { debug_output( 0, "Error - can't create udp socket: %s\n", strerror(errno) ); close( curr_gateway_tcp_sock ); curr_gateway = NULL; + debugFree( arg, 248 ); return NULL;
} @@ -1068,20 +1068,22 @@ void *client_to_gw_tun( void *arg ) { close( curr_gateway_tcp_sock ); close( curr_gateway_tun_sock ); curr_gateway = NULL; + debugFree( arg, 248 ); return NULL;
}
- if ( add_dev_tun( curr_gateway_batman_if, curr_gateway_batman_if->addr.sin_addr.s_addr, curr_gateway_tun_if, sizeof(curr_gateway_tun_if), &curr_gateway_tun_fd ) > 0 ) { + if ( add_dev_tun( curr_gw_data->batman_if, curr_gw_data->batman_if->addr.sin_addr.s_addr, curr_gateway_tun_if, sizeof(curr_gateway_tun_if), &curr_gateway_tun_fd ) > 0 ) {
- add_del_route( 0, 0, 0, 0, curr_gateway_tun_if, curr_gateway_batman_if->udp_send_sock ); + add_del_route( 0, 0, 0, 0, curr_gateway_tun_if, curr_gw_data->batman_if->udp_send_sock );
} else {
close( curr_gateway_tcp_sock ); close( curr_gateway_tun_sock ); curr_gateway = NULL; + debugFree( arg, 248 ); return NULL;
} @@ -1098,7 +1100,7 @@ void *client_to_gw_tun( void *arg ) { if ( curr_gateway_tun_fd > max_sock ) max_sock = curr_gateway_tun_fd;
- while ( ( !is_aborted() ) && ( curr_gateway != NULL ) ) { + while ( ( !is_aborted() ) && ( curr_gateway != NULL ) && ( ! curr_gw_data->gw_node->deleted ) ) {
if ( server_keep_alive_timeout + 30000 < get_time() ) { @@ -1109,8 +1111,8 @@ void *client_to_gw_tun( void *arg ) {
debug_output( 3, "server_keepalive failed: %s\n", strerror(errno) );
- gw_node->last_failure = get_time(); - gw_node->unavail_factor++; + curr_gw_data->gw_node->last_failure = get_time(); + curr_gw_data->gw_node->unavail_factor++;
break;
@@ -1147,8 +1149,8 @@ void *client_to_gw_tun( void *arg ) {
debug_output( 3, "Gateway closed connection - timeout ?\n" );
- gw_node->last_failure = get_time(); - gw_node->unavail_factor++; + curr_gw_data->gw_node->last_failure = get_time(); + curr_gw_data->gw_node->unavail_factor++;
break;
@@ -1197,7 +1199,7 @@ void *client_to_gw_tun( void *arg ) { }
/* cleanup */ - add_del_route( 0, 0, 0, 1, curr_gateway_tun_if, curr_gateway_batman_if->udp_send_sock ); + add_del_route( 0, 0, 0, 1, curr_gateway_tun_if, curr_gw_data->batman_if->udp_send_sock );
close( curr_gateway_tcp_sock ); close( curr_gateway_tun_sock ); @@ -1205,6 +1207,7 @@ void *client_to_gw_tun( void *arg ) { del_dev_tun( curr_gateway_tun_fd );
curr_gateway = NULL; + debugFree( arg, 248 );
return NULL;
@@ -1224,7 +1227,16 @@ void del_default_route() {
int8_t add_default_route() {
- if ( pthread_create( &curr_gateway_thread_id, NULL, &client_to_gw_tun, curr_gateway ) != 0 ) { + struct curr_gw_data *curr_gw_data; + + + curr_gw_data = debugMalloc( sizeof(struct curr_gw_data), 47 ); + curr_gw_data->orig = curr_gateway->orig_node->orig; + curr_gw_data->gw_node = curr_gateway; + curr_gw_data->batman_if = curr_gateway->orig_node->batman_if; + + + if ( pthread_create( &curr_gateway_thread_id, NULL, &client_to_gw_tun, curr_gw_data ) != 0 ) {
debug_output( 0, "Error - couldn't spawn thread: %s\n", strerror(errno) ); curr_gateway = NULL;