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