Fixed script and line-break quirks
[olsrd.git] / lib / nameservice / src / nameservice.c
1
2 /*
3  * Copyright (c) 2006, Jens Nachtigall <nachtigall@web.de>
4  * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
5  * Copyright (c) 2004, Andreas Tonnesen(andreto-at-olsr.org)
6  * Copyright (c) 2007, Sven-Ola <sven-ola@gmx.de>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright notice,
14  *   this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above copyright notice,
16  *   this list of conditions and the following disclaimer in the documentation
17  *   and/or other materials provided with the distribution.
18  * * Neither the name of the UniK olsr daemon nor the names of its contributors
19  *   may be used to endorse or promote products derived from this software
20  *   without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
29  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34
35 /*
36  * Dynamic linked library for UniK OLSRd
37  */
38
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <ctype.h>
44 #include <sys/types.h>
45 #include <regex.h>
46 #include <sys/stat.h>
47 #include <signal.h>
48 #include <fcntl.h>
49
50 #include "olsr.h"
51 #include "ipcalc.h"
52 #include "net_olsr.h"
53 #include "routing_table.h"
54 #include "mantissa.h"
55 #include "scheduler.h"
56 #include "parser.h"
57 #include "duplicate_set.h"
58 #include "tc_set.h"
59 #include "hna_set.h"
60 #include "mid_set.h"
61 #include "link_set.h"
62
63 #include "plugin_util.h"
64 #include "nameservice.h"
65 #include "mapwrite.h"
66 #include "compat.h"
67
68 /* config parameters */
69 static char my_hosts_file[MAX_FILE + 1];
70 static char my_sighup_pid_file[MAX_FILE + 1];
71
72 static char my_add_hosts[MAX_FILE + 1];
73 static char my_suffix[MAX_SUFFIX];
74 static int my_interval = EMISSION_INTERVAL;
75 static double my_timeout = NAME_VALID_TIME;
76 static char my_resolv_file[MAX_FILE + 1];
77 static char my_services_file[MAX_FILE + 1];
78 static char my_name_change_script[MAX_FILE + 1];
79 static char my_services_change_script[MAX_FILE + 1];
80 static char latlon_in_file[MAX_FILE + 1];
81 static char my_latlon_file[MAX_FILE + 1];
82 float my_lat = 0.0, my_lon = 0.0;
83
84 /* the databases (using hashing)
85  * for hostnames, service_lines and dns-servers
86  *
87  * my own hostnames, service_lines and dns-servers
88  * are store in a linked list (without hashing)
89  * */
90 static struct list_node name_list[HASHSIZE];
91 struct name_entry *my_names = NULL;
92 struct timer_entry *name_table_write = NULL;
93 static olsr_bool name_table_changed = OLSR_TRUE;
94
95 static struct list_node service_list[HASHSIZE];
96 static struct name_entry *my_services = NULL;
97 static olsr_bool service_table_changed = OLSR_TRUE;
98
99 static struct list_node forwarder_list[HASHSIZE];
100 static struct name_entry *my_forwarders = NULL;
101 static olsr_bool forwarder_table_changed = OLSR_TRUE;
102
103 struct list_node latlon_list[HASHSIZE];
104 static olsr_bool latlon_table_changed = OLSR_TRUE;
105
106 /* backoff timer for writing changes into a file */
107 struct timer_entry *write_file_timer = NULL;
108
109 /* periodic message generation */
110 struct timer_entry *msg_gen_timer = NULL;
111
112 /* regular expression to be matched by valid hostnames, compiled in name_init() */
113 static regex_t regex_t_name;
114 static regmatch_t regmatch_t_name;
115
116 /* regular expression to be matched by valid service_lines, compiled in name_init() */
117 static regex_t regex_t_service;
118 static int pmatch_service = 10;
119 static regmatch_t regmatch_t_service[10];
120
121 /**
122  * do initialization
123  */
124 void
125 name_constructor(void)
126 {
127   int i;
128
129 #ifdef WIN32
130   int len;
131
132   GetWindowsDirectory(my_hosts_file, MAX_FILE - 12);
133   GetWindowsDirectory(my_services_file, MAX_FILE - 12);
134   GetWindowsDirectory(my_resolv_file, MAX_FILE - 12);
135
136   len = strlen(my_hosts_file);
137   if (my_hosts_file[len - 1] != '\\')
138     strscat(my_hosts_file, "\\", sizeof(my_host_file));
139   strscat(my_hosts_file, "hosts_olsr", sizeof(my_host_file));
140
141   len = strlen(my_services_file);
142   if (my_services_file[len - 1] != '\\')
143     strscat(my_services_file, "\\", sizeof(my_services_file));
144   strscat(my_services_file, "services_olsr", sizeof(my_services_file));
145
146   len = strlen(my_resolv_file);
147   if (my_resolv_file[len - 1] != '\\')
148     strscat(my_resolv_file, "\\", sizeof(my_resolv_file));
149   strscat(my_resolv_file, "resolvconf_olsr", sizeof(my_resolv_file));
150 #else
151   strscpy(my_hosts_file, "/var/run/hosts_olsr", sizeof(my_hosts_file));
152   strscpy(my_services_file, "/var/run/services_olsr", sizeof(my_services_file));
153   strscpy(my_resolv_file, "/var/run/resolvconf_olsr", sizeof(my_resolv_file));
154   *my_sighup_pid_file = 0;
155 #endif
156
157   my_suffix[0] = '\0';
158   my_add_hosts[0] = '\0';
159   my_latlon_file[0] = '\0';
160   latlon_in_file[0] = '\0';
161   my_name_change_script[0] = '\0';
162   my_services_change_script[0] = '\0';
163
164   /* init the lists heads */
165   for (i = 0; i < HASHSIZE; i++) {
166     list_head_init(&name_list[i]);
167     list_head_init(&forwarder_list[i]);
168     list_head_init(&service_list[i]);
169     list_head_init(&latlon_list[i]);
170   }
171
172 }
173
174 static int
175 set_nameservice_server(const char *value, void *data, set_plugin_parameter_addon addon)
176 {
177   union olsr_ip_addr ip;
178   struct name_entry **v = data;
179   if (0 == strlen(value)) {
180     *v = add_name_to_list(*v, "", addon.ui, NULL);
181     OLSR_PRINTF(1, "%s got %s (main address)\n", "Got", value);
182     return 0;
183   } else if (0 < inet_pton(olsr_cnf->ip_version, value, &ip)) {
184     *v = add_name_to_list(*v, "", addon.ui, &ip);
185     OLSR_PRINTF(1, "%s got %s\n", "Got", value);
186     return 0;
187   } else {
188     OLSR_PRINTF(0, "Illegal IP address \"%s\"", value);
189   }
190   return 1;
191 }
192
193 static int
194 set_nameservice_name(const char *value, void *data, set_plugin_parameter_addon addon)
195 {
196   struct name_entry **v = data;
197   if (0 < strlen(value)) {
198     *v = add_name_to_list(*v, value, addon.ui, NULL);
199     OLSR_PRINTF(1, "%s got %s (main address)\n", "Got", value);
200     return 0;
201   } else {
202     OLSR_PRINTF(0, "Illegal name \"%s\"", value);
203   }
204   return 1;
205 }
206
207 static int
208 set_nameservice_host(const char *value, void *data, set_plugin_parameter_addon addon)
209 {
210   union olsr_ip_addr ip;
211   struct name_entry **v = data;
212   if (0 < inet_pton(olsr_cnf->ip_version, addon.pc, &ip)) {
213     // the IP is validated later
214     *v = add_name_to_list(*v, value, NAME_HOST, &ip);
215     OLSR_PRINTF(1, "%s: %s got %s\n", "Got", addon.pc, value);
216     return 0;
217   } else {
218     OLSR_PRINTF(0, "%s: Illegal IP address \"%s\"", addon.pc, value);
219   }
220   return 1;
221 }
222
223 static int
224 set_nameservice_float(const char *value, void *data, set_plugin_parameter_addon addon __attribute__ ((unused)))
225 {
226   if (data != NULL) {
227     sscanf(value, "%f", (float *)data);
228     OLSR_PRINTF(1, "%s float %f\n", "Got", *(float *)data);
229   } else {
230     OLSR_PRINTF(0, "%s float %s\n", "Ignored", value);
231   }
232   return 0;
233 }
234
235 static const struct olsrd_plugin_parameters plugin_parameters[] = {
236   {.name = "interval",.set_plugin_parameter = &set_plugin_int,.data = &my_interval},
237   {.name = "timeout",.set_plugin_parameter = &set_nameservice_float,.data = &my_timeout},
238   {.name = "sighup-pid-file",.set_plugin_parameter = &set_plugin_string,.data = &my_sighup_pid_file,.addon =
239    {sizeof(my_sighup_pid_file)}
240    }
241   ,
242   {.name = "hosts-file",.set_plugin_parameter = &set_plugin_string,.data = &my_hosts_file,.addon = {sizeof(my_hosts_file)}
243    }
244   ,
245   {.name = "name-change-script",.set_plugin_parameter = &set_plugin_string,.data = &my_name_change_script,.addon =
246    {sizeof(my_name_change_script)}
247    }
248   ,
249   {.name = "services-change-script",.set_plugin_parameter = &set_plugin_string,.data = &my_services_change_script,.addon =
250    {sizeof(my_services_change_script)}
251    }
252   ,
253   {.name = "resolv-file",.set_plugin_parameter = &set_plugin_string,.data = &my_resolv_file,.addon = {sizeof(my_resolv_file)}
254    }
255   ,
256   {.name = "suffix",.set_plugin_parameter = &set_plugin_string,.data = &my_suffix,.addon = {sizeof(my_suffix)}
257    }
258   ,
259   {.name = "add-hosts",.set_plugin_parameter = &set_plugin_string,.data = &my_add_hosts,.addon = {sizeof(my_add_hosts)}
260    }
261   ,
262   {.name = "services-file",.set_plugin_parameter = &set_plugin_string,.data = &my_services_file,.addon = {sizeof(my_services_file)}
263    }
264   ,
265   {.name = "lat",.set_plugin_parameter = &set_nameservice_float,.data = &my_lat}
266   ,
267   {.name = "lon",.set_plugin_parameter = &set_nameservice_float,.data = &my_lon}
268   ,
269   {.name = "latlon-file",.set_plugin_parameter = &set_plugin_string,.data = &my_latlon_file,.addon = {sizeof(my_latlon_file)}
270    }
271   ,
272   {.name = "latlon-infile",.set_plugin_parameter = &set_plugin_string,.data = &latlon_in_file,.addon = {sizeof(latlon_in_file)}
273    }
274   ,
275   {.name = "dns-server",.set_plugin_parameter = &set_nameservice_server,.data = &my_forwarders,.addon = {NAME_FORWARDER}
276    }
277   ,
278   {.name = "name",.set_plugin_parameter = &set_nameservice_name,.data = &my_names,.addon = {NAME_HOST}
279    }
280   ,
281   {.name = "service",.set_plugin_parameter = &set_nameservice_name,.data = &my_services,.addon = {NAME_SERVICE}
282    }
283   ,
284   {.name = "",.set_plugin_parameter = &set_nameservice_host,.data = &my_names}
285   ,
286 };
287
288 void
289 olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
290 {
291   *params = plugin_parameters;
292   *size = sizeof(plugin_parameters) / sizeof(*plugin_parameters);
293 }
294
295 /**
296  * queue the name/forwarder/service given in value
297  * to the front of my_list
298  */
299 struct name_entry *
300 add_name_to_list(struct name_entry *my_list, const char *value, int type, const union olsr_ip_addr *ip)
301 {
302   struct name_entry *tmp = olsr_malloc(sizeof(struct name_entry),
303                                        "new name_entry add_name_to_list");
304   tmp->name = strndup(value, MAX_NAME);
305   tmp->len = strlen(tmp->name);
306   tmp->type = type;
307   // all IPs with value 0 will be set to main_addr later
308   if (ip == NULL)
309     memset(&tmp->ip, 0, sizeof(tmp->ip));
310   else
311     tmp->ip = *ip;
312   tmp->next = my_list;
313   return tmp;
314 }
315
316 /**
317  * last initialization
318  *
319  * we have to do this here because some things like main_addr
320  * or the dns suffix (for validation) are not known before
321  *
322  * this is beause of the order in which the plugin is initialized
323  * by the plugin loader:
324  *   - first the parameters are sent
325  *   - then register_olsr_data() from olsrd_plugin.c is called
326  *     which sets up main_addr and some other variables
327  *   - register_olsr_data() then then finally calls this function
328  */
329 int
330 name_init(void)
331 {
332   struct name_entry *name;
333   union olsr_ip_addr ipz;
334   int ret;
335
336   //regex string for validating the hostnames
337   const char *regex_name = "^[[:alnum:]_.-]+$";
338   //regex string for the service line
339   size_t regex_size = 256 * sizeof(char) + strlen(my_suffix);
340   char *regex_service = olsr_malloc(regex_size, "new *char from name_init for regex_service");
341   memset(&ipz, 0, sizeof(ipz));
342
343   //compile the regex from the string
344   if ((ret = regcomp(&regex_t_name, regex_name, REG_EXTENDED)) != 0) {
345     /* #2: call regerror() if regcomp failed
346      * commented out, because only for debuggin needed
347      *
348      int errmsgsz = regerror(ret, &regex_t_name, NULL, 0);
349      char *errmsg = malloc(errmsgsz);
350      regerror(ret, &regex_t_name, errmsg, errmsgsz);
351      fprintf(stderr, "regcomp: %s", errmsg);
352      free(errmsg);
353      regfree(&regex_t_name);
354      * */
355     OLSR_PRINTF(0, "compilation of regex \"%s\" for hostname failed", regex_name);
356   }
357   // a service line is something like prot://hostname.suffix:port|tcp|my little description about this service
358   //                  for example     http://router.olsr:80|tcp|my homepage
359   //                     prot     ://  (hostname.suffix     OR         ip)
360   //regex_service = "^[[:alnum:]]+://(([[:alnum:]_.-]+.olsr)|([[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}))
361   //                 :    port              /path      |(tcp OR udp) |short description
362   //                 :[[:digit:]]+[[:alnum:]/?._=#-]*\\|(tcp|udp)\\|[^|[:cntrl:]]+$";
363   strscpy(regex_service, "^[[:alnum:]]+://(([[:alnum:]_.-]+", regex_size);
364   strscat(regex_service, my_suffix, regex_size);
365   strscat(regex_service,
366           ")|([[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3})):[[:digit:]]+[[:alnum:]/?._=#-]*\\|(tcp|udp)\\|[^|[:cntrl:]]+$",
367           regex_size);
368
369   /* #1: call regcomp() to compile the regex */
370   if ((ret = regcomp(&regex_t_service, regex_service, REG_EXTENDED)) != 0) {
371     /* #2: call regerror() if regcomp failed
372      * commented out, because only for debuggin needed
373      *
374      int errmsgsz = regerror(ret, &regex_t_service, NULL, 0);
375      char *errmsg = malloc(errmsgsz);
376      regerror(ret, &regex_t_service, errmsg, errmsgsz);
377      fprintf(stderr, "regcomp: %s", errmsg);
378      free(errmsg);
379      regfree(&regex_t_service);
380      * */
381     OLSR_PRINTF(0, "compilation of regex \"%s\" for hostname failed", regex_name);
382   }
383   free(regex_service);
384   regex_service = NULL;
385
386   //fill in main addr for all entries with ip==0
387   //this does not matter for service, because the ip does not matter
388   //for service
389
390   for (name = my_names; name != NULL; name = name->next) {
391     if (ipequal(&name->ip, &ipz)) {
392       OLSR_PRINTF(2, "NAME PLUGIN: insert main addr for name %s \n", name->name);
393       name->ip = olsr_cnf->main_addr;
394     }
395   }
396   for (name = my_forwarders; name != NULL; name = name->next) {
397     if (name->ip.v4.s_addr == 0) {
398       OLSR_PRINTF(2, "NAME PLUGIN: insert main addr for name %s \n", name->name);
399       name->ip = olsr_cnf->main_addr;
400     }
401   }
402
403   //check if entries I want to announce myself are valid and allowed
404   my_names = remove_nonvalid_names_from_list(my_names, NAME_HOST);
405   my_forwarders = remove_nonvalid_names_from_list(my_forwarders, NAME_FORWARDER);
406   my_services = remove_nonvalid_names_from_list(my_services, NAME_SERVICE);
407
408   /* register functions with olsrd */
409   olsr_parser_add_function(&olsr_parser, PARSER_TYPE);
410
411   /* periodic message generation */
412   msg_gen_timer = olsr_start_timer(my_interval * MSEC_PER_SEC, EMISSION_JITTER, OLSR_TIMER_PERIODIC, &olsr_namesvc_gen, NULL, 0);
413
414   mapwrite_init(my_latlon_file);
415
416   return 1;
417 }
418
419 struct name_entry *
420 remove_nonvalid_names_from_list(struct name_entry *my_list, int type)
421 {
422   struct name_entry *next = my_list;
423   olsr_bool valid = OLSR_FALSE;
424   if (my_list == NULL) {
425     return NULL;
426   }
427
428   switch (type) {
429   case NAME_HOST:
430     valid = is_name_wellformed(my_list->name) && allowed_ip(&my_list->ip);
431     break;
432   case NAME_FORWARDER:
433     valid = allowed_ip(&my_list->ip);
434     break;
435   case NAME_SERVICE:
436     valid = allowed_service(my_list->name);
437     break;
438   case NAME_LATLON:
439     valid = is_latlon_wellformed(my_list->name);
440     break;
441   }
442
443   if (!valid) {
444     struct ipaddr_str strbuf;
445     OLSR_PRINTF(1, "NAME PLUGIN: invalid or malformed parameter %s (%s), fix your config!\n", my_list->name,
446                 olsr_ip_to_string(&strbuf, &my_list->ip));
447     next = my_list->next;
448     free(my_list->name);
449     my_list->name = NULL;
450     free(my_list);
451     my_list = NULL;
452     return remove_nonvalid_names_from_list(next, type);
453   } else {
454     struct ipaddr_str strbuf;
455     OLSR_PRINTF(2, "NAME PLUGIN: validate parameter %s (%s) -> OK\n", my_list->name, olsr_ip_to_string(&strbuf, &my_list->ip));
456     my_list->next = remove_nonvalid_names_from_list(my_list->next, type);
457     return my_list;
458   }
459 }
460
461 /**
462  * called at unload: free everything
463  *
464  * XXX: should I delete the hosts/services/resolv.conf files on exit?
465  */
466 void
467 name_destructor(void)
468 {
469   OLSR_PRINTF(2, "NAME PLUGIN: exit. cleaning up...\n");
470
471   free_name_entry_list(&my_names);
472   free_name_entry_list(&my_services);
473   free_name_entry_list(&my_forwarders);
474
475   free_all_list_entries(name_list);
476   free_all_list_entries(service_list);
477   free_all_list_entries(forwarder_list);
478   free_all_list_entries(latlon_list);
479
480   olsr_stop_timer(write_file_timer);
481   olsr_stop_timer(msg_gen_timer);
482
483   regfree(&regex_t_name);
484   regfree(&regex_t_service);
485   mapwrite_exit();
486 }
487
488 /* free all list entries */
489 void
490 free_all_list_entries(struct list_node *this_db_list)
491 {
492   struct db_entry *db;
493   struct list_node *list_head, *list_node, *list_node_next;
494
495   int i;
496
497   for (i = 0; i < HASHSIZE; i++) {
498
499     list_head = &this_db_list[i];
500
501     for (list_node = list_head->next; list_node != list_head; list_node = list_node_next) {
502
503       /* prefetch next node before loosing context */
504       list_node_next = list_node->next;
505
506       db = list2db(list_node);
507       olsr_namesvc_delete_db_entry(db);
508     }
509   }
510 }
511
512 /**
513  * The write file timer has fired.
514  */
515 void
516 olsr_expire_write_file_timer(void *context __attribute__ ((unused)))
517 {
518   write_file_timer = NULL;
519
520   write_resolv_file();          /* if forwarder_table_changed */
521   write_hosts_file();           /* if name_table_changed */
522   write_services_file();        /* if service_table_changed */
523 #ifdef WIN32
524   write_latlon_file();          /* if latlon_table_changed */
525 #endif
526 }
527
528 /*
529  * Kick a timer to write everything into a file.
530  * This also paces things a bit.
531  */
532 static void
533 olsr_start_write_file_timer(void)
534 {
535   if (write_file_timer) {
536     return;
537   }
538
539   write_file_timer = olsr_start_timer(5 * MSEC_PER_SEC, 5, OLSR_TIMER_ONESHOT, olsr_expire_write_file_timer, NULL, 0);
540 }
541
542 /*
543  * Delete and unlink db_entry.
544  */
545 void
546 olsr_namesvc_delete_db_entry(struct db_entry *db)
547 {
548   struct ipaddr_str strbuf;
549   OLSR_PRINTF(2, "NAME PLUGIN: %s timed out... deleting\n", olsr_ip_to_string(&strbuf, &db->originator));
550
551   olsr_start_write_file_timer();
552   olsr_stop_timer(db->db_timer);        /* stop timer if running */
553
554   /* Delete */
555   free_name_entry_list(&db->names);
556   list_remove(&db->db_list);
557   free(db);
558 }
559
560 /**
561  * Callback for the db validity timer.
562  */
563 static void
564 olsr_nameservice_expire_db_timer(void *context)
565 {
566   struct db_entry *db;
567
568   db = (struct db_entry *)context;
569   db->db_timer = NULL;          /* be pedandic */
570
571   olsr_namesvc_delete_db_entry(db);
572 }
573
574 /**
575  * Scheduled event: generate and send NAME packet
576  */
577 void
578 olsr_namesvc_gen(void *foo __attribute__ ((unused)))
579 {
580   /* send buffer: huge */
581   char buffer[10240];
582   union olsr_message *message = (union olsr_message *)buffer;
583   struct interface *ifn;
584   int namesize;
585
586   /* fill message */
587   if (olsr_cnf->ip_version == AF_INET) {
588     /* IPv4 */
589     message->v4.olsr_msgtype = MESSAGE_TYPE;
590     message->v4.olsr_vtime = reltime_to_me(my_timeout * MSEC_PER_SEC);
591     memcpy(&message->v4.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
592     message->v4.ttl = MAX_TTL;
593     message->v4.hopcnt = 0;
594     message->v4.seqno = htons(get_msg_seqno());
595
596     namesize = encap_namemsg((struct namemsg *)&message->v4.message);
597     namesize = namesize + sizeof(struct olsrmsg);
598
599     message->v4.olsr_msgsize = htons(namesize);
600   } else {
601     /* IPv6 */
602     message->v6.olsr_msgtype = MESSAGE_TYPE;
603     message->v6.olsr_vtime = reltime_to_me(my_timeout * MSEC_PER_SEC);
604     memcpy(&message->v6.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
605     message->v6.ttl = MAX_TTL;
606     message->v6.hopcnt = 0;
607     message->v6.seqno = htons(get_msg_seqno());
608
609     namesize = encap_namemsg((struct namemsg *)&message->v6.message);
610     namesize = namesize + sizeof(struct olsrmsg6);
611
612     message->v6.olsr_msgsize = htons(namesize);
613   }
614
615   /* looping trough interfaces */
616   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
617     OLSR_PRINTF(3, "NAME PLUGIN: Generating packet - [%s]\n", ifn->int_name);
618
619     if (net_outbuffer_push(ifn, message, namesize) != namesize) {
620       /* send data and try again */
621       net_output(ifn);
622       if (net_outbuffer_push(ifn, message, namesize) != namesize) {
623         OLSR_PRINTF(1, "NAME PLUGIN: could not send on interface: %s\n", ifn->int_name);
624       }
625     }
626   }
627 }
628
629 /**
630  * Parse name olsr message of NAME type
631  */
632 void
633 olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr)
634 {
635   struct namemsg *namemessage;
636   union olsr_ip_addr originator;
637   olsr_reltime vtime;
638   int size;
639   olsr_u16_t seqno;
640
641   /* Fetch the originator of the messsage */
642   if (olsr_cnf->ip_version == AF_INET) {
643     memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize);
644     seqno = ntohs(m->v4.seqno);
645   } else {
646     memcpy(&originator, &m->v6.originator, olsr_cnf->ipsize);
647     seqno = ntohs(m->v6.seqno);
648   }
649
650   /* Fetch the message based on IP version */
651   if (olsr_cnf->ip_version == AF_INET) {
652     vtime = me_to_reltime(m->v4.olsr_vtime);
653     size = ntohs(m->v4.olsr_msgsize);
654     namemessage = (struct namemsg *)&m->v4.message;
655   } else {
656     vtime = me_to_reltime(m->v6.olsr_vtime);
657     size = ntohs(m->v6.olsr_msgsize);
658     namemessage = (struct namemsg *)&m->v6.message;
659   }
660
661   /* Check if message originated from this node.
662      If so - back off */
663   if (ipequal(&originator, &olsr_cnf->main_addr))
664     return;
665
666   /* Check that the neighbor this message was received from is symmetric.
667      If not - back off */
668   if (check_neighbor_link(ipaddr) != SYM_LINK) {
669     struct ipaddr_str strbuf;
670     OLSR_PRINTF(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(&strbuf, ipaddr));
671     return;
672   }
673
674   update_name_entry(&originator, namemessage, size, vtime);
675 }
676
677 /**
678  * Encapsulate a name message into a packet.
679  *
680  * It assumed that there is enough space in the buffer to do this!
681  *
682  * Returns: the length of the message that was appended
683  */
684 int
685 encap_namemsg(struct namemsg *msg)
686 {
687   struct name_entry *my_name;
688   struct name_entry *my_service;
689
690   // add the hostname, service and forwarder entries after the namemsg header
691   char *pos = (char *)msg + sizeof(struct namemsg);
692   short i = 0;
693
694   // names
695   for (my_name = my_names; my_name != NULL; my_name = my_name->next) {
696     pos = create_packet((struct name *)pos, my_name);
697     i++;
698   }
699   // forwarders
700   for (my_name = my_forwarders; my_name != NULL; my_name = my_name->next) {
701     pos = create_packet((struct name *)pos, my_name);
702     i++;
703   }
704   // services
705   for (my_service = my_services; my_service != NULL; my_service = my_service->next) {
706     pos = create_packet((struct name *)pos, my_service);
707     i++;
708   }
709   // latlon
710   if ('\0' != latlon_in_file[0]) {
711     FILE *in = fopen(latlon_in_file, "r");
712     if (in != NULL) {
713       fscanf(in, "%f,%f", &my_lat, &my_lon);
714       fclose(in);
715     } else {
716       OLSR_PRINTF(0, "NAME PLUGIN: cant read latlon in file %s\n", latlon_in_file);
717     }
718   }
719   if (0.0 != my_lat && 0.0 != my_lon) {
720     char s[64];
721     struct name_entry e;
722     memset(&e, 0, sizeof(e));
723     sprintf(s, "%f,%f,%d", my_lat, my_lon, get_isdefhna_latlon());
724     e.len = strlen(s);
725     e.type = NAME_LATLON;
726     e.name = s;
727     lookup_defhna_latlon(&e.ip);
728     pos = create_packet((struct name *)pos, &e);
729     i++;
730   }
731   // write the namemsg header with the number of announced entries and the protocol version
732   msg->nr_names = htons(i);
733   msg->version = htons(NAME_PROTOCOL_VERSION);
734
735   return pos - (char *)msg;     //length
736 }
737
738 /**
739  * convert each of my to be announced name_entries into network
740  * compatible format
741  *
742  * return the length of the name packet
743  */
744 char *
745 create_packet(struct name *to, struct name_entry *from)
746 {
747   char *pos = (char *)to;
748   int k;
749   struct ipaddr_str strbuf;
750   OLSR_PRINTF(3, "NAME PLUGIN: Announcing name %s (%s) %d\n", from->name, olsr_ip_to_string(&strbuf, &from->ip), from->len);
751   to->type = htons(from->type);
752   to->len = htons(from->len);
753   to->ip = from->ip;
754   pos += sizeof(struct name);
755   memcpy(pos, from->name, from->len);
756   pos += from->len;
757   for (k = from->len; (k & 3) != 0; k++)
758     *pos++ = '\0';
759   return pos;
760 }
761
762 /**
763  * decapsulate a received name, service or forwarder and update the corresponding hash table if necessary
764  */
765 void
766 decap_namemsg(struct name *from_packet, struct name_entry **to, olsr_bool * this_table_changed)
767 {
768   struct ipaddr_str strbuf;
769   struct name_entry *tmp;
770   struct name_entry *already_saved_name_entries;
771   char *name = (char *)from_packet + sizeof(struct name);
772   int type_of_from_packet = ntohs(from_packet->type);
773   unsigned int len_of_name = ntohs(from_packet->len);
774   OLSR_PRINTF(4, "NAME PLUGIN: decap type=%d, len=%d, name=%s\n", type_of_from_packet, len_of_name, name);
775
776   //XXX: should I check the from_packet->ip here? If so, why not also check the ip from HOST and SERVICE?
777   if ((type_of_from_packet == NAME_HOST && !is_name_wellformed(name))
778       || (type_of_from_packet == NAME_SERVICE && !is_service_wellformed(name))
779       || (type_of_from_packet == NAME_LATLON && !is_latlon_wellformed(name))) {
780     OLSR_PRINTF(4, "NAME PLUGIN: invalid name [%s] received, skipping.\n", name);
781     return;
782   }
783   //ignore all packets with a too long name
784   //or a spoofed len of its included name string
785   if (len_of_name > MAX_NAME || strlen(name) != len_of_name || NULL != strchr(name, '\\') || NULL != strchr(name, '\'')) {
786     OLSR_PRINTF(4, "NAME PLUGIN: from_packet->len %d > MAX_NAME %d or from_packet->len %d !0 strlen(name [%s] in packet)\n",
787                 len_of_name, MAX_NAME, len_of_name, name);
788     return;
789   }
790   // don't insert the received entry again, if it has already been inserted in the hash table.
791   // Instead only the validity time is set in insert_new_name_in_list function, which calls this one
792   for (already_saved_name_entries = (*to); already_saved_name_entries != NULL;
793        already_saved_name_entries = already_saved_name_entries->next) {
794     if ((type_of_from_packet == NAME_HOST || type_of_from_packet == NAME_SERVICE)
795         && strncmp(already_saved_name_entries->name, name, len_of_name) == 0) {
796       OLSR_PRINTF(4, "NAME PLUGIN: received name or service entry %s (%s) already in hash table\n", name,
797                   olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
798       return;
799     } else if (type_of_from_packet == NAME_FORWARDER && ipequal(&already_saved_name_entries->ip, &from_packet->ip)) {
800       OLSR_PRINTF(4, "NAME PLUGIN: received forwarder entry %s (%s) already in hash table\n", name,
801                   olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
802       return;
803     } else if (type_of_from_packet == NAME_LATLON) {
804       if (0 != strncmp(already_saved_name_entries->name, name, len_of_name)) {
805         OLSR_PRINTF(4, "NAME PLUGIN: updating name %s -> %s (%s)\n", already_saved_name_entries->name, name,
806                     olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
807         free(already_saved_name_entries->name);
808         already_saved_name_entries->name = olsr_malloc(len_of_name + 1, "upd name_entry name");
809         strscpy(already_saved_name_entries->name, name, len_of_name + 1);
810
811         *this_table_changed = OLSR_TRUE;
812         olsr_start_write_file_timer();
813       }
814       if (!ipequal(&already_saved_name_entries->ip, &from_packet->ip)) {
815         struct ipaddr_str strbuf2, strbuf3;
816         OLSR_PRINTF(4, "NAME PLUGIN: updating ip %s -> %s (%s)\n", olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip),
817                     olsr_ip_to_string(&strbuf2, &from_packet->ip), olsr_ip_to_string(&strbuf3, &already_saved_name_entries->ip));
818         already_saved_name_entries->ip = from_packet->ip;
819
820         *this_table_changed = OLSR_TRUE;
821         olsr_start_write_file_timer();
822       }
823       if (!*this_table_changed) {
824         OLSR_PRINTF(4, "NAME PLUGIN: received latlon entry %s (%s) already in hash table\n", name,
825                     olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
826       }
827       return;
828     }
829   }
830
831   //if not yet known entry
832   tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry");
833   tmp->type = ntohs(from_packet->type);
834   tmp->len = len_of_name > MAX_NAME ? MAX_NAME : ntohs(from_packet->len);
835   tmp->name = olsr_malloc(tmp->len + 1, "new name_entry name");
836   tmp->ip = from_packet->ip;
837   strscpy(tmp->name, name, tmp->len + 1);
838
839   OLSR_PRINTF(3, "\nNAME PLUGIN: create new name/service/forwarder entry %s (%s) [len=%d] [type=%d] in linked list\n", tmp->name,
840               olsr_ip_to_string(&strbuf, &tmp->ip), tmp->len, tmp->type);
841
842   *this_table_changed = OLSR_TRUE;
843   olsr_start_write_file_timer();
844
845   // queue to front
846   tmp->next = *to;
847   *to = tmp;
848 }
849
850 /**
851  * unpack the received message and delegate to the decapsulation function for each
852  * name/service/forwarder entry in the message
853  */
854 void
855 update_name_entry(union olsr_ip_addr *originator, struct namemsg *msg, int msg_size, olsr_reltime vtime)
856 {
857   struct ipaddr_str strbuf;
858   char *pos, *end_pos;
859   struct name *from_packet;
860   int i;
861
862   OLSR_PRINTF(3, "NAME PLUGIN: Received Message from %s\n", olsr_ip_to_string(&strbuf, originator));
863
864   if (ntohs(msg->version) != NAME_PROTOCOL_VERSION) {
865     OLSR_PRINTF(3, "NAME PLUGIN: ignoring wrong version %d\n", msg->version);
866     return;
867   }
868
869   /* now add the names from the message */
870   pos = (char *)msg + sizeof(struct namemsg);
871   end_pos = pos + msg_size - sizeof(struct name *);     // at least one struct name has to be left
872
873   for (i = ntohs(msg->nr_names); i > 0 && pos < end_pos; i--) {
874     from_packet = (struct name *)pos;
875
876     switch (ntohs(from_packet->type)) {
877     case NAME_HOST:
878       insert_new_name_in_list(originator, name_list, from_packet, &name_table_changed, vtime);
879       break;
880     case NAME_FORWARDER:
881       insert_new_name_in_list(originator, forwarder_list, from_packet, &forwarder_table_changed, vtime);
882       break;
883     case NAME_SERVICE:
884       insert_new_name_in_list(originator, service_list, from_packet, &service_table_changed, vtime);
885       break;
886     case NAME_LATLON:
887       insert_new_name_in_list(originator, latlon_list, from_packet, &latlon_table_changed, vtime);
888       break;
889     default:
890       OLSR_PRINTF(3, "NAME PLUGIN: Received Message of unknown type [%d] from (%s)\n", from_packet->type,
891                   olsr_ip_to_string(&strbuf, originator));
892       break;
893     }
894
895     pos += sizeof(struct name);
896     pos += 1 + ((ntohs(from_packet->len) - 1) | 3);
897   }
898   if (i != 0)
899     OLSR_PRINTF(4, "NAME PLUGIN: Lost %d entries in received packet due to length inconsistency (%s)\n", i,
900                 olsr_ip_to_string(&strbuf, originator));
901 }
902
903 /**
904  * insert all the new names,services and forwarders from a received packet into the
905  * corresponding entry for this ip in the corresponding hash table
906  */
907 void
908 insert_new_name_in_list(union olsr_ip_addr *originator, struct list_node *this_list, struct name *from_packet,
909                         olsr_bool * this_table_changed, olsr_reltime vtime)
910 {
911   int hash;
912   struct db_entry *entry;
913   struct list_node *list_head, *list_node;
914
915   olsr_bool entry_found = OLSR_FALSE;
916
917   hash = olsr_ip_hashing(originator);
918
919   /* find the entry for originator, if there is already one */
920   list_head = &this_list[hash];
921   for (list_node = list_head->next; list_node != list_head; list_node = list_node->next) {
922
923     entry = list2db(list_node);
924
925     if (ipequal(originator, &entry->originator)) {
926       struct ipaddr_str strbuf;
927       // found
928       OLSR_PRINTF(4, "NAME PLUGIN: found entry for (%s) in its hash table\n", olsr_ip_to_string(&strbuf, originator));
929
930       //delegate to function for parsing the packet and linking it to entry->names
931       decap_namemsg(from_packet, &entry->names, this_table_changed);
932
933       olsr_set_timer(&entry->db_timer, vtime, OLSR_NAMESVC_DB_JITTER, OLSR_TIMER_ONESHOT, &olsr_nameservice_expire_db_timer, entry,
934                      0);
935
936       entry_found = OLSR_TRUE;
937     }
938   }
939
940   if (!entry_found) {
941     struct ipaddr_str strbuf;
942     OLSR_PRINTF(3, "NAME PLUGIN: create new db entry for ip (%s) in hash table\n", olsr_ip_to_string(&strbuf, originator));
943
944     /* insert a new entry */
945     entry = olsr_malloc(sizeof(struct db_entry), "new db_entry");
946     memset(entry, 0, sizeof(struct db_entry));
947
948     entry->originator = *originator;
949
950     olsr_set_timer(&entry->db_timer, vtime, OLSR_LINK_LOSS_JITTER, OLSR_TIMER_ONESHOT, &olsr_nameservice_expire_db_timer, entry, 0);
951
952     entry->names = NULL;
953
954     /* insert to the list */
955     list_add_before(&this_list[hash], &entry->db_list);
956
957     //delegate to function for parsing the packet and linking it to entry->names
958     decap_namemsg(from_packet, &entry->names, this_table_changed);
959   }
960 }
961
962 #ifndef WIN32
963 static void
964 send_sighup_to_pidfile(char *pid_file)
965 {
966   int fd;
967   int i = 0;
968   int result;
969   pid_t ipid;
970   char line[20];
971   char *endptr;
972
973   fd = open(pid_file, O_RDONLY);
974   if (fd < 0) {
975     OLSR_PRINTF(2, "NAME PLUGIN: can't open file %s\n", pid_file);
976     return;
977   }
978
979   while (i < 19) {
980     result = read(fd, line + i, 19 - i);
981     if (!result) {              /* EOF */
982       break;
983     } else if (result > 0) {
984       i += result;
985     } else if (errno != EINTR && errno != EAGAIN) {
986       OLSR_PRINTF(2, "NAME PLUGIN: can't read file %s\n", pid_file);
987       return;
988     }
989   }
990   line[i] = 0;
991   close(fd);
992   ipid = strtol(line, &endptr, 0);
993   if (endptr == line) {
994     OLSR_PRINTF(2, "NAME PLUGIN: invalid pid at file %s\n", pid_file);
995     return;
996   }
997
998   result = kill(ipid, SIGHUP);
999   if (result == 0) {
1000     OLSR_PRINTF(2, "NAME PLUGIN: SIGHUP sent to pid %i\n", ipid);
1001   } else {
1002     OLSR_PRINTF(2, "NAME PLUGIN: failed to send SIGHUP to pid %i\n", ipid);
1003   }
1004
1005 }
1006 #endif
1007
1008 /**
1009  * write names to a file in /etc/hosts compatible format
1010  */
1011 void
1012 write_hosts_file(void)
1013 {
1014   int hash;
1015   struct name_entry *name;
1016   struct db_entry *entry;
1017   struct list_node *list_head, *list_node;
1018   FILE *hosts;
1019   FILE *add_hosts;
1020   int c = 0;
1021   time_t currtime;
1022
1023 #ifdef MID_ENTRIES
1024   struct mid_address *alias;
1025 #endif
1026
1027   if (!name_table_changed)
1028     return;
1029
1030   OLSR_PRINTF(2, "NAME PLUGIN: writing hosts file\n");
1031
1032   hosts = fopen(my_hosts_file, "w");
1033   if (hosts == NULL) {
1034     OLSR_PRINTF(2, "NAME PLUGIN: cant write hosts file\n");
1035     return;
1036   }
1037
1038   fprintf(hosts, "### this /etc/hosts file is overwritten regularly by olsrd\n");
1039   fprintf(hosts, "### do not edit\n\n");
1040
1041   fprintf(hosts, "127.0.0.1\tlocalhost\n");
1042   fprintf(hosts, "::1\t\tlocalhost\n\n");
1043
1044   // copy content from additional hosts filename
1045   if (my_add_hosts[0] != '\0') {
1046     add_hosts = fopen(my_add_hosts, "r");
1047     if (add_hosts == NULL) {
1048       OLSR_PRINTF(2, "NAME PLUGIN: cant open additional hosts file\n");
1049     } else {
1050       fprintf(hosts, "### contents from '%s' ###\n\n", my_add_hosts);
1051       while ((c = getc(add_hosts)) != EOF)
1052         putc(c, hosts);
1053     }
1054     fclose(add_hosts);
1055     fprintf(hosts, "\n### olsr names ###\n\n");
1056   }
1057   // write own names
1058   for (name = my_names; name != NULL; name = name->next) {
1059     struct ipaddr_str strbuf;
1060     fprintf(hosts, "%s\t%s%s\t# myself\n", olsr_ip_to_string(&strbuf, &name->ip), name->name, my_suffix);
1061   }
1062
1063   // write received names
1064   for (hash = 0; hash < HASHSIZE; hash++) {
1065     list_head = &name_list[hash];
1066     for (list_node = list_head->next; list_node != list_head; list_node = list_node->next) {
1067
1068       entry = list2db(list_node);
1069
1070       for (name = entry->names; name != NULL; name = name->next) {
1071         struct ipaddr_str strbuf;
1072         OLSR_PRINTF(6, "%s\t%s%s\t#%s\n", olsr_ip_to_string(&strbuf, &name->ip), name->name, my_suffix,
1073                     olsr_ip_to_string(&strbuf, &entry->originator));
1074
1075         fprintf(hosts, "%s\t%s%s\t# %s\n", olsr_ip_to_string(&strbuf, &name->ip), name->name, my_suffix,
1076                 olsr_ip_to_string(&strbuf, &entry->originator));
1077
1078 #ifdef MID_ENTRIES
1079         // write mid entries
1080         if ((alias = mid_lookup_aliases(&name->ip)) != NULL) {
1081           unsigned short mid_num = 1;
1082           char mid_prefix[MID_MAXLEN];
1083
1084           while (alias != NULL) {
1085             struct ipaddr_str midbuf;
1086
1087             // generate mid prefix
1088             sprintf(mid_prefix, MID_PREFIX, mid_num);
1089
1090             OLSR_PRINTF(6, "%s\t%s%s%s\t# %s (mid #%i)\n", olsr_ip_to_string(&midbuf, &alias->alias), mid_prefix, name->name,
1091                         my_suffix, olsr_ip_to_string(&strbuf, &entry->originator), mid_num);
1092
1093             fprintf(hosts, "%s\t%s%s%s\t# %s (mid #%i)\n", olsr_ip_to_string(&midbuf, &alias->alias), mid_prefix, name->name,
1094                     my_suffix, olsr_ip_to_string(&strbuf, &entry->originator), mid_num);
1095
1096             alias = alias->next_alias;
1097             mid_num++;
1098           }
1099         }
1100 #endif
1101       }
1102     }
1103   }
1104
1105   if (time(&currtime)) {
1106     fprintf(hosts, "\n### written by olsrd at %s", ctime(&currtime));
1107   }
1108
1109   fclose(hosts);
1110
1111 #ifndef WIN32
1112   if (*my_sighup_pid_file)
1113     send_sighup_to_pidfile(my_sighup_pid_file);
1114 #endif
1115   name_table_changed = OLSR_FALSE;
1116
1117   // Executes my_name_change_script after writing the hosts file
1118   if (my_name_change_script[0] != '\0') {
1119     if (system(my_name_change_script) != -1) {
1120       OLSR_PRINTF(2, "NAME PLUGIN: Name changed, %s executed\n", my_name_change_script);
1121     } else {
1122       OLSR_PRINTF(2, "NAME PLUGIN: WARNING! Failed to execute %s on hosts change\n", my_name_change_script);
1123     }
1124   }
1125 }
1126
1127 /**
1128  * write services to a file in the format:
1129  * service  #originator ip
1130  *
1131  * since service has a special format
1132  * each line will look similar to e.g.
1133  * http://me.olsr:80|tcp|my little homepage
1134  */
1135 void
1136 write_services_file(void)
1137 {
1138   int hash;
1139   struct name_entry *name;
1140   struct db_entry *entry;
1141   struct list_node *list_head, *list_node;
1142   FILE *services_file;
1143   time_t currtime;
1144
1145   if (!service_table_changed)
1146     return;
1147
1148   OLSR_PRINTF(2, "NAME PLUGIN: writing services file\n");
1149
1150   services_file = fopen(my_services_file, "w");
1151   if (services_file == NULL) {
1152     OLSR_PRINTF(2, "NAME PLUGIN: cant write services_file file\n");
1153     return;
1154   }
1155
1156   fprintf(services_file, "### this file is overwritten regularly by olsrd\n");
1157   fprintf(services_file, "### do not edit\n\n");
1158
1159   // write own services
1160   for (name = my_services; name != NULL; name = name->next) {
1161     fprintf(services_file, "%s\t# my own service\n", name->name);
1162   }
1163
1164   // write received services
1165   for (hash = 0; hash < HASHSIZE; hash++) {
1166     list_head = &service_list[hash];
1167     for (list_node = list_head->next; list_node != list_head; list_node = list_node->next) {
1168
1169       entry = list2db(list_node);
1170
1171       for (name = entry->names; name != NULL; name = name->next) {
1172         struct ipaddr_str strbuf;
1173         OLSR_PRINTF(6, "%s\t", name->name);
1174         OLSR_PRINTF(6, "\t#%s\n", olsr_ip_to_string(&strbuf, &entry->originator));
1175
1176         fprintf(services_file, "%s\t", name->name);
1177         fprintf(services_file, "\t#%s\n", olsr_ip_to_string(&strbuf, &entry->originator));
1178       }
1179     }
1180   }
1181
1182   if (time(&currtime)) {
1183     fprintf(services_file, "\n### written by olsrd at %s", ctime(&currtime));
1184   }
1185
1186   fclose(services_file);
1187   service_table_changed = OLSR_FALSE;
1188
1189   // Executes my_services_change_script after writing the services file
1190   if (my_services_change_script[0] != '\0') {
1191     if (system(my_services_change_script) != -1) {
1192       OLSR_PRINTF(2, "NAME PLUGIN: Service changed, %s executed\n", my_services_change_script);
1193     } else {
1194       OLSR_PRINTF(2, "NAME PLUGIN: WARNING! Failed to execute %s on service change\n", my_services_change_script);
1195     }
1196   }
1197 }
1198
1199 /**
1200  * Sort the nameserver pointer array.
1201  *
1202  * fresh entries are at the beginning of the array and
1203  * the best entry is at the end of the array.
1204  */
1205 static void
1206 select_best_nameserver(struct rt_entry **rt)
1207 {
1208   int nameserver_idx;
1209   struct rt_entry *rt1, *rt2;
1210
1211   for (nameserver_idx = 0; nameserver_idx < NAMESERVER_COUNT; nameserver_idx++) {
1212
1213     rt1 = rt[nameserver_idx];
1214     rt2 = rt[nameserver_idx + 1];
1215
1216     /*
1217      * compare the next two pointers in the array.
1218      * if the second pointer is NULL then percolate it up.
1219      */
1220     if (!rt2 || olsr_cmp_rt(rt1, rt2)) {
1221 #ifndef NODEBUG
1222       struct ipaddr_str strbuf;
1223       struct lqtextbuffer lqbuffer;
1224 #endif
1225       /*
1226        * first is better, swap the pointers.
1227        */
1228       OLSR_PRINTF(6, "NAME PLUGIN: nameserver %s, cost %s\n", olsr_ip_to_string(&strbuf, &rt1->rt_dst.prefix),
1229                   get_linkcost_text(rt1->rt_best->rtp_metric.cost, OLSR_TRUE, &lqbuffer));
1230
1231       rt[nameserver_idx] = rt2;
1232       rt[nameserver_idx + 1] = rt1;
1233     }
1234   }
1235 }
1236
1237 /**
1238  * write the 3 best upstream DNS servers to resolv.conf file
1239  * best means the 3 with the best etx value in routing table
1240  */
1241 void
1242 write_resolv_file(void)
1243 {
1244   int hash;
1245   struct name_entry *name;
1246   struct db_entry *entry;
1247   struct list_node *list_head, *list_node;
1248   struct rt_entry *route;
1249   static struct rt_entry *nameserver_routes[NAMESERVER_COUNT + 1];
1250   FILE *resolv;
1251   int i = 0;
1252   time_t currtime;
1253
1254   if (!forwarder_table_changed || my_forwarders != NULL || my_resolv_file[0] == '\0')
1255     return;
1256
1257   /* clear the array of 3+1 nameserver routes */
1258   memset(nameserver_routes, 0, sizeof(nameserver_routes));
1259
1260   for (hash = 0; hash < HASHSIZE; hash++) {
1261     list_head = &forwarder_list[hash];
1262     for (list_node = list_head->next; list_node != list_head; list_node = list_node->next) {
1263
1264       entry = list2db(list_node);
1265
1266       for (name = entry->names; name != NULL; name = name->next) {
1267 #ifndef NODEBUG
1268         struct ipaddr_str strbuf;
1269         struct lqtextbuffer lqbuffer;
1270 #endif
1271         route = olsr_lookup_routing_table(&name->ip);
1272
1273         OLSR_PRINTF(6, "NAME PLUGIN: check route for nameserver %s %s", olsr_ip_to_string(&strbuf, &name->ip),
1274                     route ? "suceeded" : "failed");
1275
1276         if (route == NULL)      // it's possible that route is not present yet
1277           continue;
1278
1279         /* enqueue it on the head of list */
1280         *nameserver_routes = route;
1281         OLSR_PRINTF(6, "NAME PLUGIN: found nameserver %s, cost %s", olsr_ip_to_string(&strbuf, &name->ip),
1282                     get_linkcost_text(route->rt_best->rtp_metric.cost, OLSR_TRUE, &lqbuffer));
1283
1284         /* find the closet one */
1285         select_best_nameserver(nameserver_routes);
1286       }
1287     }
1288   }
1289
1290   /* if there is no best route we are done */
1291   if (nameserver_routes[NAMESERVER_COUNT] == NULL)
1292     return;
1293
1294   /* write to file */
1295   OLSR_PRINTF(2, "NAME PLUGIN: try to write to resolv file\n");
1296   resolv = fopen(my_resolv_file, "w");
1297   if (resolv == NULL) {
1298     OLSR_PRINTF(2, "NAME PLUGIN: can't write resolv file\n");
1299     return;
1300   }
1301   fprintf(resolv, "### this file is overwritten regularly by olsrd\n");
1302   fprintf(resolv, "### do not edit\n\n");
1303
1304   for (i = NAMESERVER_COUNT; i >= 0; i--) {
1305     struct ipaddr_str strbuf;
1306
1307     route = nameserver_routes[i];
1308
1309     OLSR_PRINTF(2, "NAME PLUGIN: nameserver_routes #%d %p\n", i, route);
1310
1311     if (!route) {
1312       continue;
1313     }
1314
1315     OLSR_PRINTF(2, "NAME PLUGIN: nameserver %s\n", olsr_ip_to_string(&strbuf, &route->rt_dst.prefix));
1316     fprintf(resolv, "nameserver %s\n", olsr_ip_to_string(&strbuf, &route->rt_dst.prefix));
1317   }
1318   if (time(&currtime)) {
1319     fprintf(resolv, "\n### written by olsrd at %s", ctime(&currtime));
1320   }
1321   fclose(resolv);
1322   forwarder_table_changed = OLSR_FALSE;
1323 }
1324
1325 /**
1326  * completely free a list of name_entries
1327  */
1328 void
1329 free_name_entry_list(struct name_entry **list)
1330 {
1331   struct name_entry **tmp = list;
1332   struct name_entry *to_delete;
1333   while (*tmp != NULL) {
1334     to_delete = *tmp;
1335     *tmp = (*tmp)->next;
1336
1337     /* flag changes */
1338     switch (to_delete->type) {
1339     case NAME_HOST:
1340       name_table_changed = OLSR_TRUE;
1341       break;
1342     case NAME_FORWARDER:
1343       forwarder_table_changed = OLSR_TRUE;
1344       break;
1345     case NAME_SERVICE:
1346       service_table_changed = OLSR_TRUE;
1347       break;
1348     case NAME_LATLON:
1349       latlon_table_changed = OLSR_TRUE;
1350       break;
1351     default:
1352       break;
1353     }
1354
1355     free(to_delete->name);
1356     to_delete->name = NULL;
1357     free(to_delete);
1358     to_delete = NULL;
1359   }
1360 }
1361
1362 /**
1363  * we only allow names for IP addresses which we are
1364  * responsible for:
1365  * so the IP must either be from one of the interfaces
1366  * or inside a HNA which we have configured
1367  */
1368 olsr_bool
1369 allowed_ip(const union olsr_ip_addr *addr)
1370 {
1371   struct ip_prefix_list *hna;
1372   struct interface *iface;
1373   union olsr_ip_addr tmp_ip, tmp_msk;
1374   struct ipaddr_str strbuf;
1375
1376   OLSR_PRINTF(6, "checking %s\n", olsr_ip_to_string(&strbuf, addr));
1377
1378   for (iface = ifnet; iface; iface = iface->int_next) {
1379     OLSR_PRINTF(6, "interface %s\n", olsr_ip_to_string(&strbuf, &iface->ip_addr));
1380     if (ipequal(&iface->ip_addr, addr)) {
1381       OLSR_PRINTF(6, "MATCHED\n");
1382       return OLSR_TRUE;
1383     }
1384   }
1385
1386   if (olsr_cnf->ip_version == AF_INET) {
1387     for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
1388       union olsr_ip_addr netmask;
1389       OLSR_PRINTF(6, "HNA %s/%d\n", olsr_ip_to_string(&strbuf, &hna->net.prefix), hna->net.prefix_len);
1390       if (hna->net.prefix_len == 0) {
1391         continue;
1392       }
1393       olsr_prefix_to_netmask(&netmask, hna->net.prefix_len);
1394       if ((addr->v4.s_addr & netmask.v4.s_addr) == hna->net.prefix.v4.s_addr) {
1395         OLSR_PRINTF(6, "MATCHED\n");
1396         return OLSR_TRUE;
1397       }
1398     }
1399   } else {
1400     for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
1401       unsigned int i;
1402       OLSR_PRINTF(6, "HNA %s/%d\n", olsr_ip_to_string(&strbuf, &hna->net.prefix), hna->net.prefix_len);
1403       if (hna->net.prefix_len == 0)
1404         continue;
1405       olsr_prefix_to_netmask(&tmp_msk, hna->net.prefix_len);
1406       for (i = 0; i < sizeof(tmp_ip.v6.s6_addr); i++) {
1407         tmp_ip.v6.s6_addr[i] = addr->v6.s6_addr[i] & tmp_msk.v6.s6_addr[i];
1408       }
1409       if (ipequal(&tmp_ip, &hna->net.prefix)) {
1410         OLSR_PRINTF(6, "MATCHED\n");
1411         return OLSR_TRUE;
1412       }
1413     }
1414   }
1415   return OLSR_FALSE;
1416 }
1417
1418 /** check if name has the right syntax, i.e. it must adhere to a special regex
1419  * stored in regex_t_name
1420  * necessary to avaid names like "0.0.0.0 google.de\n etc"
1421  */
1422 olsr_bool
1423 is_name_wellformed(const char *name)
1424 {
1425   return regexec(&regex_t_name, name, 1, &regmatch_t_name, 0) == 0;
1426 }
1427
1428 /**
1429  * check if the service is in the right syntax and also that the hostname
1430  * or ip whithin the service is allowed
1431  */
1432 olsr_bool
1433 allowed_service(const char *service_line)
1434 {
1435   /* the call of is_service_wellformed generates the submatches stored in regmatch_t_service
1436    * these are then used by allowed_hostname_or_ip_in_service
1437    * see regexec(3) for more infos */
1438   if (!is_service_wellformed(service_line)) {
1439     return OLSR_FALSE;
1440   } else if (!allowed_hostname_or_ip_in_service(service_line, &(regmatch_t_service[1]))) {
1441     return OLSR_FALSE;
1442   }
1443
1444   return OLSR_TRUE;
1445 }
1446
1447 olsr_bool
1448 allowed_hostname_or_ip_in_service(const char *service_line, const regmatch_t * hostname_or_ip_match)
1449 {
1450   char *hostname_or_ip;
1451   union olsr_ip_addr olsr_ip;
1452   struct name_entry *name;
1453   if (hostname_or_ip_match->rm_so < 0 || hostname_or_ip_match->rm_eo < 0) {
1454     return OLSR_FALSE;
1455   }
1456
1457   hostname_or_ip = strndup(&service_line[hostname_or_ip_match->rm_so], hostname_or_ip_match->rm_eo - hostname_or_ip_match->rm_so);
1458   //hostname is one of the names, that I announce (i.e. one that i am allowed to announce)
1459   for (name = my_names; name != NULL; name = name->next) {
1460     if (strncmp(name->name, hostname_or_ip, name->len - strlen(my_suffix))
1461         == 0) {
1462       OLSR_PRINTF(4, "NAME PLUGIN: hostname %s in service %s is OK\n", hostname_or_ip, service_line);
1463       free(hostname_or_ip);
1464       hostname_or_ip = NULL;
1465       return OLSR_TRUE;
1466     }
1467   }
1468
1469   //ip in service-line is allowed
1470   if (inet_pton(olsr_cnf->ip_version, hostname_or_ip, &olsr_ip) > 0) {
1471     if (allowed_ip(&olsr_ip)) {
1472       struct ipaddr_str strbuf;
1473       OLSR_PRINTF(2, "NAME PLUGIN: ip %s in service %s is OK\n", olsr_ip_to_string(&strbuf, &olsr_ip), service_line);
1474       free(hostname_or_ip);
1475       hostname_or_ip = NULL;
1476       return OLSR_TRUE;
1477     }
1478   }
1479
1480   OLSR_PRINTF(1, "NAME PLUGIN: ip or hostname %s in service %s is NOT allowed (does not belong to you)\n", hostname_or_ip,
1481               service_line);
1482   free(hostname_or_ip);
1483   hostname_or_ip = NULL;
1484
1485   return OLSR_FALSE;
1486 }
1487
1488 /**
1489  * check if the service matches the syntax
1490  * of "protocol://host:port/path|tcp_or_udp|a short description",
1491  * which is given in the regex regex_t_service
1492  */
1493 olsr_bool
1494 is_service_wellformed(const char *service_line)
1495 {
1496   return regexec(&regex_t_service, service_line, pmatch_service, regmatch_t_service, 0) == 0;
1497 }
1498
1499 /**
1500  * check if the latlot matches the syntax
1501  */
1502 olsr_bool
1503 is_latlon_wellformed(const char *latlon_line)
1504 {
1505   int hna = -1;
1506   float a = 0.0, b = 0.0;
1507   sscanf(latlon_line, "%f,%f,%d", &a, &b, &hna);
1508   return (a != 0.0 && b != 0.0 && -1 != hna);
1509 }
1510
1511 /**
1512  * Returns 1 if this olsrd announces inet
1513  */
1514 olsr_bool
1515 get_isdefhna_latlon(void)
1516 {
1517   struct ip_prefix_list *hna;
1518   for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
1519     if (hna->net.prefix_len == 0) {
1520       return OLSR_TRUE;
1521     }
1522   }
1523   return OLSR_FALSE;
1524 }
1525
1526 /**
1527  * Grabs the current HNA selected default route
1528  */
1529 void
1530 lookup_defhna_latlon(union olsr_ip_addr *ip)
1531 {
1532   struct rt_entry *rt;
1533   struct avl_node *rt_tree_node;
1534   struct olsr_ip_prefix prefix;
1535
1536   memset(ip, 0, sizeof(ip));
1537   memset(&prefix, 0, sizeof(prefix));
1538
1539   if (NULL != (rt_tree_node = avl_find(&routingtree, &prefix))) {
1540     rt = rt_tree2rt(rt_tree_node);
1541     *ip = rt->rt_best->rtp_nexthop.gateway;
1542   }
1543 }
1544
1545 /**
1546  * lookup a nodes name
1547  */
1548 const char *
1549 lookup_name_latlon(union olsr_ip_addr *ip)
1550 {
1551   int hash;
1552   struct db_entry *entry;
1553   struct list_node *list_head, *list_node;
1554   struct name_entry *name;
1555
1556   for (hash = 0; hash < HASHSIZE; hash++) {
1557     list_head = &name_list[hash];
1558     for (list_node = list_head->next; list_node != list_head; list_node = list_node->next) {
1559
1560       entry = list2db(list_node);
1561
1562       for (name = entry->names; name != NULL; name = name->next) {
1563         if (ipequal(&name->ip, ip))
1564           return name->name;
1565       }
1566     }
1567   }
1568   return "";
1569 }
1570
1571 #ifdef WIN32
1572
1573 /**
1574  * write latlon positions to a javascript file
1575  */
1576 void
1577 write_latlon_file(void)
1578 {
1579   FILE *fmap;
1580
1581   if (!my_names || !latlon_table_changed)
1582     return;
1583
1584   OLSR_PRINTF(2, "NAME PLUGIN: writing latlon file\n");
1585
1586   if (NULL == (fmap = fopen(my_latlon_file, "w"))) {
1587     OLSR_PRINTF(0, "NAME PLUGIN: cant write latlon file\n");
1588     return;
1589   }
1590   fprintf(fmap, "/* This file is overwritten regularly by olsrd */\n");
1591   mapwrite_work(fmap);
1592   fclose(fmap);
1593   latlon_table_changed = OLSR_FALSE;
1594 }
1595 #endif
1596
1597 /*
1598  * Local Variables:
1599  * mode: c
1600  * c-indent-tabs-mode: t
1601  * indent-tabs-mode: t
1602  * c-basic-offset: 4
1603  * tab-width: 4
1604  * End:
1605  */