really minor performance-improvement
[olsrd.git] / lib / cl_roam / src / cl_roam.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #include "cl_roam.h"
43 #include "olsr_types.h"
44 #include "ipcalc.h"
45 #include "scheduler.h"
46 #include "olsr.h"
47 #include "olsr_cookie.h"
48 #include "olsr_ip_prefix_list.h"
49 #include "olsr_logging.h"
50
51 #include <stdio.h>
52 #include <string.h>
53 #include <stdlib.h>
54 #include <net/route.h>
55 #include <unistd.h>
56 #include <errno.h>
57 #include <pthread.h>
58 #include "neighbor_table.h"
59 #include "olsr.h"
60 #include "olsr_cfg.h"
61 #include "interfaces.h"
62 #include "olsr_protocol.h"
63 #include "net_olsr.h"
64 #include "link_set.h"
65 #include "ipcalc.h"
66 #include "lq_plugin.h"
67 #include "olsr_cfg_gen.h"
68 #include "common/string.h"
69 #include "olsr_ip_prefix_list.h"
70 #include "olsr_logging.h"
71 #include <netinet/in.h>
72 #include <sys/socket.h>
73 #include <arpa/inet.h>
74
75 #define PLUGIN_INTERFACE_VERSION 5
76
77 static int has_inet_gateway;
78 static struct olsr_cookie_info *event_timer_cookie;
79 static union olsr_ip_addr gw_netmask;
80
81 /**
82  * Plugin interface version
83  * Used by main olsrd to check plugin interface version
84  */
85 int
86 olsrd_plugin_interface_version(void)
87 {
88   return PLUGIN_INTERFACE_VERSION;
89 }
90
91 static const struct olsrd_plugin_parameters plugin_parameters[] = {
92 };
93
94
95
96 typedef struct { 
97         struct in_addr ip;
98         u_int64_t mac;
99         struct in_addr from_node;
100         char is_announced;
101         float last_seen;
102  } guest_client;
103
104
105
106 typedef struct {
107         guest_client *client;
108         struct client_list *list;
109 } client_list;
110
111
112
113
114 client_list *list;
115 struct interface *ifn;
116
117
118
119 void ping(guest_client *);
120
121 void
122 olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
123 {
124   *params = plugin_parameters;
125   *size = ARRAYSIZE(plugin_parameters);
126 }
127
128
129
130 void *PrintHello(void *threadid)
131 {
132    long tid;
133    tid = (long)threadid;
134    printf("Hello World! It's me, thread #%ld!\n", tid);
135    pthread_exit(NULL);
136 }
137
138
139
140
141
142 /**
143  * Initialize plugin
144  * Called after all parameters are passed
145  */
146 int
147 olsrd_plugin_init(void)
148 {
149
150
151   
152   list=(client_list*)malloc( sizeof(client_list) );
153
154
155
156   OLSR_INFO(LOG_PLUGINS, "OLSRD automated Client Roaming Plugin\n");
157
158
159   gw_netmask.v4.s_addr = inet_addr("255.255.255.255");
160
161   has_inet_gateway = 0;
162
163
164   /* create the cookie */
165   event_timer_cookie = olsr_alloc_cookie("cl roam: Event", OLSR_COOKIE_TYPE_TIMER);
166
167   /* Register the GW check */
168   olsr_start_timer(3 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC, &olsr_event, NULL, event_timer_cookie);
169   //system("echo \"1\" ");
170   //pthread_create(&ping_thread, NULL, &do_ping, NULL);
171   //system("echo \"2\" ");
172   //CreateThread(NULL, 0, do_ping, NULL, 0, &ThreadId);
173   //if (pthread_create(&ping_thread, NULL, do_ping, NULL) != 0) {
174    // OLSR_WARN(LOG_PLUGINS, "pthread_create() error");
175    // return 0;
176   //}
177
178
179
180
181
182
183
184   return 1;
185 }
186
187
188
189 int ping_thread(guest_client * target)
190 {
191
192     char ping_command[50];
193
194
195     snprintf(ping_command, sizeof(ping_command), "arping -I ath0 -w 1 -c 1 -q %s", inet_ntoa(target->ip));
196     return system(ping_command);
197
198 }
199
200
201
202 void ping_thread_infinite(guest_client * target)
203 {
204     char ping_command[50];
205
206
207     snprintf(ping_command, sizeof(ping_command), "arping -I ath0 -q %s", inet_ntoa(target->ip));
208     system(ping_command);
209
210 }
211
212
213
214 void ping(guest_client * target)
215 {
216         int rc;
217         pthread_t thread;
218     rc = pthread_create(&thread, NULL, ping_thread, (void *) target   );
219     if (rc){
220        printf("ERROR; return code from pthread_create() is %d\n", rc);
221        exit(-1);
222     }
223 }
224
225 void ping_infinite(guest_client * target)
226 {
227         int rc;
228         pthread_t thread;
229     rc = pthread_create(&thread, NULL, ping_thread_infinite, (void *) target   );
230     if (rc){
231        printf("ERROR; return code from pthread_create() is %d\n", rc);
232        exit(-1);
233     }
234 }
235
236
237
238
239
240
241
242
243 struct olsr_message msg;
244
245
246
247 void add_route(void* guest) {
248
249         guest_client * host = (guest_client *) guest;
250
251         if (ping_thread(host)==0) {
252
253                 OLSR_DEBUG(LOG_PLUGINS, "Adding Route\n");
254                 printf("Added Route\n");
255                 ip_prefix_list_add(&olsr_cnf->hna_entries, &(host->ip), olsr_netmask_to_prefix(&gw_netmask));
256                 host->is_announced=1;
257         } else
258                   printf("Decided not to\n");
259 }
260
261
262
263
264
265 void check_for_route(guest_client * host)
266 {
267
268   if (host->last_seen < 5.0 && ! host->is_announced) {
269           pthread_t add;
270           printf("maybe add something\n");
271           int rc = pthread_create(&add, NULL, add_route, (void *)host);
272           if (rc){
273                    printf("ERROR; return code from pthread_create() is %d\n", rc);
274                    exit(-1);
275                 }
276   } else if ((host->last_seen > 5.0) &&  host->is_announced) {
277       OLSR_DEBUG(LOG_PLUGINS, "Removing Route\n");
278       system("echo \"Entferne route\" ");
279       ip_prefix_list_remove(&olsr_cnf->hna_entries, &(host->ip), olsr_netmask_to_prefix(&gw_netmask), olsr_cnf->ip_version);
280       host->is_announced=0;
281 }
282 }
283
284 void check_client_list(client_list * clist) {
285   if (clist!=NULL && clist->client!=NULL) {
286
287     //ping(clist->client);
288           if(clist->client->is_announced==1)
289                   if( ! check_if_associcated(clist->client))
290                           clist->client->last_seen+=2;
291     check_for_route(clist->client);
292
293
294     check_client_list(clist->list);
295   }
296 }
297
298
299
300 guest_client * get_client_by_mac(client_list * clist, u_int64_t mac) {
301   if (clist!=NULL && clist->client!=NULL) {
302
303     if (clist->client->mac == mac)
304         return clist->client;
305     else
306         return get_client_by_mac(clist->list, mac);
307   }
308   else
309           return NULL;
310 }
311
312
313
314 int ip_is_in_guest_list(client_list * list, guest_client * host) {
315 if (list==NULL)
316   return 0;
317 if (list->client==NULL)
318   return 0;
319 else if (inet_lnaof(list->client->ip) == inet_lnaof(host->ip))
320   return 1;
321 else
322   return ip_is_in_guest_list(list->list, host);
323 }
324
325
326 void check_local_leases(client_list * clist){
327   check_leases(clist,"/var/dhcp.leases" , 1.0);
328 }
329
330
331 void check_leases(client_list * clist, char file[], float def_last_seen) {
332           FILE * fp = fopen(file, "r");
333           char s1[50];
334           char s2[50];
335           char s3[50];
336           char s4[50];
337           long long int one, two, three, four, five, six;
338
339           while (1) {
340                   int parse = fscanf (fp, "%s %llx:%llx:%llx:%llx:%llx:%llx %s %s", s1, &one, &two, &three, &four, &five, &six, s3, s4);
341             if (parse==EOF)
342               break;
343             if(parse==9) {
344             guest_client* user;
345             //printf ("String 3 = %s\n", s3);
346             user = (guest_client*)malloc( sizeof(guest_client) );
347             inet_aton(s3, &(user->ip));
348             user->mac= six | five<<8 | four<<16 | three<<24 | two<<32 | one<<40;
349             user->last_seen=def_last_seen;
350             user->is_announced=0;
351             //printf("last seen on Add %f\n",user->last_seen);
352             add_client_to_list(clist, user);
353
354         }
355           }
356           fclose(fp);
357
358
359         }
360
361
362
363
364 void check_remote_leases(client_list * clist){
365   check_leases(clist,"/tmp/otherclient" , 20.0);
366
367 }
368
369
370
371
372
373 int check_if_associcated(guest_client *client)
374 {
375   FILE * fp = fopen("/proc/net/madwifi/ath0/associated_sta", "r");
376   //FILE * fp = fopen("/home/raphael/tmp/leases", "r");
377   char s1[50];
378   char s2[50];
379   char s3[50];
380   int rssi;
381   float last_rx;
382   int parse;
383
384   long long int one, two, three, four, five, six;
385
386   while (1) {
387     parse = fscanf (fp, "macaddr: <%llx:%llx:%llx:%llx:%llx:%llx>\n", &one, &two, &three, &four, &five, &six);
388     if (parse==EOF || parse!=6)
389       break;
390     if ((six | five<<8 | four<<16 | three<<24 | two<<32 | one<<40)==client->mac) {
391         fclose(fp);
392         return 1;
393     }
394     if (parse==EOF)
395           break;
396     //printf ("rssi = %s\n", s2);
397     parse = fscanf (fp, " last_rx %f\n", &last_rx);
398     if (parse==EOF)
399           break;
400
401   }
402   fclose(fp);
403
404
405 }
406
407
408
409
410
411
412
413
414 // Will be handy to identify when a client roamed to us. Not used yet.
415 void check_associations(client_list * clist){
416   FILE * fp = fopen("/proc/net/madwifi/ath0/associated_sta", "r");
417   //FILE * fp = fopen("/home/raphael/tmp/leases", "r");
418   char s1[50];
419   char s2[50];
420   char s3[50];
421   int rssi;
422   float last_rx;
423   int parse;
424
425   long long int one, two, three, four, five, six;
426
427   while (1) {
428     parse = fscanf (fp, "macaddr: <%llx:%llx:%llx:%llx:%llx:%llx>\n", &one, &two, &three, &four, &five, &six);
429     if (parse==EOF || parse!=6)
430       break;
431     uint64_t mac = six | five<<8 | four<<16 | three<<24 | two<<32 | one<<40;
432     //printf ("macaddr: %llx\n", mac);
433     parse = fscanf (fp, " rssi %s\n", s2);
434     if (parse==EOF)
435           break;
436     //printf ("rssi = %s\n", s2);
437     parse = fscanf (fp, " last_rx %f\n", &last_rx);
438     if (parse==EOF)
439           break;
440     //printf ("last_rx = %f\n", last_rx);
441     guest_client* node = get_client_by_mac(clist, mac);
442     if (node!=NULL) {
443         //printf("Sichtung!\n");
444         node->last_seen=last_rx;
445         //printf("last_seen= %f\n",node->last_seen);
446     }
447
448   }
449   fclose(fp);
450
451
452 }
453
454
455
456
457
458 void add_client_to_list(client_list * clist, guest_client * host) {
459   if (ip_is_in_guest_list(clist,  host)) {
460     free(host);
461   }
462   else {
463     if (clist->client!=NULL) {
464       client_list * this_one;
465       this_one = (client_list *)malloc( sizeof(client_list) );
466       this_one->client = host;
467       this_one->list=clist->list;
468       clist->list=this_one;
469       printf("added something\n");
470     } else {
471       clist->client=host;
472       printf("added something\n");
473     }
474     ping_infinite(host);
475   }
476 }
477
478
479
480
481
482 void check_for_new_clients(client_list * clist) {
483     check_local_leases(clist);
484     check_associations(clist);
485 }
486
487
488
489
490
491 void
492 olsr_event(void *foo __attribute__ ((unused)))
493 {
494         struct nbr_entry *nbr;
495         check_for_new_clients(list);
496     check_client_list(list);
497
498
499
500
501
502     OLSR_FOR_ALL_NBR_ENTRIES(nbr) {
503         union olsr_ip_addr foobar = nbr->nbr_addr;
504
505                 char wget_command[70];
506
507
508                 snprintf(wget_command, sizeof(wget_command), "wget -q -O /tmp/otherclient http://%s/dhcp.leases", inet_ntoa(foobar.v4));
509
510                 system(wget_command);
511
512                 check_remote_leases(list);
513
514         }OLSR_FOR_ALL_NBR_ENTRIES_END();
515
516
517
518
519
520
521
522
523
524 }
525
526
527
528
529
530
531