00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #ifdef _WRS_KERNEL
00048 #include <vxWorks.h>
00049 #include <sockLib.h>
00050 #include <wrn/coreip/netinet/in.h>
00051 #else
00052 #include <unistd.h>
00053 #include <errno.h>
00054 #include <stdarg.h>
00055 #endif
00056 #include <stdio.h>
00057
00058 #include "olsr.h"
00059 #include "ipcalc.h"
00060 #include "neighbor_table.h"
00061 #include "tc_set.h"
00062 #include "hna_set.h"
00063 #include "link_set.h"
00064 #include "olsr_ip_prefix_list.h"
00065 #include "olsr_logging.h"
00066 #include "os_net.h"
00067 #include "plugin_util.h"
00068
00069 #define PLUGIN_DESCR "OLSRD dot draw plugin"
00070 #define PLUGIN_AUTHOR "Andreas Tonnesen"
00071
00072 #ifdef _WRS_KERNEL
00073 static int ipc_open;
00074 static int ipc_socket_up;
00075 #define DOT_DRAW_PORT 2004
00076 #endif
00077
00078 static int dotdraw_init(void);
00079 static int dotdraw_enable(void);
00080 static int dotdraw_exit(void);
00081
00082 static int ipc_socket;
00083
00084 static union olsr_ip_addr ipc_accept_ip;
00085 static int ipc_port;
00086
00087
00088 static const struct olsrd_plugin_parameters plugin_parameters[] = {
00089 {.name = "port",.set_plugin_parameter = &set_plugin_port,.data = &ipc_port},
00090 {.name = "accept",.set_plugin_parameter = &set_plugin_ipaddress,.data = &ipc_accept_ip},
00091 };
00092
00093 OLSR_PLUGIN6(plugin_parameters) {
00094 .descr = PLUGIN_DESCR,
00095 .author = PLUGIN_AUTHOR,
00096 .init = dotdraw_init,
00097 .enable = dotdraw_enable,
00098 .exit = dotdraw_exit,
00099 .deactivate = false
00100 };
00101
00102
00103 static int
00104 pcf_event(int, int, int, int);
00105
00106 static void
00107 ipc_action(int, void *, unsigned int);
00108
00109 static void
00110 ipc_print_neigh_link(int, const struct nbr_entry *neighbor);
00111
00112 static void
00113 ipc_print_tc_link(int, const struct tc_entry *, const struct tc_edge_entry *);
00114
00115 static void
00116 ipc_print_net(int, const union olsr_ip_addr *, const struct olsr_ip_prefix *);
00117
00118 static void
00119 ipc_send(int, const char *, int);
00120
00121 static void
00122 ipc_send_fmt(int, const char *format, ...) __attribute__ ((format(printf, 2, 3)));
00123
00124 #define ipc_send_str(fd, data) ipc_send((fd), (data), strlen(data))
00125
00126
00127 static int
00128 dotdraw_init(void)
00129 {
00130
00131 ipc_port = 2004;
00132 ipc_accept_ip.v4.s_addr = htonl(INADDR_LOOPBACK);
00133
00134 ipc_socket = -1;
00135 return 0;
00136 }
00137
00141 static int
00142 dotdraw_exit(void)
00143 {
00144 if (ipc_socket != -1) {
00145 os_close(ipc_socket);
00146 ipc_socket = -1;
00147 }
00148 return 0;
00149 }
00150
00151
00152 static void
00153 ipc_print_neigh_link(int ipc_connection, const struct nbr_entry *neighbor)
00154 {
00155 struct ipaddr_str mainaddrstrbuf, strbuf;
00156 olsr_linkcost etx = 0.0;
00157 const char *style;
00158 const char *adr = olsr_ip_to_string(&mainaddrstrbuf, &olsr_cnf->router_id);
00159 char lqbuffer[LQTEXT_MAXLENGTH];
00160
00161 if (neighbor->is_sym == 0) {
00162 style = "dashed";
00163 } else {
00164 const struct link_entry *lnk = get_best_link_to_neighbor_ip(&neighbor->nbr_addr);
00165 if (lnk) {
00166 etx = lnk->linkcost;
00167 }
00168 style = "solid";
00169 }
00170
00171 ipc_send_fmt(ipc_connection,
00172 "\"%s\" -> \"%s\"[label=\"%s\", style=%s];\n",
00173 adr, olsr_ip_to_string(&strbuf, &neighbor->nbr_addr),
00174 olsr_get_linkcost_text(etx, false, lqbuffer, sizeof(lqbuffer)), style);
00175
00176 if (neighbor->is_mpr) {
00177 ipc_send_fmt(ipc_connection, "\"%s\"[shape=box];\n", adr);
00178 }
00179 }
00180
00181 static int
00182 dotdraw_enable(void) {
00183 struct sockaddr_in addr;
00184 uint32_t yes = 1;
00185
00186 if (ipc_socket != -1) {
00187 os_close(ipc_socket);
00188 }
00189
00190
00191 ipc_socket = socket(AF_INET, SOCK_STREAM, 0);
00192 if (ipc_socket == -1) {
00193 OLSR_WARN(LOG_PLUGINS, "(DOT DRAW)IPC socket %s\n", strerror(errno));
00194 return 1;
00195 }
00196
00197 if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
00198 OLSR_WARN(LOG_PLUGINS, "SO_REUSEADDR failed %s\n", strerror(errno));
00199 os_close(ipc_socket);
00200 return 1;
00201 }
00202 #if defined __FreeBSD__ && defined SO_NOSIGPIPE
00203 if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0) {
00204 OLSR_WARN(LOG_PLUGINS, "SO_REUSEADDR failed %s\n", strerror(errno));
00205 os_close(ipc_socket);
00206 return 1;
00207 }
00208 #endif
00209
00210
00211
00212
00213 memset(&addr, 0, sizeof(addr));
00214 addr.sin_family = AF_INET;
00215 addr.sin_addr.s_addr = INADDR_ANY;
00216 addr.sin_port = htons(ipc_port);
00217
00218
00219 if (bind(ipc_socket, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
00220 OLSR_WARN(LOG_PLUGINS, "(DOT DRAW)IPC bind %s\n", strerror(errno));
00221 os_close(ipc_socket);
00222 return 1;
00223 }
00224
00225
00226 if (listen(ipc_socket, 1) == -1) {
00227 OLSR_WARN(LOG_PLUGINS, "(DOT DRAW)IPC listen %s\n", strerror(errno));
00228 os_close(ipc_socket);
00229 return 1;
00230 }
00231
00232
00233 if (NULL == olsr_socket_add(ipc_socket, &ipc_action, NULL, OLSR_SOCKET_READ)) {
00234 OLSR_WARN(LOG_PLUGINS, "(DOT DRAW)Could not register socket with scheduler\n");
00235 os_close(ipc_socket);
00236 return 1;
00237 }
00238
00239 return 0;
00240 }
00241
00242
00243 static void
00244 ipc_action(int fd __attribute__ ((unused)), void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
00245 {
00246 struct sockaddr_in pin;
00247 socklen_t addrlen = sizeof(struct sockaddr_in);
00248 int ipc_connection = accept(ipc_socket, (struct sockaddr *)&pin, &addrlen);
00249 if (ipc_connection == -1) {
00250 OLSR_WARN(LOG_PLUGINS, "(DOT DRAW)IPC accept: %s\n", strerror(errno));
00251 return;
00252 }
00253 #ifndef _WRS_KERNEL
00254 if (ip4cmp(&pin.sin_addr, &ipc_accept_ip.v4) != 0) {
00255 OLSR_WARN(LOG_PLUGINS, "Front end-connection from foreign host (%s) not allowed!\n", inet_ntoa(pin.sin_addr));
00256 os_close(ipc_connection);
00257 return;
00258 }
00259 #endif
00260 OLSR_DEBUG(LOG_PLUGINS, "(DOT DRAW)IPC: Connection from %s\n", inet_ntoa(pin.sin_addr));
00261 pcf_event(ipc_connection, 1, 1, 1);
00262 os_close(ipc_connection);
00263 }
00264
00265
00269 static int
00270 pcf_event(int ipc_connection, int chgs_neighborhood, int chgs_topology, int chgs_hna)
00271 {
00272 int res = 0;
00273
00274 if (chgs_neighborhood || chgs_topology || chgs_hna) {
00275 struct nbr_entry *neighbor_table_tmp, *nbr_iterator;
00276 struct tc_entry *tc, *tc_iterator;
00277 struct hna_net *hna, *hna_iterator;
00278 struct ip_prefix_entry *prefix, *prefix_iterator;
00279
00280
00281 ipc_send_str(ipc_connection, "digraph topology\n{\n");
00282
00283
00284 OLSR_FOR_ALL_NBR_ENTRIES(neighbor_table_tmp, nbr_iterator) {
00285 ipc_print_neigh_link(ipc_connection, neighbor_table_tmp);
00286 }
00287
00288
00289 OLSR_FOR_ALL_TC_ENTRIES(tc, tc_iterator) {
00290 struct tc_edge_entry *tc_edge, *edge_iterator;
00291 OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge, edge_iterator) {
00292 if (tc_edge->edge_inv) {
00293 ipc_print_tc_link(ipc_connection, tc, tc_edge);
00294 }
00295 }
00296 }
00297
00298
00299 OLSR_FOR_ALL_TC_ENTRIES(tc, tc_iterator) {
00300
00301 OLSR_FOR_ALL_TC_HNA_ENTRIES(tc, hna, hna_iterator) {
00302 ipc_print_net(ipc_connection, &tc->addr, &hna->hna_prefix);
00303 }
00304 }
00305
00306
00307 OLSR_FOR_ALL_IPPREFIX_ENTRIES(&olsr_cnf->hna_entries, prefix, prefix_iterator) {
00308 ipc_print_net(ipc_connection, &olsr_cnf->router_id, &prefix->net);
00309 }
00310 ipc_send_str(ipc_connection, "}\n\n");
00311
00312 res = 1;
00313 }
00314
00315 if (ipc_socket == -1) {
00316 dotdraw_enable();
00317 }
00318 return res;
00319 }
00320
00321 static void
00322 ipc_print_tc_link(int ipc_connection, const struct tc_entry *entry, const struct tc_edge_entry *dst_entry)
00323 {
00324 struct ipaddr_str strbuf1, strbuf2;
00325 char lqbuffer[LQTEXT_MAXLENGTH];
00326
00327 ipc_send_fmt(ipc_connection,
00328 "\"%s\" -> \"%s\"[label=\"%s\"];\n",
00329 olsr_ip_to_string(&strbuf1, &entry->addr),
00330 olsr_ip_to_string(&strbuf2, &dst_entry->T_dest_addr),
00331 olsr_get_linkcost_text(dst_entry->cost, false, lqbuffer, sizeof(lqbuffer)));
00332 }
00333
00334
00335 static void
00336 ipc_print_net(int ipc_connection, const union olsr_ip_addr *gw, const struct olsr_ip_prefix *net)
00337 {
00338 struct ipaddr_str gwbuf;
00339 struct ipprefix_str netbuf;
00340
00341 ipc_send_fmt(ipc_connection,
00342 "\"%s\" -> \"%s\"[label=\"HNA\"];\n", olsr_ip_to_string(&gwbuf, gw), olsr_ip_prefix_to_string(&netbuf, net));
00343 ipc_send_fmt(ipc_connection, "\"%s\"[shape=diamond];\n", netbuf.buf);
00344 }
00345
00346 static void
00347 ipc_send(int ipc_connection, const char *data, int size)
00348 {
00349 if (ipc_connection != -1) {
00350 #if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __MacOSX__ || \
00351 defined _WRS_KERNEL
00352 #define FLAGS 0
00353 #else
00354 #define FLAGS MSG_NOSIGNAL
00355 #endif
00356 if (send(ipc_connection, data, size, FLAGS) == -1) {
00357 OLSR_WARN(LOG_PLUGINS, "(DOT DRAW)IPC connection lost!\n");
00358 os_close(ipc_connection);
00359 }
00360 }
00361 }
00362
00363 static void
00364 ipc_send_fmt(int ipc_connection, const char *format, ...)
00365 {
00366 if (ipc_connection != -1) {
00367 char buf[4096];
00368 int len;
00369 va_list arg;
00370 va_start(arg, format);
00371 len = vsnprintf(buf, sizeof(buf), format, arg);
00372 va_end(arg);
00373 ipc_send(ipc_connection, buf, len);
00374 }
00375 }
00376
00377
00378
00379
00380
00381
00382