~ubuntu-branches/ubuntu/trusty/batmand/trusty

« back to all changes in this revision

Viewing changes to batman.c

  • Committer: Bazaar Package Importer
  • Author(s): Holger Levsen
  • Date: 2007-11-26 09:10:49 UTC
  • Revision ID: james.westby@ubuntu.com-20071126091049-9fqg546f2c4ct759
Tags: upstream-0.2
ImportĀ upstreamĀ versionĀ 0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2006 B.A.T.M.A.N. contributors:
 
3
 * Thomas Lopatic, Corinna 'Elektra' Aichele, Axel Neumann,
 
4
 * Felix Fietkau, Marek Lindner
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of version 2 of the GNU General Public
 
8
 * License as published by the Free Software Foundation.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful, but
 
11
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
13
 * General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
18
 * 02110-1301, USA
 
19
 *
 
20
 */
 
21
 
 
22
 
 
23
 
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <stdio.h>
 
27
#include "os.h"
 
28
#include "batman.h"
 
29
#include "originator.h"
 
30
#include "schedule.h"
 
31
 
 
32
#include <errno.h>  /* should be removed together with tcp control channel */
 
33
 
 
34
 
 
35
/* "-d" is the command line switch for the debug level,
 
36
 * specify it multiple times to increase verbosity
 
37
 * 0 gives a minimum of messages to save CPU-Power
 
38
 * 1 normal
 
39
 * 2 verbose
 
40
 * 3 very verbose
 
41
 * Beware that high debugging levels eat a lot of CPU-Power
 
42
 */
 
43
 
 
44
uint8_t debug_level = 0;
 
45
 
 
46
/* "-g" is the command line switch for the gateway class,
 
47
 * 0 no gateway
 
48
 * 1 modem
 
49
 * 2 ISDN
 
50
 * 3 Double ISDN
 
51
 * 3 256 KBit
 
52
 * 5 UMTS/ 0.5 MBit
 
53
 * 6 1 MBit
 
54
 * 7 2 MBit
 
55
 * 8 3 MBit
 
56
 * 9 5 MBit
 
57
 * 10 6 MBit
 
58
 * 11 >6 MBit
 
59
 * this option is used to determine packet path
 
60
 */
 
61
 
 
62
char *gw2string[] = { "No Gateway",
 
63
                      "56 KBit (e.g. Modem)",
 
64
                      "64 KBit (e.g. ISDN)",
 
65
                      "128 KBit (e.g. double ISDN)",
 
66
                      "256 KBit",
 
67
                      "512 KBit (e.g. UMTS)",
 
68
                      "1 MBit",
 
69
                      "2 MBit",
 
70
                      "3 MBit",
 
71
                      "5 MBit",
 
72
                      "6 MBit",
 
73
                      ">6 MBit" };
 
74
 
 
75
uint8_t gateway_class = 0;
 
76
 
 
77
/* "-r" is the command line switch for the routing class,
 
78
 * 0 set no default route
 
79
 * 1 use fast internet connection
 
80
 * 2 use stable internet connection
 
81
 * 3 use use best statistic (olsr style)
 
82
 * this option is used to set the routing behaviour
 
83
 */
 
84
 
 
85
uint8_t routing_class = 0;
 
86
 
 
87
 
 
88
int16_t orginator_interval = 1000;   /* orginator message interval in miliseconds */
 
89
 
 
90
struct gw_node *curr_gateway = NULL;
 
91
pthread_t curr_gateway_thread_id = 0;
 
92
pthread_mutex_t curr_gw_mutex = PTHREAD_MUTEX_INITIALIZER;
 
93
 
 
94
uint32_t pref_gateway = 0;
 
95
 
 
96
unsigned char *hna_buff = NULL;
 
97
 
 
98
uint8_t num_hna = 0;
 
99
 
 
100
uint8_t found_ifs = 0;
 
101
int32_t receive_max_sock = 0;
 
102
fd_set receive_wait_set;
 
103
 
 
104
uint8_t unix_client = 0;
 
105
 
 
106
struct hashtable_t *orig_hash;
 
107
 
 
108
LIST_HEAD(forw_list);
 
109
LIST_HEAD(gw_list);
 
110
LIST_HEAD(if_list);
 
111
LIST_HEAD(hna_list);
 
112
 
 
113
struct vis_if vis_if;
 
114
struct unix_if unix_if;
 
115
struct debug_clients debug_clients;
 
116
 
 
117
unsigned char *vis_packet = NULL;
 
118
uint16_t vis_packet_size = 0;
 
119
 
 
120
 
 
121
 
 
122
void usage( void ) {
 
123
 
 
124
        fprintf( stderr, "Usage: batman [options] interface [interface interface]\n" );
 
125
        fprintf( stderr, "       -a announce network(s)\n" );
 
126
        fprintf( stderr, "       -b run connection in batch mode\n" );
 
127
        fprintf( stderr, "       -c connect via unix socket\n" );
 
128
        fprintf( stderr, "       -d debug level\n" );
 
129
        fprintf( stderr, "       -g gateway class\n" );
 
130
        fprintf( stderr, "       -h this help\n" );
 
131
        fprintf( stderr, "       -H verbose help\n" );
 
132
        fprintf( stderr, "       -o orginator interval in ms\n" );
 
133
        fprintf( stderr, "       -p preferred gateway\n" );
 
134
        fprintf( stderr, "       -r routing class\n" );
 
135
        fprintf( stderr, "       -s visualisation server\n" );
 
136
        fprintf( stderr, "       -v print version\n" );
 
137
 
 
138
}
 
