Commit 42f1d300 authored by 's avatar
Browse files

MAPI/Web Application for Network Traffic Characterization

git-svn-id: file:///home/svn/mapi/trunk@520 8d5bb341-7cf1-0310-8cf6-ba355fef3186
parent 667277a0
C_WARNINGS = -w -Wall
CC = gcc
INCLUDE = -I../trunk
MAPI = ../..//
BINS = p2pmon p2pform.cgi
.PHONY: all clean
all: $(BINS)
%.o : %.c
$(CC) $(CFLAGS) $(INCLUDE) -c $<
p2pmon: p2pmon.o util.o
$(CC) $(CFLAGS) $(MAPI) $^ -o $@ -lrrd
p2pform.cgi: p2pform.o util.o
$(CC) $(CFLAGS) $^ -o $@ -lcgic
$(RM) *.o $(BINS) p2pmon_form.html p2pmon.cgi p2pmon.rrd
p2pmon categorizes the monitored traffic and is able to recognize traffic
from several P2P applications that use dynamic port numbers. Written on
top of DiMAPI, p2pmon may run on a different host than the monitoring
sensor. The results are presented through a web page, which also offers
an interface for specifying which filters will be used.
- Assuming that the MAPI trunk directory is '/home/zebraman/trunk', the p2pmon
directory should be '/home/zebraman/p2pmon'. Otherwise, change the variables
MAPI and INCLUDE in the Makefile appropriately
- MAPI should have been compiled with the flags WITH_DIMAPI and
WITH_TRACKING enabled in 'trunk/'
- p2pmon requires a web server and rrdtool version 1.2 or higher (in
Debian, apt-get install apache rrdtool)
- Compile p2pmon using 'make'. p2pmon requires librrd and libcgic (in
Debian, apt-get install librrd2-dev libcgicg1-dev)
- Run the script to set up the necessary files in your web
server's root directory. It takes as parameter the absolute path of the
web server's root directory. The script will create a directory p2pmon
and the necessary files and symbolic links for the web interface. For
example, if the root folder is /var/www, then
./ /var/www
will create '/var/www/p2pmon', and the web interface will be accessible
Specifically, for the above paths, will create:
/var/www/test/p2pmon/p2pmon_form.html -> /home/zebraman/p2pmon/p2pmon_form.html
/var/www/test/p2pmon/cgi-bin/p2pform.cgi -> /home/zebraman/p2pmon/p2pform.cgi
/var/www/test/p2pmon/cgi-bin/p2pmon.cgi -> /home/zebraman/p2pmon/p2pmon.cgi
Note that the actual files p2pmon_form.html and p2pmon.cgi are created
dynamically upon p2pmon's invocation.
- Finaly, you should configure your webserver to allow script execution in
the cgi-bin directory. For Apache, just edit /etc/apache/httpd.conf and,
using the above paths as an example, add the following
ScriptAlias /p2pmon/cgi-bin/ /var/www/p2pmon/cgi-bin/
For Apache2 you should also uncomment the following:
AddHandler cgi-script .cgi
and restart the web server.
- mapid and agent should be running at the monitoring sensor (see
'trunk/README_DIMAPI' for details)
- p2pmon takes two arguments: the subnet that we are going to monitor and
the address of the monitoring sensor (scope). Let's see two different
* p2pmon and mapi running on different hosts:
Organization with class B network. Monitoring sensor with IP address Its monitoring interface is eth1. Mapid monitors all traffic
to and from 147.52.* p2pmon should be invoked as
./p2pmon 147.52
If p2pmon runs on, then the web interface will
be accessible at
* p2pmon and mapid running on the same host:
A user wants to monitor the traffic of his/her workstation with IP
address Mapid is running on the workstation and monitors
the eth0 interface. p2pmon should be invoked as
./p2pmon localhost:eth0
- Note that after hitting 'update' in the web interface, it takes 2-3 seconds
until the update is completed
<title>CGI-C Test Form</title>
<frameset cols="50%,50%">
<frame src="cgi-bin/p2pmon.cgi" name="fig">
<frame src="./top.html" name="text">
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h> /* for Unix domain sockets: struct sockaddr_un */
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include "p2pmon.h"
#include "util.h"
#include <cgic.h>
extern int daemon_proc;
int cgiMain() {
char name[81];
char buf[MAXLINE];
int result, invalid, i;
int filter_choices[NUMFILTERS];
char *filter_names[NUMFILTERS];
int sockfd;
struct sockaddr_un servaddr;
daemon_proc = 1; /* syslog instead of stderr for err_* functions */
if ((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
/* create the address we will be connecting to */
bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
strcpy(servaddr.sun_path, UNIXSTR_PATH);
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");
result = cgiFormStringNoNewlines("subnet", name, 81);
if (result == cgiFormEmpty)
snprintf(name, 81, "empty");
for (i=0; i<NUMFILTERS; ++i)
filter_names[i] = filter[i].name;
result = cgiFormCheckboxMultiple("filters", filter_names, NUMFILTERS, filter_choices, &invalid);
Writen(sockfd, filter_choices, NUMFILTERS*sizeof(int));
Writen(sockfd, name, strlen(name)+1); // send '\0'
Readn(sockfd, buf, 3);
fprintf(cgiOut, "<HTML>\n<HEAD>\n</HEAD>\n");
fprintf(cgiOut, "<BODY><meta http-equiv=\"refresh\" content=\"0;url=../p2pmon_form.html\">\n");
fprintf(cgiOut, "</BODY></HTML>\n");
return 0;
This diff is collapsed.
#include "../../mapi.h"
struct filter_t {
int fd_in;
int fd_out;
int fid_in;
int fid_out;
int top_in;
int top_out;
char *name;
enum {F_BPF, F_TRACKER} type;
char *f;
enum {ACTIVE, INACTIVE} state;
struct filter_t filter[] = {
{0,0,0,0,0,0, "Total", F_BPF, NULL, ACTIVE}, // this should always be first
{0,0,0,0,0,0, "HTTP", F_BPF, "(port 80 or port 443)", ACTIVE},
{0,0,0,0,0,0, "SSH", F_BPF, "(port 22 or port 23 or port 107 or port 614 or port 992)", ACTIVE},
{0,0,0,0,0,0, "SMTP", F_BPF, "((tcp and port 25) or (udp and port 995))", ACTIVE},
{0,0,0,0,0,0, "DNS", F_BPF, "port 53", ACTIVE},
{0,0,0,0,0,0, "NETBIOS", F_BPF, "(port 137 or port 138 or port 139 or port 445)", ACTIVE},
{0,0,0,0,0,0, "RTSP", F_BPF, "(port 554 or port 8554 or port 322)", ACTIVE},
{0,0,0,0,0,0, "ICMP", F_BPF, "icmp", ACTIVE},
{0,0,0,0,0,0, "OpenVPN", F_BPF, "port 1194", ACTIVE},
{0,0,0,0,0,0, "WoW", F_BPF, "port 3724", ACTIVE},
{0,0,0,0,0,0, "FTP", F_TRACKER, "TRACK_FTP", ACTIVE},
{0,0,0,0,0,0, "Gnutella", F_TRACKER, "TRACK_GNUTELLA", ACTIVE},
{0,0,0,0,0,0, "BitTorrent", F_TRACKER, "TRACK_TORRENT", ACTIVE},
{0,0,0,0,0,0, "eDonkey", F_TRACKER, "TRACK_EDONKEY", ACTIVE},
{0,0,0,0,0,0, "DC++", F_TRACKER, "TRACK_DC", ACTIVE},
{0,0,0,0,0,0, "IP-in-IP", F_BPF, "ip[9] == 4", ACTIVE},
// {0,0,0,0,0,0, "IP-in-IP", F_TRACKER, "TRACK_IPOVERIP", ACTIVE},
#define NUMFILTERS (int)(sizeof(filter)/sizeof(filter[0]))
if [ $# -ne 1 ]; then
echo 1>&2 "Usage: $0 <path to web server's root directory>"
exit 1
mkdir $1/p2pmon
mkdir $1/p2pmon/cgi-bin
# awful
chmod 777 $1/p2pmon
cp index.html $1/p2pmon
ln -s `pwd`/p2pmon_form.html $1/p2pmon/p2pmon_form.html
ln -s `pwd`/p2pmon.cgi $1/p2pmon/cgi-bin/p2pmon.cgi
ln -s `pwd`/p2pform.cgi $1/p2pmon/cgi-bin/p2pform.cgi
echo -e "\nDONE - created the following files in $1/p2pmon\n"
ls -Rl $1/p2pmon
echo -e "\nDon't forget to enable script execution for $1/p2pmon/cgi-bin \
in your web server's configuration"
exit 0
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h> /* variable argument lists */
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <syslog.h>
#include "util.h"
static void err_doit(int, const char *, va_list);
int daemon_proc; /* set nonzero for syslog */
/* Fatal error unrelated to system call - Print message and terminate */
void err_quit(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
err_doit(0, fmt, ap);
/* Fatal error related to system call - Print message and terminate */
void err_sys(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
err_doit(1, fmt, ap);
/* Print message and return to caller. Caller specifies "errnoflag" */
static void err_doit(int errnoflag, const char *fmt, va_list ap) {
int errno_save, n;
char buf[MAXLINE + 1];
errno_save = errno; /* value caller might want printed */
vsnprintf(buf, MAXLINE, fmt, ap); /* safe */
n = strlen(buf);
if (errnoflag)
snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
strcat(buf, "\n");
if (daemon_proc) {
syslog(LOG_ERR, buf);
} else {
fflush(stdout); /* in case stdout and stderr are the same */
fputs(buf, stderr);
/* Write "n" bytes to a descriptor. */
ssize_t writen(int fd, const void *vptr, size_t n) {
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (nwritten < 0 && errno == EINTR)
nwritten = 0; /* and call write() again */
return(-1); /* error */
nleft -= nwritten;
ptr += nwritten;
void Writen(int fd, void *ptr, size_t nbytes) {
if (writen(fd, ptr, nbytes) != (ssize_t)nbytes)
err_sys("writen error");
/* Read "n" bytes from a descriptor. */
ssize_t readn(int fd, void *vptr, size_t n) {
size_t nleft;
ssize_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nread = read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0; /* and call read() again */
} else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
return(n - nleft); /* return >= 0 */
ssize_t Readn(int fd, void *ptr, size_t nbytes) {
ssize_t n;
if ( (n = readn(fd, ptr, nbytes)) < 0)
err_sys("readn error");
/* readline XXX NOT THREAD-SAFE */
static int read_cnt;
static char *read_ptr;
static char read_buf[MAXLINE];
static ssize_t
my_read(int fd, char *ptr)
if (read_cnt <= 0) {
if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
if (errno == EINTR)
goto again;
} else if (read_cnt == 0)
read_ptr = read_buf;
*ptr = *read_ptr++;
readline(int fd, void *vptr, size_t maxlen)
ssize_t n, rc;
char c, *ptr;
ptr = vptr;
for (n = 1; n < (ssize_t)maxlen; n++) {
if ( (rc = my_read(fd, &c)) == 1) {
*ptr++ = c;
//if (c == '\n')
if (c == '\0')
break; /* newline is stored, like fgets() */
} else if (rc == 0) {
*ptr = 0;
return(n - 1); /* EOF, n - 1 bytes were read */
} else
return(-1); /* error, errno set by read() */
*ptr = 0; /* null terminate like fgets() */
readlinebuf(void **vptrptr)
if (read_cnt)
*vptrptr = read_ptr;
/* end readline */
Readline(int fd, void *ptr, size_t maxlen)
ssize_t n;
if ( (n = readline(fd, ptr, maxlen)) < 0)
err_sys("readline error");
#define UNIXSTR_PATH "/tmp/unix.str" /* Unix domain stream */
#define MAXLINE 4096 /* max text line length */
void err_quit(const char *, ...);
void err_sys(const char *, ...);
void Writen(int fd, void *ptr, size_t nbytes);
ssize_t Readn(int fd, void *ptr, size_t nbytes);
ssize_t Readline(int fd, void *ptr, size_t maxlen);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment