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