1 /*
2  * The olsr.org Optimized Link-State Routing daemon (olsrd)
3  *
4  * (c) by the OLSR project
5  *
6  * See our Git repository to find out who worked on this file
7  * and thus is a copyright holder on it.
8  *
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * * Redistributions of source code must retain the above copyright
16  *   notice, this list of conditions and the following disclaimer.
17  * * Redistributions in binary form must reproduce the above copyright
18  *   notice, this list of conditions and the following disclaimer in
19  *   the documentation and/or other materials provided with the
20  *   distribution.
21  * * Neither the name of olsr.org, olsrd nor the names of its
22  *   contributors may be used to endorse or promote products derived
23  *   from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * Visit http://www.olsr.org for more information.
39  *
40  * If you find this software useful feel free to make a donation
41  * to the project. For more information see the website or contact
42  * the copyright holders.
43  *
44  */
45 
46 /*
47  * -Threaded ping code added by Jens Nachtigall
48  * -HNA4 checking by bjoern riemer
49  */
50 
51 #include <arpa/inet.h>
52 
53 #include "olsr_types.h"
54 #include "olsrd_dyn_gw.h"
55 #include "olsr.h"
56 #include "defs.h"
57 #include "ipcalc.h"
58 #include "scheduler.h"
59 #include "log.h"
60 #include "routing_table.h"
61 #include "olsr_cfg.h"
62 
63 #include <stdio.h>
64 #include <string.h>
65 #include <stdlib.h>
66 #include <sys/time.h>
67 #include <net/route.h>
68 #include <unistd.h>
69 #include <errno.h>
70 #include <time.h>
71 #ifndef _WIN32
72 #include <pthread.h>
73 #else /* _WIN32 */
74 #define WIN32_LEAN_AND_MEAN
75 #include <windows.h>
76 #undef interface
77 
78 #define close(x) closesocket(x)
79 
80 typedef HANDLE pthread_mutex_t;
81 typedef HANDLE pthread_t;
82 
83 int pthread_create(HANDLE * Hand, void *Attr, void *(*Func) (void *), void *Arg);
84 int pthread_kill(HANDLE Hand, int Sig);
85 int pthread_mutex_init(HANDLE * Hand, void *Attr);
86 int pthread_mutex_lock(HANDLE * Hand);
87 int pthread_mutex_unlock(HANDLE * Hand);
88 
89 struct ThreadPara {
90   void *(*Func) (void *);
91   void *Arg;
92 };
93 #endif /* _WIN32 */
94 
95 static int hna_check_interval	= DEFAULT_HNA_CHECK_INTERVAL;
96 /* set default interval, in case none is given in the config file */
97 static int ping_check_interval = DEFAULT_PING_CHECK_INTERVAL;
98 
99 /* list to store the Ping IP addresses given in the config file */
100 struct ping_list {
101   char *ping_address;
102   struct ping_list *next;
103 };
104 
105 static struct ping_list *add_to_ping_list(const char *, struct ping_list *);
106 
107 struct hna_list {
108   union olsr_ip_addr   hna_addr;
109   uint8_t              hna_prefixlen;
110   bool                 hna_added;
111   bool                 checked;
112   bool                 active;
113   struct hna_list *    next;
114 };
115 
116 static struct hna_list *add_to_hna_list(struct hna_list *, union olsr_ip_addr *hna_addr, uint8_t hna_prefixlen);
117 
118 struct hna_group {
119   struct hna_list *    hna_list;
120   struct ping_list *   ping_hosts;
121   bool                 probe_ok;
122   struct hna_group *   next;
123 };
124 
125 bool hna_ping_check	= false;
126 static struct hna_group * hna_groups = NULL;
127 
128 static struct hna_group *add_to_hna_group(struct hna_group *);
129 
130 static void *looped_checks(void *);
131 
132 static bool check_gw(union olsr_ip_addr *, uint8_t, struct ping_list *);
133 
134 static int ping_is_possible(struct ping_list *);
135 
136 static char ping_cmd[PING_CMD_MAX_LEN] = { DEFAULT_PING_CMD };
137 
138 /* Event function to register with the scheduler */
139 static void olsr_event_doing_hna(void *);
140 
141 struct hna_list* find_hna(uint32_t src_addr, uint32_t src_mask);
142 
143 char *get_ip_str(uint32_t address, char *s, size_t maxlen);
144 int update_routing(void);
145 
146 /**
147  * read config file parameters
148  */
149 static int
set_plugin_ping(const char * value,void * data,set_plugin_parameter_addon addon)150 set_plugin_ping(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
151 {
152   union olsr_ip_addr foo_addr;
153 
154   if (inet_pton(olsr_cnf->ip_version, value, &foo_addr) <= 0) {
155     OLSR_PRINTF(0, "Illegal IP address \"%s\"", value);
156     return 1;
157   }
158 
159   if (hna_groups == NULL) {
160     hna_groups = add_to_hna_group(hna_groups);
161     if (hna_groups == NULL)
162       return 1;
163   } else {
164     if (hna_groups->hna_list != NULL) {
165       hna_groups = add_to_hna_group(hna_groups);
166     }
167   }
168 
169   hna_groups->ping_hosts = add_to_ping_list(value, hna_groups->ping_hosts);
170   hna_ping_check = true;
171 
172   return 0;
173 }
174 
175 static int
set_plugin_hna(const char * value,void * data,set_plugin_parameter_addon addon)176 set_plugin_hna(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
177 {
178   union olsr_ip_addr temp_addr;
179   union olsr_ip_addr temp_mask;
180   char s_addr[128];
181   char s_mask[128];
182 
183   //Example: 192.168.1.0  255.255.255.0
184   int i = sscanf(value, "%127s %127s", s_addr, s_mask);
185   if (i != 2) {
186     OLSR_PRINTF(0, "Cannot get IP address and netmask from \"%s\"", value);
187     return 1;
188   }
189 
190   if (inet_pton(olsr_cnf->ip_version, s_addr, &temp_addr) <= 0) {
191     OLSR_PRINTF(0, "Illegal IP address \"%s\"", s_addr);
192     return 1;
193   }
194 
195   if (inet_pton(olsr_cnf->ip_version, s_mask, &temp_mask) <= 0) {
196     OLSR_PRINTF(0, "Illegal netmask \"%s\"", s_mask);
197     return 1;
198   }
199 
200   if (hna_groups == NULL)
201   {
202     hna_groups = add_to_hna_group(hna_groups);
203     if (hna_groups == NULL) {
204       return 1;
205     }
206   }
207 
208   hna_groups->hna_list = add_to_hna_list(hna_groups->hna_list, &temp_addr, olsr_netmask_to_prefix(&temp_mask));
209   if (hna_groups->hna_list == NULL) {
210     return 1;
211   }
212   return 0;
213 }
214 
215 static int
set_plugin_cmd(const char * value,void * data,set_plugin_parameter_addon addon)216 set_plugin_cmd(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
217 {
218   size_t len = strlen(value);
219 
220   if (len < PING_CMD_MAX_LEN) {
221     strncpy(ping_cmd, value, PING_CMD_MAX_LEN - 1);
222     ping_cmd[PING_CMD_MAX_LEN - 1] = '\0';
223     return 0;
224   }
225 
226   return 1;
227 }
228 
229 static const struct olsrd_plugin_parameters plugin_parameters[] = {
230   {.name = "interval",      .set_plugin_parameter = &set_plugin_int,  .data = &ping_check_interval  },
231   {.name = "pinginterval",  .set_plugin_parameter = &set_plugin_int,  .data = &ping_check_interval  },
232   {.name = "checkinterval", .set_plugin_parameter = &set_plugin_int,  .data = &hna_check_interval   },
233   {.name = "ping",          .set_plugin_parameter = &set_plugin_ping, .data = NULL                  },
234   {.name = "hna",           .set_plugin_parameter = &set_plugin_hna,  .data = NULL                  },
235   {.name = "pingcmd",       .set_plugin_parameter = &set_plugin_cmd,  .data = &ping_cmd             },
236 };
237 
238 void
olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters ** params,int * size)239 olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
240 {
241   *params = plugin_parameters;
242   *size = sizeof(plugin_parameters) / sizeof(*plugin_parameters);
243 }
244 
245 /**
246  *Do initialization here
247  *
248  *
249  *This function is called by the my_init
250  *function in uolsrd_plugin.c
251  *It is ran _after_ register_olsr_param
252  */
253 int
olsrd_plugin_init(void)254 olsrd_plugin_init(void)
255 {
256   pthread_t ping_thread;
257 
258   if (hna_groups == NULL) {
259     hna_groups = add_to_hna_group(hna_groups);
260     if (hna_groups == NULL)
261       return 1;
262   }
263 
264   // Add a default gateway if the top entry was just a ping address
265   if (hna_groups->hna_list == NULL) {
266     union olsr_ip_addr temp_addr;
267     union olsr_ip_addr temp_mask;
268 
269     temp_addr.v4.s_addr = INET_ADDR;
270     temp_mask.v4.s_addr = INET_MASK;
271     hna_groups->hna_list = add_to_hna_list(hna_groups->hna_list, &temp_addr, olsr_netmask_to_prefix(&temp_mask));
272     if (hna_groups->hna_list == NULL) {
273       return 1;
274     }
275   }
276 
277   // Prepare all routing information
278   update_routing();
279 
280   if (hna_ping_check) {
281     pthread_create(&ping_thread, NULL, looped_checks, NULL);
282   } else {
283     struct hna_group *grp;
284     for (grp = hna_groups; grp; grp = grp->next) {
285       grp->probe_ok = true;
286     }
287   }
288 
289   // Print the current configuration
290   {
291     struct hna_group *grp;
292     int i = 0;
293     for (grp = hna_groups; grp; grp = grp->next, ++i) {
294       struct hna_list *lst;
295       struct ping_list *png;
296 
297       olsr_printf(1, "Group %d:\n", i);
298       for (lst = grp->hna_list; lst; lst = lst->next) {
299         char addr[INET_ADDRSTRLEN];
300         olsr_printf(1, "  HNA %s\n", get_ip_str(lst->hna_addr.v4.s_addr, addr, INET_ADDRSTRLEN));
301       }
302       for (png = grp->ping_hosts; png; png = png->next) {
303         olsr_printf(1, "  PING %s\n", png->ping_address);
304       }
305     }
306   }
307 
308   /* Register the GW check */
309   olsr_start_timer(hna_check_interval, 0, OLSR_TIMER_PERIODIC, &olsr_event_doing_hna, NULL, 0);
310   return 1;
311 }
312 
olsrd_plugin_fini(void)313 void olsrd_plugin_fini(void) {
314   if (!hna_groups) {
315     return;
316   }
317 
318   while (hna_groups->ping_hosts) {
319     struct ping_list* next = hna_groups->ping_hosts->next;
320     free(hna_groups->ping_hosts->ping_address);
321     free(hna_groups->ping_hosts);
322     hna_groups->ping_hosts = next;
323   }
324 
325   while (hna_groups->hna_list) {
326     struct hna_list * next = hna_groups->hna_list->next;
327     free(hna_groups->hna_list);
328     hna_groups->hna_list = next;
329   }
330 
331   free(hna_groups);
332   hna_groups = NULL;
333 }
334 
335 
336 /**
337  * Scheduled event to update the hna table,
338  * called from olsrd main thread to keep the hna table thread-safe
339  */
340 static void
olsr_event_doing_hna(void * foo)341 olsr_event_doing_hna(void *foo __attribute__ ((unused)))
342 {
343   struct hna_group* grp;
344   struct hna_list *li;
345 
346   update_routing();
347 
348   for (grp = hna_groups; grp; grp = grp->next) {
349     for (li = grp->hna_list; li; li = li->next) {
350       if (!li->hna_added) {
351         if (grp->probe_ok && li->active) {
352           olsr_printf(1, "Adding OLSR local HNA entry\n");
353           ip_prefix_list_add(&olsr_cnf->hna_entries, &li->hna_addr, li->hna_prefixlen);
354           li->hna_added = true;
355         }
356       } else {
357         if (!grp->probe_ok || !li->active) {
358           while (ip_prefix_list_remove(&olsr_cnf->hna_entries, &li->hna_addr, li->hna_prefixlen)) {
359             olsr_printf(1, "Removing OLSR local HNA entry\n");
360           }
361           li->hna_added = false;
362         }
363       }
364     }
365   }
366 }
367 
368 /**
369  * the threaded function which happens within an endless loop,
370  * reiterated every "Interval" sec (as given in the config or
371  * the default value)
372  */
373 static void
looped_checks(void * foo)374 *looped_checks(void *foo __attribute__ ((unused)))
375 {
376   for (;;) {
377     struct hna_group *grp;
378     struct hna_list *li;
379     struct timespec remainder_spec;
380     /* the time to wait in "Interval" sec (see connfig), default=5sec */
381     struct timespec sleeptime_spec = { ping_check_interval, 0L };
382 
383     for (grp = hna_groups; grp; grp = grp->next) {
384       for (li = grp->hna_list; li; li = li->next) {
385 
386     		// If this HNA is not active skip to the next one
387         if (!li->active)
388           continue;
389 
390         /* check for gw in table entry and if Ping IPs are given also do pings */
391         grp->probe_ok = check_gw(&li->hna_addr, li->hna_prefixlen, grp->ping_hosts);
392         if (grp->probe_ok)
393           break;	// Valid host found so we can bail out of the inner loop here
394       }
395     }
396 
397     while (nanosleep(&sleeptime_spec, &remainder_spec) < 0)
398       sleeptime_spec = remainder_spec;
399   }
400 
401   return NULL;
402 }
403 
404 /* -------------------------------------------------------------------------
405  * Function   : find_hna
406  * Description: Lookup an HNA that matches the specified parameters
407  * Input      : src_addr - IP address of the HNA to find
408  *              src_mask - Address mask of the HNA to find
409  * Output     : none
410  * Return     : The HNA specified or NULL when HNA not found
411  * Data Used  : none
412  * ------------------------------------------------------------------------- */
413 struct hna_list*
find_hna(uint32_t src_addr,uint32_t src_mask)414 find_hna(uint32_t src_addr, uint32_t src_mask)
415 {
416   struct hna_group * grp;
417   struct hna_list *li;
418   union olsr_ip_addr mask;
419 
420   for (grp = hna_groups; grp; grp = grp->next) {
421     for (li = grp->hna_list; li; li = li->next) {
422       olsr_prefix_to_netmask(&mask, li->hna_prefixlen);
423       if (li->hna_addr.v4.s_addr == src_addr && mask.v4.s_addr == src_mask) {
424         return li;
425       }
426     }
427   }
428   return NULL;
429 }
430 
431 /* -------------------------------------------------------------------------
432  * Function   : get_ip_str
433  * Description: Convert the specified address to an IPv4 compatible string
434  * Input      : address - IPv4 address to convert to string
435  *              s       - string buffer to contain the resulting string
436  *              maxlen  - maximum length of the string buffer
437  * Output     : none
438  * Return     : Pointer to the string buffer containing the result
439  * Data Used  : none
440  * ------------------------------------------------------------------------- */
441 char *
get_ip_str(uint32_t address,char * s,size_t maxlen)442 get_ip_str(uint32_t address, char *s, size_t maxlen)
443 {
444   struct sockaddr_in v4;
445 
446   v4.sin_addr.s_addr = address;
447   inet_ntop(AF_INET, &v4.sin_addr, s, maxlen);
448 
449   return s;
450 }
451 
452 /* -------------------------------------------------------------------------
453  * Function   : update_routing
454  * Description: Mark the HNAs in the HNA list(s) corresponding to the results
455  *              found in the routing table. HNAs that are found in the routing
456  *              table will be marked as 'active', otherwise they'll remain
457  *              inactive.
458  * Input      : nothing
459  * Output     : none
460  * Return     : -1 if an error occurred, 0 otherwise
461  * Data Used  : none
462  * ------------------------------------------------------------------------- */
463 int
update_routing(void)464 update_routing(void)
465 {
466   char buf[1024], iface[16];
467   uint32_t gate_addr, dest_addr, netmask;
468   unsigned int iflags;
469   int metric, refcnt, use;
470   struct hna_group *grp;
471   struct hna_list *li;
472 
473   FILE *fp = fopen(PROCENTRY_ROUTE, "r");
474   if (!fp) {
475     perror(PROCENTRY_ROUTE);
476     olsr_printf(1, "INET (IPv4) not configured in this system.\n");
477     return -1;
478   }
479 
480   // Phase 1: reset the 'checked' flag, during the check of the routing table we
481   // will (re)discover whether the HNA is valid or not.
482   for (grp = hna_groups; grp; grp = grp->next) {
483     for (li = grp->hna_list; li; li = li->next) {
484       li->checked = false;
485     }
486   }
487 
488   /*
489      olsr_printf(1, "Genmask         Destination     Gateway         "
490      "Flags Metric Ref    Use Iface\n");
491    */
492   while (fgets(buf, sizeof(buf), fp)) {
493     struct hna_list *hna;
494     char s_addr[INET_ADDRSTRLEN], s_mask[INET_ADDRSTRLEN];
495 
496     int num = sscanf(buf,
497                      "%15s %128X %128X %X %d %d %d %128X \n",
498                      iface,
499                      &dest_addr,
500                      &gate_addr,
501                      &iflags,
502                      &refcnt,
503                      &use,
504                      &metric,
505                      &netmask);
506     if (num < 8)
507       continue;
508 
509     get_ip_str(dest_addr, s_addr, INET_ADDRSTRLEN);
510     get_ip_str(netmask, s_mask, INET_ADDRSTRLEN);
511 
512     hna = find_hna(dest_addr, netmask);
513     if (hna == NULL) {	// Entry not found, try the next one
514       continue;
515     }
516 
517     if ((iflags & RTF_UP) && (metric != olsr_cnf->fib_metric_default)) {
518       hna->checked = true;
519     }
520   }
521   fclose(fp);
522 
523   // Phase 2: now copy the 'checked' flag to the 'active' flag.
524   // The total check is a 2-phase process so the ping check loop won't be
525   // disturbed too badly.
526   for (grp = hna_groups; grp; grp = grp->next) {
527     for (li = grp->hna_list; li; li = li->next) {
528       li->active = li->checked;
529     }
530   }
531 
532   return 0;
533 }
534 
535 /* -------------------------------------------------------------------------
536  * Function   : check_gw
537  * Description: Check the specified gateway(s) by sending a ping
538  * Input      : addr      - the address of the HNA to which the ping is related
539  *              prefixlen - the length of the prefix for this HNA
540  *              the_ping_list - list with related ping hosts
541  * Output     : none
542  * Return     : true if the ping host could be reached, false otherwise
543  * Data Used  : none
544  * ------------------------------------------------------------------------- */
545 static bool
check_gw(union olsr_ip_addr * addr,uint8_t prefixlen,struct ping_list * the_ping_list)546 check_gw(union olsr_ip_addr *addr, uint8_t prefixlen, struct ping_list *the_ping_list)
547 {
548   bool retval = false;
549   union olsr_ip_addr mask;
550 
551   olsr_prefix_to_netmask(&mask, prefixlen);
552 
553   /* don't ping, if there was no "Ping" IP addr in the config file */
554   if (the_ping_list != NULL) {
555     /*validate the found inet gw by pinging */
556     if (ping_is_possible(the_ping_list)) {
557       olsr_printf(1, "HNA[%08x/%08x](ping is possible) detected in routing table.\n", addr->v4.s_addr, mask.v4.s_addr);
558       retval = true;
559     }
560   } else {
561     olsr_printf(1, "HNA[%08x/%08x] detected in routing table.\n", addr->v4.s_addr, mask.v4.s_addr);
562     retval = true;
563   }
564 
565   if (retval == false) {
566     /* And we cast here since we get warnings on Win32 */
567     olsr_printf(1, "HNA[%08x/%08x] is invalid\n", (unsigned int)addr->v4.s_addr, (unsigned int)mask.v4.s_addr);
568   }
569   return retval;
570 }
571 
572 /* -------------------------------------------------------------------------
573  * Function   : ping_is_possible
574  * Description: Ping the specified host(s)
575  * Input      : the_ping_list - the list of hosts to ping
576  * Output     : none
577  * Return     : 1 if any host responded, 0 otherwise
578  * Data Used  : none
579  * ------------------------------------------------------------------------- */
580 static int
ping_is_possible(struct ping_list * the_ping_list)581 ping_is_possible(struct ping_list *the_ping_list)
582 {
583   struct ping_list *list;
584   for (list = the_ping_list; list; list = list->next) {
585     char ping_command[sizeof(ping_cmd) + INET6_ADDRSTRLEN];
586     snprintf(ping_command, sizeof(ping_command), ping_cmd, list->ping_address);
587     olsr_printf(1, "\nDo ping on (%s) %s ...\n", ping_cmd, list->ping_address);
588     if (system(ping_command) == 0) {
589       olsr_printf(1, "...OK\n\n");
590       return 1;
591     }
592     olsr_printf(1, "...FAILED\n\n");
593   }
594   return 0;
595 }
596 
597 /* -------------------------------------------------------------------------
598  * Function   : add_to_ping_list
599  * Description: Add a new ping host to the list of ping hosts
600  * Input      : ping_address - the address of the ping host
601  *              the_ping_list - the list of ping hosts
602  * Output     : none
603  * Return     : a pointer to the newly added ping host, i.e. start of the list
604  * Data Used  : none
605  * ------------------------------------------------------------------------- */
606 /* add the valid IPs to the head of the list */
607 static struct ping_list *
add_to_ping_list(const char * ping_address,struct ping_list * the_ping_list)608 add_to_ping_list(const char *ping_address, struct ping_list *the_ping_list)
609 {
610   struct ping_list *new = calloc(1, sizeof(struct ping_list));
611   if (!new) {
612     olsr_exit("DYN GW: Out of memory", EXIT_FAILURE);
613   }
614   new->ping_address = strdup(ping_address);
615   new->next = the_ping_list;
616   return new;
617 }
618 
619 /* -------------------------------------------------------------------------
620  * Function   : add_to_hna_list
621  * Description: Add a new HNA entry to the list of HNA entries
622  * Input      : list_root - the start of the list with HNA entries
623  *              hna_addr  - the address of the new HNA entry
624  *              prefixlen - the prefix-length of the new HNA entry
625  * Output     : none
626  * Return     : a pointer to the newly added HNA entry, i.e. start of the list
627  * Data Used  : none
628  * ------------------------------------------------------------------------- */
629 static struct hna_list *
add_to_hna_list(struct hna_list * list_root,union olsr_ip_addr * hna_addr,uint8_t hna_prefixlen)630 add_to_hna_list(struct hna_list *list_root, union olsr_ip_addr *hna_addr, uint8_t hna_prefixlen)
631 {
632   struct hna_list *new = calloc(1, sizeof(struct hna_list));
633   if (new == NULL) {
634     olsr_exit("DYN GW: Out of memory", EXIT_FAILURE);
635   }
636 
637   new->hna_addr.v4 = hna_addr->v4;
638   new->hna_prefixlen = hna_prefixlen;
639   new->hna_added = false;
640   new->next = list_root;
641   return new;
642 }
643 
644 /* -------------------------------------------------------------------------
645  * Function   : add_to_hna_group
646  * Description: Add a new HNA group to the list of HNA groups
647  * Input      : list_root - the start of the list with HNA groups
648  * Output     : none
649  * Return     : a pointer to the newly added HNA group, i.e. start of the list
650  * Data Used  : none
651  * ------------------------------------------------------------------------- */
652 static struct hna_group *
add_to_hna_group(struct hna_group * list_root)653 add_to_hna_group(struct hna_group *list_root)
654 {
655   struct hna_group *new = calloc(1, sizeof(struct hna_group));
656   if (new == NULL) {
657     olsr_exit("DYN GW: Out of memory", EXIT_FAILURE);
658   }
659 
660   new->next =  list_root;
661   return new;
662 }
663 
664 
665 #ifdef _WIN32
666 
667 /*
668  * Windows pthread compat stuff
669  */
670 static unsigned long __stdcall
ThreadWrapper(void * Para)671 ThreadWrapper(void *Para)
672 {
673   struct ThreadPara *Cast;
674   void *(*Func) (void *);
675   void *Arg;
676 
677   Cast = (struct ThreadPara *)Para;
678 
679   Func = Cast->Func;
680   Arg = Cast->Arg;
681 
682   HeapFree(GetProcessHeap(), 0, Para);
683 
684   Func(Arg);
685 
686   return 0;
687 }
688 
689 int
pthread_create(HANDLE * Hand,void * Attr,void * (* Func)(void *),void * Arg)690 pthread_create(HANDLE * Hand, void *Attr __attribute__ ((unused)), void *(*Func) (void *), void *Arg)
691 {
692   struct ThreadPara *Para;
693   unsigned long ThreadId;
694 
695   Para = HeapAlloc(GetProcessHeap(), 0, sizeof(struct ThreadPara));
696 
697   if (Para == NULL)
698     return -1;
699 
700   Para->Func = Func;
701   Para->Arg = Arg;
702 
703   *Hand = CreateThread(NULL, 0, ThreadWrapper, Para, 0, &ThreadId);
704 
705   if (*Hand == NULL)
706     return -1;
707 
708   return 0;
709 }
710 
711 int
pthread_kill(HANDLE Hand,int Sig)712 pthread_kill(HANDLE Hand, int Sig __attribute__ ((unused)))
713 {
714   if (!TerminateThread(Hand, 0))
715     return -1;
716 
717   return 0;
718 }
719 
720 int
pthread_mutex_init(HANDLE * Hand,void * Attr)721 pthread_mutex_init(HANDLE * Hand, void *Attr __attribute__ ((unused)))
722 {
723   *Hand = CreateMutex(NULL, FALSE, NULL);
724 
725   if (*Hand == NULL)
726     return -1;
727 
728   return 0;
729 }
730 
731 int
pthread_mutex_lock(HANDLE * Hand)732 pthread_mutex_lock(HANDLE * Hand)
733 {
734   if (WaitForSingleObject(*Hand, INFINITE) == WAIT_FAILED)
735     return -1;
736 
737   return 0;
738 }
739 
740 int
pthread_mutex_unlock(HANDLE * Hand)741 pthread_mutex_unlock(HANDLE * Hand)
742 {
743   if (!ReleaseMutex(*Hand))
744     return -1;
745 
746   return 0;
747 }
748 
749 #endif /* _WIN32 */
750 
751 /*
752  * Local Variables:
753  * c-basic-offset: 2
754  * indent-tabs-mode: nil
755  * End:
756  */
757