2 * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
3 * Copyright (c) 2004, Andreas Tønnesen(andreto-at-olsr.org)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
32 /* $Id: nameservice.c,v 1.4 2005/03/01 21:35:14 tlopatic Exp $ */
35 * Dynamic linked library for UniK OLSRd
42 #include "nameservice.h"
43 #include "olsrd_copy.h"
46 /* send buffer: size of IPv6 message + the maximum size of the name */
47 static char buffer[sizeof(struct olsrmsg6) + MAX_NAME];
49 /* config parameters */
50 static char my_filename_buff[MAX_FILE + 1];
51 char* my_filename = my_filename_buff;
52 int my_interval = EMISSION_INTERVAL;
53 double my_timeout = NAME_VALID_TIME;
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;
62 free_name_entry_list(struct name_entry **list)
64 struct name_entry **tmp = list;
65 struct name_entry *to_delete;
66 while (*tmp != NULL) {
69 free( to_delete->name );
77 allowed_ip(union olsr_ip_addr *addr)
79 // we only allow names for IP addresses which announce
80 // so the IP must either be from one of the interfaces
81 // or inside a HNA which we have configured
83 struct hna4_entry *hna4;
86 olsr_printf(6, "checking %s\n", olsr_ip_to_string(addr));
88 for(ifs = cfg->interfaces; ifs; ifs = ifs->next)
90 struct interface *rifs = ifs->interf;
91 olsr_printf(6, "interface %s\n", olsr_ip_to_string(&rifs->ip_addr));
92 if (COMP_IP(&rifs->ip_addr, addr)) {
93 olsr_printf(6, "MATCHED\n");
99 for (hna4 = cfg->hna4_entries; hna4; hna4 = hna4->next)
101 olsr_printf(6, "HNA %s/%s\n",
102 olsr_ip_to_string(&hna4->net),
103 olsr_ip_to_string(&hna4->netmask));
105 if ( hna4->netmask.v4 != 0 && (addr->v4 & hna4->netmask.v4) == hna4->net.v4 ) {
106 olsr_printf(6, "MATCHED\n");
124 GetWindowsDirectory(my_filename_buff, MAX_FILE - 12);
126 len = strlen(my_filename_buff);
128 if (my_filename_buff[len - 1] != '\\')
129 my_filename_buff[len++] = '\\';
131 strcpy(my_filename_buff + len, "olsrd.hosts");
133 strcpy(my_filename_buff, "/var/run/hosts_olsr");
137 for(i = 0; i < HASHSIZE; i++) {
141 /* fix received parameters */
142 // we have to do this here because some things like main_addr
143 // are not known before
144 struct name_entry *name;
145 for (name = my_names; name != NULL; name = name->next) {
146 if (name->ip.v4 == 0) {
148 memcpy(&name->ip, main_addr, ipsize);
150 // IP from config file
151 // check if we are allowed to announce a name for this IP
152 // we can only do this if we also announce the IP
154 if (!allowed_ip(&name->ip)) {
155 olsr_printf(1, "NAME PLUGIN: name for unknown IP %s not allowed, fix your config!\n",
156 olsr_ip_to_string(&name->ip));
162 /* Register functions with olsrd */
163 olsr_parser_add_function(&olsr_parser, PARSER_TYPE, 1);
164 olsr_register_timeout_function(&olsr_timeout);
165 olsr_register_scheduler_event(&olsr_event, NULL, my_interval, 0, NULL);
178 struct db_entry **tmp;
179 struct db_entry *to_delete;
181 olsr_printf(2, "NAME PLUGIN: exit. cleaning up...\n");
183 free_name_entry_list(&my_names);
185 /* free list entries */
186 for(i = 0; i < HASHSIZE; i++)
193 free_name_entry_list(&to_delete->names);
202 * Called for all plugin parameters
205 register_olsr_param(char *key, char *value)
207 if(!strcmp(key, "name")) {
208 // name for main address
209 struct name_entry *tmp;
210 tmp = malloc(sizeof(struct name_entry));
211 tmp->name = strndup( value, MAX_NAME );
212 tmp->len = strlen( tmp->name );
213 tmp->type = NAME_HOST;
214 // will be set to main_addr later
215 memset(&tmp->ip, 0, sizeof(tmp->ip));
216 tmp->next = my_names;
219 printf("\nNAME PLUGIN parameter name: %s (%s)\n", tmp->name, olsr_ip_to_string(&tmp->ip));
221 else if(!strcmp(key, "filename")) {
222 my_filename = strndup( value, MAX_FILE );
223 printf("\nNAME PLUGIN parameter filename: %s\n", my_filename);
225 else if(!strcmp(key, "interval")) {
226 my_interval = atoi(value);
227 printf("\n(NAME PLUGIN parameter interval: %d\n", my_interval);
229 else if(!strcmp(key, "timeout")) {
230 my_timeout = atof(value);
231 printf("\nNAME PLUGIN parameter timeout: %f\n", my_timeout);
234 // assume this is an IP address and hostname
235 // the IPs are validated later
236 struct name_entry *tmp;
237 tmp = malloc(sizeof(struct name_entry));
238 tmp->name = strndup( value, MAX_NAME );
239 tmp->len = strlen( tmp->name );
242 if (!inet_aton(key, &ip)) {
243 printf("\nNAME PLUGIN invalid IP %s, fix your config!\n", key);
246 tmp->ip.v4 = ip.s_addr;
247 tmp->next = my_names;
250 printf("\nNAME PLUGIN parameter: %s (%s)\n", tmp->name, olsr_ip_to_string(&tmp->ip));
258 * A timeout function called every time
259 * the scheduler is polled: time out old list entries
264 struct db_entry **tmp;
265 struct db_entry *to_delete;
268 for(index=0;index<HASHSIZE;index++)
270 for (tmp = &list[index]; *tmp != NULL; )
272 /* check if the entry is timed out */
273 if (olsr_timed_out(&(*tmp)->timer))
278 olsr_printf(2, "NAME PLUGIN: %s timed out... deleting\n",
279 olsr_ip_to_string(&to_delete->originator));
282 free_name_entry_list(&to_delete->names);
284 name_table_changed = OLSR_TRUE;
295 * Scheduled event: generate and send NAME packet
298 olsr_event(void *foo)
300 union olsr_message *message = (union olsr_message*)buffer;
301 struct interface *ifn;
304 olsr_printf(3, "NAME PLUGIN: Generating packet - ");
306 /* looping trough interfaces */
307 for (ifn = ifs; ifn ; ifn = ifn->int_next)
309 olsr_printf(3, "[%s]\n", ifn->int_name);
311 if(ipversion == AF_INET)
314 message->v4.olsr_msgtype = MESSAGE_TYPE;
315 message->v4.olsr_vtime = double_to_me(my_timeout);
316 memcpy(&message->v4.originator, main_addr, ipsize);
317 message->v4.ttl = MAX_TTL;
318 message->v4.hopcnt = 0;
319 message->v4.seqno = htons(get_msg_seqno());
321 namesize = encap_namemsg(&message->v4.msg);
322 namesize = namesize + sizeof(struct olsrmsg);
324 message->v4.olsr_msgsize = htons(namesize);
329 message->v6.olsr_msgtype = MESSAGE_TYPE;
330 message->v6.olsr_vtime = double_to_me(my_timeout);
331 memcpy(&message->v6.originator, main_addr, ipsize);
332 message->v6.ttl = MAX_TTL;
333 message->v6.hopcnt = 0;
334 message->v6.seqno = htons(get_msg_seqno());
336 namesize = encap_namemsg(&message->v6.msg);
337 namesize = namesize + sizeof(struct olsrmsg6);
339 message->v6.olsr_msgsize = htons(namesize);
342 if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
343 /* send data and try again */
345 if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
346 olsr_printf(1, "NAME PLUGIN: could not send on interface: %s\n", ifn->int_name);
354 * Parse name olsr message of NAME type
357 olsr_parser(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *in_addr)
359 struct namemsg *message;
360 union olsr_ip_addr originator;
363 /* Fetch the originator of the messsage */
364 memcpy(&originator, &m->v4.originator, ipsize);
366 /* Fetch the message based on IP version */
367 if(ipversion == AF_INET) {
368 message = &m->v4.msg;
369 vtime = me_to_double(m->v4.olsr_vtime);
372 message = &m->v6.msg;
373 vtime = me_to_double(m->v6.olsr_vtime);
376 /* Check if message originated from this node.
378 if(memcmp(&originator, main_addr, ipsize) == 0)
381 /* Check that the neighbor this message was received from is symmetric.
383 if(check_neighbor_link(in_addr) != SYM_LINK) {
384 olsr_printf(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(in_addr));
388 /* Check if this message has been processed before
389 * Remeber that this also registeres the message as
390 * processed if nessecary
392 if(!check_dup_proc(&originator, ntohs(m->v4.seqno))) {
393 /* If so - do not process */
397 update_name_entry(&originator, message, vtime);
400 /* Forward the message if nessecary
401 * default_fwd does all the work for us! */
402 default_fwd(m, &originator, ntohs(m->v4.seqno), in_if, in_addr);
406 #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
407 #define padding(x,r) (r)-(x)%(r);
410 * Encapsulate a name message into a packet.
412 * It assumed that there is enough space in the buffer to do this!
414 * Returns: the length of the message that was appended
417 encap_namemsg(struct namemsg* msg)
419 struct name_entry *my_name = my_names;
420 struct name* to_packet;
421 char* pos = (char*)msg + sizeof(struct namemsg);
423 while (my_name!=NULL)
425 olsr_printf(3, "NAME PLUGIN: Announcing name %s (%s)\n",
426 my_name->name, olsr_ip_to_string(&my_name->ip));
428 to_packet = (struct name*)pos;
429 to_packet->type = htons(my_name->type);
430 to_packet->len = htons(my_name->len);
431 memcpy(&to_packet->ip, &my_name->ip, ipsize);
432 pos += sizeof(struct name);
433 strncpy(pos, my_name->name, my_name->len);
435 // padding to 4 byte boundaries
436 long pad = (long)pos + roundup(my_name->len, 4) - my_name->len;
437 while ((long)pos < pad) {
441 my_name = my_name->next;
444 msg->nr_names = htons(i);
445 msg->version = htons(NAME_PROTOCOL_VERSION);
446 return pos - (char*)msg; //length
451 * decapsulate a name message and update name_entries if necessary
454 decap_namemsg( struct namemsg *msg, struct name_entry **to )
457 struct name_entry *tmp;
458 struct name *from_packet;
460 olsr_printf(4, "NAME PLUGIN: decapsulating name msg\n");
462 if (ntohs(msg->version) != NAME_PROTOCOL_VERSION) {
463 olsr_printf(3, "NAME PLUGIN: ignoring wrong version %d\n", msg->version);
467 // for now ist easier to just delete everything, than
468 // to update selectively
469 free_name_entry_list(to);
471 /* now add the names from the message */
472 pos = (char*)msg + sizeof(struct namemsg);
474 for (i=ntohs(msg->nr_names); i >= 0; i--) {
475 tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry");
477 from_packet = (struct name*)pos;
478 from_packet->type = ntohs(from_packet->type);
479 from_packet->len = ntohs(from_packet->len);
480 tmp->type = from_packet->type;
481 memcpy(&tmp->ip, &from_packet->ip, ipsize);
483 tmp->name = olsr_malloc(from_packet->len+1, "new name_entry name");
484 strncpy(tmp->name, (char*)from_packet+sizeof(struct name), from_packet->len);
485 tmp->name[from_packet->len] = '\0';
487 olsr_printf(3, "NAME PLUGIN: New name %s (%s) %d\n",
488 tmp->name, olsr_ip_to_string(&tmp->ip), from_packet->len);
494 // next name from packet
495 pos += sizeof(struct name) + roundup(from_packet->len,4);
501 * Update or register a new name entry
504 update_name_entry(union olsr_ip_addr *originator, struct namemsg *msg, double vtime)
507 struct db_entry *entry;
509 olsr_printf(3, "NAME PLUGIN: Received Name Message from %s\n",
510 olsr_ip_to_string(originator));
512 hash = olsr_hashing(originator);
514 /* find the entry for originator */
515 for (entry = list[hash]; entry != NULL; entry = entry->next)
517 if (memcmp(originator, &entry->originator, ipsize) == 0) {
519 olsr_printf(4, "NAME PLUGIN: %s found\n",
520 olsr_ip_to_string(originator));
522 decap_namemsg(msg, &entry->names);
524 olsr_get_timestamp(vtime * 1000, &entry->timer);
526 name_table_changed = OLSR_TRUE;
531 olsr_printf(3, "NAME PLUGIN: New entry %s\n",
532 olsr_ip_to_string(originator));
534 /* insert a new entry */
535 entry = olsr_malloc(sizeof(struct db_entry), "new db_entry");
536 memcpy(&entry->originator, originator, ipsize);
537 olsr_get_timestamp(vtime * 1000, &entry->timer);
540 entry->next = list[hash];
543 decap_namemsg(msg, &entry->names);
545 name_table_changed = OLSR_TRUE;
550 * write names to a file in /etc/hosts compatible format
556 struct name_entry *name;
557 struct db_entry *entry;
560 if(!name_table_changed)
563 olsr_printf(2, "NAME PLUGIN: writing hosts file\n");
565 hosts = fopen( my_filename, "w" );
567 fprintf(hosts, "# this /etc/hosts file is overwritten regularly by olsrd\n");
568 fprintf(hosts, "# do not edit\n");
571 for (name = my_names; name != NULL; name = name->next) {
572 fprintf(hosts, "%s\t%s\t# myself\n", olsr_ip_to_string(&name->ip), name->name );
575 // write received names
576 for(hash = 0; hash < HASHSIZE; hash++)
578 for(entry = list[hash]; entry != NULL; entry = entry->next)
580 for (name = entry->names; name != NULL; name = name->next)
582 olsr_printf(6, "%s\t%s", olsr_ip_to_string(&name->ip), name->name);
583 olsr_printf(6, "\t#%s\n", olsr_ip_to_string(&entry->originator));
585 fprintf(hosts, "%s\t%s", olsr_ip_to_string(&name->ip), name->name);
586 fprintf(hosts, "\t# %s\n", olsr_ip_to_string(&entry->originator));
592 name_table_changed = OLSR_FALSE;