139
 
 
140
 
 
141
 
 
142
void verbose_usage( void ) {
 
143
 
 
144
        fprintf( stderr, "Usage: batman [options] interface [interface interface]\n\n" );
 
145
        fprintf( stderr, "       -a announce network(s)\n" );
 
146
        fprintf( stderr, "          network/netmask is expected\n" );
 
147
        fprintf( stderr, "       -b run connection in batch mode\n" );
 
148
        fprintf( stderr, "       -c connect to running batmand via unix socket\n" );
 
149
        fprintf( stderr, "       -d debug level\n" );
 
150
        fprintf( stderr, "          default:         0 -> debug disabled\n" );
 
151
        fprintf( stderr, "          allowed values:  1 -> list neighbours\n" );
 
152
        fprintf( stderr, "                           2 -> list gateways\n" );
 
153
        fprintf( stderr, "                           3 -> observe batman\n" );
 
154
        fprintf( stderr, "                           4 -> observe batman (very verbose)\n\n" );
 
155
        fprintf( stderr, "       -g gateway class\n" );
 
156
        fprintf( stderr, "          default:         0 -> this is not an internet gateway\n" );
 
157
        fprintf( stderr, "          allowed values:  1 -> modem line\n" );
 
158
        fprintf( stderr, "                           2 -> ISDN line\n" );
 
159
        fprintf( stderr, "                           3 -> double ISDN\n" );
 
160
        fprintf( stderr, "                           4 -> 256 KBit\n" );
 
161
        fprintf( stderr, "                           5 -> UMTS / 0.5 MBit\n" );
 
162
        fprintf( stderr, "                           6 -> 1 MBit\n" );
 
163
        fprintf( stderr, "                           7 -> 2 MBit\n" );
 
164
        fprintf( stderr, "                           8 -> 3 MBit\n" );
 
165
        fprintf( stderr, "                           9 -> 5 MBit\n" );
 
166
        fprintf( stderr, "                          10 -> 6 MBit\n" );
 
167
        fprintf( stderr, "                          11 -> >6 MBit\n\n" );
 
168
        fprintf( stderr, "       -h shorter help\n" );
 
169
        fprintf( stderr, "       -H this help\n" );
 
170
        fprintf( stderr, "       -o orginator interval in ms\n" );
 
171
        fprintf( stderr, "          default: 1000, allowed values: >0\n\n" );
 
172
        fprintf( stderr, "       -p preferred gateway\n" );
 
173
        fprintf( stderr, "          default: none, allowed values: IP\n\n" );
 
174
        fprintf( stderr, "       -r routing class (only needed if gateway class = 0)\n" );
 
175
        fprintf( stderr, "          default:         0 -> set no default route\n" );
 
176
        fprintf( stderr, "          allowed values:  1 -> use fast internet connection\n" );
 
177
        fprintf( stderr, "                           2 -> use stable internet connection\n" );
 
178
        fprintf( stderr, "                           3 -> use best statistic internet connection (olsr style)\n\n" );
 
179
        fprintf( stderr, "       -s visualisation server\n" );
 
180
        fprintf( stderr, "          default: none, allowed values: IP\n\n" );
 
181
        fprintf( stderr, "       -v print version\n" );
 
182
 
 
183
}
 
184
 
 
185
 
 
186
 
 
187
void add_del_hna( struct orig_node *orig_node, int8_t del ) {
 
188
 
 
189
        uint16_t hna_buff_count = 0;
 
190
        uint32_t hna, netmask;
 
191
 
 
192
 
 
193
        while ( ( hna_buff_count + 1 ) * 5 <= orig_node->hna_buff_len ) {
 
194
 
 
195
                memcpy( &hna, ( uint32_t *)&orig_node->hna_buff[ hna_buff_count * 5 ], 4 );
 
196
                netmask = ( uint32_t )orig_node->hna_buff[ ( hna_buff_count * 5 ) + 4 ];
 
197
 
 
198
                if ( ( netmask > 0 ) && ( netmask < 33 ) )
 
199
                        add_del_route( hna, netmask, orig_node->router->addr, del, orig_node->batman_if->dev, orig_node->batman_if->udp_send_sock );
 
200
 
 
201
                hna_buff_count++;
 
202
 
 
203
        }
 
204
 
 
205
        if ( del ) {
 
206
 
 
207
                debugFree( orig_node->hna_buff, 1101 );
 
208
                orig_node->hna_buff_len = 0;
 
209
 
 
210
        }
 
211
 
 
212
}
 
