The following commit has been merged in the master branch: commit 40b7e5478feeaf31bb4e19279a18f4dddec58628 Author: Marek Lindner lindner_marek@yahoo.de Date: Mon Mar 12 23:52:31 2007 +0100
merge hash memory leak fix from batman advanced fix hash_iterate (missing entries while using hash_iterate() && hash_remove()) no gateways in range display bug fixed try to remove routes from kernel routing table on SIGSEGV
diff --git a/allocate.c b/allocate.c index 52cbb34..a09fb88 100644 --- a/allocate.c +++ b/allocate.c @@ -26,6 +26,7 @@ #include "os.h" #include "allocate.h"
+ #define DEBUG_MALLOC #define MEMORY_USAGE
@@ -177,10 +178,13 @@ void checkIntegrity(void)
void checkLeak(void) { + struct chunkHeader *walker;
for (walker = chunkList; walker != NULL; walker = walker->next) fprintf(stderr, "Memory leak detected, malloc tag = %d\n", walker->tag); + + }
void *debugMalloc(uint32_t length, int32_t tag) diff --git a/batman.c b/batman.c index 2ec4db4..6173270 100644 --- a/batman.c +++ b/batman.c @@ -508,7 +508,7 @@ int isDuplicate( struct orig_node *orig_node, uint16_t seqno ) {
int isBidirectionalNeigh( struct orig_node *orig_neigh_node, struct batman_if *if_incoming ) {
- if( orig_neigh_node->bidirect_link[if_incoming->if_num] > 0 && ( orig_neigh_node->bidirect_link[if_incoming->if_num] + (bidirectional_timeout) ) >= get_time() ) + if ( orig_neigh_node->bidirect_link[if_incoming->if_num] > 0 && ( orig_neigh_node->bidirect_link[if_incoming->if_num] + (bidirectional_timeout) ) >= get_time() ) return 1; else return 0; diff --git a/hash.c b/hash.c index 42c2bbc..da09301 100644 --- a/hash.c +++ b/hash.c @@ -19,7 +19,8 @@
#include <stdio.h> /* NULL */ -#include "batman.h" +#include "batman-specific.h" +
/* clears the hash */ void hash_init(struct hashtable_t *hash) { @@ -60,8 +61,8 @@ void hash_delete(struct hashtable_t *hash, hashdata_free_cb free_cb) { /* free only the hashtable and the hash itself. */ void hash_destroy(struct hashtable_t *hash) {
- debugFree( hash->table, 1301 ); - debugFree( hash, 1302 ); + debugFree( hash->table, 1302 ); + debugFree( hash, 1303 );
}
@@ -76,24 +77,35 @@ struct hash_it_t *hash_iterate(struct hashtable_t *hash, struct hash_it_t *iter_ if (iter_in == NULL) { iter= debugMalloc(sizeof(struct hash_it_t), 301); iter->index = -1; - iter->bucket = NULL; + iter->bucket = iter->next_bucket = NULL; } else iter= iter_in; - if ( iter->bucket!=NULL ) { - iter->bucket = iter->bucket->next; /* choose next */ - if (iter->bucket !=NULL) /* if fine, return it */ + if (iter->bucket!=NULL) { + /* if hash_remove() was used since last call our next pointer may not + correspond with our last next position - we don't to miss some entries */ + if ( (iter->next_bucket!=NULL) && (iter->bucket->next!=iter->next_bucket) ) { + iter->bucket = &(hash->table[ iter->index ]); + iter->next_bucket = ((struct element_t *)&(hash->table[ iter->index ]))->next; + return(iter); + } else if (iter->bucket->next!=NULL) { + iter->bucket = iter->bucket->next; /* choose next */ + iter->next_bucket = iter->bucket->next; return(iter); + } else { + iter->bucket = iter->next_bucket = NULL; + } } iter->index++; while ( iter->index < hash->size ) { /* go through the entries of the hash table */ if ((hash->table[ iter->index ].data) != NULL){ iter->bucket = &(hash->table[ iter->index ]); + iter->next_bucket = ((struct element_t *)&(hash->table[ iter->index ]))->next; return(iter); /* if this table entry is not null, return it */ } else iter->index++; /* else, go to the next */ } /* nothing to iterate over anymore */ - debugFree(iter, 1303); + debugFree(iter, 1304); return(NULL); }
@@ -109,7 +121,7 @@ struct hashtable_t *hash_new(int size, hashdata_compare_cb compare, hashdata_cho hash->size= size; hash->table= debugMalloc( sizeof(struct element_t) * size, 303); if ( hash->table == NULL ) { /* could not allocate the table */ - debugFree(hash, 1304); + debugFree(hash, 1305); return(NULL); } hash->compare= compare; @@ -179,7 +191,7 @@ void *hash_find(struct hashtable_t *hash, void *keydata) { * we just need the key for comparing. */ void *hash_remove(struct hashtable_t *hash, void *data) { int index; - struct element_t *bucket, *last_bucket; + struct element_t *bucket, *last_bucket, *next_bucket; void *data_save;
index = hash->choose( data , hash->size ); @@ -194,12 +206,15 @@ void *hash_remove(struct hashtable_t *hash, void *data) { if ( bucket->next == NULL ) { /* there is no next bucket, nothing to preserve. */ bucket->data= NULL; } else { /* else, move the second bucket onto the first one */ + next_bucket = bucket->next; bucket->data= bucket->next->data; bucket->next= bucket->next->next; + debugFree(next_bucket, 1306); /* free the next_bucket, as we copied its data into our + * first bucket. */ } } else { /* not the first entry */ last_bucket->next= bucket->next; - debugFree(bucket, 1305); + debugFree(bucket, 1307); }
hash->elements--; @@ -244,22 +259,21 @@ struct hashtable_t *hash_resize(struct hashtable_t *hash, int size) {
/* print the hash table for debugging */ -void hash_debug( struct hashtable_t *hash) { +void hash_debug(struct hashtable_t *hash) { int i; struct element_t *bucket; for (i=0; i<hash->size;i++) { - printf("[%d] ",i); +// printf("[%d] ",i); if (hash->table[i].data != NULL) { - printf("[%10p] ", hash->table[i].data); - + printf("[%d] [%10p] ", i, hash->table[i].data);
bucket= hash->table[i].next; while (bucket != NULL) { printf("-> [%10p] ", bucket->data); bucket= bucket->next; } + printf("\n"); } - printf("\n");
} } diff --git a/hash.h b/hash.h index 8052078..5c21773 100644 --- a/hash.h +++ b/hash.h @@ -30,6 +30,7 @@ struct element_t { struct hash_it_t { int index; struct element_t *bucket; + struct element_t *next_bucket; };
struct hashtable_t { diff --git a/orginator.c b/orginator.c index 5d46624..6862637 100644 --- a/orginator.c +++ b/orginator.c @@ -20,6 +20,7 @@
#include <string.h> +#include <stdlib.h> #include "os.h" #include "batman.h"
@@ -64,6 +65,8 @@ struct orig_node *get_orig_node( uint32_t addr ) {
prof_start( PROF_get_orig_node ); struct orig_node *orig_node; + struct hashtable_t *swaphash; + static char orig_str[ADDR_STR_LEN];
orig_node = ((struct orig_node *)hash_find( orig_hash, &addr )); @@ -76,7 +79,8 @@ struct orig_node *get_orig_node( uint32_t addr ) { }
- debug_output( 4, "Creating new originator\n" ); + addr_to_string( addr, orig_str, ADDR_STR_LEN ); + debug_output( 4, "Creating new originator: %s \n", orig_str );
orig_node = debugMalloc( sizeof(struct orig_node), 401 ); memset(orig_node, 0, sizeof(struct orig_node)); @@ -89,14 +93,21 @@ struct orig_node *get_orig_node( uint32_t addr ) { orig_node->bidirect_link = debugMalloc( found_ifs * sizeof(uint32_t), 402 ); memset( orig_node->bidirect_link, 0, found_ifs * sizeof(uint32_t) );
- hash_add(orig_hash, orig_node); - if (orig_hash->elements * 4 > orig_hash->size) { - struct hashtable_t *swaphash; - swaphash = hash_resize(orig_hash, orig_hash->size*2); - if (swaphash == NULL) - debug_output( 0, "Couldn't resize hash table\n" ); - else - orig_hash = swaphash; + hash_add( orig_hash, orig_node ); + + if ( orig_hash->elements * 4 > orig_hash->size ) { + + swaphash = hash_resize( orig_hash, orig_hash->size * 2 ); + + if ( swaphash == NULL ) { + + debug_output( 0, "Couldn't resize hash table \n" ); + restore_defaults(); + exit(EXIT_FAILURE); + + } + + orig_hash = swaphash;
}
@@ -210,7 +221,6 @@ void purge_orig( uint32_t curr_time ) { uint8_t gw_purged = 0, neigh_purged = 0; static char orig_str[ADDR_STR_LEN];
- debug_output( 4, "purge() \n" );
/* for all origins... */ while ( NULL != ( hashit = hash_iterate( orig_hash, hashit ) ) ) { @@ -219,8 +229,8 @@ void purge_orig( uint32_t curr_time ) {
if ( (int)( ( orig_node->last_aware + ( 2 * TIMEOUT ) ) < curr_time ) ) {
- addr_to_string(orig_node->orig, orig_str, ADDR_STR_LEN); - debug_output( 4, "Orginator timeout: originator %s, last_aware %u)\n", orig_str, orig_node->last_aware ); + addr_to_string( orig_node->orig, orig_str, ADDR_STR_LEN ); + debug_output( 4, "Orginator timeout: originator %s, last_aware %u) \n", orig_str, orig_node->last_aware );
hash_remove( orig_hash, orig_node );
@@ -243,7 +253,7 @@ void purge_orig( uint32_t curr_time ) { 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 ); + debug_output( 3, "Removing gateway %s from gateway list \n", orig_str );
gw_node->deleted = get_time();
@@ -352,6 +362,8 @@ void debug_orig() { debug_output( 2, "%s via: %s(%i), gw_class %i - %s, reliability: %i \n", str, str2, gw_node->orig_node->router->packet_count, gw_node->orig_node->gwflags, gw2string[gw_node->orig_node->gwflags], gw_node->unavail_factor ); }
+ batman_count++; + }
if ( batman_count == 0 ) diff --git a/posix-specific.c b/posix-specific.c index de9e028..2a5fda3 100644 --- a/posix-specific.c +++ b/posix-specific.c @@ -40,9 +40,8 @@ #include <syslog.h>
#include "os.h" +#include "orginator.h" #include "batman-specific.h" -#include "list.h" -#include "allocate.h"
@@ -112,13 +111,14 @@ void debug_output( int8_t debug_prio, char *format, ... ) { if ( debug_prio_intern == 3 ) dprintf( debug_level_info->fd, "[%10u] ", get_time() );
- if ( ( ( debug_level == 1 ) || ( debug_level == 2 ) ) && ( debug_level_info->fd == 1 ) && ( strcmp( format, "BOD\n" ) == 0 ) ) { + if ( ( ( debug_level == 1 ) || ( debug_level == 2 ) ) && ( debug_level_info->fd == 1 ) && ( strncmp( format, "BOD\n", 3 ) == 0 ) ) {
system( "clear" );
} else {
- vdprintf( debug_level_info->fd, format, args ); + if ( ( ( debug_level != 1 ) && ( debug_level != 2 ) ) || ( debug_level_info->fd != 1 ) || ( strncmp( format, "EOD\n", 3 ) == 0 ) ) + vdprintf( debug_level_info->fd, format, args );
}
@@ -1587,9 +1587,11 @@ void *gw_listen( void *arg ) {
void segmentation_fault( int32_t sig ) {
+ debug_output( 0, "Error - SIGSEGV received !\n" ); + restore_defaults();
- debug_output( 0, "Error - SIGSEGV received !\n" ); + purge_orig( get_time() + ( 5 * TIMEOUT ) + orginator_interval );
exit(EXIT_FAILURE);