ebb858558f1dd23cee79951f747d0e62a6747488
[olsrd.git] / lib / nameservice / src / nameservice.c
1 /*
2  * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto-at-olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright notice, 
11  *   this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright notice, 
13  *   this list of conditions and the following disclaimer in the documentation 
14  *   and/or other materials provided with the distribution.
15  * * Neither the name of the UniK olsr daemon nor the names of its contributors 
16  *   may be used to endorse or promote products derived from this software 
17  *   without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
22  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
26  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
27  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  */
31
32 /* $Id: nameservice.c,v 1.16 2006/12/12 10:54:52 kattemat Exp $ */
33
34 /*
35  * Dynamic linked library for UniK OLSRd
36  */
37
38 #include <stdio.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42
43 #include "olsr.h"
44 #include "net_olsr.h"
45 #include "routing_table.h"
46 #include "mantissa.h"
47 #include "scheduler.h"
48 #include "parser.h"
49 #include "duplicate_set.h"
50 #include "link_set.h"
51
52 #include "nameservice.h"
53 #include "olsrd_copy.h"
54 #include "compat.h"
55
56 /* send buffer: huge */
57 static char buffer[10240];
58
59 /* config parameters */
60 static char my_hosts_file[MAX_FILE + 1];
61 static char my_add_hosts[MAX_FILE + 1];
62 static char my_suffix[MAX_SUFFIX];
63 static int my_interval = EMISSION_INTERVAL;
64 static double my_timeout = NAME_VALID_TIME;
65 static olsr_bool have_dns_server = OLSR_FALSE;
66 static union olsr_ip_addr my_dns_server;
67 static char my_resolv_file[MAX_FILE +1];
68
69 /* the database (using hashing) */
70 struct db_entry* list[HASHSIZE];
71 struct name_entry *my_names = NULL;
72 olsr_bool name_table_changed = OLSR_TRUE;
73
74 static void free_routing_table_list(struct rt_entry **list) ;
75 static struct rt_entry *host_lookup_routing_table(union olsr_ip_addr *);
76
77 /**
78  * do initialization
79  */
80 void
81 name_constructor() 
82 {
83         int i;
84         
85 #ifdef WIN32
86         int len;
87
88         GetWindowsDirectory(my_hosts_file, MAX_FILE - 12);
89
90         len = strlen(my_hosts_file);
91  
92         if (my_hosts_file[len - 1] != '\\')
93                 my_hosts_file[len++] = '\\';
94  
95         strcpy(my_hosts_file + len, "hosts_olsr");
96 #else
97         strcpy(my_hosts_file, "/var/run/hosts_olsr");
98 #endif
99
100         my_suffix[0] = '\0';
101         my_add_hosts[0] = '\0';
102         my_resolv_file[0] = '\0';
103         
104         /* init list */
105         for(i = 0; i < HASHSIZE; i++) {
106                 list[i] = NULL;
107         }
108         
109         memset(&my_dns_server, 0, sizeof(my_dns_server));
110 }
111
112
113 /**
114  * called for all plugin parameters
115  */
116 int
117 olsrd_plugin_register_param(char *key, char *value)
118 {
119         if(!strcmp(key, "interval")) {
120                 my_interval = atoi(value);
121                 printf("\nNAME PLUGIN: parameter interval: %d\n", my_interval);
122         }
123         else if(!strcmp(key, "timeout")) {
124                 my_timeout = atof(value);
125                 printf("\nNAME PLUGIN: parameter timeout: %f\n", my_timeout);
126         } 
127         else if(!strcmp(key, "hosts-file")) {
128                 strncpy( my_hosts_file, value, MAX_FILE );
129                 printf("\nNAME PLUGIN: parameter filename: %s\n", my_hosts_file);
130         }
131         else if(!strcmp(key, "resolv-file")) {
132                 strncpy(my_resolv_file, value, MAX_FILE);
133                 printf("\nNAME PLUGIN: parameter resolv file: %s\n", my_resolv_file);
134         }
135         else if(!strcmp(key, "suffix")) {
136                 strncpy(my_suffix, value, MAX_SUFFIX);
137                 printf("\nNAME PLUGIN: parameter suffix: %s\n", my_suffix);
138         }
139         else if(!strcmp(key, "add-hosts")) {
140                 strncpy(my_add_hosts, value, MAX_FILE);
141                 printf("\nNAME PLUGIN: parameter additional host: %s\n", my_add_hosts);
142         }
143         else if(!strcmp(key, "dns-server")) {
144                 union olsr_ip_addr ip;
145                 if (strlen(value) == 0) {
146                         // set dns server ip to main address
147                         // which is not known yet
148                         have_dns_server = OLSR_TRUE;
149                 }
150                 else if (inet_pton(olsr_cnf->ip_version, value, &ip) == 1) {
151                         memcpy(&my_dns_server, &ip, olsr_cnf->ipsize);
152                         have_dns_server = OLSR_TRUE;
153                 }
154                 else {
155                         printf("\nNAME PLUGIN: invalid dns-server IP %s\n", value);
156                 }
157         }
158         else if(!strcmp(key, "name")) {
159                 // name for main address
160                 struct name_entry *tmp;
161                 tmp = malloc(sizeof(struct name_entry));
162                 tmp->name = strndup( value, MAX_NAME );
163                 tmp->len = strlen( tmp->name );
164                 tmp->type = NAME_HOST;
165                 // will be set to main_addr later
166                 memset(&tmp->ip, 0, sizeof(tmp->ip));
167                 tmp->next = my_names;
168                 my_names = tmp;
169                 
170                 printf("\nNAME PLUGIN: parameter name: %s (main address)\n", tmp->name);
171         }
172         else {
173                 // assume this is an IP address and hostname
174                 union olsr_ip_addr ip;
175                 
176                 if (inet_pton(olsr_cnf->ip_version, key, &ip) == 1) {
177                         // the IP is validated later
178                         struct name_entry *tmp;
179                         tmp = malloc(sizeof(struct name_entry));
180                         tmp->name = strndup( value, MAX_NAME );
181                         tmp->len = strlen( tmp->name );
182                         tmp->type = NAME_HOST;
183                         memcpy(&tmp->ip, &ip, olsr_cnf->ipsize);
184                         tmp->next = my_names;
185                         my_names = tmp;
186                         printf("\nNAME PLUGIN: parameter %s (%s)\n", tmp->name,
187                                 olsr_ip_to_string(&tmp->ip));
188                 } 
189                 else {
190                         printf("\nNAME PLUGIN: invalid IP %s for name %s!\n", key, value);
191                 }
192         }
193
194         return 1;
195 }
196
197
198 /**
199  * last initialization
200  *
201  * we have to do this here because some things like main_addr 
202  * are not known before
203  *
204  * this is beause of the order in which the plugin is initzalized 
205  * by the plugin loader:
206  *   - first the parameters are sent
207  *   - then register_olsr_data() from olsrd_plugin.c is called
208  *     which sets up main_addr and some other variables
209  *   - register_olsr_data() then then finally calls this function
210  */
211 int
212 name_init()
213 {
214         struct name_entry *name;
215         struct name_entry *prev=NULL;
216         union olsr_ip_addr ipz;
217
218         memset(&ipz, 0, sizeof(ipz));
219
220         /* fixup names and IP addresses */
221         for (name = my_names; name != NULL; name = name->next) {
222                 if (memcmp(&name->ip, &ipz, olsr_cnf->ipsize) == 0) {
223                         // insert main_addr
224                         memcpy(&name->ip, &olsr_cnf->main_addr, olsr_cnf->ipsize);
225                         prev = name;
226                 } else {
227                         // IP from config file
228                         // check if we are allowed to announce a name for this IP
229                         // we can only do this if we also announce the IP        
230                         if (!allowed_ip(&name->ip)) {
231                                 olsr_printf(1, "NAME PLUGIN: name for unknown IP %s not allowed, fix your config!\n", 
232                                         olsr_ip_to_string(&name->ip));
233                                 if (prev!=NULL) {
234                                         prev->next = name->next;
235                                         free(name->name);
236                                         free(name);
237                                 }
238                         }
239                         else {
240                                 prev = name;
241                         }
242                 }
243         }
244                 
245         if (have_dns_server) {
246                 if (memcmp(&my_dns_server, &ipz, olsr_cnf->ipsize) == 0) {
247                         memcpy(&my_dns_server, &olsr_cnf->main_addr, olsr_cnf->ipsize);
248                         printf("\nNAME PLUGIN: announcing upstream DNS server: %s\n", 
249                                 olsr_ip_to_string(&my_dns_server));
250                 }
251                 else if (!allowed_ip(&my_dns_server)) {
252                         printf("NAME PLUGIN: announcing DNS server on unknown IP %s is not allowed, fix your config!\n", 
253                                 olsr_ip_to_string(&my_dns_server));
254                         memset(&my_dns_server, 0, sizeof(my_dns_server));
255                         have_dns_server = OLSR_FALSE;
256                 }
257                 else {
258                         printf("\nNAME PLUGIN: announcing upstream DNS server: %s\n", 
259                                 olsr_ip_to_string(&my_dns_server));
260                 }
261         }
262         
263         /* register functions with olsrd */
264         olsr_parser_add_function(&olsr_parser, PARSER_TYPE, 1);
265         olsr_register_timeout_function(&olsr_timeout);
266         olsr_register_scheduler_event(&olsr_event, NULL, my_interval, 0, NULL);
267
268         return 1;
269 }
270
271
272 /**
273  * called at unload: free everything
274  */
275 void
276 name_destructor()
277 {
278         int i;
279         struct db_entry **tmp;
280         struct db_entry *to_delete;
281         
282         olsr_printf(2, "NAME PLUGIN: exit. cleaning up...\n");
283         
284         free_name_entry_list(&my_names);
285         
286         /* free list entries */
287         for(i = 0; i < HASHSIZE; i++)
288         {
289                 tmp = &list[i];
290                 while(*tmp != NULL)
291                 {
292                         to_delete = *tmp;
293                         *tmp = (*tmp)->next;
294                         free_name_entry_list(&to_delete->names);
295                         free(to_delete);
296                         to_delete = NULL;
297                 }
298         }
299 }
300
301
302 /**
303  * A timeout function called every time
304  * the scheduler is polled: time out old list entries
305  * and write changes to file
306  */
307 void
308 olsr_timeout()
309 {
310         struct db_entry **tmp;
311         struct db_entry *to_delete;
312         int index;
313
314         for(index=0;index<HASHSIZE;index++)
315         {
316                 for (tmp = &list[index]; *tmp != NULL; )
317                 {
318                         /* check if the entry is timed out */
319                         if (olsr_timed_out(&(*tmp)->timer))
320                         {
321                                 to_delete = *tmp;
322                                 *tmp = (*tmp)->next;
323                                 
324                                 olsr_printf(2, "NAME PLUGIN: %s timed out... deleting\n", 
325                                         olsr_ip_to_string(&to_delete->originator));
326         
327                                 /* Delete */
328                                 free_name_entry_list(&to_delete->names);
329                                 free(to_delete);
330                                 name_table_changed = OLSR_TRUE;
331                         } else {
332                                 tmp = &(*tmp)->next;
333                         }
334                 }
335         }
336         write_resolv_file();
337         write_hosts_file();
338 }
339
340
341 /**
342  * Scheduled event: generate and send NAME packet
343  */
344 void
345 olsr_event(void *foo)
346 {
347         union olsr_message *message = (union olsr_message*)buffer;
348         struct interface *ifn;
349         int namesize;
350   
351         /* looping trough interfaces */
352         for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
353         {
354                 olsr_printf(3, "NAME PLUGIN: Generating packet - [%s]\n", ifn->int_name);
355
356                 /* fill message */
357                 if(olsr_cnf->ip_version == AF_INET)
358                 {
359                         /* IPv4 */
360                         message->v4.olsr_msgtype = MESSAGE_TYPE;
361                         message->v4.olsr_vtime = double_to_me(my_timeout);
362                         memcpy(&message->v4.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
363                         message->v4.ttl = MAX_TTL;
364                         message->v4.hopcnt = 0;
365                         message->v4.seqno = htons(get_msg_seqno());
366                         
367                         namesize = encap_namemsg((struct namemsg*)&message->v4.message);
368                         namesize = namesize + sizeof(struct olsrmsg);
369                         
370                         message->v4.olsr_msgsize = htons(namesize);
371                 }
372                 else
373                 {
374                         /* IPv6 */
375                         message->v6.olsr_msgtype = MESSAGE_TYPE;
376                         message->v6.olsr_vtime = double_to_me(my_timeout);
377                         memcpy(&message->v6.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
378                         message->v6.ttl = MAX_TTL;
379                         message->v6.hopcnt = 0;
380                         message->v6.seqno = htons(get_msg_seqno());
381                         
382                         namesize = encap_namemsg((struct namemsg*)&message->v6.message);
383                         namesize = namesize + sizeof(struct olsrmsg6);
384                         
385                         message->v6.olsr_msgsize = htons(namesize);
386                 }
387                 
388                 if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
389                         /* send data and try again */
390                         net_output(ifn);
391                         if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
392                                 olsr_printf(1, "NAME PLUGIN: could not send on interface: %s\n", ifn->int_name);
393                         }
394                 }
395         }
396 }
397
398
399 /**
400  * Parse name olsr message of NAME type
401  */
402 void
403 olsr_parser(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *in_addr)
404 {
405         struct namemsg *namemessage;
406         union olsr_ip_addr originator;
407         double vtime;
408         int size;
409         olsr_u16_t seqno;
410
411         /* Fetch the originator of the messsage */
412         if(olsr_cnf->ip_version == AF_INET) {
413                 memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize);
414                 seqno = ntohs(m->v4.seqno);
415         } else {
416                 memcpy(&originator, &m->v6.originator, olsr_cnf->ipsize);
417                 seqno = ntohs(m->v6.seqno);
418         }
419                 
420         /* Fetch the message based on IP version */
421         if(olsr_cnf->ip_version == AF_INET) {
422                 vtime = ME_TO_DOUBLE(m->v4.olsr_vtime);
423                 size = ntohs(m->v4.olsr_msgsize);
424                 namemessage = (struct namemsg*)&m->v4.message;
425         }
426         else {
427                 vtime = ME_TO_DOUBLE(m->v6.olsr_vtime);
428                 size = ntohs(m->v6.olsr_msgsize);
429                 namemessage = (struct namemsg*)&m->v6.message;
430         }
431
432         /* Check if message originated from this node. 
433         If so - back off */
434         if(memcmp(&originator, &olsr_cnf->main_addr, olsr_cnf->ipsize) == 0)
435                 return;
436
437         /* Check that the neighbor this message was received from is symmetric. 
438         If not - back off*/
439         if(check_neighbor_link(in_addr) != SYM_LINK) {
440                 olsr_printf(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(in_addr));
441                 return;
442         }
443
444         /* Check if this message has been processed before
445         * Remeber that this also registeres the message as
446         * processed if nessecary
447         */
448         if(!olsr_check_dup_table_proc(&originator, seqno)) {
449                 /* If so - do not process */
450                 goto forward;
451         }
452
453         update_name_entry(&originator, namemessage, size, vtime);
454
455 forward:
456         /* Forward the message if nessecary
457         * default_fwd does all the work for us! */
458         olsr_forward_message(m, &originator, seqno, in_if, in_addr);
459 }
460
461
462 /**
463  * Encapsulate a name message into a packet. 
464  *
465  * It assumed that there is enough space in the buffer to do this!
466  *
467  * Returns: the length of the message that was appended
468  */
469 int
470 encap_namemsg(struct namemsg* msg)
471 {
472         struct name_entry *my_name = my_names;
473         struct name* to_packet;
474         char* pos = (char*)msg + sizeof(struct namemsg);
475         short i=0;
476         int k;
477         
478         // upstream dns server
479         if (have_dns_server) {
480                 olsr_printf(3, "NAME PLUGIN: Announcing DNS server (%s)\n", 
481                         olsr_ip_to_string(&my_dns_server));
482                 to_packet = (struct name*)pos;
483                 to_packet->type = htons(NAME_FORWARDER);
484                 to_packet->len = htons(0);
485                 memcpy(&to_packet->ip, &my_dns_server, olsr_cnf->ipsize);
486                 pos += sizeof(struct name);
487                 i++;
488         }
489
490         // names
491         for (my_name = my_names; my_name!=NULL; my_name = my_name->next)
492         {
493                 olsr_printf(3, "NAME PLUGIN: Announcing name %s (%s) %d\n", 
494                         my_name->name, olsr_ip_to_string(&my_name->ip), my_name->len);
495                         
496                 to_packet = (struct name*)pos;
497                 to_packet->type = htons(my_name->type);
498                 to_packet->len = htons(my_name->len);
499                 memcpy(&to_packet->ip, &my_name->ip, olsr_cnf->ipsize);
500                 pos += sizeof(struct name);
501                 strncpy(pos, my_name->name, my_name->len);
502                 pos += my_name->len;
503                 // padding to 4 byte boundaries
504                 for (k = my_name->len; (k & 3) != 0; k++)
505                         *pos++ = '\0';
506                 i++;
507         }
508         msg->nr_names = htons(i);
509         msg->version = htons(NAME_PROTOCOL_VERSION);
510         return pos - (char*)msg; //length
511 }
512
513
514 /**
515  * decapsulate a name message and update name_entries if necessary
516  */
517 void
518 decap_namemsg( struct namemsg *msg, int size, struct name_entry **to )
519 {
520         char *pos, *end_pos;
521         struct name_entry *tmp;
522         struct name *from_packet; 
523         int i;
524         
525         olsr_printf(4, "NAME PLUGIN: decapsulating name msg (size %d)\n", size);
526         
527         if (ntohs(msg->version) != NAME_PROTOCOL_VERSION) {
528                 olsr_printf(3, "NAME PLUGIN: ignoring wrong version %d\n", msg->version);
529                 return;
530         }
531         
532         // for now ist easier to just delete everything, than
533         // to update selectively
534         free_name_entry_list(to);
535         name_table_changed = OLSR_TRUE;
536         
537         /* now add the names from the message */
538         pos = (char*)msg + sizeof(struct namemsg);
539         end_pos = pos + size - sizeof(struct name*); // at least one struct name has to be left
540         
541         for (i=ntohs(msg->nr_names); i > 0 && pos<end_pos; i--) 
542         {
543                 from_packet = (struct name*)pos;
544                 
545                 tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry");         
546                 tmp->type = ntohs(from_packet->type);
547                 tmp->len = ntohs(from_packet->len) > MAX_NAME ? MAX_NAME : ntohs(from_packet->len);
548                 tmp->name = olsr_malloc(tmp->len+1, "new name_entry name");
549                 memcpy(&tmp->ip, &from_packet->ip, olsr_cnf->ipsize);
550                 pos += sizeof(struct name);
551                 strncpy(tmp->name, pos, tmp->len);
552                 tmp->name[tmp->len] = '\0';
553
554                 olsr_printf(3, "NAME PLUGIN: New name %s (%s) %d %d\n", 
555                         tmp->name, olsr_ip_to_string(&tmp->ip), tmp->len, tmp->type);
556
557                 // queue to front
558                 tmp->next = *to;
559                 *to = tmp;
560
561                 // name + padding
562                 pos += 1 + ((tmp->len - 1) | 3);
563         }
564         if (i!=0)
565                 olsr_printf(4, "NAME PLUGIN: Lost %d names due to length inconsistency\n", i);
566 }
567
568
569 /**
570  * Update or register a new name entry
571  */
572 void
573 update_name_entry(union olsr_ip_addr *originator, struct namemsg *msg, int msg_size, double vtime)
574 {
575         int hash;
576         struct db_entry *entry;
577
578         olsr_printf(3, "NAME PLUGIN: Received Name Message from %s\n", 
579                 olsr_ip_to_string(originator));
580
581         hash = olsr_hashing(originator);
582
583         /* find the entry for originator */
584         for (entry = list[hash]; entry != NULL; entry = entry->next)
585         {
586                 if (memcmp(originator, &entry->originator, olsr_cnf->ipsize) == 0) {
587                         // found
588                         olsr_printf(4, "NAME PLUGIN: %s found\n", 
589                                 olsr_ip_to_string(originator));
590                 
591                         decap_namemsg(msg, msg_size, &entry->names);
592                         
593                         olsr_get_timestamp(vtime * 1000, &entry->timer);
594                         
595                         return;
596                 }
597         }
598
599         olsr_printf(3, "NAME PLUGIN: New entry %s\n", 
600                 olsr_ip_to_string(originator));
601                 
602         /* insert a new entry */
603         entry = olsr_malloc(sizeof(struct db_entry), "new db_entry");
604         
605         memcpy(&entry->originator, originator, olsr_cnf->ipsize);
606         olsr_get_timestamp(vtime * 1000, &entry->timer);
607         entry->names = NULL;
608         // queue to front
609         entry->next = list[hash];
610         list[hash] = entry;
611         
612         decap_namemsg(msg, msg_size, &entry->names);
613
614         name_table_changed = OLSR_TRUE;
615 }
616
617
618 /**
619  * write names to a file in /etc/hosts compatible format
620  */
621 void
622 write_hosts_file()
623 {
624         int hash;
625         struct name_entry *name;
626         struct db_entry *entry;
627         FILE* hosts;
628         FILE* add_hosts;
629         int c=0;
630         time_t currtime;
631   
632         if (!name_table_changed)
633                 return;
634
635         olsr_printf(2, "NAME PLUGIN: writing hosts file\n");
636                       
637         hosts = fopen( my_hosts_file, "w" );
638         if (hosts == NULL) {
639                 olsr_printf(2, "NAME PLUGIN: cant write hosts file\n");
640                 return;
641         }
642         
643         fprintf(hosts, "### this /etc/hosts file is overwritten regularly by olsrd\n");
644         fprintf(hosts, "### do not edit\n\n");
645
646         fprintf(hosts, "127.0.0.1\tlocalhost\n");
647         fprintf(hosts, "::1\t\tlocalhost\n\n");
648         
649         // copy content from additional hosts filename
650         if (my_add_hosts[0] != '\0') {
651                 add_hosts = fopen( my_add_hosts, "r" );
652                 if (add_hosts == NULL) {
653                         olsr_printf(2, "NAME PLUGIN: cant open additional hosts file\n");
654                 }
655                 else {
656                         fprintf(hosts, "### contents from '%s' ###\n\n", my_add_hosts);
657                         while ((c = getc(add_hosts)) != EOF)
658                                 putc(c, hosts);
659                 }
660                 fclose(add_hosts);              
661                 fprintf(hosts, "\n### olsr names ###\n\n");
662         }
663         
664         // write own names
665         for (name = my_names; name != NULL; name = name->next) {
666                 fprintf(hosts, "%s\t%s%s\t# myself\n", olsr_ip_to_string(&name->ip),
667                         name->name, my_suffix );
668         }
669         
670         // write received names
671         for (hash = 0; hash < HASHSIZE; hash++) 
672         {
673                 for(entry = list[hash]; entry != NULL; entry = entry->next)
674                 {
675                         for (name = entry->names; name != NULL; name = name->next) 
676                         {
677                                 if (name->type == NAME_HOST) {
678                                         olsr_printf(6, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
679                                         olsr_printf(6, "\t#%s\n", olsr_ip_to_string(&entry->originator));
680                                         
681                                         fprintf(hosts, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
682                                         fprintf(hosts, "\t# %s\n", olsr_ip_to_string(&entry->originator));
683                                 }
684                         }
685                 }
686         }
687
688         if (time(&currtime)) {
689                 fprintf(hosts, "\n### written by olsrd at %s", ctime(&currtime));
690         }
691           
692         fclose(hosts);
693         name_table_changed = OLSR_FALSE;
694 }
695
696
697 /**
698  * write upstream DNS servers to resolv.conf file
699  */
700 void
701 write_resolv_file()
702 {
703         int hash;
704         struct name_entry *name, *tmp_dns, *last_dns, *dnslist = NULL;
705         struct db_entry *entry;
706         struct rt_entry *best_routes = NULL;
707         struct rt_entry *route, *tmp = NULL, *last;
708         FILE* resolv;
709         int i=0;
710         
711         if (my_resolv_file[0] == '\0')
712                 return;
713         
714         if (!name_table_changed)
715                 return;
716
717         olsr_printf(2, "NAME PLUGIN: writing resolv file\n");
718
719         for (hash = 0; hash < HASHSIZE; hash++) 
720         {
721                 for(entry = list[hash]; entry != NULL; entry = entry->next)
722                 {
723                         for (name = entry->names; name != NULL; name = name->next) 
724                         {
725                                 if (name->type != NAME_FORWARDER)
726                                         continue;
727                                 
728                                 /* find the nearest one */
729                                 route = host_lookup_routing_table(&name->ip);
730                                 if (route==NULL) // it's possible that route is not present yet
731                                         continue;
732                                 
733                                 if (best_routes == NULL || route->rt_etx < best_routes->rt_etx) {
734                                         olsr_printf(6, "NAME PLUGIN: best nameserver %s\n",
735                                                 olsr_ip_to_string(&name->ip));
736                                         if (best_routes!=NULL)
737                                                 olsr_printf(6, "NAME PLUGIN: better than %f (%s)\n",
738                                                         best_routes->rt_etx,
739                                                         olsr_ip_to_string(&best_routes->rt_dst));
740                                         
741                                         tmp = olsr_malloc(sizeof(struct rt_entry), "new rt_entry");
742                                         memcpy(&tmp->rt_dst, &route->rt_dst, olsr_cnf->ipsize);
743                                         tmp->rt_etx = route->rt_etx;
744                                         tmp->next = best_routes;
745                                         best_routes = tmp;
746                                         tmp_dns = olsr_malloc(sizeof(struct name_entry), "write_resolv name_entry");
747                                         COPY_IP(&tmp_dns->ip, &name->ip);
748                                         tmp_dns->type = name->type;
749                                         tmp_dns->len = 0;
750                                         tmp_dns->name = NULL;
751                                         tmp_dns->next = dnslist;
752                                         dnslist = tmp_dns;
753                                 } else {
754                                         // queue in etx order
755                                         last = best_routes;
756                                         last_dns = dnslist;
757                                         while ( last->next!=NULL && i<3 ) {
758                                                 if (last->next->rt_etx > route->rt_etx)
759                                                         break;
760                                                 last = last->next;
761                                                 last_dns = last_dns->next;
762                                                 i++;
763                                         }
764                                         if (i<3) {
765                                                 olsr_printf(6, "NAME PLUGIN: queue %f (%s)",
766                                                         route->rt_etx,
767                                                         olsr_ip_to_string(&name->ip));
768                                                 olsr_printf(6, " after %f (%s)\n", 
769                                                         last->rt_etx, olsr_ip_to_string(&last_dns->ip));
770                                                 
771                                                 tmp = olsr_malloc(sizeof(struct rt_entry), "new rt_entry");
772                                                 memcpy(&tmp->rt_dst, &route->rt_dst, olsr_cnf->ipsize);
773                                                 tmp->rt_etx = route->rt_etx;
774                                                 tmp->next = last->next;
775                                                 last->next = tmp;
776
777                                                 tmp_dns = olsr_malloc(sizeof(struct name_entry), "write_resolv name_entry");
778                                                 COPY_IP(&tmp_dns->ip, &name->ip);
779                                                 tmp_dns->type = name->type;
780                                                 tmp_dns->len = 0;
781                                                 tmp_dns->name = NULL;
782                                                 tmp_dns->next = last_dns->next;
783                                                 last_dns->next = tmp_dns;
784                                         } else {
785                                                 olsr_printf(6, "NAME PLUGIN: don't need more than 3 nameservers\n");
786                                         }
787                                 }
788                         }
789                 }
790         }
791         if (best_routes==NULL)
792                 return;
793                  
794         /* write to file */
795         resolv = fopen( my_resolv_file, "w" );
796         if (resolv == NULL) {
797                 olsr_printf(2, "NAME PLUGIN: can't write resolv file\n");
798                 return;
799         }
800         i=0;
801         for (tmp_dns=dnslist; tmp_dns!=NULL && i<3; tmp_dns=tmp_dns->next) {
802                 olsr_printf(6, "NAME PLUGIN: nameserver %s\n", olsr_ip_to_string(&tmp_dns->ip));
803                 fprintf(resolv, "nameserver %s\n", olsr_ip_to_string(&tmp_dns->ip));
804                 i++;
805         }
806         free_name_entry_list(&dnslist);
807         if(tmp != NULL) {
808             free_routing_table_list(&tmp);
809         }
810         fclose(resolv);
811 }
812
813
814 /**
815  * completely free a list of name_entries
816  */
817 void 
818 free_name_entry_list(struct name_entry **list) 
819 {
820         struct name_entry **tmp = list;
821         struct name_entry *to_delete;
822         while (*tmp != NULL) {
823                 to_delete = *tmp;
824                 *tmp = (*tmp)->next;
825                 free( to_delete->name );
826                 free( to_delete );
827                 to_delete = NULL;
828         }
829 }
830
831
832 /**
833  * completely free a list of rt_entries
834  */
835 static void 
836 free_routing_table_list(struct rt_entry **list) 
837 {
838         struct rt_entry **tmp = list;
839         struct rt_entry *to_delete;
840         while (*tmp != NULL) {
841                 to_delete = *tmp;
842                 *tmp = (*tmp)->next;
843                 free( to_delete );
844                 to_delete = NULL;
845         }
846 }
847
848
849 /**
850  * we only allow names for IP addresses which we are
851  * responsible for: 
852  * so the IP must either be from one of the interfaces
853  * or inside a HNA which we have configured 
854  */
855 olsr_bool
856 allowed_ip(union olsr_ip_addr *addr)
857 {
858         struct hna4_entry *hna4;
859         struct hna6_entry *hna6;
860         struct interface *iface;
861         union olsr_ip_addr tmp_ip, tmp_msk;
862         
863         olsr_printf(6, "checking %s\n", olsr_ip_to_string(addr));
864         
865         for(iface = ifnet; iface; iface = iface->int_next)
866         {
867                 olsr_printf(6, "interface %s\n", olsr_ip_to_string(&iface->ip_addr));
868                 if (COMP_IP(&iface->ip_addr, addr)) {
869                         olsr_printf(6, "MATCHED\n");
870                         return OLSR_TRUE;
871                 }
872         }
873         
874         if (olsr_cnf->ip_version == AF_INET) {
875                 for (hna4 = olsr_cnf->hna4_entries; hna4; hna4 = hna4->next)
876                 {
877                         olsr_printf(6, "HNA %s/%s\n", 
878                                 olsr_ip_to_string(&hna4->net),
879                                 olsr_ip_to_string(&hna4->netmask));
880         
881                         if ( hna4->netmask.v4 != 0 &&
882                             (addr->v4 & hna4->netmask.v4) == hna4->net.v4 ) {
883                                 olsr_printf(6, "MATCHED\n");
884                                 return OLSR_TRUE;
885                         }
886                 }
887         } else {
888                 int i;
889
890                 for (hna6 = olsr_cnf->hna6_entries; hna6; hna6 = hna6->next)
891                 {
892                         olsr_printf(6, "HNA %s/%d\n", 
893                                 olsr_ip_to_string(&hna6->net),
894                                 hna6->prefix_len);
895                         if ( hna6->prefix_len == 0 )
896                                 continue;
897                         olsr_prefix_to_netmask(&tmp_msk, hna6->prefix_len);
898                         for (i = 0; i < 16; i++) {
899                                 tmp_ip.v6.s6_addr[i] = addr->v6.s6_addr[i] &
900                                         tmp_msk.v6.s6_addr[i];
901                         }
902                         if (COMP_IP(&tmp_ip, &hna6->net)) {
903                                 olsr_printf(6, "MATCHED\n");
904                                 return OLSR_TRUE;
905                         }
906                 }
907         }
908         return OLSR_FALSE;
909 }
910
911 static struct rt_entry *
912 host_lookup_routing_table(union olsr_ip_addr *dst)
913 {
914         olsr_u32_t index;
915         union olsr_ip_addr tmp_ip, tmp_msk;
916         struct rt_entry *walker;
917   
918         walker = olsr_lookup_routing_table(dst);
919         if (walker != NULL)
920                 return walker;
921
922         for (index = 0; index < HASHSIZE; index++) {
923                 for (walker = hna_routes[index].next;
924                     walker != &hna_routes[index]; walker = walker->next) {
925                         if (COMP_IP(&walker->rt_dst, dst))
926                                 return walker;
927                         if (olsr_cnf->ip_version == AF_INET) {
928                                 if ( walker->rt_mask.v4 != 0 &&
929                                     (dst->v4 & walker->rt_mask.v4) ==
930                                     walker->rt_dst.v4 ) {
931                                         olsr_printf(6, "MATCHED\n");
932                                         return walker;
933                                 }
934                         } else {
935                                 int i;
936
937                                 if ( walker->rt_mask.v6 == 0 )
938                                         continue;
939                                 olsr_prefix_to_netmask(&tmp_msk,
940                                     walker->rt_mask.v6);
941                                 for (i = 0; i < 16; i++) {
942                                         tmp_ip.v6.s6_addr[i] =
943                                             dst->v6.s6_addr[i] &
944                                             tmp_msk.v6.s6_addr[i];
945                                 }
946                                 if (COMP_IP(&tmp_ip, &walker->rt_dst)) {
947                                         olsr_printf(6, "MATCHED\n");
948                                         return walker;
949                                 }
950                         }
951                 }
952         }
953         return NULL;
954 }