/*
*
* Copyright (C) 2006-07 Luca Deri <deri@ntop.org>
*
* http://www.ntop.org/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "ntop.h"
#include "globals-report.h"
/* Forward */
static int initRemoteFunct(void);
static void termRemoteFunct(u_char termNtop);
static void handleRemoteHTTPrequest(char* url);
/* Static */
static int sock = -1;
static pthread_t remoteThread;
/* ****************************** */
static PluginInfo RemotepluginInfo[] = {
{
VERSION, /* current ntop version */
"Remote",
"This plugin allows remote applications to access ntop data",
"0.1", /* version */
"<a class=mailto href=\"mailto:deri@ntop.org\">L. Deri</A>",
"Remoteplugin", /* http://<host>:<port>/plugins/Remoteplugin */
0, /* Active by default */
ViewOnly,
0, /* Inactive setup */
initRemoteFunct, /* InitFunc */
termRemoteFunct, /* TermFunc */
NULL, /* PluginFunc */
handleRemoteHTTPrequest, /* http request handler */
NULL, /* no host creation/deletion handle */
NULL, /* BPF Filter */
NULL, /* no status */
NULL /* no extra pages */
}
};
/* ****************************** */
/* Plugin entry fctn */
#ifdef MAKE_STATIC_PLUGIN
PluginInfo* remotePluginEntryFctn(void)
#else
PluginInfo* PluginEntryFctn(void)
#endif
{
traceEvent(CONST_TRACE_ALWAYSDISPLAY,
"Remote: Welcome to %s. (C) 2006-07 by L.Deri",
RemotepluginInfo->pluginName);
return(RemotepluginInfo);
}
/* ****************************** */
static void* remoteMainLoop(void* notUsed _UNUSED_) {
while(myGlobals.ntopRunState < FLAG_NTOPSTATE_SHUTDOWN) {
fd_set remoteMask;
int rc, all_right = 1;
char buf[1500], rsp[1500];
FD_ZERO(&remoteMask);
FD_SET(sock, &remoteMask);
if((rc = select(sock+1, &remoteMask, NULL, NULL, NULL)) > 0) {
char *method = NULL, *reference = NULL, *strtokstate;
void *ref = NULL;
struct sockaddr_in from;
socklen_t fromlen = sizeof(from);
memset(buf, 0, sizeof(buf));
rc = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr*)&from, &fromlen);
traceEvent(CONST_TRACE_INFO, "Received %d bytes [%s]", rc, buf);
method = strtok_r(buf, "\n;", &strtokstate);
if(method) {
if((reference = strtok_r(NULL, "\n;", &strtokstate))) {
traceEvent(CONST_TRACE_INFO, "-> '%s'", reference);
if(!strncmp(reference, "reference: 0x", 13)) {
reference += 13; /* Move to the reference pointer */
sscanf(reference, "%p", &ref);
traceEvent(CONST_TRACE_INFO, "---> '%p'", ref);
}
}
}
if(method && reference && all_right) {
if(!strncmp(method, "call: ", 6)) {
int device;
method += 6; /* Move to the method name */
traceEvent(CONST_TRACE_INFO, "Method '%s'", method);
if(!strncmp(method, "getFirstHost", strlen("getFirstHost"))) {
/* getFirstHost(device) */
method += 1+strlen("getFirstHost");
device = atoi(method);
if(device >= myGlobals.numDevices)
safe_snprintf(__FILE__, __LINE__, rsp, sizeof(rsp), "error: parameter out of range;\n");
else {
HostTraffic *el = getFirstHost(device);
add_valid_ptr(el);
safe_snprintf(__FILE__, __LINE__, rsp, sizeof(rsp), "rsp: ok;\nreference: %p;\n", el);
}
} else if(!strncmp(method, "getNextHost", strlen("getNextHost"))) {
/* getNextHost(device) */
method += 1+strlen("getNextHost");
device = atoi(method);
if(device >= myGlobals.numDevices)
safe_snprintf(__FILE__, __LINE__, rsp, sizeof(rsp), "error: parameter out of range;\n");
else if((ref == NULL) || (!is_valid_ptr((void*)ref)))
safe_snprintf(__FILE__, __LINE__, rsp, sizeof(rsp), "error: invalid reference;\n");
else {
HostTraffic *el = (HostTraffic*)ref, *next;
remove_valid_ptr(el);
next = getNextHost(device, el);
add_valid_ptr(next);
safe_snprintf(__FILE__, __LINE__, rsp, sizeof(rsp), "rsp: ok;\nreference: %p;\n", next);
}
} else if(!strncmp(method, "getHostAttribute", strlen("getHostAttribute"))) {
/* getHostAttribute(<attribute name>) */
if((ref == NULL) || (!is_valid_ptr((void*)ref)))
safe_snprintf(__FILE__, __LINE__, rsp, sizeof(rsp), "error: invalid reference;\n");
else {
HostTraffic *el = (HostTraffic*)ref;
char *attr = method+1+strlen("getHostAttribute");
char *ret = NULL;
attr[strlen(attr)-1] = '\0';
if(!strcmp(attr, "ethAddress")) ret = el->ethAddressString;
else if(!strcmp(attr, "hostNumIpAddress")) ret = el->hostNumIpAddress;
if(ret != NULL)
safe_snprintf(__FILE__, __LINE__, rsp, sizeof(rsp), "rsp: ok;\nreference: %p;\nvalue: %s;\n", el, ret);
else
safe_snprintf(__FILE__, __LINE__, rsp, sizeof(rsp), "error: unknown host attribute;\n");
}
} else
safe_snprintf(__FILE__, __LINE__, rsp, sizeof(rsp), "error: unknown method;\n");
}
} else
safe_snprintf(__FILE__, __LINE__, rsp, sizeof(rsp), "error: invalid parameters format;\n");
rc = sendto(sock, rsp, strlen(rsp), 0, (struct sockaddr*)&from, fromlen);
traceEvent(CONST_TRACE_INFO, "Sent %d bytes [%s]", rc, rsp);
}
}
traceEvent(CONST_TRACE_INFO, "Remote plugin TERMLOOP");
return(NULL);
}
/* ****************************** */
static int initRemoteFunct(void) {
int sockopt = 1, rc;
struct sockaddr_in sockIn;
traceEvent(CONST_TRACE_INFO, "Welcome to the Remote plugin");
if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
traceEvent(CONST_TRACE_ERROR, "REMOTE: unable to create UDP socket");
return -1;
}
rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt));
memset(&sockIn, 0, sizeof(sockIn));
sockIn.sin_family = AF_INET;
sockIn.sin_port = (int)htons(myGlobals.runningPref.webPort);
sockIn.sin_addr.s_addr = INADDR_ANY;
errno = 0;
rc = bind(sock, (struct sockaddr *)&sockIn, sizeof(sockIn));
if((rc < 0) || (errno != 0)) {
closeNwSocket(&myGlobals.sock);
traceEvent(CONST_TRACE_ERROR, "REMOTE: binding problem '%s'(%d), plugin disabled", strerror(errno), errno);
closeNwSocket(&sock);
sock = -1;
return(-1);
} else {
traceEvent(CONST_TRACE_INFO, "Remote plugin listening on UDP port %d",
myGlobals.runningPref.webPort);
createThread(&remoteThread, remoteMainLoop, NULL);
}
return(0);
}
/* ****************************** */
static void termRemoteFunct(u_char termNtop /* 0=term plugin, 1=term ntop */) {
if(remoteThread) killThread(&remoteThread);
if(sock != -1) closeNwSocket(&sock);
traceEvent(CONST_TRACE_INFO, "Remote: Thanks for using ntop Remote plugin");
traceEvent(CONST_TRACE_ALWAYSDISPLAY, "Remote: Done");
}
/* ****************************** */
static void handleRemoteHTTPrequest(char* url /* NOTUSED */) {
sendHTTPHeader(FLAG_HTTP_TYPE_HTML, 0, 1);
printHTMLheader("Remote Plugin", NULL, 0);
sendString("<center>This plugin is not supposed to display you anything as it<br>"
"implements remote network access to ntop</center>\n");
printHTMLtrailer();
}
syntax highlighted by Code2HTML, v. 0.9.1