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.23 2007/04/20 14:06:18 bernd67 Exp $
44 * Dynamic linked library for the olsr.org olsr daemon
48 #include <sys/types.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
62 #include "olsr_types.h"
63 #include "neighbor_table.h"
64 #include "two_hop_neighbor_table.h"
69 #include "socket_parser.h"
71 #include "olsrd_dot_draw.h"
72 #include "olsrd_plugin.h"
76 #define close(x) closesocket(x)
80 static int ipc_socket;
82 static int ipc_connection;
83 static int ipc_socket_up;
87 /* IPC initialization function */
89 plugin_ipc_init(void);
92 olsr_netmask_to_string(union hna_netmask *mask);
94 /* Event function to register with the sceduler */
96 pcf_event(int, int, int);
102 ipc_print_neigh_link(struct neighbor_entry *neighbor);
105 ipc_print_tc_link(struct tc_entry *entry, struct topo_dst *dst_entry);
108 ipc_print_net(union olsr_ip_addr *, union olsr_ip_addr *, union hna_netmask *);
111 ipc_send(const char *, int);
114 ipc_send_str(const char *);
117 calc_etx(double, double);
121 *Do initialization here
123 *This function is called by the my_init
124 *function in uolsrd_plugin.c
127 olsrd_plugin_init(void)
129 /* Initial IPC value */
135 /* Register the "ProcessChanges" function */
136 register_pcf(&pcf_event);
145 * destructor - called at unload
148 olsr_plugin_exit(void)
156 ipc_print_neigh_link(struct neighbor_entry *neighbor)
161 char* style = "solid";
162 struct link_entry* link;
163 adr = olsr_ip_to_string(&olsr_cnf->main_addr);
164 sprintf( buf, "\"%s\" -> ", adr );
167 adr = olsr_ip_to_string(&neighbor->neighbor_main_addr);
169 if (neighbor->status == 0) { // non SYM
173 link = get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
175 etx = calc_etx( link->loss_link_quality, link->neigh_link_quality);
179 sprintf( buf, "\"%s\"[label=\"%.2f\", style=%s];\n", adr, etx, style );
182 if (neighbor->is_mpr) {
183 sprintf( buf, "\"%s\"[shape=box];\n", adr );
190 plugin_ipc_init(void)
192 struct sockaddr_in sin;
195 /* Init ipc socket */
196 if ((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
198 olsr_printf(1, "(DOT DRAW)IPC socket %s\n", strerror(errno));
203 if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0)
205 perror("SO_REUSEADDR failed");
209 #if defined __FreeBSD__ && defined SO_NOSIGPIPE
210 if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0)
212 perror("SO_REUSEADDR failed");
217 /* Bind the socket */
219 /* complete the socket structure */
220 memset(&sin, 0, sizeof(sin));
221 sin.sin_family = AF_INET;
222 sin.sin_addr.s_addr = INADDR_ANY;
223 sin.sin_port = htons(ipc_port);
225 /* bind the socket to the port number */
226 if (bind(ipc_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1)
228 olsr_printf(1, "(DOT DRAW)IPC bind %s\n", strerror(errno));
232 /* show that we are willing to listen */
233 if (listen(ipc_socket, 1) == -1)
235 olsr_printf(1, "(DOT DRAW)IPC listen %s\n", strerror(errno));
240 /* Register with olsrd */
241 printf("Adding socket with olsrd\n");
242 add_olsr_socket(ipc_socket, &ipc_action);
251 ipc_action(int fd __attribute__((unused)))
253 struct sockaddr_in pin;
254 socklen_t addrlen = sizeof(struct sockaddr_in);
260 rc = close(ipc_connection);
261 } while (rc == -1 && (errno == EINTR || errno == EAGAIN));
263 olsr_printf(1, "(DOT DRAW) Error on closing previously active TCP connection on fd %d: %s\n", ipc_connection, strerror(errno));
268 if ((ipc_connection = accept(ipc_socket, (struct sockaddr *) &pin, &addrlen)) == -1)
270 olsr_printf(1, "(DOT DRAW)IPC accept: %s\n", strerror(errno));
274 char *addr = inet_ntoa(pin.sin_addr);
275 if(ntohl(pin.sin_addr.s_addr) != ntohl(ipc_accept_ip.s_addr))
277 olsr_printf(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
278 close(ipc_connection);
284 olsr_printf(1, "(DOT DRAW)IPC: Connection from %s\n",addr);
295 pcf_event(int changes_neighborhood,
296 int changes_topology,
301 struct neighbor_entry *neighbor_table_tmp;
302 struct tc_entry *entry;
303 struct topo_dst *dst_entry;
304 struct hna_entry *tmp_hna;
305 struct hna_net *tmp_net;
309 if(changes_neighborhood || changes_topology || changes_hna)
311 /* Print tables to IPC socket */
313 ipc_send_str("digraph topology\n{\n");
316 for(index=0;index<HASHSIZE;index++)
319 for(neighbor_table_tmp = neighbortable[index].next;
320 neighbor_table_tmp != &neighbortable[index];
321 neighbor_table_tmp = neighbor_table_tmp->next)
323 ipc_print_neigh_link( neighbor_table_tmp );
328 for(index=0;index<HASHSIZE;index++)
330 /* For all TC entries */
331 entry = tc_table[index].next;
332 while(entry != &tc_table[index])
334 /* For all destination entries of that TC entry */
335 dst_entry = entry->destinations.next;
336 while(dst_entry != &entry->destinations)
338 ipc_print_tc_link(entry, dst_entry);
339 dst_entry = dst_entry->next;
346 for(index=0;index<HASHSIZE;index++)
348 tmp_hna = hna_set[index].next;
349 /* Check all entrys */
350 while(tmp_hna != &hna_set[index])
352 /* Check all networks */
353 tmp_net = tmp_hna->networks.next;
355 while(tmp_net != &tmp_hna->networks)
357 ipc_print_net(&tmp_hna->A_gateway_addr,
358 &tmp_net->A_network_addr,
359 &tmp_net->A_netmask);
360 tmp_net = tmp_net->next;
363 tmp_hna = tmp_hna->next;
368 ipc_send_str("}\n\n");
381 #define MIN_LINK_QUALITY 0.01
383 calc_etx(double loss, double neigh_loss)
385 if (loss < MIN_LINK_QUALITY || neigh_loss < MIN_LINK_QUALITY)
388 return 1.0 / (loss * neigh_loss);
393 ipc_print_tc_link(struct tc_entry *entry, struct topo_dst *dst_entry)
397 double etx = calc_etx( dst_entry->link_quality, dst_entry->inverse_link_quality );
399 adr = olsr_ip_to_string(&entry->T_last_addr);
400 sprintf( buf, "\"%s\" -> ", adr );
403 adr = olsr_ip_to_string(&dst_entry->T_dest_addr);
404 sprintf( buf, "\"%s\"[label=\"%.2f\"];\n", adr, etx );
410 ipc_print_net(union olsr_ip_addr *gw, union olsr_ip_addr *net, union hna_netmask *mask)
414 adr = olsr_ip_to_string(gw);
417 ipc_send_str("\" -> \"");
418 adr = olsr_ip_to_string(net);
421 adr = olsr_netmask_to_string(mask);
423 ipc_send_str("\"[label=\"HNA\"];\n");
425 adr = olsr_ip_to_string(net);
428 adr = olsr_netmask_to_string(mask);
431 ipc_send_str("[shape=diamond];\n");
435 ipc_send_str(const char *data)
439 return ipc_send(data, strlen(data));
444 ipc_send(const char *data, int size)
449 #if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __MacOSX__
452 #define FLAGS MSG_NOSIGNAL
454 if (send(ipc_connection, data, size, FLAGS) == -1)
456 olsr_printf(1, "(DOT DRAW)IPC connection lost!\n");
457 close(ipc_connection);
466 olsr_netmask_to_string(union hna_netmask *mask)
471 if(olsr_cnf->ip_version == AF_INET)
473 in.s_addr = mask->v4;
479 static char netmask[5];
480 sprintf(netmask, "%d", mask->v6);