2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
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.
33 * Visit http://www.olsr.org for more information.
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.
42 * -Threaded ping code added by Jens Nachtigall
43 * -HNA4 checking by bjoern riemer
46 #include <arpa/inet.h>
48 #include "olsr_types.h"
49 #include "olsrd_dyn_gw.h"
53 #include "scheduler.h"
59 #include <net/route.h>
61 #include <linux/in_route.h>
69 #define WIN32_LEAN_AND_MEAN
73 #define close(x) closesocket(x)
75 typedef HANDLE pthread_mutex_t;
76 typedef HANDLE pthread_t;
78 int pthread_create(HANDLE *Hand, void *Attr, void *(*Func)(void *), void *Arg);
79 int pthread_kill(HANDLE Hand, int Sig);
80 int pthread_mutex_init(HANDLE *Hand, void *Attr);
81 int pthread_mutex_lock(HANDLE *Hand);
82 int pthread_mutex_unlock(HANDLE *Hand);
86 void *(*Func)(void *);
92 /* set default interval, in case none is given in the config file */
93 static int check_interval = 5;
95 /* list to store the Ping IP addresses given in the config file */
98 struct ping_list *next;
101 static struct ping_list *
102 add_to_ping_list(const char *, struct ping_list *);
105 union olsr_ip_addr hna_net;
106 olsr_u8_t hna_prefixlen;
107 struct ping_list *ping_hosts;
110 struct hna_list *next;
113 static struct hna_list *
114 add_to_hna_list(struct hna_list *,
115 union olsr_ip_addr *hna_net,
116 olsr_u8_t hna_prefixlen );
118 struct hna_list *the_hna_list = NULL;
121 looped_checks(void *) __attribute__((noreturn));
124 check_gw(union olsr_ip_addr *, olsr_u8_t,struct ping_list *);
127 ping_is_possible(struct ping_list *);
129 /* Event function to register with the scheduler */
131 olsr_event_doing_hna(void *);
134 * read config file parameters
136 static int set_plugin_double(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
139 const double d = strtod(value, &endptr);
140 if (*endptr != '\0' || endptr == value) {
141 OLSR_PRINTF(0, "Illegal double \"%s\"", value);
147 OLSR_PRINTF(1, "%s double %lf\n", "Got", d);
149 OLSR_PRINTF(0, "%s double %lf\n", "Ignored", d);
154 static int set_plugin_ping(const char *value, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
156 union olsr_ip_addr foo_addr;
158 if (inet_pton(olsr_cnf->ip_version, value, &foo_addr) <= 0) {
159 OLSR_PRINTF(0, "Illegal IP address \"%s\"", value);
162 /*if first ping without hna then assume inet gateway*/
163 if (the_hna_list == NULL){
164 union olsr_ip_addr temp_net;
165 union olsr_ip_addr temp_netmask;
166 temp_net.v4.s_addr = INET_NET;
167 temp_netmask.v4.s_addr = INET_PREFIX;
168 the_hna_list = add_to_hna_list(the_hna_list, &temp_net, olsr_netmask_to_prefix(&temp_netmask));
169 if (the_hna_list == NULL) {
173 the_hna_list->ping_hosts = add_to_ping_list(value, the_hna_list->ping_hosts);
177 static int set_plugin_hna(const char *value, void *data __attribute__((unused)), set_plugin_parameter_addon addon __attribute__((unused)))
179 union olsr_ip_addr temp_net;
180 union olsr_ip_addr temp_netmask;
184 //192.168.1.0 255.255.255.0
185 int i = sscanf(value,"%128s %128s", s_netaddr, s_mask);
187 OLSR_PRINTF(0, "Cannot get IP address and netmask from \"%s\"", value);
191 //printf("%s():i:%i; net:%s; mask:%s\n",__func__,i,s_netaddr,s_mask);
192 if (inet_pton(olsr_cnf->ip_version, s_netaddr, &temp_net) <= 0) {
193 OLSR_PRINTF(0, "Illegal IP address \"%s\"", s_netaddr);
197 //printf("GOT: %s(%08x)",inet_ntoa(foo_addr),foo_addr.s_addr);
198 if (inet_pton(olsr_cnf->ip_version, s_netaddr, &temp_netmask) <= 0) {
199 OLSR_PRINTF(0, "Illegal netmask \"%s\"", s_netaddr);
203 //printf("/%s(%08x)\n",inet_ntoa(foo_addr),foo_addr.s_addr);
204 //printf("%s():got->%s/%s\n",__func__,olsr_ip_to_string((union olsr_ip_addr *)&));
205 the_hna_list = add_to_hna_list(the_hna_list, &temp_net, olsr_netmask_to_prefix(&temp_netmask));
206 if (the_hna_list != NULL) {
212 static const struct olsrd_plugin_parameters plugin_parameters[] = {
213 { .name = "interval", .set_plugin_parameter = &set_plugin_double, .data = &check_interval },
214 { .name = "ping", .set_plugin_parameter = &set_plugin_ping, .data = NULL },
215 { .name = "hna", .set_plugin_parameter = &set_plugin_hna, .data = NULL },
218 void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
220 *params = plugin_parameters;
221 *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
225 *Do initialization here
228 *This function is called by the my_init
229 *function in uolsrd_plugin.c
230 *It is ran _after_ register_olsr_param
233 olsrd_plugin_init(void)
235 pthread_t ping_thread;
237 //gw_net.v4 = INET_NET;
238 //gw_netmask.v4 = INET_PREFIX;
240 //gw_already_added = 0;
241 //has_available_gw = 0;
244 /* Remove all local Inet HNA entries */
245 /*while(remove_local_hna4_entry(&gw_net, &gw_netmask))
247 olsr_printf(1, "HNA Internet gateway deleted\n");
250 pthread_create(&ping_thread, NULL, (void *(*)(void *))looped_checks, NULL);
252 /* Register the GW check */
253 olsr_start_timer(3 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC,
254 &olsr_event_doing_hna, NULL, 0);
261 * Scheduled event to update the hna table,
262 * called from olsrd main thread to keep the hna table thread-safe
265 olsr_event_doing_hna(void *foo __attribute__((unused)))
269 if (has_available_gw == 1 && gw_already_added == 0) {
270 olsr_printf(1, "Adding OLSR local HNA entry for Internet\n");
271 add_local_hna_entry(&gw_net, &gw_netmask);
272 gw_already_added = 1;
273 } else if ((has_available_gw == 0) && (gw_already_added == 1)) {
274 // Remove all local Inet HNA entries /
275 while(remove_local_hna4_entry(&gw_net, &gw_netmask)) {
276 olsr_printf(1, "Removing OLSR local HNA entry for Internet\n");
278 gw_already_added = 0;
281 for(li=the_hna_list; li; li=li->next){
282 if((li->probe_ok==1)&&(li->hna_added==0)){
283 olsr_printf(1, "Adding OLSR local HNA entry\n");
284 ip_prefix_list_add(&olsr_cnf->hna_entries, &li->hna_net, li->hna_prefixlen);
286 }else if((li->probe_ok==0)&&(li->hna_added==1)){
287 while(ip_prefix_list_remove(&olsr_cnf->hna_entries, &li->hna_net, li->hna_prefixlen)) {
288 olsr_printf(1, "Removing OLSR local HNA entry\n");
298 * the threaded function which happens within an endless loop,
299 * reiterated every "Interval" sec (as given in the config or
303 looped_checks(void *foo __attribute__((unused)))
307 struct timespec remainder_spec;
308 /* the time to wait in "Interval" sec (see connfig), default=5sec */
309 struct timespec sleeptime_spec = { check_interval, 0L };
311 for(li = the_hna_list; li; li = li->next){
312 /* check for gw in table entry and if Ping IPs are given also do pings */
313 li->probe_ok = check_gw(&li->hna_net,li->hna_prefixlen,li->ping_hosts);
314 //has_available_gw = check_gw(&gw_net, &gw_netmask);
317 while(nanosleep(&sleeptime_spec, &remainder_spec) < 0)
318 sleeptime_spec = remainder_spec;
326 check_gw(union olsr_ip_addr *net, olsr_u8_t prefixlen, struct ping_list *the_ping_list)
328 char buf[1024], iface[16];
329 olsr_u32_t gate_addr, dest_addr, netmask;
331 int metric, refcnt, use;
333 union olsr_ip_addr mask;
335 FILE *fp = fopen(PROCENTRY_ROUTE, "r");
338 perror(PROCENTRY_ROUTE);
339 olsr_printf(1, "INET (IPv4) not configured in this system.\n");
343 olsr_prefix_to_netmask(&mask, prefixlen);
345 olsr_printf(1, "Genmask Destination Gateway "
346 "Flags Metric Ref Use Iface\n");
348 while (fgets(buf, sizeof(buf), fp))
350 int num = sscanf(buf, "%15s %128X %128X %X %d %d %d %128X \n",
351 iface, &dest_addr, &gate_addr,
352 &iflags, &refcnt, &use, &metric, &netmask);
357 olsr_printf(1, "%-15s ", olsr_ip_to_string((union olsr_ip_addr *)&netmask));
359 olsr_printf(1, "%-15s ", olsr_ip_to_string((union olsr_ip_addr *)&dest_addr));
361 olsr_printf(1, "%-15s %-6d %-2d %7d %s\n",
362 olsr_ip_to_string((union olsr_ip_addr *)&gate_addr),
363 metric, refcnt, use, iface);
366 if( (iflags & RTF_UP) &&
368 (netmask == mask.v4.s_addr) &&
369 (dest_addr == net->v4.s_addr))
371 if ( ((mask.v4.s_addr == INET_PREFIX)&&(net->v4.s_addr == INET_NET))&&(!(iflags & RTF_GATEWAY)))
376 /* don't ping, if there was no "Ping" IP addr in the config file */
377 if (the_ping_list != NULL) {
378 /*validate the found inet gw by pinging*/
379 if (ping_is_possible(the_ping_list)) {
380 olsr_printf(1, "HNA[%08x/%08x](ping is possible) VIA %s detected in routing table.\n", dest_addr,netmask,iface);
384 olsr_printf(1, "HNA[%08x/%08x] VIA %s detected in routing table.\n", dest_addr,netmask,iface);
392 /* And we cast here since we get warnings on Win32 */
393 olsr_printf(1, "HNA[%08x/%08x] is invalid\n", (unsigned int)net->v4.s_addr, (unsigned int)mask.v4.s_addr);
399 ping_is_possible(struct ping_list *the_ping_list)
401 struct ping_list *list;
402 for(list = the_ping_list; list; list = list->next) {
403 char ping_command[50];
404 snprintf(ping_command, sizeof(ping_command), "ping -c 1 -q %s", list->ping_address);
405 olsr_printf(1, "\nDo ping on %s ...\n", list->ping_address);
406 if (system(ping_command) == 0) {
407 olsr_printf(1, "...OK\n\n");
410 olsr_printf(1, "...FAILED\n\n");
415 /* add the valid IPs to the head of the list */
416 static struct ping_list *
417 add_to_ping_list(const char *ping_address, struct ping_list *the_ping_list)
419 struct ping_list *new = malloc(sizeof(struct ping_list));
422 fprintf(stderr, "DYN GW: Out of memory!\n");
425 new->ping_address = strdup(ping_address);
426 new->next = the_ping_list;
432 static struct hna_list *
433 add_to_hna_list(struct hna_list * list_root, union olsr_ip_addr *hna_net, olsr_u8_t hna_prefixlen )
435 struct hna_list *new = malloc(sizeof(struct hna_list));
438 fprintf(stderr, "DYN GW: Out of memory!\n");
441 //memcpy(&new->hna_net,hna_net,sizeof(union hna_net));
442 //memcpy(&new->hna_netmask,hna_netmask,sizeof(union hna_netmask));
443 new->hna_net.v4=hna_net->v4;
444 new->hna_prefixlen=hna_prefixlen;
447 new->ping_hosts=NULL;
454 * Windows ptread compat stuff
456 static unsigned long __stdcall ThreadWrapper(void *Para)
458 struct ThreadPara *Cast;
459 void *(*Func)(void *);
462 Cast = (struct ThreadPara *)Para;
467 HeapFree(GetProcessHeap(), 0, Para);
474 int pthread_create(HANDLE *Hand, void *Attr __attribute__((unused)), void *(*Func)(void *), void *Arg)
476 struct ThreadPara *Para;
477 unsigned long ThreadId;
479 Para = HeapAlloc(GetProcessHeap(), 0, sizeof (struct ThreadPara));
487 *Hand = CreateThread(NULL, 0, ThreadWrapper, Para, 0, &ThreadId);
495 int pthread_kill(HANDLE Hand, int Sig __attribute__((unused)))
497 if (!TerminateThread(Hand, 0))
503 int pthread_mutex_init(HANDLE *Hand, void *Attr __attribute__((unused)))
505 *Hand = CreateMutex(NULL, FALSE, NULL);
513 int pthread_mutex_lock(HANDLE *Hand)
515 if (WaitForSingleObject(*Hand, INFINITE) == WAIT_FAILED)
521 int pthread_mutex_unlock(HANDLE *Hand)
523 if (!ReleaseMutex(*Hand))