213
 
 
214
 
 
215
 
 
216
void choose_gw() {
 
217
 
 
218
        prof_start( PROF_choose_gw );
 
219
        struct list_head *pos;
 
220
        struct gw_node *gw_node, *tmp_curr_gw = NULL;
 
221
        uint8_t max_gw_class = 0, max_packets = 0, max_gw_factor = 0;
 
222
        static char orig_str[ADDR_STR_LEN];
 
223
 
 
224
 
 
225
        if ( routing_class == 0 ) {
 
226
 
 
227
                prof_stop( PROF_choose_gw );
 
228
                return;
 
229
 
 
230
        }
 
231
 
 
232
        if ( list_empty(&gw_list) ) {
 
233
 
 
234
                if ( curr_gateway != NULL ) {
 
235
 
 
236
                        debug_output( 3, "Removing default route - no gateway in range \n" );
 
237
 
 
238
                        del_default_route();
 
239
 
 
240
                }
 
241
 
 
242
                prof_stop( PROF_choose_gw );
 
243
                return;
 
244
 
 
245
        }
 
246
 
 
247
 
 
248
        list_for_each(pos, &gw_list) {
 
249
 
 
250
                gw_node = list_entry(pos, struct gw_node, list);
 
251
 
 
252
                /* ignore this gateway if recent connection attempts were unsuccessful */
 
253
                if ( ( gw_node->unavail_factor * gw_node->unavail_factor * 30000 ) + gw_node->last_failure > get_time() )
 
254
                        continue;
 
255
 
 
256
                if ( gw_node->orig_node->router == NULL )
 
257
                        continue;
 
258
 
 
259
                if ( gw_node->deleted )
 
260
                        continue;
 
261
 
 
262
                switch ( routing_class ) {
 
263
 
 
264
                        case 1:   /* fast connection */
 
265
                                if ( ( ( gw_node->orig_node->router->packet_count * gw_node->orig_node->gwflags ) > max_gw_factor ) || ( ( ( gw_node->orig_node->router->packet_count * gw_node->orig_node->gwflags ) == max_gw_factor ) && ( gw_node->orig_node->router->packet_count > max_packets ) ) )
 
266
                                        tmp_curr_gw = gw_node;
 
267
                                break;
 
268
 
 
269
                        case 2:   /* stable connection */
 
270
                                /* FIXME - not implemented yet */
 
271
                                if ( ( ( gw_node->orig_node->router->packet_count * gw_node->orig_node->gwflags ) > max_gw_factor ) || ( ( ( gw_node->orig_node->router->packet_count * gw_node->orig_node->gwflags ) == max_gw_factor ) && ( gw_node->orig_node->router->packet_count > max_packets ) ) )
 
272
                                        tmp_curr_gw = gw_node;
 
273
                                break;
 
274
 
 
275
                        default:  /* use best statistic (olsr style) */
 
276
                                if ( gw_node->orig_node->router->packet_count > max_packets )
 
277
                                        tmp_curr_gw = gw_node;
 
278
                                break;
 
279
 
 
280
                }
 
281
 
 
282
                if ( gw_node->orig_node->gwflags > max_gw_class )
 
283
                        max_gw_class = gw_node->orig_node->gwflags;
 
284
 
 
285
                if ( gw_node->orig_node->router->packet_count > max_packets )
 
286
                        max_packets = gw_node->orig_node->router->packet_count;
 
287
 
 
288
                if ( ( gw_node->orig_node->router->packet_count * gw_node->orig_node->gwflags ) > max_gw_class )
 
289
                        max_gw_factor = ( gw_node->orig_node->router->packet_count * gw_node->orig_node->gwflags );
 
290
 
 
291
                if ( ( pref_gateway != 0 ) && ( pref_gateway == gw_node->orig_node->orig ) ) {
 
292
 
 
293
                        tmp_curr_gw = gw_node;
 
294
 
 
295
                        addr_to_string( tmp_curr_gw->orig_node->orig, orig_str, ADDR_STR_LEN );
 
296
                        debug_output( 3, "Preferred gateway found: %s (%i,%i,%i) \n", orig_str, gw_node->orig_node->gwflags, gw_node->orig_node->router->packet_count, ( gw_node->orig_node->router->packet_count * gw_node->orig_node->gwflags ) );
 
297
 
 
298
                        break;
 
299
 
 
300
                }
 
301
 
 
302
        }
 
303
 
 
304
 
 
305
        if ( curr_gateway != tmp_curr_gw ) {
 
306
 
 
307
                if ( pthread_mutex_trylock( &curr_gw_mutex ) == 0 ) {
 
308
 
 
309
                        if ( curr_gateway != NULL ) {
 
310
 
 
311
                                debug_output( 3, "Removing default route - better gateway found \n" );
 
312
 
 
313
                                del_default_route();
 
314
 
 
315
                        }
 
316
 
 
317
                        curr_gateway = tmp_curr_gw;
 
318
 
 
319
                        /* may be the last gateway is now gone */
 
320
                        if ( ( curr_gateway != NULL ) && ( !is_aborted() ) ) {
 
321
 
 
322
                                addr_to_string( curr_gateway->orig_node->orig, orig_str, ADDR_STR_LEN );
 
323
                                debug_output( 3, "Adding default route to %s (%i,%i,%i) \n", orig_str, max_gw_class, max_packets, max_gw_factor );
 
324
 
 
325
                                add_default_route();
 
326
 
 
327
                        }
 
328
 
 
329
                        if ( pthread_mutex_unlock( &curr_gw_mutex ) < 0 )
 
330
                                debug_output( 0, "Error - could not unlock mutex (choose_gw): %s \n", strerror( errno ) );
 
331
 
 
332
                } else {
 
333
 
 
334
                        debug_output( 0, "Warning - could not change default route (mutex locked): %s \n", strerror( EBUSY ) );
 
335
 
 
336
                }
 
337
 
 
338
        }
 
339
 
 
340
        prof_stop( PROF_choose_gw );
 
341
 
 
342
}
 
