2 * The olsr.org Optimized Link-State Routing daemon (olsrd)
4 * (c) by the OLSR project
6 * See our Git repository to find out who worked on this file
7 * and thus is a copyright holder on it.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
21 * * Neither the name of olsr.org, olsrd nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
38 * Visit http://www.olsr.org for more information.
40 * If you find this software useful feel free to make a donation
41 * to the project. For more information see the website or contact
42 * the copyright holders.
47 * Dynamic linked library for the olsr.org olsr daemon
53 #include <wrn/coreip/netinet/in.h>
54 #else /* _WRS_KERNEL */
55 #include <sys/types.h>
56 #include <sys/socket.h>
57 #include <netinet/in.h>
58 #include <arpa/inet.h>
68 #endif /* _WRS_KERNEL */
72 #include "olsr_types.h"
73 #include "neighbor_table.h"
74 #include "two_hop_neighbor_table.h"
80 #include "lq_plugin.h"
81 #include "common/autobuf.h"
83 #include "olsrd_dot_draw.h"
84 #include "olsrd_plugin.h"
87 #define close(x) closesocket(x)
92 static int ipc_socket_up;
93 #define DOT_DRAW_PORT 2004
94 #endif /* _WRS_KERNEL */
96 static int ipc_socket = -1;
98 struct autobuf outbuffer;
99 static int outbuffer_socket = -1;
101 static struct timer_entry *writetimer_entry = NULL;
103 /* IPC initialization function */
104 static int plugin_ipc_init(void);
106 /* Event function to register with the sceduler */
107 static int pcf_event(int, int, int);
109 static void ipc_action(int, void *, unsigned int);
111 static void ipc_print_neigh_link(struct autobuf *abuf, const struct neighbor_entry *neighbor);
113 static void ipc_print_tc_link(struct autobuf *abuf, const struct tc_entry *, const struct tc_edge_entry *);
115 static void ipc_print_net(struct autobuf *abuf, const union olsr_ip_addr *, const union olsr_ip_addr *, uint8_t);
118 *Do initialization here
120 *This function is called by the my_init
121 *function in uolsrd_plugin.c
125 olsrd_dotdraw_init(void)
126 #else /* _WRS_KERNEL */
128 olsrd_plugin_init(void)
129 #endif /* _WRS_KERNEL */
134 /* Register the "ProcessChanges" function */
135 register_pcf(&pcf_event);
141 * destructor - called at unload
145 olsrd_dotdraw_exit(void)
146 #else /* _WRS_KERNEL */
148 olsr_plugin_exit(void)
149 #endif /* _WRS_KERNEL */
151 if (writetimer_entry) {
152 close(outbuffer_socket);
153 abuf_free(&outbuffer);
154 olsr_stop_timer(writetimer_entry);
156 if (ipc_socket != -1) {
162 ipc_print_neigh_link(struct autobuf *abuf, const struct neighbor_entry *neighbor)
164 static const char DASHED[] = "dashed";
165 static const char SOLID[] = "solid";
167 struct ipaddr_str mainaddrstrbuf, strbuf;
168 olsr_linkcost etx = 0.0;
170 const char *adr = olsr_ip_to_string(&mainaddrstrbuf, &olsr_cnf->main_addr);
171 struct link_entry *the_link;
172 struct lqtextbuffer lqbuffer;
174 if (neighbor->status == 0) { /* non SYM */
177 the_link = get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
179 etx = the_link->linkcost;
184 abuf_appendf(abuf, "\"%s\" -> \"%s\"[label=\"%s\", style=%s];\n", adr, olsr_ip_to_string(&strbuf, &neighbor->neighbor_main_addr),
185 get_linkcost_text(etx, false, &lqbuffer), style);
187 if (neighbor->is_mpr) {
188 abuf_appendf(abuf, "\"%s\"[shape=box];\n", adr);
193 plugin_ipc_init(void)
195 struct sockaddr_in sock_in;
198 if (ipc_socket != -1) {
202 /* Init ipc socket */
203 ipc_socket = socket(AF_INET, SOCK_STREAM, 0);
204 if (ipc_socket == -1) {
205 olsr_printf(1, "(DOT DRAW)IPC socket %s\n", strerror(errno));
209 if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
210 perror("SO_REUSEADDR failed");
214 #if (defined __FreeBSD__ || defined __FreeBSD_kernel__) && defined SO_NOSIGPIPE
215 if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0) {
216 perror("SO_REUSEADDR failed");
220 #endif /* (defined __FreeBSD__ || defined __FreeBSD_kernel__) && defined SO_NOSIGPIPE */
222 /* Bind the socket */
224 /* complete the socket structure */
225 memset(&sock_in, 0, sizeof(sock_in));
226 sock_in.sin_family = AF_INET;
227 sock_in.sin_addr.s_addr = ipc_listen_ip.v4.s_addr;
228 sock_in.sin_port = htons(ipc_port);
230 /* bind the socket to the port number */
231 if (bind(ipc_socket, (struct sockaddr *)&sock_in, sizeof(sock_in)) == -1) {
232 olsr_printf(1, "(DOT DRAW)IPC bind %s\n", strerror(errno));
237 /* show that we are willing to listen */
238 if (listen(ipc_socket, 1) == -1) {
239 olsr_printf(1, "(DOT DRAW)IPC listen %s\n", strerror(errno));
244 /* Register with olsrd */
245 add_olsr_socket(ipc_socket, &ipc_action, NULL, NULL, SP_PR_READ);
251 ipc_action(int fd __attribute__ ((unused)), void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
253 struct sockaddr_in pin;
254 socklen_t addrlen = sizeof(struct sockaddr_in);
257 ipc_connection = accept(ipc_socket, (struct sockaddr *)&pin, &addrlen);
258 if (ipc_connection == -1) {
259 olsr_printf(1, "(DOT DRAW)IPC accept: %s\n", strerror(errno));
263 if (outbuffer_socket != -1) {
264 olsr_printf(1, "(DOT DRAW)Only one connection at once allowed.\n");
265 close(ipc_connection);
269 if (!ip4equal(&pin.sin_addr, &ipc_accept_ip.v4) && ipc_accept_ip.v4.s_addr != INADDR_ANY) {
270 olsr_printf(0, "Front end-connection from foreign host (%s) not allowed!\n", inet_ntoa(pin.sin_addr));
271 CLOSE(ipc_connection);
274 #endif /* _WRS_KERNEL */
275 olsr_printf(1, "(DOT DRAW)IPC: Connection from %s\n", inet_ntoa(pin.sin_addr));
277 abuf_init(&outbuffer, AUTOBUFCHUNK);
278 outbuffer_socket = ipc_connection;
284 dotdraw_write_data(void *foo __attribute__ ((unused))) {
290 /* prevent warning on WIN32 */
291 FD_SET((unsigned int)outbuffer_socket, &set);
296 result = select(outbuffer_socket + 1, NULL, &set, NULL, &tv);
301 if (FD_ISSET(outbuffer_socket, &set)) {
302 result = send(outbuffer_socket, outbuffer.buf, outbuffer.len, 0);
304 abuf_pull(&outbuffer, result);
307 /* close this socket and cleanup*/
308 close(outbuffer_socket);
309 abuf_free(&outbuffer);
310 olsr_stop_timer(writetimer_entry);
311 writetimer_entry = NULL;
312 outbuffer_socket = -1;
321 pcf_event(int my_changes_neighborhood, int my_changes_topology, int my_changes_hna)
323 struct neighbor_entry *neighbor_table_tmp;
325 struct tc_edge_entry *tc_edge;
326 struct hna_entry *tmp_hna;
327 struct hna_net *tmp_net;
328 struct ip_prefix_list *hna;
332 if (outbuffer_socket == -1) {
336 if (my_changes_neighborhood || my_changes_topology || my_changes_hna) {
337 /* Print tables to IPC socket */
338 abuf_puts(&outbuffer, "digraph topology\n{\n");
341 OLSR_FOR_ALL_NBR_ENTRIES(neighbor_table_tmp) {
342 ipc_print_neigh_link(&outbuffer, neighbor_table_tmp);
344 OLSR_FOR_ALL_NBR_ENTRIES_END(neighbor_table_tmp);
347 OLSR_FOR_ALL_TC_ENTRIES(tc) {
348 OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
349 if (tc_edge->edge_inv) {
350 ipc_print_tc_link(&outbuffer, tc, tc_edge);
353 OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
355 OLSR_FOR_ALL_TC_ENTRIES_END(tc);
358 OLSR_FOR_ALL_HNA_ENTRIES(tmp_hna) {
360 /* Check all networks */
361 for (tmp_net = tmp_hna->networks.next; tmp_net != &tmp_hna->networks; tmp_net = tmp_net->next) {
362 ipc_print_net(&outbuffer, &tmp_hna->A_gateway_addr,
363 &tmp_net->hna_prefix.prefix, tmp_net->hna_prefix.prefix_len);
366 OLSR_FOR_ALL_HNA_ENTRIES_END(tmp_hna);
368 /* Local HNA entries */
369 for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
370 ipc_print_net(&outbuffer, &olsr_cnf->main_addr, &hna->net.prefix, hna->net.prefix_len);
372 abuf_puts(&outbuffer, "}\n\n");
377 if (writetimer_entry == NULL) {
378 writetimer_entry = olsr_start_timer(100, 0, OLSR_TIMER_PERIODIC, &dotdraw_write_data, NULL, 0);
385 ipc_print_tc_link(struct autobuf *abuf, const struct tc_entry *entry, const struct tc_edge_entry *dst_entry)
387 struct ipaddr_str strbuf1, strbuf2;
388 struct lqtextbuffer lqbuffer;
390 abuf_appendf(abuf, "\"%s\" -> \"%s\"[label=\"%s\"];\n", olsr_ip_to_string(&strbuf1, &entry->addr),
391 olsr_ip_to_string(&strbuf2, &dst_entry->T_dest_addr), get_linkcost_text(dst_entry->cost, false, &lqbuffer));
395 ipc_print_net(struct autobuf *abuf, const union olsr_ip_addr *gw, const union olsr_ip_addr *net, uint8_t prefixlen)
397 struct ipaddr_str gwbuf, netbuf;
399 abuf_appendf(abuf, "\"%s\" -> \"%s/%d\"[label=\"HNA\"];\n", olsr_ip_to_string(&gwbuf, gw), olsr_ip_to_string(&netbuf, net), prefixlen);
401 abuf_appendf(abuf, "\"%s/%d\"[shape=diamond];\n", olsr_ip_to_string(&netbuf, net), prefixlen);
407 * indent-tabs-mode: nil