/*
* The olsr.org Optimized Link-State Routing daemon(olsrd)
* Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
* includes code by Bruno Randolf
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of olsr.org, olsrd nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Visit http://www.olsr.org for more information.
*
* If you find this software useful feel free to make a donation
* to the project. For more information see the website or contact
* the copyright holders.
*
* $Id: olsrd_pgraph.c,v 1.8 2007/09/13 15:31:59 bernd67 Exp $
*/
/*
* Dynamic linked library for the olsr.org olsr daemon
*/
#include "olsrd_pgraph.h"
#include "socket_parser.h"
#include "olsrd_plugin.h"
#include "plugin_util.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#ifdef WIN32
#define close(x) closesocket(x)
#endif
#define PLUGIN_NAME "OLSRD pgraph plugin"
#define PLUGIN_VERSION "0.1"
#define PLUGIN_AUTHOR "Richard Gopaul"
#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
#define PLUGIN_INTERFACE_VERSION 5
static union olsr_ip_addr ipc_accept_ip;
static int ipc_port;
static int ipc_socket;
static int ipc_connection;
void my_init(void) __attribute__((constructor));
void my_fini(void) __attribute__((destructor));
/*
* Defines the version of the plugin interface that is used
* THIS IS NOT THE VERSION OF YOUR PLUGIN!
* Do not alter unless you know what you are doing!
*/
int
olsrd_plugin_interface_version(void)
{
return PLUGIN_INTERFACE_VERSION;
}
/**
*Constructor
*/
void
my_init(void)
{
/* Print plugin info to stdout */
printf("%s\n", MOD_DESC);
/* defaults for parameters */
ipc_port = 2004;
if (olsr_cnf->ip_version == AF_INET) {
ipc_accept_ip.v4 = htonl(INADDR_LOOPBACK);
} else {
ipc_accept_ip.v6 = in6addr_loopback;
}
ipc_socket = -1;
ipc_connection = -1;
}
/**
*Destructor
*/
void
my_fini(void)
{
if(ipc_socket >= 0) {
close(ipc_socket);
ipc_socket = -1;
}
if(ipc_connection >= 0) {
close(ipc_connection);
ipc_connection = -1;
}
}
static const struct olsrd_plugin_parameters plugin_parameters[] = {
{ .name = "port", .set_plugin_parameter = &set_plugin_port, .data = &ipc_port },
{ .name = "accept", .set_plugin_parameter = &set_plugin_ipaddress, .data = &ipc_accept_ip },
};
void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
{
*params = plugin_parameters;
*size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
}
/* Event function to register with the sceduler */
static int pcf_event(int, int, int);
static void ipc_action(int);
#if 0
static struct link_entry *olsr_neighbor_best_link(union olsr_ip_addr *main);
#endif
static void ipc_print_neigh_link(struct neighbor_entry *neighbor);
static void ipc_print_tc_link(struct tc_entry *entry, struct tc_edge_entry *dst_entry);
#if 0
static void ipc_print_net(union olsr_ip_addr *, union olsr_ip_addr *, union hna_netmask *);
#endif
static int ipc_send(const char *, int);
static void ipc_print_neigh_link(struct neighbor_entry *);
static int plugin_ipc_init(void);
static void ipc_print_neigh_link(struct neighbor_entry *neighbor)
{
char buf[256];
int len;
const char* main_adr;
const char* adr;
// double etx=0.0;
// char* style = "solid";
// struct link_entry* link;
main_adr = olsr_ip_to_string(&olsr_cnf->main_addr);
adr = olsr_ip_to_string(&neighbor->neighbor_main_addr);
len = sprintf( buf, "add link %s %s\n", main_adr, adr );
ipc_send(buf, len);
// if (neighbor->status == 0) { // non SYM
// style = "dashed";
// }
// else {
/* find best link to neighbor for the ETX */
//? why cant i just get it one time at fetch_olsrd_data??? (br1)
// if(olsr_plugin_io(GETD__LINK_SET, &link, sizeof(link)) && link)
// {
// link_set = link; // for olsr_neighbor_best_link
// link = olsr_neighbor_best_link(&neighbor->neighbor_main_addr);
// if (link) {
// etx = calc_etx( link->loss_link_quality, link->neigh_link_quality);
// }
// }
// }
//len = sprintf( buf, "\"%s\"[label=\"%.2f\", style=%s];\n", adr, etx, style );
//len = sprintf( buf, "%s\n", adr );
//ipc_send(buf, len);
//if (neighbor->is_mpr) {
// len = sprintf( buf, "\"%s\"[shape=box];\n", adr );
// ipc_send(buf, len);
//}
}
/**
*Do initialization here
*
*This function is called by the my_init
*function in uolsrd_plugin.c
*/
int olsrd_plugin_init(void)
{
/* Initial IPC value */
ipc_socket = -1;
/* Register the "ProcessChanges" function */
register_pcf(&pcf_event);
return 1;
}
static int plugin_ipc_init(void)
{
struct sockaddr_in sin;
olsr_u32_t yes = 1;
/* Init ipc socket */
if ((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
olsr_printf(1, "(DOT DRAW)IPC socket %s\n", strerror(errno));
return 0;
}
else
{
if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0)
{
perror("SO_REUSEADDR failed");
return 0;
}
#ifdef __FreeBSD__
if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0)
{
perror("SO_NOSIGPIPE failed");
return 0;
}
#endif
/* Bind the socket */
/* complete the socket structure */
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(ipc_port);
/* bind the socket to the port number */
if (bind(ipc_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1)
{
olsr_printf(1, "(DOT DRAW)IPC bind %s\n", strerror(errno));
return 0;
}
/* show that we are willing to listen */
if (listen(ipc_socket, 1) == -1)
{
olsr_printf(1, "(DOT DRAW)IPC listen %s\n", strerror(errno));
return 0;
}
/* Register with olsrd */
add_olsr_socket(ipc_socket, &ipc_action);
}
return 1;
}
static void ipc_action(int fd __attribute__((unused)))
{
struct sockaddr_in pin;
socklen_t addrlen;
char *addr;
char buf[256] ;
int len ;
addrlen = sizeof(struct sockaddr_in);
if ((ipc_connection = accept(ipc_socket, (struct sockaddr *) &pin, &addrlen)) == -1)
{
olsr_printf(1, "(DOT DRAW)IPC accept: %s\n", strerror(errno));
exit(1);
}
else
{
addr = inet_ntoa(pin.sin_addr);
/*
if(ntohl(pin.sin_addr.s_addr) != ntohl(ipc_accept_ip.s_addr))
{
olsr_printf(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
close(ipc_connection);
return;
}
else
{
*/
olsr_printf(1, "(DOT DRAW)IPC: Connection from %s\n",addr);
len = sprintf(buf, "add node %s\n", olsr_ip_to_string(&olsr_cnf->main_addr));
ipc_send(buf, len);
pcf_event(1, 1, 1);
// }
}
}
/**
*Scheduled event
*/
static int pcf_event(int changes_neighborhood,
int changes_topology,
int changes_hna __attribute__((unused)))
{
int res;
olsr_u8_t index;
struct neighbor_entry *neighbor_table_tmp;
struct tc_entry *tc;
struct tc_edge_entry *tc_edge;
res = 0;
//if(changes_neighborhood || changes_topology || changes_hna)
if(changes_neighborhood || changes_topology)
{
/* Print tables to IPC socket */
//ipc_send("start ", strlen("start "));
/* Neighbors */
for(index=0;index<HASHSIZE;index++)
{
for(neighbor_table_tmp = neighbortable[index].next;
neighbor_table_tmp != &neighbortable[index];
neighbor_table_tmp = neighbor_table_tmp->next)
{
ipc_print_neigh_link( neighbor_table_tmp );
}
}
/* Topology */
OLSR_FOR_ALL_TC_ENTRIES(tc) {
OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
ipc_print_tc_link(tc, tc_edge);
} OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
} OLSR_FOR_ALL_TC_ENTRIES_END(tc);
ipc_send(" end ", strlen(" end "));
/* HNA entries */
// for(index=0;index<HASHSIZE;index++)
// {
// tmp_hna = hna_set[index].next;
// /* Check all entrys */
// while(tmp_hna != &hna_set[index])
// {
// /* Check all networks */
// tmp_net = tmp_hna->networks.next;
//
// while(tmp_net != &tmp_hna->networks)
// {
// ipc_print_net(&tmp_hna->A_gateway_addr,
// &tmp_net->A_network_addr,
// &tmp_net->A_netmask);
// tmp_net = tmp_net->next;
// }
//
// tmp_hna = tmp_hna->next;
// }
// }
// ipc_send("}\n\n", strlen("}\n\n"));
res = 1;
}
if(ipc_socket == -1)
plugin_ipc_init();
return res;
}
#if 0
#define MIN_LINK_QUALITY 0.01
static double calc_etx(double loss, double neigh_loss)
{
if (loss < MIN_LINK_QUALITY || neigh_loss < MIN_LINK_QUALITY)
return 0.0;
else
return 1.0 / (loss * neigh_loss);
}
#endif
static void ipc_print_tc_link(struct tc_entry *entry, struct tc_edge_entry *dst_entry)
{
char buf[256];
int len;
const char* main_adr;
const char* adr;
// double etx = calc_etx( dst_entry->link_quality, dst_entry->inverse_link_quality );
main_adr = olsr_ip_to_string(&entry->addr);
adr = olsr_ip_to_string(&dst_entry->T_dest_addr);
len = sprintf( buf, "add link %s %s\n", main_adr, adr );
ipc_send(buf, len);
}
#if 0
static void
ipc_print_net(union olsr_ip_addr *gw, union olsr_ip_addr *net, union hna_netmask *mask)
{
const char *adr;
adr = olsr_ip_to_string(gw);
ipc_send("\"", 1);
ipc_send(adr, strlen(adr));
ipc_send("\" -> \"", strlen("\" -> \""));
adr = olsr_ip_to_string(net);
ipc_send(adr, strlen(adr));
ipc_send("/", 1);
adr = olsr_netmask_to_string(mask);
ipc_send(adr, strlen(adr));
ipc_send("\"[label=\"HNA\"];\n", strlen("\"[label=\"HNA\"];\n"));
ipc_send("\"", 1);
adr = olsr_ip_to_string(net);
ipc_send(adr, strlen(adr));
ipc_send("/", 1);
adr = olsr_netmask_to_string(mask);
ipc_send(adr, strlen(adr));
ipc_send("\"", 1);
ipc_send("[shape=diamond];\n", strlen("[shape=diamond];\n"));
}
#endif
static int ipc_send(const char *data, int size)
{
if(ipc_connection == -1)
return 0;
#if defined __FreeBSD__ || defined __MacOSX__
#define FLAG 0
#else
#define FLAG MSG_NOSIGNAL
#endif
if (send(ipc_connection, data, size, FLAG) < 0)
{
olsr_printf(1, "(DOT DRAW)IPC connection lost!\n");
close(ipc_connection);
ipc_connection = -1;
return -1;
}
return 1;
}
#if 0
static struct link_entry *olsr_neighbor_best_link(union olsr_ip_addr *main)
{
struct link_entry *walker;
double best = 0.0;
double curr;
struct link_entry *res = NULL;
// loop through all links
for (walker = link_set; walker != NULL; walker = walker->next)
{
// check whether it's a link to the requested neighbor and
// whether the link's quality is better than what we have
if(COMP_IP(main, &walker->neighbor->neighbor_main_addr))
{
curr = walker->loss_link_quality * walker->neigh_link_quality;
if (curr >= best)
{
best = curr;
res = walker;
}
}
}
return res;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1