343
 
 
344
 
 
345
 
 
346
void update_routes( struct orig_node *orig_node, struct neigh_node *neigh_node, unsigned char *hna_recv_buff, int16_t hna_buff_len ) {
 
347
 
 
348
        prof_start( PROF_update_routes );
 
349
        static char orig_str[ADDR_STR_LEN], next_str[ADDR_STR_LEN];
 
350
 
 
351
 
 
352
        debug_output( 4, "update_routes() \n" );
 
353
 
 
354
 
 
355
        if ( ( orig_node != NULL ) && ( orig_node->router != neigh_node ) ) {
 
356
 
 
357
                if ( ( orig_node != NULL ) && ( neigh_node != NULL ) ) {
 
358
                        addr_to_string( orig_node->orig, orig_str, ADDR_STR_LEN );
 
359
                        addr_to_string( neigh_node->addr, next_str, ADDR_STR_LEN );
 
360
                        debug_output( 4, "Route to %s via %s \n", orig_str, next_str );
 
361
                }
 
362
 
 
363
                /* route altered or deleted */
 
364
                if ( ( ( orig_node->router != NULL ) && ( neigh_node != NULL ) ) || ( neigh_node == NULL ) ) {
 
365
 
 
366
                        if ( neigh_node == NULL ) {
 
367
                                debug_output( 4, "Deleting previous route \n" );
 
368
                        } else {
 
369
                                debug_output( 4, "Route changed \n" );
 
370
                        }
 
371
 
 
372
                        /* remove old announced network(s) */
 
373
                        if ( orig_node->hna_buff_len > 0 )
 
374
                                add_del_hna( orig_node, 1 );
 
375
 
 
376
                        add_del_route( orig_node->orig, 32, orig_node->router->addr, 1, orig_node->batman_if->dev, orig_node->batman_if->udp_send_sock );
 
377
 
 
378
                }
 
379
 
 
380
                /* route altered or new route added */
 
381
                if ( ( ( orig_node->router != NULL ) && ( neigh_node != NULL ) ) || ( orig_node->router == NULL ) ) {
 
382
 
 
383
                        if ( orig_node->router == NULL ) {
 
384
                                debug_output( 4, "Adding new route \n" );
 
385
                        } else {
 
386
                                debug_output( 4, "Route changed \n" );
 
387
                        }
 
388
 
 
389
                        add_del_route( orig_node->orig, 32, neigh_node->addr, 0, neigh_node->if_incoming->dev, neigh_node->if_incoming->udp_send_sock );
 
390
 
 
391
                        orig_node->batman_if = neigh_node->if_incoming;
 
392
                        orig_node->router = neigh_node;
 
393
 
 
394
                        /* add new announced network(s) */
 
395
                        if ( hna_buff_len > 0 ) {
 
396
 
 
397
                                orig_node->hna_buff = debugMalloc( hna_buff_len, 101 );
 
398
                                orig_node->hna_buff_len = hna_buff_len;
 
399
 
 
400
                                memmove( orig_node->hna_buff, hna_recv_buff, hna_buff_len );
 
401
 
 
402
                                add_del_hna( orig_node, 0 );
 
403
 
 
404
                        }
 
405
 
 
406
                }
 
407
 
 
408
                orig_node->router = neigh_node;
 
409
 
 
410
        } else if ( orig_node != NULL ) {
 
411
 
 
412
                /* may be just HNA changed */
 
413
                if ( ( hna_buff_len != orig_node->hna_buff_len ) || ( ( hna_buff_len > 0 ) && ( orig_node->hna_buff_len > 0 ) && ( memcmp( orig_node->hna_buff, hna_recv_buff, hna_buff_len ) != 0 ) ) ) {
 
414
 
 
415
                        if ( orig_node->hna_buff_len > 0 )
 
416
                                add_del_hna( orig_node, 1 );
 
417
 
 
418
                        if ( hna_buff_len > 0 ) {
 
419
 
 
420
                                orig_node->hna_buff = debugMalloc( hna_buff_len, 102 );
 
421
                                orig_node->hna_buff_len = hna_buff_len;
 
422
 
 
423
                                memcpy( orig_node->hna_buff, hna_recv_buff, hna_buff_len );
 
424
 
 
425
                                add_del_hna( orig_node, 0 );
 
426
 
 
427
                        }
 
428
 
 
429
                }
 
430
 
 
431
        }
 
432
 
 
433
        prof_stop( PROF_update_routes );
 
434
 
 
435
}
 
436
 
 
437
 
 
438
 
 
439
void update_gw_list( struct orig_node *orig_node, uint8_t new_gwflags ) {
 
440
 
 
441
        prof_start( PROF_update_gw_list );
 
442
        struct list_head *gw_pos, *gw_pos_tmp;
 
443
        struct gw_node *gw_node;
 
444
        static char orig_str[ADDR_STR_LEN];
 
445
 
 
446
        list_for_each_safe( gw_pos, gw_pos_tmp, &gw_list ) {
 
447
 
 
448
                gw_node = list_entry(gw_pos, struct gw_node, list);
 
449
 
 
450
                if ( gw_node->orig_node == orig_node ) {
 
451
 
 
452
                        addr_to_string( gw_node->orig_node->orig, orig_str, ADDR_STR_LEN );
 
453
                        debug_output( 3, "Gateway class of originator %s changed from %i to %i \n", orig_str, gw_node->orig_node->gwflags, new_gwflags );
 
454
 
 
455
                        if ( new_gwflags == 0 ) {
 
456
 
 
457
                                gw_node->deleted = get_time();
 
458
 
 
459
                                debug_output( 3, "Gateway %s removed from gateway list \n", orig_str );
 
460
 
 
461
                        } else {
 
462
 
 
463
                                gw_node->deleted = 0;
 
464
                                gw_node->orig_node->gwflags = new_gwflags;
 
465
 
 
466
                        }
 
467
 
 
468
                        prof_stop( PROF_update_gw_list );
 
469
                        choose_gw();
 
470
                        return;
 
471
 
 
472
                }
 
473
 
 
474
        }
 
475
 
 
476
        addr_to_string( orig_node->orig, orig_str, ADDR_STR_LEN );
 
477
        debug_output( 3, "Found new gateway %s -> class: %i - %s \n", orig_str, new_gwflags, gw2string[new_gwflags] );
 
478
 
 
479
        gw_node = debugMalloc( sizeof(struct gw_node), 103 );
 
480
        memset( gw_node, 0, sizeof(struct gw_node) );
 
481
        INIT_LIST_HEAD( &gw_node->list );
 
482
 
 
483
        gw_node->orig_node = orig_node;
 
484
        gw_node->unavail_factor = 0;
 
485
        gw_node->last_failure = get_time();
 
486
 
 
487
        list_add_tail( &gw_node->list, &gw_list );
 
488
 
 
489
        prof_stop( PROF_update_gw_list );
 
490
 
 
491
        choose_gw();
 
492
 
 
493
}
 
494
 
 
495
 
 
496
 
 
497
int isDuplicate( struct orig_node *orig_node, uint16_t seqno ) {
 
498
 
 
499
        prof_start( PROF_is_duplicate );
 
500
        struct list_head *neigh_pos;
 
501
        struct neigh_node *neigh_node;
 
502
 
 
503
        list_for_each( neigh_pos, &orig_node->neigh_list ) {
 
504
 
 
505
                neigh_node = list_entry( neigh_pos, struct neigh_node, list );
 
506
 
 
507
                if ( get_bit_status( neigh_node->seq_bits, orig_node->last_seqno, seqno ) ) {
 
508
 
 
509
                        prof_stop( PROF_is_duplicate );
 
510
                        return 1;
 
511
 
 
512
                }
 
513
 
 
514
        }
 
515
 
 
516
        prof_stop( PROF_is_duplicate );
 
517
 
 
518
        return 0;
 
519
 
 
520
}
 
