2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
4 * includes code by Bruno Randolf
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of olsr.org, olsrd nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * Visit http://www.olsr.org for more information.
36 * If you find this software useful feel free to make a donation
37 * to the project. For more information see the website or contact
38 * the copyright holders.
40 * $Id: olsrd_dot_draw.c,v 1.13 2005/05/25 16:33:24 br1 Exp $
44 * Dynamic linked library for the olsr.org olsr daemon
47 #include "olsrd_dot_draw.h"
54 #define close(x) closesocket(x)
63 calc_etx(double, double);
66 ipc_print_neigh_link(struct neighbor_entry *);
72 ipc_print_neigh_link(struct neighbor_entry *neighbor)
78 char* style = "solid";
79 struct link_entry* link;
80 adr = olsr_ip_to_string(main_addr);
81 len = sprintf( buf, "\"%s\" -> ", adr );
84 adr = olsr_ip_to_string(&neighbor->neighbor_main_addr);
86 if (neighbor->status == 0) { // non SYM
90 /* find best link to neighbor for the ETX */
91 //? why cant i just get it one time at fetch_olsrd_data??? (br1)
92 if(olsr_plugin_io(GETD__LINK_SET, &link, sizeof(link)) && link)
94 link_set = link; // for olsr_neighbor_best_link
95 link = olsr_neighbor_best_link(&neighbor->neighbor_main_addr);
97 etx = calc_etx( link->loss_link_quality, link->neigh_link_quality);
102 len = sprintf( buf, "\"%s\"[label=\"%.2f\", style=%s];\n", adr, etx, style );
105 if (neighbor->is_mpr) {
106 len = sprintf( buf, "\"%s\"[shape=box];\n", adr );
112 *Do initialization here
114 *This function is called by the my_init
115 *function in uolsrd_plugin.c
121 /* Initial IPC value */
125 /* Register the "ProcessChanges" function */
126 register_pcf(&pcf_event);
134 struct sockaddr_in sin;
137 /* Init ipc socket */
138 if ((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
140 olsr_printf(1, "(DOT DRAW)IPC socket %s\n", strerror(errno));
145 if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0)
147 perror("SO_REUSEADDR failed");
152 if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0)
154 perror("SO_REUSEADDR failed");
159 /* Bind the socket */
161 /* complete the socket structure */
162 memset(&sin, 0, sizeof(sin));
163 sin.sin_family = AF_INET;
164 sin.sin_addr.s_addr = INADDR_ANY;
165 sin.sin_port = htons(ipc_port);
167 /* bind the socket to the port number */
168 if (bind(ipc_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1)
170 olsr_printf(1, "(DOT DRAW)IPC bind %s\n", strerror(errno));
174 /* show that we are willing to listen */
175 if (listen(ipc_socket, 1) == -1)
177 olsr_printf(1, "(DOT DRAW)IPC listen %s\n", strerror(errno));
182 /* Register with olsrd */
183 add_olsr_socket(ipc_socket, &ipc_action);
193 struct sockaddr_in pin;
197 addrlen = sizeof(struct sockaddr_in);
199 if ((ipc_connection = accept(ipc_socket, (struct sockaddr *) &pin, &addrlen)) == -1)
201 olsr_printf(1, "(DOT DRAW)IPC accept: %s\n", strerror(errno));
206 addr = inet_ntoa(pin.sin_addr);
207 if(ntohl(pin.sin_addr.s_addr) != ntohl(ipc_accept_ip.s_addr))
209 olsr_printf(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
210 close(ipc_connection);
216 olsr_printf(1, "(DOT DRAW)IPC: Connection from %s\n",addr);
224 * destructor - called at unload
235 /* Mulitpurpose funtion */
237 plugin_io(int cmd, void *data, size_t size)
256 pcf_event(int changes_neighborhood,
257 int changes_topology,
262 struct neighbor_entry *neighbor_table_tmp;
263 struct tc_entry *entry;
264 struct topo_dst *dst_entry;
265 struct hna_entry *tmp_hna;
266 struct hna_net *tmp_net;
270 if(changes_neighborhood || changes_topology || changes_hna)
272 /* Print tables to IPC socket */
274 ipc_send("digraph topology\n{\n", strlen("digraph topology\n{\n"));
277 for(index=0;index<HASHSIZE;index++)
280 for(neighbor_table_tmp = neighbortable[index].next;
281 neighbor_table_tmp != &neighbortable[index];
282 neighbor_table_tmp = neighbor_table_tmp->next)
284 ipc_print_neigh_link( neighbor_table_tmp );
289 for(index=0;index<HASHSIZE;index++)
291 /* For all TC entries */
292 entry = tc_table[index].next;
293 while(entry != &tc_table[index])
295 /* For all destination entries of that TC entry */
296 dst_entry = entry->destinations.next;
297 while(dst_entry != &entry->destinations)
299 ipc_print_tc_link(entry, dst_entry);
300 dst_entry = dst_entry->next;
307 for(index=0;index<HASHSIZE;index++)
309 tmp_hna = hna_set[index].next;
310 /* Check all entrys */
311 while(tmp_hna != &hna_set[index])
313 /* Check all networks */
314 tmp_net = tmp_hna->networks.next;
316 while(tmp_net != &tmp_hna->networks)
318 ipc_print_net(&tmp_hna->A_gateway_addr,
319 &tmp_net->A_network_addr,
320 &tmp_net->A_netmask);
321 tmp_net = tmp_net->next;
324 tmp_hna = tmp_hna->next;
329 ipc_send("}\n\n", strlen("}\n\n"));
341 #define MIN_LINK_QUALITY 0.01
343 calc_etx(double loss, double neigh_loss)
345 if (loss < MIN_LINK_QUALITY || neigh_loss < MIN_LINK_QUALITY)
348 return 1.0 / (loss * neigh_loss);
353 ipc_print_tc_link(struct tc_entry *entry, struct topo_dst *dst_entry)
358 double etx = calc_etx( dst_entry->link_quality, dst_entry->inverse_link_quality );
360 adr = olsr_ip_to_string(&entry->T_last_addr);
361 len = sprintf( buf, "\"%s\" -> ", adr );
364 adr = olsr_ip_to_string(&dst_entry->T_dest_addr);
365 len = sprintf( buf, "\"%s\"[label=\"%.2f\"];\n", adr, etx );
370 ipc_print_net(union olsr_ip_addr *gw, union olsr_ip_addr *net, union hna_netmask *mask)
374 adr = olsr_ip_to_string(gw);
376 ipc_send(adr, strlen(adr));
377 ipc_send("\" -> \"", strlen("\" -> \""));
378 adr = olsr_ip_to_string(net);
379 ipc_send(adr, strlen(adr));
381 adr = olsr_netmask_to_string(mask);
382 ipc_send(adr, strlen(adr));
383 ipc_send("\"[label=\"HNA\"];\n", strlen("\"[label=\"HNA\"];\n"));
385 adr = olsr_ip_to_string(net);
386 ipc_send(adr, strlen(adr));
388 adr = olsr_netmask_to_string(mask);
389 ipc_send(adr, strlen(adr));
391 ipc_send("[shape=diamond];\n", strlen("[shape=diamond];\n"));
397 ipc_send(char *data, int size)
402 #if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
403 if (send(ipc_connection, data, size, 0) < 0)
405 if (send(ipc_connection, data, size, MSG_NOSIGNAL) < 0)
408 olsr_printf(1, "(DOT DRAW)IPC connection lost!\n");
409 close(ipc_connection);
422 *Converts a olsr_ip_addr to a string
423 *Goes for both IPv4 and IPv6
425 *@param the IP to convert
426 *@return a pointer to a static string buffer
427 *representing the address in "dots and numbers"
431 olsr_ip_to_string(union olsr_ip_addr *addr)
433 static int index = 0;
434 static char buff[4][100];
438 if(ipversion == AF_INET)
446 ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));
449 strncpy(buff[index], ret, 100);
453 index = (index + 1) & 3;
460 *This function is just as bad as the previous one :-(
463 olsr_netmask_to_string(union hna_netmask *mask)
468 if(ipversion == AF_INET)
470 in.s_addr = mask->v4;
478 sprintf(netmask, "%d", mask->v6);
485 #define COMP_IP(ip1, ip2) (!memcmp(ip1, ip2, ipsize))
486 struct link_entry *olsr_neighbor_best_link(union olsr_ip_addr *main)
488 struct link_entry *walker;
491 struct link_entry *res = NULL;
493 // loop through all links
495 for (walker = link_set; walker != NULL; walker = walker->next)
497 // check whether it's a link to the requested neighbor and
498 // whether the link's quality is better than what we have
499 if(COMP_IP(main, &walker->neighbor->neighbor_main_addr))
501 curr = walker->loss_link_quality * walker->neigh_link_quality;