6b1008a426f41712987ab4e4b8c53a60d1161765
[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.8 2005/03/07 13:29:40 br1 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 #include "nameservice.h"
43 #include "olsrd_copy.h"
44
45
46 /* send buffer: huge */
47 static char buffer[10240];
48
49 /* config parameters */
50 static char my_filename[MAX_FILE + 1];
51 static char my_suffix[MAX_SUFFIX];
52 int my_interval = EMISSION_INTERVAL;
53 double my_timeout = NAME_VALID_TIME;
54
55 /* the database (using hashing) */
56 struct db_entry* list[HASHSIZE];
57 struct name_entry *my_names = NULL;
58 olsr_bool name_table_changed = OLSR_TRUE;
59
60
61 /**
62  * do initialization
63  */
64 void
65 name_constructor() 
66 {
67         int i;
68         
69 #ifdef WIN32
70         int len;
71
72         GetWindowsDirectory(my_filename, MAX_FILE - 12);
73
74         len = strlen(my_filename);
75  
76         if (my_filename[len - 1] != '\\')
77                 my_filename[len++] = '\\';
78  
79         strcpy(my_filename + len, "hosts_olsr");
80 #else
81         strcpy(my_filename, "/var/run/hosts_olsr");
82 #endif
83
84         my_suffix[0] = '\0';
85         
86         /* init list */
87         for(i = 0; i < HASHSIZE; i++) {
88                 list[i] = NULL;
89         }
90 }
91
92
93 /**
94  * called for all plugin parameters
95  */
96 int
97 register_olsr_param(char *key, char *value)
98 {
99         if(!strcmp(key, "name")) {
100                 // name for main address
101                 struct name_entry *tmp;
102                 tmp = malloc(sizeof(struct name_entry));
103                 tmp->name = strndup( value, MAX_NAME );
104                 tmp->len = strlen( tmp->name );
105                 tmp->type = NAME_HOST;
106                 // will be set to main_addr later
107                 memset(&tmp->ip, 0, sizeof(tmp->ip));
108                 tmp->next = my_names;
109                 my_names = tmp;
110                 
111                 printf("\nNAME PLUGIN: parameter name: %s (main address)\n", tmp->name);
112         } 
113         else if(!strcmp(key, "filename")) {
114                 strncpy( my_filename, value, MAX_FILE );
115                 printf("\nNAME PLUGIN: parameter filename: %s\n", my_filename);
116         }
117         else if(!strcmp(key, "interval")) {
118                 my_interval = atoi(value);
119                 printf("\nNAME PLUGIN: parameter interval: %d\n", my_interval);
120         }
121         else if(!strcmp(key, "timeout")) {
122                 my_timeout = atof(value);
123                 printf("\nNAME PLUGIN: parameter timeout: %f\n", my_timeout);
124         }
125         else if(!strcmp(key, "suffix")) {
126                 strncpy(my_suffix, value, MAX_SUFFIX);
127                 printf("\nNAME PLUGIN: parameter suffix: %s\n", my_suffix);
128         }
129
130         else {
131                 // assume this is an IP address and hostname
132                 struct in_addr ip;
133                 
134                 if (inet_aton(key, &ip)) {
135                         // the IP is validated later
136                         struct name_entry *tmp;
137                         tmp = malloc(sizeof(struct name_entry));
138                         tmp->name = strndup( value, MAX_NAME );
139                         tmp->len = strlen( tmp->name );
140                         tmp->type = NAME_HOST;
141                         tmp->ip.v4 = ip.s_addr;
142                         tmp->next = my_names;
143                         my_names = tmp;
144                         printf("\nNAME PLUGIN: parameter %s (%s)\n", tmp->name,
145                                 olsr_ip_to_string(&tmp->ip));
146                 } 
147                 else {
148                         printf("\nNAME PLUGIN: invalid IP %s, fix your config!\n", key);
149                 }
150         }
151
152         return 1;
153 }
154
155
156 /**
157  * last initialization
158  *
159  * we have to do this here because some things like main_addr 
160  * are not known before
161  *
162  * this is beause of the order in which the plugin is initzalized 
163  * by the plugin loader:
164  *   - first the parameters are sent
165  *   - then register_olsr_data() from olsrd_plugin.c is called
166  *     which sets up main_addr and some other variables
167  *   - register_olsr_data() then then finally calls this function
168  */
169 int
170 olsr_plugin_init()
171 {
172         struct name_entry *name;
173         struct name_entry *prev=NULL;
174
175         /* fixup names and IP addresses */
176         for (name = my_names; name != NULL; name = name->next) {
177                 if (name->ip.v4 == 0) {
178                         // insert main_addr
179                         memcpy(&name->ip, main_addr, ipsize);
180                         prev = name;
181                 } else {
182                         // IP from config file
183                         // check if we are allowed to announce a name for this IP
184                         // we can only do this if we also announce the IP
185                          
186                         if (!allowed_ip(&name->ip)) {
187                                 olsr_printf(1, "NAME PLUGIN: name for unknown IP %s not allowed, fix your config!\n", 
188                                         olsr_ip_to_string(&name->ip));
189                                 if (prev!=NULL) {
190                                         prev->next = name->next;
191                                         free(name->name);
192                                         free(name);
193                                 }
194                         }
195                         else {
196                                 prev = name;
197                         }
198                 }
199         }
200         
201         /* register functions with olsrd */
202         olsr_parser_add_function(&olsr_parser, PARSER_TYPE, 1);
203         olsr_register_timeout_function(&olsr_timeout);
204         olsr_register_scheduler_event(&olsr_event, NULL, my_interval, 0, NULL);
205
206         return 1;
207 }
208
209
210 /**
211  * called at unload: free everything
212  */
213 void
214 olsr_plugin_exit()
215 {
216         int i;
217         struct db_entry **tmp;
218         struct db_entry *to_delete;
219         
220         olsr_printf(2, "NAME PLUGIN: exit. cleaning up...\n");
221         
222         free_name_entry_list(&my_names);
223         
224         /* free list entries */
225         for(i = 0; i < HASHSIZE; i++)
226         {
227                 tmp = &list[i];
228                 while(*tmp != NULL)
229                 {
230                         to_delete = *tmp;
231                         *tmp = (*tmp)->next;
232                         free_name_entry_list(&to_delete->names);
233                         free(to_delete);
234                         to_delete = NULL;
235                 }
236         }
237 }
238
239
240 /**
241  * A timeout function called every time
242  * the scheduler is polled: time out old list entries
243  */
244 void
245 olsr_timeout()
246 {
247         struct db_entry **tmp;
248         struct db_entry *to_delete;
249         int index;
250
251         for(index=0;index<HASHSIZE;index++)
252         {
253                 for (tmp = &list[index]; *tmp != NULL; )
254                 {
255                         /* check if the entry is timed out */
256                         if (olsr_timed_out(&(*tmp)->timer))
257                         {
258                                 to_delete = *tmp;
259                                 *tmp = (*tmp)->next;
260                                 
261                                 olsr_printf(2, "NAME PLUGIN: %s timed out... deleting\n", 
262                                         olsr_ip_to_string(&to_delete->originator));
263         
264                                 /* Delete */
265                                 free_name_entry_list(&to_delete->names);
266                                 free(to_delete);
267                                 name_table_changed = OLSR_TRUE;
268                         } else {
269                                 tmp = &(*tmp)->next;
270                         }
271                 }
272         }
273         write_name_table();
274 }
275
276
277 /**
278  * Scheduled event: generate and send NAME packet
279  */
280 void
281 olsr_event(void *foo)
282 {
283         union olsr_message *message = (union olsr_message*)buffer;
284         struct interface *ifn;
285         int namesize;
286   
287         /* looping trough interfaces */
288         for (ifn = ifs; ifn ; ifn = ifn->int_next) 
289         {
290                 olsr_printf(3, "NAME PLUGIN: Generating packet - [%s]\n", ifn->int_name);
291
292                 /* fill message */
293                 if(ipversion == AF_INET)
294                 {
295                         /* IPv4 */
296                         message->v4.olsr_msgtype = MESSAGE_TYPE;
297                         message->v4.olsr_vtime = double_to_me(my_timeout);
298                         memcpy(&message->v4.originator, main_addr, ipsize);
299                         message->v4.ttl = MAX_TTL;
300                         message->v4.hopcnt = 0;
301                         message->v4.seqno = htons(get_msg_seqno());
302                         
303                         namesize = encap_namemsg((struct namemsg*)&message->v4.message);
304                         namesize = namesize + sizeof(struct olsrmsg);
305                         
306                         message->v4.olsr_msgsize = htons(namesize);
307                 }
308                 else
309                 {
310                         /* IPv6 */
311                         message->v6.olsr_msgtype = MESSAGE_TYPE;
312                         message->v6.olsr_vtime = double_to_me(my_timeout);
313                         memcpy(&message->v6.originator, main_addr, ipsize);
314                         message->v6.ttl = MAX_TTL;
315                         message->v6.hopcnt = 0;
316                         message->v6.seqno = htons(get_msg_seqno());
317                         
318                         namesize = encap_namemsg((struct namemsg*)&message->v6.message);
319                         namesize = namesize + sizeof(struct olsrmsg6);
320                         
321                         message->v6.olsr_msgsize = htons(namesize);
322                 }
323                 
324                 if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
325                         /* send data and try again */
326                         net_output(ifn);
327                         if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
328                                 olsr_printf(1, "NAME PLUGIN: could not send on interface: %s\n", ifn->int_name);
329                         }
330                 }
331         }
332 }
333
334
335 /**
336  * Parse name olsr message of NAME type
337  */
338 void
339 olsr_parser(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *in_addr)
340 {
341         struct namemsg *namemessage;
342         union olsr_ip_addr originator;
343         double vtime;
344         int size;
345
346         /* Fetch the originator of the messsage */
347         memcpy(&originator, &m->v4.originator, ipsize);
348                 
349         /* Fetch the message based on IP version */
350         if(ipversion == AF_INET) {
351                 vtime = me_to_double(m->v4.olsr_vtime);
352                 size = ntohs(m->v4.olsr_msgsize);
353                 namemessage = (struct namemsg*)&m->v4.message;
354         }
355         else {
356                 vtime = me_to_double(m->v6.olsr_vtime);
357                 size = ntohs(m->v6.olsr_msgsize);
358                 namemessage = (struct namemsg*)&m->v4.message;
359         }
360
361         /* Check if message originated from this node. 
362         If so - back off */
363         if(memcmp(&originator, main_addr, ipsize) == 0)
364                 return;
365
366         /* Check that the neighbor this message was received from is symmetric. 
367         If not - back off*/
368         if(check_neighbor_link(in_addr) != SYM_LINK) {
369                 olsr_printf(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(in_addr));
370                 return;
371         }
372
373         /* Check if this message has been processed before
374         * Remeber that this also registeres the message as
375         * processed if nessecary
376         */
377         if(!check_dup_proc(&originator, ntohs(m->v4.seqno))) {
378                 /* If so - do not process */
379                 goto forward;
380         }
381
382         update_name_entry(&originator, namemessage, size, vtime);
383
384 forward:
385         /* Forward the message if nessecary
386         * default_fwd does all the work for us! */
387         default_fwd(m, &originator, ntohs(m->v4.seqno), in_if, in_addr);
388 }
389
390
391 /**
392  * Encapsulate a name message into a packet. 
393  *
394  * It assumed that there is enough space in the buffer to do this!
395  *
396  * Returns: the length of the message that was appended
397  */
398 int
399 encap_namemsg(struct namemsg* msg)
400 {
401         struct name_entry *my_name = my_names;
402         struct name* to_packet;
403         char* pos = (char*)msg + sizeof(struct namemsg);
404         short i=0;
405         int k;
406         for (my_name = my_names; my_name!=NULL; my_name = my_name->next)
407         {
408                 olsr_printf(3, "NAME PLUGIN: Announcing name %s (%s) %d\n", 
409                         my_name->name, olsr_ip_to_string(&my_name->ip), my_name->len);
410                         
411                 to_packet = (struct name*)pos;
412                 to_packet->type = htons(my_name->type);
413                 to_packet->len = htons(my_name->len);
414                 memcpy(&to_packet->ip, &my_name->ip, ipsize);
415                 pos += sizeof(struct name);
416                 strncpy(pos, my_name->name, my_name->len);
417                 pos += my_name->len;
418                 // padding to 4 byte boundaries
419                 for (k = my_name->len; (k & 3) != 0; k++)
420                         *pos++ = '\0';
421                 i++;
422         }
423         msg->nr_names = htons(i);
424         msg->version = htons(NAME_PROTOCOL_VERSION);
425         return pos - (char*)msg; //length
426 }
427
428
429 /**
430  * decapsulate a name message and update name_entries if necessary
431  */
432 void
433 decap_namemsg( struct namemsg *msg, int size, struct name_entry **to )
434 {
435         char *pos, *end_pos;
436         struct name_entry *tmp;
437         struct name *from_packet; 
438         int i;
439         
440         olsr_printf(4, "NAME PLUGIN: decapsulating name msg (size %d)\n", size);
441         
442         if (ntohs(msg->version) != NAME_PROTOCOL_VERSION) {
443                 olsr_printf(3, "NAME PLUGIN: ignoring wrong version %d\n", msg->version);
444                 return;
445         }
446         
447         // for now ist easier to just delete everything, than
448         // to update selectively
449         free_name_entry_list(to);
450         
451         /* now add the names from the message */
452         pos = (char*)msg + sizeof(struct namemsg);
453         end_pos = pos + size - sizeof(struct name*); // at least one struct name hast to be left
454         
455         for (i=ntohs(msg->nr_names); i > 0 && pos<end_pos; i--) 
456         {
457                 from_packet = (struct name*)pos;
458                 
459                 tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry");         
460                 tmp->type = ntohs(from_packet->type);
461                 tmp->len = ntohs(from_packet->len) > MAX_NAME ? MAX_NAME : ntohs(from_packet->len);
462                 tmp->name = olsr_malloc(tmp->len+1, "new name_entry name");
463                 memcpy(&tmp->ip, &from_packet->ip, ipsize);
464                 pos += sizeof(struct name);
465                 strncpy(tmp->name, pos, tmp->len);
466                 tmp->name[tmp->len] = '\0';
467
468                 olsr_printf(3, "NAME PLUGIN: New name %s (%s) %d %d\n", 
469                         tmp->name, olsr_ip_to_string(&tmp->ip), tmp->len, tmp->type);
470
471                 // queue to front
472                 tmp->next = *to;
473                 *to = tmp;
474
475                 // name + padding
476                 pos += 1 + ((tmp->len - 1) | 3);
477         }
478         if (i!=0)
479                 olsr_printf(4, "NAME PLUGIN: Lost %d names due to length inconsistency\n", i);
480 }
481
482
483 /**
484  * Update or register a new name entry
485  */
486 void
487 update_name_entry(union olsr_ip_addr *originator, struct namemsg *msg, int msg_size, double vtime)
488 {
489         int hash;
490         struct db_entry *entry;
491
492         olsr_printf(3, "NAME PLUGIN: Received Name Message from %s\n", 
493                 olsr_ip_to_string(originator));
494
495         hash = olsr_hashing(originator);
496
497         /* find the entry for originator */
498         for (entry = list[hash]; entry != NULL; entry = entry->next)
499         {
500                 if (memcmp(originator, &entry->originator, ipsize) == 0) {
501                         // found
502                         olsr_printf(4, "NAME PLUGIN: %s found\n", 
503                                 olsr_ip_to_string(originator));
504                 
505                         decap_namemsg(msg, msg_size, &entry->names);
506                         
507                         olsr_get_timestamp(vtime * 1000, &entry->timer);
508                         
509                         name_table_changed = OLSR_TRUE;
510                         return;
511                 }
512         }
513
514         olsr_printf(3, "NAME PLUGIN: New entry %s\n", 
515                 olsr_ip_to_string(originator));
516                 
517         /* insert a new entry */
518         entry = olsr_malloc(sizeof(struct db_entry), "new db_entry");
519         memcpy(&entry->originator, originator, ipsize);
520         olsr_get_timestamp(vtime * 1000, &entry->timer);
521         entry->names = NULL;
522         // queue to front
523         entry->next = list[hash];
524         list[hash] = entry;
525         
526         decap_namemsg(msg, msg_size, &entry->names);
527
528         name_table_changed = OLSR_TRUE;
529 }
530
531
532 /**
533  * write names to a file in /etc/hosts compatible format
534  */
535 void
536 write_name_table()
537 {
538         int hash;
539         struct name_entry *name;
540         struct db_entry *entry;
541         FILE* hosts;
542
543         if(!name_table_changed)
544                 return;
545
546         olsr_printf(2, "NAME PLUGIN: writing hosts file\n");
547                       
548         hosts = fopen( my_filename, "w" );
549         if (hosts == NULL) {
550                 olsr_printf(2, "NAME PLUGIN: cant write hosts file\n");
551                 return;
552         }
553         
554         fprintf(hosts, "# this /etc/hosts file is overwritten regularly by olsrd\n");
555         fprintf(hosts, "# do not edit\n");
556         
557         // write own names
558         for (name = my_names; name != NULL; name = name->next) {
559                 fprintf(hosts, "%s\t%s%s\t# myself\n", olsr_ip_to_string(&name->ip),
560                         name->name, my_suffix );
561         }
562         
563         // write received names
564         for(hash = 0; hash < HASHSIZE; hash++) 
565         {
566                 for(entry = list[hash]; entry != NULL; entry = entry->next)
567                 {
568                         for (name = entry->names; name != NULL; name = name->next) 
569                         {
570                                 olsr_printf(6, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
571                                 olsr_printf(6, "\t#%s\n", olsr_ip_to_string(&entry->originator));
572                                 
573                                 fprintf(hosts, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
574                                 fprintf(hosts, "\t# %s\n", olsr_ip_to_string(&entry->originator));
575                         }
576                 }
577         }
578         
579         fclose(hosts);
580         name_table_changed = OLSR_FALSE;
581 }
582
583 /**
584  * completely free a list of name_entries
585  */
586 void 
587 free_name_entry_list(struct name_entry **list) 
588 {
589         struct name_entry **tmp = list;
590         struct name_entry *to_delete;
591         while (*tmp != NULL) {
592                 to_delete = *tmp;
593                 *tmp = (*tmp)->next;
594                 free( to_delete->name );
595                 free( to_delete );
596                 to_delete = NULL;
597         }
598 }
599
600
601 /**
602  * we only allow names for IP addresses which we are
603  * responsible for: 
604  * so the IP must either be from one of the interfaces
605  * or inside a HNA which we have configured 
606  */
607 olsr_bool
608 allowed_ip(union olsr_ip_addr *addr)
609 {
610         struct hna4_entry *hna4;
611         struct olsr_if *ifs;
612         
613         olsr_printf(6, "checking %s\n", olsr_ip_to_string(addr));
614         
615         for(ifs = cfg->interfaces; ifs; ifs = ifs->next)
616         {
617                 struct interface *rifs = ifs->interf;
618                 olsr_printf(6, "interface %s\n", olsr_ip_to_string(&rifs->ip_addr));
619                 if (COMP_IP(&rifs->ip_addr, addr)) {
620                         olsr_printf(6, "MATCHED\n");
621                         return OLSR_TRUE;
622                         
623                 }
624         }
625         
626         for (hna4 = cfg->hna4_entries; hna4; hna4 = hna4->next)
627         {
628                 olsr_printf(6, "HNA %s/%s\n", 
629                         olsr_ip_to_string(&hna4->net),
630                         olsr_ip_to_string(&hna4->netmask));
631                 
632                 if ( hna4->netmask.v4 != 0 && (addr->v4 & hna4->netmask.v4) == hna4->net.v4 ) {
633                         olsr_printf(6, "MATCHED\n");
634                         return OLSR_TRUE;
635                 }
636         }
637         return OLSR_FALSE;
638 }