521
 
 
522
int isBntog( uint32_t neigh, struct orig_node *orig_tog_node ) {
 
523
 
 
524
        if ( ( orig_tog_node->router != NULL ) && ( orig_tog_node->router->addr == neigh ) )
 
525
                return 1;
 
526
 
 
527
        return 0;
 
528
 
 
529
}
 
530
 
 
531
int isBidirectionalNeigh( struct orig_node *orig_neigh_node, struct batman_if *if_incoming ) {
 
532
 
 
533
        if ( ( if_incoming->out.seqno - 2 - orig_neigh_node->bidirect_link[if_incoming->if_num] ) <  BIDIRECT_TIMEOUT )
 
534
                return 1;
 
535
 
 
536
        return 0;
 
537
 
 
538
}
 
539
 
 
540
 
 
541
 
 
542
void generate_vis_packet() {
 
543
 
 
544
        struct hash_it_t *hashit = NULL;
 
545
        struct orig_node *orig_node;
 
546
 
 
547
 
 
548
        if ( vis_packet != NULL ) {
 
549
 
 
550
                debugFree( vis_packet, 1102 );
 
551
                vis_packet = NULL;
 
552
                vis_packet_size = 0;
 
553
 
 
554
        }
 
555
 
 
556
        /* sender ip and gateway class */
 
557
        vis_packet_size = 6;
 
558
        vis_packet = debugMalloc( vis_packet_size, 104 );
 
559
 
 
560
        memcpy( vis_packet, (unsigned char *)&(((struct batman_if *)if_list.next)->addr.sin_addr.s_addr), 4 );
 
561
        vis_packet[4] = gateway_class;
 
562
        vis_packet[5] = SEQ_RANGE;
 
563
 
 
564
 
 
565
        while ( NULL != ( hashit = hash_iterate( orig_hash, hashit ) ) ) {
 
566
 
 
567
                orig_node = hashit->bucket->data;
 
568
 
 
569
                /* we interested in 1 hop neighbours only */
 
570
                if ( ( orig_node->router != NULL ) && ( orig_node->orig == orig_node->router->addr ) ) {
 
571
 
 
572
                        /* neighbour ip and packet count */
 
573
                        vis_packet_size += 5;
 
574
 
 
575
                        vis_packet = debugRealloc( vis_packet, vis_packet_size, 105 );
 
576
 
 
577
                        memcpy( vis_packet + vis_packet_size - 5, (unsigned char *)&orig_node->orig, 4 );
 
578
 
 
579
                        vis_packet[vis_packet_size - 1] = orig_node->router->packet_count;
 
580
 
 
581
                }
 
582
 
 
583
        }
 
584
 
 
585
        if ( vis_packet_size == 6 ) {
 
586
 
 
587
                debugFree( vis_packet, 1107 );
 
588
                vis_packet = NULL;
 
589
                vis_packet_size = 0;
 
590
 
 
591
        }
 
592
 
 
593
}
 
594
 
 
595
 
 
596
 
 
597
void send_vis_packet() {
 
598
 
 
599
        generate_vis_packet();
 
600
 
 
601
        if ( vis_packet != NULL )
 
602
                send_packet( vis_packet, vis_packet_size, &vis_if.addr, vis_if.sock );
 
603
 
 
604
}
 
