mapitutor.tex 43 KB
Newer Older
's avatar
committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
\documentclass[a4paper, 11pt]{article}

\usepackage{graphicx}
\usepackage{amsmath}
\usepackage{epsfig}
\usepackage{verbatim}
\usepackage{times, courier}
% a greater variety of symbols
\usepackage{amsmath, amssymb}
% Nicely format and linebreak URLs in the bibliography (and elsewhere).
\usepackage{url}
\makeatletter % Define a new style that will use a smaller font.
\def\url@newstyle{%
  \@ifundefined{selectfont}{\def\UrlFont{\sf}}{\def\UrlFont{\small\ttfamily}}}
\makeatother
\urlstyle{new}  % Now actually use the newly defined style.
% fancyvrb for code line numbering etc..
\usepackage{fancyvrb}

\clubpenalty=10000
\widowpenalty=10000

\advance\textwidth 1.4cm
\advance\oddsidemargin -0.7cm
\advance\evensidemargin -0.7cm

\newenvironment{code}{\small\verbatim}{\endverbatim}

\pagestyle{plain}

\begin{document}
\title{\bf A Tutorial Introduction to MAPI}
\date{\small \today}
\maketitle
\thispagestyle{empty}



\section{Introduction}

This document provides a tutorial introduction to the Monitoring Application
Programming Interface (MAPI). It aims to give first-time users an overview
of the basic functionality of MAPI for rapid development of advanced
network monitoring applications.

\subsection{What is MAPI?}

