/*
* The olsr.org Optimized Link-State Routing daemon (olsrd)
*
* Copyright (c) 2004, Thomas Lopatic (thomas@olsr.org)
* 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: plugin.c,v 1.13 2007/09/17 22:24:22 bernd67 Exp $
*/
#include <string.h>
#include <time.h> // clock_t required by olsrd includes
#include "link.h"
#include "plugin.h"
#include "lib.h"
#include "os_unix.h"
#include "http.h"
#include "glua.h"
#include "glua_ext.h"
#include "olsrd_plugin.h"
#include <defs.h>
#include <olsr.h>
#include <scheduler.h>
#include <parser.h>
#include <link_set.h>
#include <neighbor_table.h>
#include <two_hop_neighbor_table.h>
#include <mid_set.h>
#include <tc_set.h>
#include <hna_set.h>
#include <routing_table.h>
#include <olsr_protocol.h>
#include <lq_route.h>
#include <mpr_selector_set.h>
#include <duplicate_set.h>
#define PLUGIN_INTERFACE_VERSION 5
#define MESSAGE_TYPE 129
int olsrd_plugin_interface_version(void);
int olsrd_plugin_register_param(char *name, char *value);
int olsrd_plugin_init(void);
static int ipAddrLen;
static union olsr_ip_addr *mainAddr;
static struct interface *intTab = NULL;
static struct neighbor_entry *neighTab = NULL;
static struct mid_entry *midTab = NULL;
static struct hna_entry *hnaTab = NULL;
static struct olsrd_config *config = NULL;
static int iterIndex;
#if 0
/* not used */
static struct interface *iterIntTab = NULL;
static struct mid_entry *iterMidTab = NULL;
static struct hna_entry *iterHnaTab = NULL;
#endif
static struct link_entry *iterLinkTab = NULL;
static struct neighbor_entry *iterNeighTab = NULL;
static struct tc_entry *iterTcTab = NULL;
static struct rt_entry *iterRouteTab = NULL;
static void __attribute__((constructor)) banner(void)
{
printf("Tiny Application Server 0.1 by olsr.org\n");
}
static double lqToEtx(double lq, double nlq)
{
if (lq < MIN_LINK_QUALITY || nlq < MIN_LINK_QUALITY)
return 0.0;
else
return 1.0 / (lq * nlq);
}
int iterLinkTabNext(char *buff, int len)
{
double etx;
if (iterLinkTab == NULL)
return -1;
etx = lqToEtx(iterLinkTab->loss_link_quality,
iterLinkTab->neigh_link_quality);
snprintf(buff, len, "local~%s~remote~%s~main~%s~hysteresis~%f~lq~%f~nlq~%f~etx~%f~",
rawIpAddrToString(&iterLinkTab->local_iface_addr, ipAddrLen),
rawIpAddrToString(&iterLinkTab->neighbor_iface_addr, ipAddrLen),
rawIpAddrToString(&iterLinkTab->neighbor->neighbor_main_addr, ipAddrLen),
iterLinkTab->L_link_quality, iterLinkTab->loss_link_quality,
iterLinkTab->neigh_link_quality, etx);
iterLinkTab = iterLinkTab->next;
return 0;
}
void iterLinkTabInit(void)
{
iterLinkTab = get_link_set();
}
int iterNeighTabNext(char *buff, int len)
{
int res;
int i;
struct neighbor_2_list_entry *neigh2;
if (iterNeighTab == NULL)
return -1;
res = snprintf(buff, len,
"main~%s~symmetric~%s~mpr~%s~mprs~%s~willingness~%d~[~neighbors2~",
rawIpAddrToString(&iterNeighTab->neighbor_main_addr, ipAddrLen),
iterNeighTab->status == SYM ? "true" : "false",
iterNeighTab->is_mpr != 0 ? "true" : "false",
olsr_lookup_mprs_set(&iterNeighTab->neighbor_main_addr) != NULL ?
"true" : "false",
iterNeighTab->willingness);
i = 0;
len -= res;
buff += res;
len -= 2;
for (neigh2 = iterNeighTab->neighbor_2_list.next;
neigh2 != &iterNeighTab->neighbor_2_list;
neigh2 = neigh2->next)
{
res = snprintf(buff, len, "%d~%s~", i,
rawIpAddrToString(&neigh2->neighbor_2->neighbor_2_addr,
ipAddrLen));
if (res < len)
buff += res;
len -= res;
if (len <= 0)
break;
i++;
}
strcpy(buff, "]~");
iterNeighTab = iterNeighTab->next;
if (iterNeighTab == &neighTab[iterIndex])
{
iterNeighTab = NULL;
while (++iterIndex < HASHSIZE)
if (neighTab[iterIndex].next != &neighTab[iterIndex])
{
iterNeighTab = neighTab[iterIndex].next;
break;
}
}
return 0;
}
void iterNeighTabInit(void)
{
iterNeighTab = NULL;
if (neighTab == NULL)
return;
for (iterIndex = 0; iterIndex < HASHSIZE; iterIndex++)
if (neighTab[iterIndex].next != &neighTab[iterIndex])
{
iterNeighTab = neighTab[iterIndex].next;
break;
}
}
int iterRouteTabNext(char *buff, int len)
{
struct avl_node *rt_tree_node;
if (iterRouteTab == NULL)
return -1;
snprintf(buff, len, "destination~%s~gateway~%s~interface~%s~metric~%d~",
rawIpAddrToString(&iterRouteTab->rt_dst.prefix, ipAddrLen),
rawIpAddrToString(&iterRouteTab->rt_best->rtp_nexthop.gateway, ipAddrLen),
if_ifwithindex_name(iterRouteTab->rt_best->rtp_nexthop.iif_index),
iterRouteTab->rt_best->rtp_metric.hops);
rt_tree_node = avl_walk_next(&iterRouteTab->rt_tree_node);
if (rt_tree_node) {
iterRouteTab = rt_tree_node->data;
} else {
iterRouteTab = NULL;
}
return 0;
}
void iterRouteTabInit(void)
{
struct avl_node *node;
avl_init(&routingtree, avl_comp_prefix_default);
routingtree_version = 0;
node = avl_walk_first(&routingtree);
iterRouteTab = node ? node->data : NULL;
}
int iterTcTabNext(char *buff, int len)
{
int res;
int i;
struct tc_edge_entry *tc_edge;
if (iterTcTab == NULL)
return -1;
res = snprintf(buff, len,
"main~%s~[~destinations~",
rawIpAddrToString(&iterTcTab->addr, ipAddrLen));
len -= res;
buff += res;
len -= 2;
i = 0;
OLSR_FOR_ALL_TC_EDGE_ENTRIES(iterTcTab, tc_edge) {
res = snprintf(buff, len, "[~%d~address~%s~etx~%f~]~", i,
rawIpAddrToString(&tc_edge->T_dest_addr, ipAddrLen),
lqToEtx(tc_edge->link_quality, tc_edge->inverse_link_quality));
if (res < len)
buff += res;
len -= res;
if (len <= 0)
break;
i++;
} OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(iterTcTab, tc_edge);
strcpy(buff, "]~");
iterTcTab = olsr_getnext_tc_entry(iterTcTab);
return 0;
}
void iterTcTabInit(void)
{
struct avl_node *node;
avl_init(&tc_tree, avl_comp_prefix_default);
node = avl_walk_first(&tc_tree);
iterTcTab = node ? node->data : NULL;
}
static void parserFunc(union olsr_message *msg, struct interface *inInt,
union olsr_ip_addr *neighIntAddr)
{
char *mess = (char *)msg;
union olsr_ip_addr *orig = (union olsr_ip_addr *)(mess + 4);
unsigned short seqNo = (mess[ipAddrLen + 6] << 8) | mess[ipAddrLen + 7];
int len = (mess[2] << 8) | mess[3];
char *service, *string;
int i;
if (memcmp(orig, mainAddr, ipAddrLen) == 0)
return;
if (check_neighbor_link(neighIntAddr) != SYM_LINK)
{
error("TAS message not from symmetric neighbour\n");
return;
}
if (len < ipAddrLen + 8 + 2)
{
error("short TAS message received (%d bytes)\n", len);
return;
}
if (olsr_check_dup_table_proc(orig, seqNo) != 0)
{
len -= ipAddrLen + 8;
service = mess + ipAddrLen + 8;
for (i = 0; i < len && service[i] != 0; i++);
if (i++ == len)
{
error("TAS message has unterminated service string\n");
return;
}
if (i == len)
{
error("TAS message lacks payload string\n");
return;
}
string = service + i;
len -= i;
for (i = 0; i < len && string[i] != 0; i++);
if (i == len)
{
error("TAS message has unterminated payload string\n");
return;
}
httpAddTasMessage(service, string, rawIpAddrToString(orig, ipAddrLen));
}
olsr_forward_message(msg, orig, seqNo, inInt, neighIntAddr);
}
void sendMessage(const char *service, const char *string)
{
unsigned char *mess, *walker;
int len, pad;
unsigned short seqNo;
struct interface *inter;
pad = len = ipAddrLen + 8 + strlen(service) + 1 + strlen(string) + 1;
len = 1 + ((len - 1) | 3);
pad = len - pad;
walker = mess = allocMem(len);
seqNo = get_msg_seqno();
*walker++ = MESSAGE_TYPE;
*walker++ = 0;
*walker++ = (unsigned char)(len >> 8);
*walker++ = (unsigned char)len;
memcpy(walker, mainAddr, ipAddrLen);
walker += ipAddrLen;
*walker++ = 255;
*walker++ = 0;
*walker++ = (unsigned char)(seqNo >> 8);
*walker++ = (unsigned char)seqNo;
while (*service != 0)
*walker++ = *service++;
*walker++ = 0;
while (*string != 0)
*walker++ = *string++;
*walker++ = 0;
while (pad-- > 0)
*walker++ = 0;
for (inter = intTab; inter != NULL; inter = inter->int_next)
{
if (net_outbuffer_push(inter, mess, len) != len)
{
net_output(inter);
net_outbuffer_push(inter, mess, len);
}
}
}
static void serviceFunc(void)
{
static int up = 0;
if (up == 0)
{
if (httpSetup() < 0)
return;
up = 1;
}
if (up != 0)
httpService((int)(1.0 / config->pollrate));
}
int olsrd_plugin_interface_version(void)
{
return PLUGIN_INTERFACE_VERSION;
}
int olsrd_plugin_init(void)
{
ipAddrLen = olsr_cnf->ipsize;
mainAddr = &olsr_cnf->main_addr;
intTab = ifnet;
neighTab = neighbortable;
midTab = mid_set;
hnaTab = hna_set;
config = olsr_cnf;
httpInit();
olsr_register_timeout_function(serviceFunc, OLSR_FALSE);
olsr_parser_add_function(parserFunc, MESSAGE_TYPE, 1);
return 0;
}
static const struct olsrd_plugin_parameters plugin_parameters[] = {
{ .name = "address", .set_plugin_parameter = &httpSetAddress, .data = NULL },
{ .name = "port", .set_plugin_parameter = &httpSetPort, .data = NULL },
{ .name = "rootdir", .set_plugin_parameter = &httpSetRootDir, .data = NULL },
{ .name = "workdir", .set_plugin_parameter = &httpSetWorkDir, .data = NULL },
{ .name = "indexfile", .set_plugin_parameter = &httpSetIndexFile, .data = NULL },
{ .name = "user", .set_plugin_parameter = &httpSetUser, .data = NULL },
{ .name = "password", .set_plugin_parameter = &httpSetPassword, .data = NULL },
{ .name = "sesstime", .set_plugin_parameter = &httpSetSessTime, .data = NULL },
{ .name = "pubdir", .set_plugin_parameter = &httpSetPubDir, .data = NULL },
{ .name = "quantum", .set_plugin_parameter = &httpSetQuantum, .data = NULL },
{ .name = "messtime", .set_plugin_parameter = &httpSetMessTime, .data = NULL },
{ .name = "messlimit", .set_plugin_parameter = &httpSetMessLimit, .data = NULL },
};
void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
{
*params = plugin_parameters;
*size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
}
/*
* Local Variables:
* c-basic-offset: 2
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1