pgraph: remove PLUGIN_AUTHOR, Git shows who worked on it
[olsrd.git] / lib / pgraph / src / olsrd_pgraph.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
5  *                     includes code by Bruno Randolf
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  *   notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  *   notice, this list of conditions and the following disclaimer in
16  *   the documentation and/or other materials provided with the
17  *   distribution.
18  * * Neither the name of olsr.org, olsrd nor the names of its
19  *   contributors may be used to endorse or promote products derived
20  *   from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Visit http://www.olsr.org for more information.
36  *
37  * If you find this software useful feel free to make a donation
38  * to the project. For more information see the website or contact
39  * the copyright holders.
40  *
41  */
42
43 /*
44  * Dynamic linked library for the olsr.org olsr daemon
45  */
46
47 #include "olsrd_pgraph.h"
48 #include "ipcalc.h"
49 #include "olsrd_plugin.h"
50 #include "plugin_util.h"
51 #include "net_olsr.h"
52
53 #include <stdio.h>
54 #include <string.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <errno.h>
58 #include <signal.h>
59 #ifdef _WIN32
60 #define close(x) closesocket(x)
61 #endif /* _WIN32 */
62
63 #define PLUGIN_NAME    "OLSRD pgraph plugin"
64 #define PLUGIN_VERSION "0.1"
65 #define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION
66 #define PLUGIN_INTERFACE_VERSION 5
67
68 static union olsr_ip_addr ipc_accept_ip;
69 static int ipc_port;
70
71 static int ipc_socket;
72 static int ipc_connection;
73
74 void my_init(void) __attribute__ ((constructor));
75
76 void my_fini(void) __attribute__ ((destructor));
77
78 /*
79  * Defines the version of the plugin interface that is used
80  * THIS IS NOT THE VERSION OF YOUR PLUGIN!
81  * Do not alter unless you know what you are doing!
82  */
83 int
84 olsrd_plugin_interface_version(void)
85 {
86   return PLUGIN_INTERFACE_VERSION;
87 }
88
89 /**
90  *Constructor
91  */
92 void
93 my_init(void)
94 {
95   /* Print plugin info to stdout */
96   printf("%s\n", MOD_DESC);
97
98   /* defaults for parameters */
99   ipc_port = 2004;
100   if (olsr_cnf->ip_version == AF_INET) {
101     ipc_accept_ip.v4.s_addr = htonl(INADDR_LOOPBACK);
102   } else {
103     ipc_accept_ip.v6 = in6addr_loopback;
104   }
105   ipc_socket = -1;
106   ipc_connection = -1;
107 }
108
109 /**
110  *Destructor
111  */
112 void
113 my_fini(void)
114 {
115   if (ipc_socket >= 0) {
116     close(ipc_socket);
117     ipc_socket = -1;
118   }
119   if (ipc_connection >= 0) {
120     close(ipc_connection);
121     ipc_connection = -1;
122   }
123
124 }
125
126 static const struct olsrd_plugin_parameters plugin_parameters[] = {
127   {.name = "port",.set_plugin_parameter = &set_plugin_port,.data = &ipc_port},
128   {.name = "accept",.set_plugin_parameter = &set_plugin_ipaddress,.data = &ipc_accept_ip},
129 };
130
131 void
132 olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
133 {
134   *params = plugin_parameters;
135   *size = sizeof(plugin_parameters) / sizeof(*plugin_parameters);
136 }
137
138 /* Event function to register with the sceduler */
139 static int pcf_event(int, int, int);
140
141 static void ipc_action(int, void *, unsigned int);
142
143 static void ipc_print_neigh_link(struct neighbor_entry *neighbor);
144
145 static void ipc_print_tc_link(struct tc_entry *entry, struct tc_edge_entry *dst_entry);
146
147 static int ipc_send(const char *, int);
148
149 static void ipc_print_neigh_link(struct neighbor_entry *);
150
151 static int plugin_ipc_init(void);
152
153 static void
154 ipc_print_neigh_link(struct neighbor_entry *neighbor)
155 {
156   char buf[256];
157   int len;
158   struct ipaddr_str main_adr, adr;
159 //  double etx=0.0;
160 //  char* style = "solid";
161 //  struct link_entry* link;
162
163   len =
164     sprintf(buf, "add link %s %s\n", olsr_ip_to_string(&main_adr, &olsr_cnf->main_addr),
165             olsr_ip_to_string(&adr, &neighbor->neighbor_main_addr));
166   ipc_send(buf, len);
167
168 //  if (neighbor->status == 0) { // non SYM
169 //      style = "dashed";
170 //  }
171 //  else {
172   /* find best link to neighbor for the ETX */
173   //? why cant i just get it one time at fetch_olsrd_data??? (br1)
174 //    if(olsr_plugin_io(GETD__LINK_SET, &link, sizeof(link)) && link)
175 //    {
176 //      link_set = link; // for olsr_neighbor_best_link
177 //      link = olsr_neighbor_best_link(&neighbor->neighbor_main_addr);
178 //      if (link) {
179 //        etx = olsr_calc_etx(link);
180 //      }
181 //    }
182 //  }
183
184   //len = sprintf( buf, "\"%s\"[label=\"%.2f\", style=%s];\n", adr, etx, style );
185   //len = sprintf( buf, "%s\n", adr );
186   //ipc_send(buf, len);
187
188   //if (neighbor->is_mpr) {
189   //   len = sprintf( buf, "\"%s\"[shape=box];\n", adr );
190   //   ipc_send(buf, len);
191   //}
192 }
193
194 /**
195  *Do initialization here
196  *
197  *This function is called by the my_init
198  *function in uolsrd_plugin.c
199  */
200 int
201 olsrd_plugin_init(void)
202 {
203
204   /* Initial IPC value */
205   ipc_socket = -1;
206
207   /* Register the "ProcessChanges" function */
208   register_pcf(&pcf_event);
209
210   return 1;
211 }
212
213 static int
214 plugin_ipc_init(void)
215 {
216   struct sockaddr_in sin;
217   uint32_t yes = 1;
218
219   /* Init ipc socket */
220   if ((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
221     olsr_printf(1, "(DOT DRAW)IPC socket %s\n", strerror(errno));
222     return 0;
223   } else {
224     if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
225       perror("SO_REUSEADDR failed");
226       return 0;
227     }
228 #if defined __FreeBSD__
229     if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0) {
230       perror("SO_NOSIGPIPE failed");
231       return 0;
232     }
233 #endif /* defined __FreeBSD__ */
234
235     /* Bind the socket */
236
237     /* complete the socket structure */
238     memset(&sin, 0, sizeof(sin));
239     sin.sin_family = AF_INET;
240     sin.sin_addr.s_addr = INADDR_ANY;
241     sin.sin_port = htons(ipc_port);
242
243     /* bind the socket to the port number */
244     if (bind(ipc_socket, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
245       olsr_printf(1, "(DOT DRAW)IPC bind %s\n", strerror(errno));
246       return 0;
247     }
248
249     /* show that we are willing to listen */
250     if (listen(ipc_socket, 1) == -1) {
251       olsr_printf(1, "(DOT DRAW)IPC listen %s\n", strerror(errno));
252       return 0;
253     }
254
255     /* Register with olsrd */
256     add_olsr_socket(ipc_socket, &ipc_action, NULL, NULL, SP_PR_READ);
257   }
258
259   return 1;
260 }
261
262 static void
263 ipc_action(int fd __attribute__ ((unused)), void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
264 {
265   struct sockaddr_in pin;
266   socklen_t addrlen;
267   char *addr;
268   char buf[256];
269   int len;
270
271   addrlen = sizeof(struct sockaddr_in);
272
273   if ((ipc_connection = accept(ipc_socket, (struct sockaddr *)&pin, &addrlen)) == -1) {
274     char buf2[1024];
275     snprintf(buf2, sizeof(buf2), "(DOT DRAW)IPC accept error: %s", strerror(errno));
276     olsr_exit(buf2, EXIT_FAILURE);
277   } else {
278     struct ipaddr_str main_addr;
279     addr = inet_ntoa(pin.sin_addr);
280
281 /*
282       if(ntohl(pin.sin_addr.s_addr) != ntohl(ipc_accept_ip.s_addr))
283         {
284           olsr_printf(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
285           close(ipc_connection);
286           return;
287         }
288       else
289         {
290 */
291     olsr_printf(1, "(DOT DRAW)IPC: Connection from %s\n", addr);
292     len = sprintf(buf, "add node %s\n", olsr_ip_to_string(&main_addr, &olsr_cnf->main_addr));
293     ipc_send(buf, len);
294     pcf_event(1, 1, 1);
295 //      }
296   }
297
298 }
299
300 /**
301  *Scheduled event
302  */
303 static int
304 pcf_event(int my_changes_neighborhood, int my_changes_topology, int my_changes_hna __attribute__ ((unused)))
305 {
306   int res;
307   struct neighbor_entry *neighbor_table_tmp;
308   struct tc_entry *tc;
309   struct tc_edge_entry *tc_edge;
310
311   res = 0;
312
313   if (my_changes_neighborhood || my_changes_topology) {
314     /* Print tables to IPC socket */
315
316     //ipc_send("start ", strlen("start "));
317
318     /* Neighbors */
319     OLSR_FOR_ALL_NBR_ENTRIES(neighbor_table_tmp) {
320       ipc_print_neigh_link(neighbor_table_tmp);
321     }
322     OLSR_FOR_ALL_NBR_ENTRIES_END(neighbor_table_tmp);
323
324     /* Topology */
325     OLSR_FOR_ALL_TC_ENTRIES(tc) {
326       OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
327         ipc_print_tc_link(tc, tc_edge);
328       }
329       OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
330     }
331     OLSR_FOR_ALL_TC_ENTRIES_END(tc);
332
333     ipc_send(" end ", strlen(" end "));
334
335     /* HNA entries */
336 //      for(index=0;index<HASHSIZE;index++)
337 //      {
338 //        tmp_hna = hna_set[index].next;
339 //        /* Check all entrys */
340 //        while(tmp_hna != &hna_set[index])
341 //          {
342 //            /* Check all networks */
343 //            tmp_net = tmp_hna->networks.next;
344 //
345 //            while(tmp_net != &tmp_hna->networks)
346 //              {
347 //                ipc_print_net(&tmp_hna->A_gateway_addr,
348 //                              &tmp_net->A_network_addr,
349 //                              &tmp_net->A_netmask);
350 //                tmp_net = tmp_net->next;
351 //              }
352 //
353 //            tmp_hna = tmp_hna->next;
354 //          }
355 //      }
356
357 //      ipc_send("}\n\n", strlen("}\n\n"));
358
359     res = 1;
360   }
361
362   if (ipc_socket == -1) {
363     plugin_ipc_init();
364   }
365
366   return res;
367 }
368
369 static void
370 ipc_print_tc_link(struct tc_entry *entry, struct tc_edge_entry *dst_entry)
371 {
372   char buf[256];
373   int len;
374   struct ipaddr_str main_adr, adr;
375 //  double etx = olsr_calc_tc_etx(dst_entry);
376
377   len =
378     sprintf(buf, "add link %s %s\n", olsr_ip_to_string(&main_adr, &entry->addr), olsr_ip_to_string(&adr, &dst_entry->T_dest_addr));
379   ipc_send(buf, len);
380 }
381
382 static int
383 ipc_send(const char *data, int size)
384 {
385   if (ipc_connection == -1)
386     return 0;
387
388 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __OpenBSD__
389 #define FLAG 0
390 #else /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __OpenBSD__ */
391 #define FLAG MSG_NOSIGNAL
392 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __OpenBSD__ */
393   if (send(ipc_connection, data, size, FLAG) < 0) {
394     olsr_printf(1, "(DOT DRAW)IPC connection lost!\n");
395     close(ipc_connection);
396     ipc_connection = -1;
397     return -1;
398   }
399
400   return 1;
401 }
402
403 /*
404  * Local Variables:
405  * c-basic-offset: 2
406  * indent-tabs-mode: nil
407  * End:
408  */