0a64108b36ebcfd3f240f3257c8f04bf0f7bdc74
[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.7 2005/03/03 18:20:16 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 #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                 } else {
181                         // IP from config file
182                         // check if we are allowed to announce a name for this IP
183                         // we can only do this if we also announce the IP
184                          
185                         if (!allowed_ip(&name->ip)) {
186                                 olsr_printf(1, "NAME PLUGIN: name for unknown IP %s not allowed, fix your config!\n", 
187                                         olsr_ip_to_string(&name->ip));
188                                 if (prev!=NULL) {
189                                         prev->next = name->next;
190                                         free(name->name);
191                                         free(name);
192                                 }
193                         }
194                 }
195                 prev = name;
196         }
197         
198         /* register functions with olsrd */
199         olsr_parser_add_function(&olsr_parser, PARSER_TYPE, 1);
200         olsr_register_timeout_function(&olsr_timeout);
201         olsr_register_scheduler_event(&olsr_event, NULL, my_interval, 0, NULL);
202
203         return 1;
204 }
205
206
207 /**
208  * called at unload: free everything
209  */
210 void
211 olsr_plugin_exit()
212 {
213         int i;
214         struct db_entry **tmp;
215         struct db_entry *to_delete;
216         
217         olsr_printf(2, "NAME PLUGIN: exit. cleaning up...\n");
218         
219         free_name_entry_list(&my_names);
220         
221         /* free list entries */
222         for(i = 0; i < HASHSIZE; i++)
223         {
224                 tmp = &list[i];
225                 while(*tmp != NULL)
226                 {
227                         to_delete = *tmp;
228                         *tmp = (*tmp)->next;
229                         free_name_entry_list(&to_delete->names);
230                         free(to_delete);
231                         to_delete = NULL;
232                 }
233         }
234 }
235
236
237 /**
238  * A timeout function called every time
239  * the scheduler is polled: time out old list entries
240  */
241 void
242 olsr_timeout()
243 {
244         struct db_entry **tmp;
245         struct db_entry *to_delete;
246         int index;
247
248         for(index=0;index<HASHSIZE;index++)
249         {
250                 for (tmp = &list[index]; *tmp != NULL; )
251                 {
252                         /* check if the entry is timed out */
253                         if (olsr_timed_out(&(*tmp)->timer))
254                         {
255                                 to_delete = *tmp;
256                                 *tmp = (*tmp)->next;
257                                 
258                                 olsr_printf(2, "NAME PLUGIN: %s timed out... deleting\n", 
259                                         olsr_ip_to_string(&to_delete->originator));
260         
261                                 /* Delete */
262                                 free_name_entry_list(&to_delete->names);
263                                 free(to_delete);
264                                 name_table_changed = OLSR_TRUE;
265                         } else {
266                                 tmp = &(*tmp)->next;
267                         }
268                 }
269         }
270         write_name_table();
271 }
272
273
274 /**
275  * Scheduled event: generate and send NAME packet
276  */
277 void
278 olsr_event(void *foo)
279 {
280         union olsr_message *message = (union olsr_message*)buffer;
281         struct interface *ifn;
282         int namesize;
283   
284         olsr_printf(3, "NAME PLUGIN: Generating packet - ");
285
286         /* looping trough interfaces */
287         for (ifn = ifs; ifn ; ifn = ifn->int_next) 
288         {
289                 olsr_printf(3, "[%s]\n", ifn->int_name);
290                 /* fill message */
291                 if(ipversion == AF_INET)
292                 {
293                         /* IPv4 */
294                         message->v4.olsr_msgtype = MESSAGE_TYPE;
295                         message->v4.olsr_vtime = double_to_me(my_timeout);
296                         memcpy(&message->v4.originator, main_addr, ipsize);
297                         message->v4.ttl = MAX_TTL;
298                         message->v4.hopcnt = 0;
299                         message->v4.seqno = htons(get_msg_seqno());
300                 
301                         namesize = encap_namemsg((struct namemsg*)&message->v4.message);
302                         namesize = namesize + sizeof(struct olsrmsg);
303                 
304                         message->v4.olsr_msgsize = htons(namesize);
305                 }
306                 else
307                 {
308                         /* IPv6 */
309                         message->v6.olsr_msgtype = MESSAGE_TYPE;
310                         message->v6.olsr_vtime = double_to_me(my_timeout);
311                         memcpy(&message->v6.originator, main_addr, ipsize);
312                         message->v6.ttl = MAX_TTL;
313                         message->v6.hopcnt = 0;
314                         message->v6.seqno = htons(get_msg_seqno());
315           
316                         namesize = encap_namemsg((struct namemsg*)&message->v6.message);
317                         namesize = namesize + sizeof(struct olsrmsg6);
318           
319                         message->v6.olsr_msgsize = htons(namesize);
320                 }
321         
322                 if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
323                         /* send data and try again */
324                         net_output(ifn);
325                         if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
326                                 olsr_printf(1, "NAME PLUGIN: could not send on interface: %s\n", ifn->int_name);
327                         }
328                 }
329         }
330 }
331
332
333 /**
334  * Parse name olsr message of NAME type
335  */
336 void
337 olsr_parser(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *in_addr)
338 {
339         struct namemsg *namemessage;
340         union olsr_ip_addr originator;
341         double vtime;
342         int size;
343
344         /* Fetch the originator of the messsage */
345         memcpy(&originator, &m->v4.originator, ipsize);
346                 
347         /* Fetch the message based on IP version */
348         if(ipversion == AF_INET) {
349                 vtime = me_to_double(m->v4.olsr_vtime);
350                 size = ntohs(m->v4.olsr_msgsize);
351                 namemessage = (struct namemsg*)&m->v4.message;
352         }
353         else {
354                 vtime = me_to_double(m->v6.olsr_vtime);
355                 size = ntohs(m->v6.olsr_msgsize);
356                 namemessage = (struct namemsg*)&m->v4.message;
357         }
358
359         /* Check if message originated from this node. 
360         If so - back off */
361         if(memcmp(&originator, main_addr, ipsize) == 0)
362                 return;
363
364         /* Check that the neighbor this message was received from is symmetric. 
365         If not - back off*/
366         if(check_neighbor_link(in_addr) != SYM_LINK) {
367                 olsr_printf(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(in_addr));
368                 return;
369         }
370
371         /* Check if this message has been processed before
372         * Remeber that this also registeres the message as
373         * processed if nessecary
374         */
375         if(!check_dup_proc(&originator, ntohs(m->v4.seqno))) {
376                 /* If so - do not process */
377                 goto forward;
378         }
379
380         update_name_entry(&originator, namemessage, size, vtime);
381
382 forward:
383         /* Forward the message if nessecary
384         * default_fwd does all the work for us! */
385         default_fwd(m, &originator, ntohs(m->v4.seqno), in_if, in_addr);
386 }
387
388
389 /**
390  * Encapsulate a name message into a packet. 
391  *
392  * It assumed that there is enough space in the buffer to do this!
393  *
394  * Returns: the length of the message that was appended
395  */
396 int
397 encap_namemsg(struct namemsg* msg)
398 {
399         struct name_entry *my_name = my_names;
400         struct name* to_packet;
401         char* pos = (char*)msg + sizeof(struct namemsg);
402         short i=0;
403         int k;
404         for (my_name = my_names; my_name!=NULL; my_name = my_name->next)
405         {
406                 olsr_printf(3, "NAME PLUGIN: Announcing name %s (%s) %d\n", 
407                         my_name->name, olsr_ip_to_string(&my_name->ip), my_name->len);
408                         
409                 to_packet = (struct name*)pos;
410                 to_packet->type = htons(my_name->type);
411                 to_packet->len = htons(my_name->len);
412                 memcpy(&to_packet->ip, &my_name->ip, ipsize);
413                 pos += sizeof(struct name);
414                 strncpy(pos, my_name->name, my_name->len);
415                 pos += my_name->len;
416                 // padding to 4 byte boundaries
417                 for (k = my_name->len; (k & 3) != 0; k++)
418                   *pos++ = '\0';
419                 i++;
420         }
421         msg->nr_names = htons(i);
422         msg->version = htons(NAME_PROTOCOL_VERSION);
423         return pos - (char*)msg; //length
424 }
425
426
427 /**
428  * decapsulate a name message and update name_entries if necessary
429  */
430 void
431 decap_namemsg( struct namemsg *msg, int size, struct name_entry **to )
432 {
433         char *pos, *end_pos;
434         struct name_entry *tmp;
435         struct name *from_packet; 
436         int i;
437         
438         olsr_printf(4, "NAME PLUGIN: decapsulating name msg (size %d)\n", size);
439         
440         if (ntohs(msg->version) != NAME_PROTOCOL_VERSION) {
441                 olsr_printf(3, "NAME PLUGIN: ignoring wrong version %d\n", msg->version);
442                 return;
443         }
444         
445         // for now ist easier to just delete everything, than
446         // to update selectively
447         free_name_entry_list(to);
448         
449         /* now add the names from the message */
450         pos = (char*)msg + sizeof(struct namemsg);
451         end_pos = pos + size - sizeof(struct name*); // at least one struct name hast to be left
452         
453         for (i=ntohs(msg->nr_names); i > 0 && pos<end_pos; i--) 
454         {
455                 from_packet = (struct name*)pos;
456                 
457                 tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry");         
458                 tmp->type = ntohs(from_packet->type);
459                 tmp->len = ntohs(from_packet->len) > MAX_NAME ? MAX_NAME : ntohs(from_packet->len);
460                 tmp->name = olsr_malloc(tmp->len+1, "new name_entry name");
461                 memcpy(&tmp->ip, &from_packet->ip, ipsize);
462                 pos += sizeof(struct name);
463                 strncpy(tmp->name, pos, tmp->len);
464                 tmp->name[tmp->len] = '\0';
465
466                 olsr_printf(3, "NAME PLUGIN: New name %s (%s) %d %d\n", 
467                         tmp->name, olsr_ip_to_string(&tmp->ip), tmp->len, tmp->type);
468
469                 // queue to front
470                 tmp->next = *to;
471                 *to = tmp;
472
473                 // name + padding
474                 pos += 1 + ((tmp->len - 1) | 3);
475         }
476         if (i!=0)
477                 olsr_printf(4, "NAME PLUGIN: Lost %d names due to length inconsistency\n", i);
478 }
479
480
481 /**
482  * Update or register a new name entry
483  */
484 void
485 update_name_entry(union olsr_ip_addr *originator, struct namemsg *msg, int msg_size, double vtime)
486 {
487         int hash;
488         struct db_entry *entry;
489
490         olsr_printf(3, "NAME PLUGIN: Received Name Message from %s\n", 
491                 olsr_ip_to_string(originator));
492
493         hash = olsr_hashing(originator);
494
495         /* find the entry for originator */
496         for (entry = list[hash]; entry != NULL; entry = entry->next)
497         {
498                 if (memcmp(originator, &entry->originator, ipsize) == 0) {
499                         // found
500                         olsr_printf(4, "NAME PLUGIN: %s found\n", 
501                                 olsr_ip_to_string(originator));
502                 
503                         decap_namemsg(msg, msg_size, &entry->names);
504                         
505                         olsr_get_timestamp(vtime * 1000, &entry->timer);
506                         
507                         name_table_changed = OLSR_TRUE;
508                         return;
509                 }
510         }
511
512         olsr_printf(3, "NAME PLUGIN: New entry %s\n", 
513                 olsr_ip_to_string(originator));
514                 
515         /* insert a new entry */
516         entry = olsr_malloc(sizeof(struct db_entry), "new db_entry");
517         memcpy(&entry->originator, originator, ipsize);
518         olsr_get_timestamp(vtime * 1000, &entry->timer);
519         entry->names = NULL;
520         // queue to front
521         entry->next = list[hash];
522         list[hash] = entry;
523         
524         decap_namemsg(msg, msg_size, &entry->names);
525
526         name_table_changed = OLSR_TRUE;
527 }
528
529
530 /**
531  * write names to a file in /etc/hosts compatible format
532  */
533 void
534 write_name_table()
535 {
536         int hash;
537         struct name_entry *name;
538         struct db_entry *entry;
539         FILE* hosts;
540
541         if(!name_table_changed)
542                 return;
543
544         olsr_printf(2, "NAME PLUGIN: writing hosts file\n");
545                       
546         hosts = fopen( my_filename, "w" );
547         if (hosts == NULL) {
548                 olsr_printf(2, "NAME PLUGIN: cant write hosts file\n");
549                 return;
550         }
551         
552         fprintf(hosts, "# this /etc/hosts file is overwritten regularly by olsrd\n");
553         fprintf(hosts, "# do not edit\n");
554         
555         // write own names
556         for (name = my_names; name != NULL; name = name->next) {
557                 fprintf(hosts, "%s\t%s%s\t# myself\n", olsr_ip_to_string(&name->ip),
558                         name->name, my_suffix );
559         }
560         
561         // write received names
562         for(hash = 0; hash < HASHSIZE; hash++) 
563         {
564                 for(entry = list[hash]; entry != NULL; entry = entry->next)
565                 {
566                         for (name = entry->names; name != NULL; name = name->next) 
567                         {
568                                 olsr_printf(6, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
569                                 olsr_printf(6, "\t#%s\n", olsr_ip_to_string(&entry->originator));
570                                 
571                                 fprintf(hosts, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
572                                 fprintf(hosts, "\t# %s\n", olsr_ip_to_string(&entry->originator));
573                         }
574                 }
575         }
576         
577         fclose(hosts);
578         name_table_changed = OLSR_FALSE;
579 }
580
581 /**
582  * completely free a list of name_entries
583  */
584 void 
585 free_name_entry_list(struct name_entry **list) 
586 {
587         struct name_entry **tmp = list;
588         struct name_entry *to_delete;
589         while (*tmp != NULL) {
590                 to_delete = *tmp;
591                 *tmp = (*tmp)->next;
592                 free( to_delete->name );
593                 free( to_delete );
594                 to_delete = NULL;
595         }
596 }
597
598
599 /**
600  * we only allow names for IP addresses which we are
601  * responsible for: 
602  * so the IP must either be from one of the interfaces
603  * or inside a HNA which we have configured 
604  */
605 olsr_bool
606 allowed_ip(union olsr_ip_addr *addr)
607 {
608         struct hna4_entry *hna4;
609         struct olsr_if *ifs;
610         
611         olsr_printf(6, "checking %s\n", olsr_ip_to_string(addr));
612         
613         for(ifs = cfg->interfaces; ifs; ifs = ifs->next)
614         {
615                 struct interface *rifs = ifs->interf;
616                 olsr_printf(6, "interface %s\n", olsr_ip_to_string(&rifs->ip_addr));
617                 if (COMP_IP(&rifs->ip_addr, addr)) {
618                         olsr_printf(6, "MATCHED\n");
619                         return OLSR_TRUE;
620                         
621                 }
622         }
623         
624         for (hna4 = cfg->hna4_entries; hna4; hna4 = hna4->next)
625         {
626                 olsr_printf(6, "HNA %s/%s\n", 
627                         olsr_ip_to_string(&hna4->net),
628                         olsr_ip_to_string(&hna4->netmask));
629                 
630                 if ( hna4->netmask.v4 != 0 && (addr->v4 & hna4->netmask.v4) == hna4->net.v4 ) {
631                         olsr_printf(6, "MATCHED\n");
632                         return OLSR_TRUE;
633                 }
634         }
635         return OLSR_FALSE;
636 }