00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "aodv.h"
00033 #include <string.h>
00034
00035 void
00036 clear_aodv_routing_table( aodv_routing_table_t* table )
00037 {
00038 aodv_table_entry_t* head;
00039 aodv_table_entry_t* curr;
00040 aodv_table_entry_t* next;
00041
00042 if ( NULL == table )
00043 {
00044 return;
00045 }
00046 if ( NULL == table->head )
00047 {
00048 return;
00049 }
00050
00051 head = table->head;
00052 curr = head;
00053 do
00054 {
00055 next = curr->next;
00056 free_aodv_table_entry(curr);
00057 curr = next;
00058 } while ( curr != head );
00059
00060 table->head = NULL;
00061 }
00062
00063 aodv_table_entry_t*
00064 add_aodv_table_entry( aodv_routing_table_t* table,
00065 const aodv_addr_t* destination,
00066 uint16_t prefix_size )
00067 {
00068 aodv_table_entry_t* head;
00069 aodv_table_entry_t* tail;
00070 aodv_table_entry_t* temp;
00071
00072 if ( NULL == table )
00073 {
00074 return NULL;
00075 }
00076
00077 temp = new_aodv_table_entry();
00078 if ( NULL == temp )
00079 {
00080 return NULL;
00081 }
00082 set_aodv_addr( &(temp->destination.addr), destination );
00083 temp->destination.prefix = prefix_size;
00084
00085 if ( NULL == table->head )
00086 {
00087 table->head = temp;
00088 temp->next = temp;
00089 temp->prev = temp;
00090 }
00091 else
00092 {
00093 head = table->head;
00094 tail = head->prev;
00095 temp->next = head;
00096 temp->prev = tail;
00097 head->prev = temp;
00098 tail->next = temp;
00099 }
00100
00101 return temp;
00102 }
00103
00104 void
00105 remove_aodv_table_entry( aodv_routing_table_t* table,
00106 aodv_table_entry_t* entry )
00107 {
00108 aodv_table_entry_t* curr;
00109 aodv_table_entry_t* next;
00110 unsigned char is_head;
00111 unsigned char is_tail;
00112
00113 if ( NULL == table ) return;
00114 if ( NULL == entry ) return;
00115 if ( NULL == table->head ) return;
00116
00117 curr = table->head;
00118 do
00119 {
00120 next = curr->next;
00121 if ( curr == entry )
00122 {
00123 is_head = 0;
00124 is_tail = 0;
00125 if ( curr == table->head ) is_head = 1;
00126 if ( curr == table->head->prev ) is_tail = 1;
00127
00128 if ( is_head && is_tail )
00129 {
00130 table->head = NULL;
00131 next = NULL;
00132 }
00133 else
00134 {
00135 if ( is_head )
00136 {
00137 table->head = next;
00138 }
00139 curr->prev->next = next;
00140 next->prev = curr->prev;
00141 }
00142 free_aodv_table_entry( curr );
00143 return;
00144 }
00145 curr = next;
00146 } while ( curr != table->head );
00147 }
00148
00149 aodv_table_entry_t*
00150 update_aodv_table_entry( aodv_state_t* state,
00151 const aodv_msghdr_t* hdrs,
00152 const aodv_node_list_t* node,
00153 unsigned char hop_count )
00154 {
00155 aodv_table_entry_t* entry;
00156 uint32_t cmp;
00157
00158 if ( NULL == state ) return NULL;
00159 if ( NULL == hdrs ) return NULL;
00160 if ( NULL == node ) return NULL;
00161
00162 entry = aodv_lookup( &(state->routing_table), &(node->node) );
00163 if ( NULL == entry )
00164 {
00165 entry =
00166 add_aodv_table_entry( &(state->routing_table), &(node->node), 0 );
00167 if ( NULL == entry ) return NULL;
00168 }
00169 cmp = aodv_cmp_seq( node->seq, entry->dest_seq );
00170 if ( ( cmp > 0 ) ||
00171 ( ( 0 == cmp ) && ( ( ! entry->valid_route ) ||
00172 ( hop_count < entry->hop_count ) ) ) )
00173 {
00174 aodv_update_route_expiry( state, entry );
00175 entry->dest_seq = node->seq;
00176 set_aodv_addr( &(entry->next_hop), &(hdrs->addr) );
00177 entry->hop_count = hop_count;
00178 entry->interface = hdrs->interface;
00179 entry->valid_route = 1;
00180 }
00181 return entry;
00182 }
00183
00184 aodv_table_entry_t*
00185 new_aodv_table_entry()
00186 {
00187 aodv_table_entry_t* temp;
00188 temp = (aodv_table_entry_t*) malloc( sizeof(aodv_table_entry_t) );
00189 if ( NULL == temp )
00190 {
00191 return NULL;
00192 }
00193 temp->next = NULL;
00194 temp->prev = NULL;
00195 temp->destination.addr.data = NULL;
00196 temp->destination.addr.length = 0U;
00197 temp->destination.prefix = 0;
00198 temp->dest_seq = 0;
00199 temp->next_hop.data = NULL;
00200 temp->next_hop.length = 0U;
00201 temp->lifetime.tv_sec = -1;
00202 temp->lifetime.tv_usec = 0;
00203 temp->hop_count = 0;
00204 temp->interface = -1;
00205 temp->valid_route = 0;
00206 return temp;
00207 }
00208
00209 void
00210 free_aodv_table_entry( aodv_table_entry_t* entry )
00211 {
00212 if ( NULL == entry ) return;
00213 if ( NULL != entry->destination.addr.data )
00214 free( entry->destination.addr.data );
00215 if ( NULL != entry->next_hop.data )
00216 free( entry->next_hop.data );
00217 free(entry);
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227 aodv_table_entry_t*
00228 aodv_lookup( const aodv_routing_table_t* table,
00229 const aodv_addr_t* destination )
00230 {
00231 aodv_table_entry_t* curr;
00232 aodv_table_entry_t* best;
00233 uint16_t curr_prefix;
00234 uint16_t best_prefix;
00235
00236 if ( NULL == table )
00237 {
00238 return NULL;
00239 }
00240 if ( NULL == table->head )
00241 {
00242 return NULL;
00243 }
00244 if ( NULL == destination )
00245 {
00246 return NULL;
00247 }
00248
00249 best = NULL;
00250 best_prefix = ~0;
00251 curr = table->head;
00252 do
00253 {
00254 if ( 0 == curr->destination.prefix )
00255 {
00256 if ( 0 == aodv_cmp_addr( &(curr->destination.addr), destination ) )
00257 {
00258 return curr;
00259 }
00260 }
00261 else
00262 {
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 curr_prefix = curr->destination.prefix;
00284 if ( (8 * destination->length) >= curr_prefix )
00285 {
00286 if ( curr_prefix < best_prefix )
00287 {
00288 char nomatch = 0;
00289 uint16_t ip = curr_prefix / 8;
00290 unsigned char bp = curr_prefix % 8;
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 if ( ip > 0 )
00305 {
00306 nomatch |= memcmp( curr->destination.addr.data,
00307 destination->data,
00308 ip );
00309 }
00310
00311
00312 if ( ( !nomatch ) && ( bp > 0 ) )
00313 {
00314 unsigned char mask = ~0 << bp;
00315 nomatch |= ( ( curr->destination.addr.data[ip] & mask ) !=
00316 ( destination->data[ip] & mask ) );
00317
00318 }
00319
00320 if ( !nomatch )
00321 {
00322 best = curr;
00323 best_prefix = curr_prefix;
00324 }
00325 }
00326 }
00327 }
00328 curr = curr->next;
00329 } while ( curr != table->head );
00330
00331 return best;
00332 }
00333
00334 void
00335 aodv_invalidate_route( aodv_state_t* state, const aodv_addr_t* destination )
00336 {
00337 aodv_routing_table_t* table;
00338 aodv_table_entry_t* entry;
00339
00340 if ( NULL == state ) return;
00341
00342 table = &(state->routing_table);
00343 entry = aodv_lookup( table, destination );
00344 if ( NULL == entry )
00345 {
00346 return;
00347 }
00348 if ( entry->valid_route )
00349 {
00350 aodv_invalidate_routing_entry( state, entry );
00351 }
00352 }
00353
00354 void
00355 aodv_invalidate_routing_entry( aodv_state_t* state,
00356 aodv_table_entry_t* entry )
00357 {
00358 if ( NULL == state ) return;
00359 if ( NULL == entry ) return;
00360
00361 entry->valid_route = 0;
00362 aodv_incr_seq_base( &(entry->dest_seq) );
00363 }
00364
00365 unsigned char
00366 aodv_table_entry_is_expired( const aodv_table_entry_t* entry )
00367 {
00368 if ( NULL == entry ) return 0;
00369
00370 return aodv_pasttime( &(entry->lifetime) );
00371 }
00372
00373 static void
00374 _update_route_lifetime( aodv_table_entry_t* entry,
00375 unsigned int lifetime )
00376 {
00377 struct timeval* tv = &(entry->lifetime);
00378 aodv_gettime(tv);
00379 tv->tv_usec += 1000 * lifetime;
00380 while( tv->tv_usec >= 1000000 )
00381 {
00382 tv->tv_usec -= 1000000;
00383 tv->tv_sec += 1;
00384 }
00385 }
00386
00387 void
00388 aodv_update_route_expiry( const aodv_state_t* state,
00389 aodv_table_entry_t* entry )
00390 {
00391 _update_route_lifetime( entry, state->params.active_route_timeout );
00392 }
00393
00394 void
00395 aodv_update_invalid_route_lifetime( const aodv_state_t* state,
00396 aodv_table_entry_t* entry )
00397 {
00398 _update_route_lifetime( entry, state->params.delete_period );
00399 }
00400
00401 void
00402 aodv_broken_link( aodv_state_t* state, const aodv_addr_t* bad_hop )
00403 {
00404 aodv_table_entry_t* thead;
00405 aodv_table_entry_t* tcurr;
00406 int gen_rerr = 0;
00407 aodv_rerr_t rerr;
00408 rerr.dest_count = 0;
00409 rerr.unreachable = 0;
00410
00411 if ( NULL == state ) return;
00412
00413 thead = state->routing_table.head;
00414 tcurr = thead;
00415 if ( 0 != thead )
00416 {
00417 do
00418 {
00419 if ( tcurr->valid_route &&
00420 ( 0 == aodv_cmp_addr( bad_hop, &(tcurr->next_hop) ) ) )
00421 {
00422 gen_rerr = 1;
00423 aodv_invalidate_routing_entry( state, tcurr );
00424 rerr.dest_count++;
00425 aodv_add_to_node_list( &(rerr.unreachable),
00426 &(tcurr->destination.addr),
00427 tcurr->dest_seq );
00428 }
00429 tcurr = tcurr->next;
00430 } while ( tcurr != thead );
00431 }
00432
00433 if ( gen_rerr )
00434 {
00435 if ( aodv_insert_time( state->rerr_time_ring ) )
00436 {
00437 aodv_bcast_rerr( state, &rerr );
00438 }
00439 }
00440 }