605
 
 
606
 
 
607
 
 
608
int8_t batman() {
 
609
 
 
610
        struct list_head *if_pos, *neigh_pos, *hna_pos, *hna_pos_tmp, *forw_pos, *forw_pos_tmp;
 
611
        struct orig_node *orig_neigh_node, *orig_node;
 
612
        struct batman_if *batman_if, *if_incoming;
 
613
        struct neigh_node *neigh_node;
 
614
        struct hna_node *hna_node;
 
615
        struct forw_node *forw_node;
 
616
        uint32_t neigh, hna, netmask, debug_timeout, vis_timeout, select_timeout, curr_time, rcvd_time;
 
617
        unsigned char in[1501], *hna_recv_buff;
 
618
        static char orig_str[ADDR_STR_LEN], neigh_str[ADDR_STR_LEN], ifaddr_str[ADDR_STR_LEN];
 
619
        int16_t hna_buff_count, hna_buff_len;
 
620
        uint8_t forward_old, if_rp_filter_all_old, if_rp_filter_default_old, if_send_redirects_all_old, if_send_redirects_default_old;
 
621
        uint8_t is_my_addr, is_my_orig, is_broadcast, is_duplicate, is_bidirectional, is_bntog, is_directNeigh, forward_duplicate_packet, has_unidirectional_flag, has_directlink_flag, has_version;
 
622
        int8_t res;
 
623
 
 
624
 
 
625
        debug_timeout = vis_timeout = get_time();
 
626
        get_uptime_sec();
 
627
 
 
628
 
 
629
        if ( NULL == ( orig_hash = hash_new( 128, compare_orig, choose_orig ) ) )
 
630
                return(-1);
 
631
 
 
632
        /* for profiling the functions */
 
633
        prof_init( PROF_choose_gw, "choose_gw" );
 
634
        prof_init( PROF_update_routes, "update_routes" );
 
635
        prof_init( PROF_update_gw_list, "update_gw_list" );
 
636
        prof_init( PROF_is_duplicate, "isDuplicate" );
 
637
        prof_init( PROF_get_orig_node, "get_orig_node" );
 
638
        prof_init( PROF_update_originator, "update_orig" );
 
639
        prof_init( PROF_purge_orginator, "purge_orig" );
 
640
        prof_init( PROF_schedule_forward_packet, "schedule_forward_packet" );
 
641
        prof_init( PROF_send_outstanding_packets, "send_outstanding_packets" );
 
642
 
 
643
        if ( !( list_empty( &hna_list ) ) ) {
 
644
 
 
645
                list_for_each( hna_pos, &hna_list ) {
 
646
 
 
647
                        hna_node = list_entry(hna_pos, struct hna_node, list);
 
648
 
 
649
                        hna_buff = debugRealloc( hna_buff, ( num_hna + 1 ) * 5 * sizeof( unsigned char ), 15 );
 
650
 
 
651
                        memmove( &hna_buff[ num_hna * 5 ], ( unsigned char *)&hna_node->addr, 4 );
 
652
                        hna_buff[ ( num_hna * 5 ) + 4 ] = ( unsigned char ) hna_node->netmask;
 
653
 
 
654
                        num_hna++;
 
655
 
 
656
                }
 
657
 
 
658
        }
 
659
 
 
660
        list_for_each( if_pos, &if_list ) {
 
661
 
 
662
                batman_if = list_entry( if_pos, struct batman_if, list );
 
663
 
 
664
                batman_if->out.orig = batman_if->addr.sin_addr.s_addr;
 
665
                batman_if->out.flags = 0x00;
 
666
                batman_if->out.ttl = TTL;
 
667
                batman_if->out.seqno = 1;
 
668
                batman_if->out.gwflags = gateway_class;
 
669
                batman_if->out.version = COMPAT_VERSION;
 
670
 
 
671
                batman_if->if_rp_filter_old = get_rp_filter( batman_if->dev );
 
672
                set_rp_filter( 0 , batman_if->dev );
 
673
 
 
674
                batman_if->if_send_redirects_old = get_send_redirects( batman_if->dev );
 
675
                set_send_redirects( 0 , batman_if->dev );
 
676
 
 
677
                schedule_own_packet( batman_if );
 
678
 
 
679
        }
 
680
 
 
681
        if_rp_filter_all_old = get_rp_filter( "all" );
 
682
        if_rp_filter_default_old = get_rp_filter( "default" );
 
683
 
 
684
        if_send_redirects_all_old = get_send_redirects( "all" );
 
685
        if_send_redirects_default_old = get_send_redirects( "default" );
 
686
 
 
687
        set_rp_filter( 0, "all" );
 
688
        set_rp_filter( 0, "default" );
 
689
 
 
690
        set_send_redirects( 0, "all" );
 
691
        set_send_redirects( 0, "default" );
 
692
 
 
693
        forward_old = get_forwarding();
 
694
        set_forwarding(1);
 
695
 
 
696
        while ( !is_aborted() ) {
 
697
 
 
698
                debug_output( 4, " \n \n" );
 
699
 
 
700
                /* harden select_timeout against sudden time change (e.g. ntpdate) */
 
701
                curr_time = get_time();
 
702
                select_timeout = ( curr_time < ((struct forw_node *)forw_list.next)->send_time ? ((struct forw_node *)forw_list.next)->send_time - curr_time : 10 );
 
703
 
 
704
                res = receive_packet( ( unsigned char *)&in, sizeof(in), &hna_buff_len, &neigh, select_timeout, &if_incoming );
 
705
 
 
706
                rcvd_time = get_time();
 
707
 
 
708
                if ( res < 0 )
 
709
                        return -1;
 
710
 
 
711
                if ( res > 0 ) {
 
712
 
 
713
 
 
714
                        is_my_addr = is_my_orig = is_broadcast = is_duplicate = is_bidirectional = is_bntog = forward_duplicate_packet = 0;
 
715
 
 
716
                        has_unidirectional_flag =       ((struct packet *)&in)->flags & UNIDIRECTIONAL ? 1 : 0;
 
717
                        has_directlink_flag =           ((struct packet *)&in)->flags & DIRECTLINK ? 1 : 0;
 
718
                        has_version =                   ((struct packet *)&in)->version;
 
719
 
 
720
                        addr_to_string( ((struct packet *)&in)->orig, orig_str, sizeof(orig_str) );
 
721
                        addr_to_string( neigh, neigh_str, sizeof(neigh_str) );
 
722
                        addr_to_string( if_incoming->addr.sin_addr.s_addr, ifaddr_str, sizeof(ifaddr_str) );
 
723
 
 
724
                        debug_output( 4, "Received BATMAN packet via NB: %s, IF: %s %s (from OG: %s, seqno %d, TTL %d, V %d, UDF %d, IDF %d) \n",
 
725
                                        neigh_str, if_incoming->dev, ifaddr_str, orig_str, ((struct packet *)&in)->seqno, ((struct packet *)&in)->ttl,
 
726
                                        has_version, has_unidirectional_flag, has_directlink_flag );
 
727
 
 
728
                        hna_buff_len -= sizeof(struct packet);
 
729
                        hna_recv_buff = ( hna_buff_len > 4 ? in + sizeof(struct packet) : NULL );
 
730
 
 
731
                        list_for_each( if_pos, &if_list ) {
 
732
 
 
733
                                batman_if = list_entry(if_pos, struct batman_if, list);
 
734
 
 
735
                                if ( neigh == batman_if->addr.sin_addr.s_addr )
 
736
                                        is_my_addr = 1;
 
737
 
 
738
                                if ( ((struct packet *)&in)->orig == batman_if->addr.sin_addr.s_addr )
 
739
                                        is_my_orig = 1;
 
740
 
 
741
                                if ( neigh == batman_if->broad.sin_addr.s_addr )
 
742
                                        is_broadcast = 1;
 
743
 
 
744
                        }
 
745
 
 
746
 
 
747
                        if ( ((struct packet *)&in)->gwflags != 0 )
 
748
                                debug_output( 4, "Is an internet gateway (class %i) \n", ((struct packet *)&in)->gwflags );
 
749
 
 
750
                        if ( hna_buff_len > 4 ) {
 
751
 
 
752
                                debug_output( 4, "HNA information received (%i HNA network%s): \n", hna_buff_len / 5, ( hna_buff_len / 5 > 1 ? "s": "" ) );
 
753
                                hna_buff_count = 0;
 
754
 
 
755
                                while ( ( hna_buff_count + 1 ) * 5 <= hna_buff_len ) {
 
756
 
 
757
                                        memmove( &hna, ( uint32_t *)&hna_recv_buff[ hna_buff_count * 5 ], 4 );
 
758
                                        netmask = ( uint32_t )hna_recv_buff[ ( hna_buff_count * 5 ) + 4 ];
 
759
 
 
760
                                        addr_to_string( hna, orig_str, sizeof (orig_str) );
 
761
 
 
762
                                        if ( ( netmask > 0 ) && ( netmask < 33 ) )
 
763
                                                debug_output( 4, "hna: %s/%i \n", orig_str, netmask );
 
764
                                        else
 
765
                                                debug_output( 4, "hna: %s/%i -> ignoring (invalid netmask) \n", orig_str, netmask );
 
766
 
 
767
                                        hna_buff_count++;
 
768
 
 
769
                                }
 
770
 
 
771
                        }
 
772
 
 
773
 
 
774
                        if ( ((struct packet *)&in)->version != COMPAT_VERSION ) {
 
775
 
 
776
                                debug_output( 4, "Drop packet: incompatible batman version (%i) \n", ((struct packet *)&in)->version );
 
777
 
 
778
                        } else if ( is_my_addr ) {
 
779
 
 
780
                                debug_output( 4, "Drop packet: received my own broadcast (sender: %s) \n", neigh_str );
 
781
 
 
782
                        } else if ( is_broadcast ) {
 
783
 
 
784
                                debug_output( 4, "Drop packet: ignoring all packets with broadcast source IP (sender: %s) \n", neigh_str );
 
785
 
 
786
                        } else if ( is_my_orig ) {
 
787
 
 
788
                                orig_neigh_node = get_orig_node( neigh );
 
789
 
 
790
 
 
791
                                debug_output( 4, "received my own OGM via NB lastTxIfSeqno: %d, currRxSeqno: %d, prevRxSeqno: %d, currRxSeqno-prevRxSeqno %d \n",
 
792
                                                                (if_incoming->out.seqno - 2), ((struct packet *)&in)->seqno, orig_neigh_node->bidirect_link[if_incoming->if_num], ((struct packet *)&in)->seqno - orig_neigh_node->bidirect_link[if_incoming->if_num] );
 
793
 
 
794
                                /* neighbour has to indicate direct link and it has to come via the corresponding interface */
 
795
                                /* if received seqno equals last send seqno save new seqno for bidirectional check */
 
796
                                if ( ( has_directlink_flag ) && ( if_incoming->addr.sin_addr.s_addr == ((struct packet *)&in)->orig ) &&
 
797
                                        ( ( ((struct packet *)&in)->seqno + 2) == if_incoming->out.seqno  ) ) {
 
798
                                        debug_output( 4, "indicating bidirectional link - updating bidirect_link seqno \n");
 
799
 
 
800
                                        orig_neigh_node->bidirect_link[if_incoming->if_num] = ((struct packet *)&in)->seqno;
 
801
 
 
802
 
 
803
                                } else {
 
804
                                        debug_output( 4, "NOT indicating bidirectional link - NOT updating bidirect_link seqno  \n");
 
805
 
 
806
                                }
 
807
 
 
808
                                debug_output( 4, "Drop packet: originator packet from myself (via neighbour) \n" );
 
809
 
 
810
                        } else if ( ((struct packet *)&in)->flags & UNIDIRECTIONAL ) {
 
811
 
 
812
                                debug_output( 4, "Drop packet: originator packet with unidirectional flag \n" );
 
813
 
 
814
                        } else {
 
815
 
 
816
                                is_directNeigh = ( ((struct packet *)&in)->orig == neigh ) ? 1 : 0 ;
 
817
 
 
818
                                orig_node = get_orig_node( ((struct packet *)&in)->orig );
 
819
 
 
820
                                if( is_directNeigh ) {
 
821
 
 
822
                                        orig_neigh_node = orig_node;
 
823
 
 
824
                                } else {
 
825
 
 
826
                                        orig_neigh_node = get_orig_node( neigh );
 
827
 
 
828
                                }
 
829
 
 
830
                                if ( is_directNeigh == 0 && orig_neigh_node->router == NULL ) {
 
831
 
 
832
                                        debug_output( 4, "Drop packet: OGM via unkown neighbor! \n" );
 
833
 
 
834
                                } else {
 
835
 
 
836
                                        is_duplicate = isDuplicate( orig_node, ((struct packet *)&in)->seqno );
 
837
 
 
838
                                        is_bidirectional = isBidirectionalNeigh( orig_neigh_node, if_incoming );
 
839
 
 
840
                                        /* update ranking */
 
841
                                        if ( ( is_bidirectional ) && ( !is_duplicate ) )
 
842
                                        update_orig( orig_node, (struct packet *)&in, neigh, if_incoming, hna_recv_buff, hna_buff_len, rcvd_time );
 
843
 
 
844
                                        is_bntog = isBntog(neigh, orig_node );
 
845
 
 
846
                                        /* is single hop (direct) neighbour */
 
847
                                        if ( is_directNeigh ) {
 
848
 
 
849
                                                /* it is our best route towards him */
 
850
                                                if ( is_bidirectional && is_bntog ) {
 
851
 
 
852
                                                        /* mark direct link on incoming interface */
 
853
                                                        schedule_forward_packet( (struct packet *)&in, 0, 1, hna_recv_buff, hna_buff_len, if_incoming );
 
854
 
 
855
                                                        debug_output( 4, "Forward packet: rebroadcast neighbour packet with direct link flag \n" );
 
856
 
 
857
                                                        /* if an unidirectional neighbour sends us a packet - retransmit it with unidirectional flag to tell him that we get its packets */
 
858
                                                        /* if a bidirectional neighbour sends us a packet - retransmit it with unidirectional flag if it is not our best link to it in order to prevent routing problems */
 
859
                                                } else if ( ( is_bidirectional && !is_bntog ) || ( !is_bidirectional ) ) {
 
860
 
 
861
                                                        schedule_forward_packet( (struct packet *)&in, 1, 1, hna_recv_buff, hna_buff_len, if_incoming );
 
862
 
 
863
                                                        debug_output( 4, "Forward packet: rebroadcast neighbour packet with direct link and unidirectional flag \n" );
 
864
 
 
865
                                                }
 
866
 
 
867
                                        /* multihop orginator */
 
868
                                        } else {
 
869
 
 
870
                                                if ( is_bidirectional && is_bntog ) {
 
871
 
 
872
                                                        if ( !is_duplicate ) {
 
873
 
 
874
                                                                schedule_forward_packet( (struct packet *)&in, 0, 0, hna_recv_buff, hna_buff_len, if_incoming );
 
875
 
 
876
                                                                debug_output( 4, "Forward packet: rebroadcast orginator packet \n" );
 
877
 
 
878
                                                        } else { /* is_bntog anyway */
 
879
 
 
880
                                                                list_for_each( neigh_pos, &orig_node->neigh_list ) {
 
881
 
 
882
                                                                        neigh_node = list_entry(neigh_pos, struct neigh_node, list);
 
883
 
 
884
                                                                        if ( ( neigh_node->addr == neigh ) && ( neigh_node->if_incoming == if_incoming ) ) {
 
885
 
 
886
                                                                                if ( neigh_node->last_ttl == ((struct packet *)&in)->ttl ) {
 
887
 
 
888
                                                                                        forward_duplicate_packet = 1;
 
889
 
 
890
                                                                                        /* also update only last_valid time if arrived (and rebroadcasted because best neighbor) */
 
891
                                                                                        orig_node->last_valid = rcvd_time;
 
892
                                                                                        neigh_node->last_valid = rcvd_time;
 
893
 
 
894
                                                                                }
 
895
 
 
896
                                                                                break;
 
897
 
 
898
                                                                        }
 
899
 
 
900
                                                                }
 
901
 
 
902
                                                                /* we are forwarding duplicate o-packets if they come via our best neighbour and ttl is valid */
 
903
                                                                if ( forward_duplicate_packet ) {
 
904
 
 
905
                                                                        schedule_forward_packet( (struct packet *)&in, 0, 0, hna_recv_buff, hna_buff_len, if_incoming );
 
906
 
 
907
                                                                        debug_output( 4, "Forward packet: duplicate packet received via best neighbour with best ttl \n" );
 
908
 
 
909
                                                                } else {
 
910
 
 
911
                                                                        debug_output( 4, "Drop packet: duplicate packet received via best neighbour but not best ttl \n" );
 
912
 
 
913
                                                                }
 
914
 
 
915
                                                        }
 
916
 
 
917
                                                } else {
 
918
 
 
919
                                                        debug_output( 4, "Drop packet: received via bidirectional link: %s, BNTOG: %s ! \n",
 
920
                                                                        is_bidirectional?"YES":" NO", is_bntog?"YES":" NO" );
 
921
 
 
922
                                                }
 
923
 
 
924
                                        }
 
925
 
 
926
                                }
 
927
 
 
928
                        }
 
929
 
 
930
                }
 
931
 
 
932
 
 
933
                send_outstanding_packets();
 
934
 
 
935
 
 
936
                get_uptime_sec();
 
937
 
 
938
 
 
939
                if ( debug_timeout + 1000 < rcvd_time ) {
 
940
 
 
941
                        debug_timeout = rcvd_time;
 
942
 
 
943
                        purge_orig( rcvd_time );
 
944
 
 
945
                        debug_orig();
 
946
 
 
947
                        checkIntegrity();
 
948
 
 
949
                        if ( debug_clients.clients_num[2] > 0 )
 
950
                                prof_print();
 
951
 
 
952
                        if ( ( routing_class != 0 ) && ( curr_gateway == NULL ) )
 
953
                                choose_gw();
 
954
 
 
955
                        if ( ( vis_if.sock ) && ( vis_timeout + 10000 < rcvd_time ) ){
 
956
 
 
957
                                vis_timeout = rcvd_time;
 
958
                                send_vis_packet();
 
959
 
 
960
                        }
 
961
 
 
962
                }
 
963
 
 
964
        }
 
965
 
 
966
 
 
967
        if ( debug_level > 0 )
 
968
                printf( "Deleting all BATMAN routes\n" );
 
969
 
 
970
        purge_orig( get_time() + ( 5 * PURGE_TIMEOUT ) + orginator_interval );
 
971
 
 
972
        hash_destroy( orig_hash );
 
973
 
 
974
 
 
975
        list_for_each_safe( hna_pos, hna_pos_tmp, &hna_list ) {
 
976
 
 
977
                hna_node = list_entry(hna_pos, struct hna_node, list);
 
978
 
 
979
                debugFree( hna_node, 1103 );
 
980
 
 
981
        }
 
982
 
 
983
        if ( hna_buff != NULL )
 
984
                debugFree( hna_buff, 1104 );
 
985
 
 
986
 
 
987
        list_for_each_safe( forw_pos, forw_pos_tmp, &forw_list ) {
 
988
                forw_node = list_entry( forw_pos, struct forw_node, list );
 
989
 
 
990
                list_del( forw_pos );
 
991
 
 
992
                debugFree( forw_node->pack_buff, 1105 );
 
993
                debugFree( forw_node, 1106 );
 
994
 
 
995
        }
 
996
 
 
997
        if ( vis_packet != NULL )
 
998
                debugFree( vis_packet, 1108 );
 
999
 
 
1000
        set_forwarding( forward_old );
 
1001
 
 
1002
        list_for_each( if_pos, &if_list ) {
 
1003
 
 
1004
                batman_if = list_entry(if_pos, struct batman_if, list);
 
1005
 
 
1006
                set_rp_filter( batman_if->if_rp_filter_old , batman_if->dev );
 
1007
                set_send_redirects( batman_if->if_send_redirects_old , batman_if->dev );
 
1008
 
 
1009
        }
 
1010
 
 
1011
        set_rp_filter( if_rp_filter_all_old, "all" );
 
1012
        set_rp_filter( if_rp_filter_default_old, "default" );
 
1013
 
 
1014
        set_send_redirects( if_send_redirects_all_old, "all" );
 
1015
        set_send_redirects( if_send_redirects_default_old, "default" );
 
1016
 
 
1017
        return 0;
 
1018
 
 
1019
}