Merge branch 'master' into scheduler_cleanup
[olsrd.git] / lib / cl_roam / src / cl_roam.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41 #include "cl_roam.h"
42 #include "olsr_types.h"
43 #include "ipcalc.h"
44 #include "olsr_timer.h"
45 #include "olsr_socket.h"
46 #include "olsr.h"
47 #include "olsr_memcookie.h"
48 #include "olsr_ip_prefix_list.h"
49 #include "olsr_logging.h"
50 #include "os_system.h"
51
52 #include <stdio.h>
53 #include <string.h>
54 #include <stdlib.h>
55 #include <net/route.h>
56 #include <unistd.h>
57 #include <parser.h>
58 #include <pthread.h>
59 #include "neighbor_table.h"
60 #include "olsr.h"
61 #include "olsr_cfg.h"
62 #include "interfaces.h"
63 #include "olsr_protocol.h"
64 #include "net_olsr.h"
65 #include "link_set.h"
66 #include "ipcalc.h"
67 #include "lq_plugin.h"
68 #include "olsr_cfg_gen.h"
69 #include "common/string.h"
70 #include "olsr_ip_prefix_list.h"
71 #include "olsr_logging.h"
72 #include <netinet/in.h>
73 #include <sys/socket.h>
74 #include <arpa/inet.h>
75
76 #define PLUGIN_INTERFACE_VERSION 5
77
78 static int has_inet_gateway;
79 static struct olsr_timer_info *event_timer_info1;
80 static struct olsr_timer_info *event_timer_info2;
81 static struct olsr_timer_info *arping_timer_info;
82 static union olsr_ip_addr gw_netmask;
83
84 static void check_ping_result(void *foo);
85
86 /**
87  * Plugin interface version
88  * Used by main olsrd to check plugin interface version
89  */
90 int olsrd_plugin_interface_version(void) {
91   return PLUGIN_INTERFACE_VERSION;
92 }
93
94 static const struct olsrd_plugin_parameters plugin_parameters[] = { };
95
96 struct guest_client {
97   union olsr_ip_addr ip;
98   u_int64_t mac;
99   struct in_addr from_node;
100   char is_announced;
101   float last_seen;
102   pthread_t ping_thread;
103   pthread_t ping_thread_add;
104   struct olsr_memcookie_info *arping_timer_cookie;
105   char ping_thread_done;
106   struct olsr_timer_entry *arping_timer;
107   int remaing_announcements;
108   //who is in charge of this client
109   union olsr_ip_addr master_ip;
110 };
111
112 struct client_list {
113   struct guest_client *client;
114   struct client_list *list;
115 };
116
117 //Declaration of all functions
118 static void check_client_list(struct client_list * clist);
119 static int ip_is_in_guest_list(struct client_list * list, struct guest_client * host);
120 static void check_remote_leases(struct client_list * clist);
121 static int check_if_associcated(struct guest_client *client);
122 static void check_associations(struct client_list * clist);
123 static void add_client_to_list(struct client_list * clist, struct guest_client * host);
124 static void check_for_new_clients(struct client_list * clist);
125 static void* check_neighbour_host(void* neighbour);
126 static void spread_host(struct guest_client * host);
127 static void single_hna(union olsr_ip_addr * ip, uint32_t vtime);
128 static void olsr_event1(void *foo __attribute__ ((unused)) );
129 static struct guest_client * get_client_by_ip(union olsr_ip_addr ip);
130 #if 0
131 static void *
132 relay_spread_host(union olsr_ip_addr host_ip, union olsr_ip_addr master_ip, uint8_t TTL, uint8_t Hopcount);
133 #endif
134 static void
135     olsr_parser(struct olsr_message *msg, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr,
136         enum duplicate_status status);
137 static void check_leases(struct client_list * clist, const char *file, float def_last_seen);
138 static void check_local_leases(struct client_list * clist);
139 static struct guest_client * get_client_by_mac(struct client_list * clist, u_int64_t mac);
140 static void update_routes_now(void);
141 static void check_for_route(struct guest_client * host);
142
143 static void olsr_event1(void *foo __attribute__ ((unused)) );
144 static void olsr_event2(void *foo  __attribute__ ((unused)));
145
146 void update_routes_now(void) {
147   //Recalculate our own routing table RIGHT NOW
148
149   OLSR_INFO(LOG_PLUGINS, "Forcing recalculation of routing-table\n");
150
151   //actual calculation
152   olsr_calculate_routing_table(true);
153   //printf("updated\n");
154 }
155
156 struct client_list *list;
157 struct interface *ifn;
158
159 void ping(struct guest_client *);
160
161 void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size) {
162   *params = plugin_parameters;
163   *size = ARRAYSIZE(plugin_parameters);
164 }
165
166 struct guest_client * get_client_by_ip(union olsr_ip_addr ip) {
167   if (list != NULL && list->client != NULL) {
168
169     if (strcmp(inet_ntoa(list->client->ip.v4), inet_ntoa(ip.v4)) == 0)
170       return list->client;
171     else
172       return get_client_by_ip(ip);
173   } else
174     return NULL;
175 }
176
177 #if 0
178 static void *
179 relay_spread_host(union olsr_ip_addr host_ip, union olsr_ip_addr master_ip, uint8_t TTL, uint8_t Hopcount) {
180   struct interface *ifp;
181   struct list_iterator iterator;
182   uint8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE] __attribute__ ((aligned));
183   uint8_t *curr = msg_buffer;
184   uint8_t *length_field, *last;
185
186   OLSR_INFO(LOG_PACKET_CREATION, "Building Message Relay\n-------------------\n");
187
188   // My message Type 134:
189   pkt_put_u8(&curr, 134);
190   // validity
191   pkt_put_reltime(&curr, 20000);
192
193   length_field = curr;
194   pkt_put_u16(&curr, 0); /* put in real messagesize later */
195
196   pkt_put_ipaddress(&curr, &olsr_cnf->router_id);
197
198   // TTL
199   pkt_put_u8(&curr, TTL - 1);
200   pkt_put_u8(&curr, Hopcount + 1);
201   pkt_put_u16(&curr, get_msg_seqno());
202
203   last = msg_buffer + sizeof(msg_buffer) - olsr_cnf->ipsize;
204
205   if (TTL < 1) {
206     OLSR_DEBUG(LOG_PLUGINS, "Not relaying, TTL exceded");
207     return NULL;
208   }
209
210   // Actual message
211   //first IP to announce
212   pkt_put_ipaddress(&curr, &host_ip);
213   // second: announcing IP
214   pkt_put_ipaddress(&curr, &master_ip);
215
216   //Put in Message size
217   pkt_put_u16(&length_field, curr - msg_buffer);
218
219   OLSR_FOR_ALL_INTERFACES(ifp, iterator) {
220     if (net_outbuffer_bytes_left(ifp) < curr - msg_buffer) {
221       net_output(ifp);
222       set_buffer_timer(ifp);
223     }
224     // buffer gets pushed NOW
225     net_outbuffer_push(ifp, msg_buffer, curr - msg_buffer);
226     net_output(ifp);
227     set_buffer_timer(ifp);
228   }
229
230   OLSR_INFO(LOG_PLUGINS, "Relayed some foo!");
231
232   return NULL;
233 }
234 #endif
235
236 void olsr_parser(struct olsr_message *msg, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr,
237     enum duplicate_status status __attribute__ ((unused))) {
238   const uint8_t *curr;
239   union olsr_ip_addr ip, master_ip;
240   struct guest_client * guest;
241
242   // my MessageType
243   if (msg->type != 134) {
244     printf("recieved something else\n");
245     return;
246   }
247   OLSR_DEBUG(LOG_PLUGINS, "Recieved roaming-messagetype from %s\n", inet_ntoa(ipaddr->v4));
248   curr = msg->payload;
249   pkt_get_ipaddress(&curr, &ip);
250   pkt_get_ipaddress(&curr, &master_ip);
251
252   guest = get_client_by_ip(ip);
253
254   // Forward it --start--
255   /*
256    if (status == DUPLICATE_OLSR_MESSAGE) {
257    OLSR_INFO(LOG_PLUGINS, "Not relaying, duplicate");
258    }
259    else {
260    relay_spread_host(ip, master_ip, msg->ttl, msg->hopcnt);
261    }
262    */
263
264   // Forwarding --end--
265
266   if (guest != NULL) {
267     if ((guest->is_announced) != 0) {
268       char route_command[50];
269       int ret;
270
271       OLSR_INFO(LOG_PLUGINS, "Having to revoke announcement for %s\n", inet_ntoa(guest->ip.v4));
272       guest->is_announced = 0;
273       guest->last_seen = 90.0;
274       guest->remaing_announcements = 0;
275
276       ip_prefix_list_remove(&olsr_cnf->hna_entries, &(guest->ip), olsr_netmask_to_prefix(&gw_netmask),
277           olsr_cnf->ip_version);
278       snprintf(route_command, sizeof(route_command), "route del %s dev ath0 metric 0", inet_ntoa(guest->ip.v4));
279       if ((ret = system(route_command))) {
280         OLSR_WARN(LOG_PLUGINS, "cl_roam: Warning, system '%s' returned %d\n", route_command, ret);
281       }
282       single_hna(&ip, 0);
283     }
284   }
285
286   if (guest != NULL) {
287     OLSR_DEBUG(LOG_PLUGINS, "Old master: %s\n", inet_ntoa(guest->master_ip.v4));
288     OLSR_DEBUG(LOG_PLUGINS, "New master: %s\n", inet_ntoa(master_ip.v4));
289     if (memcmp(&(guest->master_ip.v4), &(master_ip.v4), sizeof(union olsr_ip_addr)) != 0) {
290       guest->master_ip = master_ip;
291       OLSR_INFO(LOG_PLUGINS, "Updating Routes because %s changed\n", inet_ntoa(guest->ip.v4));
292       update_routes_now();
293     } else {
294       struct ipaddr_str buf1, buf2;
295       OLSR_DEBUG(LOG_PLUGINS, "Not updating, because %s stayed at %s\n",
296           olsr_ip_to_string(&buf1, &guest->ip), olsr_ip_to_string(&buf2, &master_ip));
297     }
298   } else {
299     OLSR_INFO(LOG_PLUGINS, "Updating Routes for unknown client\n");
300     update_routes_now();
301   }
302
303 }
304
305 /**
306  * Initialize plugin
307  * Called after all parameters are passed
308  */
309 int olsrd_plugin_init(void) {
310   list = (struct client_list*) olsr_malloc(sizeof(struct client_list), "client_list");
311
312   OLSR_INFO(LOG_PLUGINS, "OLSRD automated Client Roaming Plugin\n");
313
314   gw_netmask.v4.s_addr = inet_addr("255.255.255.255");
315
316   has_inet_gateway = 0;
317
318   /* create the cookie */
319   event_timer_info1 = olsr_timer_add("cl roam: Event1", &olsr_event1, true);
320   event_timer_info2 = olsr_timer_add("cl roam: Event2", &olsr_event2, true);
321   arping_timer_info = olsr_timer_add("cl roam: Maybe add something", &check_ping_result, true);
322
323   /* Register the GW check */
324   olsr_timer_start(1 * MSEC_PER_SEC, 0, NULL, event_timer_info1);
325   olsr_timer_start(20 * MSEC_PER_SEC, 0, NULL, event_timer_info2);
326
327   /* register functions with olsrd */
328   // somehow my cool new message.....
329   olsr_parser_add_function(&olsr_parser, 134);
330
331   return 1;
332 }
333
334 static void* ping_thread(void* guest) {
335   char ping_command[50];
336   ssize_t result;
337   struct guest_client * target = (struct guest_client *) guest;
338   target->ping_thread_done = 0;
339
340   snprintf(ping_command, sizeof(ping_command), "arping -I ath0 -w 1 -c 1 -q %s", inet_ntoa(target->ip.v4));
341   //printf("%s\n",ping_command);
342   result = system(ping_command);
343   target->ping_thread_done = 1;
344   //printf("ping thread finished\n");
345   return (void*) result;
346 }
347
348 static  __attribute__ ((noreturn)) void* ping_thread_infinite(void * target_void) {
349   char ping_command[50];
350   struct guest_client * target = (struct guest_client*) target_void;
351   while (1) {
352     int ret;
353     snprintf(ping_command, sizeof(ping_command), "arping -I ath0 -q -c 10 %s", inet_ntoa(target->ip.v4));
354     if ((ret = system(ping_command))) {
355       OLSR_WARN(LOG_PLUGINS, "cl_roam: Warning, system '%s' returned %d\n", ping_command, ret);
356     }
357     pthread_testcancel();
358   }
359 }
360
361 static void ping_infinite(struct guest_client * target) {
362   int rc;
363   pthread_t thread;
364   if (target->ping_thread == 0) {
365     rc = pthread_create(&thread, NULL, ping_thread_infinite, (void *) target);
366     if (rc) {
367       printf("ERROR; return code from pthread_create() is %d\n", rc);
368       os_exit(-1);
369     }
370     target->ping_thread = thread;
371     OLSR_INFO(LOG_PLUGINS, "Set up ping-thread for %s\n", inet_ntoa(target->ip.v4));
372   } else
373     OLSR_INFO(LOG_PLUGINS, "Ping-thread for %s already exists!\n", inet_ntoa(target->ip.v4));
374 }
375
376 static void check_ping_result(void *foo) {
377   struct guest_client * host = (struct guest_client *) foo;
378
379   if (!host->ping_thread_done) {
380     OLSR_DEBUG(LOG_PLUGINS, "Ping-thread for %s not finished\n", inet_ntoa(host->ip.v4));
381
382   } else {
383     /* should be same size as (void*) */
384     ssize_t ping_res;
385
386     olsr_timer_stop(host->arping_timer);
387     pthread_join(host->ping_thread_add, (void*) &ping_res);
388     host->arping_timer = NULL;
389     host->ping_thread_done = 0;
390     if (ping_res == 0) {
391       char route_command[50];
392       int ret;
393       OLSR_INFO(LOG_PLUGINS, "Adding Route for %s\n", inet_ntoa(host->ip.v4));
394
395       ip_prefix_list_add(&olsr_cnf->hna_entries, &(host->ip), olsr_netmask_to_prefix(&gw_netmask));
396       host->is_announced = 1;
397       host->remaing_announcements = 15;
398
399       snprintf(route_command, sizeof(route_command), "route add %s dev ath0 metric 0", inet_ntoa(host->ip.v4));
400       if ((ret = system(route_command))) {
401         OLSR_WARN(LOG_PLUGINS, "cl_roam: Warning, system '%s' returned %d\n", route_command, ret);
402       }
403
404       host->master_ip = olsr_cnf->router_id;
405
406       spread_host(host);
407       //This really big time will be overwritten by the next normal hna-announcement
408       single_hna(&host->ip, -1);
409
410       //Append to buffer, will be send at some time. In case it didn't arrive at the old master
411       spread_host(host);
412     } else {
413       host->last_seen += 0.5;
414       check_for_route(host);
415     }
416   }
417 }
418
419 static void check_for_route(struct guest_client * host) {
420   //printf("%f, %i, %x\n",host->last_seen , host->is_announced  ,host->ping_thread_add );
421   if (host->last_seen < 10.0 && !host->is_announced && host->arping_timer == NULL) {
422     int rc;
423
424     //printf("maybe add something\n");
425     if (host->arping_timer_cookie == NULL)
426     //printf("timer started\n");
427     host->arping_timer = olsr_timer_start(250, 5, host, arping_timer_info);
428     rc = pthread_create(&(host->ping_thread_add), NULL, ping_thread, (void *) host);
429   } else if ((host->last_seen > 60.0) && host->is_announced) {
430     char route_command[50];
431     int ret;
432     OLSR_INFO(LOG_PLUGINS, "Removing Route for %s\n", inet_ntoa(host->ip.v4));
433     ip_prefix_list_remove(&olsr_cnf->hna_entries, &host->ip, olsr_netmask_to_prefix(&gw_netmask), olsr_cnf->ip_version);
434     snprintf(route_command, sizeof(route_command), "route del %s dev ath0 metric 0", inet_ntoa(host->ip.v4));
435     if ((ret = system(route_command))) {
436       OLSR_WARN(LOG_PLUGINS, "cl_roam: Warning, system '%s' returned %d\n", route_command, ret);
437     }
438     host->is_announced = 0;
439   } else if (host->is_announced && host->remaing_announcements > 0) {
440     host->remaing_announcements--;
441     spread_host(host);
442     single_hna(&host->ip, -1);
443   }
444 }
445
446 static void check_client_list(struct client_list * clist) {
447   if (clist != NULL && clist->client != NULL) {
448     //ping(clist->client);
449     if (clist->client->is_announced == 1 || clist->client->ping_thread != 0) {
450       if (!check_if_associcated(clist->client)) {
451         if (clist->client->is_announced == 1) {
452           clist->client->last_seen += 5;
453         }
454         if (clist->client->ping_thread != 0) {
455           //printf("attempting to kill ping-thread\n");
456           pthread_detach(clist->client->ping_thread);
457           //pthread_kill(clist->client->ping_thread, 1);
458           //pthread_cancel(clist->client->ping_thread);
459           pthread_cancel(clist->client->ping_thread);
460           //printf("killed ping-thread\n");
461           OLSR_INFO(LOG_PLUGINS, "Killed ping-thread for %s\n", inet_ntoa(clist->client->ip.v4));
462           // clist->client->ping_thread=NULL; (not a pointer !)
463         }
464       }
465     }
466     check_for_route(clist->client);
467     check_client_list(clist->list);
468   }
469 }
470
471 struct guest_client * get_client_by_mac(struct client_list * clist, u_int64_t mac) {
472   if (clist != NULL && clist->client != NULL) {
473     if (clist->client->mac == mac)
474       return clist->client;
475     else
476       return get_client_by_mac(clist->list, mac);
477   } else
478     return NULL;
479 }
480
481 int ip_is_in_guest_list(struct client_list *l, struct guest_client * host) {
482   if (l == NULL)
483     return 0;
484   if (l->client == NULL)
485     return 0;
486   else if (inet_lnaof(l->client->ip.v4) == inet_lnaof(host->ip.v4))
487     return 1;
488   else
489     return ip_is_in_guest_list(l->list, host);
490 }
491
492 void check_local_leases(struct client_list * clist) {
493   check_leases(clist, "/var/dhcp.leases", 1.0);
494 }
495
496 void check_leases(struct client_list * clist, const char *file, float def_last_seen) {
497   char s1[50];
498   char s3[50];
499   long long int one, two, three, four, five, six;
500
501   FILE * fp = fopen(file, "r");
502   if (fp == NULL) {
503     printf("failed to open %s\n", file);
504   }
505
506   while (1) {
507     int parse = fscanf(fp, "%s %llx:%llx:%llx:%llx:%llx:%llx %s %*s %*s\n", s1, &one, &two, &three, &four, &five, &six,
508         s3);
509     if (parse == EOF)
510       break;
511     if (parse == 8) {
512       struct guest_client* user;
513       //printf ("String 3 = %s\n", s3);
514       user = (struct guest_client*) malloc(sizeof(struct guest_client));
515       inet_aton(s3, &(user->ip.v4));
516       user->mac = six | five << 8 | four << 16 | three << 24 | two << 32 | one << 40;
517       user->last_seen = def_last_seen;
518       user->is_announced = 0;
519       user->ping_thread = 0;
520       user->arping_timer = NULL;
521       user->arping_timer_cookie = NULL;
522       //printf("last seen on Add %f\n",user->last_seen);
523       add_client_to_list(clist, user);
524     }
525   }
526   fclose(fp);
527 }
528
529 static void check_remote_leases(struct client_list * clist) {
530   FILE *my_leases;
531   FILE *fp;
532   char s1[50];
533   char s3[50];
534   long long int one, two, three, four, five, six;
535
536   fp = fopen("/tmp/otherclient", "r");
537   if (fp == NULL) {
538     printf("failed to open %s\n", "/tmp/otherclient");
539   }
540   my_leases = fopen("/var/dhcp.leases", "a");
541   if (my_leases == NULL) {
542     printf("failed to open %s\n", "/var/dhcp.leases");
543   }
544
545   while (1) {
546     int parse = fscanf(fp, "%s %llx:%llx:%llx:%llx:%llx:%llx %s %*s %*s\n", s1, &one, &two, &three, &four, &five, &six,
547         s3);
548     if (parse == EOF)
549       break;
550     if (parse == 8) {
551       struct guest_client* user;
552       //printf ("String 3 = %s\n", s3);
553       user = (struct guest_client*) malloc(sizeof(struct guest_client));
554       inet_aton(s3, &(user->ip.v4));
555       user->mac = six | five << 8 | four << 16 | three << 24 | two << 32 | one << 40;
556       user->last_seen = 30.0;
557       user->is_announced = 0;
558       user->ping_thread = 0;
559       user->arping_timer = NULL;
560       user->arping_timer_cookie = NULL;
561       //printf("last seen on Add %f\n",user->last_seen);
562
563       if (!(ip_is_in_guest_list(clist, user))) {
564         fprintf(my_leases, "%s %llx:%llx:%llx:%llx:%llx:%llx %s * *\n", s1, one, two, three, four, five, six, s3);
565       }
566       add_client_to_list(clist, user);
567     }
568   }
569   fclose(fp);
570   fclose(my_leases);
571 }
572
573 static int check_if_associcated(struct guest_client *client) {
574   char s2[50];
575   float last_rx;
576   int parse;
577   uint64_t mac;
578   long long int one, two, three, four, five, six;
579
580   FILE * fp = fopen("/proc/net/madwifi/ath0/associated_sta", "r");
581   if (fp == NULL) {
582     printf("failed to open %s\n", "/proc/net/madwifi/ath0/associated_sta");
583     return EXIT_FAILURE;
584   }
585   //FILE * fp = fopen("/home/raphael/tmp/leases", "r");
586
587   while (1) {
588     parse = fscanf(fp, "macaddr: <%llx:%llx:%llx:%llx:%llx:%llx>\n", &one, &two, &three, &four, &five, &six);
589     if (parse == EOF || parse != 6)
590       break;
591     mac = six | five << 8 | four << 16 | three << 24 | two << 32 | one << 40;
592     //printf ("am at %llx\n", mac);
593     if (mac == client->mac) {
594       //printf("found it!\n");
595       fclose(fp);
596       return 1;
597     }
598     parse = fscanf(fp, " rssi %s\n", s2);
599     if (parse == EOF)
600       break;
601     parse = fscanf(fp, " last_rx %f\n", &last_rx);
602     if (parse == EOF)
603       break;
604   }
605
606   fclose(fp);
607
608   return 0;
609 }
610
611 static void check_associations(struct client_list * clist) {
612   char s2[50];
613   float last_rx;
614   int parse;
615
616   long long int one, two, three, four, five, six;
617   FILE * fp = fopen("/proc/net/madwifi/ath0/associated_sta", "r");
618   if (fp == NULL) {
619     printf("failed to open %s\n", "/proc/net/madwifi/ath0/associated_sta");
620   }
621   //FILE * fp = fopen("/home/raphael/tmp/leases", "r");
622
623   while (1) {
624     uint64_t mac;
625     struct guest_client* node;
626     parse = fscanf(fp, "macaddr: <%llx:%llx:%llx:%llx:%llx:%llx>\n", &one, &two, &three, &four, &five, &six);
627     if (parse == EOF || parse != 6)
628       break;
629     mac = six | five << 8 | four << 16 | three << 24 | two << 32 | one << 40;
630     //printf ("macaddr: %llx\n", mac);
631     parse = fscanf(fp, " rssi %s\n", s2);
632     if (parse == EOF)
633       break;
634     //printf ("rssi = %s\n", s2);
635     parse = fscanf(fp, " last_rx %f\n", &last_rx);
636     if (parse == EOF)
637       break;
638     //printf ("last_rx = %f\n", last_rx);
639     node = get_client_by_mac(clist, mac);
640     if (node != NULL) {
641       //printf("Sichtung!\n");
642       node->last_seen = last_rx;
643       if (node->ping_thread == 0) {
644         ping_infinite(node);
645       }
646     }
647   }
648   fclose(fp);
649 }
650
651 void add_client_to_list(struct client_list * clist, struct guest_client * host) {
652   if (ip_is_in_guest_list(clist, host)) {
653     free(host);
654   } else {
655     if (clist->client != NULL) {
656       struct client_list * this_one;
657       this_one = (struct client_list *) olsr_malloc(sizeof(struct client_list), "clist");
658       this_one->client = host;
659       this_one->list = clist->list;
660       clist->list = this_one;
661       OLSR_INFO(LOG_PLUGINS, "Keeping track of %s\n", inet_ntoa(host->ip.v4));
662     } else {
663       clist->client = host;
664       OLSR_INFO(LOG_PLUGINS, "Keeping track of %s\n", inet_ntoa(host->ip.v4));
665     }
666     ping_infinite(host);
667     host->arping_timer = NULL;
668     check_for_route(host);
669
670   }
671 }
672
673 static void check_for_new_clients(struct client_list * clist) {
674   check_local_leases(clist);
675   check_associations(clist);
676 }
677
678 static void* check_neighbour_host(void* neighbour) {
679   struct nbr_entry *nbr = (struct nbr_entry*) neighbour;
680   union olsr_ip_addr foobar = nbr->nbr_addr;
681
682   char wget_command[70];
683
684   snprintf(wget_command, sizeof(wget_command), "wget -T 2 -q -O /tmp/otherclient http://%s/dhcp.leases", inet_ntoa(
685       foobar.v4));
686   if (system(wget_command) == 0) {
687
688     check_remote_leases(list);
689   }
690   return NULL;
691 }
692
693 static void spread_host(struct guest_client * host) {
694   struct interface *ifp, *iterator;
695   uint8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE] __attribute__ ((aligned));
696   uint8_t *curr = msg_buffer;
697   uint8_t *length_field, *last;
698
699   OLSR_INFO(LOG_PACKET_CREATION, "Building HNA\n-------------------\n");
700
701   // My message Type 134:
702   pkt_put_u8(&curr, 134);
703   // hna-validity
704   pkt_put_reltime(&curr, 20000);
705
706   length_field = curr;
707   pkt_put_u16(&curr, 0); /* put in real messagesize later */
708
709   pkt_put_ipaddress(&curr, &olsr_cnf->router_id);
710
711   // TTL
712   pkt_put_u8(&curr, 3);
713   pkt_put_u8(&curr, 0);
714   pkt_put_u16(&curr, get_msg_seqno());
715
716   last = msg_buffer + sizeof(msg_buffer) - olsr_cnf->ipsize;
717
718   // Actual message
719   //first IP to announce
720   pkt_put_ipaddress(&curr, &(host->ip));
721   // second: announcing IP
722   pkt_put_ipaddress(&curr, &olsr_cnf->router_id);
723
724   //Put in Message size
725   pkt_put_u16(&length_field, curr - msg_buffer);
726
727   OLSR_FOR_ALL_INTERFACES(ifp, iterator) {
728     if (net_outbuffer_bytes_left(ifp) < curr - msg_buffer) {
729       net_output(ifp);
730       set_buffer_timer(ifp);
731     }
732     // buffer gets pushed out in single_hna, or at flush-time
733     net_outbuffer_push(ifp, msg_buffer, curr - msg_buffer);
734   }
735
736 }
737
738 // sends packet immedeately!
739 void single_hna(union olsr_ip_addr * ip, uint32_t vtime) {
740   union olsr_ip_addr subnet;
741   struct interface *ifp, *iterator;
742   uint8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE] __attribute__ ((aligned));
743   uint8_t *curr = msg_buffer;
744   uint8_t *length_field, *last;
745
746   //printf("single hna %x with time %i\n",*ip, time);
747   OLSR_INFO(LOG_PACKET_CREATION, "Building HNA\n-------------------\n");
748
749   // My message Type 134:
750   pkt_put_u8(&curr, HNA_MESSAGE);
751   // hna-validity
752   pkt_put_reltime(&curr, vtime);
753
754   length_field = curr;
755   pkt_put_u16(&curr, 0); /* put in real messagesize later */
756
757   pkt_put_ipaddress(&curr, &olsr_cnf->router_id);
758
759   // TTL
760   pkt_put_u8(&curr, 2);
761   pkt_put_u8(&curr, 0);
762   pkt_put_u16(&curr, get_msg_seqno());
763
764   last = msg_buffer + sizeof(msg_buffer) - olsr_cnf->ipsize;
765
766   inet_aton("255.255.255.255", &subnet.v4);
767   pkt_put_ipaddress(&curr, ip);
768   pkt_put_ipaddress(&curr, &subnet);
769
770   pkt_put_u16(&length_field, curr - msg_buffer);
771
772   OLSR_FOR_ALL_INTERFACES(ifp, iterator) {
773     net_output(ifp);
774     net_outbuffer_push(ifp, msg_buffer, curr - msg_buffer);
775     net_output(ifp);
776     set_buffer_timer(ifp);
777   }
778 }
779
780 static void olsr_event1(void *foo __attribute__ ((unused)) ) {
781   check_for_new_clients(list);
782   check_client_list(list);
783 }
784
785 static void olsr_event2(void *foo  __attribute__ ((unused))) {
786   struct nbr_entry *nbr, *iterator;
787
788   OLSR_FOR_ALL_NBR_ENTRIES(nbr, iterator) {
789     int rc;
790     pthread_t thread;
791     rc = pthread_create(&thread, NULL, check_neighbour_host, (void *) nbr);
792     if (rc) {
793       printf("ERROR; return code from pthread_create() is %d\n", rc);
794       os_exit(-1);
795     }
796   }
797 }
798