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