MAPI is a highly {\em expressive} and flexible network monitoring API which
enables users to clearly communicate their monitoring needs to the
underlying traffic monitoring platform.
MAPI has been designed as part of the SCAMPI network monitoring
system\footnote{\tt http://www.ist-scampi.org/}.
Briefly, SCAMPI uses programmable hardware to perform computationally
intensive operations, while the middleware offers support for running
multiple monitoring applications simultaneously, and MAPI offers a
standardized API to applications that is much more expressive than existing
solutions. Furthermore, MAPI can also be used with commodity network
interfaces or specialized network monitoring hardware (e.g., DAG
cards\footnote{\tt http://www.endace.com/}).

\subsection{Why should I use MAPI?}

MAPI builds on a generalized flow abstraction that allows users to tailor
measurements to their own needs.
MAPI elevates network flows to {\em first-class status}, 
enabling programmers to define and operate on flows in a flexible and 
efficient way.
Where necessary and feasible, MAPI also allows the user to trigger
custom processing routines not only on summarized data, but also on 
the packets themselves.

The expressiveness of MAPI enables the underlying monitoring
system to make informed decisions in choosing the most efficient
implementation, while providing a coherent interface on top of different
lower-level elements, including intelligent switches,
high-performance network processors, and special-purpose network
interface cards. Thus, besides providing performance benefits,
MAPI decouples the development of the monitoring applications from the
environment on top of which they will be executed. Applications are written
once, and are able to run on top of various monitoring environments without
the need to alter or re-compile their code.



\section{Basic Functions}

This section gives an overview of the basic MAPI function calls.
For more information about the available MAPI functions
and their complete description please refer to
's avatar
committed
90 91
{\tt mapi(3)} and {\tt mapi\_stdflib(3)} man pages, also included in
Appendices \ref{sec:manpage} and \ref{sec:manstdflib}, respectively.
's avatar
committed
92 93 94 95 96 97 98 99 100 101 102

\subsection{Creating and Terminating Network Flows}

Central to the operation of the MAPI  
is the action of creating  a network  flow:

\begin{code}  
int mapi_create_flow(char *dev)
\end{code}

This call creates a network flow and returns a flow 
's avatar
 
committed
103
descriptor {\tt fd} that refers to it, or -1 on error.
's avatar
committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117
This  network flow consists of all network packets which 
go through network device {\tt dev}.
The packets of this flow can be further reduced to those which satisfy an appropriate
filter or other condition, as described in Section \ref{apply-functs}.

Besides creating a network flow, monitoring applications may
also close the flow when they are no longer interested in
monitoring:

\begin{code}  
int mapi_close_flow(int fd)
\end{code}  

After closing a flow, all the structures that have been allocated for the flow are released.
's avatar
 
committed
118
If the call fails, a value of -1 is returned.
's avatar
committed
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

\subsection{Applying functions to Network Flows}
\label{apply-functs}

Network flows allow users to treat packets
that belong to different flows in different ways.
For example, a user may be interested in {\em logging}
all packets of a flow (e.g. to record an intrusion attempt),
or in just {\em counting} the packets and their lengths
(e.g. to count the bandwidth usage of an application),
or in {\em sampling} the packets
(e.g. to find the IP addresses that generate most of the traffic).
The abstraction of the network flow
allows the user to clearly communicate to the underlying monitoring system
these different monitoring needs.
To enable users to communicate these different
requirements, MAPI enables users to
associate functions with network flows:

\begin{code}
int mapi_apply_function(int fd, char * funct, ...)
\end{code}  

The above association applies the function {\tt funct} 
to every packet of the network flow {\tt fd},
and returns a relevant function descriptor {\tt fid}.
Depending on the applied function, additional arguments may be passed.
Based on the header and payload of the packet, the function will
perform some computation, and may optionally discard the packet.

MAPI provides several 
{\em predefined} functions 
that cover some standard monitoring needs through the MAPI Standard Library
's avatar
committed
152
({\tt stdflib}).
's avatar
committed
153 154 155 156 157 158 159 160
For example, applying the {\tt BPF\_FILTER} function with parameter
{\tt tcp and dst port 80} restricts the packets of the network flow 
denoted by the flow descriptor {\tt fd}
to the TCP packets destined to port {\tt 80}. 
Other example functions include:
{\tt PKT\_COUNTER} which counts all packets in a flow,
{\tt SAMPLE} which can be used to sample packets, etc.
For a complete list of the available functions
's avatar
committed
161 162
in {\tt stdflib} and their description please refer to the
{\tt mapi\_stdflib(3)} man page, also included in Appendix~\ref{sec:manstdflib}.
's avatar
committed
163 164 165 166 167 168 169 170 171 172

Although these functions enable users to process packets,
and compute the network traffic metrics they are interested in
without receiving the packets in their own address space,
they must somehow communicate their results to the interested users.
For example, a user that will define that the function
{\tt PKT\_COUNTER}  will be applied to a flow,
will be interested in reading what is the number of packets that have
been counted so far.
This can be achieved by allocating a small amount of memory
's avatar
committed
173
for a data structure that contains the results.
's avatar
committed
174 175 176 177 178 179
The functions that will be applied to the packets
of the flow will write their results into this data structure.
The user who is interested in reading the results will read the
data structure using:

\begin{code}  
's avatar
committed
180
mapi_results_t * mapi_read_results(int fd, int fid)
's avatar
committed
181 182 183 184 185
\end{code}

The above call receives the results computed by the function
denoted by the function descriptor {\tt fid},
which has been applied to the network flow {\tt fd}.
's avatar
committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
It returns a pointer to the memory where the result's data structure is stored.

\begin{code}
typedef struct mapi_results {
  void* res;			//Pointer to function specific result data
  unsigned long long ts;	//timestamp
  int size;			//size of the result
} mapi_results_t;
\end{code}

The res field of this data structure is a pointer to the actual result.
It also provides a 64-bit timestamp for the results, that is the number of microseconds 
since 00:00:00 UTC, January 1, 1970 (the number of seconds is the upper 32 bits).   
It refers to the time when the MAPI stub received the result from mapid.
The memory for the results of each function is allocated from the stub once, 
during the  instantiation  of the flow.
's avatar
committed
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231

\subsection{Reading packets from a flow}
\label{reading-packets}

Once a flow is established, the user will probably want to read
packets from the flow. Packets can be read one-at-a-time
using the following {\em blocking} call:

\begin{code}
struct mapipkt * mapi_get_next_pkt(int fd, int fid)
\end{code}

which reads the next packet that belongs to flow {\tt fd}.
In order to read packets, the function {\tt TO\_BUFFER}
(which returns the relevant {\tt fid} parameter)
must have previously been applied to the flow.
If the user does not want to read one packet at-a-time
and possibly block, (s)he may register
a callback function that will be called when a packet
to the specific flow is available:

\begin{code}  
int mapi_loop(int fd, int fid, int cnt, mapi_handler callback)
\end{code}  

The above call makes sure that  the handler {\tt callback} 
will be invoked for each of the next {\tt cnt} packets 
that will arrive in the flow {\tt fd}.


's avatar
committed
232
\section{Distributed Monitoring (DiMAPI)}
's avatar
committed
233
\label{sec:dimapi}
's avatar
committed
234 235 236 237 238 239 240 241 242 243 244

The MAPI also offers capabilities for distributed passive network monitoring, using
many remote and distributed monitoring sensors. This is achieved through an extension
of the basic MAPI functionallity that we call DiMAPI. We describe in this section the
basic functionality that DiMAPI offers to users in order to develop advanced distrbuted 
network monitoring applications.

\subsection{What is DiMAPI?}

DiMAPI is an Application Programming Interface for Distributed Network 
Monitoring that provides to users the same framework as MAPI.
's avatar
committed
245
It enhances MAPI with the functionality of remote and distributed network monitoring. 
's avatar
committed
246 247 248 249 250 251 252 253
DiMAPI has been designed as part of the LOBSTER network monitoring system\footnote{\tt http://www.ist-lobster.org/}.
The applications that use DiMAPI can easily communicate with many remote monitoring
sensors, properly configure them and retrieve results from every one.

\subsection{When should I use DiMAPI?}

DiMAPI offers the expressive and flexible framework that MAPI provides
for applications that need to run remotely or use more than one
's avatar
committed
254 255 256 257
monitoring sensors. All the applications that till now run locally
(in the same computer where the monitoring interface is located), can also
run remotely (the monitoring interface belongs to a remote host) in exactly 
the same way by using DiMAPI. Also, DiMAPI can be used for the development
's avatar
committed
258 259 260 261 262 263 264 265
of applications that communicate with many distributed monitoring sensors, 
by using the notion of network scope.

\subsection{Writing applications using DiMAPI}

Writing applications using DiMAPI is done in exactly the same way as using MAPI.
Firstly, using \textit{mapi\_create\_flow} you can create network flows described from
the flow descriptor that is returned. \textit{mapi\_create\_flow} takes as argument the network scope
's avatar
committed
266
that consists of all the monitoring sensors we want, including the monitoring 
's avatar
committed
267
interface for each one, e.g. 
's avatar
committed
268
  \begin{code}mapi_create_flow("host1:eth0, host1:eth1, host2:/dev/dag, host3:eth0");\end{code}
's avatar
committed
269
For every network flow, you can apply the function you want using the
's avatar
committed
270
\textit{mapi\_apply\_function}. This function will be applied to all the remote monitoring sensors defined
's avatar
committed
271 272 273
at the network scope.
Before getting the results, the \textit{mapi\_connect} function 
have to be called. To get results from the remote sensors, the \textit{mapi\_read\_results}
's avatar
committed
274 275 276 277 278 279
function is used for the corresponding function that have been applied in exactly the same way as in local MAPI.

While in MAPI the \textit{mapi\_read\_results} function returns a single instance of mapi\_results\_t struct, 
in DiMAPI it returns a vector of mapi\_results\_t structs, one for every remote monitoring sensor 
(int the same order that these sensors had been declared in \textit{mapi\_create\_flow}.
We remind that \textit{mapi\_read\_results} returns the following data structure:
's avatar
committed
280 281

\begin{code}
's avatar
 
committed
282 283 284 285 286
typedef struct mapi_results {
  void* res;			//Pointer to function specific result data
  unsigned long long ts;	//timestamp
  int size;			//size of the result
} mapi_results_t;
's avatar
committed
287 288 289 290 291 292 293 294
\end{code}

For flows  associated  with  remote  interfaces, the timestamp that is returned by 
\textit{mapi\_read\_results} refers to the time when
mapicommd received the result from its associated local mapid.  
mapiommd then just forwards this timestamp to the MAPI stub of the remote
application.  This avoids any interference with the  network  RTT.
The necessary memory for these structs has been allocated, once per every function applied.
's avatar
committed
295

's avatar
committed
296 297 298 299 300 301
In order to know the number of the remote monitoring hosts that our network scope 
consists of, and so the number of the mapi\_results\_t instances that \textit{mapi\_read\_results}
will return, we use the \textit{mapi\_get\_scope\_size} function.

\begin{code}
int mapi_get_scope_size(int fd)
's avatar
committed
302 303
\end{code}

's avatar
committed
304 305 306 307
This function takes as a single argument the flow descriptor and returns the number of
the corresponding monitoring sensors. In case of a local MAPI application, it returns 1.
In this way we provide full compatibility between MAPI and DiMAPI applications. 

's avatar
committed
308 309
The other MAPI function that returns data from the monitoring sensors is the 
\textit{mapi\_get\_next\_pkt} function. In DiMAPI, the \textit{mapi\_get\_next\_pkt} returns packets from
's avatar
committed
310
the monitoring sensors in a round-robin way, if it is possible. 
's avatar
committed
311 312 313
Finally, in order to terminate, cleanup and close a network flow the \textit{mapi\_close\_flow}
fucntion is used.

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
\section{Management function calls}
MAPI contains various management function calls that provides information about
a running MAPI daemon (MAPId). These function calls provides information about
available devices and libraries as well as active flows and functions applied to
flows.

The available function calls are:
\begin{code}
int mapi_get_device_info(int devicenumber, mapi_device_info_t* info);
int mapi_get_next_device_info(int devicenumber, mapi_device_info_t* info);
int mapi_get_library_info(int libnum, mapi_lib_info_t *info);
int mapi_get_next_library_info(int libnum, mapi_lib_info_t* info);
int mapi_get_libfunct_info(int libnum, mapi_libfunct_info_t *info);
int mapi_get_libfunct_next_info(int libnum, mapi_libfunct_info_t *info);
int mapi_get_flow_info(int fd, mapi_flow_info_t *info);
int mapi_get_next_flow_info(int fd, mapi_flow_info_t *info);
int mapi_get_function_info(int fd, int fid, mapi_function_info_t *info);
int mapi_get_next_function_info(int fd, int fid, mapi_function_info_t *info);
\end{code}

The mapi\_get\_?\_info calls, retrieves information about one specific resource
identified by an integer ID. The mapi\_get\_next\_?\_info calls returns information
about the next resource with a hight ID than the one specified. This is used for
looping through all available resources.

The following code is an example on how the management functions can be used for listing all available libraries and the functions in each library:

\begin{Verbatim}[numbersep=12pt, numbers=left, baselinestretch=1.0, fontsize=\small]
int id=-1,fid;
mapi_lib_info_t info;
mapi_libfunct_info_t finfo;
	
printf("ID\tName\t# functions\n");
while(mapi_get_next_library_info(id++,&info)==0) {
	printf("%d\t%s\t%d\n",info.id,info.libname,info.functs);
	fid=-1;
	while(mapi_get_next_libfunct_info(info.id,fid++,&finfo)==0)
  	    printf("\t\t%s(%s)\n",finfo.name,finfo.argdescr);		
}
\end{Verbatim}

This code uses mapi\_get\_next\_library\_info to loop through all available libraries and print out the id and name of the library and the number of functions. It then uses the mapi\_get\_next\_libfunct\_info to loop through and print information about all the available functions in each library.

's avatar
committed
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
\section{Installation}

MAPI is available from {\tt http://mapi.uninett.no} as a source
code distribution.
Currently MAPI has been tested with the Linux OS and supports the following
monitoring interfaces:
\begin{itemize}
\item Commodity Ethernet NICs
\item Endace DAG cards
\end{itemize}

It is recommended to download the latest public source code release.
You can also checkout the latest development version from the subversion
repository using the following command:
\begin{code}
svn co --username public --password public \
        https://svn.testnett.uninett.no/mapi/trunk
\end{code}

\subsection{Software Compilation}

After you have unpacked the sources, you first need to
configure the distribution using the supplied {\tt configure}
script.\footnote{In case you have checked out the sources from the
subversion repository, you
need to first run the supplied {\tt bootstrap.sh} script in order to create
the generated autoconf files. It requires the latest versions of the
{\tt autoconf}, {\tt automake}, and {\tt libtool} tools.} 
The following configure options are available for enabling support for
optional features:

\renewcommand{\arraystretch}{1.6}
\begin{tabular}{rp{7cm}}
{\tt --enable-dimapi} & Support for remote and distributed monitoring (cf.
Section~\ref{sec:dimapi}) \\
392
{\tt --enable-ssl} & Enable encryption of DiMAPI traffic \\
's avatar
committed
393 394 395 396 397
{\tt --enable-dag} & Support for Endace DAG packet capture cards \\
\multicolumn{2}{l}{MAPI function libraries} \\
{\tt --enable-trackflib} & Build the traffic characterization library \\
{\tt --enable-anonflib} & Build the traffic anonymization library \\
{\tt --enable-ipfixflib} & Build the NetFlow export library \\
398
{\tt --enable-extraflib} & Build the Extra MAPI function library \\
's avatar
committed
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
\multicolumn{2}{l}{Miscellaneous options} \\
{\tt --enable-funcstats} & Enable function statistics. This option enables packet
counters for each applied function \\
\end{tabular}
\renewcommand{\arraystretch}{1.0}
\\\\

\noindent Follow these steps to compile and install the software:
\begin{code}
./configure
make
make install
\end{code}

The default installation prefix is {\tt /usr/local} and can be changed with
the {\tt --prefix} configure parameter. All files are installed in
appropriate directories under the prefix path. For example, binaries are
installed in {\tt <prefix>/sbin}.

\subsubsection{Library path}

The {\tt libmapi} library is installed by default into {\tt
/usr/local/lib}. Some Linux distributions do not scan this directory as
part of the default library path, so this can cause problems to programs
linked with the shared version of {\tt libmapi}.

To resolve this issue, you can add {\tt /usr/local/lib} to the default
system library path by adding the line {\tt /usr/local/lib} into {\tt
/etc/ld.so.conf}.  After saving it, run {\tt ldconfig} to update the system
library cache.

Another possible option, however not recommended, is to set the environment
variable {\tt LD\_LIBRARY\_PATH} as follows:
's avatar
committed
432

's avatar
committed
433 434 435 436 437
\begin{code}
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
\end{code}


's avatar
committed
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
\subsection{Monitoring Sensor Configuration}

In order to setup a monitoring sensor, the MAPI daemon (\textit{mapid}) has to 
be configured and run to the monitoring machine.
\textit{mapid} is configured via the \textit{mapi.conf} configuration file, located in the
installation directory (usually \textit{/usr/local/etc/mapi/mapi.conf}).
In this file we can configure the network interfaces that can provide \textit{mapid} with network packets,
their corresponding MAPI drivers, the MAPI function libraries that we want to support in 
this \textit{mapid}, the libraries and drivers path and other.
A typical example of this file is given below:

\begin{scriptsize}
\begin{verbatim}
libpath=/usr/local/share/mapi
drvpath=/usr/local/share/mapi

libs=stdflib.so:extraflib.so

debug=2
dimapi_port=2233

[driver]
device=eth0
driver=mapinicdrv.so

[driver]
device=eth1
driver=mapinicdrv.so

[driver]
device=lo
driver=mapinicdrv.so
description=This is a driver for local capture

[format]
format=MFF_PCAP
driver=mapinicdrv.so
description=Offline pcap-capture

\end{verbatim}
\end{scriptsize}

For DiMAPI, the MAPI communication daemon (\textit{mapicommd}) must also run to the 
monitoring machine.
\textit{mapicommd} is responsible for accepting requests for all the MAPI calls from remote hosts,
forward them to the local \textit{mapid} and return the answers and results from the local
\textit{mapid} back to the remote application.
\textit{mapicommd} uses TCP sockets with SSL encryption for the communication.
The port number that \textit{mapicommd} uses to listen for incoming connections is defined in
\textit{mapi.conf} located in the installation directory.


\subsection{Compiling new MAPI applications}

Any user is able to write its own MAPI applications and programs, using the basic
functions described above and the several function libraries that is also provided.
In order to compile a MAPI program, the flag \textit{-lmapi} should be used.
For example:

\begin{verbatim}
     gcc my_mapi_program.c -o my_mapi_program -lmapi
\end{verbatim}
's avatar
committed
500 501


's avatar
committed
502 503 504 505 506 507 508 509 510 511 512 513 514 515
\section{Examples}

The following sections present some example programs
that introduce the concept of the network flow as defined in MAPI,
and demonstrate the ease of programming simple applications that perform
complex monitoring operations using MAPI.

\subsection{Getting Started: Simple Packet Count}

This first simple program demonstrates the basic steps that must be taken
in order to create and use a network flow. In this example, a network
flow is used for counting the number of packets destined to a web server
in a time period of 10 seconds.

's avatar
committed
516
\begin{Verbatim}[numbersep=12pt, numbers=left, baselinestretch=1.0, fontsize=\small]
's avatar
committed
517 518 519
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
's avatar
committed
520
#include <mapi.h>
's avatar
committed
521 522 523 524

int main() {

    int fd, fid;
's avatar
 
committed
525
    mapi_results_t *result;
's avatar
committed
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548

    /* create a flow using the eth0 interface */
    fd = mapi_create_flow("eth0");
    if (fd < 0) {
        printf("Could not create flow\n");
        exit(EXIT_FAILURE);
    }

    /* keep only the packets directed to the web server */
    mapi_apply_function(fd, "BPF_FILTER", "tcp and dst port 80");
    
    /* and just count them */
    fid = mapi_apply_function(fd, "PKT_COUNTER");

    /* connect to the flow */
    if(mapi_connect(fd) < 0) {
        printf("Could not connect to flow %d\n", fd);
        exit(EXIT_FAILURE);
    }
    
    sleep(10);
    
    /* read the results of the applied PKT_COUNTER function */
's avatar
 
committed
549
    result = (mapi_results_t *)mapi_read_results(fd, fid);
's avatar
committed
550
    printf("pkts: %llu\n", *((unsigned long long*)result->res) );
's avatar
committed
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
    
    mapi_close_flow(fd);
    return 0;
}
\end{Verbatim}

The flow of the code is as follows: We begin by creating a network flow
(line~12) that will receive the packets we are interested in.
We specify that we are going to use the {\tt eth0} network interface
for monitoring the traffic.
For a different monitoring adapter we would use something like {\tt
/dev/scampi/0} for a Scampi adapter, or {\tt /dev/dag0} for a DAG card,
depending on the configuration. We store the returned flow descriptor in the
variable {\tt fd} for future reference to the flow.

In the next step we restrict the packets of the newly created flow to
those destined to our web server by applying the function {\tt
BPF\_FILTER} (line~19) using the filter {\tt tcp and dst port 80}.
The filtering expression is written using the {\tt tcpdump(8)}
syntax. Since we are interested in just counting the packets, we also
apply the {\tt PKT\_COUNTER} function (line~22). 
In order to later read the results of that function,
we store the returned function descriptor in {\tt fid}.

The final step is to start the operation of the network flow by connecting
to it (line~25). The call to {\tt mapi\_connect()}
actually activates the flow inside the MAPI daemon ({\tt mapid}),
which then starts processing the monitored traffic according to
the specifications of the flow. In our case, it just keeps a count of the
packets that match the filtering condition.

After 10 seconds, we read the packet count by passing the relevant
flow descriptor {\tt fd} and function descriptor {\tt fid}
to {\tt mapi\_read\_results()} (line~33).
Our work is done, so we close the network flow in order to free the
resources allocated in {\tt mapid} (line~36).

\subsection{Link Utilization}

Our next example presents an application that periodically reports the
utilization of a network link. It uses two network flows to separate the
incoming from the outgoing traffic, and demonstrates how to retrieve the
results of an applied function by reference.

's avatar
committed
595
\begin{Verbatim}[numbersep=12pt, numbers=left, baselinestretch=1.0, fontsize=\small]
's avatar
committed
596 597 598 599
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
's avatar
committed
600
#include <mapi.h>
's avatar
committed
601 602 603 604 605 606 607

static void terminate();
int in_fd, out_fd;

int main() {

    int in_fid, out_fid;
's avatar
committed
608
    mapi_results_t *result1, *result2;
's avatar
committed
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
    unsigned long long *in_cnt, *out_cnt;
    unsigned long long in_prev=0, out_prev=0;
    
    signal(SIGINT, terminate);
    signal(SIGQUIT, terminate);
    signal(SIGTERM, terminate);

    /* create two flows, one for each traffic direction */
    in_fd = mapi_create_flow("eth0");
    out_fd = mapi_create_flow("eth0");
    if ((in_fd < 0) || (out_fd < 0)) {
        printf("Could not create flow\n");
        exit(EXIT_FAILURE);
    }

    /* separate incoming from outgoing packets */
's avatar
committed
625 626 627 628
    mapi_apply_function(in_fd, "BPF_FILTER",
            "dst host 139.91.145.84");
    mapi_apply_function(out_fd, "BPF_FILTER",
            "src host 139.91.145.84");
's avatar
committed
629 630 631 632 633 634 635 636 637 638 639 640 641
    
    /* count the bytes of each flow */
    in_fid = mapi_apply_function(in_fd, "BYTE_COUNTER");
    out_fid = mapi_apply_function(out_fd, "BYTE_COUNTER");

    /* connect to the flows */
    if(mapi_connect(in_fd) < 0) {
        printf("Could not connect to flow %d\n", in_fd);
        exit(EXIT_FAILURE);
    }
    if(mapi_connect(out_fd) < 0) {
        printf("Could not connect to flow %d\n", out_fd);
        exit(EXIT_FAILURE);
's avatar
committed
642
    } 
's avatar
committed
643 644 645 646
        
    while(1) {      /* forever, report the load */
        
        sleep(1);
's avatar
committed
647
      
's avatar
committed
648
        result1 = mapi_read_results(
's avatar
committed
649
            in_fd, in_fid);
's avatar
committed
650
        result2 = mapi_read_results(
's avatar
committed
651
            out_fd, out_fid);
's avatar
committed
652
        in_cnt = result1->res;
's avatar
committed
653
        out_cnt = result2->res;
's avatar
committed
654
  
's avatar
committed
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
        printf("incoming: %.2f Mbit/s (%llu bytes)\n",
                (*in_cnt-in_prev)*8/1000000.0, (*in_cnt-in_prev));
        printf("outgoing: %.2f Mbit/s (%llu bytes)\n\n",
                (*out_cnt-out_prev)*8/1000000.0, (*out_cnt-out_prev));

        in_prev = *in_cnt;
        out_prev = *out_cnt;
    }
    
    return 0;
}

void terminate() {
    mapi_close_flow(in_fd);
    mapi_close_flow(out_fd);
    exit(EXIT_SUCCESS);
}
\end{Verbatim}

The basic initial steps are similar to those in the previous example, with
the main difference of manipulating two network flows instead of one.
We begin by creating two network flows
's avatar
committed
677
with flow descriptors {\tt in\_fd} and {\tt out\_fd} (lines~22 and~23)
's avatar
committed
678 679
for the incoming and outgoing traffic, respectively, and then we
apply the filters that will differentiate the traffic captured
's avatar
committed
680
by each flow (lines~30--~33).
's avatar
committed
681 682 683 684 685 686 687 688 689 690 691
In our case, we monitor the link that connects the host
139.91.145.84 to the Internet. All incoming packets will then have
139.91.145.84 as destination address,
while all outgoing packets will have this IP as source address.
In case that we would monitor a link that connects a whole subnet
to the Internet, the host in the filtering conditions should be replaced
by that subnet. For instance, for the subnet 139.91/16,
we would define the filter {\tt dst net 139.91.0.0} for the incoming traffic.

Since we are interested in counting the amount of traffic
passing through the monitored link,
's avatar
committed
692
we apply the {\tt BYTE\_COUNTER} function to both flows (lines 36 and 37),
's avatar
committed
693 694 695
and save the relevant function descriptors in {\tt in\_fid} and {\tt out\_fid}
for future reference.

's avatar
committed
696 697 698
After activating the flows (lines 40--47), we enter the main program loop, 
which periodically calls the 
{\tt mapi\_read\_results()} for each flow (lines 53--56) and
's avatar
committed
699
prints the incoming and outgoing traffic in Mbit/s, and the number of bytes
's avatar
committed
700
seen in each one second interval (lines 60--63).
's avatar
committed
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
In each iteration, the current value of each  {\tt BYTE\_COUNTER} function
result is retrieved by dereferencing {\tt in\_cnt} and {\tt out\_cnt}.

In order to ensure a graceful termination of the program, we have initially
registered the signals {\tt SIGINT}, {\tt SIGTERM}, and {\tt SIGQUIT} with
the function {\tt terminate()} (lines 16--18),
which closes the two flows and terminates the process.

\subsection{Worm Detection}

This example demonstrates how MAPI can be used for the detection of an
Internet worm---a rather complicated task that requires deep packet
inspection. The simplified application presented here
constantly inspects the monitored traffic and
prints any packets that match the {\em signature} of the Slapper worm.

A signature describes an intrusion threat by matching characteristic
parts of the attack packet(s) against the packets of the traffic stream.
Such signatures are commonly used in
Network Intrusion Detection Systems (NIDSes), which constantly examine
the network traffic and determine whether any signatures indicating intrusion
attempts are matched.
For example, a packet directed to port 80 that contains the string
{\tt /bin/perl.exe} is probably an indication of a malicious user attacking a
web server. This attack can be detected by a signature which checks the
destination port number of each captured packet,
and defines a string search for {\tt /bin/perl.exe} in the packet payload.

's avatar
committed
729
\begin{Verbatim}[numbersep=12pt, numbers=left, baselinestretch=1.0, fontsize=\small]
's avatar
committed
730 731 732 733 734 735 736 737 738 739 740
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
/* inet_ntoa() */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

's avatar
committed
741
#include <mapi.h>
's avatar
committed
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848

static void terminate();
void print_IP_pkt(struct mapipkt *pkt);

int fd;

int main() {

    int fid;
    struct mapipkt *pkt;
    
    signal(SIGINT, terminate);
    signal(SIGQUIT, terminate);
    signal(SIGTERM, terminate);

    /* create a flow using the eth0 interface */
    fd = mapi_create_flow("eth0");
    if (fd < 0) {
        printf("Could not create flow\n");
        exit(EXIT_FAILURE);
    }

    /* the bpf part of the signature */
    mapi_apply_function(fd, "BPF_FILTER",
            "udp and src port 2002 and dst net 139.91.23 and dst port 80");
    
    /* the content search part of the signature */
    mapi_apply_function(fd, "STR_SEARCH",
            "|00 00|E|00 00|E|00 00|@|00|", 0, 100);

    /* must use TO_BUFFER in order to read full packet records */
    fid = mapi_apply_function(fd, "TO_BUFFER");

    /* connect to the flow */
    if(mapi_connect(fd) < 0) {
        printf("Could not connect to flow %d\n", fd);
        exit(EXIT_FAILURE);
    }
    
    while(1) {     /* forever, wait for matching packets */
        
        pkt = mapi_get_next_pkt(fd, fid);
        printf("\nSlapper worm packet!\n");
        print_IP_pkt(pkt);
    }
    
    return 0;
}

void terminate() {
    mapi_close_flow(fd);
    exit(EXIT_SUCCESS);
}
\end{Verbatim}

In the same fashion as with the previous examples, the program starts
by creating a network flow using the {\tt eth0} network interface (line 29).
We then configure the network flow
according to the worm signature (lines 36--41).
For the identification of the Slapper worm,
we use the following signature taken from the default ruleset of the
popular Snort Intrusion Detection System\footnote{\tt http://www.snort.org/}:

\begin{code}
alert udp $EXTERNAL_NET 2002 -> $HTTP_SERVERS $HTTP_PORTS
(msg:"MISC slapper worm admin traffic";
content:"|00 00|E|00 00|E|00 00|@|00|"; depth:100;
reference:url,isc.incidents.org/analysis.html?id=167;
reference:url,www.cert.org/advisories/CA-2002-27.html;
classtype:trojan-activity; sid:1889; rev:5;)
\end{code}

We presume that {\tt \$EXTERNAL\_NET} is set to {\tt any} IP address,
{\tt \$HTTP\_SERVERS} is set to the subnet 139.91.23,
and {\tt \$HTTP\_PORTS} is set to 80.
Given these assumptions, packets that match this signature
can also be returned by a network flow, after the application
of the appropriate MAPI functions, as follows:
\begin{itemize}
\item the condition {\tt \$EXTERNAL\_NET 2002 -> \$HTTP\_SERVERS \$HTTP\_PORTS}
is fulfilled by applying the {\tt BPF\_FILTER} function with the filter
{\tt udp and src port 2002 and dst net 139.91.23 and dst port 80} (line 36).

\item the content search condition {\tt content:"|00 00|E|00 00|E|00 00|@|00|";}
{\tt depth:100;} is fulfilled by applying the {\tt STR\_SEARCH} function with the
same {\tt content} and {\tt depth} parameters, and {\tt 0} for the {\tt
offset} parameter (line 40).
\end{itemize}

In order to print specific information about each attack packet,
we have to receive the full records of the matching packets to the
address space of the application.
This is accomplished by applying the function {\tt TO\_BUFFER} (line 43),
which instructs {\tt mapid} to store the packets that match the
conditions of the flow into a shared memory segment.
The application can then retrieve the stored records using
{\tt mapi\_get\_next\_pkt()}.

In the main execution loop, the application blocks into
{\tt mapi\_get\_next\_pkt()} (line 54) until a matching packet is available.
When such a packet is captured, the application prints its source and
destination MAC and IP addresses by calling {\tt print\_IP\_pkt()}.
The listing of the {\tt print\_IP\_pkt()} function
is included in Appendix~\ref{sec:misccode}. Since the application has
access to the full packet record, {\tt print\_IP\_pkt()} can be altered
as needed to print any other part of the packet, even the whole packet payload.

's avatar
committed
849
\subsection{Authentication and Authorization in DiMAPI}
's avatar
 
committed
850 851
This example illustrates the authentication and authorization
mechanism implemented in DiMAPI. 
852 853 854 855
In most cases, administrators of sensors may not want users to have full
access to the monitoring system for privacy and performance reasons.
As far as privacy is concerned,
an administrator may not be willing to provide full packets to users,
's avatar
 
committed
856 857 858 859
but only anonymized packets, in a way he sees fit.
To improve the scalability of this, users are supposed to belong in
Virtual Organizations, and the aforementioned policies apply to VOs
alone.
's avatar
committed
860

's avatar
 
committed
861 862 863 864 865
The administrator of each sensor can create a file that specifies
the anonymization policy that will be applied to the flows that
a user creates.
The file can be specified in the /src/vod/vod.conf configuration
file, in the following way:
's avatar
committed
866

's avatar
committed
867
\begin{code}
's avatar
 
committed
868 869 870 871 872 873 874 875 876 877 878 879 880 881
[files]
policiesfile=/etc/dimapi_policies.conf
\end{code}

An example of such a policy is the following:

\begin{code}
[VO]
ANONYMIZE=TCP:PAYLOAD:STRIP:0
ANONYMIZE=IP:SRC_IP:RANDOM
ANONYMIZE=IP:CHECKSUM:CHECKSUM_ADJUST

#[VO]
#FUNCTION=PROTOCOL:FIELD:ANONYMIZATION_FUNCTION:OPTIONAL_ARGUMENT
's avatar
committed
882 883 884
\end{code}

Policies in general specify that the administrator of the sensor, 
's avatar
 
committed
885 886 887 888 889 890
permit the Virtual Organizations identified in the {\tt VO} field
to receive packets from the network flows they create that are
anonymized according to the policy he has set.
In this policy, the conditions restrict the members of VO to
receive packets with no TCP payload, randomized source IP addresses,
and fixed checksum field.
's avatar
committed
891 892


's avatar
committed
893
\begin{Verbatim}[numbersep=12pt, numbers=left, baselinestretch=1.0, fontsize=\small]
's avatar
committed
894 895 896 897
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
's avatar
committed
898
#include <mapi.h>
's avatar
committed
899 900 901

static int fd;

's avatar
committed
902 903
static void die(int d);

's avatar
committed
904 905
int main(int argc,char **argv)
{
's avatar
committed
906
  int counter, loop = 10, connect_status;
's avatar
committed
907
  mapi_results_t *dres;
's avatar
committed
908 909 910 911 912 913

  signal(SIGINT,die);
  signal(SIGTERM,die);
  signal(SIGQUIT,die);

  /* create a flow using the eth0 interface */
's avatar
committed
914
  fd = mapi_create_flow("localhost:eth0");
's avatar
committed
915 916 917 918 919 920 921 922
  if (fd <0)
  {
	  printf("Could not create flow\n");
  }

  /* apply a packet counter */
  counter = mapi_apply_function(fd,"PKT_COUNTER");

's avatar
 
committed
923 924
  /* authenticate the user creating the flow */
  if ( mapi_authenticate(fd, "John","Doe","VO_Of_Unknown_Members") != 0 )
's avatar
committed
925
  {
's avatar
 
committed
926
    printf("Authentication failed\n");
's avatar
committed
927 928 929 930 931 932 933
    die(0);
  }
  
  /* connect to the flow */
  connect_status = mapi_connect(fd);
  if(connect_status < 0)
  {
's avatar
committed
934
	printf("mapi_connect has failed.\n");
's avatar
committed
935 936 937 938 939 940
	die(0);
  }

  while( loop-- ) //count the packets
  {
    sleep(1);
's avatar
committed
941 942 943
    dres = mapi_read_results(fd,counter);
    if(dres)
      printf("PKTS=%llu\n",*((unsigned long long*)dres->res) );
's avatar
committed
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
    else
      printf("mapi_read_results failed!\n");
  }

  die(0);
  return 0;
}

 static void die(int d)
{
  mapi_close_flow(fd);
  exit(0);
}


\end{Verbatim}

's avatar
committed
961 962 963
The user creates a flow (line 21) and then applies the packet counter
function (line 28). He then proceeds to authenticate himself as the
creator of the flow. This is done with the {\tt mapi\_authenticate} function (line 31).
's avatar
 
committed
964 965
The user is verified to belong in the VO specified, and then the 
password is checked for matching. When the user connect to
's avatar
committed
966
the flow (line 38), the mapi daemon further checks if the flow is authenticated
's avatar
 
committed
967
If it does not, an error is returned to the user.
's avatar
committed
968 969 970
For this example, the DiMAPI support is needed, so MAPI should be configured with the
\textit{--enable-dimapi} configuration option.

's avatar
committed
971

's avatar
committed
972 973 974 975 976 977
\subsection{Using DiMAPI}

This is a simple application that demonstrates the use of DiMAPI for distributed network monitoring.
In this example we just count all the web packets in every monitoring sensor.


's avatar
committed
978
\begin{Verbatim}[numbersep=12pt, numbers=left, baselinestretch=1.0, fontsize=\small]
's avatar
committed
979 980 981 982
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
's avatar
committed
983
#include <mapi.h>
's avatar
committed
984 985 986 987 988 989

static void terminate();
int fd;

int main() {

's avatar
committed
990
  int fid;
's avatar
committed
991
  mapi_results_t *dres;
's avatar
committed
992 993
  unsigned long long *count, total_count=0;
  int i, loop;
's avatar
committed
994
  int number_of_sensors;
's avatar
committed
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006

  signal(SIGINT, terminate);
  signal(SIGQUIT, terminate);
  signal(SIGTERM, terminate);

  /* create a flow using a scope of three monitoring sensors */
  fd = mapi_create_flow("sensor.uninett.no:/dev/dag0, 
               mon1.ics.forth.gr:eth0, 123.45.6.7:eth2");
  if (fd < 0) {
    printf("Could not create flow\n");
    exit(EXIT_FAILURE);
  }
's avatar
committed
1007

's avatar
committed
1008 1009 1010 1011 1012
  /* keep only the web packets */
  if (mapi_apply_function(fd, "BPF_FILTER", "tcp and port 80") < 0) {
      printf("Could not apply BPF_FILTER function\n");
      exit(EXIT_FAILURE);
  }
's avatar
committed
1013

's avatar
committed
1014 1015 1016 1017 1018 1019
  /* count them in every monitoring sensor */
  fid = mapi_apply_function(fd, "PKT_COUNTER");
  if (fid < 0) {
    printf("Could not apply PKT_COUNTER function\n");
    exit(EXIT_FAILURE);
  }
's avatar
committed
1020

's avatar
committed
1021 1022 1023 1024 1025
  /* connect to the flow */
  if(mapi_connect(fd) < 0) {
    printf("Could not connect to flow %d\n", fd);
    exit(EXIT_FAILURE);
  }
's avatar
committed
1026 1027 1028

  /* get the number of the monitoring sensors */
  number_of_sensors = mapi_get_scope_size(fd);
's avatar
committed
1029
   
's avatar
committed
1030 1031 1032 1033
  /* read the results of the applied PKT_COUNTER function from all 
     hosts every 1 sec */
  while(loop--){
    sleep(1);
's avatar
committed
1034

's avatar
committed
1035
    dres = mapi_read_results(fd, fid);
's avatar
committed
1036

's avatar
committed
1037
    for (i=0; i<number_of_sensors; i++) {
's avatar
committed
1038 1039 1040
      count = (unsigned long long*) dres[i].res;
      printf("web pkts in host %d: %llu\n",i, *count);
      total_count += *count;
's avatar
committed
1041
    }
's avatar
committed
1042 1043
    printf("Total web packets: %llu\n",total_count);
  }
's avatar
committed
1044
    
's avatar
committed
1045
  return 0;
's avatar
committed
1046 1047 1048
}

void terminate() {
's avatar
committed
1049 1050
  mapi_close_flow(fd);
  exit(EXIT_SUCCESS);
's avatar
committed
1051 1052 1053
}
\end{Verbatim}

's avatar
committed
1054
We create a network flow with a scope of three monitoring sensors (line~23).
's avatar
committed
1055 1056 1057 1058
Then we apply to this network flow the functions \textit{BPF\_FILTER} and 
\textit{PKT\_COUNTER}. These functions will be applied in all monitoring
sensors we declared. Then we connect to this flow and start receiving results from \textit{PKT\_COUNTER}
every one second. The \textit{mapi\_read\_results} function returns a 
's avatar
committed
1059 1060 1061 1062 1063
\textit{mapi\_results\_t} element. The \textit{mapi\_get\_scope\_size} function gives up the
number of the monitoring hosts that should give results, 
one \textit{mapi\_results\_t} instance (in a table) per every monitoring sensor 
(in our example this will be equal to three). 
The actual result of the \textit{PKR\_COUNTER} function
's avatar
committed
1064
for the monitoring sensor \textit{i} is retrieved from \textit{dres[i].res} field.
's avatar
committed
1065 1066
Finally, we close the network flow in order to free all the
resources allocated in every monitoring sensor.
's avatar
committed
1067 1068
For this example, MAPI should be configured with the \textit{--enable-dimapi} configuration option
for DiMAPI support.
's avatar
committed
1069 1070


's avatar
committed
1071 1072 1073 1074
\subsection{Using Anonymization}

This is a simple application that shows some basic anonymization features of MAPI.

's avatar
committed
1075
\begin{Verbatim}[numbersep=12pt, numbers=left, baselinestretch=1.0, fontsize=\small]
's avatar
committed
1076 1077
#include <stdio.h>
#include <mapi.h>
's avatar
committed
1078 1079 1080 1081 1082 1083 1084 1085
#include <stdlib.h>
#include <unistd.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

1086
void print_IP_pkt(struct mapipkt *rec);
's avatar
committed
1087 1088 1089

int main(int argc, char *argv[]) {

's avatar
committed
1090 1091 1092 1093
        int fd;
	int fid;
	int connect_status;
	struct mapipkt *pkt;	
's avatar
committed
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105

	fd=mapi_create_flow("eth0");
	if(fd==-1) {
	    printf("Flow cannot be created. Exiting..\n");
	    exit(-1);
	}

	//Anonymization of TCP packets

	mapi_apply_function(fd,"BPF_FILTER","tcp");

	//map IP addresses to sequential integers (1-to-1 mapping)
's avatar
committed
1106 1107
	mapi_apply_function(fd,"ANONYMIZE", "IP,SRC_IP,MAP");
	mapi_apply_function(fd,"ANONYMIZE", "IP,DST_IP,MAP");
's avatar
committed
1108 1109

	//replace with zero, tcp and ip options
's avatar
committed
1110 1111
	mapi_apply_function(fd,"ANONYMIZE", "IP,OPTIONS,ZERO");
	mapi_apply_function(fd,"ANONYMIZE", "TCP,TCP_OPTIONS,ZERO");
's avatar
committed
1112 1113

	//remove payload
's avatar
committed
1114
	mapi_apply_function(fd,"ANONYMIZE", "TCP,PAYLOAD,STRIP,0");
's avatar
committed
1115
	//checksum fix in IP fixes checksums in TCP and UDP as well
's avatar
committed
1116
	mapi_apply_function(fd,"ANONYMIZE", "IP,CHECKSUM,CHECKSUM_ADJUST");
's avatar
committed
1117
	fid = mapi_apply_function(fd, "TO_BUFFER");
's avatar
committed
1118 1119 1120

	/* connect to the flow */
	connect_status = mapi_connect(fd);
's avatar
committed
1121
	if(connect_status < 0) {
's avatar
committed
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
		printf("Connect failed");
		exit(0);
	}

	while(1) {     /* forever, wait for matching packets */
		
		pkt = mapi_get_next_pkt(fd, fid);
		printf("\nAnonymized tcp packet captured!\n");
		print_IP_pkt(pkt);
	}

	return 0;
's avatar
committed
1134
}
's avatar
committed
1135 1136 1137 1138 1139
\end{Verbatim}


In the above example, we create a network flow that captures only tcp packets. Then we apply anonymization
on IP addresses, TCP/IP options, TCP payload and finally we fix TCP/IP checksums. A complete list of
's avatar
committed
1140 1141 1142 1143 1144
protocols and anonymization functions supported
is provided in the {\tt anonflib} man page, included in
Appendix~\ref{sec:mananonflib}.
The listing of the {\tt print\_IP\_pkt()} function
is included in Appendix~\ref{sec:misccode}.
's avatar
committed
1145 1146
For this example, the \textit{anonflib} library should be used.
So, MAPI should be configured with \textit{--enable-anonflib}.
's avatar
committed
1147

's avatar
committed
1148

1149

's avatar
committed
1150 1151 1152 1153 1154 1155 1156
\appendix

\newpage
\section{MAPI man page}
\label{sec:manpage}

\begin{scriptsize}
's avatar
committed
1157
\input{man_mapi}
's avatar
committed
1158 1159 1160
\end{scriptsize}

\newpage
's avatar
committed
1161 1162
\section{MAPI {\tt stdflib} man page}
\label{sec:manstdflib}
's avatar
committed
1163 1164

\begin{scriptsize}
's avatar
committed
1165 1166
\input{man_mapi_stdflib}
\end{scriptsize}
's avatar
committed
1167

1168 1169 1170 1171 1172 1173 1174 1175
\newpage
\section{MAPI {\tt extraflib} man page}
\label{sec:manextraflib}

\begin{scriptsize}
\input{man_mapi_extraflib}
\end{scriptsize}

's avatar
committed
1176 1177 1178
\newpage
\section{MAPI {\tt trackflib} man page}
\label{sec:mantrackflib}
's avatar
committed
1179

's avatar
committed
1180 1181
\begin{scriptsize}
\input{man_mapi_trackflib}
's avatar
committed
1182 1183
\end{scriptsize}

's avatar
committed
1184 1185 1186
\newpage
\section{MAPI {\tt anonflib} man page}
\label{sec:mananonflib}
's avatar
committed
1187

's avatar
committed
1188 1189 1190
\begin{scriptsize}
\input{man_mapi_anonflib}
\end{scriptsize}
's avatar
committed
1191 1192 1193 1194

\section{{\tt print\_IP\_pkt()} listing}
\label{sec:misccode}

's avatar
committed
1195
\begin{Verbatim}[numbersep=12pt, numbers=left, baselinestretch=1.0, fontsize=\small]
's avatar
committed
1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
void print_IP_pkt(struct mapipkt *rec) {
    
    int i;
    unsigned char *p;
    struct ether_header *eth;
    struct iphdr *iph;
    
    p = &(rec->pkt);
    eth = (struct ether_header *)p;

    /* print MAC addresses */
    for(i=0; i<ETH_ALEN; i++) {
        printf("%.2X", eth->ether_shost[i]);
        if(i != 5) printf(":");
    }       
    printf(" -> ");
    for(i=0; i<ETH_ALEN; i++){ 
        printf("%.2X", eth->ether_dhost[i]); 
        if(i != 5) printf(":");
    }
    
    /* make sure that this is indeed an IP packet */
    if (ntohs(eth->ether_type) != ETHERTYPE_IP) {
        printf("print_IP_pkt(): Not an IP packet\n");
        return;
    }

    /* lay the IP header struct over the packet data */
    iph = (struct iphdr *)(p + ETH_HLEN);
    
    printf("\n%s -> ", inet_ntoa(*(struct in_addr *)&(iph->saddr)));
    printf("%s\n", inet_ntoa(*(struct in_addr *)&(iph->daddr)));
}
\end{Verbatim}

's avatar
committed
1231 1232


's avatar
committed
1233
\end{document}