aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYING165
-rw-r--r--ChangeLog16
-rw-r--r--INSTALL365
-rw-r--r--Makefile.am8
-rw-r--r--README.md59
-rw-r--r--README.protocols18
-rwxr-xr-xautogen.sh7
-rw-r--r--configure.ac84
-rw-r--r--doc/nDPI_QuickStartGuide.pagesbin0 -> 157979 bytes
-rw-r--r--doc/nDPI_QuickStartGuide.pdfbin0 -> 146256 bytes
-rw-r--r--example/Makefile.am12
-rw-r--r--example/Win32/pcapExample.sln20
-rw-r--r--example/Win32/pcapExample.suobin0 -> 306688 bytes
-rw-r--r--example/Win32/pcapExample/pcapExample.cpp11
-rw-r--r--example/Win32/pcapExample/pcapExample.vcxproj230
-rw-r--r--example/Win32/pcapExample/pcapExample.vcxproj.filters462
-rw-r--r--example/Win32/pcapExample/pcapExample.vcxproj.user3
-rw-r--r--example/ndpiReader.c1788
-rw-r--r--example/protos.txt18
l---------lib1
-rw-r--r--libndpi.pc.in10
-rw-r--r--libndpi.sym27
-rw-r--r--m4/ax_pthread.m4332
-rw-r--r--ndpi-netfilter/README4
-rw-r--r--packages/homebrew/README11
-rw-r--r--packages/homebrew/ndpi.rb23
-rw-r--r--packages/ubuntu/Makefile42
-rw-r--r--packages/ubuntu/Makefile.in42
-rwxr-xr-xpackages/ubuntu/configure2863
-rw-r--r--packages/ubuntu/configure.in32
-rw-r--r--packages/ubuntu/debian/COPYRIGHT340
-rw-r--r--packages/ubuntu/debian/README2
-rw-r--r--packages/ubuntu/debian/changelog.in4
-rw-r--r--packages/ubuntu/debian/compat1
-rw-r--r--packages/ubuntu/debian/conffiles0
-rw-r--r--packages/ubuntu/debian/control.in28
-rw-r--r--packages/ubuntu/debian/dirs1
-rw-r--r--packages/ubuntu/debian/docs1
-rw-r--r--packages/ubuntu/debian/files.in1
-rwxr-xr-xpackages/ubuntu/debian/postinst34
-rw-r--r--packages/ubuntu/debian/postrm13
-rw-r--r--packages/ubuntu/debian/preinst35
-rwxr-xr-xpackages/ubuntu/debian/prerm14
-rwxr-xr-xpackages/ubuntu/debian/rules59
-rw-r--r--src/include/Makefile.am9
-rw-r--r--src/include/linux_compat.h188
-rw-r--r--src/include/ndpi_api.h242
-rw-r--r--src/include/ndpi_define.h309
-rw-r--r--src/include/ndpi_main.h156
-rw-r--r--src/include/ndpi_protocol_ids.h244
-rw-r--r--src/include/ndpi_protocols.h181
-rw-r--r--src/include/ndpi_typedefs.h852
-rw-r--r--src/include/ndpi_unix.h53
-rw-r--r--src/include/ndpi_win32.h73
-rw-r--r--src/lib/Makefile.am158
-rw-r--r--src/lib/ndpi_content_match.c.inc7410
-rw-r--r--src/lib/ndpi_main.c5706
-rw-r--r--src/lib/protocols/afp.c75
-rw-r--r--src/lib/protocols/aimini.c283
-rw-r--r--src/lib/protocols/applejuice.c57
-rw-r--r--src/lib/protocols/armagetron.c102
-rw-r--r--src/lib/protocols/attic/flash.c93
-rw-r--r--src/lib/protocols/attic/ftp.c469
-rw-r--r--src/lib/protocols/attic/manolito.c180
-rw-r--r--src/lib/protocols/attic/popo.c86
-rw-r--r--src/lib/protocols/attic/secondlife.c123
-rw-r--r--src/lib/protocols/ayiya.c67
-rw-r--r--src/lib/protocols/battlefield.c118
-rw-r--r--src/lib/protocols/bgp.c57
-rw-r--r--src/lib/protocols/bittorrent.c469
-rw-r--r--src/lib/protocols/btlib.c509
-rw-r--r--src/lib/protocols/btlib.h147
-rw-r--r--src/lib/protocols/ciscovpn.c70
-rw-r--r--src/lib/protocols/citrix.c93
-rw-r--r--src/lib/protocols/collectd.c53
-rw-r--r--src/lib/protocols/corba.c48
-rw-r--r--src/lib/protocols/crossfire.c85
-rw-r--r--src/lib/protocols/dcerpc.c54
-rw-r--r--src/lib/protocols/dhcp.c60
-rw-r--r--src/lib/protocols/dhcpv6.c60
-rw-r--r--src/lib/protocols/directconnect.c474
-rw-r--r--src/lib/protocols/directdownloadlink.c737
-rw-r--r--src/lib/protocols/dns.c300
-rw-r--r--src/lib/protocols/dofus.c149
-rw-r--r--src/lib/protocols/dropbox.c77
-rw-r--r--src/lib/protocols/edonkey.c211
-rw-r--r--src/lib/protocols/fasttrack.c82
-rw-r--r--src/lib/protocols/fiesta.c97
-rw-r--r--src/lib/protocols/filetopia.c83
-rw-r--r--src/lib/protocols/florensia.c122
-rw-r--r--src/lib/protocols/ftp_control.c999
-rw-r--r--src/lib/protocols/ftp_data.c275
-rw-r--r--src/lib/protocols/gnutella.c375
-rw-r--r--src/lib/protocols/gtp.c85
-rw-r--r--src/lib/protocols/guildwars.c71
-rw-r--r--src/lib/protocols/h323.c97
-rw-r--r--src/lib/protocols/halflife2_and_mods.c65
-rw-r--r--src/lib/protocols/http.c981
-rw-r--r--src/lib/protocols/http_activesync.c54
-rw-r--r--src/lib/protocols/iax.c94
-rw-r--r--src/lib/protocols/icecast.c91
-rw-r--r--src/lib/protocols/imesh.c294
-rw-r--r--src/lib/protocols/ipp.c112
-rw-r--r--src/lib/protocols/irc.c804
-rw-r--r--src/lib/protocols/jabber.c311
-rw-r--r--src/lib/protocols/kerberos.c82
-rw-r--r--src/lib/protocols/kontiki.c65
-rw-r--r--src/lib/protocols/ldap.c101
-rw-r--r--src/lib/protocols/lotus_notes.c87
-rw-r--r--src/lib/protocols/mail_imap.c293
-rw-r--r--src/lib/protocols/mail_pop.c204
-rw-r--r--src/lib/protocols/mail_smtp.c180
-rw-r--r--src/lib/protocols/maplestory.c87
-rw-r--r--src/lib/protocols/mdns.c146
-rw-r--r--src/lib/protocols/meebo.c165
-rw-r--r--src/lib/protocols/megaco.c49
-rw-r--r--src/lib/protocols/mgcp.c102
-rw-r--r--src/lib/protocols/mms.c80
-rw-r--r--src/lib/protocols/msn.c563
-rw-r--r--src/lib/protocols/mssql.c61
-rw-r--r--src/lib/protocols/mysql.c70
-rw-r--r--src/lib/protocols/netbios.c368
-rw-r--r--src/lib/protocols/netflow.c93
-rw-r--r--src/lib/protocols/nfs.c86
-rw-r--r--src/lib/protocols/noe.c52
-rw-r--r--src/lib/protocols/non_tcp_udp.c108
-rw-r--r--src/lib/protocols/ntp.c68
-rw-r--r--src/lib/protocols/openft.c56
-rw-r--r--src/lib/protocols/openvpn.c69
-rw-r--r--src/lib/protocols/oracle.c62
-rw-r--r--src/lib/protocols/oscar.c273
-rw-r--r--src/lib/protocols/pando.c157
-rw-r--r--src/lib/protocols/pcanywhere.c55
-rw-r--r--src/lib/protocols/postgres.c120
-rw-r--r--src/lib/protocols/pplive.c220
-rw-r--r--src/lib/protocols/ppstream.c105
-rw-r--r--src/lib/protocols/pptp.c61
-rw-r--r--src/lib/protocols/qq.c665
-rw-r--r--src/lib/protocols/quake.c91
-rw-r--r--src/lib/protocols/radius.c76
-rw-r--r--src/lib/protocols/rdp.c56
-rw-r--r--src/lib/protocols/redis.c92
-rw-r--r--src/lib/protocols/rsync.c56
-rw-r--r--src/lib/protocols/rtcp.c52
-rw-r--r--src/lib/protocols/rtmp.c92
-rw-r--r--src/lib/protocols/rtp.c325
-rw-r--r--src/lib/protocols/rtsp.c120
-rw-r--r--src/lib/protocols/sflow.c49
-rw-r--r--src/lib/protocols/shoutcast.c107
-rw-r--r--src/lib/protocols/sip.c200
-rw-r--r--src/lib/protocols/skinny.c63
-rw-r--r--src/lib/protocols/skype.c122
-rw-r--r--src/lib/protocols/smb.c57
-rw-r--r--src/lib/protocols/snmp.c126
-rw-r--r--src/lib/protocols/socks4.c96
-rw-r--r--src/lib/protocols/socks5.c92
-rw-r--r--src/lib/protocols/socrates.c80
-rw-r--r--src/lib/protocols/sopcast.c219
-rw-r--r--src/lib/protocols/soulseek.c286
-rw-r--r--src/lib/protocols/spotify.c128
-rw-r--r--src/lib/protocols/ssdp.c70
-rw-r--r--src/lib/protocols/ssh.c68
-rw-r--r--src/lib/protocols/ssl.c637
-rw-r--r--src/lib/protocols/stealthnet.c58
-rw-r--r--src/lib/protocols/steam.c286
-rw-r--r--src/lib/protocols/stun.c188
-rw-r--r--src/lib/protocols/syslog.c130
-rw-r--r--src/lib/protocols/tcp_udp.c78
-rw-r--r--src/lib/protocols/tds.c91
-rw-r--r--src/lib/protocols/teamspeak.c65
-rw-r--r--src/lib/protocols/teamviewer.c100
-rw-r--r--src/lib/protocols/telegram.c68
-rw-r--r--src/lib/protocols/telnet.c107
-rw-r--r--src/lib/protocols/tftp.c70
-rw-r--r--src/lib/protocols/thunder.c211
-rw-r--r--src/lib/protocols/tor.c109
-rw-r--r--src/lib/protocols/tvants.c78
-rw-r--r--src/lib/protocols/tvuplayer.c153
-rw-r--r--src/lib/protocols/twitter.c63
-rw-r--r--src/lib/protocols/usenet.c105
-rw-r--r--src/lib/protocols/veohtv.c116
-rw-r--r--src/lib/protocols/vhua.c68
-rw-r--r--src/lib/protocols/viber.c48
-rw-r--r--src/lib/protocols/vmware.c45
-rw-r--r--src/lib/protocols/vnc.c67
-rw-r--r--src/lib/protocols/warcraft3.c100
-rw-r--r--src/lib/protocols/whoisdas.c60
-rw-r--r--src/lib/protocols/winmx.c104
-rw-r--r--src/lib/protocols/world_of_kung_fu.c58
-rw-r--r--src/lib/protocols/world_of_warcraft.c210
-rw-r--r--src/lib/protocols/xbox.c103
-rw-r--r--src/lib/protocols/xdmcp.c69
-rw-r--r--src/lib/protocols/yahoo.c434
-rw-r--r--src/lib/protocols/zattoo.c235
-rw-r--r--src/lib/protocols/zmq.c100
-rw-r--r--src/lib/third_party/include/actypes.h135
-rw-r--r--src/lib/third_party/include/ahocorasick.h69
-rw-r--r--src/lib/third_party/include/node.h66
-rw-r--r--src/lib/third_party/include/patricia.h302
-rw-r--r--src/lib/third_party/include/sort.h6
-rw-r--r--src/lib/third_party/src/ahocorasick.c391
-rw-r--r--src/lib/third_party/src/node.c260
-rw-r--r--src/lib/third_party/src/patricia.c1076
-rw-r--r--src/lib/third_party/src/sort.c130
204 files changed, 47689 insertions, 1 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 000000000..cca7fc278
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 000000000..9bd7818c0
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,16 @@
+2014-03-21:
+- improved support for eDonkey/eMule/Kademlia
+- improved support for PPLive
+
+2014-03-20:
+- code optimizations
+- consistency improvements
+- added support for new applications: Pando Media Booster
+- improved support for Steam
+- added support for new web services: Wikipedia, MSN, Amazon, eBay, CNN
+
+2014-03-19:
+- added new protocols: FTP, code improvements
+
+2014-03-17:
+- added new protocols: SOCKSv4, SOCKSv5, RTMP
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 000000000..7d1c323be
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,365 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved. This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+ Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package. Some packages provide this
+`INSTALL' file but do not implement all of the features documented
+below. The lack of an optional feature in a given package is not
+necessarily a bug. More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+ The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package, generally using the just-built uninstalled binaries.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation. When installing into a prefix owned by root, it is
+ recommended that the package be configured and built as a regular
+ user, and only the `make install' phase executed with root
+ privileges.
+
+ 5. Optionally, type `make installcheck' to repeat any self-tests, but
+ this time using the binaries in their final installed location.
+ This target does not install anything. Running this target as a
+ regular user, particularly if the prior `make install' required
+ root privileges, verifies that the installation completed
+ correctly.
+
+ 6. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 7. Often, you can also type `make uninstall' to remove the installed
+ files again. In practice, not all packages have tested that
+ uninstallation works correctly, even though it is required by the
+ GNU Coding Standards.
+
+ 8. Some packages, particularly those that use Automake, provide `make
+ distcheck', which can by used by developers to test that all other
+ targets like `make install' and `make uninstall' work correctly.
+ This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'. This
+is known as a "VPATH" build.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+ On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them. In general, the
+default for these options is expressed in terms of `${prefix}', so that
+specifying just `--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+ The most portable way to affect installation locations is to pass the
+correct locations to `configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+`make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+ The first method involves providing an override variable for each
+affected directory. For example, `make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+`${prefix}'. Any directories that were specified during `configure',
+but not in terms of `${prefix}', must each be overridden at install
+time for the entire installation to be relocated. The approach of
+makefile variable overrides for each directory variable is required by
+the GNU Coding Standards, and ideally causes no recompilation.
+However, some platforms have known limitations with the semantics of
+shared libraries that end up requiring recompilation when using this
+method, particularly noticeable in packages that use GNU Libtool.
+
+ The second method involves providing the `DESTDIR' variable. For
+example, `make install DESTDIR=/alternate/directory' will prepend
+`/alternate/directory' before all installation names. The approach of
+`DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters. On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of `${prefix}'
+at `configure' time.
+
+Optional Features
+=================
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+ Some packages offer the ability to configure how verbose the
+execution of `make' will be. For these packages, running `./configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with `make V=1'; while running `./configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with `make V=0'.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file. The option `-nodtk' can be used as
+a workaround. If GNU CC is not installed, it is therefore recommended
+to try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+ On Solaris, don't put `/usr/ucb' early in your `PATH'. This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+ On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'. It is recommended to use the following options:
+
+ ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+ Print a summary of the options unique to this package's
+ `configure', and exit. The `short' variant lists options used
+ only in the top level, while the `recursive' variant lists options
+ also present in any nested packages.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+ Use DIR as the installation prefix. *note Installation Names::
+ for more details, including other options available for fine-tuning
+ the installation locations.
+
+`--no-create'
+`-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 000000000..80258e773
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,8 @@
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = src/lib example
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libndpi.pc
+
+EXTRA_DIST = libndpi.sym autogen.sh
diff --git a/README.md b/README.md
index 4d0b1c616..d2bc89259 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,58 @@
-# ndpi
+This directory contains a modified version of OpenDPI which
+includes ntop extensions. I have tried to push them into the
+OpenDPI source tree but nobody in answering emails so I have
+decided to create my own source tree
+
+==========
+
+In order to compile this library do
+
+# ./autogen.sh
+# ./configure
+# make
+
+Please note that the pre-requisites for compilation include:
+- GNU tools (autogen, automake, autoconf, libtool)
+- GNU C compiler (gcc)
+
+==========
+
+The entire procedure of adding new protocols in detail:
+
+1. Add new protocol together with its unique ID to:
+src/include/ndpi_protocols_osdpi.h
+
+2. Create a new protocol in:
+src/lib/protocols/
+
+3. Variables to be kept for the duration of the entire flow (as state variables) needs to be placed in:
+/include/ndpi_structs.h
+in ndpi_flow_tcp_struct (for TCP only), ndpi_flow_udp_struct (for UDP only), or ndpi_flow_struct (for both).
+
+4. Add a new entry for the search function for the new protocol in:
+src/include/ndpi_protocols.h
+
+5. Choose (do not change anything) a selection bitmask from:
+src/include/ndpi_define.h
+
+6. Add a new entry in ndpi_set_protocol_detection_bitmask2 in:
+src/lib/ndpi_main.c
+
+7. Set protocol default ports in ndpi_init_protocol_defaults in:
+src/lib/ndpi_main.c
+
+8. Add the new protocol file to:
+src/lib/Makefile.am
+
+9. ./autogen.sh
+10. ./configure
+11. make
+
+==========
+
+If you want to distribute a source tar file of nDPI do:
+
+# make dist
+
+--------------------------
+April 2015 - ntop \ No newline at end of file
diff --git a/README.protocols b/README.protocols
new file mode 100644
index 000000000..27d8c6408
--- /dev/null
+++ b/README.protocols
@@ -0,0 +1,18 @@
+Tor
+---
+
+Tor protocol can use SSL to hide itself. These are examples:
+
+TCP 37.128.208.46:9001 <-> 172.16.253.130:2078 [VLAN: 0][proto: 91/SSL][132 pkts/93834 bytes][SSL client: www.jwrpsthzrih.com]
+TCP 172.16.253.130:2021 <-> 75.147.140.249:443 [VLAN: 0][proto: 91/SSL][28 pkts/8053 bytes][SSL client: www.5akw23dx.com]
+TCP 172.16.253.130:2077 <-> 77.247.181.163:443 [VLAN: 0][proto: 91/SSL][136 pkts/94329 bytes][SSL client: www.fk4pprq42hsvl2wey.com]
+
+It can be detected by analyzing the SSL client certificate and checking the name that does not match to a real host in
+addition of begin a bit weird. As doing DNS resolution is not a task for nDPI we let applications do and then recognize
+SSL-tunnelled connections.
+
+See http://www.netresec.com/?page=Blog&month=2013-04&post=Detecting-TOR-Communication-in-Network-Traffic
+
+For this reason nDPI uses a heuristic, non-DNS based, approach to detect tor communications. If possible, apps
+should validate the certificate using the DNS. This is not something nDPI can afford to do for performance
+reasons
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 000000000..9853e65ef
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+#
+# 1.5.1 r8171 06/09/2014
+#
+autoreconf -ivf
+./configure
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 000000000..b5079143f
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,84 @@
+AC_INIT([libndpi], [1.5.2])
+
+AC_CONFIG_MACRO_DIR([m4])
+
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+
+LT_INIT
+
+AC_PROG_CC
+AX_PTHREAD
+
+if test -d ".svn"; then :
+SVN_RELEASE=`svn info . | grep "^Revision"|cut -d " " -f 2`
+SVN_DATE=`svn info . | grep "^Last Changed Date"|cut -d " " -f 4-`
+else
+SVN_RELEASE="${PACKAGE_VERSION}"
+SVN_DATE=`date`
+fi
+
+AC_DEFINE_UNQUOTED(NDPI_SVN_RELEASE, "r${SVN_RELEASE}", [SVN Release])
+AC_DEFINE_UNQUOTED(NDPI_SVN_DATE, "${SVN_DATE}", [Last SVN change])
+
+AC_CHECK_HEADERS([netinet/in.h stdint.h stdlib.h string.h unistd.h])
+
+PCAP_HOME=$HOME/PF_RING/userland
+
+if test -d $PCAP_HOME; then :
+ echo -n ""
+else
+ PCAP_HOME=`pwd`/../../PF_RING/userland
+fi
+
+SHORT_MACHINE=`uname -m | cut -b1-3`
+if test $SHORT_MACHINE = "arm"; then
+LIBNUMA=""
+else
+LIBNUMA="-lnuma"
+fi
+
+if test -f $PCAP_HOME/libpcap/libpcap.a; then :
+ echo "Using libpcap from $PCAP_HOME"
+ PCAP_INC="-I $PCAP_HOME/libpcap"
+ PCAP_LIB="$PCAP_HOME/libpcap/libpcap.a $PCAP_HOME/lib/libpfring.a $LIBNUMA"
+
+ AC_CHECK_LIB([rt], [clock_gettime], [PCAP_LIB="$PCAP_LIB -lrt"])
+ AC_CHECK_LIB([nl], [nl_handle_alloc], [PCAP_LIB="$PCAP_LIB -lnl"])
+else
+ AC_CHECK_LIB([pcap], [pcap_open_live], [PCAP_LIB="-lpcap"])
+
+ if test $ac_cv_lib_pcap_pcap_open_live = "no"; then :
+ echo ""
+ echo "ERROR: Missing libpcap(-dev) library required to compile the example application"
+ echo "ERROR: Please install it and try again"
+ exit
+ fi
+fi
+
+if test -d /usr/local/include/json-c/; then :
+ CFLAGS="$CFLAGS -I/usr/local/include/json-c/"
+ LDFLAGS="$LDFLAGS -L/usr/local/lib -ljson-c"
+else
+ CFLAGS="$CFLAGS $(pkg-config --cflags json-c)"
+ LDFLAGS="$LDFLAGS $(pkg-config --libs json-c)"
+fi
+
+OLD_LIBS=$LIBS
+LIBS="-L/opt/napatech3/lib $LIBS"
+AC_CHECK_LIB([ntapi],
+ [NT_Init],
+ [PCAP_LIB="$PCAP_LIB -L/opt/napatech3/lib -lntapi"],
+ [], [] )
+LIBS=$OLD_LIBS
+
+AC_CHECK_LIB(json-c, json_object_new_object, AC_DEFINE_UNQUOTED(HAVE_JSON_C, 1, [The JSON-C library is present]))
+
+AC_CONFIG_FILES([Makefile src/lib/Makefile example/Makefile libndpi.pc])
+AC_CONFIG_HEADERS(config.h)
+AC_SUBST(SVN_RELEASE)
+AC_SUBST(SVN_DATE)
+AC_SUBST(JSON_C_LIB)
+AC_SUBST(PCAP_INC)
+AC_SUBST(PCAP_LIB)
+
+AC_OUTPUT
diff --git a/doc/nDPI_QuickStartGuide.pages b/doc/nDPI_QuickStartGuide.pages
new file mode 100644
index 000000000..e2313a184
--- /dev/null
+++ b/doc/nDPI_QuickStartGuide.pages
Binary files differ
diff --git a/doc/nDPI_QuickStartGuide.pdf b/doc/nDPI_QuickStartGuide.pdf
new file mode 100644
index 000000000..f29be2a91
--- /dev/null
+++ b/doc/nDPI_QuickStartGuide.pdf
Binary files differ
diff --git a/example/Makefile.am b/example/Makefile.am
new file mode 100644
index 000000000..f98bae9ae
--- /dev/null
+++ b/example/Makefile.am
@@ -0,0 +1,12 @@
+bin_PROGRAMS = ndpiReader
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/include @PCAP_INC@
+AM_CFLAGS = @PTHREAD_CFLAGS@
+
+LDADD = $(top_builddir)/src/lib/libndpi.la @JSON_C_LIB@ @PTHREAD_LIBS@ @PCAP_LIB@
+AM_LDFLAGS = -static
+
+ndpiReader_SOURCES = ndpiReader.c
+
+ndpiReader.o: ndpiReader.c
+
diff --git a/example/Win32/pcapExample.sln b/example/Win32/pcapExample.sln
new file mode 100644
index 000000000..3c061ed01
--- /dev/null
+++ b/example/Win32/pcapExample.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcapExample", "pcapExample\pcapExample.vcxproj", "{F6A2C0AE-2110-438A-87E4-7C1CFCE064C6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F6A2C0AE-2110-438A-87E4-7C1CFCE064C6}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F6A2C0AE-2110-438A-87E4-7C1CFCE064C6}.Debug|Win32.Build.0 = Debug|Win32
+ {F6A2C0AE-2110-438A-87E4-7C1CFCE064C6}.Release|Win32.ActiveCfg = Release|Win32
+ {F6A2C0AE-2110-438A-87E4-7C1CFCE064C6}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/example/Win32/pcapExample.suo b/example/Win32/pcapExample.suo
new file mode 100644
index 000000000..122e224b4
--- /dev/null
+++ b/example/Win32/pcapExample.suo
Binary files differ
diff --git a/example/Win32/pcapExample/pcapExample.cpp b/example/Win32/pcapExample/pcapExample.cpp
new file mode 100644
index 000000000..ad7655eea
--- /dev/null
+++ b/example/Win32/pcapExample/pcapExample.cpp
@@ -0,0 +1,11 @@
+// pcapExample.cpp : Defines the entry point for the console application.
+//
+
+#include "stdafx.h"
+
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ return 0;
+}
+
diff --git a/example/Win32/pcapExample/pcapExample.vcxproj b/example/Win32/pcapExample/pcapExample.vcxproj
new file mode 100644
index 000000000..2b86797bd
--- /dev/null
+++ b/example/Win32/pcapExample/pcapExample.vcxproj
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F6A2C0AE-2110-438A-87E4-7C1CFCE064C6}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>pcapExample</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>C:\ntop\nprobe\nprobe-win-32;C:\ntop\winpcap\Include;C:\ntop\dependencies\nDPI\src\lib\third_party\include;C:\ntop\dependencies\nDPI\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>Wsock32.lib;Ws2_32.lib;C:\ntop\winpcap\Lib\Packet.lib;C:\ntop\winpcap\Lib\wpcap.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\..\nprobe\nprobe-win-32\getopt.c" />
+ <ClCompile Include="..\..\..\..\..\nprobe\nprobe-win-32\getopt1.c" />
+ <ClCompile Include="..\..\..\src\lib\ndpi_main.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\afp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\aimini.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\applejuice.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\armagetron.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\battlefield.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\bgp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\bittorrent.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\ciscovpn.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\citrix.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\corba.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\crossfire.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\dcerpc.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\dhcp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\dhcpv6.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\directconnect.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\directdownloadlink.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\dns.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\dofus.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\dropbox.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\edonkey.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\fasttrack.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\feidian.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\fiesta.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\filetopia.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\flash.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\florensia.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\ftp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\gadu_gadu.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\gnutella.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\gtp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\guildwars.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\h323.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\halflife2_and_mods.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\http.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\http_activesync.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\i23v5.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\iax.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\icecast.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\imesh.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\ipp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\irc.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\jabber.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\kerberos.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\kontiki.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\ldap.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\lotus_notes.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\mail_imap.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\mail_pop.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\mail_smtp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\maplestory.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\mdns.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\meebo.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\mgcp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\mms.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\msn.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\mssql.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\mysql.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\netbios.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\netflow.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\nfs.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\noe.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\non_tcp_udp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\ntp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\openft.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\openvpn.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\oracle.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\oscar.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\pando.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\pcanywhere.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\popo.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\postgres.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\pplive.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\ppstream.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\pptp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\qq.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\quake.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\radius.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\rdp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\rsync.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\rtcp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\rtp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\rtsp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\sflow.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\shoutcast.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\sip.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\skinny.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\skype.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\smb.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\snmp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\socrates.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\sopcast.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\soulseek.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\spotify.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\ssdp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\ssh.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\ssl.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\stealthnet.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\steam.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\stun.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\syslog.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\tcp_udp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\tds.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\teamspeak.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\teamviewer.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\telnet.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\tftp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\thunder.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\tor.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\tvants.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\tvuplayer.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\usenet.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\veohtv.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\viber.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\vmware.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\vnc.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\warcraft3.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\winmx.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\world_of_kung_fu.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\world_of_warcraft.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\xbox.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\xdmcp.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\yahoo.c" />
+ <ClCompile Include="..\..\..\src\lib\protocols\zattoo.c" />
+ <ClCompile Include="..\..\..\src\lib\third_party\src\ahocorasick.c" />
+ <ClCompile Include="..\..\..\src\lib\third_party\src\node.c" />
+ <ClCompile Include="..\..\..\src\lib\third_party\src\sort.c" />
+ <ClCompile Include="..\..\pcapReader.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\..\..\nprobe\nprobe-win-32\getopt.h" />
+ <ClInclude Include="..\..\..\src\include\linux_compat.h" />
+ <ClInclude Include="..\..\..\src\include\ndpi_api.h" />
+ <ClInclude Include="..\..\..\src\include\ndpi_debug_functions.h" />
+ <ClInclude Include="..\..\..\src\include\ndpi_define.h" />
+ <ClInclude Include="..\..\..\src\include\ndpi_macros.h" />
+ <ClInclude Include="..\..\..\src\include\ndpi_main.h" />
+ <ClInclude Include="..\..\..\src\include\ndpi_protocols.h" />
+ <ClInclude Include="..\..\..\src\include\ndpi_protocols_osdpi.h" />
+ <ClInclude Include="..\..\..\src\include\ndpi_protocol_history.h" />
+ <ClInclude Include="..\..\..\src\include\ndpi_public_functions.h" />
+ <ClInclude Include="..\..\..\src\include\ndpi_structs.h" />
+ <ClInclude Include="..\..\..\src\include\ndpi_utils.h" />
+ <ClInclude Include="..\..\..\src\lib\third_party\include\actypes.h" />
+ <ClInclude Include="..\..\..\src\lib\third_party\include\ahocorasick.h" />
+ <ClInclude Include="..\..\..\src\lib\third_party\include\node.h" />
+ <ClInclude Include="..\..\..\src\lib\third_party\include\sort.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/example/Win32/pcapExample/pcapExample.vcxproj.filters b/example/Win32/pcapExample/pcapExample.vcxproj.filters
new file mode 100644
index 000000000..394d9dc7a
--- /dev/null
+++ b/example/Win32/pcapExample/pcapExample.vcxproj.filters
@@ -0,0 +1,462 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\pcapReader.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\ndpi_main.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\zattoo.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\afp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\aimini.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\applejuice.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\armagetron.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\battlefield.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\bgp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\bittorrent.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\ciscovpn.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\citrix.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\corba.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\crossfire.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\dcerpc.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\dhcp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\dhcpv6.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\directconnect.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\directdownloadlink.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\dns.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\dofus.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\dropbox.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\edonkey.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\fasttrack.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\feidian.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\fiesta.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\filetopia.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\flash.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\florensia.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\ftp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\gadu_gadu.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\gnutella.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\gtp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\guildwars.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\h323.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\halflife2_and_mods.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\http.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\http_activesync.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\i23v5.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\iax.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\icecast.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\imesh.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\ipp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\irc.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\jabber.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\kerberos.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\kontiki.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\ldap.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\lotus_notes.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\mail_imap.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\mail_pop.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\mail_smtp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\maplestory.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\mdns.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\meebo.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\mgcp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\mms.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\msn.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\mssql.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\mysql.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\netbios.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\netflow.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\nfs.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\noe.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\non_tcp_udp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\ntp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\openft.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\openvpn.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\oracle.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\oscar.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\pando.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\pcanywhere.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\popo.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\postgres.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\pplive.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\ppstream.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\pptp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\qq.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\quake.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\radius.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\rdp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\rsync.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\rtcp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\rtp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\rtsp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\sflow.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\shoutcast.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\sip.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\skinny.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\skype.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\smb.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\snmp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\socrates.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\sopcast.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\soulseek.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\spotify.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\ssdp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\ssh.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\ssl.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\stealthnet.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\steam.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\stun.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\syslog.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\tcp_udp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\tds.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\teamspeak.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\teamviewer.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\telnet.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\tftp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\thunder.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\tor.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\tvants.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\tvuplayer.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\usenet.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\veohtv.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\viber.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\vmware.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\vnc.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\warcraft3.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\winmx.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\world_of_kung_fu.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\world_of_warcraft.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\xbox.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\xdmcp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\protocols\yahoo.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\third_party\src\ahocorasick.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\third_party\src\node.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\lib\third_party\src\sort.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\..\nprobe\nprobe-win-32\getopt.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\..\nprobe\nprobe-win-32\getopt1.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\src\lib\third_party\include\actypes.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\lib\third_party\include\ahocorasick.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\lib\third_party\include\node.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\lib\third_party\include\sort.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\ndpi_api.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\ndpi_debug_functions.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\ndpi_define.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\ndpi_macros.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\ndpi_main.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\ndpi_protocol_history.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\ndpi_protocols.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\ndpi_protocols_osdpi.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\ndpi_public_functions.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\ndpi_structs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\ndpi_utils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\include\linux_compat.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\..\nprobe\nprobe-win-32\getopt.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/example/Win32/pcapExample/pcapExample.vcxproj.user b/example/Win32/pcapExample/pcapExample.vcxproj.user
new file mode 100644
index 000000000..695b5c78b
--- /dev/null
+++ b/example/Win32/pcapExample/pcapExample.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/example/ndpiReader.c b/example/ndpiReader.c
new file mode 100644
index 000000000..41a4b42ed
--- /dev/null
+++ b/example/ndpiReader.c
@@ -0,0 +1,1788 @@
+/*
+ * ndpiReader.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2014 - Matteo Bogo <matteo.bogo@gmail.com> (JSON support)
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef linux
+#define _GNU_SOURCE
+#include <sched.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef WIN32
+#include <winsock2.h> /* winsock.h is included automatically */
+#include <process.h>
+#include <io.h>
+#include <getopt.h>
+#define getopt getopt____
+#else
+#include <unistd.h>
+#include <netinet/in.h>
+#endif
+#include <string.h>
+#include <stdarg.h>
+#include <search.h>
+#include <pcap.h>
+#include <signal.h>
+#include <pthread.h>
+
+#include "../config.h"
+
+#ifdef HAVE_JSON_C
+#include <json.h>
+#endif
+
+#include "ndpi_api.h"
+
+#include <sys/socket.h>
+
+#define MAX_NUM_READER_THREADS 16
+
+/**
+ * @brief Set main components necessary to the detection
+ * @details TODO
+ */
+static void setupDetection(u_int16_t thread_id);
+
+/**
+ * Client parameters
+ */
+static char *_pcap_file[MAX_NUM_READER_THREADS]; /**< Ingress pcap file/interafaces */
+static FILE *playlist_fp[MAX_NUM_READER_THREADS] = { NULL }; /**< Ingress playlist */
+static char *_bpf_filter = NULL; /**< bpf filter */
+static char *_protoFilePath = NULL; /**< Protocol file path */
+#ifdef HAVE_JSON_C
+static char *_jsonFilePath = NULL; /**< JSON file path */
+#endif
+#ifdef HAVE_JSON_C
+static json_object *jArray_known_flows, *jArray_unknown_flows;
+#endif
+static u_int8_t live_capture = 0, full_http_dissection = 0;
+static u_int8_t undetected_flows_deleted = 0;
+/**
+ * User preferences
+ */
+static u_int8_t enable_protocol_guess = 1, verbose = 0, nDPI_traceLevel = 0, json_flag = 0;
+static u_int16_t decode_tunnels = 0;
+static u_int16_t num_loops = 1;
+static u_int8_t shutdown_app = 0;
+static u_int8_t num_threads = 1;
+static u_int32_t current_ndpi_memory = 0, max_ndpi_memory = 0;
+#ifdef linux
+static int core_affinity[MAX_NUM_READER_THREADS];
+#endif
+
+static struct timeval pcap_start, pcap_end;
+
+/**
+ * Detection parameters
+ */
+static u_int32_t detection_tick_resolution = 1000;
+static time_t capture_for = 0;
+static time_t capture_until = 0;
+
+#define IDLE_SCAN_PERIOD 10 /* msec (use detection_tick_resolution = 1000) */
+#define MAX_IDLE_TIME 30000
+#define IDLE_SCAN_BUDGET 1024
+
+#define NUM_ROOTS 512
+
+static u_int32_t num_flows;
+
+struct thread_stats {
+ u_int32_t guessed_flow_protocols;
+ u_int64_t raw_packet_count;
+ u_int64_t ip_packet_count;
+ u_int64_t total_wire_bytes, total_ip_bytes, total_discarded_bytes;
+ u_int64_t protocol_counter[NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS + 1];
+ u_int64_t protocol_counter_bytes[NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS + 1];
+ u_int32_t protocol_flows[NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS + 1];
+ u_int32_t ndpi_flow_count;
+ u_int64_t tcp_count, udp_count;
+ u_int64_t mpls_count, pppoe_count, vlan_count, fragmented_count;
+ u_int64_t packet_len[6];
+ u_int16_t max_packet_len;
+};
+
+struct reader_thread {
+ struct ndpi_detection_module_struct *ndpi_struct;
+ void *ndpi_flows_root[NUM_ROOTS];
+ char _pcap_error_buffer[PCAP_ERRBUF_SIZE];
+ pcap_t *_pcap_handle;
+ u_int64_t last_time;
+ u_int64_t last_idle_scan_time;
+ u_int32_t idle_scan_idx;
+ u_int32_t num_idle_flows;
+ pthread_t pthread;
+ int _pcap_datalink_type;
+
+ /* TODO Add barrier */
+ struct thread_stats stats;
+
+ struct ndpi_flow *idle_flows[IDLE_SCAN_BUDGET];
+};
+
+static struct reader_thread ndpi_thread_info[MAX_NUM_READER_THREADS];
+
+#define GTP_U_V1_PORT 2152
+#define MAX_NDPI_FLOWS 200000000
+/**
+ * @brief ID tracking
+ */
+typedef struct ndpi_id {
+ u_int8_t ip[4]; //< Ip address
+ struct ndpi_id_struct *ndpi_id; //< nDpi worker structure
+} ndpi_id_t;
+
+static u_int32_t size_id_struct = 0; //< ID tracking structure size
+
+#ifndef ETH_P_IP
+#define ETH_P_IP 0x0800
+#endif
+
+// flow tracking
+typedef struct ndpi_flow {
+ u_int32_t lower_ip;
+ u_int32_t upper_ip;
+ u_int16_t lower_port;
+ u_int16_t upper_port;
+ u_int8_t detection_completed, protocol;
+ u_int16_t vlan_id;
+ struct ndpi_flow_struct *ndpi_flow;
+ char lower_name[32], upper_name[32];
+
+ u_int64_t last_seen;
+
+ u_int64_t bytes;
+ u_int32_t packets;
+
+ // result only, not used for flow identification
+ u_int32_t detected_protocol;
+
+ char host_server_name[256];
+
+ struct {
+ char client_certificate[48], server_certificate[48];
+ } ssl;
+
+ void *src_id, *dst_id;
+} ndpi_flow_t;
+
+
+static u_int32_t size_flow_struct = 0;
+
+static void help(u_int long_help) {
+ printf("ndpiReader -i <file|device> [-f <filter>][-s <duration>]\n"
+ " [-p <protos>][-l <loops>[-d][-h][-t][-v <level>]\n"
+ " [-n <threads>] [-j <file>]\n\n"
+ "Usage:\n"
+ " -i <file.pcap|device> | Specify a pcap file/playlist to read packets from or a device for live capture (comma-separated list)\n"
+ " -f <BPF filter> | Specify a BPF filter for filtering selected traffic\n"
+ " -s <duration> | Maximum capture duration in seconds (live traffic capture only)\n"
+ " -p <file>.protos | Specify a protocol file (eg. protos.txt)\n"
+ " -l <num loops> | Number of detection loops (test only)\n"
+ " -n <num threads> | Number of threads. Default: number of interfaces in -i. Ignored with pcap files.\n"
+ " -j <file.json> | Specify a file to write the content of packets in .json format\n"
+#ifdef linux
+ " -g <id:id...> | Thread affinity mask (one core id per thread)\n"
+#endif
+ " -d | Disable protocol guess and use only DPI\n"
+ " -t | Dissect GTP tunnels\n"
+ " -h | This help\n"
+ " -v <1|2> | Verbose 'unknown protocol' packet print. 1=verbose, 2=very verbose\n");
+
+ if(long_help) {
+ printf("\n\nSupported protocols:\n");
+ num_threads = 1;
+ setupDetection(0);
+ ndpi_dump_protocols(ndpi_thread_info[0].ndpi_struct);
+ }
+
+ exit(!long_help);
+}
+
+/* ***************************************************** */
+
+static void parseOptions(int argc, char **argv) {
+ char *__pcap_file = NULL, *bind_mask = NULL;
+ int thread_id, opt;
+#ifdef linux
+ u_int num_cores = sysconf( _SC_NPROCESSORS_ONLN );
+#endif
+
+ while ((opt = getopt(argc, argv, "df:g:i:hp:l:s:tv:V:n:j:")) != EOF) {
+ switch (opt) {
+ case 'd':
+ enable_protocol_guess = 0;
+ break;
+
+ case 'i':
+ _pcap_file[0] = optarg;
+ break;
+
+ case 'f':
+ _bpf_filter = optarg;
+ break;
+
+ case 'g':
+ bind_mask = optarg;
+ break;
+
+ case 'l':
+ num_loops = atoi(optarg);
+ break;
+
+ case 'n':
+ num_threads = atoi(optarg);
+ break;
+
+ case 'p':
+ _protoFilePath = optarg;
+ break;
+
+ case 's':
+ capture_for = atoi(optarg);
+ capture_until = capture_for + time(NULL);
+ break;
+
+ case 't':
+ decode_tunnels = 1;
+ break;
+
+ case 'v':
+ verbose = atoi(optarg);
+ break;
+
+ case 'V':
+ printf("%d\n",atoi(optarg) );
+ nDPI_traceLevel = atoi(optarg);
+ break;
+
+ case 'h':
+ help(1);
+ break;
+
+ case 'j':
+#ifndef HAVE_JSON_C
+ printf("WARNING: this copy of ndpiReader has been compiled without JSON-C: json export disabled\n");
+#else
+ _jsonFilePath = optarg;
+ json_flag = 1;
+#endif
+ break;
+
+ default:
+ help(0);
+ break;
+ }
+ }
+
+ // check parameters
+ if(_pcap_file[0] == NULL || strcmp(_pcap_file[0], "") == 0) {
+ help(0);
+ }
+
+ if(strchr(_pcap_file[0], ',')) { /* multiple ingress interfaces */
+ num_threads = 0; /* setting number of threads = number of interfaces */
+ __pcap_file = strtok(_pcap_file[0], ",");
+ while (__pcap_file != NULL && num_threads < MAX_NUM_READER_THREADS) {
+ _pcap_file[num_threads++] = __pcap_file;
+ __pcap_file = strtok(NULL, ",");
+ }
+ } else {
+ if(num_threads > MAX_NUM_READER_THREADS) num_threads = MAX_NUM_READER_THREADS;
+ for(thread_id = 1; thread_id < num_threads; thread_id++)
+ _pcap_file[thread_id] = _pcap_file[0];
+ }
+
+#ifdef linux
+ for(thread_id = 0; thread_id < num_threads; thread_id++)
+ core_affinity[thread_id] = -1;
+
+ if(num_cores > 1 && bind_mask != NULL) {
+ char *core_id = strtok(bind_mask, ":");
+ thread_id = 0;
+ while (core_id != NULL && thread_id < num_threads) {
+ core_affinity[thread_id++] = atoi(core_id) % num_cores;
+ core_id = strtok(NULL, ":");
+ }
+ }
+#endif
+}
+
+/* ***************************************************** */
+
+static void debug_printf(u_int32_t protocol, void *id_struct,
+ ndpi_log_level_t log_level,
+ const char *format, ...) {
+ va_list va_ap;
+#ifndef WIN32
+ struct tm result;
+#endif
+
+ if(log_level <= nDPI_traceLevel) {
+ char buf[8192], out_buf[8192];
+ char theDate[32];
+ const char *extra_msg = "";
+ time_t theTime = time(NULL);
+
+ va_start (va_ap, format);
+
+ if(log_level == NDPI_LOG_ERROR)
+ extra_msg = "ERROR: ";
+ else if(log_level == NDPI_LOG_TRACE)
+ extra_msg = "TRACE: ";
+ else
+ extra_msg = "DEBUG: ";
+
+ memset(buf, 0, sizeof(buf));
+ strftime(theDate, 32, "%d/%b/%Y %H:%M:%S", localtime_r(&theTime,&result) );
+ vsnprintf(buf, sizeof(buf)-1, format, va_ap);
+
+ snprintf(out_buf, sizeof(out_buf), "%s %s%s", theDate, extra_msg, buf);
+ printf("%s", out_buf);
+ fflush(stdout);
+ }
+
+ va_end(va_ap);
+}
+
+/* ***************************************************** */
+
+static void *malloc_wrapper(unsigned long size) {
+ current_ndpi_memory += size;
+
+ if(current_ndpi_memory > max_ndpi_memory)
+ max_ndpi_memory = current_ndpi_memory;
+
+ return malloc(size);
+}
+
+/* ***************************************************** */
+
+static void free_wrapper(void *freeable) {
+ free(freeable);
+}
+
+/* ***************************************************** */
+
+static char* ipProto2Name(u_short proto_id) {
+ static char proto[8];
+
+ switch(proto_id) {
+ case IPPROTO_TCP:
+ return("TCP");
+ break;
+ case IPPROTO_UDP:
+ return("UDP");
+ break;
+ case IPPROTO_ICMP:
+ return("ICMP");
+ break;
+ case 112:
+ return("VRRP");
+ break;
+ case IPPROTO_IGMP:
+ return("IGMP");
+ break;
+ }
+
+ snprintf(proto, sizeof(proto), "%u", proto_id);
+ return(proto);
+}
+
+/* ***************************************************** */
+
+/*
+ * A faster replacement for inet_ntoa().
+ */
+char* intoaV4(unsigned int addr, char* buf, u_short bufLen) {
+ char *cp, *retStr;
+ uint byte;
+ int n;
+
+ cp = &buf[bufLen];
+ *--cp = '\0';
+
+ n = 4;
+ do {
+ byte = addr & 0xff;
+ *--cp = byte % 10 + '0';
+ byte /= 10;
+ if(byte > 0) {
+ *--cp = byte % 10 + '0';
+ byte /= 10;
+ if(byte > 0)
+ *--cp = byte + '0';
+ }
+ *--cp = '.';
+ addr >>= 8;
+ } while (--n > 0);
+
+ /* Convert the string to lowercase */
+ retStr = (char*)(cp+1);
+
+ return(retStr);
+}
+
+/* ***************************************************** */
+
+static void printFlow(u_int16_t thread_id, struct ndpi_flow *flow) {
+#ifdef HAVE_JSON_C
+ json_object *jObj;
+#endif
+
+ if(!json_flag) {
+#if 0
+ printf("\t%s [VLAN: %u] %s:%u <-> %s:%u\n",
+ ipProto2Name(flow->protocol), flow->vlan_id,
+ flow->lower_name, ntohs(flow->lower_port),
+ flow->upper_name, ntohs(flow->upper_port));
+
+#else
+ printf("\t%u", ++num_flows);
+
+ printf("\t%s %s:%u <-> %s:%u ",
+ ipProto2Name(flow->protocol),
+ flow->lower_name, ntohs(flow->lower_port),
+ flow->upper_name, ntohs(flow->upper_port));
+
+ if(flow->vlan_id > 0) printf("[VLAN: %u]", flow->vlan_id);
+
+ printf("[proto: %u/%s][%u pkts/%llu bytes]",
+ flow->detected_protocol,
+ ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_protocol),
+ flow->packets, (long long unsigned int)flow->bytes);
+
+ if(flow->host_server_name[0] != '\0') printf("[Host: %s]", flow->host_server_name);
+ if(flow->ssl.client_certificate[0] != '\0') printf("[SSL client: %s]", flow->ssl.client_certificate);
+ if(flow->ssl.server_certificate[0] != '\0') printf("[SSL server: %s]", flow->ssl.server_certificate);
+
+ printf("\n");
+#endif
+ } else {
+#ifdef HAVE_JSON_C
+ jObj = json_object_new_object();
+
+ json_object_object_add(jObj,"protocol",json_object_new_string(ipProto2Name(flow->protocol)));
+ json_object_object_add(jObj,"host_a.name",json_object_new_string(flow->lower_name));
+ json_object_object_add(jObj,"host_a.port",json_object_new_int(ntohs(flow->lower_port)));
+ json_object_object_add(jObj,"host_b.name",json_object_new_string(flow->upper_name));
+ json_object_object_add(jObj,"host_n.port",json_object_new_int(ntohs(flow->upper_port)));
+ json_object_object_add(jObj,"detected.protocol",json_object_new_int(flow->detected_protocol));
+ json_object_object_add(jObj,"detected.protocol.name",json_object_new_string(ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_protocol)));
+ json_object_object_add(jObj,"packets",json_object_new_int(flow->packets));
+ json_object_object_add(jObj,"bytes",json_object_new_int(flow->bytes));
+
+ if(flow->host_server_name[0] != '\0')
+ json_object_object_add(jObj,"host.server.name",json_object_new_string(flow->host_server_name));
+
+ if((flow->ssl.client_certificate[0] != '\0') || (flow->ssl.server_certificate[0] != '\0')) {
+ json_object *sjObj = json_object_new_object();
+
+ if(flow->ssl.client_certificate[0] != '\0')
+ json_object_object_add(sjObj, "client", json_object_new_string(flow->ssl.client_certificate));
+
+ if(flow->ssl.server_certificate[0] != '\0')
+ json_object_object_add(sjObj, "server", json_object_new_string(flow->ssl.server_certificate));
+
+ json_object_object_add(jObj, "ssl", sjObj);
+ }
+
+ //flow->protos.ssl.client_certificate, flow->protos.ssl.server_certificate);
+ if(json_flag == 1)
+ json_object_array_add(jArray_known_flows,jObj);
+ else if(json_flag == 2)
+ json_object_array_add(jArray_unknown_flows,jObj);
+#endif
+ }
+}
+
+/* ***************************************************** */
+
+static void free_ndpi_flow(struct ndpi_flow *flow) {
+ if(flow->ndpi_flow) { ndpi_free_flow(flow->ndpi_flow); flow->ndpi_flow = NULL; }
+ if(flow->src_id) { ndpi_free(flow->src_id); flow->src_id = NULL; }
+ if(flow->dst_id) { ndpi_free(flow->dst_id); flow->dst_id = NULL; }
+}
+
+/* ***************************************************** */
+
+static void ndpi_flow_freer(void *node) {
+ struct ndpi_flow *flow = (struct ndpi_flow*)node;
+
+ free_ndpi_flow(flow);
+ ndpi_free(flow);
+}
+
+/* ***************************************************** */
+
+static void node_print_unknown_proto_walker(const void *node, ndpi_VISIT which, int depth, void *user_data) {
+ struct ndpi_flow *flow = *(struct ndpi_flow**)node;
+ u_int16_t thread_id = *((u_int16_t*)user_data);
+
+ if(flow->detected_protocol != 0 /* UNKNOWN */) return;
+
+ if((which == ndpi_preorder) || (which == ndpi_leaf)) /* Avoid walking the same node multiple times */
+ printFlow(thread_id, flow);
+}
+
+/* ***************************************************** */
+
+static void node_print_known_proto_walker(const void *node, ndpi_VISIT which, int depth, void *user_data) {
+ struct ndpi_flow *flow = *(struct ndpi_flow**)node;
+ u_int16_t thread_id = *((u_int16_t*)user_data);
+
+ if(flow->detected_protocol == 0 /* UNKNOWN */) return;
+
+ if((which == ndpi_preorder) || (which == ndpi_leaf)) /* Avoid walking the same node multiple times */
+ printFlow(thread_id, flow);
+}
+
+/* ***************************************************** */
+
+static unsigned int node_guess_undetected_protocol(u_int16_t thread_id,
+ struct ndpi_flow *flow) {
+ flow->detected_protocol = ndpi_guess_undetected_protocol(ndpi_thread_info[thread_id].ndpi_struct,
+ flow->protocol,
+ ntohl(flow->lower_ip),
+ ntohs(flow->lower_port),
+ ntohl(flow->upper_ip),
+ ntohs(flow->upper_port));
+ // printf("Guess state: %u\n", flow->detected_protocol);
+ if(flow->detected_protocol != 0)
+ ndpi_thread_info[thread_id].stats.guessed_flow_protocols++;
+
+ return flow->detected_protocol;
+}
+
+/* ***************************************************** */
+
+static void node_proto_guess_walker(const void *node, ndpi_VISIT which, int depth, void *user_data) {
+ struct ndpi_flow *flow = *(struct ndpi_flow **) node;
+ u_int16_t thread_id = *((u_int16_t *) user_data);
+
+#if 0
+ printf("<%d>Walk on node %s (%p)\n",
+ depth,
+ which == preorder?"preorder":
+ which == postorder?"postorder":
+ which == endorder?"endorder":
+ which == leaf?"leaf": "unknown",
+ flow);
+#endif
+
+ if((which == ndpi_preorder) || (which == ndpi_leaf)) { /* Avoid walking the same node multiple times */
+ if(enable_protocol_guess) {
+ if(flow->detected_protocol == 0 /* UNKNOWN */) {
+ node_guess_undetected_protocol(thread_id, flow);
+ // printFlow(thread_id, flow);
+ }
+ }
+
+ ndpi_thread_info[thread_id].stats.protocol_counter[flow->detected_protocol] += flow->packets;
+ ndpi_thread_info[thread_id].stats.protocol_counter_bytes[flow->detected_protocol] += flow->bytes;
+ ndpi_thread_info[thread_id].stats.protocol_flows[flow->detected_protocol]++;
+ }
+}
+
+/* ***************************************************** */
+
+static void node_idle_scan_walker(const void *node, ndpi_VISIT which, int depth, void *user_data) {
+ struct ndpi_flow *flow = *(struct ndpi_flow **) node;
+ u_int16_t thread_id = *((u_int16_t *) user_data);
+
+ if(ndpi_thread_info[thread_id].num_idle_flows == IDLE_SCAN_BUDGET) /* TODO optimise with a budget-based walk */
+ return;
+
+ if((which == ndpi_preorder) || (which == ndpi_leaf)) { /* Avoid walking the same node multiple times */
+ if(flow->last_seen + MAX_IDLE_TIME < ndpi_thread_info[thread_id].last_time) {
+
+ /* update stats */
+ node_proto_guess_walker(node, which, depth, user_data);
+
+ if (flow->detected_protocol == 0 /* UNKNOWN */ && !undetected_flows_deleted)
+ undetected_flows_deleted = 1;
+
+ free_ndpi_flow(flow);
+ ndpi_thread_info[thread_id].stats.ndpi_flow_count--;
+
+ /* adding to a queue (we can't delete it from the tree inline ) */
+ ndpi_thread_info[thread_id].idle_flows[ndpi_thread_info[thread_id].num_idle_flows++] = flow;
+ }
+ }
+}
+
+/* ***************************************************** */
+
+static int node_cmp(const void *a, const void *b) {
+ struct ndpi_flow *fa = (struct ndpi_flow*)a;
+ struct ndpi_flow *fb = (struct ndpi_flow*)b;
+
+ if(fa->vlan_id < fb->vlan_id ) return(-1); else { if(fa->vlan_id > fb->vlan_id ) return(1); }
+ if(fa->lower_ip < fb->lower_ip ) return(-1); else { if(fa->lower_ip > fb->lower_ip ) return(1); }
+ if(fa->lower_port < fb->lower_port) return(-1); else { if(fa->lower_port > fb->lower_port) return(1); }
+ if(fa->upper_ip < fb->upper_ip ) return(-1); else { if(fa->upper_ip > fb->upper_ip ) return(1); }
+ if(fa->upper_port < fb->upper_port) return(-1); else { if(fa->upper_port > fb->upper_port) return(1); }
+ if(fa->protocol < fb->protocol ) return(-1); else { if(fa->protocol > fb->protocol ) return(1); }
+
+ return(0);
+}
+
+/* ***************************************************** */
+
+static struct ndpi_flow *get_ndpi_flow(u_int16_t thread_id,
+ const u_int8_t version,
+ u_int16_t vlan_id,
+ const struct ndpi_iphdr *iph,
+ u_int16_t ip_offset,
+ u_int16_t ipsize,
+ u_int16_t l4_packet_len,
+ struct ndpi_id_struct **src,
+ struct ndpi_id_struct **dst,
+ u_int8_t *proto,
+ const struct ndpi_ip6_hdr *iph6) {
+ u_int32_t idx, l4_offset;
+ struct ndpi_tcphdr *tcph = NULL;
+ struct ndpi_udphdr *udph = NULL;
+ u_int32_t lower_ip;
+ u_int32_t upper_ip;
+ u_int16_t lower_port;
+ u_int16_t upper_port;
+ struct ndpi_flow flow;
+ void *ret;
+ u_int8_t *l3;
+
+ /*
+ Note: to keep things simple (ndpiReader is just a demo app)
+ we handle IPv6 a-la-IPv4.
+ */
+ if(version == 4) {
+ if(ipsize < 20)
+ return NULL;
+
+ if((iph->ihl * 4) > ipsize || ipsize < ntohs(iph->tot_len)
+ || (iph->frag_off & htons(0x1FFF)) != 0)
+ return NULL;
+
+ l4_offset = iph->ihl * 4;
+ l3 = (u_int8_t*)iph;
+ } else {
+ l4_offset = sizeof(struct ndpi_ip6_hdr);
+ l3 = (u_int8_t*)iph6;
+ }
+
+ if(l4_packet_len < 64)
+ ndpi_thread_info[thread_id].stats.packet_len[0]++;
+ else if(l4_packet_len >= 64 && l4_packet_len < 128)
+ ndpi_thread_info[thread_id].stats.packet_len[1]++;
+ else if(l4_packet_len >= 128 && l4_packet_len < 256)
+ ndpi_thread_info[thread_id].stats.packet_len[2]++;
+ else if(l4_packet_len >= 256 && l4_packet_len < 1024)
+ ndpi_thread_info[thread_id].stats.packet_len[3]++;
+ else if(l4_packet_len >= 1024 && l4_packet_len < 1500)
+ ndpi_thread_info[thread_id].stats.packet_len[4]++;
+ else if(l4_packet_len >= 1500)
+ ndpi_thread_info[thread_id].stats.packet_len[5]++;
+
+ if(l4_packet_len > ndpi_thread_info[thread_id].stats.max_packet_len)
+ ndpi_thread_info[thread_id].stats.max_packet_len = l4_packet_len;
+
+ if(iph->saddr < iph->daddr) {
+ lower_ip = iph->saddr;
+ upper_ip = iph->daddr;
+ } else {
+ lower_ip = iph->daddr;
+ upper_ip = iph->saddr;
+ }
+
+ *proto = iph->protocol;
+
+ if(iph->protocol == 6 && l4_packet_len >= 20) {
+ ndpi_thread_info[thread_id].stats.tcp_count++;
+
+ // tcp
+ tcph = (struct ndpi_tcphdr *) ((u_int8_t *) l3 + l4_offset);
+ if(iph->saddr < iph->daddr) {
+ lower_port = tcph->source;
+ upper_port = tcph->dest;
+ } else {
+ lower_port = tcph->dest;
+ upper_port = tcph->source;
+
+ if(iph->saddr == iph->daddr) {
+ if(lower_port > upper_port) {
+ u_int16_t p = lower_port;
+
+ lower_port = upper_port;
+ upper_port = p;
+ }
+ }
+ }
+ } else if(iph->protocol == 17 && l4_packet_len >= 8) {
+ // udp
+ ndpi_thread_info[thread_id].stats.udp_count++;
+
+ udph = (struct ndpi_udphdr *) ((u_int8_t *) l3 + l4_offset);
+ if(iph->saddr < iph->daddr) {
+ lower_port = udph->source;
+ upper_port = udph->dest;
+ } else {
+ lower_port = udph->dest;
+ upper_port = udph->source;
+ }
+ } else {
+ // non tcp/udp protocols
+ lower_port = 0;
+ upper_port = 0;
+ }
+
+ flow.protocol = iph->protocol, flow.vlan_id = vlan_id;
+ flow.lower_ip = lower_ip, flow.upper_ip = upper_ip;
+ flow.lower_port = lower_port, flow.upper_port = upper_port;
+
+ if(0)
+ printf("[NDPI] [%u][%u:%u <-> %u:%u]\n",
+ iph->protocol, lower_ip, ntohs(lower_port), upper_ip, ntohs(upper_port));
+
+ idx = (vlan_id + lower_ip + upper_ip + iph->protocol + lower_port + upper_port) % NUM_ROOTS;
+ ret = ndpi_tfind(&flow, &ndpi_thread_info[thread_id].ndpi_flows_root[idx], node_cmp);
+
+ if(ret == NULL) {
+ if(ndpi_thread_info[thread_id].stats.ndpi_flow_count == MAX_NDPI_FLOWS) {
+ printf("ERROR: maximum flow count (%u) has been exceeded\n", MAX_NDPI_FLOWS);
+ exit(-1);
+ } else {
+ struct ndpi_flow *newflow = (struct ndpi_flow*)malloc(sizeof(struct ndpi_flow));
+
+ if(newflow == NULL) {
+ printf("[NDPI] %s(1): not enough memory\n", __FUNCTION__);
+ return(NULL);
+ }
+
+ memset(newflow, 0, sizeof(struct ndpi_flow));
+ newflow->protocol = iph->protocol, newflow->vlan_id = vlan_id;
+ newflow->lower_ip = lower_ip, newflow->upper_ip = upper_ip;
+ newflow->lower_port = lower_port, newflow->upper_port = upper_port;
+
+ if(version == 4) {
+ inet_ntop(AF_INET, &lower_ip, newflow->lower_name, sizeof(newflow->lower_name));
+ inet_ntop(AF_INET, &upper_ip, newflow->upper_name, sizeof(newflow->upper_name));
+ } else {
+ inet_ntop(AF_INET6, &iph6->ip6_src, newflow->lower_name, sizeof(newflow->lower_name));
+ inet_ntop(AF_INET6, &iph6->ip6_dst, newflow->upper_name, sizeof(newflow->upper_name));
+ }
+
+ if((newflow->ndpi_flow = malloc_wrapper(size_flow_struct)) == NULL) {
+ printf("[NDPI] %s(2): not enough memory\n", __FUNCTION__);
+ return(NULL);
+ } else
+ memset(newflow->ndpi_flow, 0, size_flow_struct);
+
+ if((newflow->src_id = malloc_wrapper(size_id_struct)) == NULL) {
+ printf("[NDPI] %s(3): not enough memory\n", __FUNCTION__);
+ return(NULL);
+ } else
+ memset(newflow->src_id, 0, size_id_struct);
+
+ if((newflow->dst_id = malloc_wrapper(size_id_struct)) == NULL) {
+ printf("[NDPI] %s(4): not enough memory\n", __FUNCTION__);
+ return(NULL);
+ } else
+ memset(newflow->dst_id, 0, size_id_struct);
+
+ ndpi_tsearch(newflow, &ndpi_thread_info[thread_id].ndpi_flows_root[idx], node_cmp); /* Add */
+ ndpi_thread_info[thread_id].stats.ndpi_flow_count++;
+
+ *src = newflow->src_id, *dst = newflow->dst_id;
+
+ // printFlow(thread_id, newflow);
+
+ return(newflow);
+ }
+ } else {
+ struct ndpi_flow *flow = *(struct ndpi_flow**)ret;
+
+ if(flow->lower_ip == lower_ip && flow->upper_ip == upper_ip
+ && flow->lower_port == lower_port && flow->upper_port == upper_port)
+ *src = flow->src_id, *dst = flow->dst_id;
+ else
+ *src = flow->dst_id, *dst = flow->src_id;
+
+ return flow;
+ }
+}
+
+/* ***************************************************** */
+
+static struct ndpi_flow *get_ndpi_flow6(u_int16_t thread_id,
+ u_int16_t vlan_id,
+ const struct ndpi_ip6_hdr *iph6,
+ u_int16_t ip_offset,
+ struct ndpi_id_struct **src,
+ struct ndpi_id_struct **dst,
+ u_int8_t *proto) {
+ struct ndpi_iphdr iph;
+
+ memset(&iph, 0, sizeof(iph));
+ iph.version = 4;
+ iph.saddr = iph6->ip6_src.__u6_addr.__u6_addr32[2] + iph6->ip6_src.__u6_addr.__u6_addr32[3];
+ iph.daddr = iph6->ip6_dst.__u6_addr.__u6_addr32[2] + iph6->ip6_dst.__u6_addr.__u6_addr32[3];
+ iph.protocol = iph6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
+
+ if(iph.protocol == 0x3C /* IPv6 destination option */) {
+ u_int8_t *options = (u_int8_t*)iph6 + sizeof(const struct ndpi_ip6_hdr);
+
+ iph.protocol = options[0];
+ }
+
+ return(get_ndpi_flow(thread_id, 6, vlan_id, &iph, ip_offset,
+ sizeof(struct ndpi_ip6_hdr),
+ ntohs(iph6->ip6_ctlun.ip6_un1.ip6_un1_plen),
+ src, dst, proto, iph6));
+}
+
+/* ***************************************************** */
+
+static void setupDetection(u_int16_t thread_id) {
+ NDPI_PROTOCOL_BITMASK all;
+
+ memset(&ndpi_thread_info[thread_id], 0, sizeof(ndpi_thread_info[thread_id]));
+
+ // init global detection structure
+ ndpi_thread_info[thread_id].ndpi_struct = ndpi_init_detection_module(detection_tick_resolution,
+ malloc_wrapper, free_wrapper, debug_printf);
+ if(ndpi_thread_info[thread_id].ndpi_struct == NULL) {
+ printf("ERROR: global structure initialization failed\n");
+ exit(-1);
+ }
+
+ if(full_http_dissection)
+ ndpi_thread_info[thread_id].ndpi_struct->http_dissect_response = 1;
+
+ // enable all protocols
+ NDPI_BITMASK_SET_ALL(all);
+ ndpi_set_protocol_detection_bitmask2(ndpi_thread_info[thread_id].ndpi_struct, &all);
+
+ // allocate memory for id and flow tracking
+ size_id_struct = ndpi_detection_get_sizeof_ndpi_id_struct();
+ size_flow_struct = ndpi_detection_get_sizeof_ndpi_flow_struct();
+
+ // clear memory for results
+ memset(ndpi_thread_info[thread_id].stats.protocol_counter, 0, sizeof(ndpi_thread_info[thread_id].stats.protocol_counter));
+ memset(ndpi_thread_info[thread_id].stats.protocol_counter_bytes, 0, sizeof(ndpi_thread_info[thread_id].stats.protocol_counter_bytes));
+ memset(ndpi_thread_info[thread_id].stats.protocol_flows, 0, sizeof(ndpi_thread_info[thread_id].stats.protocol_flows));
+
+ if(_protoFilePath != NULL)
+ ndpi_load_protocols_file(ndpi_thread_info[thread_id].ndpi_struct, _protoFilePath);
+}
+
+/* ***************************************************** */
+
+static void terminateDetection(u_int16_t thread_id) {
+ int i;
+
+ for(i=0; i<NUM_ROOTS; i++) {
+ ndpi_tdestroy(ndpi_thread_info[thread_id].ndpi_flows_root[i], ndpi_flow_freer);
+ ndpi_thread_info[thread_id].ndpi_flows_root[i] = NULL;
+ }
+
+ ndpi_exit_detection_module(ndpi_thread_info[thread_id].ndpi_struct, free_wrapper);
+}
+
+/* ***************************************************** */
+
+// ipsize = header->len - ip_offset ; rawsize = header->len
+static unsigned int packet_processing(u_int16_t thread_id,
+ const u_int64_t time,
+ u_int16_t vlan_id,
+ const struct ndpi_iphdr *iph,
+ struct ndpi_ip6_hdr *iph6,
+ u_int16_t ip_offset,
+ u_int16_t ipsize, u_int16_t rawsize) {
+ struct ndpi_id_struct *src, *dst;
+ struct ndpi_flow *flow;
+ struct ndpi_flow_struct *ndpi_flow = NULL;
+ u_int32_t protocol = 0;
+ u_int8_t proto;
+
+ if(iph)
+ flow = get_ndpi_flow(thread_id, 4, vlan_id, iph, ip_offset, ipsize,
+ ntohs(iph->tot_len) - (iph->ihl * 4),
+ &src, &dst, &proto, NULL);
+ else
+ flow = get_ndpi_flow6(thread_id, vlan_id, iph6, ip_offset, &src, &dst, &proto);
+
+ if(flow != NULL) {
+ ndpi_thread_info[thread_id].stats.ip_packet_count++;
+ ndpi_thread_info[thread_id].stats.total_wire_bytes += rawsize + 24 /* CRC etc */, ndpi_thread_info[thread_id].stats.total_ip_bytes += rawsize;
+ ndpi_flow = flow->ndpi_flow;
+ flow->packets++, flow->bytes += rawsize;
+ flow->last_seen = time;
+ } else {
+ return(0);
+ }
+
+ if(flow->detection_completed) return(0);
+
+ protocol = (const u_int32_t)ndpi_detection_process_packet(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow,
+ iph ? (uint8_t *)iph : (uint8_t *)iph6,
+ ipsize, time, src, dst);
+
+ flow->detected_protocol = protocol;
+
+ if((flow->detected_protocol != NDPI_PROTOCOL_UNKNOWN)
+ || ((proto == IPPROTO_UDP) && (flow->packets > 8))
+ || ((proto == IPPROTO_TCP) && (flow->packets > 10))) {
+ flow->detection_completed = 1;
+
+ snprintf(flow->host_server_name, sizeof(flow->host_server_name), "%s", flow->ndpi_flow->host_server_name);
+
+ if((proto == IPPROTO_TCP) && (flow->detected_protocol != NDPI_PROTOCOL_DNS)) {
+ snprintf(flow->ssl.client_certificate, sizeof(flow->ssl.client_certificate), "%s", flow->ndpi_flow->protos.ssl.client_certificate);
+ snprintf(flow->ssl.server_certificate, sizeof(flow->ssl.server_certificate), "%s", flow->ndpi_flow->protos.ssl.server_certificate);
+ }
+
+ if((
+ (flow->detected_protocol == NDPI_PROTOCOL_HTTP)
+ || (flow->detected_protocol == NDPI_SERVICE_FACEBOOK)
+ )
+ && full_http_dissection) {
+ char *method;
+
+ printf("[URL] %s\n", ndpi_get_http_url(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow));
+ printf("[Content-Type] %s\n", ndpi_get_http_content_type(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow));
+
+ switch(ndpi_get_http_method(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow)) {
+ case HTTP_METHOD_OPTIONS: method = "HTTP_METHOD_OPTIONS"; break;
+ case HTTP_METHOD_GET: method = "HTTP_METHOD_GET"; break;
+ case HTTP_METHOD_HEAD: method = "HTTP_METHOD_HEAD"; break;
+ case HTTP_METHOD_POST: method = "HTTP_METHOD_POST"; break;
+ case HTTP_METHOD_PUT: method = "HTTP_METHOD_PUT"; break;
+ case HTTP_METHOD_DELETE: method = "HTTP_METHOD_DELETE"; break;
+ case HTTP_METHOD_TRACE: method = "HTTP_METHOD_TRACE"; break;
+ case HTTP_METHOD_CONNECT: method = "HTTP_METHOD_CONNECT"; break;
+ default: method = "HTTP_METHOD_UNKNOWN"; break;
+ }
+
+ printf("[Method] %s\n", method);
+ }
+
+ free_ndpi_flow(flow);
+
+ if(verbose > 1) {
+ if(enable_protocol_guess) {
+ if(flow->detected_protocol == 0 /* UNKNOWN */) {
+ protocol = node_guess_undetected_protocol(thread_id, flow);
+ }
+ }
+
+ printFlow(thread_id, flow);
+ }
+ }
+
+#if 0
+ if(ndpi_flow->l4.tcp.host_server_name[0] != '\0')
+ printf("%s\n", ndpi_flow->l4.tcp.host_server_name);
+#endif
+
+ if(live_capture) {
+ if(ndpi_thread_info[thread_id].last_idle_scan_time + IDLE_SCAN_PERIOD < ndpi_thread_info[thread_id].last_time) {
+ /* scan for idle flows */
+ ndpi_twalk(ndpi_thread_info[thread_id].ndpi_flows_root[ndpi_thread_info[thread_id].idle_scan_idx], node_idle_scan_walker, &thread_id);
+
+ /* remove idle flows (unfortunately we cannot do this inline) */
+ while (ndpi_thread_info[thread_id].num_idle_flows > 0)
+ ndpi_tdelete(ndpi_thread_info[thread_id].idle_flows[--ndpi_thread_info[thread_id].num_idle_flows],
+ &ndpi_thread_info[thread_id].ndpi_flows_root[ndpi_thread_info[thread_id].idle_scan_idx], node_cmp);
+
+ if(++ndpi_thread_info[thread_id].idle_scan_idx == NUM_ROOTS) ndpi_thread_info[thread_id].idle_scan_idx = 0;
+ ndpi_thread_info[thread_id].last_idle_scan_time = ndpi_thread_info[thread_id].last_time;
+ }
+ }
+
+ return 0;
+}
+
+/* ****************************************************** */
+
+char* formatTraffic(float numBits, int bits, char *buf) {
+ char unit;
+
+ if(bits)
+ unit = 'b';
+ else
+ unit = 'B';
+
+ if(numBits < 1024) {
+ snprintf(buf, 32, "%lu %c", (unsigned long)numBits, unit);
+ } else if(numBits < 1048576) {
+ snprintf(buf, 32, "%.2f K%c", (float)(numBits)/1024, unit);
+ } else {
+ float tmpMBits = ((float)numBits)/1048576;
+
+ if(tmpMBits < 1024) {
+ snprintf(buf, 32, "%.2f M%c", tmpMBits, unit);
+ } else {
+ tmpMBits /= 1024;
+
+ if(tmpMBits < 1024) {
+ snprintf(buf, 32, "%.2f G%c", tmpMBits, unit);
+ } else {
+ snprintf(buf, 32, "%.2f T%c", (float)(tmpMBits)/1024, unit);
+ }
+ }
+ }
+
+ return(buf);
+}
+
+/* ***************************************************** */
+
+char* formatPackets(float numPkts, char *buf) {
+ if(numPkts < 1000) {
+ snprintf(buf, 32, "%.2f", numPkts);
+ } else if(numPkts < 1000000) {
+ snprintf(buf, 32, "%.2f K", numPkts/1000);
+ } else {
+ numPkts /= 1000000;
+ snprintf(buf, 32, "%.2f M", numPkts);
+ }
+
+ return(buf);
+}
+
+/* ***************************************************** */
+
+#ifdef HAVE_JSON_C
+static void json_init() {
+ jArray_known_flows = json_object_new_array();
+ jArray_unknown_flows = json_object_new_array();
+}
+#endif
+
+/* ***************************************************** */
+
+char* formatBytes(u_int32_t howMuch, char *buf, u_int buf_len) {
+ char unit = 'B';
+
+ if(howMuch < 1024) {
+ snprintf(buf, buf_len, "%lu %c", (unsigned long)howMuch, unit);
+ } else if(howMuch < 1048576) {
+ snprintf(buf, buf_len, "%.2f K%c", (float)(howMuch)/1024, unit);
+ } else {
+ float tmpGB = ((float)howMuch)/1048576;
+
+ if(tmpGB < 1024) {
+ snprintf(buf, buf_len, "%.2f M%c", tmpGB, unit);
+ } else {
+ tmpGB /= 1024;
+
+ snprintf(buf, buf_len, "%.2f G%c", tmpGB, unit);
+ }
+ }
+
+ return(buf);
+}
+
+/* ***************************************************** */
+
+static void printResults(u_int64_t tot_usec) {
+ u_int32_t i;
+ u_int64_t total_flow_bytes = 0;
+ u_int avg_pkt_size = 0;
+ struct thread_stats cumulative_stats;
+ int thread_id;
+ char buf[32];
+#ifdef HAVE_JSON_C
+ FILE *json_fp;
+ json_object *jObj_main, *jObj_trafficStats, *jArray_detProto, *jObj;
+#endif
+ long long unsigned int breed_stats[NUM_BREEDS] = { 0 };
+
+ memset(&cumulative_stats, 0, sizeof(cumulative_stats));
+
+ for(thread_id = 0; thread_id < num_threads; thread_id++) {
+ if(ndpi_thread_info[thread_id].stats.total_wire_bytes == 0) continue;
+
+ for(i=0; i<NUM_ROOTS; i++)
+ ndpi_twalk(ndpi_thread_info[thread_id].ndpi_flows_root[i], node_proto_guess_walker, &thread_id);
+
+ /* Stats aggregation */
+ cumulative_stats.guessed_flow_protocols += ndpi_thread_info[thread_id].stats.guessed_flow_protocols;
+ cumulative_stats.raw_packet_count += ndpi_thread_info[thread_id].stats.raw_packet_count;
+ cumulative_stats.ip_packet_count += ndpi_thread_info[thread_id].stats.ip_packet_count;
+ cumulative_stats.total_wire_bytes += ndpi_thread_info[thread_id].stats.total_wire_bytes;
+ cumulative_stats.total_ip_bytes += ndpi_thread_info[thread_id].stats.total_ip_bytes;
+ cumulative_stats.total_discarded_bytes += ndpi_thread_info[thread_id].stats.total_discarded_bytes;
+
+ for(i = 0; i < ndpi_get_num_supported_protocols(ndpi_thread_info[0].ndpi_struct); i++) {
+ cumulative_stats.protocol_counter[i] += ndpi_thread_info[thread_id].stats.protocol_counter[i];
+ cumulative_stats.protocol_counter_bytes[i] += ndpi_thread_info[thread_id].stats.protocol_counter_bytes[i];
+ cumulative_stats.protocol_flows[i] += ndpi_thread_info[thread_id].stats.protocol_flows[i];
+ }
+
+ cumulative_stats.ndpi_flow_count += ndpi_thread_info[thread_id].stats.ndpi_flow_count;
+ cumulative_stats.tcp_count += ndpi_thread_info[thread_id].stats.tcp_count;
+ cumulative_stats.udp_count += ndpi_thread_info[thread_id].stats.udp_count;
+ cumulative_stats.mpls_count += ndpi_thread_info[thread_id].stats.mpls_count;
+ cumulative_stats.pppoe_count += ndpi_thread_info[thread_id].stats.pppoe_count;
+ cumulative_stats.vlan_count += ndpi_thread_info[thread_id].stats.vlan_count;
+ cumulative_stats.fragmented_count += ndpi_thread_info[thread_id].stats.fragmented_count;
+ for(i = 0; i < 6; i++)
+ cumulative_stats.packet_len[i] += ndpi_thread_info[thread_id].stats.packet_len[i];
+ cumulative_stats.max_packet_len += ndpi_thread_info[thread_id].stats.max_packet_len;
+ }
+
+ printf("\nnDPI Memory statistics:\n");
+ printf("\tnDPI Memory (once): %-13s\n", formatBytes(sizeof(struct ndpi_detection_module_struct), buf, sizeof(buf)));
+ printf("\tFlow Memory (per flow): %-13s\n", formatBytes(size_flow_struct, buf, sizeof(buf)));
+ printf("\tActual Memory: %-13s\n", formatBytes(current_ndpi_memory, buf, sizeof(buf)));
+ printf("\tPeak Memory: %-13s\n", formatBytes(max_ndpi_memory, buf, sizeof(buf)));
+
+ if(!json_flag) {
+ printf("\nTraffic statistics:\n");
+ printf("\tEthernet bytes: %-13llu (includes ethernet CRC/IFC/trailer)\n",
+ (long long unsigned int)cumulative_stats.total_wire_bytes);
+ printf("\tDiscarded bytes: %-13llu\n",
+ (long long unsigned int)cumulative_stats.total_discarded_bytes);
+ printf("\tIP packets: %-13llu of %llu packets total\n",
+ (long long unsigned int)cumulative_stats.ip_packet_count,
+ (long long unsigned int)cumulative_stats.raw_packet_count);
+ /* In order to prevent Floating point exception in case of no traffic*/
+ if(cumulative_stats.total_ip_bytes && cumulative_stats.raw_packet_count)
+ avg_pkt_size = (unsigned int)(cumulative_stats.total_ip_bytes/cumulative_stats.raw_packet_count);
+ printf("\tIP bytes: %-13llu (avg pkt size %u bytes)\n",
+ (long long unsigned int)cumulative_stats.total_ip_bytes,avg_pkt_size);
+ printf("\tUnique flows: %-13u\n", cumulative_stats.ndpi_flow_count);
+
+ printf("\tTCP Packets: %-13lu\n", (unsigned long)cumulative_stats.tcp_count);
+ printf("\tUDP Packets: %-13lu\n", (unsigned long)cumulative_stats.udp_count);
+ printf("\tVLAN Packets: %-13lu\n", (unsigned long)cumulative_stats.vlan_count);
+ printf("\tMPLS Packets: %-13lu\n", (unsigned long)cumulative_stats.mpls_count);
+ printf("\tPPPoE Packets: %-13lu\n", (unsigned long)cumulative_stats.pppoe_count);
+ printf("\tFragmented Packets: %-13lu\n", (unsigned long)cumulative_stats.fragmented_count);
+ printf("\tMax Packet size: %-13u\n", cumulative_stats.max_packet_len);
+ printf("\tPacket Len < 64: %-13lu\n", (unsigned long)cumulative_stats.packet_len[0]);
+ printf("\tPacket Len 64-128: %-13lu\n", (unsigned long)cumulative_stats.packet_len[1]);
+ printf("\tPacket Len 128-256: %-13lu\n", (unsigned long)cumulative_stats.packet_len[2]);
+ printf("\tPacket Len 256-1024: %-13lu\n", (unsigned long)cumulative_stats.packet_len[3]);
+ printf("\tPacket Len 1024-1500: %-13lu\n", (unsigned long)cumulative_stats.packet_len[4]);
+ printf("\tPacket Len > 1500: %-13lu\n", (unsigned long)cumulative_stats.packet_len[5]);
+
+ if(tot_usec > 0) {
+ char buf[32], buf1[32];
+ float t = (float)(cumulative_stats.ip_packet_count*1000000)/(float)tot_usec;
+ float b = (float)(cumulative_stats.total_wire_bytes * 8 *1000000)/(float)tot_usec;
+ float traffic_duration;
+ if (live_capture) traffic_duration = tot_usec;
+ else traffic_duration = (pcap_end.tv_sec*1000000 + pcap_end.tv_usec) - (pcap_start.tv_sec*1000000 + pcap_start.tv_usec);
+ printf("\tnDPI throughput: %s pps / %s/sec\n", formatPackets(t, buf), formatTraffic(b, 1, buf1));
+ t = (float)(cumulative_stats.ip_packet_count*1000000)/(float)traffic_duration;
+ b = (float)(cumulative_stats.total_wire_bytes * 8 *1000000)/(float)traffic_duration;
+ printf("\tTraffic throughput: %s pps / %s/sec\n", formatPackets(t, buf), formatTraffic(b, 1, buf1));
+ printf("\tTraffic duration: %.3f sec\n", traffic_duration/1000000);
+ }
+
+ if(enable_protocol_guess)
+ printf("\tGuessed flow protos: %-13u\n", cumulative_stats.guessed_flow_protocols);
+ } else {
+#ifdef HAVE_JSON_C
+ if((json_fp = fopen(_jsonFilePath,"w")) == NULL) {
+ printf("Error create .json file\n");
+ json_flag = 0;
+ } else {
+ jObj_main = json_object_new_object();
+ jObj_trafficStats = json_object_new_object();
+ jArray_detProto = json_object_new_array();
+
+ json_object_object_add(jObj_trafficStats,"ethernet.bytes",json_object_new_int64(cumulative_stats.total_wire_bytes));
+ json_object_object_add(jObj_trafficStats,"discarded.bytes",json_object_new_int64(cumulative_stats.total_discarded_bytes));
+ json_object_object_add(jObj_trafficStats,"ip.packets",json_object_new_int64(cumulative_stats.ip_packet_count));
+ json_object_object_add(jObj_trafficStats,"total.packets",json_object_new_int64(cumulative_stats.raw_packet_count));
+ json_object_object_add(jObj_trafficStats,"ip.bytes",json_object_new_int64(cumulative_stats.total_ip_bytes));
+ json_object_object_add(jObj_trafficStats,"avg.pkt.size",json_object_new_int(cumulative_stats.total_ip_bytes/cumulative_stats.raw_packet_count));
+ json_object_object_add(jObj_trafficStats,"unique.flows",json_object_new_int(cumulative_stats.ndpi_flow_count));
+ json_object_object_add(jObj_trafficStats,"tcp.pkts",json_object_new_int64(cumulative_stats.tcp_count));
+ json_object_object_add(jObj_trafficStats,"udp.pkts",json_object_new_int64(cumulative_stats.udp_count));
+ json_object_object_add(jObj_trafficStats,"vlan.pkts",json_object_new_int64(cumulative_stats.vlan_count));
+ json_object_object_add(jObj_trafficStats,"mpls.pkts",json_object_new_int64(cumulative_stats.mpls_count));
+ json_object_object_add(jObj_trafficStats,"pppoe.pkts",json_object_new_int64(cumulative_stats.pppoe_count));
+ json_object_object_add(jObj_trafficStats,"fragmented.pkts",json_object_new_int64(cumulative_stats.fragmented_count));
+ json_object_object_add(jObj_trafficStats,"max.pkt.size",json_object_new_int(cumulative_stats.max_packet_len));
+ json_object_object_add(jObj_trafficStats,"pkt.len_min64",json_object_new_int64(cumulative_stats.packet_len[0]));
+ json_object_object_add(jObj_trafficStats,"pkt.len_64_128",json_object_new_int64(cumulative_stats.packet_len[1]));
+ json_object_object_add(jObj_trafficStats,"pkt.len_128_256",json_object_new_int64(cumulative_stats.packet_len[2]));
+ json_object_object_add(jObj_trafficStats,"pkt.len_256_1024",json_object_new_int64(cumulative_stats.packet_len[3]));
+ json_object_object_add(jObj_trafficStats,"pkt.len_1024_1500",json_object_new_int64(cumulative_stats.packet_len[4]));
+ json_object_object_add(jObj_trafficStats,"pkt.len_grt1500",json_object_new_int64(cumulative_stats.packet_len[5]));
+ json_object_object_add(jObj_trafficStats,"guessed.flow.protos",json_object_new_int(cumulative_stats.guessed_flow_protocols));
+
+ json_object_object_add(jObj_main,"traffic.statistics",jObj_trafficStats);
+ }
+#endif
+ }
+
+ if(!json_flag) printf("\n\nDetected protocols:\n");
+ for(i = 0; i <= ndpi_get_num_supported_protocols(ndpi_thread_info[0].ndpi_struct); i++) {
+ ndpi_protocol_breed_t breed = ndpi_get_proto_breed(ndpi_thread_info[0].ndpi_struct, i);
+
+ if(cumulative_stats.protocol_counter[i] > 0) {
+ breed_stats[breed] += (long long unsigned int)cumulative_stats.protocol_counter_bytes[i];
+
+ if(!json_flag) {
+ printf("\t%-20s packets: %-13llu bytes: %-13llu "
+ "flows: %-13u\n",
+ ndpi_get_proto_name(ndpi_thread_info[0].ndpi_struct, i),
+ (long long unsigned int)cumulative_stats.protocol_counter[i],
+ (long long unsigned int)cumulative_stats.protocol_counter_bytes[i],
+ cumulative_stats.protocol_flows[i]);
+ } else {
+#ifdef HAVE_JSON_C
+ jObj = json_object_new_object();
+
+ json_object_object_add(jObj,"name",json_object_new_string(ndpi_get_proto_name(ndpi_thread_info[0].ndpi_struct, i)));
+ json_object_object_add(jObj,"breed",json_object_new_string(ndpi_get_proto_breed_name(ndpi_thread_info[0].ndpi_struct, breed)));
+ json_object_object_add(jObj,"packets",json_object_new_int64(cumulative_stats.protocol_counter[i]));
+ json_object_object_add(jObj,"bytes",json_object_new_int64(cumulative_stats.protocol_counter_bytes[i]));
+ json_object_object_add(jObj,"flows",json_object_new_int(cumulative_stats.protocol_flows[i]));
+
+ json_object_array_add(jArray_detProto,jObj);
+#endif
+ }
+
+ total_flow_bytes += cumulative_stats.protocol_counter_bytes[i];
+ }
+ }
+
+ if(!json_flag) {
+ printf("\n\nProtocol statistics:\n");
+
+ for(i=0; i < NUM_BREEDS; i++) {
+ if(breed_stats[i] > 0) {
+ printf("\t%-20s %13llu bytes\n",
+ ndpi_get_proto_breed_name(ndpi_thread_info[0].ndpi_struct, i),
+ breed_stats[i]);
+ }
+ }
+ }
+
+ // printf("\n\nTotal Flow Traffic: %llu (diff: %llu)\n", total_flow_bytes, cumulative_stats.total_ip_bytes-total_flow_bytes);
+
+ if(verbose) {
+ if(!json_flag) printf("\n");
+
+ num_flows = 0;
+ for(thread_id = 0; thread_id < num_threads; thread_id++) {
+ for(i=0; i<NUM_ROOTS; i++)
+ ndpi_twalk(ndpi_thread_info[thread_id].ndpi_flows_root[i], node_print_known_proto_walker, &thread_id);
+ }
+
+ for(thread_id = 0; thread_id < num_threads; thread_id++) {
+ if(ndpi_thread_info[thread_id].stats.protocol_counter[0 /* 0 = Unknown */] > 0) {
+ if(!json_flag) {
+ printf("\n\nUndetected flows:%s\n", undetected_flows_deleted ? " (expired flows are not listed below)" : "");
+ }
+
+ if(json_flag)
+ json_flag = 2;
+ break;
+ }
+ }
+
+ num_flows = 0;
+ for(thread_id = 0; thread_id < num_threads; thread_id++) {
+ if(ndpi_thread_info[thread_id].stats.protocol_counter[0] > 0) {
+ for(i=0; i<NUM_ROOTS; i++)
+ ndpi_twalk(ndpi_thread_info[thread_id].ndpi_flows_root[i], node_print_unknown_proto_walker, &thread_id);
+ }
+ }
+ }
+
+ if(json_flag != 0) {
+#ifdef HAVE_JSON_C
+ json_object_object_add(jObj_main,"detected.protos",jArray_detProto);
+ json_object_object_add(jObj_main,"known.flows",jArray_known_flows);
+
+ if(json_object_array_length(jArray_unknown_flows) != 0)
+ json_object_object_add(jObj_main,"unknown.flows",jArray_unknown_flows);
+
+ fprintf(json_fp,"%s\n",json_object_to_json_string(jObj_main));
+ fclose(json_fp);
+#endif
+ }
+}
+
+/* ***************************************************** */
+
+static void closePcapFile(u_int16_t thread_id) {
+ if(ndpi_thread_info[thread_id]._pcap_handle != NULL) {
+ pcap_close(ndpi_thread_info[thread_id]._pcap_handle);
+ }
+}
+
+/* ***************************************************** */
+
+static void breakPcapLoop(u_int16_t thread_id) {
+ if(ndpi_thread_info[thread_id]._pcap_handle != NULL) {
+ pcap_breakloop(ndpi_thread_info[thread_id]._pcap_handle);
+ }
+}
+
+/* ***************************************************** */
+
+// executed for each packet in the pcap file
+void sigproc(int sig) {
+ static int called = 0;
+ int thread_id;
+
+ if(called) return; else called = 1;
+ shutdown_app = 1;
+
+ for(thread_id=0; thread_id<num_threads; thread_id++)
+ breakPcapLoop(thread_id);
+}
+
+/* ***************************************************** */
+
+static int getNextPcapFileFromPlaylist(u_int16_t thread_id, char filename[], u_int32_t filename_len) {
+
+ if(playlist_fp[thread_id] == NULL) {
+ if((playlist_fp[thread_id] = fopen(_pcap_file[thread_id], "r")) == NULL)
+ return -1;
+ }
+
+ next_line:
+ if(fgets(filename, filename_len, playlist_fp[thread_id])) {
+ int l = strlen(filename);
+ if(filename[0] == '\0' || filename[0] == '#') goto next_line;
+ if(filename[l-1] == '\n') filename[l-1] = '\0';
+ return 0;
+ } else {
+ fclose(playlist_fp[thread_id]);
+ playlist_fp[thread_id] = NULL;
+ return -1;
+ }
+}
+
+/* ***************************************************** */
+
+static void configurePcapHandle(u_int16_t thread_id) {
+ ndpi_thread_info[thread_id]._pcap_datalink_type = pcap_datalink(ndpi_thread_info[thread_id]._pcap_handle);
+
+ if(_bpf_filter != NULL) {
+ struct bpf_program fcode;
+
+ if(pcap_compile(ndpi_thread_info[thread_id]._pcap_handle, &fcode, _bpf_filter, 1, 0xFFFFFF00) < 0) {
+ printf("pcap_compile error: '%s'\n", pcap_geterr(ndpi_thread_info[thread_id]._pcap_handle));
+ } else {
+ if(pcap_setfilter(ndpi_thread_info[thread_id]._pcap_handle, &fcode) < 0) {
+ printf("pcap_setfilter error: '%s'\n", pcap_geterr(ndpi_thread_info[thread_id]._pcap_handle));
+ } else
+ printf("Successfully set BPF filter to '%s'\n", _bpf_filter);
+ }
+ }
+}
+
+/* ***************************************************** */
+
+static void openPcapFileOrDevice(u_int16_t thread_id) {
+ u_int snaplen = 1536;
+ int promisc = 1;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ /* trying to open a live interface */
+ if((ndpi_thread_info[thread_id]._pcap_handle = pcap_open_live(_pcap_file[thread_id], snaplen, promisc, 500, errbuf)) == NULL) {
+ capture_for = capture_until = 0;
+
+ live_capture = 0;
+ num_threads = 1; /* Open pcap files in single threads mode */
+
+ /* trying to open a pcap file */
+ if((ndpi_thread_info[thread_id]._pcap_handle = pcap_open_offline(_pcap_file[thread_id], ndpi_thread_info[thread_id]._pcap_error_buffer)) == NULL) {
+ char filename[256];
+
+ /* trying to open a pcap playlist */
+ if(getNextPcapFileFromPlaylist(thread_id, filename, sizeof(filename)) != 0 ||
+ (ndpi_thread_info[thread_id]._pcap_handle = pcap_open_offline(filename, ndpi_thread_info[thread_id]._pcap_error_buffer)) == NULL) {
+
+ printf("ERROR: could not open pcap file or playlist: %s\n", ndpi_thread_info[thread_id]._pcap_error_buffer);
+ exit(-1);
+ } else {
+ if(!json_flag) printf("Reading packets from playlist %s...\n", _pcap_file[thread_id]);
+ }
+ } else {
+ if(!json_flag) printf("Reading packets from pcap file %s...\n", _pcap_file[thread_id]);
+ }
+ } else {
+ live_capture = 1;
+
+ if(!json_flag) printf("Capturing live traffic from device %s...\n", _pcap_file[thread_id]);
+ }
+
+ configurePcapHandle(thread_id);
+
+ if(capture_for > 0) {
+ if(!json_flag) printf("Capturing traffic up to %u seconds\n", (unsigned int)capture_for);
+
+#ifndef WIN32
+ alarm(capture_for);
+ signal(SIGALRM, sigproc);
+#endif
+ }
+}
+
+/* ***************************************************** */
+
+static void pcap_packet_callback(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
+ const struct ndpi_ethhdr *ethernet;
+ struct ndpi_iphdr *iph;
+ struct ndpi_ip6_hdr *iph6;
+ u_int64_t time;
+ u_int16_t type, ip_offset, ip_len;
+ u_int16_t frag_off = 0, vlan_id = 0;
+ u_int8_t proto = 0, vlan_packet = 0;
+ u_int16_t thread_id = *((u_int16_t*)args);
+
+ // printf("[ndpiReader] pcap_packet_callback : [%u.%u.%u.%u.%u -> %u.%u.%u.%u.%u]\n", ethernet->h_dest[1],ethernet->h_dest[2],ethernet->h_dest[3],ethernet->h_dest[4],ethernet->h_dest[5],ethernet->h_source[1],ethernet->h_source[2],ethernet->h_source[3],ethernet->h_source[4],ethernet->h_source[5]);
+ ndpi_thread_info[thread_id].stats.raw_packet_count++;
+
+ if((capture_until != 0) && (header->ts.tv_sec >= capture_until)) {
+ if(ndpi_thread_info[thread_id]._pcap_handle != NULL)
+ pcap_breakloop(ndpi_thread_info[thread_id]._pcap_handle);
+
+ return;
+ }
+
+ if (!live_capture) {
+ if (!pcap_start.tv_sec) pcap_start.tv_sec = header->ts.tv_sec, pcap_start.tv_usec = header->ts.tv_usec;
+ pcap_end.tv_sec = header->ts.tv_sec, pcap_end.tv_usec = header->ts.tv_usec;
+ }
+
+ time = ((uint64_t) header->ts.tv_sec) * detection_tick_resolution +
+ header->ts.tv_usec / (1000000 / detection_tick_resolution);
+
+ if(ndpi_thread_info[thread_id].last_time > time) { /* safety check */
+ // printf("\nWARNING: timestamp bug in the pcap file (ts delta: %llu, repairing)\n", ndpi_thread_info[thread_id].last_time - time);
+ time = ndpi_thread_info[thread_id].last_time;
+ }
+ ndpi_thread_info[thread_id].last_time = time;
+
+ if(ndpi_thread_info[thread_id]._pcap_datalink_type == DLT_NULL) {
+ if(ntohl(*((u_int32_t*)packet)) == 2)
+ type = ETH_P_IP;
+ else
+ type = 0x86DD; /* IPv6 */
+
+ ip_offset = 4;
+ } else if(ndpi_thread_info[thread_id]._pcap_datalink_type == DLT_EN10MB) {
+ ethernet = (struct ndpi_ethhdr *) packet;
+ ip_offset = sizeof(struct ndpi_ethhdr);
+ type = ntohs(ethernet->h_proto);
+ } else if(ndpi_thread_info[thread_id]._pcap_datalink_type == 113 /* Linux Cooked Capture */) {
+ type = (packet[14] << 8) + packet[15];
+ ip_offset = 16;
+ } else
+ return;
+
+ while(1) {
+ if(type == 0x8100 /* VLAN */) {
+ vlan_id = ((packet[ip_offset] << 8) + packet[ip_offset+1]) & 0xFFF;
+ type = (packet[ip_offset+2] << 8) + packet[ip_offset+3];
+ ip_offset += 4;
+ vlan_packet = 1;
+ } else if(type == 0x8847 /* MPLS */) {
+ u_int32_t label = ntohl(*((u_int32_t*)&packet[ip_offset]));
+
+ ndpi_thread_info[thread_id].stats.mpls_count++;
+ type = 0x800, ip_offset += 4;
+
+ while((label & 0x100) != 0x100) {
+ ip_offset += 4;
+ label = ntohl(*((u_int32_t*)&packet[ip_offset]));
+ }
+ } else if(type == 0x8864 /* PPPoE */) {
+ ndpi_thread_info[thread_id].stats.pppoe_count++;
+ type = 0x0800;
+ ip_offset += 8;
+ } else
+ break;
+ }
+
+ ndpi_thread_info[thread_id].stats.vlan_count += vlan_packet;
+
+ iph = (struct ndpi_iphdr *) &packet[ip_offset];
+
+ // just work on Ethernet packets that contain IP
+ if(type == ETH_P_IP && header->caplen >= ip_offset) {
+ frag_off = ntohs(iph->frag_off);
+
+ proto = iph->protocol;
+ if(header->caplen < header->len) {
+ static u_int8_t cap_warning_used = 0;
+
+ if(cap_warning_used == 0) {
+ if(!json_flag) printf("\n\nWARNING: packet capture size is smaller than packet size, DETECTION MIGHT NOT WORK CORRECTLY\n\n");
+ cap_warning_used = 1;
+ }
+ }
+ }
+
+ if(iph->version == 4) {
+ ip_len = ((u_short)iph->ihl * 4);
+ iph6 = NULL;
+
+ if((frag_off & 0x3FFF) != 0) {
+ static u_int8_t ipv4_frags_warning_used = 0;
+
+ ndpi_thread_info[thread_id].stats.fragmented_count++;
+ if(ipv4_frags_warning_used == 0) {
+ if(!json_flag) printf("\n\nWARNING: IPv4 fragments are not handled by this demo (nDPI supports them)\n");
+ ipv4_frags_warning_used = 1;
+ }
+
+ ndpi_thread_info[thread_id].stats.total_discarded_bytes += header->len;
+ return;
+ }
+ } else if(iph->version == 6) {
+ iph6 = (struct ndpi_ip6_hdr *)&packet[ip_offset];
+ proto = iph6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
+ ip_len = sizeof(struct ndpi_ip6_hdr);
+
+ if(proto == 0x3C /* IPv6 destination option */) {
+ u_int8_t *options = (u_int8_t*)&packet[ip_offset+ip_len];
+
+ proto = options[0];
+ ip_len += 8 * (options[1] + 1);
+ }
+
+ iph = NULL;
+ } else {
+ static u_int8_t ipv4_warning_used = 0;
+
+ v4_warning:
+ if(ipv4_warning_used == 0) {
+ if(!json_flag) printf("\n\nWARNING: only IPv4/IPv6 packets are supported in this demo (nDPI supports both IPv4 and IPv6), all other packets will be discarded\n\n");
+ ipv4_warning_used = 1;
+ }
+
+ ndpi_thread_info[thread_id].stats.total_discarded_bytes += header->len;
+ return;
+ }
+
+ if(decode_tunnels && (proto == IPPROTO_UDP)) {
+ struct ndpi_udphdr *udp = (struct ndpi_udphdr *)&packet[ip_offset+ip_len];
+ u_int16_t sport = ntohs(udp->source), dport = ntohs(udp->dest);
+
+ if((sport == GTP_U_V1_PORT) || (dport == GTP_U_V1_PORT)) {
+ /* Check if it's GTPv1 */
+ u_int offset = ip_offset+ip_len+sizeof(struct ndpi_udphdr);
+ u_int8_t flags = packet[offset];
+ u_int8_t message_type = packet[offset+1];
+
+ if((((flags & 0xE0) >> 5) == 1 /* GTPv1 */) && (message_type == 0xFF /* T-PDU */)) {
+ ip_offset = ip_offset+ip_len+sizeof(struct ndpi_udphdr)+8 /* GTPv1 header len */;
+
+ if(flags & 0x04) ip_offset += 1; /* next_ext_header is present */
+ if(flags & 0x02) ip_offset += 4; /* sequence_number is present (it also includes next_ext_header and pdu_number) */
+ if(flags & 0x01) ip_offset += 1; /* pdu_number is present */
+
+ iph = (struct ndpi_iphdr *) &packet[ip_offset];
+
+ if(iph->version != 4) {
+ // printf("WARNING: not good (packet_id=%u)!\n", (unsigned int)ndpi_thread_info[thread_id].stats.raw_packet_count);
+ goto v4_warning;
+ }
+ }
+ }
+ }
+
+ // process the packet
+ packet_processing(thread_id, time, vlan_id, iph, iph6,
+ ip_offset, header->len - ip_offset, header->len);
+}
+
+/* ******************************************************************** */
+
+static void runPcapLoop(u_int16_t thread_id) {
+ if((!shutdown_app) && (ndpi_thread_info[thread_id]._pcap_handle != NULL))
+ pcap_loop(ndpi_thread_info[thread_id]._pcap_handle, -1, &pcap_packet_callback, (u_char*)&thread_id);
+}
+
+/* ******************************************************************** */
+
+void *processing_thread(void *_thread_id) {
+ long thread_id = (long) _thread_id;
+
+#ifdef linux
+ if(core_affinity[thread_id] >= 0) {
+ cpu_set_t cpuset;
+ CPU_ZERO(&cpuset);
+ CPU_SET(core_affinity[thread_id], &cpuset);
+
+ if(pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) != 0)
+ fprintf(stderr, "Error while binding thread %ld to core %d\n", thread_id, core_affinity[thread_id]);
+ else {
+ if(!json_flag) printf("Running thread %ld on core %d...\n", thread_id, core_affinity[thread_id]);
+ }
+ } else
+#endif
+ if(!json_flag) printf("Running thread %ld...\n", thread_id);
+
+ pcap_loop:
+ runPcapLoop(thread_id);
+
+ if(playlist_fp[thread_id] != NULL) { /* playlist: read next file */
+ char filename[256];
+
+ if(getNextPcapFileFromPlaylist(thread_id, filename, sizeof(filename)) == 0 &&
+ (ndpi_thread_info[thread_id]._pcap_handle = pcap_open_offline(filename, ndpi_thread_info[thread_id]._pcap_error_buffer)) != NULL) {
+ configurePcapHandle(thread_id);
+ goto pcap_loop;
+ }
+ }
+
+ return NULL;
+}
+
+/* ******************************************************************** */
+
+void test_lib() {
+ struct timeval begin, end;
+ u_int64_t tot_usec;
+ long thread_id;
+
+#ifdef HAVE_JSON_C
+ json_init();
+#endif
+
+ for(thread_id = 0; thread_id < num_threads; thread_id++) {
+ setupDetection(thread_id);
+ openPcapFileOrDevice(thread_id);
+ }
+
+ gettimeofday(&begin, NULL);
+
+ /* Running processing threads */
+ for(thread_id = 0; thread_id < num_threads; thread_id++)
+ pthread_create(&ndpi_thread_info[thread_id].pthread, NULL, processing_thread, (void *) thread_id);
+
+ /* Waiting for completion */
+ for(thread_id = 0; thread_id < num_threads; thread_id++)
+ pthread_join(ndpi_thread_info[thread_id].pthread, NULL);
+
+ gettimeofday(&end, NULL);
+ tot_usec = end.tv_sec*1000000 + end.tv_usec - (begin.tv_sec*1000000 + begin.tv_usec);
+
+ /* Printing cumulative results */
+ printResults(tot_usec);
+
+ for(thread_id = 0; thread_id < num_threads; thread_id++) {
+ closePcapFile(thread_id);
+ terminateDetection(thread_id);
+ }
+}
+
+/* ***************************************************** */
+
+int main(int argc, char **argv) {
+ int i;
+
+ memset(ndpi_thread_info, 0, sizeof(ndpi_thread_info));
+ memset(&pcap_start, 0, sizeof(pcap_start));
+ memset(&pcap_end, 0, sizeof(pcap_end));
+
+ parseOptions(argc, argv);
+
+ if(!json_flag) {
+ printf("\n-----------------------------------------------------------\n"
+ "* NOTE: This is demo app to show *some* nDPI features.\n"
+ "* In this demo we have implemented only some basic features\n"
+ "* just to show you what you can do with the library. Feel \n"
+ "* free to extend it and send us the patches for inclusion\n"
+ "------------------------------------------------------------\n\n");
+
+ printf("Using nDPI (%s) [%d thread(s)]\n", ndpi_revision(), num_threads);
+ }
+
+ signal(SIGINT, sigproc);
+
+ for(i=0; i<num_loops; i++)
+ test_lib();
+
+ return 0;
+}
+
+/* ****************************************************** */
+
+#ifdef WIN32
+#ifndef __GNUC__
+#define EPOCHFILETIME (116444736000000000i64)
+#else
+#define EPOCHFILETIME (116444736000000000LL)
+#endif
+
+struct timezone {
+ int tz_minuteswest; /* minutes W of Greenwich */
+ int tz_dsttime; /* type of dst correction */
+};
+
+/* ***************************************************** */
+
+#if 0
+int gettimeofday(struct timeval *tv, void *notUsed) {
+ tv->tv_sec = time(NULL);
+ tv->tv_usec = 0;
+ return(0);
+}
+#endif
+
+/* ***************************************************** */
+
+int gettimeofday(struct timeval *tv, struct timezone *tz) {
+ FILETIME ft;
+ LARGE_INTEGER li;
+ __int64 t;
+ static int tzflag;
+
+ if(tv) {
+ GetSystemTimeAsFileTime(&ft);
+ li.LowPart = ft.dwLowDateTime;
+ li.HighPart = ft.dwHighDateTime;
+ t = li.QuadPart; /* In 100-nanosecond intervals */
+ t -= EPOCHFILETIME; /* Offset to the Epoch time */
+ t /= 10; /* In microseconds */
+ tv->tv_sec = (long)(t / 1000000);
+ tv->tv_usec = (long)(t % 1000000);
+ }
+
+ if(tz) {
+ if(!tzflag) {
+ _tzset();
+ tzflag++;
+ }
+
+ tz->tz_minuteswest = _timezone / 60;
+ tz->tz_dsttime = _daylight;
+ }
+
+ return 0;
+}
+#endif /* WIN32 */
diff --git a/example/protos.txt b/example/protos.txt
new file mode 100644
index 000000000..722399da9
--- /dev/null
+++ b/example/protos.txt
@@ -0,0 +1,18 @@
+# Format:
+# <tcp|udp>:<port>,<tcp|udp>:<port>,.....@<proto>
+
+tcp:81,tcp:8181@HTTP
+udp:5061-5062@SIP
+tcp:860,udp:860,tcp:3260,udp:3260@iSCSI
+tcp:3000@ntop
+
+# Subprotocols
+# Format:
+# host:"<value>",host:"<value>",.....@<subproto>
+
+host:"googlesyndacation.com"@Google
+host:"venere.com"@Venere
+host:"kataweb.it",host:"repubblica.it"@Repubblica
+
+
+
diff --git a/lib b/lib
new file mode 120000
index 000000000..d049b7c46
--- /dev/null
+++ b/lib
@@ -0,0 +1 @@
+src/lib/.libs \ No newline at end of file
diff --git a/libndpi.pc.in b/libndpi.pc.in
new file mode 100644
index 000000000..291429cc7
--- /dev/null
+++ b/libndpi.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libndpi
+Description: deep packet inspection library
+Version: @VERSION@
+Libs: -L${libdir} -lndpi
+Cflags: -I${includedir}/libndpi-@VERSION@
diff --git a/libndpi.sym b/libndpi.sym
new file mode 100644
index 000000000..52307a2f4
--- /dev/null
+++ b/libndpi.sym
@@ -0,0 +1,27 @@
+ndpi_dump_protocols
+ndpi_get_proto_name
+ndpi_free
+ndpi_guess_undetected_protocol
+ndpi_tfind
+ndpi_tsearch
+ndpi_set_protocol_detection_bitmask2
+ndpi_detection_get_sizeof_ndpi_id_struct
+ndpi_detection_get_sizeof_ndpi_flow_struct
+ndpi_load_protocols_file
+ndpi_tdestroy
+ndpi_exit_detection_module
+ndpi_detection_process_packet
+ndpi_twalk
+ndpi_tdelete
+ndpi_revision
+ndpi_init_detection_module
+ndpi_get_num_supported_protocols
+ndpi_set_proto_defaults
+ndpi_get_protocol_id
+ndpi_find_port_based_protocol
+ndpi_get_http_method
+ndpi_get_http_url
+ndpi_get_http_content_type
+ndpi_free_flow
+ndpi_get_proto_breed
+ndpi_get_proto_breed_name
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
new file mode 100644
index 000000000..d383ad5c6
--- /dev/null
+++ b/m4/ax_pthread.m4
@@ -0,0 +1,332 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+#
+# DESCRIPTION
+#
+# This macro figures out how to build C programs using POSIX threads. It
+# sets the PTHREAD_LIBS output variable to the threads library and linker
+# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
+# flags that are needed. (The user can also force certain compiler
+# flags/libs to be tested by setting these environment variables.)
+#
+# Also sets PTHREAD_CC to any special C compiler that is needed for
+# multi-threaded programs (defaults to the value of CC otherwise). (This
+# is necessary on AIX to use the special cc_r compiler alias.)
+#
+# NOTE: You are assumed to not only compile your program with these flags,
+# but also link it with them as well. e.g. you should link with
+# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+#
+# If you are only building threads programs, you may wish to use these
+# variables in your default LIBS, CFLAGS, and CC:
+#
+# LIBS="$PTHREAD_LIBS $LIBS"
+# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+# CC="$PTHREAD_CC"
+#
+# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
+# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
+# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+#
+# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+# PTHREAD_CFLAGS.
+#
+# ACTION-IF-FOUND is a list of shell commands to run if a threads library
+# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
+# is not found. If ACTION-IF-FOUND is not specified, the default action
+# will define HAVE_PTHREAD.
+#
+# Please let the authors know if this macro fails on any platform, or if
+# you have any other suggestions or comments. This macro was based on work
+# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
+# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
+# Alejandro Forero Cuervo to the autoconf macro repository. We are also
+# grateful for the helpful feedback of numerous users.
+#
+# Updated for Autoconf 2.68 by Daniel Richard G.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.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 3 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, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 21
+
+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
+AC_DEFUN([AX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_PUSH([C])
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
+ AC_MSG_RESULT([$ax_pthread_ok])
+ if test x"$ax_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case ${host_os} in
+ solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
+ ;;
+
+ darwin*)
+ ax_pthread_flags="-pthread $ax_pthread_flags"
+ ;;
+esac
+
+# Clang doesn't consider unrecognized options an error unless we specify
+# -Werror. We throw in some extra Clang-specific options to ensure that
+# this doesn't happen for GCC, which also accepts -Werror.
+
+AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
+save_CFLAGS="$CFLAGS"
+ax_pthread_extra_flags="-Werror"
+CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
+ [AC_MSG_RESULT([yes])],
+ [ax_pthread_extra_flags=
+ AC_MSG_RESULT([no])])
+CFLAGS="$save_CFLAGS"
+
+if test x"$ax_pthread_ok" = xno; then
+for flag in $ax_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
+ if test x"$ax_pthread_config" = xno; then continue; fi
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+ static void routine(void *a) { a = 0; }
+ static void *start_routine(void *a) { return a; }],
+ [pthread_t th; pthread_attr_t attr;
+ pthread_create(&th, 0, start_routine, 0);
+ pthread_join(th, 0);
+ pthread_attr_init(&attr);
+ pthread_cleanup_push(routine, 0);
+ pthread_cleanup_pop(0) /* ; */])],
+ [ax_pthread_ok=yes],
+ [])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT([$ax_pthread_ok])
+ if test "x$ax_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$ax_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ attr_name=unknown
+ for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+ [int attr = $attr; return attr /* ; */])],
+ [attr_name=$attr; break],
+ [])
+ done
+ AC_MSG_RESULT([$attr_name])
+ if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
+ [Define to necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case ${host_os} in
+ aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
+ osf* | hpux*) flag="-D_REENTRANT";;
+ solaris*)
+ if test "$GCC" = "yes"; then
+ flag="-D_REENTRANT"
+ else
+ # TODO: What about Clang on Solaris?
+ flag="-mt -D_REENTRANT"
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$flag])
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+ [ax_cv_PTHREAD_PRIO_INHERIT], [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
+ [[int i = PTHREAD_PRIO_INHERIT;]])],
+ [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+ [ax_cv_PTHREAD_PRIO_INHERIT=no])
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
+ [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: compile with *_r variant
+ if test "x$GCC" != xyes; then
+ case $host_os in
+ aix*)
+ AS_CASE(["x/$CC"],
+ [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
+ [#handle absolute path differently from PATH based program lookup
+ AS_CASE(["x$CC"],
+ [x/*],
+ [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
+ [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
+ ;;
+ esac
+ fi
+fi
+
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+
+AC_SUBST([PTHREAD_LIBS])
+AC_SUBST([PTHREAD_CFLAGS])
+AC_SUBST([PTHREAD_CC])
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$ax_pthread_ok" = xyes; then
+ ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
+ :
+else
+ ax_pthread_ok=no
+ $2
+fi
+AC_LANG_POP
+])dnl AX_PTHREAD
diff --git a/ndpi-netfilter/README b/ndpi-netfilter/README
new file mode 100644
index 000000000..8cd573d61
--- /dev/null
+++ b/ndpi-netfilter/README
@@ -0,0 +1,4 @@
+This package is a GPL implementation of an iptables and netfilter module for
+nDPI integration into the Linux kernel.
+
+https://github.com/ewildgoose/ndpi-netfilter
diff --git a/packages/homebrew/README b/packages/homebrew/README
new file mode 100644
index 000000000..c05b32fde
--- /dev/null
+++ b/packages/homebrew/README
@@ -0,0 +1,11 @@
+=== HOMEBREW PACKAGE ===
+
+NB: Work in progress
+
+- SUBMIT FORMULA
+cp ndpi.rb /usr/local/Library/Formula/
+
+- INSTALL FORMULA
+#check the formula
+brew audit ndpi
+brew install -vd ndpi \ No newline at end of file
diff --git a/packages/homebrew/ndpi.rb b/packages/homebrew/ndpi.rb
new file mode 100644
index 000000000..ec06446a5
--- /dev/null
+++ b/packages/homebrew/ndpi.rb
@@ -0,0 +1,23 @@
+require "formula"
+
+class Ndpi < Formula
+ homepage "http://www.ntop.org/products/ndpi/"
+ url "https://downloads.sourceforge.net/project/ntop/nDPI/libndpi-1.5.1.tar.gz"
+ sha1 "0a6ed585545ab6611f3f0ac9efd9eb36bb5481dd"
+
+ depends_on "autoconf" => :build
+ depends_on "automake" => :build
+ depends_on "pkg-config" => :build
+ depends_on "libtool" => :build
+ depends_on "json-c"
+
+ def install
+ system "./configure","--prefix=#{prefix}"
+ system "make"
+ system "make", "install"
+ end
+
+ test do
+ system "#{bin}/ndpiReader","-h"
+ end
+end
diff --git a/packages/ubuntu/Makefile b/packages/ubuntu/Makefile
new file mode 100644
index 000000000..5f1684155
--- /dev/null
+++ b/packages/ubuntu/Makefile
@@ -0,0 +1,42 @@
+#
+# Change it according to your setup
+#
+NDPI_HOME=$(PWD)/../..
+NDPI_BUILD=${NDPI_HOME}/packages/ubuntu
+
+all: clean ndpi
+
+ndpi:
+ \rm -rf ./usr ./debian/tmp ./debian/ndpi-dev
+ mkdir -p ./usr/local ./debian/ndpi-dev
+ mkdir -p ./usr/local/ndpi/lib ./usr/local/ndpi/bin ./ndpi-dev/usr/local/include/ndpi/
+ cd ${NDPI_HOME}; ./autogen.sh; ./configure; make
+ cp $(NDPI_HOME)/lib/libndpi.a $(NDPI_HOME)/lib/libndpi.so* ./usr/local/ndpi/lib/
+ cp $(NDPI_HOME)/example/ndpiReader ./usr/local/ndpi/bin/
+ cp $(NDPI_HOME)/src/include/*.h ndpi-dev/usr/local/include/ndpi/
+ -rm -fr ndpi-dev/usr/local/include/nprobe/ndpi/.svn ndpi-dev/usr/local/include/ndpi/Makefile* ndpi-dev/usr/local/include/ndpi/ndpi_win32.h* ndpi-dev/usr/local/include/ndpi/include
+ -find ./usr/local/lib -name "*.la" -exec /bin/rm {} ';'
+ @echo
+ @find . -name "*~" -exec /bin/rm {} ';'
+ dpkg-buildpackage -rfakeroot -d -us -uc
+ dpkg-sig --sign builder -k 7921DF34 ../ndpi*deb
+ @\rm -f ../ndpi*dsc ../ndpi*.gz ../ndpi*changes
+ @/bin/mv ../ndpi*deb .
+ @echo
+ @echo "Package built."
+ @/bin/ls ndpi*deb
+ @echo "-------------------------------"
+ -dpkg --contents ndpi*amd64.deb
+ @echo "-------------------------------"
+ @echo "-------------------------------"
+ -dpkg --contents ndpi*all.deb
+ @echo "-------------------------------"
+
+distclean:
+ echo "dummy distclean"
+
+install:
+ echo "dummy install"
+
+clean:
+ -rm -rf *~ *deb debian/tmp ./usr
diff --git a/packages/ubuntu/Makefile.in b/packages/ubuntu/Makefile.in
new file mode 100644
index 000000000..5f1684155
--- /dev/null
+++ b/packages/ubuntu/Makefile.in
@@ -0,0 +1,42 @@
+#
+# Change it according to your setup
+#
+NDPI_HOME=$(PWD)/../..
+NDPI_BUILD=${NDPI_HOME}/packages/ubuntu
+
+all: clean ndpi
+
+ndpi:
+ \rm -rf ./usr ./debian/tmp ./debian/ndpi-dev
+ mkdir -p ./usr/local ./debian/ndpi-dev
+ mkdir -p ./usr/local/ndpi/lib ./usr/local/ndpi/bin ./ndpi-dev/usr/local/include/ndpi/
+ cd ${NDPI_HOME}; ./autogen.sh; ./configure; make
+ cp $(NDPI_HOME)/lib/libndpi.a $(NDPI_HOME)/lib/libndpi.so* ./usr/local/ndpi/lib/
+ cp $(NDPI_HOME)/example/ndpiReader ./usr/local/ndpi/bin/
+ cp $(NDPI_HOME)/src/include/*.h ndpi-dev/usr/local/include/ndpi/
+ -rm -fr ndpi-dev/usr/local/include/nprobe/ndpi/.svn ndpi-dev/usr/local/include/ndpi/Makefile* ndpi-dev/usr/local/include/ndpi/ndpi_win32.h* ndpi-dev/usr/local/include/ndpi/include
+ -find ./usr/local/lib -name "*.la" -exec /bin/rm {} ';'
+ @echo
+ @find . -name "*~" -exec /bin/rm {} ';'
+ dpkg-buildpackage -rfakeroot -d -us -uc
+ dpkg-sig --sign builder -k 7921DF34 ../ndpi*deb
+ @\rm -f ../ndpi*dsc ../ndpi*.gz ../ndpi*changes
+ @/bin/mv ../ndpi*deb .
+ @echo
+ @echo "Package built."
+ @/bin/ls ndpi*deb
+ @echo "-------------------------------"
+ -dpkg --contents ndpi*amd64.deb
+ @echo "-------------------------------"
+ @echo "-------------------------------"
+ -dpkg --contents ndpi*all.deb
+ @echo "-------------------------------"
+
+distclean:
+ echo "dummy distclean"
+
+install:
+ echo "dummy install"
+
+clean:
+ -rm -rf *~ *deb debian/tmp ./usr
diff --git a/packages/ubuntu/configure b/packages/ubuntu/configure
new file mode 100755
index 000000000..857a095ca
--- /dev/null
+++ b/packages/ubuntu/configure
@@ -0,0 +1,2863 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for Makefile.in 1.0.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='Makefile.in'
+PACKAGE_TARNAME='makefile-in'
+PACKAGE_VERSION='1.0'
+PACKAGE_STRING='Makefile.in 1.0'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+PFRING_SVN_RELEASE
+SVN_RELEASE
+KERNEL
+DATE
+EXTN
+MACHINE
+PFRING_VERS
+NDPI_VERS
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures Makefile.in 1.0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/makefile-in]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of Makefile.in 1.0:";;
+ esac
+ cat <<\_ACEOF
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+Makefile.in configure 1.0
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by Makefile.in $as_me 1.0, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+NDPI_VERS=`cat ../../config.h | grep -w VERSION | cut -d \" -f 2`
+PFRING_VERS=`cat $HOME/PF_RING/kernel/linux/pf_ring.h | grep RING_VERSION | head -1 | cut -d '"' -f 2`
+SVN_RELEASE=`svn info ../.. | grep "^Revision"|cut -d " " -f 2`
+PFRING_SVN_RELEASE=`svn info $HOME/PF_RING | grep "^Revision"|cut -d " " -f 2`
+MACHINE=`uname -m`
+
+if test $MACHINE = "x86_64"; then
+ EXTN="amd64"
+else
+ EXTN="i386"
+fi
+
+DATE=`date -R`
+KERNEL=`uname -r`
+
+
+
+
+
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile"
+
+ac_config_files="$ac_config_files debian/changelog"
+
+ac_config_files="$ac_config_files debian/files"
+
+ac_config_files="$ac_config_files debian/control"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by Makefile.in $as_me 1.0, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+Makefile.in config.status 1.0
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "debian/changelog") CONFIG_FILES="$CONFIG_FILES debian/changelog" ;;
+ "debian/files") CONFIG_FILES="$CONFIG_FILES debian/files" ;;
+ "debian/control") CONFIG_FILES="$CONFIG_FILES debian/control" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/packages/ubuntu/configure.in b/packages/ubuntu/configure.in
new file mode 100644
index 000000000..bf0608cf5
--- /dev/null
+++ b/packages/ubuntu/configure.in
@@ -0,0 +1,32 @@
+AC_INIT([Makefile.in], 1.0)
+
+NDPI_VERS=`cat ../../config.h | grep -w VERSION | cut -d \" -f 2`
+PFRING_VERS=`cat $HOME/PF_RING/kernel/linux/pf_ring.h | grep RING_VERSION | head -1 | cut -d '"' -f 2`
+SVN_RELEASE=`svn info ../.. | grep "^Revision"|cut -d " " -f 2`
+PFRING_SVN_RELEASE=`svn info $HOME/PF_RING | grep "^Revision"|cut -d " " -f 2`
+MACHINE=`uname -m`
+
+if test $MACHINE = "x86_64"; then
+ EXTN="amd64"
+else
+ EXTN="i386"
+fi
+
+DATE=`date -R`
+KERNEL=`uname -r`
+
+AC_SUBST(NDPI_VERS)
+AC_SUBST(PFRING_VERS)
+AC_SUBST(MACHINE)
+AC_SUBST(EXTN)
+AC_SUBST(DATE)
+AC_SUBST(KERNEL)
+AC_SUBST(SVN_RELEASE)
+AC_SUBST(PFRING_SVN_RELEASE)
+
+AC_CONFIG_FILES(Makefile)
+AC_CONFIG_FILES(debian/changelog)
+AC_CONFIG_FILES(debian/files)
+AC_CONFIG_FILES(debian/control)
+
+AC_OUTPUT
diff --git a/packages/ubuntu/debian/COPYRIGHT b/packages/ubuntu/debian/COPYRIGHT
new file mode 100644
index 000000000..d60c31a97
--- /dev/null
+++ b/packages/ubuntu/debian/COPYRIGHT
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/packages/ubuntu/debian/README b/packages/ubuntu/debian/README
new file mode 100644
index 000000000..6563a5d36
--- /dev/null
+++ b/packages/ubuntu/debian/README
@@ -0,0 +1,2 @@
+This directory contains the files needed to build the package
+named 'nprobe' for the Debian GNU/Linux distribution.
diff --git a/packages/ubuntu/debian/changelog.in b/packages/ubuntu/debian/changelog.in
new file mode 100644
index 000000000..15d86b02d
--- /dev/null
+++ b/packages/ubuntu/debian/changelog.in
@@ -0,0 +1,4 @@
+ndpi (@NDPI_VERS@-@SVN_RELEASE@) stable; urgency=high
+ * Last packaged version
+
+ -- Luca Deri <deri@ntop.org> @DATE@
diff --git a/packages/ubuntu/debian/compat b/packages/ubuntu/debian/compat
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/packages/ubuntu/debian/compat
@@ -0,0 +1 @@
+1
diff --git a/packages/ubuntu/debian/conffiles b/packages/ubuntu/debian/conffiles
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/packages/ubuntu/debian/conffiles
diff --git a/packages/ubuntu/debian/control.in b/packages/ubuntu/debian/control.in
new file mode 100644
index 000000000..56191e2eb
--- /dev/null
+++ b/packages/ubuntu/debian/control.in
@@ -0,0 +1,28 @@
+Source: ndpi
+Section: free
+Priority: optional
+Maintainer: Luca Deri <deri@ntop.org>
+Standards-Version: @NDPI_VERSION@
+Build-Depends:
+Build-Conflicts:
+
+Package: ndpi
+Architecture: @EXTN@
+Depends: pfring (=@PFRING_VERS@-@PFRING_SVN_RELEASE@), libnuma
+Recommends:
+Suggests:
+Pre-Depends:
+Conflicts:
+Provides:
+Replaces:
+Description: A network probe.
+
+Package: ndpi-dev
+Section: libdevel
+Architecture: all
+Depends: ndpi (= ${binary:Version}), ${misc:Depends}
+Conflicts:
+Description: development library and header files for ndpi
+ Headers, static libraries, and documentation for the ndpi library
+
+
diff --git a/packages/ubuntu/debian/dirs b/packages/ubuntu/debian/dirs
new file mode 100644
index 000000000..c648ad7d0
--- /dev/null
+++ b/packages/ubuntu/debian/dirs
@@ -0,0 +1 @@
+usr/local/ndpi
diff --git a/packages/ubuntu/debian/docs b/packages/ubuntu/debian/docs
new file mode 100644
index 000000000..e845566c0
--- /dev/null
+++ b/packages/ubuntu/debian/docs
@@ -0,0 +1 @@
+README
diff --git a/packages/ubuntu/debian/files.in b/packages/ubuntu/debian/files.in
new file mode 100644
index 000000000..8f8691216
--- /dev/null
+++ b/packages/ubuntu/debian/files.in
@@ -0,0 +1 @@
+ndpi_@NDPI_VERS@_@EXTN@.deb free optional
diff --git a/packages/ubuntu/debian/postinst b/packages/ubuntu/debian/postinst
new file mode 100755
index 000000000..65bf04230
--- /dev/null
+++ b/packages/ubuntu/debian/postinst
@@ -0,0 +1,34 @@
+#!/bin/sh -e
+
+case "$1" in
+ configure)
+ # continue below
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ exit 0
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 0
+ ;;
+esac
+
+umask 022
+
+# Update shared libs
+echo "/usr/local/lib\n" > /etc/ld.so.conf.d/nprobe.conf
+echo "Rebuilding ld cache..."
+/sbin/ldconfig
+
+echo "Adding the nprobe startup script"
+update-rc.d nprobe defaults 93 >/dev/null
+
+echo "Making the /etc/nprobe directory..."
+mkdir -p /etc/nprobe/
+
+echo "Making the /var/log/nprobe directory..."
+mkdir -p /var/log/nprobe
+
+exit 0
diff --git a/packages/ubuntu/debian/postrm b/packages/ubuntu/debian/postrm
new file mode 100644
index 000000000..8ea16af2d
--- /dev/null
+++ b/packages/ubuntu/debian/postrm
@@ -0,0 +1,13 @@
+#!/bin/sh -e
+
+set -e
+
+#\/bin/rm /etc/ld.so.conf.d/nprobe.conf
+/sbin/ldconfig
+
+# Not needed: upstart does it
+if [ "$1" = "purge" ] ; then
+ update-rc.d nprobe remove >/dev/null
+fi
+
+exit 0
diff --git a/packages/ubuntu/debian/preinst b/packages/ubuntu/debian/preinst
new file mode 100644
index 000000000..cf9323e94
--- /dev/null
+++ b/packages/ubuntu/debian/preinst
@@ -0,0 +1,35 @@
+#! /bin/sh
+# preinst script for nbox
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <new-preinst> `install'
+# * <new-preinst> `install' <old-version>
+# * <new-preinst> `upgrade' <old-version>
+# * <old-preinst> `abort-upgrade' <new-version>
+
+case "$1" in
+ install|upgrade)
+ if test -f /usr/local/sbin/nprobe; then
+ rm /usr/local/sbin/nprobe
+ fi
+ ;;
+
+ abort-upgrade)
+ ;;
+
+ *)
+ echo "preinst called with unknown argument \`$1'" >&2
+ exit 0
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+
+
+exit 0
diff --git a/packages/ubuntu/debian/prerm b/packages/ubuntu/debian/prerm
new file mode 100755
index 000000000..58af3b74c
--- /dev/null
+++ b/packages/ubuntu/debian/prerm
@@ -0,0 +1,14 @@
+#!/bin/sh -e
+
+# Only shut the daemon down if we're really removing the package. If this is
+# an upgrade, we will instead do a restart in the postinst... this keeps nprobe
+# from being left shut down for a long time, which could pose problems.
+case "$1" in
+upgrade)
+ ;;
+*)
+ /etc/init.d/nprobe stop
+ ;;
+esac
+
+exit 0 \ No newline at end of file
diff --git a/packages/ubuntu/debian/rules b/packages/ubuntu/debian/rules
new file mode 100755
index 000000000..0000bdaf5
--- /dev/null
+++ b/packages/ubuntu/debian/rules
@@ -0,0 +1,59 @@
+#!/usr/bin/make -f
+
+# Uncomment this to turn on verbose mode.
+# export DH_VERBOSE=1
+
+#
+# debian/compat
+# We should use at least comparibily version 5
+# but this requires the whole building process
+# to be remade and this is something we leave
+# to when we will have more time
+# http://www.tin.org/bin/man.cgi?section=7&topic=debhelper
+#
+
+package=ndpi
+
+build: build-stamp
+build-stamp:
+ dh_testdir
+
+clean:
+ dh_testdir
+ dh_testroot
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+ dh_installinit
+ dh_installman
+# install the files into debian/tmp.
+ cp -r ./usr/ ./debian/tmp
+ cp -r ./ndpi-dev/* ./debian/ndpi-dev/
+ -find ./debian/tmp -name .svn -exec /bin/rm -rf {} ';'
+ -find ./debian/tmp -executable -type f |xargs strip
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_installdeb
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
new file mode 100644
index 000000000..71a507ae2
--- /dev/null
+++ b/src/include/Makefile.am
@@ -0,0 +1,9 @@
+
+library_includedir=$(includedir)/libndpi-1.4/libndpi
+
+library_include_HEADERS = ndpi_api.h \
+ ndpi_debug_functions.h \
+ ndpi_define.h \
+ ndpi_macros.h \
+ ndpi_protocols_osdpi.h \
+ ndpi_public_functions.h
diff --git a/src/include/linux_compat.h b/src/include/linux_compat.h
new file mode 100644
index 000000000..38601f180
--- /dev/null
+++ b/src/include/linux_compat.h
@@ -0,0 +1,188 @@
+/*
+ * linux_compat.h
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifndef __NDPI_LINUX_COMPAT_H__
+#define __NDPI_LINUX_COMPAT_H__
+
+#include "ndpi_define.h"
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#include <machine/endian.h>
+
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+#ifndef __LITTLE_ENDIAN__
+#define __LITTLE_ENDIAN__ 1
+#endif
+#else
+#ifndef __BIG_ENDIAN__
+#define __BIG_ENDIAN__ 1
+#endif
+#endif
+#endif
+
+#pragma pack(push, 1) /* push current alignment to stack */
+#pragma pack(1) /* set alignment to 1 byte boundary */
+
+#pragma pack(pop) /* restore original alignment from stack */
+
+struct ndpi_ethhdr {
+ u_char h_dest[6]; /* destination eth addr */
+ u_char h_source[6]; /* source ether addr */
+ u_int16_t h_proto; /* packet type ID field */
+};
+
+struct ndpi_80211q {
+ u_int16_t vlanId;
+ u_int16_t protoType;
+};
+
+struct ndpi_iphdr {
+#if defined(__LITTLE_ENDIAN__)
+ u_int8_t ihl:4, version:4;
+#elif defined(__BIG_ENDIAN__)
+ u_int8_t version:4, ihl:4;
+#else
+# error "Byte order must be defined"
+#endif
+ u_int8_t tos;
+ u_int16_t tot_len;
+ u_int16_t id;
+ u_int16_t frag_off;
+ u_int8_t ttl;
+ u_int8_t protocol;
+ u_int16_t check;
+ u_int32_t saddr;
+ u_int32_t daddr;
+};
+
+
+#ifdef WIN32
+
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int uint;
+typedef unsigned long u_long;
+typedef u_char u_int8_t;
+typedef u_short u_int16_t;
+typedef uint u_int32_t;
+
+#define _WS2TCPIP_H_ /* Avoid compilation problems */
+#define HAVE_SIN6_LEN
+
+
+/* IPv6 address */
+/* Already defined in WS2tcpip.h */
+struct ndpi_win_in6_addr
+{
+ union
+ {
+ u_int8_t u6_addr8[16];
+ u_int16_t u6_addr16[8];
+ u_int32_t u6_addr32[4];
+ } in6_u;
+#ifdef s6_addr
+#undef s6_addr
+#endif
+
+#ifdef s6_addr16
+#undef s6_addr16
+#endif
+
+#ifdef s6_addr32
+#undef s6_addr32
+#endif
+
+#define s6_addr in6_u.u6_addr8
+ // #define s6_addr16 in6_u.u6_addr16
+ // #define s6_addr32 in6_u.u6_addr32
+
+};
+
+#define in6_addr win_in6_addr
+
+/* Generic extension header. */
+struct ndpi_ip6_ext
+{
+ u_int8_t ip6e_nxt; /* next header. */
+ u_int8_t ip6e_len; /* length in units of 8 octets. */
+};
+
+#define s6_addr16 __u6_addr.__u6_addr16
+#define s6_addr32 __u6_addr.__u6_addr32
+#else
+#ifndef __KERNEL__
+#include <arpa/inet.h>
+#endif
+#endif
+
+
+
+struct ndpi_in6_addr {
+ union {
+ u_int8_t __u6_addr8[16];
+ u_int16_t __u6_addr16[8];
+ u_int32_t __u6_addr32[4];
+ } __u6_addr; /* 128-bit IP6 address */
+};
+
+struct ndpi_ip6_hdr {
+ union {
+ struct ndpi_ip6_hdrctl {
+ u_int32_t ip6_un1_flow;
+ u_int16_t ip6_un1_plen;
+ u_int8_t ip6_un1_nxt;
+ u_int8_t ip6_un1_hlim;
+ } ip6_un1;
+ u_int8_t ip6_un2_vfc;
+ } ip6_ctlun;
+ struct ndpi_in6_addr ip6_src;
+ struct ndpi_in6_addr ip6_dst;
+};
+
+struct ndpi_tcphdr {
+ u_int16_t source;
+ u_int16_t dest;
+ u_int32_t seq;
+ u_int32_t ack_seq;
+#if defined(__LITTLE_ENDIAN__)
+ u_int16_t res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1;
+#elif defined(__BIG_ENDIAN__)
+ u_int16_t doff:4, res1:4, cwr:1, ece:1, urg:1, ack:1, psh:1, rst:1, syn:1, fin:1;
+#else
+# error "Byte order must be defined"
+#endif
+ u_int16_t window;
+ u_int16_t check;
+ u_int16_t urg_ptr;
+};
+
+struct ndpi_udphdr {
+ u_int16_t source;
+ u_int16_t dest;
+ u_int16_t len;
+ u_int16_t check;
+};
+
+#endif
diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h
new file mode 100644
index 000000000..2bfd345f9
--- /dev/null
+++ b/src/include/ndpi_api.h
@@ -0,0 +1,242 @@
+/*
+ * ndpi_api.h
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifndef __NDPI_PUBLIC_FUNCTIONS_H__
+#define __NDPI_PUBLIC_FUNCTIONS_H__
+
+#include "ndpi_main.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * This function returns the size of the flow struct
+ * @return the size of the flow struct
+ */
+ u_int32_t ndpi_detection_get_sizeof_ndpi_flow_struct(void);
+
+ /**
+ * This function returns the size of the id struct
+ * @return the size of the id struct
+ */
+ u_int32_t ndpi_detection_get_sizeof_ndpi_id_struct(void);
+
+
+ /* Public malloc/free */
+ void* ndpi_malloc(unsigned long size);
+ void* ndpi_calloc(unsigned long count, unsigned long size);
+ void ndpi_free(void *ptr);
+ void *ndpi_realloc(void *ptr, size_t old_size, size_t new_size);
+ char *ndpi_strdup(const char *s);
+ /*
+ * Find the first occurrence of find in s, where the search is limited to the
+ * first slen characters of s.
+ */
+ char* ndpi_strnstr(const char *s, const char *find, size_t slen);
+
+ /**
+ * This function returns the nDPI protocol id for IP-based protocol detection
+ */
+ u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, struct in_addr *pin);
+
+ /**
+ * Same as ndpi_network_ptree_match
+ */
+ u_int16_t ndpi_host_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t host);
+
+ /**
+ * This function returns a new initialized detection module.
+ * @param ticks_per_second the timestamp resolution per second (like 1000 for millisecond resolution)
+ * @param ndpi_malloc function pointer to a memory allocator
+ * @param ndpi_debug_printf a function pointer to a debug output function, use NULL in productive envionments
+ * @return the initialized detection module
+ */
+ struct ndpi_detection_module_struct *ndpi_init_detection_module(u_int32_t ticks_per_second,
+ void* (*__ndpi_malloc)(unsigned long size),
+ void (*__ndpi_free)(void *ptr),
+ ndpi_debug_function_ptr ndpi_debug_printf);
+
+
+ /**
+ * This function frees the memory allocated in the specified flow
+ * @param flow to free
+ */
+ void ndpi_free_flow(struct ndpi_flow_struct *flow);
+
+ /**
+ * This function enables cache support in nDPI used for some protocol such as Skype
+ * @param cache host name
+ * @param cache port
+ */
+ void ndpi_enable_cache(struct ndpi_detection_module_struct *ndpi_mod, char* host, u_int port);
+
+ /**
+ * This function destroys the detection module
+ * @param ndpi_struct the to clearing detection module
+ * @param ndpi_free function pointer to a memory free function
+ */
+ void
+ ndpi_exit_detection_module(struct ndpi_detection_module_struct
+ *ndpi_struct, void (*ndpi_free) (void *ptr));
+
+ /**
+ * This function sets the protocol bitmask2
+ * @param ndpi_struct the detection module
+ * @param detection_bitmask the protocol bitmask
+ */
+ void
+ ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_struct,
+ const NDPI_PROTOCOL_BITMASK * detection_bitmask);
+ /**
+ * This function will processes one packet and returns the ID of the detected protocol.
+ * This is the main packet processing function.
+ *
+ * @param ndpi_struct the detection module
+ * @param flow void pointer to the connection state machine
+ * @param packet the packet as unsigned char pointer with the length of packetlen. the pointer must point to the Layer 3 (IP header)
+ * @param packetlen the length of the packet
+ * @param current_tick the current timestamp for the packet
+ * @param src void pointer to the source subscriber state machine
+ * @param dst void pointer to the destination subscriber state machine
+ * @return returns the detected ID of the protocol
+ */
+ unsigned int
+ ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ const unsigned char *packet,
+ const unsigned short packetlen,
+ const u_int64_t current_tick,
+ struct ndpi_id_struct *src,
+ struct ndpi_id_struct *dst);
+
+#define NDPI_DETECTION_ONLY_IPV4 ( 1 << 0 )
+#define NDPI_DETECTION_ONLY_IPV6 ( 1 << 1 )
+
+ /**
+ * query the pointer to the layer 4 packet
+ *
+ * @param l3 pointer to the layer 3 data
+ * @param l3_len length of the layer 3 data
+ * @param l4_return filled with the pointer the layer 4 data if return value == 0, undefined otherwise
+ * @param l4_len_return filled with the length of the layer 4 data if return value == 0, undefined otherwise
+ * @param l4_protocol_return filled with the protocol of the layer 4 data if return value == 0, undefined otherwise
+ * @param flags limit operation on ipv4 or ipv6 packets, possible values are NDPI_DETECTION_ONLY_IPV4 or NDPI_DETECTION_ONLY_IPV6; 0 means any
+ * @return 0 if correct layer 4 data could be found, != 0 otherwise
+ */
+ u_int8_t ndpi_detection_get_l4(const u_int8_t * l3, u_int16_t l3_len, const u_int8_t ** l4_return, u_int16_t * l4_len_return,
+ u_int8_t * l4_protocol_return, u_int32_t flags);
+ /**
+ * returns the real protocol for the flow of the last packet given to the detection.
+ * if no real protocol could be found, the unknown protocol will be returned.
+ *
+ * @param ndpi_struct the detection module
+ * @return the protocol id of the last real protocol found in the protocol history of the flow
+ */
+ u_int16_t ndpi_detection_get_real_protocol_of_flow(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+
+ /**
+ * returns true if the protocol history of the flow of the last packet given to the detection
+ * contains the given protocol.
+ *
+ * @param ndpi_struct the detection module
+ * @return 1 if protocol has been found, 0 otherwise
+ */
+ u_int8_t ndpi_detection_flow_protocol_history_contains_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t protocol_id);
+ unsigned int ndpi_find_port_based_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int8_t proto, u_int32_t shost, u_int16_t sport, u_int32_t dhost, u_int16_t dport);
+ unsigned int ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int8_t proto, u_int32_t shost, u_int16_t sport, u_int32_t dhost, u_int16_t dport);
+ int ndpi_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, char *string_to_match, u_int string_to_match_len);
+ int ndpi_match_content_subprotocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ char *string_to_match, u_int string_to_match_len);
+ int ndpi_match_bigram(struct ndpi_detection_module_struct *ndpi_struct,
+ ndpi_automa *automa, char *bigram_to_match);
+ char* ndpi_get_proto_name(struct ndpi_detection_module_struct *mod, u_int16_t proto_id);
+ ndpi_protocol_breed_t ndpi_get_proto_breed(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t proto);
+ char* ndpi_get_proto_breed_name(struct ndpi_detection_module_struct *ndpi_struct, ndpi_protocol_breed_t breed_id);
+ int ndpi_get_protocol_id(struct ndpi_detection_module_struct *ndpi_mod, char *proto);
+ void ndpi_dump_protocols(struct ndpi_detection_module_struct *mod);
+ int matchStringProtocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow,
+ char *string_to_match, u_int string_to_match_len);
+
+ int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, char* path);
+ u_int ndpi_get_num_supported_protocols(struct ndpi_detection_module_struct *ndpi_mod);
+ char* ndpi_revision(void);
+ void ndpi_set_automa(struct ndpi_detection_module_struct *ndpi_struct, void* automa);
+
+#define ADD_TO_DETECTION_BITMASK 1
+#define NO_ADD_TO_DETECTION_BITMASK 0
+#define SAVE_DETECTION_BITMASK_AS_UNKNOWN 1
+#define NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN 0
+
+ /**
+ * This function sets a single protocol bitmask
+ * @param label Protocol name
+ * @param ndpi_struct the detection module
+ * @param detection_bitmask the protocol bitmask
+ * @param idx the index of the callback_buffer
+ * @param func void function point of the protocol search
+ * @param ndpi_selection_bitmask the protocol selected bitmask
+ * @param b_save_bitmask_unknow set true if you want save the detection bitmask as unknow
+ * @param b_add_detection_bitmask set true if you want add the protocol bitmask to the detection bitmask
+ * NB: this function does not increment the index of the callback_buffer
+ */
+ void ndpi_set_bitmask_protocol_detection(char * label, struct ndpi_detection_module_struct *ndpi_struct,
+ const NDPI_PROTOCOL_BITMASK * detection_bitmask,
+ const u_int32_t idx,
+ u_int16_t ndpi_protocol_id,
+ void (*func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow),
+ const NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_bitmask,
+ u_int8_t b_save_bitmask_unknow,
+ u_int8_t b_add_detection_bitmask);
+
+#ifdef NDPI_PROTOCOL_HTTP
+ /*
+ API used to retrieve information for HTTP flows
+ */
+ ndpi_http_method ndpi_get_http_method(struct ndpi_detection_module_struct *ndpi_mod,
+ struct ndpi_flow_struct *flow);
+
+ char* ndpi_get_http_url(struct ndpi_detection_module_struct *ndpi_mod,
+ struct ndpi_flow_struct *flow);
+
+ char* ndpi_get_http_content_type(struct ndpi_detection_module_struct *ndpi_mod,
+ struct ndpi_flow_struct *flow);
+#endif
+
+#ifdef NDPI_PROTOCOL_TOR
+ int ndpi_is_ssl_tor(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, char *certificate);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/include/ndpi_define.h b/src/include/ndpi_define.h
new file mode 100644
index 000000000..365012adb
--- /dev/null
+++ b/src/include/ndpi_define.h
@@ -0,0 +1,309 @@
+/*
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __NDPI_DEFINE_INCLUDE_FILE__
+#define __NDPI_DEFINE_INCLUDE_FILE__
+
+/*
+ gcc -E -dM - < /dev/null |grep ENDIAN
+*/
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#include <machine/endian.h>
+#endif
+
+#ifdef __OpenBSD__
+#include <endian.h>
+#define __BYTE_ORDER BYTE_ORDER
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define __LITTLE_ENDIAN__
+#else
+#define __BIG_ENDIAN__
+#endif/* BYTE_ORDER */
+#endif/* __OPENBSD__ */
+
+#if 0
+#ifndef NDPI_ENABLE_DEBUG_MESSAGES
+#define NDPI_ENABLE_DEBUG_MESSAGES
+#endif
+#endif
+
+#ifdef WIN32
+#define __LITTLE_ENDIAN__ 1
+#endif
+
+#if !(defined(__LITTLE_ENDIAN__) || defined(__BIG_ENDIAN__))
+#if defined(__mips__)
+#undef __LITTLE_ENDIAN__
+#undef __LITTLE_ENDIAN
+#define __BIG_ENDIAN__
+#endif
+
+/* Kernel modules */
+#if defined(__LITTLE_ENDIAN)
+#define __LITTLE_ENDIAN__
+#endif
+#if defined(__BIG_ENDIAN)
+#define __BIG_ENDIAN__
+#endif
+/* Everything else */
+#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__))
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define __LITTLE_ENDIAN__
+#else
+#define __BIG_ENDIAN__
+#endif
+#endif
+
+#endif
+
+#define NDPI_USE_ASYMMETRIC_DETECTION 0
+#define NDPI_SELECTION_BITMASK_PROTOCOL_SIZE u_int32_t
+
+#define NDPI_SELECTION_BITMASK_PROTOCOL_IP (1<<0)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP (1<<1)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP (1<<2)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP (1<<3)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD (1<<4)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION (1<<5)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 (1<<6)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6 (1<<7)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC (1<<8)
+/* now combined detections */
+
+/* v4 */
+#define NDPI_SELECTION_BITMASK_PROTOCOL_TCP (NDPI_SELECTION_BITMASK_PROTOCOL_IP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP)
+
+/* v6 */
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V6_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP)
+
+/* v4 or v6 */
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP (NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP)
+
+
+#define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+
+/* does it make sense to talk about udp with payload ??? have you ever seen empty udp packets ? */
+#define NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V6_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V6_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+
+#define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+
+#define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION)
+
+#define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION)
+
+#define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+
+#define NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+#define NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION (NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION | NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD)
+
+/* safe src/dst protocol check macros... */
+
+#define NDPI_SRC_HAS_PROTOCOL(src,protocol) ((src) != NULL && NDPI_COMPARE_PROTOCOL_TO_BITMASK((src)->detected_protocol_bitmask,(protocol)) != 0)
+
+#define NDPI_DST_HAS_PROTOCOL(dst,protocol) ((dst) != NULL && NDPI_COMPARE_PROTOCOL_TO_BITMASK((dst)->detected_protocol_bitmask,(protocol)) != 0)
+
+#define NDPI_SRC_OR_DST_HAS_PROTOCOL(src,dst,protocol) (NDPI_SRC_HAS_PROTOCOL(src,protocol) || NDPI_SRC_HAS_PROTOCOL(dst,protocol))
+
+/**
+ * convenience macro to check for excluded protocol
+ * a protocol is excluded if the flow is known and either the protocol is not detected at all
+ * or the excluded bitmask contains the protocol
+ */
+#define NDPI_FLOW_PROTOCOL_EXCLUDED(ndpi_struct,flow,protocol) ((flow) != NULL && \
+ ( NDPI_COMPARE_PROTOCOL_TO_BITMASK((ndpi_struct)->detection_bitmask, (protocol)) == 0 || \
+ NDPI_COMPARE_PROTOCOL_TO_BITMASK((flow)->excluded_protocol_bitmask, (protocol)) != 0 ) )
+
+/* misc definitions */
+#define NDPI_DEFAULT_MAX_TCP_RETRANSMISSION_WINDOW_SIZE 0x10000
+
+
+/* TODO: rebuild all memory areas to have a more aligned memory block here */
+
+/* DEFINITION OF MAX LINE NUMBERS FOR line parse algorithm */
+#define NDPI_MAX_PARSE_LINES_PER_PACKET 64
+
+#define MAX_PACKET_COUNTER 65000
+#define MAX_DEFAULT_PORTS 5
+
+/**********************
+ * detection features *
+ **********************/
+#define NDPI_SELECT_DETECTION_WITH_REAL_PROTOCOL ( 1 << 0 )
+
+#define NDPI_DIRECTCONNECT_CONNECTION_IP_TICK_TIMEOUT 600
+#define NDPI_IRC_CONNECTION_TIMEOUT 120
+#define NDPI_GNUTELLA_CONNECTION_TIMEOUT 60
+#define NDPI_BATTLEFIELD_CONNECTION_TIMEOUT 60
+#define NDPI_THUNDER_CONNECTION_TIMEOUT 30
+#define NDPI_RTSP_CONNECTION_TIMEOUT 5
+#define NDPI_TVANTS_CONNECTION_TIMEOUT 5
+#define NDPI_YAHOO_DETECT_HTTP_CONNECTIONS 1
+#define NDPI_YAHOO_LAN_VIDEO_TIMEOUT 30
+#define NDPI_ZATTOO_CONNECTION_TIMEOUT 120
+#define NDPI_ZATTOO_FLASH_TIMEOUT 5
+#define NDPI_JABBER_STUN_TIMEOUT 30
+#define NDPI_JABBER_FT_TIMEOUT 5
+#define NDPI_SOULSEEK_CONNECTION_IP_TICK_TIMEOUT 600
+
+#ifdef NDPI_ENABLE_DEBUG_MESSAGES
+
+#define NDPI_LOG(proto, mod, log_level, args...) \
+ { \
+ if(mod != NULL) { \
+ mod->ndpi_debug_print_file=__FILE__; \
+ mod->ndpi_debug_print_function=__FUNCTION__; \
+ mod->ndpi_debug_print_line=__LINE__; \
+ mod->ndpi_debug_printf(proto, mod, log_level, args); \
+ } \
+ }
+
+#else /* NDPI_ENABLE_DEBUG_MESSAGES */
+
+#if defined(WIN32)
+#define NDPI_LOG(...) {}
+#else
+#define NDPI_LOG(proto, mod, log_level, args...) {}
+#endif
+
+#endif /* NDPI_ENABLE_DEBUG_MESSAGES */
+
+/**
+ * macro for getting the string len of a static string
+ *
+ * use it instead of strlen to avoid runtime calculations
+ */
+#define NDPI_STATICSTRING_LEN( s ) ( sizeof( s ) - 1 )
+
+/** macro to compare 2 IPv6 addresses with each other to identify the "smaller" IPv6 address */
+#define NDPI_COMPARE_IPV6_ADDRESS_STRUCTS(x,y) \
+ ((((u_int64_t *)(x))[0]) < (((u_int64_t *)(y))[0]) || ( (((u_int64_t *)(x))[0]) == (((u_int64_t *)(y))[0]) && (((u_int64_t *)(x))[1]) < (((u_int64_t *)(y))[1])) )
+
+#if !defined(__KERNEL__) && !defined(NDPI_IPTABLES_EXT)
+#define NDPI_NUM_BITS 256
+#else
+/* custom protocols not supported */
+#define NDPI_NUM_BITS 192
+#endif
+
+#define NDPI_BITS /* 32 */ (sizeof(ndpi_ndpi_mask) * 8 /* number of bits in a byte */) /* bits per mask */
+#define howmanybits(x, y) (((x)+((y)-1))/(y))
+
+
+#define NDPI_SET(p, n) ((p)->fds_bits[(n)/NDPI_BITS] |= (1 << (((u_int32_t)n) % NDPI_BITS)))
+#define NDPI_CLR(p, n) ((p)->fds_bits[(n)/NDPI_BITS] &= ~(1 << (((u_int32_t)n) % NDPI_BITS)))
+#define NDPI_ISSET(p, n) ((p)->fds_bits[(n)/NDPI_BITS] & (1 << (((u_int32_t)n) % NDPI_BITS)))
+#define NDPI_ZERO(p) memset((char *)(p), 0, sizeof(*(p)))
+#define NDPI_ONE(p) memset((char *)(p), 0xFF, sizeof(*(p)))
+
+#define NDPI_NUM_FDS_BITS howmanybits(NDPI_NUM_BITS, NDPI_BITS)
+
+#define NDPI_PROTOCOL_BITMASK ndpi_protocol_bitmask_struct_t
+
+#define NDPI_BITMASK_ADD(a,b) NDPI_SET(&a,b)
+#define NDPI_BITMASK_DEL(a,b) NDPI_CLR(&a,b)
+#define NDPI_BITMASK_RESET(a) NDPI_ZERO(&a)
+#define NDPI_BITMASK_SET_ALL(a) NDPI_ONE(&a)
+#define NDPI_BITMASK_SET(a, b) { memcpy(&a, &b, sizeof(NDPI_PROTOCOL_BITMASK)); }
+
+/* this is a very very tricky macro *g*,
+ * the compiler will remove all shifts here if the protocol is static...
+ */
+#define NDPI_ADD_PROTOCOL_TO_BITMASK(bmask,value) NDPI_SET(&bmask,value)
+#define NDPI_DEL_PROTOCOL_FROM_BITMASK(bmask,value) NDPI_CLR(&bmask,value)
+#define NDPI_COMPARE_PROTOCOL_TO_BITMASK(bmask,value) NDPI_ISSET(&bmask,value)
+
+#define NDPI_SAVE_AS_BITMASK(bmask,value) { NDPI_ZERO(&bmask) ; NDPI_ADD_PROTOCOL_TO_BITMASK(bmask, value); }
+
+
+#define ndpi_min(a,b) ((a < b) ? a : b)
+#define ndpi_max(a,b) ((a > b) ? a : b)
+
+#define NDPI_PARSE_PACKET_LINE_INFO(ndpi_struct,flow,packet) \
+ if (packet->packet_lines_parsed_complete != 1) { \
+ ndpi_parse_packet_line_info(ndpi_struct,flow); \
+ } \
+
+#define NDPI_IPSEC_PROTOCOL_ESP 50
+#define NDPI_IPSEC_PROTOCOL_AH 51
+#define NDPI_GRE_PROTOCOL_TYPE 0x2F
+#define NDPI_ICMP_PROTOCOL_TYPE 0x01
+#define NDPI_IGMP_PROTOCOL_TYPE 0x02
+#define NDPI_EGP_PROTOCOL_TYPE 0x08
+#define NDPI_OSPF_PROTOCOL_TYPE 0x59
+#define NDPI_SCTP_PROTOCOL_TYPE 132
+#define NDPI_IPIP_PROTOCOL_TYPE 0x04
+#define NDPI_ICMPV6_PROTOCOL_TYPE 0x3a
+
+/* the get_uXX will return raw network packet bytes !! */
+#define get_u_int8_t(X,O) (*(u_int8_t *)(((u_int8_t *)X) + O))
+#define get_u_int16_t(X,O) (*(u_int16_t *)(((u_int8_t *)X) + O))
+#define get_u_int32_t(X,O) (*(u_int32_t *)(((u_int8_t *)X) + O))
+#define get_u_int64_t(X,O) (*(u_int64_t *)(((u_int8_t *)X) + O))
+
+/* new definitions to get little endian from network bytes */
+#define get_ul8(X,O) get_u_int8_t(X,O)
+
+
+#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN)
+#define get_l16(X,O) get_u_int16_t(X,O)
+#define get_l32(X,O) get_u_int32_t(X,O)
+#elif defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN)
+/* convert the bytes from big to little endian */
+#ifndef __KERNEL__
+# define get_l16(X,O) bswap_16(get_u_int16_t(X,O))
+# define get_l32(X,O) bswap_32(get_u_int32_t(X,O))
+#else
+# define get_l16(X,O) __cpu_to_le16(get_u_int16_t(X,O))
+# define get_l32(X,O) __cpu_to_le32(get_u_int32_t(X,O))
+#endif
+
+#else
+
+#error "__BYTE_ORDER MUST BE DEFINED !"
+
+#endif /* __BYTE_ORDER */
+
+/* define memory callback function */
+#define match_first_bytes(payload,st) (memcmp((payload),(st),(sizeof(st)-1))==0)
+
+#endif /* __NDPI_DEFINE_INCLUDE_FILE__ */
diff --git a/src/include/ndpi_main.h b/src/include/ndpi_main.h
new file mode 100644
index 000000000..55db9235e
--- /dev/null
+++ b/src/include/ndpi_main.h
@@ -0,0 +1,156 @@
+/*
+ * ndpi_main.h
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __NDPI_MAIN_INCLUDE_FILE__
+#define __NDPI_MAIN_INCLUDE_FILE__
+
+#ifndef __KERNEL__
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#ifndef WIN32
+#include <pthread.h>
+#endif
+#include <ctype.h>
+#include <time.h>
+#endif
+
+
+#ifndef WIN32
+#ifndef __KERNEL__
+#include <sys/time.h>
+#endif
+
+#if !defined __APPLE__ && !defined __FreeBSD__ && !defined __NetBSD__ && !defined __OpenBSD__
+
+#ifndef __KERNEL__
+#include <endian.h>
+#include <byteswap.h>
+#else
+#include <asm/byteorder.h>
+#include <linux/ctype.h>
+#endif
+
+#endif
+
+/* default includes */
+
+#ifndef __KERNEL__
+#include <sys/param.h>
+#include <limits.h>
+#endif
+#endif
+
+#include "ndpi_win32.h"
+#include "ndpi_unix.h"
+#include "ndpi_define.h"
+#include "ndpi_protocol_ids.h"
+#include "ndpi_typedefs.h"
+#include "ndpi_protocols.h"
+
+
+void *ndpi_tdelete(const void * __restrict, void ** __restrict,
+ int (*)(const void *, const void *));
+void *ndpi_tfind(const void *, void *, int (*)(const void *, const void *));
+void *ndpi_tsearch(const void *, void**, int (*)(const void *, const void *));
+void ndpi_twalk(const void *, void (*)(const void *, ndpi_VISIT, int, void*), void *user_data);
+void ndpi_tdestroy(void *vrootp, void (*freefct)(void *));
+
+int NDPI_BITMASK_COMPARE(NDPI_PROTOCOL_BITMASK a, NDPI_PROTOCOL_BITMASK b);
+int NDPI_BITMASK_IS_EMPTY(NDPI_PROTOCOL_BITMASK a);
+void NDPI_DUMP_BITMASK(NDPI_PROTOCOL_BITMASK a);
+
+extern u_int8_t ndpi_net_match(u_int32_t ip_to_check,
+ u_int32_t net,
+ u_int32_t num_bits);
+
+extern u_int8_t ndpi_ips_match(u_int32_t src, u_int32_t dst,
+ u_int32_t net, u_int32_t num_bits);
+
+u_int16_t ntohs_ndpi_bytestream_to_number(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read);
+
+u_int32_t ndpi_bytestream_to_number(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read);
+u_int64_t ndpi_bytestream_to_number64(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read);
+u_int32_t ndpi_bytestream_dec_or_hex_to_number(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read);
+u_int64_t ndpi_bytestream_dec_or_hex_to_number64(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read);
+u_int32_t ndpi_bytestream_to_ipv4(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read);
+
+
+void ndpi_int_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t detected_protocol, ndpi_protocol_type_t protocol_type);
+
+
+/* function to parse a packet which has line based information into a line based structure
+ * this function will also set some well known line pointers like:
+ * - host, user agent, empty line,....
+ */
+extern void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+extern void ndpi_parse_packet_line_info_any(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+extern u_int16_t ndpi_check_for_email_address(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, u_int16_t counter);
+extern void ndpi_int_change_packet_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t detected_protocol, ndpi_protocol_type_t protocol_type);
+extern void ndpi_int_change_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t detected_protocol,
+ ndpi_protocol_type_t protocol_type);
+extern void ndpi_set_proto_defaults(struct ndpi_detection_module_struct *ndpi_mod,
+ ndpi_protocol_breed_t protoBreed, u_int16_t protoId,
+ u_int16_t tcp_alias_protoId[2], u_int16_t udp_alias_protoId[2],
+ char *protoName,
+ ndpi_port_range *tcpDefPorts, ndpi_port_range *udpDefPorts);
+extern void ndpi_int_reset_packet_protocol(struct ndpi_packet_struct *packet);
+extern void ndpi_int_reset_protocol(struct ndpi_flow_struct *flow);
+extern int ndpi_packet_src_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t * ip);
+extern int ndpi_packet_dst_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t * ip);
+extern void ndpi_packet_src_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t * ip);
+extern void ndpi_packet_dst_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t * ip);
+extern char *ndpi_get_ip_string(struct ndpi_detection_module_struct *ndpi_struct, const ndpi_ip_addr_t * ip);
+extern char *ndpi_get_packet_src_ip_string(struct ndpi_detection_module_struct *ndpi_struct,
+ const struct ndpi_packet_struct *packet);
+extern char* ndpi_get_proto_by_id(struct ndpi_detection_module_struct *ndpi_mod, u_int id);
+extern u_int16_t ndpi_guess_protocol_id(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int8_t proto, u_int16_t sport, u_int16_t dport);
+extern int ndpi_get_protocol_id_master_proto(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int16_t protocol_id,
+ u_int16_t** tcp_master_proto,
+ u_int16_t** udp_master_proto);
+
+extern u_int8_t ndpi_net_match(u_int32_t ip_to_check,
+ u_int32_t net,
+ u_int32_t num_bits);
+
+extern u_int8_t ndpi_ips_match(u_int32_t src, u_int32_t dst,
+ u_int32_t net, u_int32_t num_bits);
+
+#ifdef NDPI_ENABLE_DEBUG_MESSAGES
+ void ndpi_debug_get_last_log_function_line(struct ndpi_detection_module_struct *ndpi_struct,
+ const char **file, const char **func, u_int32_t * line);
+#endif
+
+#include "ndpi_api.h"
+
+#endif /* __NDPI_MAIN_INCLUDE_FILE__ */
diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h
new file mode 100644
index 000000000..43e845117
--- /dev/null
+++ b/src/include/ndpi_protocol_ids.h
@@ -0,0 +1,244 @@
+/*
+ * ndpi_protocol_ids.h
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Copyright (C) 2009-11 - ipoque GmbH
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifndef __NDPI_API_INCLUDE_FILE__
+
+#endif
+
+#ifndef __NDPI_PROTOCOLS_DEFAULT_H__
+#define __NDPI_PROTOCOLS_DEFAULT_H__
+
+#define NDPI_DETECTION_SUPPORT_IPV6
+#define NDPI_PROTOCOL_HISTORY_SIZE 3
+
+#define NDPI_PROTOCOL_UNKNOWN 0
+
+#define NDPI_PROTOCOL_NO_MASTER_PROTO NDPI_PROTOCOL_UNKNOWN
+
+#define NDPI_PROTOCOL_IP_VRRP 73
+#define NDPI_PROTOCOL_IP_IPSEC 79
+#define NDPI_PROTOCOL_IP_GRE 80
+#define NDPI_PROTOCOL_IP_ICMP 81
+#define NDPI_PROTOCOL_IP_IGMP 82
+#define NDPI_PROTOCOL_IP_EGP 83
+#define NDPI_PROTOCOL_IP_SCTP 84
+#define NDPI_PROTOCOL_IP_OSPF 85
+#define NDPI_PROTOCOL_IP_IP_IN_IP 86
+#define NDPI_PROTOCOL_IP_ICMPV6 102
+
+#define NDPI_PROTOCOL_HTTP 7
+#define NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV 60
+#define NDPI_PROTOCOL_SSL_NO_CERT 64 /* SSL without certificate (Skype, Ultrasurf?) - ntop.org */
+#define NDPI_PROTOCOL_SSL 91
+#define NDPI_PROTOCOL_HTTP_APPLICATION_ACTIVESYNC 110
+#define NDPI_PROTOCOL_HTTP_CONNECT 130
+#define NDPI_PROTOCOL_HTTP_PROXY 131
+#define NDPI_PROTOCOL_SOCKS5 172 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_PROTOCOL_SOCKS4 173 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+
+#define NDPI_PROTOCOL_FTP_CONTROL 1 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_PROTOCOL_MAIL_POP 2
+#define NDPI_PROTOCOL_MAIL_SMTP 3
+#define NDPI_PROTOCOL_MAIL_IMAP 4
+#define NDPI_PROTOCOL_DNS 5
+#define NDPI_PROTOCOL_IPP 6
+#define NDPI_PROTOCOL_MDNS 8
+#define NDPI_PROTOCOL_NTP 9
+#define NDPI_PROTOCOL_NETBIOS 10
+#define NDPI_PROTOCOL_NFS 11
+#define NDPI_PROTOCOL_SSDP 12
+#define NDPI_PROTOCOL_BGP 13
+#define NDPI_PROTOCOL_SNMP 14
+#define NDPI_PROTOCOL_XDMCP 15
+#define NDPI_PROTOCOL_SMB 16
+#define NDPI_PROTOCOL_SYSLOG 17
+#define NDPI_PROTOCOL_DHCP 18
+#define NDPI_PROTOCOL_POSTGRES 19
+#define NDPI_PROTOCOL_MYSQL 20
+#define NDPI_PROTOCOL_TDS 21
+#define NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK 22
+#define NDPI_PROTOCOL_MAIL_POPS 23
+#define NDPI_PROTOCOL_APPLEJUICE 24
+#define NDPI_PROTOCOL_DIRECTCONNECT 25
+#define NDPI_PROTOCOL_SOCRATES 26
+#define NDPI_PROTOCOL_WINMX 27
+#define NDPI_PROTOCOL_VMWARE 28
+#define NDPI_PROTOCOL_MAIL_SMTPS 29
+#define NDPI_PROTOCOL_FILETOPIA 30
+#define NDPI_PROTOCOL_IMESH 31
+#define NDPI_PROTOCOL_KONTIKI 32
+#define NDPI_PROTOCOL_OPENFT 33
+#define NDPI_PROTOCOL_FASTTRACK 34
+#define NDPI_PROTOCOL_GNUTELLA 35
+#define NDPI_PROTOCOL_EDONKEY 36 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_PROTOCOL_BITTORRENT 37
+#define NDPI_PROTOCOL_EPP 38
+#define NDPI_PROTOCOL_XBOX 47
+#define NDPI_PROTOCOL_QQ 48
+#define NDPI_PROTOCOL_MOVE 49
+#define NDPI_PROTOCOL_RTSP 50
+#define NDPI_PROTOCOL_MAIL_IMAPS 51
+#define NDPI_PROTOCOL_ICECAST 52
+#define NDPI_PROTOCOL_PPLIVE 53 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_PROTOCOL_PPSTREAM 54
+#define NDPI_PROTOCOL_ZATTOO 55
+#define NDPI_PROTOCOL_SHOUTCAST 56
+#define NDPI_PROTOCOL_SOPCAST 57
+#define NDPI_PROTOCOL_TVANTS 58
+#define NDPI_PROTOCOL_TVUPLAYER 59
+#define NDPI_PROTOCOL_QQLIVE 61
+#define NDPI_PROTOCOL_THUNDER 62
+#define NDPI_PROTOCOL_SOULSEEK 63
+#define NDPI_PROTOCOL_IRC 65
+#define NDPI_PROTOCOL_AYIYA 66
+#define NDPI_PROTOCOL_UNENCRYPED_JABBER 67
+#define NDPI_PROTOCOL_MSN 68
+#define NDPI_PROTOCOL_OSCAR 69
+#define NDPI_PROTOCOL_YAHOO 70
+#define NDPI_PROTOCOL_BATTLEFIELD 71
+#define NDPI_PROTOCOL_QUAKE 72
+#define NDPI_PROTOCOL_STEAM 74 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_PROTOCOL_HALFLIFE2 75
+#define NDPI_PROTOCOL_WORLDOFWARCRAFT 76
+#define NDPI_PROTOCOL_TELNET 77
+#define NDPI_PROTOCOL_STUN 78
+#define NDPI_PROTOCOL_RTP 87
+#define NDPI_PROTOCOL_RDP 88
+#define NDPI_PROTOCOL_VNC 89
+#define NDPI_PROTOCOL_PCANYWHERE 90
+#define NDPI_PROTOCOL_SSH 92
+#define NDPI_PROTOCOL_USENET 93
+#define NDPI_PROTOCOL_MGCP 94
+#define NDPI_PROTOCOL_IAX 95
+#define NDPI_PROTOCOL_TFTP 96
+#define NDPI_PROTOCOL_AFP 97
+#define NDPI_PROTOCOL_STEALTHNET 98
+#define NDPI_PROTOCOL_AIMINI 99
+#define NDPI_PROTOCOL_SIP 100
+#define NDPI_PROTOCOL_TRUPHONE 101
+#define NDPI_PROTOCOL_DHCPV6 103
+#define NDPI_PROTOCOL_ARMAGETRON 104
+#define NDPI_PROTOCOL_CROSSFIRE 105
+#define NDPI_PROTOCOL_DOFUS 106
+#define NDPI_PROTOCOL_FIESTA 107
+#define NDPI_PROTOCOL_FLORENSIA 108
+#define NDPI_PROTOCOL_GUILDWARS 109
+#define NDPI_PROTOCOL_KERBEROS 111
+#define NDPI_PROTOCOL_LDAP 112
+#define NDPI_PROTOCOL_MAPLESTORY 113
+#define NDPI_PROTOCOL_MSSQL 114
+#define NDPI_PROTOCOL_PPTP 115
+#define NDPI_PROTOCOL_WARCRAFT3 116
+#define NDPI_PROTOCOL_WORLD_OF_KUNG_FU 117
+#define NDPI_PROTOCOL_MEEBO 118
+#define NDPI_PROTOCOL_DROPBOX 121
+#define NDPI_PROTOCOL_SKYPE 125
+#define NDPI_PROTOCOL_DCERPC 127
+#define NDPI_PROTOCOL_NETFLOW 128
+#define NDPI_PROTOCOL_SFLOW 129
+#define NDPI_PROTOCOL_CITRIX 132
+#define NDPI_PROTOCOL_SKYFILE_PREPAID 136
+#define NDPI_PROTOCOL_SKYFILE_RUDICS 137
+#define NDPI_PROTOCOL_SKYFILE_POSTPAID 138
+#define NDPI_PROTOCOL_CITRIX_ONLINE 139
+#define NDPI_PROTOCOL_WEBEX 141
+#define NDPI_PROTOCOL_VIBER 144
+#define NDPI_PROTOCOL_RADIUS 146
+#define NDPI_PROTOCOL_WINDOWS_UPDATE 147 /* Thierry Laurion */
+#define NDPI_PROTOCOL_TEAMVIEWER 148 /* xplico.org */
+#define NDPI_PROTOCOL_LOTUS_NOTES 150
+#define NDPI_PROTOCOL_SAP 151
+#define NDPI_PROTOCOL_GTP 152
+#define NDPI_PROTOCOL_UPNP 153
+#define NDPI_PROTOCOL_LLMNR 154
+#define NDPI_PROTOCOL_REMOTE_SCAN 155
+#define NDPI_PROTOCOL_SPOTIFY 156
+#define NDPI_PROTOCOL_H323 158 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_OPENVPN 159 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_NOE 160 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_CISCOVPN 161 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_TEAMSPEAK 162 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_TOR 163 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_SKINNY 164 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_RTCP 165 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_RSYNC 166 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_ORACLE 167 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_CORBA 168 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_UBUNTUONE 169 /* Remy Mudingay <mudingay@ill.fr> */
+#define NDPI_PROTOCOL_WHOIS_DAS 170
+#define NDPI_PROTOCOL_COLLECTD 171
+#define NDPI_PROTOCOL_RTMP 174 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_PROTOCOL_FTP_DATA 175 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_PROTOCOL_ZMQ 177
+#define NDPI_PROTOCOL_MEGACO 181 /* Gianluca Costa <g.costa@xplico.org> */
+#define NDPI_PROTOCOL_REDIS 182
+#define NDPI_PROTOCOL_PANDO 183 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_PROTOCOL_VHUA 184
+#define NDPI_PROTOCOL_TELEGRAM 185 /* Gianluca Costa <g.costa@xplico.org> */
+
+
+#define NDPI_CONTENT_AVI 39
+#define NDPI_CONTENT_FLASH 40
+#define NDPI_CONTENT_OGG 41
+#define NDPI_CONTENT_MPEG 42
+#define NDPI_CONTENT_QUICKTIME 43
+#define NDPI_CONTENT_REALMEDIA 44
+#define NDPI_CONTENT_WINDOWSMEDIA 45
+#define NDPI_CONTENT_MMS 46
+#define NDPI_CONTENT_WEBM 157
+
+#define NDPI_SERVICE_FACEBOOK 119
+#define NDPI_SERVICE_TWITTER 120
+#define NDPI_SERVICE_GMAIL 122
+#define NDPI_SERVICE_GOOGLE_MAPS 123
+#define NDPI_SERVICE_YOUTUBE 124
+#define NDPI_SERVICE_VEVO 188
+#define NDPI_SERVICE_GOOGLE 126
+#define NDPI_SERVICE_NETFLIX 133
+#define NDPI_SERVICE_LASTFM 134
+#define NDPI_SERVICE_GROOVESHARK 135
+#define NDPI_SERVICE_APPLE 140
+#define NDPI_SERVICE_WHATSAPP 142
+#define NDPI_SERVICE_APPLE_ICLOUD 143
+#define NDPI_SERVICE_APPLE_ITUNES 145
+#define NDPI_SERVICE_TUENTI 149
+#define NDPI_SERVICE_WIKIPEDIA 176 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_SERVICE_MSN NDPI_PROTOCOL_MSN /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_SERVICE_AMAZON 178 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_SERVICE_EBAY 179 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_SERVICE_CNN 180 /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_SERVICE_DROPBOX NDPI_PROTOCOL_DROPBOX /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_SERVICE_SKYPE NDPI_PROTOCOL_SKYPE /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_SERVICE_VIBER NDPI_PROTOCOL_VIBER /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_SERVICE_YAHOO NDPI_PROTOCOL_YAHOO /* Tomasz Bujlow <tomasz@skatnet.dk> */
+#define NDPI_SERVICE_FACEBOOK_CHAT 186
+#define NDPI_SERVICE_PANDORA 187
+
+/* UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE (NDPI_SERVICE_VEVO) */
+#define NDPI_LAST_IMPLEMENTED_PROTOCOL 188
+
+#define NDPI_MAX_SUPPORTED_PROTOCOLS (NDPI_LAST_IMPLEMENTED_PROTOCOL + 1)
+#define NDPI_MAX_NUM_CUSTOM_PROTOCOLS (NDPI_NUM_BITS-NDPI_LAST_IMPLEMENTED_PROTOCOL)
+#endif
diff --git a/src/include/ndpi_protocols.h b/src/include/ndpi_protocols.h
new file mode 100644
index 000000000..5ab0da83a
--- /dev/null
+++ b/src/include/ndpi_protocols.h
@@ -0,0 +1,181 @@
+/*
+ * ndpi_protocols.h
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifndef __NDPI_PROTOCOLS_INCLUDE_FILE__
+#define __NDPI_PROTOCOLS_INCLUDE_FILE__
+
+#include "ndpi_main.h"
+
+
+/* TCP/UDP protocols */
+u_int ndpi_search_tcp_or_udp_raw(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int8_t protocol,
+ u_int32_t saddr, u_int32_t daddr,
+ u_int16_t sport, u_int16_t dport);
+
+void ndpi_search_tcp_or_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+
+/* Applications and other protocols. */
+void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_bittorrent_init(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t size,u_int32_t timeout);
+void ndpi_bittorrent_done(struct ndpi_detection_module_struct *ndpi_struct);
+int ndpi_bittorrent_gc(struct hash_ip4p_table *ht,int key,time_t now);
+
+void ndpi_search_edonkey(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_fasttrack_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_gnutella(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_winmx_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_directconnect(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_applejuice_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_i23v5(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_socrates(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_soulseek_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_msn(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_yahoo(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_oscar(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_jabber_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_irc_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_sip(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_direct_download_link_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_mail_pop_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_mail_smtp_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_http_subprotocol_conf(struct ndpi_detection_module_struct *ndpi_struct, char *attr, char *value, int protocol_id);
+void ndpi_search_ftp_control(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_ftp_data(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_usenet_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_rtsp_tcp_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_filetopia_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_vmware(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_imesh_tcp_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_mms_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_icecast_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_shoutcast_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_veohtv_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_openft_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_stun(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_tvants_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_sopcast(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_tvuplayer(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_ppstream(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_pplive(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_iax(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_mgcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_zattoo(struct ndpi_detection_module_struct*ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_qq(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_feidian(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_ssh_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_ayiya(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_thunder(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_activesync(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_in_non_tcp_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_vnc_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_steam(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_halflife2(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_xbox(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_smb_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_telnet_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_ntp_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_nfs(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_ssdp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_worldofwarcraft(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_postgres_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_mysql_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_bgp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_quake(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_battlefield(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_secondlife(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_pcanywhere(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_rdp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_snmp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_kontiki(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_syslog(struct ndpi_detection_module_struct*ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_tds_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_netbios(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_mdns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_ipp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_ldap(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_warcraft3(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_kerberos(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_xdmcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_tftp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_mssql(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_pptp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_stealthnet(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_dhcpv6_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_meebo(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_afp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_aimini(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_florensia(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_maplestory(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_dofus(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_world_of_kung_fu(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_fiesta(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_crossfire_tcp_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_guildwars_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_armagetron_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_dropbox(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_skype(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_citrix(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_dcerpc(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_netflow(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_sflow(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_radius(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_wsus(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_teamview(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_lotus_notes(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_gtp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_spotify(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_h323(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_openvpn(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_noe(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_ciscovpn(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_viber(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_teamspeak(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_corba(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_collectd(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_oracle(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_rsync(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_rtcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_skinny(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_tor(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_whois_das(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_socks5(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_socks4(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_rtmp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_pando(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_megaco(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_redis(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_zmq(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_twitter(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_vhua(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+void ndpi_search_telegram(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+
+#endif /* __NDPI_PROTOCOLS_INCLUDE_FILE__ */
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
new file mode 100644
index 000000000..5bdd5a6e6
--- /dev/null
+++ b/src/include/ndpi_typedefs.h
@@ -0,0 +1,852 @@
+/*
+ * ndpi_typedefs.h
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Copyright (C) 2009-11 - ipoque GmbH
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __NDPI_TYPEDEFS_FILE__
+#define __NDPI_TYPEDEFS_FILE__
+
+typedef enum {
+ NDPI_LOG_ERROR,
+ NDPI_LOG_TRACE,
+ NDPI_LOG_DEBUG
+} ndpi_log_level_t;
+
+typedef void (*ndpi_debug_function_ptr) (u_int32_t protocol,
+ void *module_struct, ndpi_log_level_t log_level,
+ const char *format, ...);
+#define BT_ANNOUNCE
+
+typedef enum {
+ ndpi_preorder,
+ ndpi_postorder,
+ ndpi_endorder,
+ ndpi_leaf
+} ndpi_VISIT;
+
+typedef struct node_t {
+ char *key;
+ struct node_t *left, *right;
+} ndpi_node;
+
+typedef u_int32_t ndpi_ndpi_mask;
+
+typedef struct ndpi_protocol_bitmask_struct {
+ ndpi_ndpi_mask fds_bits[NDPI_NUM_FDS_BITS];
+} ndpi_protocol_bitmask_struct_t;
+
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+struct ndpi_ip6_addr {
+ union {
+ u_int8_t u6_addr8[16];
+ u_int16_t u6_addr16[8];
+ u_int32_t u6_addr32[4];
+ u_int64_t u6_addr64[2];
+ } ndpi_v6_u;
+
+#define ndpi_v6_addr ndpi_v6_u.u6_addr8
+#define ndpi_v6_addr16 ndpi_v6_u.u6_addr16
+#define ndpi_v6_addr32 ndpi_v6_u.u6_addr32
+#define ndpi_v6_addr64 ndpi_v6_u.u6_addr64
+};
+
+struct ndpi_ipv6hdr {
+ /* use userspace and kernelspace compatible compile parameters */
+#if defined(__LITTLE_ENDIAN__)
+ u_int8_t priority:4, version:4;
+#elif defined(__BIG_ENDIAN__)
+ u_int8_t version:4, priority:4;
+#else
+# error "Byte order must be defined"
+#endif
+
+ u_int8_t flow_lbl[3];
+
+ u_int16_t payload_len;
+ u_int8_t nexthdr;
+ u_int8_t hop_limit;
+
+ struct ndpi_ip6_addr saddr;
+ struct ndpi_ip6_addr daddr;
+};
+#endif /* NDPI_DETECTION_SUPPORT_IPV6 */
+
+typedef union {
+ u_int32_t ipv4;
+ u_int8_t ipv4_u_int8_t[4];
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ struct ndpi_ip6_addr ipv6;
+#endif
+} ndpi_ip_addr_t;
+
+
+#ifdef NDPI_PROTOCOL_BITTORRENT
+#ifndef __KERNEL__
+typedef struct spinlock {
+ volatile int val;
+} spinlock_t;
+typedef struct atomic {
+ volatile int counter;
+} atomic_t;
+
+#endif
+
+struct hash_ip4p_node {
+ struct hash_ip4p_node *next,*prev;
+ time_t lchg;
+ u_int16_t port,count:12,flag:4;
+ u_int32_t ip;
+ // + 12 bytes for ipv6
+};
+
+struct hash_ip4p {
+ struct hash_ip4p_node *top;
+ spinlock_t lock;
+ size_t len;
+};
+
+struct hash_ip4p_table {
+ size_t size;
+ int ipv6;
+ spinlock_t lock;
+ atomic_t count;
+ struct hash_ip4p tbl[0];
+};
+
+struct bt_announce { // 192 bytes
+ u_int32_t hash[5];
+ u_int32_t ip[4];
+ u_int32_t time;
+ u_int16_t port;
+ u_int8_t name_len,
+ name[192 - 4*10 - 2 - 1]; // 149 bytes
+};
+#endif
+
+typedef enum {
+ HTTP_METHOD_UNKNOWN = 0,
+ HTTP_METHOD_OPTIONS,
+ HTTP_METHOD_GET,
+ HTTP_METHOD_HEAD,
+ HTTP_METHOD_POST,
+ HTTP_METHOD_PUT,
+ HTTP_METHOD_DELETE,
+ HTTP_METHOD_TRACE,
+ HTTP_METHOD_CONNECT
+} ndpi_http_method;
+
+typedef struct ndpi_id_struct {
+ /* detected_protocol_bitmask:
+ * access this bitmask to find out whether an id has used skype or not
+ * if a flag is set here, it will not be resetted
+ * to compare this, use:
+ * if (NDPI_BITMASK_COMPARE(id->detected_protocol_bitmask,
+ * NDPI_PROTOCOL_BITMASK_XXX) != 0)
+ * {
+ * // protocol XXX detected on this id
+ * }
+ */
+ NDPI_PROTOCOL_BITMASK detected_protocol_bitmask;
+#ifdef NDPI_PROTOCOL_RTSP
+ ndpi_ip_addr_t rtsp_ip_address;
+#endif
+#ifdef NDPI_PROTOCOL_SIP
+#ifdef NDPI_PROTOCOL_YAHOO
+ u_int32_t yahoo_video_lan_timer;
+#endif
+#endif
+/* NDPI_PROTOCOL_IRC_MAXPORT % 2 must be 0 */
+#ifdef NDPI_PROTOCOL_IRC
+#define NDPI_PROTOCOL_IRC_MAXPORT 8
+ u_int16_t irc_port[NDPI_PROTOCOL_IRC_MAXPORT];
+ u_int32_t last_time_port_used[NDPI_PROTOCOL_IRC_MAXPORT];
+ u_int32_t irc_ts;
+#endif
+#ifdef NDPI_PROTOCOL_GNUTELLA
+ u_int32_t gnutella_ts;
+#endif
+#ifdef NDPI_PROTOCOL_BATTLEFIELD
+ u_int32_t battlefield_ts;
+#endif
+#ifdef NDPI_PROTOCOL_THUNDER
+ u_int32_t thunder_ts;
+#endif
+#ifdef NDPI_PROTOCOL_RTSP
+ u_int32_t rtsp_timer;
+#endif
+#ifdef NDPI_PROTOCOL_OSCAR
+ u_int32_t oscar_last_safe_access_time;
+#endif
+#ifdef NDPI_PROTOCOL_ZATTOO
+ u_int32_t zattoo_ts;
+#endif
+#ifdef NDPI_PROTOCOL_UNENCRYPED_JABBER
+ u_int32_t jabber_stun_or_ft_ts;
+#endif
+#ifdef NDPI_PROTOCOL_DIRECTCONNECT
+ u_int32_t directconnect_last_safe_access_time;
+#endif
+#ifdef NDPI_PROTOCOL_SOULSEEK
+ u_int32_t soulseek_last_safe_access_time;
+#endif
+#ifdef NDPI_PROTOCOL_DIRECTCONNECT
+ u_int16_t detected_directconnect_port;
+ u_int16_t detected_directconnect_udp_port;
+ u_int16_t detected_directconnect_ssl_port;
+#endif
+#ifdef NDPI_PROTOCOL_BITTORRENT
+#define NDPI_BT_PORTS 8
+ u_int16_t bt_port_t[NDPI_BT_PORTS];
+ u_int16_t bt_port_u[NDPI_BT_PORTS];
+#endif
+#ifdef NDPI_PROTOCOL_UNENCRYPED_JABBER
+#define JABBER_MAX_STUN_PORTS 6
+ u_int16_t jabber_voice_stun_port[JABBER_MAX_STUN_PORTS];
+ u_int16_t jabber_file_transfer_port[2];
+#endif
+#ifdef NDPI_PROTOCOL_GNUTELLA
+ u_int16_t detected_gnutella_port;
+#endif
+#ifdef NDPI_PROTOCOL_GNUTELLA
+ u_int16_t detected_gnutella_udp_port1;
+ u_int16_t detected_gnutella_udp_port2;
+#endif
+#ifdef NDPI_PROTOCOL_SOULSEEK
+ u_int16_t soulseek_listen_port;
+#endif
+#ifdef NDPI_PROTOCOL_IRC
+ u_int8_t irc_number_of_port;
+#endif
+#ifdef NDPI_PROTOCOL_OSCAR
+ u_int8_t oscar_ssl_session_id[33];
+#endif
+#ifdef NDPI_PROTOCOL_UNENCRYPED_JABBER
+ u_int8_t jabber_voice_stun_used_ports;
+#endif
+#ifdef NDPI_PROTOCOL_SIP
+#ifdef NDPI_PROTOCOL_YAHOO
+ u_int32_t yahoo_video_lan_dir:1;
+#endif
+#endif
+#ifdef NDPI_PROTOCOL_YAHOO
+ u_int32_t yahoo_conf_logged_in:1;
+ u_int32_t yahoo_voice_conf_logged_in:1;
+#endif
+#ifdef NDPI_PROTOCOL_RTSP
+ u_int32_t rtsp_ts_set:1;
+#endif
+} ndpi_id_struct;
+
+/* ************************************************** */
+
+struct ndpi_flow_tcp_struct {
+#ifdef NDPI_PROTOCOL_MAIL_SMTP
+ u_int16_t smtp_command_bitmask;
+#endif
+#ifdef NDPI_PROTOCOL_MAIL_POP
+ u_int16_t pop_command_bitmask;
+#endif
+#ifdef NDPI_PROTOCOL_QQ
+ u_int16_t qq_nxt_len;
+#endif
+#ifdef NDPI_PROTOCOL_TDS
+ u_int8_t tds_login_version;
+#endif
+#ifdef NDPI_PROTOCOL_IRC
+ u_int8_t irc_stage;
+ u_int8_t irc_port;
+#endif
+#ifdef NDPI_PROTOCOL_H323
+ u_int8_t h323_valid_packets;
+#endif
+#ifdef NDPI_PROTOCOL_GNUTELLA
+ u_int8_t gnutella_msg_id[3];
+#endif
+#ifdef NDPI_PROTOCOL_IRC
+ u_int32_t irc_3a_counter:3;
+ u_int32_t irc_stage2:5;
+ u_int32_t irc_direction:2;
+ u_int32_t irc_0x1000_full:1;
+#endif
+#ifdef NDPI_PROTOCOL_WINMX
+ u_int32_t winmx_stage:1; // 0-1
+#endif
+#ifdef NDPI_PROTOCOL_SOULSEEK
+ u_int32_t soulseek_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_FILETOPIA
+ u_int32_t filetopia_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_TDS
+ u_int32_t tds_stage:3;
+#endif
+#ifdef NDPI_PROTOCOL_USENET
+ u_int32_t usenet_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_IMESH
+ u_int32_t imesh_stage:4;
+#endif
+#ifdef NDPI_PROTOCOL_HTTP
+ u_int32_t http_setup_dir:2;
+ u_int32_t http_stage:2;
+ u_int32_t http_empty_line_seen:1;
+ u_int32_t http_wait_for_retransmission:1;
+#endif // NDPI_PROTOCOL_HTTP
+#ifdef NDPI_PROTOCOL_GNUTELLA
+ u_int32_t gnutella_stage:2; //0-2
+#endif
+#ifdef NDPI_CONTENT_MMS
+ u_int32_t mms_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_YAHOO
+ u_int32_t yahoo_sip_comm:1;
+ u_int32_t yahoo_http_proxy_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_MSN
+ u_int32_t msn_stage:3;
+ u_int32_t msn_ssl_ft:2;
+#endif
+#ifdef NDPI_PROTOCOL_SSH
+ u_int32_t ssh_stage:3;
+#endif
+#ifdef NDPI_PROTOCOL_VNC
+ u_int32_t vnc_stage:2; // 0 - 3
+#endif
+#ifdef NDPI_PROTOCOL_TELNET
+ u_int32_t telnet_stage:2; // 0 - 2
+#endif
+#ifdef NDPI_PROTOCOL_SSL
+ u_int8_t ssl_stage:2, ssl_seen_client_cert:1, ssl_seen_server_cert:1; // 0 - 5
+#endif
+#ifdef NDPI_PROTOCOL_POSTGRES
+ u_int32_t postgres_stage:3;
+#endif
+#ifdef NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK
+ u_int32_t ddlink_server_direction:1;
+#endif
+ u_int32_t seen_syn:1;
+ u_int32_t seen_syn_ack:1;
+ u_int32_t seen_ack:1;
+#ifdef NDPI_PROTOCOL_ICECAST
+ u_int32_t icecast_stage:1;
+#endif
+#ifdef NDPI_PROTOCOL_DOFUS
+ u_int32_t dofus_stage:1;
+#endif
+#ifdef NDPI_PROTOCOL_FIESTA
+ u_int32_t fiesta_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_WORLDOFWARCRAFT
+ u_int32_t wow_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV
+ u_int32_t veoh_tv_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_SHOUTCAST
+ u_int32_t shoutcast_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_RTP
+ u_int32_t rtp_special_packets_seen:1;
+#endif
+#ifdef NDPI_PROTOCOL_MAIL_POP
+ u_int32_t mail_pop_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_MAIL_IMAP
+ u_int32_t mail_imap_stage:3;
+#endif
+
+#ifdef NDPI_PROTOCOL_SKYPE
+ u_int8_t skype_packet_id;
+#endif
+
+#ifdef NDPI_PROTOCOL_CITRIX
+ u_int8_t citrix_packet_id;
+#endif
+
+#ifdef NDPI_PROTOCOL_LOTUS_NOTES
+ u_int8_t lotus_notes_packet_id;
+#endif
+
+#ifdef NDPI_PROTOCOL_TEAMVIEWER
+ u_int8_t teamviewer_stage;
+#endif
+
+#ifdef NDPI_PROTOCOL_ZMQ
+ u_int8_t prev_zmq_pkt_len;
+ u_char prev_zmq_pkt[10];
+#endif
+}
+#if !defined(WIN32)
+ __attribute__ ((__packed__))
+#endif
+ ;
+
+/* ************************************************** */
+
+struct ndpi_flow_udp_struct {
+#ifdef NDPI_PROTOCOL_BATTLEFIELD
+ u_int32_t battlefield_msg_id;
+#endif
+#ifdef NDPI_PROTOCOL_SNMP
+ u_int32_t snmp_msg_id;
+#endif
+#ifdef NDPI_PROTOCOL_BATTLEFIELD
+ u_int32_t battlefield_stage:3;
+#endif
+#ifdef NDPI_PROTOCOL_SNMP
+ u_int32_t snmp_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_PPSTREAM
+ u_int32_t ppstream_stage:3; // 0-7
+#endif
+#ifdef NDPI_PROTOCOL_HALFLIFE2
+ u_int32_t halflife2_stage:2; // 0 - 2
+#endif
+#ifdef NDPI_PROTOCOL_TFTP
+ u_int32_t tftp_stage:1;
+#endif
+#ifdef NDPI_PROTOCOL_AIMINI
+ u_int32_t aimini_stage:5;
+#endif
+#ifdef NDPI_PROTOCOL_XBOX
+ u_int32_t xbox_stage:1;
+#endif
+#ifdef NDPI_PROTOCOL_WINDOWS_UPDATE
+ u_int32_t wsus_stage:1;
+#endif
+#ifdef NDPI_PROTOCOL_SKYPE
+ u_int8_t skype_packet_id;
+#endif
+#ifdef NDPI_PROTOCOL_TEAMVIEWER
+ u_int8_t teamviewer_stage;
+#endif
+}
+#if !defined(WIN32)
+ __attribute__ ((__packed__))
+#endif
+ ;
+
+/* ************************************************** */
+
+typedef struct ndpi_int_one_line_struct {
+ const u_int8_t *ptr;
+ u_int16_t len;
+} ndpi_int_one_line_struct_t;
+
+typedef struct ndpi_packet_struct {
+ const struct ndpi_iphdr *iph;
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ const struct ndpi_ipv6hdr *iphv6;
+#endif
+ const struct ndpi_tcphdr *tcp;
+ const struct ndpi_udphdr *udp;
+ const u_int8_t *generic_l4_ptr; /* is set only for non tcp-udp traffic */
+ const u_int8_t *payload;
+
+ u_int32_t tick_timestamp;
+ u_int64_t tick_timestamp_l;
+
+ u_int16_t detected_protocol_stack[NDPI_PROTOCOL_HISTORY_SIZE];
+ u_int8_t detected_subprotocol_stack[NDPI_PROTOCOL_HISTORY_SIZE];
+
+ /* this is for simple read-only access to the real protocol
+ * used for the main loop */
+ u_int16_t real_protocol_read_only;
+
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+# if NDPI_PROTOCOL_HISTORY_SIZE > 5
+# error protocol stack size not supported
+# endif
+
+ struct {
+ u_int8_t entry_is_real_protocol:5;
+ u_int8_t current_stack_size_minus_one:3;
+ }
+#if !defined(WIN32)
+ __attribute__ ((__packed__))
+#endif
+ protocol_stack_info;
+#endif
+
+ struct ndpi_int_one_line_struct line[NDPI_MAX_PARSE_LINES_PER_PACKET];
+ struct ndpi_int_one_line_struct host_line;
+ struct ndpi_int_one_line_struct forwarded_line;
+ struct ndpi_int_one_line_struct referer_line;
+ struct ndpi_int_one_line_struct content_line;
+ struct ndpi_int_one_line_struct accept_line;
+ struct ndpi_int_one_line_struct user_agent_line;
+ struct ndpi_int_one_line_struct http_url_name;
+ struct ndpi_int_one_line_struct http_encoding;
+ struct ndpi_int_one_line_struct http_transfer_encoding;
+ struct ndpi_int_one_line_struct http_contentlen;
+ struct ndpi_int_one_line_struct http_cookie;
+ struct ndpi_int_one_line_struct http_origin;
+ struct ndpi_int_one_line_struct http_x_session_type;
+ struct ndpi_int_one_line_struct server_line;
+ struct ndpi_int_one_line_struct http_method;
+ struct ndpi_int_one_line_struct http_response;
+
+ u_int16_t l3_packet_len;
+ u_int16_t l4_packet_len;
+ u_int16_t payload_packet_len;
+ u_int16_t actual_payload_len;
+ u_int16_t num_retried_bytes;
+ u_int16_t parsed_lines;
+ u_int16_t parsed_unix_lines;
+ u_int16_t empty_line_position;
+ u_int8_t tcp_retransmission;
+ u_int8_t l4_protocol;
+
+ u_int8_t ssl_certificate_detected:4, ssl_certificate_num_checks:4;
+ u_int8_t packet_lines_parsed_complete:1,
+ packet_direction:1,
+ empty_line_position_set:1;
+} ndpi_packet_struct_t;
+
+struct ndpi_detection_module_struct;
+struct ndpi_flow_struct;
+
+typedef struct ndpi_call_function_struct {
+ NDPI_PROTOCOL_BITMASK detection_bitmask;
+ NDPI_PROTOCOL_BITMASK excluded_protocol_bitmask;
+ NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_bitmask;
+ void (*func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow);
+ u_int8_t detection_feature;
+} ndpi_call_function_struct_t;
+
+typedef struct ndpi_subprotocol_conf_struct {
+ void (*func) (struct ndpi_detection_module_struct *, char *attr, char *value, int protocol_id);
+} ndpi_subprotocol_conf_struct_t;
+
+
+typedef struct {
+ u_int16_t port_low, port_high;
+} ndpi_port_range;
+
+typedef enum {
+ NDPI_PROTOCOL_SAFE = 0, /* Safe protocol with encryption */
+ NDPI_PROTOCOL_ACCEPTABLE, /* Ok but not encrypted */
+ NDPI_PROTOCOL_FUN, /* Pure fun protocol */
+ NDPI_PROTOCOL_UNSAFE, /* Protocol with a safe version existing what should be used instead */
+ NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, /* Be prepared to troubles */
+ NDPI_PROTOCOL_UNRATED /* No idea */
+} ndpi_protocol_breed_t;
+
+#define NUM_BREEDS (NDPI_PROTOCOL_UNRATED+1)
+
+/* ntop extensions */
+typedef struct ndpi_proto_defaults {
+ char *protoName;
+ u_int16_t protoId, protoIdx;
+ u_int16_t master_tcp_protoId[2], master_udp_protoId[2]; /* The main protocols on which this sub-protocol sits on */
+ ndpi_protocol_breed_t protoBreed;
+ void (*func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow);
+} ndpi_proto_defaults_t;
+
+typedef struct ndpi_default_ports_tree_node {
+ ndpi_proto_defaults_t *proto;
+ u_int16_t default_port;
+} ndpi_default_ports_tree_node_t;
+
+typedef struct _ndpi_automa {
+ void *ac_automa; /* Real type is AC_AUTOMATA_t */
+ u_int8_t ac_automa_finalized;
+} ndpi_automa;
+
+typedef struct ndpi_detection_module_struct {
+ NDPI_PROTOCOL_BITMASK detection_bitmask;
+ NDPI_PROTOCOL_BITMASK generic_http_packet_bitmask;
+
+ u_int32_t current_ts;
+ u_int32_t ticks_per_second;
+
+#ifdef NDPI_ENABLE_DEBUG_MESSAGES
+ void *user_data;
+#endif
+ /* callback function buffer */
+ struct ndpi_call_function_struct callback_buffer[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
+ u_int32_t callback_buffer_size;
+
+ struct ndpi_call_function_struct callback_buffer_tcp_no_payload[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
+ u_int32_t callback_buffer_size_tcp_no_payload;
+
+ struct ndpi_call_function_struct callback_buffer_tcp_payload[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
+ u_int32_t callback_buffer_size_tcp_payload;
+
+ struct ndpi_call_function_struct callback_buffer_udp[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
+ u_int32_t callback_buffer_size_udp;
+
+ struct ndpi_call_function_struct callback_buffer_non_tcp_udp[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
+ u_int32_t callback_buffer_size_non_tcp_udp;
+
+ ndpi_default_ports_tree_node_t *tcpRoot, *udpRoot;
+
+#ifdef NDPI_ENABLE_DEBUG_MESSAGES
+ /* debug callback, only set when debug is used */
+ ndpi_debug_function_ptr ndpi_debug_printf;
+ const char *ndpi_debug_print_file;
+ const char *ndpi_debug_print_function;
+ u_int32_t ndpi_debug_print_line;
+#endif
+ /* misc parameters */
+ u_int32_t tcp_max_retransmission_window_size;
+
+ u_int32_t directconnect_connection_ip_tick_timeout;
+
+ /* subprotocol registration handler */
+ struct ndpi_subprotocol_conf_struct subprotocol_conf[NDPI_MAX_SUPPORTED_PROTOCOLS + 1];
+
+ u_int ndpi_num_supported_protocols;
+ u_int ndpi_num_custom_protocols;
+
+ /* HTTP/DNS/HTTPS host matching */
+ ndpi_automa host_automa, content_automa, bigrams_automa, impossible_bigrams_automa;
+
+ /* IP-based protocol detection */
+ void *protocols_ptree;
+
+ /* irc parameters */
+ u_int32_t irc_timeout;
+ /* gnutella parameters */
+ u_int32_t gnutella_timeout;
+ /* battlefield parameters */
+ u_int32_t battlefield_timeout;
+ /* thunder parameters */
+ u_int32_t thunder_timeout;
+ /* SoulSeek parameters */
+ u_int32_t soulseek_connection_ip_tick_timeout;
+ /* rtsp parameters */
+ u_int32_t rtsp_connection_timeout;
+ /* tvants parameters */
+ u_int32_t tvants_connection_timeout;
+ u_int32_t orb_rstp_ts_timeout;
+ /* yahoo */
+ // u_int32_t yahoo_http_filetransfer_timeout;
+ u_int8_t yahoo_detect_http_connections;
+ u_int32_t yahoo_lan_video_timeout;
+ u_int32_t zattoo_connection_timeout;
+ u_int32_t jabber_stun_timeout;
+ u_int32_t jabber_file_transfer_timeout;
+#ifdef NDPI_ENABLE_DEBUG_MESSAGES
+#define NDPI_IP_STRING_SIZE 40
+ char ip_string[NDPI_IP_STRING_SIZE];
+#endif
+ u_int8_t ip_version_limit;
+ /* ********************* */
+#ifdef NDPI_PROTOCOL_BITTORRENT
+ struct hash_ip4p_table *bt_ht;
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ struct hash_ip4p_table *bt6_ht;
+#endif
+#ifdef BT_ANNOUNCE
+ struct bt_announce *bt_ann;
+ int bt_ann_len;
+#endif
+#endif
+
+ ndpi_proto_defaults_t proto_defaults[NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS];
+
+ u_int8_t match_dns_host_names:1, http_dissect_response:1;
+ u_int8_t direction_detect_disable:1; /* disable internal detection of packet direction */
+} ndpi_detection_module_struct_t;
+
+typedef struct ndpi_flow_struct {
+ u_int16_t detected_protocol_stack[NDPI_PROTOCOL_HISTORY_SIZE];
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+# if NDPI_PROTOCOL_HISTORY_SIZE > 5
+# error protocol stack size not supported
+# endif
+
+ struct {
+ u_int8_t entry_is_real_protocol:5;
+ u_int8_t current_stack_size_minus_one:3;
+ }
+
+#if !defined(WIN32)
+ __attribute__ ((__packed__))
+#endif
+ protocol_stack_info;
+#endif
+
+ /* init parameter, internal used to set up timestamp,... */
+ u_int16_t guessed_protocol_id;
+
+ u_int8_t protocol_id_already_guessed:1;
+ u_int8_t no_cache_protocol:1;
+ u_int8_t init_finished:1;
+ u_int8_t setup_packet_direction:1;
+ u_int8_t packet_direction:1; /* if ndpi_struct->direction_detect_disable == 1 */
+ /* tcp sequence number connection tracking */
+ u_int32_t next_tcp_seq_nr[2];
+
+ /* the tcp / udp / other l4 value union
+ * this is used to reduce the number of bytes for tcp or udp protocol states
+ * */
+ union {
+ struct ndpi_flow_tcp_struct tcp;
+ struct ndpi_flow_udp_struct udp;
+ } l4;
+
+ struct ndpi_id_struct *server_id; /*
+ Pointer to src or dst
+ that identifies the
+ server of this connection
+ */
+#ifndef __KERNEL__
+ u_char host_server_name[256]; /* HTTP host or DNS query */
+#else
+ u_char host_server_name[160];
+#endif
+ u_char detected_os[32]; /* Via HTTP User-Agent */
+ u_char nat_ip[24]; /* Via HTTP X-Forwarded-For */
+
+ /*
+ This structure below will not not stay inside the protos
+ structure below as HTTP is used by many subprotocols
+ such as FaceBook, Google... so it is hard to know
+ when to use it or not. Thus we leave it outside for the
+ time being.
+ */
+ struct {
+ ndpi_http_method method;
+ char *url, *content_type;
+ } http;
+
+ union {
+ struct {
+ u_int8_t num_queries, num_answers, ret_code;
+ u_int8_t bad_packet /* the received packet looks bad */;
+ u_int16_t query_type, query_class, rsp_type;
+ } dns;
+
+ struct {
+ char client_certificate[48], server_certificate[48];
+ } ssl;
+ } protos;
+ /* ALL protocol specific 64 bit variables here */
+
+ /* protocols which have marked a connection as this connection cannot be protocol XXX, multiple u_int64_t */
+ NDPI_PROTOCOL_BITMASK excluded_protocol_bitmask;
+
+#if 0
+#ifdef NDPI_PROTOCOL_RTP
+ u_int32_t rtp_ssid[2];
+ u_int16_t rtp_seqnum[2]; /* current highest sequence number (only goes forwards, is not decreased by retransmissions) */
+ /* tcp and udp */
+ u_int8_t rtp_payload_type[2];
+ u_int32_t rtp_stage1:2; //0-3
+ u_int32_t rtp_stage2:2;
+#endif
+#endif
+
+#ifdef NDPI_PROTOCOL_REDIS
+ u_int8_t redis_s2d_first_char, redis_d2s_first_char;
+#endif
+
+ u_int16_t packet_counter; // can be 0-65000
+ u_int16_t packet_direction_counter[2];
+ u_int16_t byte_counter[2];
+
+#ifdef NDPI_PROTOCOL_BITTORRENT
+ u_int8_t bittorrent_stage; // can be 0-255
+#endif
+#ifdef NDPI_PROTOCOL_DIRECTCONNECT
+ u_int32_t directconnect_stage:2; // 0-1
+#endif
+#ifdef NDPI_PROTOCOL_SIP
+#ifdef NDPI_PROTOCOL_YAHOO
+ u_int32_t sip_yahoo_voice:1;
+#endif
+#endif
+#ifdef NDPI_PROTOCOL_HTTP
+ u_int32_t http_detected:1;
+#endif // NDPI_PROTOCOL_HTTP
+#ifdef NDPI_PROTOCOL_RTSP
+ u_int32_t rtsprdt_stage:2;
+ u_int32_t rtsp_control_flow:1;
+#endif
+
+#ifdef NDPI_PROTOCOL_YAHOO
+ u_int32_t yahoo_detection_finished:2;
+#endif
+#ifdef NDPI_PROTOCOL_ZATTOO
+ u_int32_t zattoo_stage:3;
+#endif
+#ifdef NDPI_PROTOCOL_QQ
+ u_int32_t qq_stage:3;
+#endif
+#ifdef NDPI_PROTOCOL_THUNDER
+ u_int32_t thunder_stage:2; // 0-3
+#endif
+#ifdef NDPI_PROTOCOL_OSCAR
+ u_int32_t oscar_ssl_voice_stage:3;
+ u_int32_t oscar_video_voice:1;
+#endif
+#ifdef NDPI_PROTOCOL_FLORENSIA
+ u_int32_t florensia_stage:1;
+#endif
+#ifdef NDPI_PROTOCOL_SOCKS5
+ u_int32_t socks5_stage:2; // 0-3
+#endif
+#ifdef NDPI_PROTOCOL_SOCKS4
+ u_int32_t socks4_stage:2; // 0-3
+#endif
+#ifdef NDPI_PROTOCOL_EDONKEY
+ u_int32_t edonkey_stage:2; // 0-3
+#endif
+#ifdef NDPI_PROTOCOL_FTP_CONTROL
+ u_int32_t ftp_control_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_FTP_DATA
+ u_int32_t ftp_data_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_RTMP
+ u_int32_t rtmp_stage:2;
+#endif
+#ifdef NDPI_PROTOCOL_PANDO
+ u_int32_t pando_stage:3;
+#endif
+#ifdef NDPI_PROTOCOL_STEAM
+ u_int32_t steam_stage:3;
+ u_int32_t steam_stage1:3; // 0 - 4
+ u_int32_t steam_stage2:2; // 0 - 2
+ u_int32_t steam_stage3:2; // 0 - 2
+#endif
+#ifdef NDPI_PROTOCOL_PPLIVE
+ u_int32_t pplive_stage1:3; // 0-6
+ u_int32_t pplive_stage2:2; // 0-2
+ u_int32_t pplive_stage3:2; // 0-2
+#endif
+
+ /* internal structures to save functions calls */
+ struct ndpi_packet_struct packet;
+ struct ndpi_flow_struct *flow;
+ struct ndpi_id_struct *src;
+ struct ndpi_id_struct *dst;
+} ndpi_flow_struct_t;
+
+typedef enum {
+ NDPI_REAL_PROTOCOL = 0,
+ NDPI_CORRELATED_PROTOCOL = 1
+} ndpi_protocol_type_t;
+
+#endif/* __NDPI_TYPEDEFS_FILE__ */
diff --git a/src/include/ndpi_unix.h b/src/include/ndpi_unix.h
new file mode 100644
index 000000000..79de7b43c
--- /dev/null
+++ b/src/include/ndpi_unix.h
@@ -0,0 +1,53 @@
+/*
+ * ndpi_unix.h
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __NDPI_UNIX_INCLUDE_FILE__
+#define __NDPI_UNIX_INCLUDE_FILE__
+
+#include "linux_compat.h"
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#include <netinet/in.h>
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <netinet/in_systm.h>
+#if defined(__OpenBSD__)
+#include <pthread.h>
+#endif
+#endif
+#endif
+
+#ifndef WIN32
+#ifndef __KERNEL__
+
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#else
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#endif
+#endif
+
+#endif /* __NDPI_UNIX_INCLUDE_FILE__ */
diff --git a/src/include/ndpi_win32.h b/src/include/ndpi_win32.h
new file mode 100644
index 000000000..3b568beb9
--- /dev/null
+++ b/src/include/ndpi_win32.h
@@ -0,0 +1,73 @@
+/*
+ * ndpi_win32.h
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __NDPI_WIN32_INCLUDE_FILE__
+#define __NDPI_WIN32_INCLUDE_FILE__
+
+#ifdef WIN32
+#include <Winsock2.h> /* winsock.h is included automatically */
+#include <process.h>
+#include <io.h>
+#include <getopt.h> /* getopt from: http://www.pwilson.net/sample.html. */
+#include <process.h> /* for getpid() and the exec..() family */
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+#define snprintf _snprintf
+
+extern char* strsep(char **stringp, const char *delim);
+
+#define __attribute__(x)
+#include <stdint.h>
+#ifndef __GNUC__
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int uint;
+typedef unsigned long u_long;
+#endif
+typedef u_char u_int8_t;
+typedef u_short u_int16_t;
+typedef unsigned int u_int32_t;
+typedef unsigned __int64 u_int64_t;
+
+
+#define pthread_t HANDLE
+#define pthread_mutex_t HANDLE
+#define pthread_rwlock_t pthread_mutex_t
+#define pthread_rwlock_init pthread_mutex_init
+#define pthread_rwlock_wrlock pthread_mutex_lock
+#define pthread_rwlock_rdlock pthread_mutex_lock
+#define pthread_rwlock_unlock pthread_mutex_unlock
+#define pthread_rwlock_destroy pthread_mutex_destroy
+
+#define gmtime_r(a, b) gmtime(a) /* Already thread safe on windows */
+
+extern unsigned long waitForNextEvent(unsigned long ulDelay /* ms */);
+
+#define sleep(a /* sec */) waitForNextEvent(1000*a /* ms */)
+
+#endif /* Win32 */
+
+#endif /* __NDPI_WIN32_INCLUDE_FILE__ */
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
new file mode 100644
index 000000000..2ecf1e2ac
--- /dev/null
+++ b/src/lib/Makefile.am
@@ -0,0 +1,158 @@
+lib_LTLIBRARIES = libndpi.la
+
+CFLAGS += -fPIC -DPIC
+libndpi_la_CPPFLAGS = -I$(top_srcdir)/src/include/ -I$(top_srcdir)/src/lib/third_party/include/
+libndpi_la_LDFLAGS = -version-info 1:0:0 -export-symbols $(top_srcdir)/libndpi.sym
+
+libndpi_la_includedir = $(includedir)/libndpi-@VERSION@/libndpi
+
+libndpi_la_include_HEADERS = ../include/ndpi_api.h \
+ ../include/linux_compat.h \
+ ../include/ndpi_define.h \
+ ../include/ndpi_main.h \
+ ../include/ndpi_protocol_ids.h \
+ ../include/ndpi_protocols.h \
+ ../include/ndpi_typedefs.h \
+ ../include/ndpi_unix.h \
+ ../include/ndpi_win32.h
+
+libndpi_la_SOURCES = ndpi_content_match.c.inc \
+ ndpi_main.c \
+ protocols/afp.c \
+ protocols/aimini.c \
+ protocols/applejuice.c \
+ protocols/armagetron.c \
+ protocols/ayiya.c \
+ protocols/battlefield.c \
+ protocols/bgp.c \
+ protocols/bittorrent.c \
+ protocols/ciscovpn.c \
+ protocols/citrix.c \
+ protocols/collectd.c \
+ protocols/corba.c \
+ protocols/crossfire.c \
+ protocols/dcerpc.c \
+ protocols/dhcp.c \
+ protocols/dhcpv6.c \
+ protocols/directconnect.c \
+ protocols/directdownloadlink.c \
+ protocols/dns.c \
+ protocols/dofus.c \
+ protocols/dropbox.c \
+ protocols/edonkey.c \
+ protocols/fasttrack.c \
+ protocols/fiesta.c \
+ protocols/filetopia.c \
+ protocols/florensia.c \
+ protocols/ftp_control.c \
+ protocols/ftp_data.c \
+ protocols/gnutella.c \
+ protocols/gtp.c \
+ protocols/guildwars.c \
+ protocols/h323.c \
+ protocols/halflife2_and_mods.c \
+ protocols/http_activesync.c \
+ protocols/http.c \
+ protocols/iax.c \
+ protocols/icecast.c \
+ protocols/imesh.c \
+ protocols/ipp.c \
+ protocols/irc.c \
+ protocols/jabber.c \
+ protocols/kerberos.c \
+ protocols/kontiki.c \
+ protocols/ldap.c \
+ protocols/lotus_notes.c \
+ protocols/mail_imap.c \
+ protocols/mail_pop.c \
+ protocols/mail_smtp.c \
+ protocols/maplestory.c \
+ protocols/mdns.c \
+ protocols/meebo.c \
+ protocols/megaco.c \
+ protocols/mgcp.c \
+ protocols/mms.c \
+ protocols/msn.c \
+ protocols/mssql.c \
+ protocols/mysql.c \
+ protocols/netbios.c \
+ protocols/netflow.c \
+ protocols/nfs.c \
+ protocols/noe.c \
+ protocols/non_tcp_udp.c \
+ protocols/ntp.c \
+ protocols/openft.c \
+ protocols/openvpn.c \
+ protocols/oracle.c \
+ protocols/oscar.c \
+ protocols/pando.c \
+ protocols/pcanywhere.c \
+ protocols/postgres.c \
+ protocols/pplive.c \
+ protocols/ppstream.c \
+ protocols/pptp.c \
+ protocols/qq.c \
+ protocols/quake.c \
+ protocols/radius.c \
+ protocols/rdp.c \
+ protocols/redis.c \
+ protocols/rsync.c \
+ protocols/rtcp.c \
+ protocols/rtmp.c \
+ protocols/rtp.c \
+ protocols/rtsp.c \
+ protocols/sflow.c \
+ protocols/shoutcast.c \
+ protocols/sip.c \
+ protocols/skinny.c \
+ protocols/skype.c \
+ protocols/smb.c \
+ protocols/snmp.c \
+ protocols/socks4.c \
+ protocols/socks5.c \
+ protocols/socrates.c \
+ protocols/sopcast.c \
+ protocols/soulseek.c \
+ protocols/spotify.c \
+ protocols/ssdp.c \
+ protocols/ssh.c \
+ protocols/ssl.c \
+ protocols/stealthnet.c \
+ protocols/steam.c \
+ protocols/stun.c \
+ protocols/syslog.c \
+ protocols/tcp_udp.c \
+ protocols/tds.c \
+ protocols/teamspeak.c \
+ protocols/teamviewer.c \
+ protocols/telegram.c \
+ protocols/telnet.c \
+ protocols/tftp.c \
+ protocols/thunder.c \
+ protocols/tor.c \
+ protocols/tvants.c \
+ protocols/tvuplayer.c \
+ protocols/twitter.c \
+ protocols/usenet.c \
+ protocols/veohtv.c \
+ protocols/viber.c \
+ protocols/vhua.c \
+ protocols/vmware.c \
+ protocols/vnc.c \
+ protocols/warcraft3.c \
+ protocols/whoisdas.c \
+ protocols/winmx.c \
+ protocols/world_of_kung_fu.c \
+ protocols/world_of_warcraft.c \
+ protocols/xbox.c \
+ protocols/xdmcp.c \
+ protocols/yahoo.c \
+ protocols/zattoo.c \
+ protocols/zmq.c \
+ third_party/include/actypes.h \
+ third_party/include/ahocorasick.h \
+ third_party/include/node.h \
+ third_party/include/sort.h \
+ third_party/src/ahocorasick.c \
+ third_party/src/node.c \
+ third_party/src/sort.c
diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc
new file mode 100644
index 000000000..3b4693fc3
--- /dev/null
+++ b/src/lib/ndpi_content_match.c.inc
@@ -0,0 +1,7410 @@
+/*
+ * ndpi_content_match.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+typedef struct {
+ char *string_to_match, *proto_name;
+ int protocol_id;
+ ndpi_protocol_breed_t protocol_breed;
+} ndpi_protocol_match;
+
+typedef struct {
+ u_int32_t network;
+ u_int8_t cidr;
+ u_int8_t value;
+} ndpi_network;
+
+/* ****************************************************** */
+
+static ndpi_network host_protocol_list[] = {
+ /*
+ Citrix GotoMeeting (AS16815, AS21866)
+ 216.115.208.0/20
+ 216.219.112.0/20
+ */
+ { 0xD873D000 /* 216.115.208.0 */, 20, NDPI_PROTOCOL_CITRIX_ONLINE },
+ { 0xD8DB7000 /* 216.219.112.0 */, 20, NDPI_PROTOCOL_CITRIX_ONLINE },
+
+ /*
+ Webex
+ 66.114.160.0/20
+ */
+ { 0x4272A000 /* 66.114.160.0 */, 20, NDPI_PROTOCOL_WEBEX },
+
+ /*
+ Viber
+ 54.171.62.0/24
+ */
+ { 0x36AB3E00 /* 54.171.62.0 */, 24, NDPI_PROTOCOL_VIBER },
+
+ /*
+ Apple (FaceTime, iMessage,...)
+ 17.0.0.0/8
+ */
+ { 0x11000000 /* 17.0.0.0 */, 8, NDPI_SERVICE_APPLE },
+
+ /*
+ Dropbox
+ 108.160.160.0/20
+ 199.47.216.0/22
+ */
+ { 0x6CA0A000 /* 108.160.160.0 */, 20, NDPI_PROTOCOL_DROPBOX },
+ { 0xC72FD800 /* 199.47.216.0 */, 22, NDPI_PROTOCOL_DROPBOX },
+ { 0x6CA0A000 /* 108.160.160.0 */, 20, NDPI_PROTOCOL_DROPBOX },
+
+ /*
+ Skype
+ 157.56.0.0/14, 157.60.0.0/16, 157.54.0.0/15
+ */
+ { 0x9D380000 /* 157.56.0.0 */, 14, NDPI_PROTOCOL_SKYPE },
+ { 0x9D3C0000 /* 157.60.0.0 */, 16, NDPI_PROTOCOL_SKYPE },
+ { 0x9D360000 /* 157.54.0.0/ */, 15, NDPI_PROTOCOL_SKYPE },
+
+ /*
+ Google
+ 173.194.0.0/16
+ */
+ { 0xADC20000 /* 173.194.0.0 */, 16, NDPI_SERVICE_GOOGLE },
+
+ /*
+ Ubuntu One
+ 91.189.89.0/21 (255.255.248.0)
+ */
+ { 0x5BBD5900 /* 91.189.89.0 */, 21, NDPI_PROTOCOL_UBUNTUONE},
+
+ /*
+ Telegram
+ route: 149.154.164.0/22
+ descr: Telegram Messenger Amsterdam Network
+ origin: AS62041
+ mnt-by: MNT-TELEGRAM
+ source: RIPE # Filtered
+
+ route: 149.154.168.0/22
+ descr: Telegram Messenger DC5 Network
+ origin: AS62014
+ mnt-by: MNT-TELEGRAM
+ source: RIPE # Filtered
+
+ http://myip.ms/view/web_hosting/363906/Telegram_Messenger_Network.html
+ */
+ { 0x959AA400 /* 149.154.164.0/22 */, 22, NDPI_PROTOCOL_TELEGRAM},
+ { 0x959AA800 /* 149.154.168.0/22 */, 22, NDPI_PROTOCOL_TELEGRAM},
+
+ /* Skype */
+ { 0x17600000, 14, NDPI_PROTOCOL_SKYPE },
+ { 0x17613000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0x17614000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0x17616000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0x17622000, 21, NDPI_PROTOCOL_SKYPE },
+ { 0x17622800, 22, NDPI_PROTOCOL_SKYPE },
+ { 0x17623800, 21, NDPI_PROTOCOL_SKYPE },
+ { 0x17624000, 18, NDPI_PROTOCOL_SKYPE },
+ { 0x17640000, 15, NDPI_PROTOCOL_SKYPE },
+ { 0x17660000, 16, NDPI_PROTOCOL_SKYPE },
+ { 0x17674000, 18, NDPI_PROTOCOL_SKYPE },
+ { 0x17678000, 17, NDPI_PROTOCOL_SKYPE },
+ { 0x40040000, 18, NDPI_PROTOCOL_SKYPE },
+ { 0x41340000, 14, NDPI_PROTOCOL_SKYPE },
+ { 0x4134A000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0x41362800, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x41364200, 23, NDPI_PROTOCOL_SKYPE },
+ { 0x41364400, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x41365200, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x41365500, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x41365A00, 23, NDPI_PROTOCOL_SKYPE },
+ { 0x41372C00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x41377500, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x4137E600, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x4137E700, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x42779000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0x46250000, 17, NDPI_PROTOCOL_SKYPE },
+ { 0x46258000, 18, NDPI_PROTOCOL_SKYPE },
+ { 0x46259600, 23, NDPI_PROTOCOL_SKYPE },
+ { 0x5EF54000, 18, NDPI_PROTOCOL_SKYPE },
+ { 0x5EF54C00, 23, NDPI_PROTOCOL_SKYPE },
+ { 0x5EF55200, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x68280000, 13, NDPI_PROTOCOL_SKYPE },
+ { 0x68920000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0x68928000, 17, NDPI_PROTOCOL_SKYPE },
+ { 0x68D00000, 13, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD1000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD1000, 21, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD1700, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD4000, 18, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD4000, 21, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD4200, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD4500, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD4600, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD4E00, 23, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD5000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD6000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD7000, 21, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD7800, 22, NDPI_PROTOCOL_SKYPE },
+ { 0x6FDD7C00, 22, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD0100, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD0500, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD0600, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD0800, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD0C00, 22, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD1200, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD1500, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD1800, 21, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD2000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD2100, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD2200, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD3D00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD3E00, 23, NDPI_PROTOCOL_SKYPE },
+ { 0x83FD8000, 17, NDPI_PROTOCOL_SKYPE },
+ { 0x84F50000, 16, NDPI_PROTOCOL_SKYPE },
+ { 0x84F59C00, 22, NDPI_PROTOCOL_SKYPE },
+ { 0x84F5A000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0x86AA0000, 16, NDPI_PROTOCOL_SKYPE },
+ { 0x86AA8000, 21, NDPI_PROTOCOL_SKYPE },
+ { 0x86AA8800, 21, NDPI_PROTOCOL_SKYPE },
+ { 0x86AAD900, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x89740000, 15, NDPI_PROTOCOL_SKYPE },
+ { 0x89748000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0x8974A000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0x89870000, 16, NDPI_PROTOCOL_SKYPE },
+ { 0x8A5B0000, 16, NDPI_PROTOCOL_SKYPE },
+ { 0x8A5B0000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0x8A5B1000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0x8A5B2000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0x9D370000, 16, NDPI_PROTOCOL_SKYPE },
+ { 0x9D380000, 16, NDPI_PROTOCOL_SKYPE },
+ { 0x9D3C1700, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x9D3C1F00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xA7DCF000, 22, NDPI_PROTOCOL_SKYPE },
+ { 0xA83D0000, 16, NDPI_PROTOCOL_SKYPE },
+ { 0xA83E0000, 15, NDPI_PROTOCOL_SKYPE },
+ { 0xA83F8000, 17, NDPI_PROTOCOL_SKYPE },
+ { 0xBFE80000, 13, NDPI_PROTOCOL_SKYPE },
+ { 0xC030E100, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xC0549F00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xC054A000, 23, NDPI_PROTOCOL_SKYPE },
+ { 0xC0C59D00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xC1954000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0xC1DD7100, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xC6310800, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xC6C88200, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xC6CEA400, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xC71E1000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0xC73C1C00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xC74AD200, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xC7675A00, 23, NDPI_PROTOCOL_SKYPE },
+ { 0xC7677A00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xC7F23000, 21, NDPI_PROTOCOL_SKYPE },
+ { 0xCA59E000, 21, NDPI_PROTOCOL_SKYPE },
+ { 0xCC4F8700, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xCC4FB300, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xCC4FC300, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xCC4FC500, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xCC4FFC00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xCC5F6000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0xCC988C00, 23, NDPI_PROTOCOL_SKYPE },
+ { 0xCE8AA800, 21, NDPI_PROTOCOL_SKYPE },
+ { 0xCEBFE000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E0000, 16, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E0000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E2000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E2900, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E3000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E3A00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E3E00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E4000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E4800, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E4D00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E6000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E6200, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E8000, 17, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2E8000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0xCF2EE000, 20, NDPI_PROTOCOL_SKYPE },
+ { 0xCF448000, 18, NDPI_PROTOCOL_SKYPE },
+ { 0xCF52FA00, 23, NDPI_PROTOCOL_SKYPE },
+ { 0xD0448800, 21, NDPI_PROTOCOL_SKYPE },
+ { 0xD04C2D00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xD04C2E00, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xD0540000, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xD0540100, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xD0540200, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xD0540300, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xD1017000, 23, NDPI_PROTOCOL_SKYPE },
+ { 0xD1B98000, 22, NDPI_PROTOCOL_SKYPE },
+ { 0xD1B9F000, 22, NDPI_PROTOCOL_SKYPE },
+ { 0xD1F0C000, 19, NDPI_PROTOCOL_SKYPE },
+ { 0xD5C78000, 18, NDPI_PROTOCOL_SKYPE },
+ { 0xD820B400, 22, NDPI_PROTOCOL_SKYPE },
+ { 0xD820F000, 22, NDPI_PROTOCOL_SKYPE },
+ { 0xD820F200, 24, NDPI_PROTOCOL_SKYPE },
+ { 0xD821F000, 22, NDPI_PROTOCOL_SKYPE },
+ { 0xD4A10800, 24, NDPI_PROTOCOL_SKYPE },
+ { 0x012A1231, 32, NDPI_PROTOCOL_TOR },
+ { 0x01E69FA1, 32, NDPI_PROTOCOL_TOR },
+ { 0x020DE985, 32, NDPI_PROTOCOL_TOR },
+ { 0x021D88C5, 32, NDPI_PROTOCOL_TOR },
+ { 0x0221585B, 32, NDPI_PROTOCOL_TOR },
+ { 0x023E1975, 32, NDPI_PROTOCOL_TOR },
+ { 0x0255D62F, 32, NDPI_PROTOCOL_TOR },
+ { 0x025B6A07, 32, NDPI_PROTOCOL_TOR },
+ { 0x025CB2FE, 32, NDPI_PROTOCOL_TOR },
+ { 0x025DFEE6, 32, NDPI_PROTOCOL_TOR },
+ { 0x025E83A7, 32, NDPI_PROTOCOL_TOR },
+ { 0x02683058, 32, NDPI_PROTOCOL_TOR },
+ { 0x026AEE77, 32, NDPI_PROTOCOL_TOR },
+ { 0x026B16BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x028BD8A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x02D9E930, 32, NDPI_PROTOCOL_TOR },
+ { 0x02E18D86, 32, NDPI_PROTOCOL_TOR },
+ { 0x02E1E75C, 32, NDPI_PROTOCOL_TOR },
+ { 0x02E688B0, 32, NDPI_PROTOCOL_TOR },
+ { 0x02E6A4FE, 32, NDPI_PROTOCOL_TOR },
+ { 0x02E7F51D, 32, NDPI_PROTOCOL_TOR },
+ { 0x02EAEAFB, 32, NDPI_PROTOCOL_TOR },
+ { 0x02EB2A85, 32, NDPI_PROTOCOL_TOR },
+ { 0x02F04269, 32, NDPI_PROTOCOL_TOR },
+ { 0x02F0667E, 32, NDPI_PROTOCOL_TOR },
+ { 0x02F0DA7F, 32, NDPI_PROTOCOL_TOR },
+ { 0x02F183CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x02F1A8DE, 32, NDPI_PROTOCOL_TOR },
+ { 0x02F2F217, 32, NDPI_PROTOCOL_TOR },
+ { 0x02F2FBEB, 32, NDPI_PROTOCOL_TOR },
+ { 0x02F4CD37, 32, NDPI_PROTOCOL_TOR },
+ { 0x02F779C1, 32, NDPI_PROTOCOL_TOR },
+ { 0x0422C8FD, 32, NDPI_PROTOCOL_TOR },
+ { 0x0422C8FD, 32, NDPI_PROTOCOL_TOR },
+ { 0x0501547D, 32, NDPI_PROTOCOL_TOR },
+ { 0x05021027, 32, NDPI_PROTOCOL_TOR },
+ { 0x050902CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x050906A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x05091513, 32, NDPI_PROTOCOL_TOR },
+ { 0x05091ADB, 32, NDPI_PROTOCOL_TOR },
+ { 0x05091ADB, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509254B, 32, NDPI_PROTOCOL_TOR },
+ { 0x05092771, 32, NDPI_PROTOCOL_TOR },
+ { 0x05092B03, 32, NDPI_PROTOCOL_TOR },
+ { 0x05092B50, 32, NDPI_PROTOCOL_TOR },
+ { 0x05093176, 32, NDPI_PROTOCOL_TOR },
+ { 0x05093394, 32, NDPI_PROTOCOL_TOR },
+ { 0x050933AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509362C, 32, NDPI_PROTOCOL_TOR },
+ { 0x05093B4E, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509437C, 32, NDPI_PROTOCOL_TOR },
+ { 0x05094F06, 32, NDPI_PROTOCOL_TOR },
+ { 0x05094F9A, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509501C, 32, NDPI_PROTOCOL_TOR },
+ { 0x050953CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x05095812, 32, NDPI_PROTOCOL_TOR },
+ { 0x050959BD, 32, NDPI_PROTOCOL_TOR },
+ { 0x05096C4A, 32, NDPI_PROTOCOL_TOR },
+ { 0x05096C56, 32, NDPI_PROTOCOL_TOR },
+ { 0x05096E85, 32, NDPI_PROTOCOL_TOR },
+ { 0x05096EEC, 32, NDPI_PROTOCOL_TOR },
+ { 0x050975D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x05097B51, 32, NDPI_PROTOCOL_TOR },
+ { 0x050981DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x05098A9B, 32, NDPI_PROTOCOL_TOR },
+ { 0x05098CC3, 32, NDPI_PROTOCOL_TOR },
+ { 0x050997F1, 32, NDPI_PROTOCOL_TOR },
+ { 0x05099C11, 32, NDPI_PROTOCOL_TOR },
+ { 0x05099E44, 32, NDPI_PROTOCOL_TOR },
+ { 0x05099E4B, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509A92E, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509A92E, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509BF34, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509C38C, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509D4CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509D642, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509E35E, 32, NDPI_PROTOCOL_TOR },
+ { 0x0509EAEE, 32, NDPI_PROTOCOL_TOR },
+ { 0x050D3E81, 32, NDPI_PROTOCOL_TOR },
+ { 0x050E066C, 32, NDPI_PROTOCOL_TOR },
+ { 0x050E30B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x050E476B, 32, NDPI_PROTOCOL_TOR },
+ { 0x050ECAE6, 32, NDPI_PROTOCOL_TOR },
+ { 0x0513A267, 32, NDPI_PROTOCOL_TOR },
+ { 0x0513B30A, 32, NDPI_PROTOCOL_TOR },
+ { 0x0513EC45, 32, NDPI_PROTOCOL_TOR },
+ { 0x0522B70F, 32, NDPI_PROTOCOL_TOR },
+ { 0x0522B7CD, 32, NDPI_PROTOCOL_TOR },
+ { 0x0522B7CF, 32, NDPI_PROTOCOL_TOR },
+ { 0x05272D98, 32, NDPI_PROTOCOL_TOR },
+ { 0x05273CF1, 32, NDPI_PROTOCOL_TOR },
+ { 0x0527465F, 32, NDPI_PROTOCOL_TOR },
+ { 0x05274C24, 32, NDPI_PROTOCOL_TOR },
+ { 0x05274CB6, 32, NDPI_PROTOCOL_TOR },
+ { 0x05274DD0, 32, NDPI_PROTOCOL_TOR },
+ { 0x05274E65, 32, NDPI_PROTOCOL_TOR },
+ { 0x05274FB5, 32, NDPI_PROTOCOL_TOR },
+ { 0x0527501C, 32, NDPI_PROTOCOL_TOR },
+ { 0x05275087, 32, NDPI_PROTOCOL_TOR },
+ { 0x05275087, 32, NDPI_PROTOCOL_TOR },
+ { 0x052752C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x052753D9, 32, NDPI_PROTOCOL_TOR },
+ { 0x052754D9, 32, NDPI_PROTOCOL_TOR },
+ { 0x052756CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x0527579C, 32, NDPI_PROTOCOL_TOR },
+ { 0x05275808, 32, NDPI_PROTOCOL_TOR },
+ { 0x05275813, 32, NDPI_PROTOCOL_TOR },
+ { 0x05275836, 32, NDPI_PROTOCOL_TOR },
+ { 0x0527597C, 32, NDPI_PROTOCOL_TOR },
+ { 0x05277240, 32, NDPI_PROTOCOL_TOR },
+ { 0x05277A42, 32, NDPI_PROTOCOL_TOR },
+ { 0x05277A42, 32, NDPI_PROTOCOL_TOR },
+ { 0x052A0AE5, 32, NDPI_PROTOCOL_TOR },
+ { 0x052C634D, 32, NDPI_PROTOCOL_TOR },
+ { 0x052C63A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x052C6B17, 32, NDPI_PROTOCOL_TOR },
+ { 0x052D4824, 32, NDPI_PROTOCOL_TOR },
+ { 0x052D4909, 32, NDPI_PROTOCOL_TOR },
+ { 0x052D4D11, 32, NDPI_PROTOCOL_TOR },
+ { 0x052D617F, 32, NDPI_PROTOCOL_TOR },
+ { 0x052D626F, 32, NDPI_PROTOCOL_TOR },
+ { 0x052D634B, 32, NDPI_PROTOCOL_TOR },
+ { 0x052D688D, 32, NDPI_PROTOCOL_TOR },
+ { 0x052D6CBD, 32, NDPI_PROTOCOL_TOR },
+ { 0x0536FAC4, 32, NDPI_PROTOCOL_TOR },
+ { 0x0538E13D, 32, NDPI_PROTOCOL_TOR },
+ { 0x0538E4D0, 32, NDPI_PROTOCOL_TOR },
+ { 0x053D223F, 32, NDPI_PROTOCOL_TOR },
+ { 0x053D260B, 32, NDPI_PROTOCOL_TOR },
+ { 0x053DA005, 32, NDPI_PROTOCOL_TOR },
+ { 0x054F44A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x054F44A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x054F47C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x054F4E61, 32, NDPI_PROTOCOL_TOR },
+ { 0x054F51C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x054F56A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x056476A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x056565E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x05656652, 32, NDPI_PROTOCOL_TOR },
+ { 0x05656746, 32, NDPI_PROTOCOL_TOR },
+ { 0x0567688C, 32, NDPI_PROTOCOL_TOR },
+ { 0x0567E82F, 32, NDPI_PROTOCOL_TOR },
+ { 0x05685A1D, 32, NDPI_PROTOCOL_TOR },
+ { 0x05686A26, 32, NDPI_PROTOCOL_TOR },
+ { 0x0581F54D, 32, NDPI_PROTOCOL_TOR },
+ { 0x0581FAAD, 32, NDPI_PROTOCOL_TOR },
+ { 0x058706AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x05873DD1, 32, NDPI_PROTOCOL_TOR },
+ { 0x05873DDA, 32, NDPI_PROTOCOL_TOR },
+ { 0x05875517, 32, NDPI_PROTOCOL_TOR },
+ { 0x05878F54, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587917D, 32, NDPI_PROTOCOL_TOR },
+ { 0x058794AB, 32, NDPI_PROTOCOL_TOR },
+ { 0x058798B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x058798D0, 32, NDPI_PROTOCOL_TOR },
+ { 0x05879ACF, 32, NDPI_PROTOCOL_TOR },
+ { 0x05879B79, 32, NDPI_PROTOCOL_TOR },
+ { 0x05879E65, 32, NDPI_PROTOCOL_TOR },
+ { 0x05879F04, 32, NDPI_PROTOCOL_TOR },
+ { 0x05879F6E, 32, NDPI_PROTOCOL_TOR },
+ { 0x05879FCF, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587A046, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587A21C, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587A2D9, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587A393, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587A5E1, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587B1B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587B209, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587B5D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587B818, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587B991, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587BA49, 32, NDPI_PROTOCOL_TOR },
+ { 0x0587BA9D, 32, NDPI_PROTOCOL_TOR },
+ { 0x058B66B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x0591316A, 32, NDPI_PROTOCOL_TOR },
+ { 0x05922138, 32, NDPI_PROTOCOL_TOR },
+ { 0x05930EA4, 32, NDPI_PROTOCOL_TOR },
+ { 0x0593158F, 32, NDPI_PROTOCOL_TOR },
+ { 0x05937036, 32, NDPI_PROTOCOL_TOR },
+ { 0x0595FA35, 32, NDPI_PROTOCOL_TOR },
+ { 0x0595FAA4, 32, NDPI_PROTOCOL_TOR },
+ { 0x0595FE6D, 32, NDPI_PROTOCOL_TOR },
+ { 0x0595FE72, 32, NDPI_PROTOCOL_TOR },
+ { 0x0596CC95, 32, NDPI_PROTOCOL_TOR },
+ { 0x0596D5F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x0596DE9A, 32, NDPI_PROTOCOL_TOR },
+ { 0x0596EF88, 32, NDPI_PROTOCOL_TOR },
+ { 0x05A4F0C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x05A6DDC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x05A72D58, 32, NDPI_PROTOCOL_TOR },
+ { 0x05A76C53, 32, NDPI_PROTOCOL_TOR },
+ { 0x05A79195, 32, NDPI_PROTOCOL_TOR },
+ { 0x05AC8CC1, 32, NDPI_PROTOCOL_TOR },
+ { 0x05AF714C, 32, NDPI_PROTOCOL_TOR },
+ { 0x05AFC17A, 32, NDPI_PROTOCOL_TOR },
+ { 0x05AFC245, 32, NDPI_PROTOCOL_TOR },
+ { 0x05B256DC, 32, NDPI_PROTOCOL_TOR },
+ { 0x05BD82BB, 32, NDPI_PROTOCOL_TOR },
+ { 0x05BD8738, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C4007B, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C40181, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C404D0, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C40A96, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C40BD0, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C40C4F, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C40C9C, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C40C9F, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C40D1A, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C40E33, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C40EEA, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C41405, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C41455, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C41AC6, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C44134, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C441E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C4426D, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C469E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C4C4A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C4E3A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C4E51D, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C78181, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C782BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C785C1, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C78E5D, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C78E7C, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C78EC3, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C78EE6, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C78EEC, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C7A208, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C7A51B, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C7A621, 32, NDPI_PROTOCOL_TOR },
+ { 0x05C7A78A, 32, NDPI_PROTOCOL_TOR },
+ { 0x05E4618A, 32, NDPI_PROTOCOL_TOR },
+ { 0x05E4CC86, 32, NDPI_PROTOCOL_TOR },
+ { 0x05F6674A, 32, NDPI_PROTOCOL_TOR },
+ { 0x05F91F00, 32, NDPI_PROTOCOL_TOR },
+ { 0x05F99676, 32, NDPI_PROTOCOL_TOR },
+ { 0x05FE818A, 32, NDPI_PROTOCOL_TOR },
+ { 0x05FF57A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x05FF57D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x081C576C, 32, NDPI_PROTOCOL_TOR },
+ { 0x0C845D90, 32, NDPI_PROTOCOL_TOR },
+ { 0x0E20584A, 32, NDPI_PROTOCOL_TOR },
+ { 0x0EA2AFC9, 32, NDPI_PROTOCOL_TOR },
+ { 0x0EC771B3, 32, NDPI_PROTOCOL_TOR },
+ { 0x0ECAE0FB, 32, NDPI_PROTOCOL_TOR },
+ { 0x0ECAE0FB, 32, NDPI_PROTOCOL_TOR },
+ { 0x0F7EF324, 32, NDPI_PROTOCOL_TOR },
+ { 0x12520388, 32, NDPI_PROTOCOL_TOR },
+ { 0x125203C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x125203CD, 32, NDPI_PROTOCOL_TOR },
+ { 0x127D01DE, 32, NDPI_PROTOCOL_TOR },
+ { 0x12B5051C, 32, NDPI_PROTOCOL_TOR },
+ { 0x12B50525, 32, NDPI_PROTOCOL_TOR },
+ { 0x12BB0144, 32, NDPI_PROTOCOL_TOR },
+ { 0x12BD4791, 32, NDPI_PROTOCOL_TOR },
+ { 0x12E400BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x12EE0155, 32, NDPI_PROTOCOL_TOR },
+ { 0x12EE0255, 32, NDPI_PROTOCOL_TOR },
+ { 0x12EF008C, 32, NDPI_PROTOCOL_TOR },
+ { 0x12EF009B, 32, NDPI_PROTOCOL_TOR },
+ { 0x12F3001E, 32, NDPI_PROTOCOL_TOR },
+ { 0x17159AC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x17162143, 32, NDPI_PROTOCOL_TOR },
+ { 0x17198709, 32, NDPI_PROTOCOL_TOR },
+ { 0x1750E204, 32, NDPI_PROTOCOL_TOR },
+ { 0x1758E805, 32, NDPI_PROTOCOL_TOR },
+ { 0x175B15E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x175B420B, 32, NDPI_PROTOCOL_TOR },
+ { 0x175C1308, 32, NDPI_PROTOCOL_TOR },
+ { 0x175C144D, 32, NDPI_PROTOCOL_TOR },
+ { 0x175C154A, 32, NDPI_PROTOCOL_TOR },
+ { 0x175C1A72, 32, NDPI_PROTOCOL_TOR },
+ { 0x175CDC55, 32, NDPI_PROTOCOL_TOR },
+ { 0x175E1BE3, 32, NDPI_PROTOCOL_TOR },
+ { 0x175E2B4C, 32, NDPI_PROTOCOL_TOR },
+ { 0x175E3FA2, 32, NDPI_PROTOCOL_TOR },
+ { 0x175E6595, 32, NDPI_PROTOCOL_TOR },
+ { 0x175ED723, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F092F, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F2687, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F26A0, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F27A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F2B1D, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F2B49, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F2B4B, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F2B4C, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F2B4D, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F2B52, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F6E41, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F6F50, 32, NDPI_PROTOCOL_TOR },
+ { 0x175F70C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x1763514C, 32, NDPI_PROTOCOL_TOR },
+ { 0x1766A02E, 32, NDPI_PROTOCOL_TOR },
+ { 0x177A8D00, 32, NDPI_PROTOCOL_TOR },
+ { 0x17E283AF, 32, NDPI_PROTOCOL_TOR },
+ { 0x17E28484, 32, NDPI_PROTOCOL_TOR },
+ { 0x17E94164, 32, NDPI_PROTOCOL_TOR },
+ { 0x17E96B78, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EE11E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EEE636, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EF045E, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EF0590, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EF0A90, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EF1378, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EF1378, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EF1399, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EF1B1C, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EF1D41, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EF1D41, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EF1DE2, 32, NDPI_PROTOCOL_TOR },
+ { 0x17EF7165, 32, NDPI_PROTOCOL_TOR },
+ { 0x17FA079F, 32, NDPI_PROTOCOL_TOR },
+ { 0x17FC36AA, 32, NDPI_PROTOCOL_TOR },
+ { 0x17FE8026, 32, NDPI_PROTOCOL_TOR },
+ { 0x17FEA584, 32, NDPI_PROTOCOL_TOR },
+ { 0x17FEA5FA, 32, NDPI_PROTOCOL_TOR },
+ { 0x17FEA6DE, 32, NDPI_PROTOCOL_TOR },
+ { 0x17FEA7E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x17FFC32F, 32, NDPI_PROTOCOL_TOR },
+ { 0x17FFCC6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x17FFF26D, 32, NDPI_PROTOCOL_TOR },
+ { 0x18015D49, 32, NDPI_PROTOCOL_TOR },
+ { 0x18041FF9, 32, NDPI_PROTOCOL_TOR },
+ { 0x18048A52, 32, NDPI_PROTOCOL_TOR },
+ { 0x18084CAE, 32, NDPI_PROTOCOL_TOR },
+ { 0x180AEB3E, 32, NDPI_PROTOCOL_TOR },
+ { 0x180CFAC8, 32, NDPI_PROTOCOL_TOR },
+ { 0x180D9384, 32, NDPI_PROTOCOL_TOR },
+ { 0x1810444C, 32, NDPI_PROTOCOL_TOR },
+ { 0x1811131D, 32, NDPI_PROTOCOL_TOR },
+ { 0x18140EAF, 32, NDPI_PROTOCOL_TOR },
+ { 0x18153FC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x18157F86, 32, NDPI_PROTOCOL_TOR },
+ { 0x18158EEB, 32, NDPI_PROTOCOL_TOR },
+ { 0x1815BE96, 32, NDPI_PROTOCOL_TOR },
+ { 0x1815EACE, 32, NDPI_PROTOCOL_TOR },
+ { 0x18166B48, 32, NDPI_PROTOCOL_TOR },
+ { 0x1816B6B0, 32, NDPI_PROTOCOL_TOR },
+ { 0x18228E2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x1833357C, 32, NDPI_PROTOCOL_TOR },
+ { 0x1834CE43, 32, NDPI_PROTOCOL_TOR },
+ { 0x1834DF47, 32, NDPI_PROTOCOL_TOR },
+ { 0x1834F2AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x183E84AB, 32, NDPI_PROTOCOL_TOR },
+ { 0x183ECD0A, 32, NDPI_PROTOCOL_TOR },
+ { 0x18405FB8, 32, NDPI_PROTOCOL_TOR },
+ { 0x18446509, 32, NDPI_PROTOCOL_TOR },
+ { 0x185AC5F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x18601285, 32, NDPI_PROTOCOL_TOR },
+ { 0x186339F8, 32, NDPI_PROTOCOL_TOR },
+ { 0x1868D868, 32, NDPI_PROTOCOL_TOR },
+ { 0x186BDA67, 32, NDPI_PROTOCOL_TOR },
+ { 0x187950A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x1880EB2A, 32, NDPI_PROTOCOL_TOR },
+ { 0x18815804, 32, NDPI_PROTOCOL_TOR },
+ { 0x188628E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x1886424B, 32, NDPI_PROTOCOL_TOR },
+ { 0x1886A34A, 32, NDPI_PROTOCOL_TOR },
+ { 0x1887456F, 32, NDPI_PROTOCOL_TOR },
+ { 0x188CE8A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x18943BB9, 32, NDPI_PROTOCOL_TOR },
+ { 0x18973BA8, 32, NDPI_PROTOCOL_TOR },
+ { 0x189C1043, 32, NDPI_PROTOCOL_TOR },
+ { 0x18A0A2C8, 32, NDPI_PROTOCOL_TOR },
+ { 0x18A2F56C, 32, NDPI_PROTOCOL_TOR },
+ { 0x18A57BA7, 32, NDPI_PROTOCOL_TOR },
+ { 0x18A6420B, 32, NDPI_PROTOCOL_TOR },
+ { 0x18AA2AAE, 32, NDPI_PROTOCOL_TOR },
+ { 0x18B5AF66, 32, NDPI_PROTOCOL_TOR },
+ { 0x18B93E50, 32, NDPI_PROTOCOL_TOR },
+ { 0x18BB1408, 32, NDPI_PROTOCOL_TOR },
+ { 0x18BE411A, 32, NDPI_PROTOCOL_TOR },
+ { 0x18C05C02, 32, NDPI_PROTOCOL_TOR },
+ { 0x18C1E947, 32, NDPI_PROTOCOL_TOR },
+ { 0x18C4398A, 32, NDPI_PROTOCOL_TOR },
+ { 0x18CB1026, 32, NDPI_PROTOCOL_TOR },
+ { 0x18CBAD0C, 32, NDPI_PROTOCOL_TOR },
+ { 0x18D48CD3, 32, NDPI_PROTOCOL_TOR },
+ { 0x18D67228, 32, NDPI_PROTOCOL_TOR },
+ { 0x18D921A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x18DCAE5D, 32, NDPI_PROTOCOL_TOR },
+ { 0x18E94A6F, 32, NDPI_PROTOCOL_TOR },
+ { 0x18EFCCC4, 32, NDPI_PROTOCOL_TOR },
+ { 0x18FBC42B, 32, NDPI_PROTOCOL_TOR },
+ { 0x18FC70B1, 32, NDPI_PROTOCOL_TOR },
+ { 0x1B6D75D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x1B78549C, 32, NDPI_PROTOCOL_TOR },
+ { 0x1B7C7C7A, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F036525, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F07B826, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F07B84C, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F07BADF, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F088004, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F0A4D53, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F0B41C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F0BF184, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1018A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F10AE02, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F11CDA0, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1269A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F12A967, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F12B428, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F12FBBE, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F13D492, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F17E469, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F180C17, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1979DC, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1E2413, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1E2E44, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1F4A40, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1F4A71, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1F4B54, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1F4BB5, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1F4CA9, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1F4DDE, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1F4E31, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1F4E8D, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F1F4F98, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F205448, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F21B915, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F22B6B1, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F2AA922, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F2CE29C, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F2D7B2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F30B0E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F326CF7, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F338AC8, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F81A64E, 32, NDPI_PROTOCOL_TOR },
+ { 0x1F86556D, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FAC1FCF, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FB29AE6, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FB8C367, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FB8C370, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FB91BCB, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FC06934, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FC06C42, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FC0E4B9, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FC18B0E, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FC9B5F1, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FCC966A, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FCC968A, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FCC9866, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FCF8399, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FCFF1A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FD2636A, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FD263D2, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FD2694A, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FD269BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FD26E3A, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FD26E82, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FD27FBA, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FDC0580, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FDC0586, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FDC0599, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FDC05C8, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FDC073F, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FDC078F, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FDC07C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FDC2AC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x1FDC326D, 32, NDPI_PROTOCOL_TOR },
+ { 0x20D7A24A, 32, NDPI_PROTOCOL_TOR },
+ { 0x23007F34, 32, NDPI_PROTOCOL_TOR },
+ { 0x23007F34, 32, NDPI_PROTOCOL_TOR },
+ { 0x2437F025, 32, NDPI_PROTOCOL_TOR },
+ { 0x2450B024, 32, NDPI_PROTOCOL_TOR },
+ { 0x25007B98, 32, NDPI_PROTOCOL_TOR },
+ { 0x25007BCF, 32, NDPI_PROTOCOL_TOR },
+ { 0x2501C2B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x2501D288, 32, NDPI_PROTOCOL_TOR },
+ { 0x2501D569, 32, NDPI_PROTOCOL_TOR },
+ { 0x2501D799, 32, NDPI_PROTOCOL_TOR },
+ { 0x25041A62, 32, NDPI_PROTOCOL_TOR },
+ { 0x25041BED, 32, NDPI_PROTOCOL_TOR },
+ { 0x2505A41C, 32, NDPI_PROTOCOL_TOR },
+ { 0x250B231C, 32, NDPI_PROTOCOL_TOR },
+ { 0x250B231C, 32, NDPI_PROTOCOL_TOR },
+ { 0x250B480D, 32, NDPI_PROTOCOL_TOR },
+ { 0x2511AD98, 32, NDPI_PROTOCOL_TOR },
+ { 0x251816D1, 32, NDPI_PROTOCOL_TOR },
+ { 0x2518F260, 32, NDPI_PROTOCOL_TOR },
+ { 0x25223476, 32, NDPI_PROTOCOL_TOR },
+ { 0x25223A38, 32, NDPI_PROTOCOL_TOR },
+ { 0x252C2C0B, 32, NDPI_PROTOCOL_TOR },
+ { 0x252EB809, 32, NDPI_PROTOCOL_TOR },
+ { 0x25304046, 32, NDPI_PROTOCOL_TOR },
+ { 0x2530417A, 32, NDPI_PROTOCOL_TOR },
+ { 0x2530417A, 32, NDPI_PROTOCOL_TOR },
+ { 0x253043AA, 32, NDPI_PROTOCOL_TOR },
+ { 0x25304A4B, 32, NDPI_PROTOCOL_TOR },
+ { 0x25304E9F, 32, NDPI_PROTOCOL_TOR },
+ { 0x25305130, 32, NDPI_PROTOCOL_TOR },
+ { 0x253056A0, 32, NDPI_PROTOCOL_TOR },
+ { 0x25305A99, 32, NDPI_PROTOCOL_TOR },
+ { 0x2530782F, 32, NDPI_PROTOCOL_TOR },
+ { 0x253078C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x253110CB, 32, NDPI_PROTOCOL_TOR },
+ { 0x253A70B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B0227, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B02BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B0EC9, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B1D49, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B24C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B2675, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B2E9F, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B2F1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B2F1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B4365, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B6052, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B60BF, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B63BF, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B640B, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B69D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B69E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B6FC0, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B704A, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B7493, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B7614, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B7662, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B76F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B794E, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B7B8E, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B7D1D, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B85D0, 32, NDPI_PROTOCOL_TOR },
+ { 0x253B9010, 32, NDPI_PROTOCOL_TOR },
+ { 0x253BA2DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x254BA34C, 32, NDPI_PROTOCOL_TOR },
+ { 0x254CCFC4, 32, NDPI_PROTOCOL_TOR },
+ { 0x256E0D88, 32, NDPI_PROTOCOL_TOR },
+ { 0x256E3C0F, 32, NDPI_PROTOCOL_TOR },
+ { 0x256EF1F9, 32, NDPI_PROTOCOL_TOR },
+ { 0x25718DEE, 32, NDPI_PROTOCOL_TOR },
+ { 0x2571B30C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25723407, 32, NDPI_PROTOCOL_TOR },
+ { 0x25780229, 32, NDPI_PROTOCOL_TOR },
+ { 0x25784275, 32, NDPI_PROTOCOL_TOR },
+ { 0x2578A080, 32, NDPI_PROTOCOL_TOR },
+ { 0x2578AC86, 32, NDPI_PROTOCOL_TOR },
+ { 0x2578AC88, 32, NDPI_PROTOCOL_TOR },
+ { 0x2578ACF2, 32, NDPI_PROTOCOL_TOR },
+ { 0x257B700E, 32, NDPI_PROTOCOL_TOR },
+ { 0x257B70FD, 32, NDPI_PROTOCOL_TOR },
+ { 0x257B756F, 32, NDPI_PROTOCOL_TOR },
+ { 0x257B924B, 32, NDPI_PROTOCOL_TOR },
+ { 0x2582E385, 32, NDPI_PROTOCOL_TOR },
+ { 0x2582E386, 32, NDPI_PROTOCOL_TOR },
+ { 0x2585814C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25869E3E, 32, NDPI_PROTOCOL_TOR },
+ { 0x258B03AB, 32, NDPI_PROTOCOL_TOR },
+ { 0x258B03E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x258B0C33, 32, NDPI_PROTOCOL_TOR },
+ { 0x258B0D4E, 32, NDPI_PROTOCOL_TOR },
+ { 0x258B166E, 32, NDPI_PROTOCOL_TOR },
+ { 0x258F094A, 32, NDPI_PROTOCOL_TOR },
+ { 0x25904351, 32, NDPI_PROTOCOL_TOR },
+ { 0x2591FF60, 32, NDPI_PROTOCOL_TOR },
+ { 0x259267E1, 32, NDPI_PROTOCOL_TOR },
+ { 0x25928712, 32, NDPI_PROTOCOL_TOR },
+ { 0x25929590, 32, NDPI_PROTOCOL_TOR },
+ { 0x25939A1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x2599010A, 32, NDPI_PROTOCOL_TOR },
+ { 0x25993585, 32, NDPI_PROTOCOL_TOR },
+ { 0x259DA955, 32, NDPI_PROTOCOL_TOR },
+ { 0x259DC059, 32, NDPI_PROTOCOL_TOR },
+ { 0x259DC2D2, 32, NDPI_PROTOCOL_TOR },
+ { 0x259DC30D, 32, NDPI_PROTOCOL_TOR },
+ { 0x259DC353, 32, NDPI_PROTOCOL_TOR },
+ { 0x259DC38F, 32, NDPI_PROTOCOL_TOR },
+ { 0x259DC3B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x259DC4DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB0012, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB007E, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB0255, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB02E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB02E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB0303, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB0408, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB04DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB052C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB056D, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB074A, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB094F, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB115F, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB122B, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB122B, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB126D, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB12B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB143B, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB144F, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB151C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB159D, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB15B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB1657, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB1683, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB17E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB17E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB1E4E, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB1F27, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB2693, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB27D2, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB33D2, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB3F72, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB4275, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB604E, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB611F, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB615F, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB62B9, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB638F, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB63C1, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB666C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB66BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB675B, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB679C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB692B, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB6941, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB6944, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB6B5B, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB6BD2, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB6BD2, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB6C50, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB6D13, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB6D3A, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB6D45, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB6E3F, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB6ED8, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB7224, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB728C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB732F, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB7487, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB76EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB7C84, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB7CC6, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB7DCF, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB7DCF, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB7DE4, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB7E15, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB8244, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB82E2, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BB89E1, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BBB023, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BBB040, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BBB404, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BBB41C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BBB441, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BBC635, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BBC69F, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BBEFBF, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BBF36D, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BBF428, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BBF6DD, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BC44E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BED50A, 32, NDPI_PROTOCOL_TOR },
+ { 0x25BF8A2B, 32, NDPI_PROTOCOL_TOR },
+ { 0x25C08768, 32, NDPI_PROTOCOL_TOR },
+ { 0x25C2350B, 32, NDPI_PROTOCOL_TOR },
+ { 0x25C3C530, 32, NDPI_PROTOCOL_TOR },
+ { 0x25C86205, 32, NDPI_PROTOCOL_TOR },
+ { 0x25C863FB, 32, NDPI_PROTOCOL_TOR },
+ { 0x25C939D9, 32, NDPI_PROTOCOL_TOR },
+ { 0x25C98337, 32, NDPI_PROTOCOL_TOR },
+ { 0x25C9DF9D, 32, NDPI_PROTOCOL_TOR },
+ { 0x25CCA01C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25CD0983, 32, NDPI_PROTOCOL_TOR },
+ { 0x25CD0B95, 32, NDPI_PROTOCOL_TOR },
+ { 0x25D13BC6, 32, NDPI_PROTOCOL_TOR },
+ { 0x25D14A11, 32, NDPI_PROTOCOL_TOR },
+ { 0x25D16FE5, 32, NDPI_PROTOCOL_TOR },
+ { 0x25D3561F, 32, NDPI_PROTOCOL_TOR },
+ { 0x25DC233D, 32, NDPI_PROTOCOL_TOR },
+ { 0x25DDA125, 32, NDPI_PROTOCOL_TOR },
+ { 0x25DDA137, 32, NDPI_PROTOCOL_TOR },
+ { 0x25DDA2E2, 32, NDPI_PROTOCOL_TOR },
+ { 0x25DDA2E2, 32, NDPI_PROTOCOL_TOR },
+ { 0x25DDA5E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x25DDA5F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x25DDC114, 32, NDPI_PROTOCOL_TOR },
+ { 0x25DDC5B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x25E48203, 32, NDPI_PROTOCOL_TOR },
+ { 0x25E48424, 32, NDPI_PROTOCOL_TOR },
+ { 0x25E60143, 32, NDPI_PROTOCOL_TOR },
+ { 0x25EB30F7, 32, NDPI_PROTOCOL_TOR },
+ { 0x25EB312E, 32, NDPI_PROTOCOL_TOR },
+ { 0x25EB317C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25EB3443, 32, NDPI_PROTOCOL_TOR },
+ { 0x25EB3753, 32, NDPI_PROTOCOL_TOR },
+ { 0x25EB3C39, 32, NDPI_PROTOCOL_TOR },
+ { 0x25EB3C3C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25EB3E07, 32, NDPI_PROTOCOL_TOR },
+ { 0x25F71635, 32, NDPI_PROTOCOL_TOR },
+ { 0x25F732A7, 32, NDPI_PROTOCOL_TOR },
+ { 0x25F7348C, 32, NDPI_PROTOCOL_TOR },
+ { 0x25F735A2, 32, NDPI_PROTOCOL_TOR },
+ { 0x25FC0CBA, 32, NDPI_PROTOCOL_TOR },
+ { 0x25FCBE85, 32, NDPI_PROTOCOL_TOR },
+ { 0x264D16FB, 32, NDPI_PROTOCOL_TOR },
+ { 0x266C0A8C, 32, NDPI_PROTOCOL_TOR },
+ { 0x26825026, 32, NDPI_PROTOCOL_TOR },
+ { 0x26825039, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E5001C, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E5001D, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E54621, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E54622, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E5462A, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E5462A, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E54633, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E54634, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E54635, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E54636, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E5463D, 32, NDPI_PROTOCOL_TOR },
+ { 0x26E54F02, 32, NDPI_PROTOCOL_TOR },
+ { 0x27775DC9, 32, NDPI_PROTOCOL_TOR },
+ { 0x294885AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x294D88FA, 32, NDPI_PROTOCOL_TOR },
+ { 0x2985828E, 32, NDPI_PROTOCOL_TOR },
+ { 0x29B619B5, 32, NDPI_PROTOCOL_TOR },
+ { 0x29D4257A, 32, NDPI_PROTOCOL_TOR },
+ { 0x29D7F1EA, 32, NDPI_PROTOCOL_TOR },
+ { 0x29DF358D, 32, NDPI_PROTOCOL_TOR },
+ { 0x29F201F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x2A02EFEA, 32, NDPI_PROTOCOL_TOR },
+ { 0x2A7010C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x2A701341, 32, NDPI_PROTOCOL_TOR },
+ { 0x2A7013C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x2BFA082A, 32, NDPI_PROTOCOL_TOR },
+ { 0x2BFA0842, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E04009C, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E0418A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E0419D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E0422F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E0427EB, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E0437B1, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E043C6A, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E0457AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E046723, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E046A12, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E046ACF, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E046F7C, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E0474B0, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E047AA2, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E047AAD, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E04AE34, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E04B777, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E04FDC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E051DC4, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E051E05, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E055F13, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E059971, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E09C314, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E0ACDFC, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E0EF5CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E10EA83, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E113FD6, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E138E1D, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E138E7E, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E14F675, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E167BDE, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E1746C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E17551F, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E1C449E, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E1C4581, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E1C6E81, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E1C6EF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E1CCAD6, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E1CCF78, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E20E8EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E20EABD, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E2423D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E24251B, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E2425B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E2425D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E24271A, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E2639C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E263E1E, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E263F07, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E26E9F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E26FA27, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E2779BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E298244, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E298454, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E2B325C, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E2D0F7B, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E2F133A, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E37146D, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E3B27B9, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E3B3A75, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E3B8EEC, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E3B9439, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E3B9998, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E3BB9D7, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E3BF04E, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E48594D, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E49F960, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E691148, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E6960BE, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E69AC56, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E69E8BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E6C27DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E76110C, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E762709, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E76A38F, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E76E5C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E7E47AA, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E7FC664, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E7FCB2F, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E7FD0F8, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E800457, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E802D63, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E802D76, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E80D52B, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E81138F, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E8115E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E817C16, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E84BCDD, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E92E027, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E95120A, 32, NDPI_PROTOCOL_TOR },
+ { 0x2E97D0D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA25245, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA26191, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA340CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA341A0, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA3449C, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA34C20, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA34CFA, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA3DB56, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA5C560, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA5DDA6, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA5DDA6, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA5DFD6, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA5DFD9, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA5DFE3, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA5F08F, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA5F2A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA5F9E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA5FAEB, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA6A127, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA7F533, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA7F545, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EA7F5AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB5EEA4, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB61224, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB6126F, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB612F5, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB61303, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB61563, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB66ABE, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB6845A, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB6D01C, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB7D9F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB7DA8D, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB7DBC4, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB7DC84, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EB9E185, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EBB039C, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EBC0425, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EBC0A17, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EBC2510, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EBC2AB0, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EC29854, 32, NDPI_PROTOCOL_TOR },
+ { 0x2ED80D2F, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EDF485B, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EDF4FDF, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EDF8DA7, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EDFCD19, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EDFF71E, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EE26D30, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EE26EB9, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EE360DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EE4045B, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EE4C713, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EE5EEAC, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EE90046, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EE9EDBB, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EEBE346, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EEC95E0, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EEF62AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EEF6472, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EEF6B4A, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EEF6CC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EEF75B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EF2623D, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EF48AFB, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EF5C841, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EF61484, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EF6220C, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EF623E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EF62E1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EF659A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EF66CAE, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EF66FCF, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EF9258F, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EFC1838, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EFC18F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EFC19F9, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EFC1A02, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EFC98C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x2EFE4BA8, 32, NDPI_PROTOCOL_TOR },
+ { 0x2F376EBC, 32, NDPI_PROTOCOL_TOR },
+ { 0x31CD342B, 32, NDPI_PROTOCOL_TOR },
+ { 0x31D4A626, 32, NDPI_PROTOCOL_TOR },
+ { 0x31D4ADDE, 32, NDPI_PROTOCOL_TOR },
+ { 0x31D4C271, 32, NDPI_PROTOCOL_TOR },
+ { 0x320163E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x32070872, 32, NDPI_PROTOCOL_TOR },
+ { 0x32073D6A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207A1DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207B03B, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207B03B, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207B03C, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207B03D, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207B03D, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207B03E, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207B83A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207C27A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207D2DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207F36B, 32, NDPI_PROTOCOL_TOR },
+ { 0x3207F36B, 32, NDPI_PROTOCOL_TOR },
+ { 0x32092FEE, 32, NDPI_PROTOCOL_TOR },
+ { 0x321F4CC3, 32, NDPI_PROTOCOL_TOR },
+ { 0x321FFF5E, 32, NDPI_PROTOCOL_TOR },
+ { 0x322300F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x322554A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x322B0AF0, 32, NDPI_PROTOCOL_TOR },
+ { 0x322B38B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x322EF39B, 32, NDPI_PROTOCOL_TOR },
+ { 0x32354A02, 32, NDPI_PROTOCOL_TOR },
+ { 0x32355AFB, 32, NDPI_PROTOCOL_TOR },
+ { 0x323995CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x3245A0C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x3248C4CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x324C9FDA, 32, NDPI_PROTOCOL_TOR },
+ { 0x324EC501, 32, NDPI_PROTOCOL_TOR },
+ { 0x324F2036, 32, NDPI_PROTOCOL_TOR },
+ { 0x32511947, 32, NDPI_PROTOCOL_TOR },
+ { 0x32532059, 32, NDPI_PROTOCOL_TOR },
+ { 0x32582849, 32, NDPI_PROTOCOL_TOR },
+ { 0x3258C0F5, 32, NDPI_PROTOCOL_TOR },
+ { 0x325A0246, 32, NDPI_PROTOCOL_TOR },
+ { 0x325DF89A, 32, NDPI_PROTOCOL_TOR },
+ { 0x325DF9E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x326F05DE, 32, NDPI_PROTOCOL_TOR },
+ { 0x326FC86F, 32, NDPI_PROTOCOL_TOR },
+ { 0x32710FAD, 32, NDPI_PROTOCOL_TOR },
+ { 0x327375B9, 32, NDPI_PROTOCOL_TOR },
+ { 0x32737A44, 32, NDPI_PROTOCOL_TOR },
+ { 0x3273E93E, 32, NDPI_PROTOCOL_TOR },
+ { 0x32740095, 32, NDPI_PROTOCOL_TOR },
+ { 0x327403DF, 32, NDPI_PROTOCOL_TOR },
+ { 0x3274048D, 32, NDPI_PROTOCOL_TOR },
+ { 0x32740599, 32, NDPI_PROTOCOL_TOR },
+ { 0x32740AF2, 32, NDPI_PROTOCOL_TOR },
+ { 0x327415AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x32741D36, 32, NDPI_PROTOCOL_TOR },
+ { 0x32741D36, 32, NDPI_PROTOCOL_TOR },
+ { 0x327420D9, 32, NDPI_PROTOCOL_TOR },
+ { 0x3274222C, 32, NDPI_PROTOCOL_TOR },
+ { 0x32742806, 32, NDPI_PROTOCOL_TOR },
+ { 0x32742AF5, 32, NDPI_PROTOCOL_TOR },
+ { 0x32742E14, 32, NDPI_PROTOCOL_TOR },
+ { 0x32742FAB, 32, NDPI_PROTOCOL_TOR },
+ { 0x3274312E, 32, NDPI_PROTOCOL_TOR },
+ { 0x3274320C, 32, NDPI_PROTOCOL_TOR },
+ { 0x3274320C, 32, NDPI_PROTOCOL_TOR },
+ { 0x32743687, 32, NDPI_PROTOCOL_TOR },
+ { 0x32743830, 32, NDPI_PROTOCOL_TOR },
+ { 0x327556D3, 32, NDPI_PROTOCOL_TOR },
+ { 0x328293BF, 32, NDPI_PROTOCOL_TOR },
+ { 0x328C5DDF, 32, NDPI_PROTOCOL_TOR },
+ { 0x328F6411, 32, NDPI_PROTOCOL_TOR },
+ { 0x3294BED5, 32, NDPI_PROTOCOL_TOR },
+ { 0x3298F1C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x32A4685A, 32, NDPI_PROTOCOL_TOR },
+ { 0x32A84435, 32, NDPI_PROTOCOL_TOR },
+ { 0x32B12972, 32, NDPI_PROTOCOL_TOR },
+ { 0x32B1AF1A, 32, NDPI_PROTOCOL_TOR },
+ { 0x32B5B129, 32, NDPI_PROTOCOL_TOR },
+ { 0x32C18F2A, 32, NDPI_PROTOCOL_TOR },
+ { 0x32C701B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x32F11E91, 32, NDPI_PROTOCOL_TOR },
+ { 0x32F57C83, 32, NDPI_PROTOCOL_TOR },
+ { 0x32F74BCD, 32, NDPI_PROTOCOL_TOR },
+ { 0x32F7C37C, 32, NDPI_PROTOCOL_TOR },
+ { 0x32F90236, 32, NDPI_PROTOCOL_TOR },
+ { 0x32FAC9FE, 32, NDPI_PROTOCOL_TOR },
+ { 0x32FAD011, 32, NDPI_PROTOCOL_TOR },
+ { 0x32FADAA1, 32, NDPI_PROTOCOL_TOR },
+ { 0x32FF615D, 32, NDPI_PROTOCOL_TOR },
+ { 0x340A7D8C, 32, NDPI_PROTOCOL_TOR },
+ { 0x364023F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x3640E586, 32, NDPI_PROTOCOL_TOR },
+ { 0x3641ACFE, 32, NDPI_PROTOCOL_TOR },
+ { 0x3641CE17, 32, NDPI_PROTOCOL_TOR },
+ { 0x3641CE2C, 32, NDPI_PROTOCOL_TOR },
+ { 0x3641CE34, 32, NDPI_PROTOCOL_TOR },
+ { 0x3641CE39, 32, NDPI_PROTOCOL_TOR },
+ { 0x3641CE3C, 32, NDPI_PROTOCOL_TOR },
+ { 0x3641CE43, 32, NDPI_PROTOCOL_TOR },
+ { 0x3641CE4A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3641CE4F, 32, NDPI_PROTOCOL_TOR },
+ { 0x3642A01A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3642ED8D, 32, NDPI_PROTOCOL_TOR },
+ { 0x36431231, 32, NDPI_PROTOCOL_TOR },
+ { 0x36441DAA, 32, NDPI_PROTOCOL_TOR },
+ { 0x3645C64F, 32, NDPI_PROTOCOL_TOR },
+ { 0x3649DA8A, 32, NDPI_PROTOCOL_TOR },
+ { 0x364D068C, 32, NDPI_PROTOCOL_TOR },
+ { 0x364D6EBC, 32, NDPI_PROTOCOL_TOR },
+ { 0x364D7868, 32, NDPI_PROTOCOL_TOR },
+ { 0x364D7DC1, 32, NDPI_PROTOCOL_TOR },
+ { 0x364F7EC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x3652C35E, 32, NDPI_PROTOCOL_TOR },
+ { 0x36542A9B, 32, NDPI_PROTOCOL_TOR },
+ { 0x36546A29, 32, NDPI_PROTOCOL_TOR },
+ { 0x36568324, 32, NDPI_PROTOCOL_TOR },
+ { 0x36571DA1, 32, NDPI_PROTOCOL_TOR },
+ { 0x36583B2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x36583F17, 32, NDPI_PROTOCOL_TOR },
+ { 0x3658A5E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x365D2B6D, 32, NDPI_PROTOCOL_TOR },
+ { 0x365E89A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x365E8BA7, 32, NDPI_PROTOCOL_TOR },
+ { 0x365EF005, 32, NDPI_PROTOCOL_TOR },
+ { 0x365EF097, 32, NDPI_PROTOCOL_TOR },
+ { 0x365EF100, 32, NDPI_PROTOCOL_TOR },
+ { 0x365EF1A2, 32, NDPI_PROTOCOL_TOR },
+ { 0x365EF1A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x365EF1AB, 32, NDPI_PROTOCOL_TOR },
+ { 0x365EF1B5, 32, NDPI_PROTOCOL_TOR },
+ { 0x365EF1B8, 32, NDPI_PROTOCOL_TOR },
+ { 0x3692143E, 32, NDPI_PROTOCOL_TOR },
+ { 0x3692CB7D, 32, NDPI_PROTOCOL_TOR },
+ { 0x36941FE1, 32, NDPI_PROTOCOL_TOR },
+ { 0x36946DAA, 32, NDPI_PROTOCOL_TOR },
+ { 0x36949610, 32, NDPI_PROTOCOL_TOR },
+ { 0x3695F2AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x369A0E1A, 32, NDPI_PROTOCOL_TOR },
+ { 0x36A49C46, 32, NDPI_PROTOCOL_TOR },
+ { 0x36AB5EF9, 32, NDPI_PROTOCOL_TOR },
+ { 0x36AD6890, 32, NDPI_PROTOCOL_TOR },
+ { 0x36AF0DB5, 32, NDPI_PROTOCOL_TOR },
+ { 0x36AF5145, 32, NDPI_PROTOCOL_TOR },
+ { 0x36B9A3E2, 32, NDPI_PROTOCOL_TOR },
+ { 0x36BB371D, 32, NDPI_PROTOCOL_TOR },
+ { 0x36BBEF10, 32, NDPI_PROTOCOL_TOR },
+ { 0x36BF1132, 32, NDPI_PROTOCOL_TOR },
+ { 0x36BF7203, 32, NDPI_PROTOCOL_TOR },
+ { 0x36BF80E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x36C25AB0, 32, NDPI_PROTOCOL_TOR },
+ { 0x36D05F8F, 32, NDPI_PROTOCOL_TOR },
+ { 0x36D5A676, 32, NDPI_PROTOCOL_TOR },
+ { 0x36E035C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x36E44160, 32, NDPI_PROTOCOL_TOR },
+ { 0x36E8A7C8, 32, NDPI_PROTOCOL_TOR },
+ { 0x36EBF7DC, 32, NDPI_PROTOCOL_TOR },
+ { 0x36EDB868, 32, NDPI_PROTOCOL_TOR },
+ { 0x36FBC11C, 32, NDPI_PROTOCOL_TOR },
+ { 0x36FBD0B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x36FC6132, 32, NDPI_PROTOCOL_TOR },
+ { 0x3A0775BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x3A604E5D, 32, NDPI_PROTOCOL_TOR },
+ { 0x3AB78278, 32, NDPI_PROTOCOL_TOR },
+ { 0x3B656242, 32, NDPI_PROTOCOL_TOR },
+ { 0x3BA79B3B, 32, NDPI_PROTOCOL_TOR },
+ { 0x3BB14C69, 32, NDPI_PROTOCOL_TOR },
+ { 0x3C230879, 32, NDPI_PROTOCOL_TOR },
+ { 0x3CEA7764, 32, NDPI_PROTOCOL_TOR },
+ { 0x3CF2B70F, 32, NDPI_PROTOCOL_TOR },
+ { 0x3CF8A2B3, 32, NDPI_PROTOCOL_TOR },
+ { 0x3D56E640, 32, NDPI_PROTOCOL_TOR },
+ { 0x3D5A3C79, 32, NDPI_PROTOCOL_TOR },
+ { 0x3DCD303F, 32, NDPI_PROTOCOL_TOR },
+ { 0x3DDB7725, 32, NDPI_PROTOCOL_TOR },
+ { 0x3DE6AE3B, 32, NDPI_PROTOCOL_TOR },
+ { 0x3DE6C615, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E040D0D, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E1E7D29, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E2BAF76, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E2C7FB8, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E315C96, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E3F9D4E, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E3FEFD7, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4B8EA6, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4B8FA7, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4B9617, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4B9DC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4B9FF9, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4BB91A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4BBB2A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4BD198, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4BEBDE, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4BF147, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4BF17F, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4BF74A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4BFB9D, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4BFDF7, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4C20B3, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4C2C95, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E4D554A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E5C6F2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E6C249B, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E6C2530, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E6CAB4C, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E70C338, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E71DF9A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E71FA27, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E71FAB4, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E7A36A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E8D24D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E8D251E, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E8D2574, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E8D2CCE, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E8D2E36, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E8D2EC1, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E8F7968, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E8F8DEE, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E8F91BE, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E8FDE16, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E92842F, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E93FB15, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E9502BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E950D39, 32, NDPI_PROTOCOL_TOR },
+ { 0x3E982BCB, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EA803D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EB0EFE5, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EB287DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EB5EEBA, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EB63D99, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EC5289B, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ECA279D, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ECB0AE6, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ECC6EC6, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED22410, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED22552, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED24579, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED245EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED24A37, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED24A89, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED24A8F, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED24ABA, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED24AC9, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED24C60, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2522C, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED252A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED252B1, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED25404, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED25414, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED25C0B, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED25C0B, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED28438, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED28990, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED289E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED289E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2AA0A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2AA1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2AA8F, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2AC5E, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2B6BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2B6EF, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2BCDA, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2BD22, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2C698, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2CC3D, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2CE19, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2CE19, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2CE35, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2D3ED, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2ECAE, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2ED55, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2EE32, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2F088, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2F3A7, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2F3B1, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED2FCAF, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED448F3, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED45233, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED454E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED45975, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED6063D, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED8D048, 32, NDPI_PROTOCOL_TOR },
+ { 0x3ED97CFD, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EDA4B01, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EDB2E85, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EDBB62A, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EDC8781, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EDC88FD, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EDC9457, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EDC945E, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EDC9460, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EDC9461, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EDCB113, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EE1CA01, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EE2FA55, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EE47585, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EF1F052, 32, NDPI_PROTOCOL_TOR },
+ { 0x3EFF6FC3, 32, NDPI_PROTOCOL_TOR },
+ { 0x3F770D78, 32, NDPI_PROTOCOL_TOR },
+ { 0x3F8EF878, 32, NDPI_PROTOCOL_TOR },
+ { 0x3FE761E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x3FE7B589, 32, NDPI_PROTOCOL_TOR },
+ { 0x3FF95AF8, 32, NDPI_PROTOCOL_TOR },
+ { 0x400535AF, 32, NDPI_PROTOCOL_TOR },
+ { 0x40167D28, 32, NDPI_PROTOCOL_TOR },
+ { 0x4022A5ED, 32, NDPI_PROTOCOL_TOR },
+ { 0x403AC85C, 32, NDPI_PROTOCOL_TOR },
+ { 0x403EF9DE, 32, NDPI_PROTOCOL_TOR },
+ { 0x404552A0, 32, NDPI_PROTOCOL_TOR },
+ { 0x40478F7C, 32, NDPI_PROTOCOL_TOR },
+ { 0x404A7772, 32, NDPI_PROTOCOL_TOR },
+ { 0x404E969E, 32, NDPI_PROTOCOL_TOR },
+ { 0x405713F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x405F3C4B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4071201D, 32, NDPI_PROTOCOL_TOR },
+ { 0x40712CCE, 32, NDPI_PROTOCOL_TOR },
+ { 0x407E2B54, 32, NDPI_PROTOCOL_TOR },
+ { 0x40801EE8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4096D384, 32, NDPI_PROTOCOL_TOR },
+ { 0x40ED332E, 32, NDPI_PROTOCOL_TOR },
+ { 0x40FB0E11, 32, NDPI_PROTOCOL_TOR },
+ { 0x4113B2B1, 32, NDPI_PROTOCOL_TOR },
+ { 0x411DE8C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4124628D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4132CB05, 32, NDPI_PROTOCOL_TOR },
+ { 0x415E2693, 32, NDPI_PROTOCOL_TOR },
+ { 0x416FBA42, 32, NDPI_PROTOCOL_TOR },
+ { 0x41B57080, 32, NDPI_PROTOCOL_TOR },
+ { 0x41B57159, 32, NDPI_PROTOCOL_TOR },
+ { 0x41B57188, 32, NDPI_PROTOCOL_TOR },
+ { 0x41B57BFE, 32, NDPI_PROTOCOL_TOR },
+ { 0x41B57F76, 32, NDPI_PROTOCOL_TOR },
+ { 0x41BF4B1E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4207CDA4, 32, NDPI_PROTOCOL_TOR },
+ { 0x42088235, 32, NDPI_PROTOCOL_TOR },
+ { 0x4208A63E, 32, NDPI_PROTOCOL_TOR },
+ { 0x421F2F84, 32, NDPI_PROTOCOL_TOR },
+ { 0x421FD0F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x422DF72A, 32, NDPI_PROTOCOL_TOR },
+ { 0x424217DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x4244A7E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x42558348, 32, NDPI_PROTOCOL_TOR },
+ { 0x426CCBC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x426D18CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x426F0210, 32, NDPI_PROTOCOL_TOR },
+ { 0x426F0214, 32, NDPI_PROTOCOL_TOR },
+ { 0x42746CB3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4275090A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4283C0D3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4289E293, 32, NDPI_PROTOCOL_TOR },
+ { 0x4292C11F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4294745A, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AB5188, 32, NDPI_PROTOCOL_TOR },
+ { 0x42ABB3C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AC0A43, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AC0CAE, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AC0CFE, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AC216A, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AC21DC, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AFD3F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AFD3F9, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AFD695, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AFD695, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AFD94E, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AFDC99, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AFDD18, 32, NDPI_PROTOCOL_TOR },
+ { 0x42AFDF91, 32, NDPI_PROTOCOL_TOR },
+ { 0x42B4C1DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x42C428FC, 32, NDPI_PROTOCOL_TOR },
+ { 0x42DC03B3, 32, NDPI_PROTOCOL_TOR },
+ { 0x42E421F8, 32, NDPI_PROTOCOL_TOR },
+ { 0x42E42752, 32, NDPI_PROTOCOL_TOR },
+ { 0x42E42772, 32, NDPI_PROTOCOL_TOR },
+ { 0x42E42CCC, 32, NDPI_PROTOCOL_TOR },
+ { 0x42E42FFE, 32, NDPI_PROTOCOL_TOR },
+ { 0x42E436C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x42E43B18, 32, NDPI_PROTOCOL_TOR },
+ { 0x42E43E5B, 32, NDPI_PROTOCOL_TOR },
+ { 0x42F64BA7, 32, NDPI_PROTOCOL_TOR },
+ { 0x42F8CC47, 32, NDPI_PROTOCOL_TOR },
+ { 0x4300A951, 32, NDPI_PROTOCOL_TOR },
+ { 0x4301F94A, 32, NDPI_PROTOCOL_TOR },
+ { 0x43125C8D, 32, NDPI_PROTOCOL_TOR },
+ { 0x43172B2E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4317B5ED, 32, NDPI_PROTOCOL_TOR },
+ { 0x4355853B, 32, NDPI_PROTOCOL_TOR },
+ { 0x43564FB9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4395F029, 32, NDPI_PROTOCOL_TOR },
+ { 0x439EE2CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x43A58EE2, 32, NDPI_PROTOCOL_TOR },
+ { 0x43A864B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x43A92D7F, 32, NDPI_PROTOCOL_TOR },
+ { 0x43AD3984, 32, NDPI_PROTOCOL_TOR },
+ { 0x43AD4C19, 32, NDPI_PROTOCOL_TOR },
+ { 0x43B43F19, 32, NDPI_PROTOCOL_TOR },
+ { 0x43B799D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x43CD598E, 32, NDPI_PROTOCOL_TOR },
+ { 0x43CD704A, 32, NDPI_PROTOCOL_TOR },
+ { 0x43D7FF8C, 32, NDPI_PROTOCOL_TOR },
+ { 0x43DC16BF, 32, NDPI_PROTOCOL_TOR },
+ { 0x43F43639, 32, NDPI_PROTOCOL_TOR },
+ { 0x43F98A71, 32, NDPI_PROTOCOL_TOR },
+ { 0x43FDF527, 32, NDPI_PROTOCOL_TOR },
+ { 0x43FF09CB, 32, NDPI_PROTOCOL_TOR },
+ { 0x440440C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x440859BD, 32, NDPI_PROTOCOL_TOR },
+ { 0x44094F72, 32, NDPI_PROTOCOL_TOR },
+ { 0x440FB66B, 32, NDPI_PROTOCOL_TOR },
+ { 0x442300D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x44238420, 32, NDPI_PROTOCOL_TOR },
+ { 0x44240EFA, 32, NDPI_PROTOCOL_TOR },
+ { 0x44342124, 32, NDPI_PROTOCOL_TOR },
+ { 0x4434AFBE, 32, NDPI_PROTOCOL_TOR },
+ { 0x443A307C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4440A1EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x44416405, 32, NDPI_PROTOCOL_TOR },
+ { 0x44429AD6, 32, NDPI_PROTOCOL_TOR },
+ { 0x44432303, 32, NDPI_PROTOCOL_TOR },
+ { 0x44472E8A, 32, NDPI_PROTOCOL_TOR },
+ { 0x445011A0, 32, NDPI_PROTOCOL_TOR },
+ { 0x44590067, 32, NDPI_PROTOCOL_TOR },
+ { 0x4461BFC0, 32, NDPI_PROTOCOL_TOR },
+ { 0x44669EA3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4468364B, 32, NDPI_PROTOCOL_TOR },
+ { 0x44706295, 32, NDPI_PROTOCOL_TOR },
+ { 0x4471943A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4494A2D8, 32, NDPI_PROTOCOL_TOR },
+ { 0x449528B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x44B7A9A7, 32, NDPI_PROTOCOL_TOR },
+ { 0x44BB40FC, 32, NDPI_PROTOCOL_TOR },
+ { 0x44E003CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x44E003CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x44E4F314, 32, NDPI_PROTOCOL_TOR },
+ { 0x44E7DBD4, 32, NDPI_PROTOCOL_TOR },
+ { 0x44E9EBD9, 32, NDPI_PROTOCOL_TOR },
+ { 0x450C569F, 32, NDPI_PROTOCOL_TOR },
+ { 0x450D2623, 32, NDPI_PROTOCOL_TOR },
+ { 0x451B5416, 32, NDPI_PROTOCOL_TOR },
+ { 0x451C5230, 32, NDPI_PROTOCOL_TOR },
+ { 0x451C5A69, 32, NDPI_PROTOCOL_TOR },
+ { 0x452731C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4532A549, 32, NDPI_PROTOCOL_TOR },
+ { 0x453EA2B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x45402255, 32, NDPI_PROTOCOL_TOR },
+ { 0x454027B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x454030A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x45403430, 32, NDPI_PROTOCOL_TOR },
+ { 0x4543FC87, 32, NDPI_PROTOCOL_TOR },
+ { 0x45596485, 32, NDPI_PROTOCOL_TOR },
+ { 0x455A97E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x455D7F39, 32, NDPI_PROTOCOL_TOR },
+ { 0x45722B5C, 32, NDPI_PROTOCOL_TOR },
+ { 0x45733217, 32, NDPI_PROTOCOL_TOR },
+ { 0x4573C28D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4588E954, 32, NDPI_PROTOCOL_TOR },
+ { 0x458A00E2, 32, NDPI_PROTOCOL_TOR },
+ { 0x458AB189, 32, NDPI_PROTOCOL_TOR },
+ { 0x458D2BC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x45928DBA, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A26B05, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A28B09, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A323DE, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A3640C, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4C3F0, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4C4EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4C524, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4C620, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4C696, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4CD93, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4CEB0, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4CFEA, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4D108, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4D197, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4D312, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4D4B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4D6FA, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4D852, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4DD41, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4DD4E, 32, NDPI_PROTOCOL_TOR },
+ { 0x45A4DD99, 32, NDPI_PROTOCOL_TOR },
+ { 0x45AC94F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x45AC9C67, 32, NDPI_PROTOCOL_TOR },
+ { 0x45ACE727, 32, NDPI_PROTOCOL_TOR },
+ { 0x45B57E1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x45C38CAE, 32, NDPI_PROTOCOL_TOR },
+ { 0x45C456D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x45C4AE92, 32, NDPI_PROTOCOL_TOR },
+ { 0x45C5AF23, 32, NDPI_PROTOCOL_TOR },
+ { 0x45C5AF24, 32, NDPI_PROTOCOL_TOR },
+ { 0x45F5523E, 32, NDPI_PROTOCOL_TOR },
+ { 0x460F3C1D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4618CF2E, 32, NDPI_PROTOCOL_TOR },
+ { 0x462438C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x46261F79, 32, NDPI_PROTOCOL_TOR },
+ { 0x462C2054, 32, NDPI_PROTOCOL_TOR },
+ { 0x463D61E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x463D61E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x463FAA56, 32, NDPI_PROTOCOL_TOR },
+ { 0x46551FF2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4663CC61, 32, NDPI_PROTOCOL_TOR },
+ { 0x4670A038, 32, NDPI_PROTOCOL_TOR },
+ { 0x4670A341, 32, NDPI_PROTOCOL_TOR },
+ { 0x467176E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x46721018, 32, NDPI_PROTOCOL_TOR },
+ { 0x46A22F33, 32, NDPI_PROTOCOL_TOR },
+ { 0x46A2595A, 32, NDPI_PROTOCOL_TOR },
+ { 0x46A56AAE, 32, NDPI_PROTOCOL_TOR },
+ { 0x46A923AD, 32, NDPI_PROTOCOL_TOR },
+ { 0x46B5013D, 32, NDPI_PROTOCOL_TOR },
+ { 0x46BB9A33, 32, NDPI_PROTOCOL_TOR },
+ { 0x46BED043, 32, NDPI_PROTOCOL_TOR },
+ { 0x470EB6E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x47139515, 32, NDPI_PROTOCOL_TOR },
+ { 0x4713954E, 32, NDPI_PROTOCOL_TOR },
+ { 0x47139BBB, 32, NDPI_PROTOCOL_TOR },
+ { 0x47139D7F, 32, NDPI_PROTOCOL_TOR },
+ { 0x47139DD5, 32, NDPI_PROTOCOL_TOR },
+ { 0x47236A50, 32, NDPI_PROTOCOL_TOR },
+ { 0x4738B62B, 32, NDPI_PROTOCOL_TOR },
+ { 0x474BC940, 32, NDPI_PROTOCOL_TOR },
+ { 0x474F591F, 32, NDPI_PROTOCOL_TOR },
+ { 0x474F9691, 32, NDPI_PROTOCOL_TOR },
+ { 0x475ACDF8, 32, NDPI_PROTOCOL_TOR },
+ { 0x475F28FC, 32, NDPI_PROTOCOL_TOR },
+ { 0x47872D47, 32, NDPI_PROTOCOL_TOR },
+ { 0x47A59723, 32, NDPI_PROTOCOL_TOR },
+ { 0x47A79A15, 32, NDPI_PROTOCOL_TOR },
+ { 0x47AE3E2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x47B1E232, 32, NDPI_PROTOCOL_TOR },
+ { 0x47B76C25, 32, NDPI_PROTOCOL_TOR },
+ { 0x47B8FBE9, 32, NDPI_PROTOCOL_TOR },
+ { 0x47B9233B, 32, NDPI_PROTOCOL_TOR },
+ { 0x47B9AB0D, 32, NDPI_PROTOCOL_TOR },
+ { 0x47C3DB07, 32, NDPI_PROTOCOL_TOR },
+ { 0x47C5EB05, 32, NDPI_PROTOCOL_TOR },
+ { 0x47C5FE48, 32, NDPI_PROTOCOL_TOR },
+ { 0x47C772A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x47CAB8E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x47CC7AF0, 32, NDPI_PROTOCOL_TOR },
+ { 0x47D7CE97, 32, NDPI_PROTOCOL_TOR },
+ { 0x47DBB265, 32, NDPI_PROTOCOL_TOR },
+ { 0x47DE7EC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x47E0883A, 32, NDPI_PROTOCOL_TOR },
+ { 0x47E6FD44, 32, NDPI_PROTOCOL_TOR },
+ { 0x47E7BE7B, 32, NDPI_PROTOCOL_TOR },
+ { 0x47EB4AB7, 32, NDPI_PROTOCOL_TOR },
+ { 0x47F5506C, 32, NDPI_PROTOCOL_TOR },
+ { 0x47FB9E4B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4800E332, 32, NDPI_PROTOCOL_TOR },
+ { 0x480EB0AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x480EB1A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x480EB30A, 32, NDPI_PROTOCOL_TOR },
+ { 0x480EB3A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x480EB552, 32, NDPI_PROTOCOL_TOR },
+ { 0x480EB83D, 32, NDPI_PROTOCOL_TOR },
+ { 0x480EBAE2, 32, NDPI_PROTOCOL_TOR },
+ { 0x481AD093, 32, NDPI_PROTOCOL_TOR },
+ { 0x481DA212, 32, NDPI_PROTOCOL_TOR },
+ { 0x482E9BBA, 32, NDPI_PROTOCOL_TOR },
+ { 0x48332350, 32, NDPI_PROTOCOL_TOR },
+ { 0x48344B1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x48345B16, 32, NDPI_PROTOCOL_TOR },
+ { 0x48345B1D, 32, NDPI_PROTOCOL_TOR },
+ { 0x48345B1E, 32, NDPI_PROTOCOL_TOR },
+ { 0x48358586, 32, NDPI_PROTOCOL_TOR },
+ { 0x484200E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4845E5D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4845F863, 32, NDPI_PROTOCOL_TOR },
+ { 0x484E8BB9, 32, NDPI_PROTOCOL_TOR },
+ { 0x48531759, 32, NDPI_PROTOCOL_TOR },
+ { 0x4859E93A, 32, NDPI_PROTOCOL_TOR },
+ { 0x485DF597, 32, NDPI_PROTOCOL_TOR },
+ { 0x488184C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x488313EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x48A0F076, 32, NDPI_PROTOCOL_TOR },
+ { 0x48AEAC8D, 32, NDPI_PROTOCOL_TOR },
+ { 0x48B13B6E, 32, NDPI_PROTOCOL_TOR },
+ { 0x48C0D011, 32, NDPI_PROTOCOL_TOR },
+ { 0x48C105B0, 32, NDPI_PROTOCOL_TOR },
+ { 0x48C5C123, 32, NDPI_PROTOCOL_TOR },
+ { 0x48D1B426, 32, NDPI_PROTOCOL_TOR },
+ { 0x48D1DB9A, 32, NDPI_PROTOCOL_TOR },
+ { 0x48D8ECC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x48DCAD6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x48DE8A0C, 32, NDPI_PROTOCOL_TOR },
+ { 0x48E1295B, 32, NDPI_PROTOCOL_TOR },
+ { 0x48EFE271, 32, NDPI_PROTOCOL_TOR },
+ { 0x48F9B964, 32, NDPI_PROTOCOL_TOR },
+ { 0x48FAD50D, 32, NDPI_PROTOCOL_TOR },
+ { 0x48FD5C2C, 32, NDPI_PROTOCOL_TOR },
+ { 0x49041E43, 32, NDPI_PROTOCOL_TOR },
+ { 0x49043472, 32, NDPI_PROTOCOL_TOR },
+ { 0x4906D179, 32, NDPI_PROTOCOL_TOR },
+ { 0x4908B6E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x490B9E26, 32, NDPI_PROTOCOL_TOR },
+ { 0x490F96AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x490FFEF1, 32, NDPI_PROTOCOL_TOR },
+ { 0x49134ECD, 32, NDPI_PROTOCOL_TOR },
+ { 0x491610C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x492574A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4926F8B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x49274DA6, 32, NDPI_PROTOCOL_TOR },
+ { 0x492C8639, 32, NDPI_PROTOCOL_TOR },
+ { 0x492D254B, 32, NDPI_PROTOCOL_TOR },
+ { 0x492FF6DF, 32, NDPI_PROTOCOL_TOR },
+ { 0x49304E30, 32, NDPI_PROTOCOL_TOR },
+ { 0x49308BE2, 32, NDPI_PROTOCOL_TOR },
+ { 0x498400F7, 32, NDPI_PROTOCOL_TOR },
+ { 0x4984FA0B, 32, NDPI_PROTOCOL_TOR },
+ { 0x49A3EC5F, 32, NDPI_PROTOCOL_TOR },
+ { 0x49A5F4EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x49A64EFD, 32, NDPI_PROTOCOL_TOR },
+ { 0x49A69CAC, 32, NDPI_PROTOCOL_TOR },
+ { 0x49AA0647, 32, NDPI_PROTOCOL_TOR },
+ { 0x49AC98E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x49C08B3F, 32, NDPI_PROTOCOL_TOR },
+ { 0x49C0E718, 32, NDPI_PROTOCOL_TOR },
+ { 0x49C6A499, 32, NDPI_PROTOCOL_TOR },
+ { 0x49C7CBB9, 32, NDPI_PROTOCOL_TOR },
+ { 0x49CAE19F, 32, NDPI_PROTOCOL_TOR },
+ { 0x49D03060, 32, NDPI_PROTOCOL_TOR },
+ { 0x49D0409E, 32, NDPI_PROTOCOL_TOR },
+ { 0x49D0A2E1, 32, NDPI_PROTOCOL_TOR },
+ { 0x49D932BB, 32, NDPI_PROTOCOL_TOR },
+ { 0x49DE0E0A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A03A527, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A323644, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A3BA760, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A3BCC47, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A436379, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A47FA54, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A5203E0, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A536574, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A561813, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A5B1B8D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A5B1B8E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A5E43C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A5FBB69, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A60E7B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A621760, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A65C9F9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A677F7F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A6DF071, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A74BA78, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A79B693, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A7CAB14, 32, NDPI_PROTOCOL_TOR },
+ { 0x4A8AA23A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4AB9DBC9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4AC09417, 32, NDPI_PROTOCOL_TOR },
+ { 0x4AC14C45, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACEB5A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFE03F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFE03F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFE7BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFE7FA, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFE998, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFECC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFED2C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFEDA7, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFEDA7, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFF207, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFF86E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFF9A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ACFFB6D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4AD045C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4AD04E82, 32, NDPI_PROTOCOL_TOR },
+ { 0x4AD2C50C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B013890, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B09754D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B435766, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B451E4D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B488B38, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B4F23FE, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B50A0EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B5169DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B52A04D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B54A327, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B6189EA, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B642932, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B65602F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B7650AB, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B76EED4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B77E8C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B7F0F49, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B82033A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B849247, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B8567ED, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B8FB432, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B91CDB1, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B965B14, 32, NDPI_PROTOCOL_TOR },
+ { 0x4B965B15, 32, NDPI_PROTOCOL_TOR },
+ { 0x4BA665D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4BB117FE, 32, NDPI_PROTOCOL_TOR },
+ { 0x4BB38B1A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4BB3AFC4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4BB66C77, 32, NDPI_PROTOCOL_TOR },
+ { 0x4BB93208, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C0A8078, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C0CDB68, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C17D13D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C1ACBF3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C1CD1A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C1CEA17, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C400D9B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C490364, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C4903AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C493996, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C4AB2F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C4ADB8A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C4C08E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C4F2E66, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C55CFD4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C5BCBA2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C5BE269, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C5CE1D8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C5DD733, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C63DE9C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C66C7AA, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C6A2761, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C702F3C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C7153C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C732D7C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C73829B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C778735, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C7A13E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C7BBBD2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C7C660E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C7CAF69, 32, NDPI_PROTOCOL_TOR },
+ { 0x4C7E0D52, 32, NDPI_PROTOCOL_TOR },
+ { 0x4CAA4864, 32, NDPI_PROTOCOL_TOR },
+ { 0x4CAEFDD2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4CB28C0E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4CB9120F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4CBAB2BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x4CBC4252, 32, NDPI_PROTOCOL_TOR },
+ { 0x4CBFD7D7, 32, NDPI_PROTOCOL_TOR },
+ { 0x4CD11461, 32, NDPI_PROTOCOL_TOR },
+ { 0x4CD90D94, 32, NDPI_PROTOCOL_TOR },
+ { 0x4CD90D94, 32, NDPI_PROTOCOL_TOR },
+ { 0x4CD995F0, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D00C9A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D01045C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D04EB00, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D06EDF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D0A7CF0, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D0AAEE8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D0AD0A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D0C1CB8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D0C1CB8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D0C65BB, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D0C84CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D0DB854, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D0DBCEF, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D142DA8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D1430C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D145762, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D149215, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D149784, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D14C9D3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D1505EA, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D15295E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D154971, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D154D67, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D15D971, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D170724, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D170A99, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D171AE2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D176F1E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D250CBF, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D2588A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D25B87E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D25DA91, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D25F08E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D292F5B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D2DFD87, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D2F7D6F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D2FD16E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D32EB4C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D343FC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D3856DC, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D396860, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D3A033E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D3AD4A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D40D46F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D422DE3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D422E18, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D44245D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D463F8D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D48932F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D489696, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D4E77D3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D51F029, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D56C546, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D56CC64, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6220E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D66D762, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D69D0D9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6D8A2A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6D8A2B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6D8A2C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6D8B1A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6D8B1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6D8B1C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6D8B57, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6D8D8A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6D8D8B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6D8D8C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D6DB99C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D765894, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D7B5606, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D834130, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D86A910, 32, NDPI_PROTOCOL_TOR },
+ { 0x4D98FB30, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DAA0102, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DAE88F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DAEB4C5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DAEF986, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DC5A34D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DCBDD5B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DCF4DB2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DCF6FCE, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DDF4BCF, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DE4A752, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DE4AF4A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DE9EE82, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DEA31CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DEA947A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF30962, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF4FEE3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF4FEE4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF4FEE5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF4FEE6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF6D813, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF7B5A2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF7B5A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF7B5A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF7B5A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF7B5A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF7B5A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DF7B5A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DFB6AF8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4DFEAE40, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E08A504, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E0D3D36, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E1506A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E18DA8A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E1B6E57, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E1FA429, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E227847, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2917A2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E29E9C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2A9D62, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2B689D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2B752E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2B8EB1, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2D136A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E1188, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E2BDD, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E2DF2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E337C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E350B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E3C1E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E40F5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E4229, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E50F7, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E512D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E5F14, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E69F1, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E6A6F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E6B0F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E70DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E7B22, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E7BAC, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E943A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E970B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E9713, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2E989E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2EA78D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2EB0A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2EC54B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2EDA0B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2EDC82, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2EDD7D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2EE185, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2EEFB7, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2EF724, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2EF729, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F0406, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F10A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F126E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F1BF6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F2323, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F273C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F27BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F297D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F2CBC, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F2CD4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F31EB, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F325C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F35B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F3DDE, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F405B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F49B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F5462, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F5699, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F5D0C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F5DC8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F5F9C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F8606, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F8B62, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F9199, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F94AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2F963D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FA559, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FA844, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FABA6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FACF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FAE9B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FBAF3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FBC04, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FBFDD, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FC5AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FD81C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FDABE, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FDBA6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FDE4A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FE0DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FE208, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FE568, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E2FE56B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E301266, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E30213F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E30E5E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E314714, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E337866, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E339FA4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E341CCA, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E344588, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E345BC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E34709C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E3500BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E3543BB, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E3578C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E35D113, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E36B32D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E36B849, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E37167F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E371BD3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E37EECD, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E382816, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E38837E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E448EF1, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E455699, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E460AE6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E559863, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E55C395, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E582ECD, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E5A0FE5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E5A8252, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E5E71A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E5EC2DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E5EFD61, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E66CF73, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E6A9813, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E6BE9E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E6BED10, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E6BEFD5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E6BFE79, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E6C3F2C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E6C3F2E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E6EA0B9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E6F4E8C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E6FEE6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E73B49D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E787A3F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E81891C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E81A639, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E81B421, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E833886, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E8B7228, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E8D50EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E8E8EF6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E8E918D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E8EAF46, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E91349D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E9BA97A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E9C75EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E9C77C8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E9DC871, 32, NDPI_PROTOCOL_TOR },
+ { 0x4E9F3CC3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EC0BD4C, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EC0F14B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EC1067E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EC128CD, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EC128FE, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EC14F78, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EC15603, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EC1674D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EC1A442, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EC6B4CD, 32, NDPI_PROTOCOL_TOR },
+ { 0x4ECD5081, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EDA527F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EDD8C72, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EE030F7, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EE0F0C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EE2A060, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EE588B8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EE96597, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EEC369E, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EEF7556, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EF7B665, 32, NDPI_PROTOCOL_TOR },
+ { 0x4EF8D759, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F4771F0, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F501132, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F59660B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F621F2A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F660402, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F6D109F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F6D94CB, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F6F13C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F6F51A0, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F6FDA32, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F700984, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F716914, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F780A62, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F78282D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F7851B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F825F7B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F861BFF, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F86EAC8, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F86EB05, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F86FF23, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F87465A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F881D2B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F882ABE, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F8BBDB9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F8C27CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F8C2975, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F8C2976, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F8C4005, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F8E6A54, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F8FB36A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F8FB572, 32, NDPI_PROTOCOL_TOR },
+ { 0x4F8FBC46, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FA04C99, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FA0A26A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FA438F1, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FA45FB4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FA5B4F3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FA5DFD1, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FAC1212, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FAC1CCD, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FACC120, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FACCC24, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FACF908, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FB73E97, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FBD0233, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FC17B35, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FC3BA9D, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FC5C597, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FC8C7B3, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FCA6B3A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FCB519B, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FD446F9, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FD62F35, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FD6C9C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FD6E742, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FD7DEA0, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FDCC79F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FE25CA4, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FE2CDCD, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FE2DAE6, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FE3BBBF, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FE478A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FE4EA15, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FE5C024, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FE755CF, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FEA50ED, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FEB63B5, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FEC5A62, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FECD8B0, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FF15810, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FF19FF7, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FF1D2DC, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FF1D690, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FF2515A, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FF35735, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FF5435F, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FF58FAB, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FF6CF32, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FF77321, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FF87986, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FFBF5CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x4FFF9947, 32, NDPI_PROTOCOL_TOR },
+ { 0x50025741, 32, NDPI_PROTOCOL_TOR },
+ { 0x5004F810, 32, NDPI_PROTOCOL_TOR },
+ { 0x500593F5, 32, NDPI_PROTOCOL_TOR },
+ { 0x500C5EB8, 32, NDPI_PROTOCOL_TOR },
+ { 0x502A9965, 32, NDPI_PROTOCOL_TOR },
+ { 0x502AA456, 32, NDPI_PROTOCOL_TOR },
+ { 0x50390AA9, 32, NDPI_PROTOCOL_TOR },
+ { 0x50393FB3, 32, NDPI_PROTOCOL_TOR },
+ { 0x50397C3A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5042877B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5043AC13, 32, NDPI_PROTOCOL_TOR },
+ { 0x504459B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x50445CF9, 32, NDPI_PROTOCOL_TOR },
+ { 0x50478577, 32, NDPI_PROTOCOL_TOR },
+ { 0x504786B5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5049D3D9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5049F28E, 32, NDPI_PROTOCOL_TOR },
+ { 0x504EF251, 32, NDPI_PROTOCOL_TOR },
+ { 0x504EF656, 32, NDPI_PROTOCOL_TOR },
+ { 0x504F1707, 32, NDPI_PROTOCOL_TOR },
+ { 0x5051111F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5051F378, 32, NDPI_PROTOCOL_TOR },
+ { 0x5051F3E2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5051F3EB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5052D7D2, 32, NDPI_PROTOCOL_TOR },
+ { 0x50555448, 32, NDPI_PROTOCOL_TOR },
+ { 0x505554DE, 32, NDPI_PROTOCOL_TOR },
+ { 0x505554F0, 32, NDPI_PROTOCOL_TOR },
+ { 0x50565329, 32, NDPI_PROTOCOL_TOR },
+ { 0x50565CB5, 32, NDPI_PROTOCOL_TOR },
+ { 0x50565D80, 32, NDPI_PROTOCOL_TOR },
+ { 0x5059C09E, 32, NDPI_PROTOCOL_TOR },
+ { 0x505A2B81, 32, NDPI_PROTOCOL_TOR },
+ { 0x505A2BDD, 32, NDPI_PROTOCOL_TOR },
+ { 0x50631FF8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5063FE73, 32, NDPI_PROTOCOL_TOR },
+ { 0x50642620, 32, NDPI_PROTOCOL_TOR },
+ { 0x50642CDB, 32, NDPI_PROTOCOL_TOR },
+ { 0x50642CFD, 32, NDPI_PROTOCOL_TOR },
+ { 0x50642D9C, 32, NDPI_PROTOCOL_TOR },
+ { 0x50648003, 32, NDPI_PROTOCOL_TOR },
+ { 0x5064BD03, 32, NDPI_PROTOCOL_TOR },
+ { 0x5064CC04, 32, NDPI_PROTOCOL_TOR },
+ { 0x5064CE96, 32, NDPI_PROTOCOL_TOR },
+ { 0x506573AA, 32, NDPI_PROTOCOL_TOR },
+ { 0x506C8F13, 32, NDPI_PROTOCOL_TOR },
+ { 0x506DA2EA, 32, NDPI_PROTOCOL_TOR },
+ { 0x506DE134, 32, NDPI_PROTOCOL_TOR },
+ { 0x506E2316, 32, NDPI_PROTOCOL_TOR },
+ { 0x506E37C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x506FEC0F, 32, NDPI_PROTOCOL_TOR },
+ { 0x50709921, 32, NDPI_PROTOCOL_TOR },
+ { 0x5071010B, 32, NDPI_PROTOCOL_TOR },
+ { 0x50743860, 32, NDPI_PROTOCOL_TOR },
+ { 0x50764CC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x50807E83, 32, NDPI_PROTOCOL_TOR },
+ { 0x50814072, 32, NDPI_PROTOCOL_TOR },
+ { 0x50868F7F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5087E176, 32, NDPI_PROTOCOL_TOR },
+ { 0x508874C1, 32, NDPI_PROTOCOL_TOR },
+ { 0x50894240, 32, NDPI_PROTOCOL_TOR },
+ { 0x508AEC03, 32, NDPI_PROTOCOL_TOR },
+ { 0x508AEFF3, 32, NDPI_PROTOCOL_TOR },
+ { 0x508B637B, 32, NDPI_PROTOCOL_TOR },
+ { 0x508B727D, 32, NDPI_PROTOCOL_TOR },
+ { 0x508C6003, 32, NDPI_PROTOCOL_TOR },
+ { 0x508F6A3C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5093219D, 32, NDPI_PROTOCOL_TOR },
+ { 0x509325F7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5098EF17, 32, NDPI_PROTOCOL_TOR },
+ { 0x50990704, 32, NDPI_PROTOCOL_TOR },
+ { 0x50A19C30, 32, NDPI_PROTOCOL_TOR },
+ { 0x50A20720, 32, NDPI_PROTOCOL_TOR },
+ { 0x50A32958, 32, NDPI_PROTOCOL_TOR },
+ { 0x50A770EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x50AB1353, 32, NDPI_PROTOCOL_TOR },
+ { 0x50AB285B, 32, NDPI_PROTOCOL_TOR },
+ { 0x50C3B7F0, 32, NDPI_PROTOCOL_TOR },
+ { 0x50CAAF5A, 32, NDPI_PROTOCOL_TOR },
+ { 0x50CAEE20, 32, NDPI_PROTOCOL_TOR },
+ { 0x50CB102E, 32, NDPI_PROTOCOL_TOR },
+ { 0x50D4A2ED, 32, NDPI_PROTOCOL_TOR },
+ { 0x50D87BFC, 32, NDPI_PROTOCOL_TOR },
+ { 0x50DA9F57, 32, NDPI_PROTOCOL_TOR },
+ { 0x50DAD94E, 32, NDPI_PROTOCOL_TOR },
+ { 0x50DB0244, 32, NDPI_PROTOCOL_TOR },
+ { 0x50DB8C29, 32, NDPI_PROTOCOL_TOR },
+ { 0x50DC5274, 32, NDPI_PROTOCOL_TOR },
+ { 0x50DCE66B, 32, NDPI_PROTOCOL_TOR },
+ { 0x50DCF46B, 32, NDPI_PROTOCOL_TOR },
+ { 0x50DFA940, 32, NDPI_PROTOCOL_TOR },
+ { 0x50DFB670, 32, NDPI_PROTOCOL_TOR },
+ { 0x50DFD0F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x50E500D2, 32, NDPI_PROTOCOL_TOR },
+ { 0x50EDE24B, 32, NDPI_PROTOCOL_TOR },
+ { 0x50EEE5A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F08096, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F080E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F086F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F08D97, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F1D942, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F1DA9A, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F1DCDD, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F1DE24, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F1DE62, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F4F39E, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F63BE9, 32, NDPI_PROTOCOL_TOR },
+ { 0x50F8D083, 32, NDPI_PROTOCOL_TOR },
+ { 0x50FEDB30, 32, NDPI_PROTOCOL_TOR },
+ { 0x50FF0BD3, 32, NDPI_PROTOCOL_TOR },
+ { 0x50FF0BE0, 32, NDPI_PROTOCOL_TOR },
+ { 0x50FF0BED, 32, NDPI_PROTOCOL_TOR },
+ { 0x5102C521, 32, NDPI_PROTOCOL_TOR },
+ { 0x5102ECA5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5104655D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5104676A, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046810, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046852, 32, NDPI_PROTOCOL_TOR },
+ { 0x510469C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046B24, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046B44, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046BBE, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046BE3, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046CC7, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046D2F, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046D7D, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046DD0, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046DFA, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046E5D, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046E95, 32, NDPI_PROTOCOL_TOR },
+ { 0x51046F6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x51047930, 32, NDPI_PROTOCOL_TOR },
+ { 0x510479B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x510479DE, 32, NDPI_PROTOCOL_TOR },
+ { 0x510479E0, 32, NDPI_PROTOCOL_TOR },
+ { 0x510479F3, 32, NDPI_PROTOCOL_TOR },
+ { 0x51047D81, 32, NDPI_PROTOCOL_TOR },
+ { 0x51047E79, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070777, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070865, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070A11, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070A1D, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070A1D, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070A44, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070AFB, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070B46, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070BFD, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070D54, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070D5A, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070DF8, 32, NDPI_PROTOCOL_TOR },
+ { 0x51070EF6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5107103B, 32, NDPI_PROTOCOL_TOR },
+ { 0x510A9F12, 32, NDPI_PROTOCOL_TOR },
+ { 0x511115F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5114849E, 32, NDPI_PROTOCOL_TOR },
+ { 0x51148B91, 32, NDPI_PROTOCOL_TOR },
+ { 0x5115F642, 32, NDPI_PROTOCOL_TOR },
+ { 0x511932A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x511CC585, 32, NDPI_PROTOCOL_TOR },
+ { 0x511E9858, 32, NDPI_PROTOCOL_TOR },
+ { 0x511E9858, 32, NDPI_PROTOCOL_TOR },
+ { 0x511F5A52, 32, NDPI_PROTOCOL_TOR },
+ { 0x513842D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5139852A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5139D087, 32, NDPI_PROTOCOL_TOR },
+ { 0x514080DE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5140E6FD, 32, NDPI_PROTOCOL_TOR },
+ { 0x51475D6A, 32, NDPI_PROTOCOL_TOR },
+ { 0x51533A04, 32, NDPI_PROTOCOL_TOR },
+ { 0x51544C43, 32, NDPI_PROTOCOL_TOR },
+ { 0x51569E1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x515900C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x515900C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x515900C5, 32, NDPI_PROTOCOL_TOR },
+ { 0x515900C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x515900C7, 32, NDPI_PROTOCOL_TOR },
+ { 0x515900C8, 32, NDPI_PROTOCOL_TOR },
+ { 0x515900C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x515900CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x515900CB, 32, NDPI_PROTOCOL_TOR },
+ { 0x515900CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x51596058, 32, NDPI_PROTOCOL_TOR },
+ { 0x51596059, 32, NDPI_PROTOCOL_TOR },
+ { 0x51596535, 32, NDPI_PROTOCOL_TOR },
+ { 0x515CACE7, 32, NDPI_PROTOCOL_TOR },
+ { 0x515F0522, 32, NDPI_PROTOCOL_TOR },
+ { 0x515F3444, 32, NDPI_PROTOCOL_TOR },
+ { 0x5160DB54, 32, NDPI_PROTOCOL_TOR },
+ { 0x5161B784, 32, NDPI_PROTOCOL_TOR },
+ { 0x5163F715, 32, NDPI_PROTOCOL_TOR },
+ { 0x51669B3F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5166F93D, 32, NDPI_PROTOCOL_TOR },
+ { 0x516A0C3C, 32, NDPI_PROTOCOL_TOR },
+ { 0x516B907F, 32, NDPI_PROTOCOL_TOR },
+ { 0x516D69B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x51853556, 32, NDPI_PROTOCOL_TOR },
+ { 0x518D6888, 32, NDPI_PROTOCOL_TOR },
+ { 0x519840EA, 32, NDPI_PROTOCOL_TOR },
+ { 0x519FC5DE, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A64037, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A98234, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A982D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A988CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A98D5C, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A98D5E, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A9957C, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A99864, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A999A7, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A99F52, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A9A86A, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A9AFA4, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A9B42B, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A9B92C, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A9D13A, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A9D20B, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A9D72F, 32, NDPI_PROTOCOL_TOR },
+ { 0x51A9FFEB, 32, NDPI_PROTOCOL_TOR },
+ { 0x51AA95F0, 32, NDPI_PROTOCOL_TOR },
+ { 0x51AAD96B, 32, NDPI_PROTOCOL_TOR },
+ { 0x51AAFFB8, 32, NDPI_PROTOCOL_TOR },
+ { 0x51AC174F, 32, NDPI_PROTOCOL_TOR },
+ { 0x51ADF051, 32, NDPI_PROTOCOL_TOR },
+ { 0x51AEE712, 32, NDPI_PROTOCOL_TOR },
+ { 0x51B0E436, 32, NDPI_PROTOCOL_TOR },
+ { 0x51B73F2E, 32, NDPI_PROTOCOL_TOR },
+ { 0x51B8EB2B, 32, NDPI_PROTOCOL_TOR },
+ { 0x51BAF377, 32, NDPI_PROTOCOL_TOR },
+ { 0x51BB1C09, 32, NDPI_PROTOCOL_TOR },
+ { 0x51BBD20D, 32, NDPI_PROTOCOL_TOR },
+ { 0x51BF7137, 32, NDPI_PROTOCOL_TOR },
+ { 0x51C93CED, 32, NDPI_PROTOCOL_TOR },
+ { 0x51CB9655, 32, NDPI_PROTOCOL_TOR },
+ { 0x51CD17DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x51D91056, 32, NDPI_PROTOCOL_TOR },
+ { 0x51D974C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x51D987C8, 32, NDPI_PROTOCOL_TOR },
+ { 0x51D99D5A, 32, NDPI_PROTOCOL_TOR },
+ { 0x51DA5B9A, 32, NDPI_PROTOCOL_TOR },
+ { 0x51DA6D6A, 32, NDPI_PROTOCOL_TOR },
+ { 0x51DA6DC3, 32, NDPI_PROTOCOL_TOR },
+ { 0x51DAEBA2, 32, NDPI_PROTOCOL_TOR },
+ { 0x51DB33CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x51DCA3CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x51DD555D, 32, NDPI_PROTOCOL_TOR },
+ { 0x51DFD766, 32, NDPI_PROTOCOL_TOR },
+ { 0x51E735A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x51E75573, 32, NDPI_PROTOCOL_TOR },
+ { 0x51E7A4A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x51E7E226, 32, NDPI_PROTOCOL_TOR },
+ { 0x51E9E3A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x51F285B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x51F6CAA9, 32, NDPI_PROTOCOL_TOR },
+ { 0x51F777FC, 32, NDPI_PROTOCOL_TOR },
+ { 0x52018046, 32, NDPI_PROTOCOL_TOR },
+ { 0x5206BA74, 32, NDPI_PROTOCOL_TOR },
+ { 0x5209EEF6, 32, NDPI_PROTOCOL_TOR },
+ { 0x520CAF74, 32, NDPI_PROTOCOL_TOR },
+ { 0x520DF0B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5213FC52, 32, NDPI_PROTOCOL_TOR },
+ { 0x52145714, 32, NDPI_PROTOCOL_TOR },
+ { 0x52173C4E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5219BB97, 32, NDPI_PROTOCOL_TOR },
+ { 0x521CC556, 32, NDPI_PROTOCOL_TOR },
+ { 0x521E7362, 32, NDPI_PROTOCOL_TOR },
+ { 0x521F29D7, 32, NDPI_PROTOCOL_TOR },
+ { 0x52239D60, 32, NDPI_PROTOCOL_TOR },
+ { 0x522BA860, 32, NDPI_PROTOCOL_TOR },
+ { 0x522DB96B, 32, NDPI_PROTOCOL_TOR },
+ { 0x522FE271, 32, NDPI_PROTOCOL_TOR },
+ { 0x52303D0C, 32, NDPI_PROTOCOL_TOR },
+ { 0x52343FD9, 32, NDPI_PROTOCOL_TOR },
+ { 0x52424777, 32, NDPI_PROTOCOL_TOR },
+ { 0x52449E7C, 32, NDPI_PROTOCOL_TOR },
+ { 0x52450ECF, 32, NDPI_PROTOCOL_TOR },
+ { 0x52453232, 32, NDPI_PROTOCOL_TOR },
+ { 0x52462723, 32, NDPI_PROTOCOL_TOR },
+ { 0x524805A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x52483D51, 32, NDPI_PROTOCOL_TOR },
+ { 0x5248765A, 32, NDPI_PROTOCOL_TOR },
+ { 0x52493309, 32, NDPI_PROTOCOL_TOR },
+ { 0x5249DF9D, 32, NDPI_PROTOCOL_TOR },
+ { 0x524A04F3, 32, NDPI_PROTOCOL_TOR },
+ { 0x524C4802, 32, NDPI_PROTOCOL_TOR },
+ { 0x52502163, 32, NDPI_PROTOCOL_TOR },
+ { 0x525088B9, 32, NDPI_PROTOCOL_TOR },
+ { 0x52532E63, 32, NDPI_PROTOCOL_TOR },
+ { 0x525EF2DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x525EFBCB, 32, NDPI_PROTOCOL_TOR },
+ { 0x525EFBCC, 32, NDPI_PROTOCOL_TOR },
+ { 0x525EFBE3, 32, NDPI_PROTOCOL_TOR },
+ { 0x525F42CB, 32, NDPI_PROTOCOL_TOR },
+ { 0x525F6B33, 32, NDPI_PROTOCOL_TOR },
+ { 0x525FEBF9, 32, NDPI_PROTOCOL_TOR },
+ { 0x52624850, 32, NDPI_PROTOCOL_TOR },
+ { 0x52668ED2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5270985F, 32, NDPI_PROTOCOL_TOR },
+ { 0x52736339, 32, NDPI_PROTOCOL_TOR },
+ { 0x52747803, 32, NDPI_PROTOCOL_TOR },
+ { 0x52761386, 32, NDPI_PROTOCOL_TOR },
+ { 0x5276F21E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5276F24F, 32, NDPI_PROTOCOL_TOR },
+ { 0x527E663F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5280FFFC, 32, NDPI_PROTOCOL_TOR },
+ { 0x52821A24, 32, NDPI_PROTOCOL_TOR },
+ { 0x5282285C, 32, NDPI_PROTOCOL_TOR },
+ { 0x52886403, 32, NDPI_PROTOCOL_TOR },
+ { 0x528B5EFC, 32, NDPI_PROTOCOL_TOR },
+ { 0x528B6271, 32, NDPI_PROTOCOL_TOR },
+ { 0x52921BD1, 32, NDPI_PROTOCOL_TOR },
+ { 0x529EEB26, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A1321E, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A13526, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A15B0D, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A16D47, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A1B614, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A1D257, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A1D4D1, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A1DF89, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A1EFB1, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A1FCA2, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A41BE4, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A50F97, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A58E4F, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A5C581, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A898B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A92496, 32, NDPI_PROTOCOL_TOR },
+ { 0x52A99B48, 32, NDPI_PROTOCOL_TOR },
+ { 0x52B1EEF0, 32, NDPI_PROTOCOL_TOR },
+ { 0x52B419BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x52B583A0, 32, NDPI_PROTOCOL_TOR },
+ { 0x52B6B40F, 32, NDPI_PROTOCOL_TOR },
+ { 0x52B70EC3, 32, NDPI_PROTOCOL_TOR },
+ { 0x52C0F11E, 32, NDPI_PROTOCOL_TOR },
+ { 0x52C409DF, 32, NDPI_PROTOCOL_TOR },
+ { 0x52C40E41, 32, NDPI_PROTOCOL_TOR },
+ { 0x52C5D42F, 32, NDPI_PROTOCOL_TOR },
+ { 0x52C79B59, 32, NDPI_PROTOCOL_TOR },
+ { 0x52C7C0A7, 32, NDPI_PROTOCOL_TOR },
+ { 0x52CBC340, 32, NDPI_PROTOCOL_TOR },
+ { 0x52D300C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x52D3138F, 32, NDPI_PROTOCOL_TOR },
+ { 0x52D3C9BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x52D3DF03, 32, NDPI_PROTOCOL_TOR },
+ { 0x52D8FE03, 32, NDPI_PROTOCOL_TOR },
+ { 0x52D91190, 32, NDPI_PROTOCOL_TOR },
+ { 0x52DB0959, 32, NDPI_PROTOCOL_TOR },
+ { 0x52DC5914, 32, NDPI_PROTOCOL_TOR },
+ { 0x52DD64C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x52DD6500, 32, NDPI_PROTOCOL_TOR },
+ { 0x52DD693D, 32, NDPI_PROTOCOL_TOR },
+ { 0x52DF08FC, 32, NDPI_PROTOCOL_TOR },
+ { 0x52DF0A44, 32, NDPI_PROTOCOL_TOR },
+ { 0x52DF0B22, 32, NDPI_PROTOCOL_TOR },
+ { 0x52DF179B, 32, NDPI_PROTOCOL_TOR },
+ { 0x52E08A09, 32, NDPI_PROTOCOL_TOR },
+ { 0x52E33F62, 32, NDPI_PROTOCOL_TOR },
+ { 0x52E4FC14, 32, NDPI_PROTOCOL_TOR },
+ { 0x52E53CF5, 32, NDPI_PROTOCOL_TOR },
+ { 0x52E58A1F, 32, NDPI_PROTOCOL_TOR },
+ { 0x52E97597, 32, NDPI_PROTOCOL_TOR },
+ { 0x52EA8DC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x52EBD32A, 32, NDPI_PROTOCOL_TOR },
+ { 0x52EC7EF6, 32, NDPI_PROTOCOL_TOR },
+ { 0x52EC89EB, 32, NDPI_PROTOCOL_TOR },
+ { 0x52EDD8E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x52EED0AD, 32, NDPI_PROTOCOL_TOR },
+ { 0x52EF14AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x52F1EC57, 32, NDPI_PROTOCOL_TOR },
+ { 0x52F298D3, 32, NDPI_PROTOCOL_TOR },
+ { 0x52F313CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x52F34F09, 32, NDPI_PROTOCOL_TOR },
+ { 0x52F4B127, 32, NDPI_PROTOCOL_TOR },
+ { 0x52F5C791, 32, NDPI_PROTOCOL_TOR },
+ { 0x52F76775, 32, NDPI_PROTOCOL_TOR },
+ { 0x52FA311C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5306C520, 32, NDPI_PROTOCOL_TOR },
+ { 0x5306EE3D, 32, NDPI_PROTOCOL_TOR },
+ { 0x531BFBEF, 32, NDPI_PROTOCOL_TOR },
+ { 0x53244725, 32, NDPI_PROTOCOL_TOR },
+ { 0x532CE6B0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5335F24A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5338EA93, 32, NDPI_PROTOCOL_TOR },
+ { 0x53451C51, 32, NDPI_PROTOCOL_TOR },
+ { 0x534C9E3E, 32, NDPI_PROTOCOL_TOR },
+ { 0x534E1005, 32, NDPI_PROTOCOL_TOR },
+ { 0x535269F0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5352C0E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5352F4DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x53530B96, 32, NDPI_PROTOCOL_TOR },
+ { 0x535352B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x53542E39, 32, NDPI_PROTOCOL_TOR },
+ { 0x53556653, 32, NDPI_PROTOCOL_TOR },
+ { 0x5355D16B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5355FC5B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5357C9F9, 32, NDPI_PROTOCOL_TOR },
+ { 0x53591FF9, 32, NDPI_PROTOCOL_TOR },
+ { 0x535D3740, 32, NDPI_PROTOCOL_TOR },
+ { 0x53638E4F, 32, NDPI_PROTOCOL_TOR },
+ { 0x53650553, 32, NDPI_PROTOCOL_TOR },
+ { 0x5365431F, 32, NDPI_PROTOCOL_TOR },
+ { 0x537560B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x53809409, 32, NDPI_PROTOCOL_TOR },
+ { 0x5380C8F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5382722D, 32, NDPI_PROTOCOL_TOR },
+ { 0x53857F91, 32, NDPI_PROTOCOL_TOR },
+ { 0x5386DFC1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5387F0D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x538C0BFC, 32, NDPI_PROTOCOL_TOR },
+ { 0x538FDBD4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5390693A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5391EDE0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5391F1E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5391F3D7, 32, NDPI_PROTOCOL_TOR },
+ { 0x539354E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x53957C88, 32, NDPI_PROTOCOL_TOR },
+ { 0x53957C88, 32, NDPI_PROTOCOL_TOR },
+ { 0x53957C89, 32, NDPI_PROTOCOL_TOR },
+ { 0x53957C89, 32, NDPI_PROTOCOL_TOR },
+ { 0x53957E1D, 32, NDPI_PROTOCOL_TOR },
+ { 0x53957F8C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5395F9A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5396023D, 32, NDPI_PROTOCOL_TOR },
+ { 0x53961097, 32, NDPI_PROTOCOL_TOR },
+ { 0x539610F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x53961184, 32, NDPI_PROTOCOL_TOR },
+ { 0x5396527A, 32, NDPI_PROTOCOL_TOR },
+ { 0x539C0058, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A05F63, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A19832, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A2026F, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A2BC64, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A2C060, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A2CD44, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A34DC3, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A3C9A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A59347, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A6EA5C, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A6EA6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A7B923, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A7B964, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A7E46B, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A8C8CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A91607, 32, NDPI_PROTOCOL_TOR },
+ { 0x53A92DE7, 32, NDPI_PROTOCOL_TOR },
+ { 0x53AB9437, 32, NDPI_PROTOCOL_TOR },
+ { 0x53ABBE6A, 32, NDPI_PROTOCOL_TOR },
+ { 0x53AEFA7D, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D19271, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D454DF, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D460B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D46270, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D46344, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D4637B, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D46612, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D4687C, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D46891, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D47185, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D47ED3, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D4A8BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x53D8F8E0, 32, NDPI_PROTOCOL_TOR },
+ { 0x53DE8DEB, 32, NDPI_PROTOCOL_TOR },
+ { 0x53E2EEA8, 32, NDPI_PROTOCOL_TOR },
+ { 0x53E334A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x53E45D4C, 32, NDPI_PROTOCOL_TOR },
+ { 0x53E71225, 32, NDPI_PROTOCOL_TOR },
+ { 0x53E941D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x53E98714, 32, NDPI_PROTOCOL_TOR },
+ { 0x53E9A8E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x53ECD04E, 32, NDPI_PROTOCOL_TOR },
+ { 0x53ED1577, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F03D90, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F042A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F077B0, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F65317, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F6A4BB, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F6D985, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F74E5A, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F80E85, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F88441, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F8A214, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F8B2D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x53F946BE, 32, NDPI_PROTOCOL_TOR },
+ { 0x53FA5511, 32, NDPI_PROTOCOL_TOR },
+ { 0x53FB40E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x53FB515D, 32, NDPI_PROTOCOL_TOR },
+ { 0x53FB5AA6, 32, NDPI_PROTOCOL_TOR },
+ { 0x53FB864C, 32, NDPI_PROTOCOL_TOR },
+ { 0x53FD36CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x53FDBBDA, 32, NDPI_PROTOCOL_TOR },
+ { 0x53FE5430, 32, NDPI_PROTOCOL_TOR },
+ { 0x53FF6645, 32, NDPI_PROTOCOL_TOR },
+ { 0x53FFCBAC, 32, NDPI_PROTOCOL_TOR },
+ { 0x540A6F0A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5413B234, 32, NDPI_PROTOCOL_TOR },
+ { 0x5413B3E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5413B450, 32, NDPI_PROTOCOL_TOR },
+ { 0x54162AF6, 32, NDPI_PROTOCOL_TOR },
+ { 0x54191CBA, 32, NDPI_PROTOCOL_TOR },
+ { 0x541B5EF7, 32, NDPI_PROTOCOL_TOR },
+ { 0x541EBB28, 32, NDPI_PROTOCOL_TOR },
+ { 0x541FC855, 32, NDPI_PROTOCOL_TOR },
+ { 0x54284D55, 32, NDPI_PROTOCOL_TOR },
+ { 0x542862BB, 32, NDPI_PROTOCOL_TOR },
+ { 0x54287046, 32, NDPI_PROTOCOL_TOR },
+ { 0x542AA5A2, 32, NDPI_PROTOCOL_TOR },
+ { 0x542D4C0A, 32, NDPI_PROTOCOL_TOR },
+ { 0x542D4C0B, 32, NDPI_PROTOCOL_TOR },
+ { 0x542D4C0C, 32, NDPI_PROTOCOL_TOR },
+ { 0x542D4C0D, 32, NDPI_PROTOCOL_TOR },
+ { 0x542E3EBA, 32, NDPI_PROTOCOL_TOR },
+ { 0x54303AC3, 32, NDPI_PROTOCOL_TOR },
+ { 0x54321453, 32, NDPI_PROTOCOL_TOR },
+ { 0x54380652, 32, NDPI_PROTOCOL_TOR },
+ { 0x54382C54, 32, NDPI_PROTOCOL_TOR },
+ { 0x5439BD00, 32, NDPI_PROTOCOL_TOR },
+ { 0x543BE658, 32, NDPI_PROTOCOL_TOR },
+ { 0x543C046D, 32, NDPI_PROTOCOL_TOR },
+ { 0x544815A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5448B905, 32, NDPI_PROTOCOL_TOR },
+ { 0x5448D5DD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5448DFC7, 32, NDPI_PROTOCOL_TOR },
+ { 0x544980C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x544A0BDE, 32, NDPI_PROTOCOL_TOR },
+ { 0x544A7D55, 32, NDPI_PROTOCOL_TOR },
+ { 0x544AACE8, 32, NDPI_PROTOCOL_TOR },
+ { 0x544B0C49, 32, NDPI_PROTOCOL_TOR },
+ { 0x5454D02F, 32, NDPI_PROTOCOL_TOR },
+ { 0x545C18D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x545C18D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x545C6C78, 32, NDPI_PROTOCOL_TOR },
+ { 0x54674A57, 32, NDPI_PROTOCOL_TOR },
+ { 0x5468A93B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5469DCFF, 32, NDPI_PROTOCOL_TOR },
+ { 0x546A4A9E, 32, NDPI_PROTOCOL_TOR },
+ { 0x546CCDB5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5470EE3A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5470EE3A, 32, NDPI_PROTOCOL_TOR },
+ { 0x54711102, 32, NDPI_PROTOCOL_TOR },
+ { 0x5471F5B1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5472F1DF, 32, NDPI_PROTOCOL_TOR },
+ { 0x54732E95, 32, NDPI_PROTOCOL_TOR },
+ { 0x5475164A, 32, NDPI_PROTOCOL_TOR },
+ { 0x54767531, 32, NDPI_PROTOCOL_TOR },
+ { 0x547688FC, 32, NDPI_PROTOCOL_TOR },
+ { 0x54779B30, 32, NDPI_PROTOCOL_TOR },
+ { 0x5477EDED, 32, NDPI_PROTOCOL_TOR },
+ { 0x547BB3B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x547D73EA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5481A36E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5481DC92, 32, NDPI_PROTOCOL_TOR },
+ { 0x548524F3, 32, NDPI_PROTOCOL_TOR },
+ { 0x548A010A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5493E1C8, 32, NDPI_PROTOCOL_TOR },
+ { 0x54947094, 32, NDPI_PROTOCOL_TOR },
+ { 0x5499DCA5, 32, NDPI_PROTOCOL_TOR },
+ { 0x549CFEEC, 32, NDPI_PROTOCOL_TOR },
+ { 0x549FE146, 32, NDPI_PROTOCOL_TOR },
+ { 0x549FEA53, 32, NDPI_PROTOCOL_TOR },
+ { 0x549FEA53, 32, NDPI_PROTOCOL_TOR },
+ { 0x54A202DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x54AD608B, 32, NDPI_PROTOCOL_TOR },
+ { 0x54AEB5BD, 32, NDPI_PROTOCOL_TOR },
+ { 0x54AFCF54, 32, NDPI_PROTOCOL_TOR },
+ { 0x54AFF159, 32, NDPI_PROTOCOL_TOR },
+ { 0x54B35824, 32, NDPI_PROTOCOL_TOR },
+ { 0x54B46D3C, 32, NDPI_PROTOCOL_TOR },
+ { 0x54B67B82, 32, NDPI_PROTOCOL_TOR },
+ { 0x54B75D03, 32, NDPI_PROTOCOL_TOR },
+ { 0x54B77113, 32, NDPI_PROTOCOL_TOR },
+ { 0x54B771CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x54B7F756, 32, NDPI_PROTOCOL_TOR },
+ { 0x54BA9896, 32, NDPI_PROTOCOL_TOR },
+ { 0x54BAD4B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x54C14BF3, 32, NDPI_PROTOCOL_TOR },
+ { 0x54C80821, 32, NDPI_PROTOCOL_TOR },
+ { 0x54C808AF, 32, NDPI_PROTOCOL_TOR },
+ { 0x54C808CF, 32, NDPI_PROTOCOL_TOR },
+ { 0x54C80AD1, 32, NDPI_PROTOCOL_TOR },
+ { 0x54C849EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x54C84DF3, 32, NDPI_PROTOCOL_TOR },
+ { 0x54C852A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x54C853D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x54C90487, 32, NDPI_PROTOCOL_TOR },
+ { 0x54C923CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x54CA3612, 32, NDPI_PROTOCOL_TOR },
+ { 0x54D08C30, 32, NDPI_PROTOCOL_TOR },
+ { 0x54D10F3F, 32, NDPI_PROTOCOL_TOR },
+ { 0x54D14924, 32, NDPI_PROTOCOL_TOR },
+ { 0x54D358E2, 32, NDPI_PROTOCOL_TOR },
+ { 0x54D7D347, 32, NDPI_PROTOCOL_TOR },
+ { 0x54DBAAE7, 32, NDPI_PROTOCOL_TOR },
+ { 0x54DBC1BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x54E26D6D, 32, NDPI_PROTOCOL_TOR },
+ { 0x54EA9B51, 32, NDPI_PROTOCOL_TOR },
+ { 0x54EA9B51, 32, NDPI_PROTOCOL_TOR },
+ { 0x54EA9B52, 32, NDPI_PROTOCOL_TOR },
+ { 0x54EA9B52, 32, NDPI_PROTOCOL_TOR },
+ { 0x54F270BE, 32, NDPI_PROTOCOL_TOR },
+ { 0x54F41F34, 32, NDPI_PROTOCOL_TOR },
+ { 0x54F520C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x54F52108, 32, NDPI_PROTOCOL_TOR },
+ { 0x54F8529C, 32, NDPI_PROTOCOL_TOR },
+ { 0x54F86B2C, 32, NDPI_PROTOCOL_TOR },
+ { 0x54F8805F, 32, NDPI_PROTOCOL_TOR },
+ { 0x54F9C0D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x54FA6A0D, 32, NDPI_PROTOCOL_TOR },
+ { 0x54FB736F, 32, NDPI_PROTOCOL_TOR },
+ { 0x54FB7CF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x550180C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5502F728, 32, NDPI_PROTOCOL_TOR },
+ { 0x55037656, 32, NDPI_PROTOCOL_TOR },
+ { 0x5504E453, 32, NDPI_PROTOCOL_TOR },
+ { 0x55082B53, 32, NDPI_PROTOCOL_TOR },
+ { 0x550AC409, 32, NDPI_PROTOCOL_TOR },
+ { 0x550AC40C, 32, NDPI_PROTOCOL_TOR },
+ { 0x550AC6EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x550AC8E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x550AC92F, 32, NDPI_PROTOCOL_TOR },
+ { 0x550ACA57, 32, NDPI_PROTOCOL_TOR },
+ { 0x550ACB47, 32, NDPI_PROTOCOL_TOR },
+ { 0x550ACBC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x550AD2C7, 32, NDPI_PROTOCOL_TOR },
+ { 0x550AD335, 32, NDPI_PROTOCOL_TOR },
+ { 0x550ADBA7, 32, NDPI_PROTOCOL_TOR },
+ { 0x550AED68, 32, NDPI_PROTOCOL_TOR },
+ { 0x550AF0FA, 32, NDPI_PROTOCOL_TOR },
+ { 0x550EF020, 32, NDPI_PROTOCOL_TOR },
+ { 0x550EF021, 32, NDPI_PROTOCOL_TOR },
+ { 0x550EF022, 32, NDPI_PROTOCOL_TOR },
+ { 0x550EF023, 32, NDPI_PROTOCOL_TOR },
+ { 0x550EF0BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x550EF0BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5511185F, 32, NDPI_PROTOCOL_TOR },
+ { 0x551184F5, 32, NDPI_PROTOCOL_TOR },
+ { 0x551184F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x55118DAE, 32, NDPI_PROTOCOL_TOR },
+ { 0x551194E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5511A451, 32, NDPI_PROTOCOL_TOR },
+ { 0x5511B149, 32, NDPI_PROTOCOL_TOR },
+ { 0x5511BE4D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5511BE4D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5511BE4F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5511BE4F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5511BE52, 32, NDPI_PROTOCOL_TOR },
+ { 0x5511BE53, 32, NDPI_PROTOCOL_TOR },
+ { 0x5511F893, 32, NDPI_PROTOCOL_TOR },
+ { 0x551590E2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5516679A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5517911A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5517F393, 32, NDPI_PROTOCOL_TOR },
+ { 0x5518D772, 32, NDPI_PROTOCOL_TOR },
+ { 0x5518D773, 32, NDPI_PROTOCOL_TOR },
+ { 0x5518D774, 32, NDPI_PROTOCOL_TOR },
+ { 0x5518D775, 32, NDPI_PROTOCOL_TOR },
+ { 0x5519090B, 32, NDPI_PROTOCOL_TOR },
+ { 0x55192D93, 32, NDPI_PROTOCOL_TOR },
+ { 0x55192F35, 32, NDPI_PROTOCOL_TOR },
+ { 0x55192FB4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5519305B, 32, NDPI_PROTOCOL_TOR },
+ { 0x55195F5B, 32, NDPI_PROTOCOL_TOR },
+ { 0x55195F95, 32, NDPI_PROTOCOL_TOR },
+ { 0x55196777, 32, NDPI_PROTOCOL_TOR },
+ { 0x5519829A, 32, NDPI_PROTOCOL_TOR },
+ { 0x55198A5D, 32, NDPI_PROTOCOL_TOR },
+ { 0x551995BF, 32, NDPI_PROTOCOL_TOR },
+ { 0x55199678, 32, NDPI_PROTOCOL_TOR },
+ { 0x5519994F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5519C155, 32, NDPI_PROTOCOL_TOR },
+ { 0x5519C444, 32, NDPI_PROTOCOL_TOR },
+ { 0x5519CB2A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5519D0C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5519D256, 32, NDPI_PROTOCOL_TOR },
+ { 0x551EA9E1, 32, NDPI_PROTOCOL_TOR },
+ { 0x551EF8C1, 32, NDPI_PROTOCOL_TOR },
+ { 0x551FBA5D, 32, NDPI_PROTOCOL_TOR },
+ { 0x551FBAD3, 32, NDPI_PROTOCOL_TOR },
+ { 0x551FBAFD, 32, NDPI_PROTOCOL_TOR },
+ { 0x55455D2E, 32, NDPI_PROTOCOL_TOR },
+ { 0x55496286, 32, NDPI_PROTOCOL_TOR },
+ { 0x55510502, 32, NDPI_PROTOCOL_TOR },
+ { 0x55513A3B, 32, NDPI_PROTOCOL_TOR },
+ { 0x55580BF3, 32, NDPI_PROTOCOL_TOR },
+ { 0x55581C88, 32, NDPI_PROTOCOL_TOR },
+ { 0x555D1259, 32, NDPI_PROTOCOL_TOR },
+ { 0x555DCBB6, 32, NDPI_PROTOCOL_TOR },
+ { 0x555DDACC, 32, NDPI_PROTOCOL_TOR },
+ { 0x55719152, 32, NDPI_PROTOCOL_TOR },
+ { 0x55728560, 32, NDPI_PROTOCOL_TOR },
+ { 0x55775204, 32, NDPI_PROTOCOL_TOR },
+ { 0x5577532C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5577538D, 32, NDPI_PROTOCOL_TOR },
+ { 0x557FC146, 32, NDPI_PROTOCOL_TOR },
+ { 0x558DC913, 32, NDPI_PROTOCOL_TOR },
+ { 0x558F5F32, 32, NDPI_PROTOCOL_TOR },
+ { 0x5596D244, 32, NDPI_PROTOCOL_TOR },
+ { 0x559F71E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x559FD180, 32, NDPI_PROTOCOL_TOR },
+ { 0x559FD19A, 32, NDPI_PROTOCOL_TOR },
+ { 0x559FD2EF, 32, NDPI_PROTOCOL_TOR },
+ { 0x559FD337, 32, NDPI_PROTOCOL_TOR },
+ { 0x55A452E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x55A8FF49, 32, NDPI_PROTOCOL_TOR },
+ { 0x55A8FFCA, 32, NDPI_PROTOCOL_TOR },
+ { 0x55AB1623, 32, NDPI_PROTOCOL_TOR },
+ { 0x55B0BCF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x55B0E108, 32, NDPI_PROTOCOL_TOR },
+ { 0x55B1669A, 32, NDPI_PROTOCOL_TOR },
+ { 0x55B2425E, 32, NDPI_PROTOCOL_TOR },
+ { 0x55B2CDC4, 32, NDPI_PROTOCOL_TOR },
+ { 0x55B2F435, 32, NDPI_PROTOCOL_TOR },
+ { 0x55B35A3B, 32, NDPI_PROTOCOL_TOR },
+ { 0x55B42652, 32, NDPI_PROTOCOL_TOR },
+ { 0x55B4F715, 32, NDPI_PROTOCOL_TOR },
+ { 0x55C35D4D, 32, NDPI_PROTOCOL_TOR },
+ { 0x55C51E77, 32, NDPI_PROTOCOL_TOR },
+ { 0x55C6B4EF, 32, NDPI_PROTOCOL_TOR },
+ { 0x55CAE1D1, 32, NDPI_PROTOCOL_TOR },
+ { 0x55CC0B35, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D2AB44, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D408E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D414C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D42B5E, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D45466, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D610D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D617BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D61DD5, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D62891, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D62CAC, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6349C, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D636FE, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D63E30, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D64469, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D646BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D64748, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6492C, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D650F9, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D665E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D66C81, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D673D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D67EF9, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D680C7, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D68211, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6909F, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D69242, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D692DD, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D69748, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D69C1C, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6C1EA, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6C3C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6CEDB, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6D38C, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6DC01, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6E066, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6E20F, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6ECCF, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D6F0DF, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D82298, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D84A33, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D85282, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D8EF08, 32, NDPI_PROTOCOL_TOR },
+ { 0x55D96A51, 32, NDPI_PROTOCOL_TOR },
+ { 0x55DA8B87, 32, NDPI_PROTOCOL_TOR },
+ { 0x55DE7764, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E00DE3, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E23FF3, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E23FF3, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E272EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E3B85B, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E4C664, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E52799, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E56B0F, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E5DB15, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E6FB1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E9156D, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E92788, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E9EC02, 32, NDPI_PROTOCOL_TOR },
+ { 0x55E9F05E, 32, NDPI_PROTOCOL_TOR },
+ { 0x55EA0282, 32, NDPI_PROTOCOL_TOR },
+ { 0x55F262DD, 32, NDPI_PROTOCOL_TOR },
+ { 0x55F2F9AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x55F3CFC9, 32, NDPI_PROTOCOL_TOR },
+ { 0x55F4D455, 32, NDPI_PROTOCOL_TOR },
+ { 0x55F5023D, 32, NDPI_PROTOCOL_TOR },
+ { 0x55FB5633, 32, NDPI_PROTOCOL_TOR },
+ { 0x5600D6BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x56017832, 32, NDPI_PROTOCOL_TOR },
+ { 0x5608E378, 32, NDPI_PROTOCOL_TOR },
+ { 0x560DA7C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x56137EFA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5616F4E3, 32, NDPI_PROTOCOL_TOR },
+ { 0x56187315, 32, NDPI_PROTOCOL_TOR },
+ { 0x561BF297, 32, NDPI_PROTOCOL_TOR },
+ { 0x562C1E07, 32, NDPI_PROTOCOL_TOR },
+ { 0x5634AE44, 32, NDPI_PROTOCOL_TOR },
+ { 0x5634AE44, 32, NDPI_PROTOCOL_TOR },
+ { 0x56387108, 32, NDPI_PROTOCOL_TOR },
+ { 0x5638E449, 32, NDPI_PROTOCOL_TOR },
+ { 0x563A3DBE, 32, NDPI_PROTOCOL_TOR },
+ { 0x563B1526, 32, NDPI_PROTOCOL_TOR },
+ { 0x563B15A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x563B15FB, 32, NDPI_PROTOCOL_TOR },
+ { 0x563B4616, 32, NDPI_PROTOCOL_TOR },
+ { 0x563B7752, 32, NDPI_PROTOCOL_TOR },
+ { 0x563B7753, 32, NDPI_PROTOCOL_TOR },
+ { 0x563E75AB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5649B3AA, 32, NDPI_PROTOCOL_TOR },
+ { 0x566187BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x56660386, 32, NDPI_PROTOCOL_TOR },
+ { 0x56679157, 32, NDPI_PROTOCOL_TOR },
+ { 0x5667972F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5667A17E, 32, NDPI_PROTOCOL_TOR },
+ { 0x566A2A77, 32, NDPI_PROTOCOL_TOR },
+ { 0x56791818, 32, NDPI_PROTOCOL_TOR },
+ { 0x567B34BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x567EB91B, 32, NDPI_PROTOCOL_TOR },
+ { 0x567FBE92, 32, NDPI_PROTOCOL_TOR },
+ { 0x5681D4E1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5681D4E1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5697D436, 32, NDPI_PROTOCOL_TOR },
+ { 0x569A0B2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x569BD0C5, 32, NDPI_PROTOCOL_TOR },
+ { 0x569F0B08, 32, NDPI_PROTOCOL_TOR },
+ { 0x56A1DCE0, 32, NDPI_PROTOCOL_TOR },
+ { 0x56A2550C, 32, NDPI_PROTOCOL_TOR },
+ { 0x56A27142, 32, NDPI_PROTOCOL_TOR },
+ { 0x56AE29E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x56AF9CFB, 32, NDPI_PROTOCOL_TOR },
+ { 0x56B00DD2, 32, NDPI_PROTOCOL_TOR },
+ { 0x56B03E45, 32, NDPI_PROTOCOL_TOR },
+ { 0x56B1719D, 32, NDPI_PROTOCOL_TOR },
+ { 0x56B3ED06, 32, NDPI_PROTOCOL_TOR },
+ { 0x56B43BD3, 32, NDPI_PROTOCOL_TOR },
+ { 0x56B7FF53, 32, NDPI_PROTOCOL_TOR },
+ { 0x56BABA50, 32, NDPI_PROTOCOL_TOR },
+ { 0x56BDAAC7, 32, NDPI_PROTOCOL_TOR },
+ { 0x56CDFD45, 32, NDPI_PROTOCOL_TOR },
+ { 0x56D0805A, 32, NDPI_PROTOCOL_TOR },
+ { 0x56D39F39, 32, NDPI_PROTOCOL_TOR },
+ { 0x56D9692B, 32, NDPI_PROTOCOL_TOR },
+ { 0x56EB2C1D, 32, NDPI_PROTOCOL_TOR },
+ { 0x57214983, 32, NDPI_PROTOCOL_TOR },
+ { 0x5740620E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5743BBE2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5743F359, 32, NDPI_PROTOCOL_TOR },
+ { 0x574823EF, 32, NDPI_PROTOCOL_TOR },
+ { 0x574849E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x574855D9, 32, NDPI_PROTOCOL_TOR },
+ { 0x574855D9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5748EFBB, 32, NDPI_PROTOCOL_TOR },
+ { 0x574933FE, 32, NDPI_PROTOCOL_TOR },
+ { 0x574A4C6A, 32, NDPI_PROTOCOL_TOR },
+ { 0x574E6298, 32, NDPI_PROTOCOL_TOR },
+ { 0x574F4F5E, 32, NDPI_PROTOCOL_TOR },
+ { 0x574FA117, 32, NDPI_PROTOCOL_TOR },
+ { 0x574FBE6A, 32, NDPI_PROTOCOL_TOR },
+ { 0x574FE6A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x57518B76, 32, NDPI_PROTOCOL_TOR },
+ { 0x5751943D, 32, NDPI_PROTOCOL_TOR },
+ { 0x575C404F, 32, NDPI_PROTOCOL_TOR },
+ { 0x575C7E3B, 32, NDPI_PROTOCOL_TOR },
+ { 0x57628430, 32, NDPI_PROTOCOL_TOR },
+ { 0x57629FE7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5762B23D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5762B905, 32, NDPI_PROTOCOL_TOR },
+ { 0x5762CE46, 32, NDPI_PROTOCOL_TOR },
+ { 0x5762FADE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5762FAF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x57660FD8, 32, NDPI_PROTOCOL_TOR },
+ { 0x576837CB, 32, NDPI_PROTOCOL_TOR },
+ { 0x57686A90, 32, NDPI_PROTOCOL_TOR },
+ { 0x57688562, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A0364, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A0E9F, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A10D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A1108, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A120D, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A14F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A154D, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A20BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A2567, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A2FBE, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A3528, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A3786, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A8C18, 32, NDPI_PROTOCOL_TOR },
+ { 0x576A945A, 32, NDPI_PROTOCOL_TOR },
+ { 0x576ABDEE, 32, NDPI_PROTOCOL_TOR },
+ { 0x576ABF5F, 32, NDPI_PROTOCOL_TOR },
+ { 0x576ABF9D, 32, NDPI_PROTOCOL_TOR },
+ { 0x576AD0EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x576AF976, 32, NDPI_PROTOCOL_TOR },
+ { 0x576AF9F8, 32, NDPI_PROTOCOL_TOR },
+ { 0x57706F89, 32, NDPI_PROTOCOL_TOR },
+ { 0x5772AA67, 32, NDPI_PROTOCOL_TOR },
+ { 0x5775DB84, 32, NDPI_PROTOCOL_TOR },
+ { 0x5775DB8C, 32, NDPI_PROTOCOL_TOR },
+ { 0x57765454, 32, NDPI_PROTOCOL_TOR },
+ { 0x577654B5, 32, NDPI_PROTOCOL_TOR },
+ { 0x577654F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x577658DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x57765B8C, 32, NDPI_PROTOCOL_TOR },
+ { 0x57765D7A, 32, NDPI_PROTOCOL_TOR },
+ { 0x57765EE7, 32, NDPI_PROTOCOL_TOR },
+ { 0x577670AD, 32, NDPI_PROTOCOL_TOR },
+ { 0x57767286, 32, NDPI_PROTOCOL_TOR },
+ { 0x577674E3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5776760C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5777BA76, 32, NDPI_PROTOCOL_TOR },
+ { 0x5779348B, 32, NDPI_PROTOCOL_TOR },
+ { 0x57793492, 32, NDPI_PROTOCOL_TOR },
+ { 0x57793497, 32, NDPI_PROTOCOL_TOR },
+ { 0x577FA5F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x578B21D9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5791BA0E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5792CEEC, 32, NDPI_PROTOCOL_TOR },
+ { 0x57954623, 32, NDPI_PROTOCOL_TOR },
+ { 0x57969A86, 32, NDPI_PROTOCOL_TOR },
+ { 0x5796CE37, 32, NDPI_PROTOCOL_TOR },
+ { 0x579737CB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5798EDA7, 32, NDPI_PROTOCOL_TOR },
+ { 0x579B0B3B, 32, NDPI_PROTOCOL_TOR },
+ { 0x579E1829, 32, NDPI_PROTOCOL_TOR },
+ { 0x579E8E9E, 32, NDPI_PROTOCOL_TOR },
+ { 0x579F41E5, 32, NDPI_PROTOCOL_TOR },
+ { 0x579FA892, 32, NDPI_PROTOCOL_TOR },
+ { 0x57A0D2C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x57A2CCAC, 32, NDPI_PROTOCOL_TOR },
+ { 0x57A3F603, 32, NDPI_PROTOCOL_TOR },
+ { 0x57A47E10, 32, NDPI_PROTOCOL_TOR },
+ { 0x57A62B46, 32, NDPI_PROTOCOL_TOR },
+ { 0x57A87901, 32, NDPI_PROTOCOL_TOR },
+ { 0x57A97C46, 32, NDPI_PROTOCOL_TOR },
+ { 0x57AC1458, 32, NDPI_PROTOCOL_TOR },
+ { 0x57AE61DF, 32, NDPI_PROTOCOL_TOR },
+ { 0x57AE69FB, 32, NDPI_PROTOCOL_TOR },
+ { 0x57AEE582, 32, NDPI_PROTOCOL_TOR },
+ { 0x57AEEF6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x57AEF49C, 32, NDPI_PROTOCOL_TOR },
+ { 0x57B2A7F3, 32, NDPI_PROTOCOL_TOR },
+ { 0x57B362F3, 32, NDPI_PROTOCOL_TOR },
+ { 0x57B38736, 32, NDPI_PROTOCOL_TOR },
+ { 0x57BA1D87, 32, NDPI_PROTOCOL_TOR },
+ { 0x57BC52C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x57BC6D89, 32, NDPI_PROTOCOL_TOR },
+ { 0x57BCC2CB, 32, NDPI_PROTOCOL_TOR },
+ { 0x57BD56C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x57C1B3EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x57C1D00E, 32, NDPI_PROTOCOL_TOR },
+ { 0x57C62255, 32, NDPI_PROTOCOL_TOR },
+ { 0x57CBC2D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x57CFD9D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x57D430C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x57D8ABB3, 32, NDPI_PROTOCOL_TOR },
+ { 0x57D93E0E, 32, NDPI_PROTOCOL_TOR },
+ { 0x57DAA8EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x57E0D2F3, 32, NDPI_PROTOCOL_TOR },
+ { 0x57E43BBD, 32, NDPI_PROTOCOL_TOR },
+ { 0x57E611F5, 32, NDPI_PROTOCOL_TOR },
+ { 0x57E6196D, 32, NDPI_PROTOCOL_TOR },
+ { 0x57E619AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x57E6335F, 32, NDPI_PROTOCOL_TOR },
+ { 0x57E64E6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x57E70AEB, 32, NDPI_PROTOCOL_TOR },
+ { 0x57E77410, 32, NDPI_PROTOCOL_TOR },
+ { 0x57EC1B9B, 32, NDPI_PROTOCOL_TOR },
+ { 0x57ECC3B9, 32, NDPI_PROTOCOL_TOR },
+ { 0x57ECC7A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x57ECD389, 32, NDPI_PROTOCOL_TOR },
+ { 0x57EFA26E, 32, NDPI_PROTOCOL_TOR },
+ { 0x57F38E21, 32, NDPI_PROTOCOL_TOR },
+ { 0x57F4FFDA, 32, NDPI_PROTOCOL_TOR },
+ { 0x57FB8C5D, 32, NDPI_PROTOCOL_TOR },
+ { 0x57FE635F, 32, NDPI_PROTOCOL_TOR },
+ { 0x580F9CD8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5811212D, 32, NDPI_PROTOCOL_TOR },
+ { 0x58401AEB, 32, NDPI_PROTOCOL_TOR },
+ { 0x58404EF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5840805B, 32, NDPI_PROTOCOL_TOR },
+ { 0x58412604, 32, NDPI_PROTOCOL_TOR },
+ { 0x5841F49C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5843639C, 32, NDPI_PROTOCOL_TOR },
+ { 0x58458580, 32, NDPI_PROTOCOL_TOR },
+ { 0x584862F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x584931A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x58493380, 32, NDPI_PROTOCOL_TOR },
+ { 0x584C5C8E, 32, NDPI_PROTOCOL_TOR },
+ { 0x584D2F56, 32, NDPI_PROTOCOL_TOR },
+ { 0x584DC1AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x584DCB92, 32, NDPI_PROTOCOL_TOR },
+ { 0x584E47B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5850B95D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5850D6BD, 32, NDPI_PROTOCOL_TOR },
+ { 0x58526C1A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5856D7D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x58574E68, 32, NDPI_PROTOCOL_TOR },
+ { 0x585BD594, 32, NDPI_PROTOCOL_TOR },
+ { 0x58614DFF, 32, NDPI_PROTOCOL_TOR },
+ { 0x58690051, 32, NDPI_PROTOCOL_TOR },
+ { 0x58719D6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x58726D58, 32, NDPI_PROTOCOL_TOR },
+ { 0x5872759B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5872E33E, 32, NDPI_PROTOCOL_TOR },
+ { 0x587E6C2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x587F6026, 32, NDPI_PROTOCOL_TOR },
+ { 0x588201AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x58823273, 32, NDPI_PROTOCOL_TOR },
+ { 0x58864FB5, 32, NDPI_PROTOCOL_TOR },
+ { 0x588678F8, 32, NDPI_PROTOCOL_TOR },
+ { 0x58869115, 32, NDPI_PROTOCOL_TOR },
+ { 0x58894FA1, 32, NDPI_PROTOCOL_TOR },
+ { 0x58959A20, 32, NDPI_PROTOCOL_TOR },
+ { 0x58982F2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5898FFF5, 32, NDPI_PROTOCOL_TOR },
+ { 0x58996247, 32, NDPI_PROTOCOL_TOR },
+ { 0x5899A4FF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5899AB6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5899B4A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x589F4697, 32, NDPI_PROTOCOL_TOR },
+ { 0x589F53F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x58A3E58B, 32, NDPI_PROTOCOL_TOR },
+ { 0x58A5F4A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x58A6C0B5, 32, NDPI_PROTOCOL_TOR },
+ { 0x58A8F257, 32, NDPI_PROTOCOL_TOR },
+ { 0x58B0042F, 32, NDPI_PROTOCOL_TOR },
+ { 0x58B0B407, 32, NDPI_PROTOCOL_TOR },
+ { 0x58B256CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x58B99B86, 32, NDPI_PROTOCOL_TOR },
+ { 0x58B9E31D, 32, NDPI_PROTOCOL_TOR },
+ { 0x58BA120C, 32, NDPI_PROTOCOL_TOR },
+ { 0x58BB785A, 32, NDPI_PROTOCOL_TOR },
+ { 0x58BBBAD8, 32, NDPI_PROTOCOL_TOR },
+ { 0x58BBE53B, 32, NDPI_PROTOCOL_TOR },
+ { 0x58BD8A61, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C3CF75, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C60910, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C61304, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C617B3, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6194C, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6195C, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C628A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C63352, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C63436, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C636D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6388C, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C64689, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C664E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C664E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C66D95, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C66DE5, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C66E98, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C66F77, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C67565, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6789B, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C67FE6, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C682D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C69A70, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6A363, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6A364, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6AF4C, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6C187, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6C259, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6C633, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6CFDE, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C6D6E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x58C8F312, 32, NDPI_PROTOCOL_TOR },
+ { 0x58CC71BD, 32, NDPI_PROTOCOL_TOR },
+ { 0x58D0CD8A, 32, NDPI_PROTOCOL_TOR },
+ { 0x58D90267, 32, NDPI_PROTOCOL_TOR },
+ { 0x58D92CAE, 32, NDPI_PROTOCOL_TOR },
+ { 0x58D94FCA, 32, NDPI_PROTOCOL_TOR },
+ { 0x58D98F35, 32, NDPI_PROTOCOL_TOR },
+ { 0x58D9ABE1, 32, NDPI_PROTOCOL_TOR },
+ { 0x58E44C31, 32, NDPI_PROTOCOL_TOR },
+ { 0x59004F17, 32, NDPI_PROTOCOL_TOR },
+ { 0x5900641C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5900878D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5900AD14, 32, NDPI_PROTOCOL_TOR },
+ { 0x5900E463, 32, NDPI_PROTOCOL_TOR },
+ { 0x5900E570, 32, NDPI_PROTOCOL_TOR },
+ { 0x5900EA67, 32, NDPI_PROTOCOL_TOR },
+ { 0x5900EC30, 32, NDPI_PROTOCOL_TOR },
+ { 0x5900F2EF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5900F7A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x59039E31, 32, NDPI_PROTOCOL_TOR },
+ { 0x590CF9FD, 32, NDPI_PROTOCOL_TOR },
+ { 0x590D5330, 32, NDPI_PROTOCOL_TOR },
+ { 0x590E57D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x590F649D, 32, NDPI_PROTOCOL_TOR },
+ { 0x590F6BF1, 32, NDPI_PROTOCOL_TOR },
+ { 0x590FC872, 32, NDPI_PROTOCOL_TOR },
+ { 0x59108C47, 32, NDPI_PROTOCOL_TOR },
+ { 0x5910B09E, 32, NDPI_PROTOCOL_TOR },
+ { 0x59122A65, 32, NDPI_PROTOCOL_TOR },
+ { 0x5912AC8B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5912AD29, 32, NDPI_PROTOCOL_TOR },
+ { 0x5912AE45, 32, NDPI_PROTOCOL_TOR },
+ { 0x5912AE56, 32, NDPI_PROTOCOL_TOR },
+ { 0x5912BE6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5916602F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5916613A, 32, NDPI_PROTOCOL_TOR },
+ { 0x591661C1, 32, NDPI_PROTOCOL_TOR },
+ { 0x591B0DD9, 32, NDPI_PROTOCOL_TOR },
+ { 0x591B4114, 32, NDPI_PROTOCOL_TOR },
+ { 0x591B5146, 32, NDPI_PROTOCOL_TOR },
+ { 0x591F3905, 32, NDPI_PROTOCOL_TOR },
+ { 0x5924EB42, 32, NDPI_PROTOCOL_TOR },
+ { 0x59284795, 32, NDPI_PROTOCOL_TOR },
+ { 0x592E64A2, 32, NDPI_PROTOCOL_TOR },
+ { 0x592E6524, 32, NDPI_PROTOCOL_TOR },
+ { 0x592E65B5, 32, NDPI_PROTOCOL_TOR },
+ { 0x59410727, 32, NDPI_PROTOCOL_TOR },
+ { 0x59412546, 32, NDPI_PROTOCOL_TOR },
+ { 0x59438C76, 32, NDPI_PROTOCOL_TOR },
+ { 0x59438C76, 32, NDPI_PROTOCOL_TOR },
+ { 0x5943B32A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5943FE26, 32, NDPI_PROTOCOL_TOR },
+ { 0x5944BDD0, 32, NDPI_PROTOCOL_TOR },
+ { 0x594669E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5949B1EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5949D520, 32, NDPI_PROTOCOL_TOR },
+ { 0x594A6CCE, 32, NDPI_PROTOCOL_TOR },
+ { 0x594D88AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5959FD25, 32, NDPI_PROTOCOL_TOR },
+ { 0x5962E64C, 32, NDPI_PROTOCOL_TOR },
+ { 0x59639B85, 32, NDPI_PROTOCOL_TOR },
+ { 0x59669393, 32, NDPI_PROTOCOL_TOR },
+ { 0x5967B502, 32, NDPI_PROTOCOL_TOR },
+ { 0x5967B832, 32, NDPI_PROTOCOL_TOR },
+ { 0x5969C582, 32, NDPI_PROTOCOL_TOR },
+ { 0x596AF415, 32, NDPI_PROTOCOL_TOR },
+ { 0x596C560B, 32, NDPI_PROTOCOL_TOR },
+ { 0x596C58E3, 32, NDPI_PROTOCOL_TOR },
+ { 0x596E9CF7, 32, NDPI_PROTOCOL_TOR },
+ { 0x596F1444, 32, NDPI_PROTOCOL_TOR },
+ { 0x5978777D, 32, NDPI_PROTOCOL_TOR },
+ { 0x59829E95, 32, NDPI_PROTOCOL_TOR },
+ { 0x59845CDA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5985A952, 32, NDPI_PROTOCOL_TOR },
+ { 0x598619DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x59869680, 32, NDPI_PROTOCOL_TOR },
+ { 0x59879056, 32, NDPI_PROTOCOL_TOR },
+ { 0x598C623C, 32, NDPI_PROTOCOL_TOR },
+ { 0x598E23D1, 32, NDPI_PROTOCOL_TOR },
+ { 0x59910E6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x599B990F, 32, NDPI_PROTOCOL_TOR },
+ { 0x599C3EBE, 32, NDPI_PROTOCOL_TOR },
+ { 0x599C5DDC, 32, NDPI_PROTOCOL_TOR },
+ { 0x599ED03F, 32, NDPI_PROTOCOL_TOR },
+ { 0x599F568B, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A0DE85, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A257B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A3ABFA, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A3B9BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A3D14F, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A3D14F, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A3DD97, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A3DD97, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A3E00A, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A3E0A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A3E0BB, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A3E31C, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A6EAF6, 32, NDPI_PROTOCOL_TOR },
+ { 0x59A9A5E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x59B08CBE, 32, NDPI_PROTOCOL_TOR },
+ { 0x59B08D09, 32, NDPI_PROTOCOL_TOR },
+ { 0x59B34E19, 32, NDPI_PROTOCOL_TOR },
+ { 0x59B37F7C, 32, NDPI_PROTOCOL_TOR },
+ { 0x59B3F11E, 32, NDPI_PROTOCOL_TOR },
+ { 0x59B891D7, 32, NDPI_PROTOCOL_TOR },
+ { 0x59BA8F86, 32, NDPI_PROTOCOL_TOR },
+ { 0x59BB8ED0, 32, NDPI_PROTOCOL_TOR },
+ { 0x59BC6DD2, 32, NDPI_PROTOCOL_TOR },
+ { 0x59BFC7F5, 32, NDPI_PROTOCOL_TOR },
+ { 0x59CF8537, 32, NDPI_PROTOCOL_TOR },
+ { 0x59CF8799, 32, NDPI_PROTOCOL_TOR },
+ { 0x59E31A37, 32, NDPI_PROTOCOL_TOR },
+ { 0x59E7763D, 32, NDPI_PROTOCOL_TOR },
+ { 0x59EA8D65, 32, NDPI_PROTOCOL_TOR },
+ { 0x59EA9DFE, 32, NDPI_PROTOCOL_TOR },
+ { 0x59EA9DFE, 32, NDPI_PROTOCOL_TOR },
+ { 0x59EE455D, 32, NDPI_PROTOCOL_TOR },
+ { 0x59EE4D04, 32, NDPI_PROTOCOL_TOR },
+ { 0x59EE4E6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x59EEAC6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x59EFDAB4, 32, NDPI_PROTOCOL_TOR },
+ { 0x59F8A679, 32, NDPI_PROTOCOL_TOR },
+ { 0x59F8AC10, 32, NDPI_PROTOCOL_TOR },
+ { 0x59F985A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x59FB968E, 32, NDPI_PROTOCOL_TOR },
+ { 0x59FC0125, 32, NDPI_PROTOCOL_TOR },
+ { 0x59FC028C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A09C850, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A0A8BC7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A0B5036, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A18B154, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A1B3C6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A1D82F0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A1D9B54, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A20BA49, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A28F78E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A3CABF0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A3FA178, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A914577, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A921D38, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A92B569, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A951B7A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A95517A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5A9B17DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AB0A48F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AB50D30, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AB88EE0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AB8A455, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AB8DE74, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AB8DE75, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AB8DE76, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AC04EC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5ADB84FD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AE14054, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AE150DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AE1558C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AE2B287, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AE4CA9F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5AE7989F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B025570, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B02F637, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B041823, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B05878B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B06757C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B09C013, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B0A081A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B0A45D7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B0A7B54, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B0CD9A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B0CEB4D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B0D634C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B0E755F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B0F4794, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B120251, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B129DE3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B152C3D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B21CED5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B225C74, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B25E831, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B265CAF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B2C7D98, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B2DE1A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B3249DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B334FF1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B336B45, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B33E422, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B33FBDE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B343F6F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B36DE01, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B3B5350, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B3D4574, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B3D52E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B3DF13E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B3EE54E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B406D9B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B406F83, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B40EADB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B41538E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B4160F6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B424E8B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B4254DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B42CC01, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B434C46, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B4D127A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B4F6E29, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B52ED7F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B605C06, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B60BC9F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B614084, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B6DF7AD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B711952, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B77D141, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B77E5A1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B790114, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B791043, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B7915E0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B791C40, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B794CCC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B794CCF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B795210, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B795219, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B79545C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B795582, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B7964C8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B7968A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B796AB2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B79734F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B797422, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B799255, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B799275, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B799341, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B799FC4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B79A5DF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B79A698, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B79A921, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B79B857, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B79C584, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B79CF22, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B79E9F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B7A640D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B7BC8A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B7BC8EB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B7EFFCD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B88A44D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B8A448F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B8A9B09, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B8C31D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B917635, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B927903, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B927A2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B95AD4F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B9A9932, 32, NDPI_PROTOCOL_TOR },
+ { 0x5B9BBD6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BB9C8DD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BB9E123, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BBA2710, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BBC7D80, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BBDB576, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BBE754D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BC2546A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BC25A27, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BC25A67, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BC7C54C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BC85544, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BCA2D9C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BCBD4EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BCDAD52, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BCE8E46, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD05448, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD26A1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD33ED4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD5082B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD50854, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD50859, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD50874, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD508EB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD508EB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD508EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD6A8F0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD6CB90, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BD6CBE9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BDBED13, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BDBED6E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BDBEDCF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BDBEDDA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BDBEDE5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BDBEDF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BDBEEDD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BDCA33E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BDD6F07, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BDEDA85, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE09509, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE09521, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE0952D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE09537, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE25911, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE434BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE49734, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE4B382, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE5141B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE6CCC6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE8D912, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BE97444, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BEA1630, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BEAE223, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BECEF87, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BECEF8C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BED34AA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BEDF43E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BEDF73E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BEE3C64, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BF0E5C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BFA7026, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BFA73B9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BFAF20A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5BFAF267, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C002464, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C0124D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C01DCB8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C07A833, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C0A3BD5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C0EC83C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C14074D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C14CB4C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C15F357, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C18851F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C18851F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C27F38B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C27F62D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C2869CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C32581A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C34249B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3C05EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3C05EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3F582D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3F582F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3F6E7C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3FAB2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3FABCF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3FAC96, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3FAE24, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3FAE46, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3FAE47, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C3FAF05, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C484CE3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C487B89, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C48FF4A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C4A357A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C4AE372, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C4B0EC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C4C7C06, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C4CC040, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C4D2D74, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C4DB1FE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C59AD55, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C5B7942, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C5B9C44, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C645773, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C647BD0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C68349B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C6893A0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C6977C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C6AE25D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C6C364C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C6C7829, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C6D0707, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C6F8E21, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C81AF11, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C83BD03, 32, NDPI_PROTOCOL_TOR },
+ { 0x5C89D859, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CC240C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CC328D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CC941B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CC94BCD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CCA214F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CCD15C1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CD13085, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CD3AE6A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CD6A588, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CD6ADD8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE016C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE0352, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE0466, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE04B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE0935, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE0946, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE1385, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE1482, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE1625, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE1671, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE19E1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE1A24, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE1A51, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE1C5A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE1C8F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE1CF3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE1D22, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE2211, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE2643, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE27B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE2DC7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE45BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDE9993, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDEA236, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDEACE5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDEB57B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDEC022, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CDECC60, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CE09A94, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CE0A09F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CE0B392, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CE10C0D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CE169B5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CE389A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CE4B19B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CE52412, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CE59221, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CE68415, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CE86216, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CED16DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CF31ED0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CF34569, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CF3BC10, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CF6147E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CF733A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CF79DB0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CF96241, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CF98F77, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CF9BCF6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CFC2031, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CFE18CB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CFE3951, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CFEB874, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CFFC311, 32, NDPI_PROTOCOL_TOR },
+ { 0x5CFFCF59, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D134D18, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D1F9BAF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D328CAA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D48650E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D515FF8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D5A73BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D5B3291, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D5CCC06, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D5E922B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D5FE37F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D5FE3F5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D5FE405, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D5FE433, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D5FE452, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D63058C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D64A738, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D6797A7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D688049, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D68A671, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D68D13D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D68D19E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D68D3A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D68D4FD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D73569C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D735EF3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D735EF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D73F102, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D760C01, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D7C3305, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D7E65DF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D804CF1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D81945A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D8456CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D84AC51, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D867771, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D8712F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D8BDD63, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D98C554, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D9C28A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5D9C4AEF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DA33850, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DA7F5B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DAE5A1E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DAE5D15, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DAE5D3F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DAF0C52, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DB49A5E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DB49C54, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DB49C63, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DB49D28, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DB49D9A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DB81566, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DB842E3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DB9654C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DB965AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DB96DBF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DBAC8D5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DBCA2EB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DBF0D22, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DC06F39, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DC0AAC8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DC0CA0C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DC16D99, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DC2904C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DC5E303, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DC5F098, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DC8C66B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DCBFB93, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DCD0C3A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DCF14E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DCF46AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DD3F085, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DD47CEB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DD71649, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DD740AF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DDA6C31, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DDB7692, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DDC0F3B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DDC7449, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DDCD36F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DDCEB0C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DDF509D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DDFCC89, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DE44D4E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DE62635, 32, NDPI_PROTOCOL_TOR },
+ { 0x5DE95360, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E05D57B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E09C10C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E104BE2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E137BC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E160545, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E168F9E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E16A01D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E170291, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E1712A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17141C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E1714BE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17194E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E171E35, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E172434, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E172599, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E1730BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17360C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17381F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E1746DE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E175892, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E176919, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17A2E3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17AB60, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17C221, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17C636, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17CCAF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17D0BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17D2A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17ECBB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E17FC1F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E188C4A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E22964B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E29C2EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E2D3BF0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E33CEA8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E46889C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E4BCF64, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E4F89B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E4FB906, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E6412A2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E6635B1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E663CAC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E67AF55, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E716902, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E71E6DD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E7CF603, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E7EB201, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E878697, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E88612A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E8DACF0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E8EF18A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E8EF1F1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E8EF21E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E8EF5CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E8EF5E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E9B5D2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E9ED927, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E9FCE6E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5E9FDCF2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EAE9EF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EB4D2CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EB4D8D9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EB4E868, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EB51414, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EB95202, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EBC1C88, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EBC39EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EBEE03A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EC6440D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EC66247, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EC66411, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EC73365, 32, NDPI_PROTOCOL_TOR },
+ { 0x5ED0E3DD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5ED2001C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5ED2BE2C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5ED3C0CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5ED61659, 32, NDPI_PROTOCOL_TOR },
+ { 0x5ED6179F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5ED9C67E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5ED9FE19, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EDA142C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EDC49D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EDD6472, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EDD9651, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EE19A57, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EE4560B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EE4DEC0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EE6CB1F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EE72228, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF23915, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF23926, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF239A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF239A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF239C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF239D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF23A46, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2C6A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2CC84, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2D178, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2D1F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2DE1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2DED7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2F342, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2F3A2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2F617, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2F618, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2FB70, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2FC29, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2FE51, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2FE51, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF2FEBF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EF72982, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EFD0E62, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EFD4CD2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EFE1877, 32, NDPI_PROTOCOL_TOR },
+ { 0x5EFE30C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F122587, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F17F611, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F182884, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F1931B0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F1BE179, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F1C5963, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F1EAD45, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F1F1B6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F1F2E02, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F25A84D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F40CB0E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F477EE6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F480939, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F4892AD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F491AE8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F4931BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F49EB59, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F4D914B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F4E3856, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F4F19B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F4F605F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F4F89F8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F500A2E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F52F5EA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F549049, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F5494AD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F54C634, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F54C806, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F54D17E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F550367, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F5503BF, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F5505D3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F55075A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F5508E2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F550A47, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F550E4F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F551449, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F55150E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F5517BD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F552522, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F55256F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F552673, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F55271C, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F552A24, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F553605, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F553C17, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F594A54, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F599862, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F5A0C37, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F5B83B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F61A0CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F69A188, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F6A1BC6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F6D7A90, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F7008D0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F71E203, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F72385D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F741FDB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F76808A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F802BA4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8137AD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F81CD53, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820959, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820959, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820979, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8209BE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820A0F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820B05, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820B0F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820B2A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820B2E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820B93, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820BA2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820BAA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820BD6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820C2F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820C77, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820F60, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820F61, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820FFB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820FFC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820FFD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F820FFE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8387B3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F83EA02, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8429AB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F843460, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F851927, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F872D77, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8BE024, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8C2AB7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8D5392, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8DE895, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8EA13F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8EAD12, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8FACD4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8FACD6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8FACF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8FC191, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F8FE1C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F91E0D0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F9A1849, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F9A58FC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F9A6A86, 32, NDPI_PROTOCOL_TOR },
+ { 0x5F9D0C83, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FA01056, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FA9BC67, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FAAB5D0, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FACEC76, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FAEE547, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD3079E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD31B0A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD349ED, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD3629F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD38811, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD38A1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD3A923, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD3CD97, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD3D865, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD3DE93, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD3E1A7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD3E408, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD3E59E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD3E781, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD3F153, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD701B5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72C66, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72C69, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72C6E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72C6F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72C7A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72C91, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72CBA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72CBB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72CBD, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72CC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72CE8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72CF9, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72D2F, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72D41, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72D44, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72D80, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72D8E, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72DBC, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72DC3, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72DC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72E24, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72E54, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72E5A, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72E67, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72E7B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72E96, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72EF4, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72F75, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72F80, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72F8B, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72F96, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72FB1, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72FBB, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72FC7, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72FCE, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72FD8, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FD72FF2, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FDC69CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FDC822D, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FDE9C03, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FDE9C04, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FDEE336, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FDFD887, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FEEE099, 32, NDPI_PROTOCOL_TOR },
+ { 0x5FEFE676, 32, NDPI_PROTOCOL_TOR },
+ { 0x601390C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x601CBD5E, 32, NDPI_PROTOCOL_TOR },
+ { 0x601F430F, 32, NDPI_PROTOCOL_TOR },
+ { 0x60210687, 32, NDPI_PROTOCOL_TOR },
+ { 0x60238283, 32, NDPI_PROTOCOL_TOR },
+ { 0x60253C3F, 32, NDPI_PROTOCOL_TOR },
+ { 0x6028292D, 32, NDPI_PROTOCOL_TOR },
+ { 0x60290DA2, 32, NDPI_PROTOCOL_TOR },
+ { 0x6029718C, 32, NDPI_PROTOCOL_TOR },
+ { 0x602A211B, 32, NDPI_PROTOCOL_TOR },
+ { 0x602CBD64, 32, NDPI_PROTOCOL_TOR },
+ { 0x602CBD65, 32, NDPI_PROTOCOL_TOR },
+ { 0x602CBD66, 32, NDPI_PROTOCOL_TOR },
+ { 0x602F411A, 32, NDPI_PROTOCOL_TOR },
+ { 0x602FE214, 32, NDPI_PROTOCOL_TOR },
+ { 0x602FE215, 32, NDPI_PROTOCOL_TOR },
+ { 0x602FE216, 32, NDPI_PROTOCOL_TOR },
+ { 0x602FEC7E, 32, NDPI_PROTOCOL_TOR },
+ { 0x60303837, 32, NDPI_PROTOCOL_TOR },
+ { 0x60341169, 32, NDPI_PROTOCOL_TOR },
+ { 0x60362A0F, 32, NDPI_PROTOCOL_TOR },
+ { 0x607E6009, 32, NDPI_PROTOCOL_TOR },
+ { 0x607E605A, 32, NDPI_PROTOCOL_TOR },
+ { 0x607E6688, 32, NDPI_PROTOCOL_TOR },
+ { 0x607E69DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x607E6E3C, 32, NDPI_PROTOCOL_TOR },
+ { 0x607E6E3C, 32, NDPI_PROTOCOL_TOR },
+ { 0x607E76E3, 32, NDPI_PROTOCOL_TOR },
+ { 0x607E7AA6, 32, NDPI_PROTOCOL_TOR },
+ { 0x607E7F58, 32, NDPI_PROTOCOL_TOR },
+ { 0x60E26D05, 32, NDPI_PROTOCOL_TOR },
+ { 0x60E29C48, 32, NDPI_PROTOCOL_TOR },
+ { 0x60E53297, 32, NDPI_PROTOCOL_TOR },
+ { 0x60E6398D, 32, NDPI_PROTOCOL_TOR },
+ { 0x60E85742, 32, NDPI_PROTOCOL_TOR },
+ { 0x60E932CF, 32, NDPI_PROTOCOL_TOR },
+ { 0x60EE056F, 32, NDPI_PROTOCOL_TOR },
+ { 0x60EE23B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x60F19A42, 32, NDPI_PROTOCOL_TOR },
+ { 0x60FA5604, 32, NDPI_PROTOCOL_TOR },
+ { 0x60FD4E6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x60FF47C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x6155B286, 32, NDPI_PROTOCOL_TOR },
+ { 0x61570E0F, 32, NDPI_PROTOCOL_TOR },
+ { 0x61573D40, 32, NDPI_PROTOCOL_TOR },
+ { 0x615D1FB9, 32, NDPI_PROTOCOL_TOR },
+ { 0x615F20B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x61664AC2, 32, NDPI_PROTOCOL_TOR },
+ { 0x61664F0E, 32, NDPI_PROTOCOL_TOR },
+ { 0x616B8418, 32, NDPI_PROTOCOL_TOR },
+ { 0x616B867F, 32, NDPI_PROTOCOL_TOR },
+ { 0x616B8A44, 32, NDPI_PROTOCOL_TOR },
+ { 0x616B8B1C, 32, NDPI_PROTOCOL_TOR },
+ { 0x616B8B6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x616B8E85, 32, NDPI_PROTOCOL_TOR },
+ { 0x616B8EDA, 32, NDPI_PROTOCOL_TOR },
+ { 0x616B8EEA, 32, NDPI_PROTOCOL_TOR },
+ { 0x61761E24, 32, NDPI_PROTOCOL_TOR },
+ { 0x62181813, 32, NDPI_PROTOCOL_TOR },
+ { 0x62185496, 32, NDPI_PROTOCOL_TOR },
+ { 0x621CA618, 32, NDPI_PROTOCOL_TOR },
+ { 0x621CF5EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x6241C4D2, 32, NDPI_PROTOCOL_TOR },
+ { 0x6245AA0A, 32, NDPI_PROTOCOL_TOR },
+ { 0x626538B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x626D3882, 32, NDPI_PROTOCOL_TOR },
+ { 0x626D7511, 32, NDPI_PROTOCOL_TOR },
+ { 0x62726199, 32, NDPI_PROTOCOL_TOR },
+ { 0x6274DF81, 32, NDPI_PROTOCOL_TOR },
+ { 0x627C74C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x628E2F36, 32, NDPI_PROTOCOL_TOR },
+ { 0x6296DFDD, 32, NDPI_PROTOCOL_TOR },
+ { 0x629B1EED, 32, NDPI_PROTOCOL_TOR },
+ { 0x629D1940, 32, NDPI_PROTOCOL_TOR },
+ { 0x629D41CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x62B436C1, 32, NDPI_PROTOCOL_TOR },
+ { 0x62B790F7, 32, NDPI_PROTOCOL_TOR },
+ { 0x62C1C54A, 32, NDPI_PROTOCOL_TOR },
+ { 0x62C774D0, 32, NDPI_PROTOCOL_TOR },
+ { 0x62C925BF, 32, NDPI_PROTOCOL_TOR },
+ { 0x62C99217, 32, NDPI_PROTOCOL_TOR },
+ { 0x62CEB470, 32, NDPI_PROTOCOL_TOR },
+ { 0x62CEB64E, 32, NDPI_PROTOCOL_TOR },
+ { 0x62D2A4C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x62D6F355, 32, NDPI_PROTOCOL_TOR },
+ { 0x62D8A86C, 32, NDPI_PROTOCOL_TOR },
+ { 0x62D99D4C, 32, NDPI_PROTOCOL_TOR },
+ { 0x62DA3282, 32, NDPI_PROTOCOL_TOR },
+ { 0x62DA372F, 32, NDPI_PROTOCOL_TOR },
+ { 0x62E0DAEE, 32, NDPI_PROTOCOL_TOR },
+ { 0x62E7895E, 32, NDPI_PROTOCOL_TOR },
+ { 0x62E818A7, 32, NDPI_PROTOCOL_TOR },
+ { 0x62EC4BEC, 32, NDPI_PROTOCOL_TOR },
+ { 0x62F5A7CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x62F62CE0, 32, NDPI_PROTOCOL_TOR },
+ { 0x62F81DE9, 32, NDPI_PROTOCOL_TOR },
+ { 0x62FC8D6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x62FFC9AB, 32, NDPI_PROTOCOL_TOR },
+ { 0x630615BE, 32, NDPI_PROTOCOL_TOR },
+ { 0x633F1919, 32, NDPI_PROTOCOL_TOR },
+ { 0x635AD476, 32, NDPI_PROTOCOL_TOR },
+ { 0x635F8924, 32, NDPI_PROTOCOL_TOR },
+ { 0x6363E834, 32, NDPI_PROTOCOL_TOR },
+ { 0x6366B2AD, 32, NDPI_PROTOCOL_TOR },
+ { 0x63E1049C, 32, NDPI_PROTOCOL_TOR },
+ { 0x63E4AB0B, 32, NDPI_PROTOCOL_TOR },
+ { 0x63EA2BA0, 32, NDPI_PROTOCOL_TOR },
+ { 0x6424B8E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x6425681C, 32, NDPI_PROTOCOL_TOR },
+ { 0x65339B42, 32, NDPI_PROTOCOL_TOR },
+ { 0x6562AEE2, 32, NDPI_PROTOCOL_TOR },
+ { 0x65634096, 32, NDPI_PROTOCOL_TOR },
+ { 0x658CD912, 32, NDPI_PROTOCOL_TOR },
+ { 0x658EC26D, 32, NDPI_PROTOCOL_TOR },
+ { 0x65B090B8, 32, NDPI_PROTOCOL_TOR },
+ { 0x65BB0480, 32, NDPI_PROTOCOL_TOR },
+ { 0x6706D5C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x670AC532, 32, NDPI_PROTOCOL_TOR },
+ { 0x670AC764, 32, NDPI_PROTOCOL_TOR },
+ { 0x67101A47, 32, NDPI_PROTOCOL_TOR },
+ { 0x67193810, 32, NDPI_PROTOCOL_TOR },
+ { 0x67298435, 32, NDPI_PROTOCOL_TOR },
+ { 0x67F05B07, 32, NDPI_PROTOCOL_TOR },
+ { 0x67FAB895, 32, NDPI_PROTOCOL_TOR },
+ { 0x68091CA1, 32, NDPI_PROTOCOL_TOR },
+ { 0x6820195D, 32, NDPI_PROTOCOL_TOR },
+ { 0x68218AAE, 32, NDPI_PROTOCOL_TOR },
+ { 0x6828018F, 32, NDPI_PROTOCOL_TOR },
+ { 0x68288AA6, 32, NDPI_PROTOCOL_TOR },
+ { 0x6829028B, 32, NDPI_PROTOCOL_TOR },
+ { 0x68311642, 32, NDPI_PROTOCOL_TOR },
+ { 0x68804E6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x68804E6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x68804E6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x68804E6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6880AB3E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6880E1CB, 32, NDPI_PROTOCOL_TOR },
+ { 0x68821999, 32, NDPI_PROTOCOL_TOR },
+ { 0x68830974, 32, NDPI_PROTOCOL_TOR },
+ { 0x68830C8B, 32, NDPI_PROTOCOL_TOR },
+ { 0x68830EAF, 32, NDPI_PROTOCOL_TOR },
+ { 0x68831377, 32, NDPI_PROTOCOL_TOR },
+ { 0x68831C36, 32, NDPI_PROTOCOL_TOR },
+ { 0x68831E06, 32, NDPI_PROTOCOL_TOR },
+ { 0x688322AA, 32, NDPI_PROTOCOL_TOR },
+ { 0x688322AC, 32, NDPI_PROTOCOL_TOR },
+ { 0x68832D66, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883335D, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883378D, 32, NDPI_PROTOCOL_TOR },
+ { 0x688337B8, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883387F, 32, NDPI_PROTOCOL_TOR },
+ { 0x68833A42, 32, NDPI_PROTOCOL_TOR },
+ { 0x68833F50, 32, NDPI_PROTOCOL_TOR },
+ { 0x68833F8F, 32, NDPI_PROTOCOL_TOR },
+ { 0x688341E1, 32, NDPI_PROTOCOL_TOR },
+ { 0x688342C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x68834956, 32, NDPI_PROTOCOL_TOR },
+ { 0x68834ACF, 32, NDPI_PROTOCOL_TOR },
+ { 0x68835F18, 32, NDPI_PROTOCOL_TOR },
+ { 0x68836C07, 32, NDPI_PROTOCOL_TOR },
+ { 0x68836ED5, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883722B, 32, NDPI_PROTOCOL_TOR },
+ { 0x68837248, 32, NDPI_PROTOCOL_TOR },
+ { 0x688375E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x68837B10, 32, NDPI_PROTOCOL_TOR },
+ { 0x68837D54, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883811E, 32, NDPI_PROTOCOL_TOR },
+ { 0x68838182, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883862F, 32, NDPI_PROTOCOL_TOR },
+ { 0x68839A74, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883A6F3, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883AC2E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883B5AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883CC93, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883CE17, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883D523, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883E7F1, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883F0A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x6883F537, 32, NDPI_PROTOCOL_TOR },
+ { 0x689C39C7, 32, NDPI_PROTOCOL_TOR },
+ { 0x689C6F36, 32, NDPI_PROTOCOL_TOR },
+ { 0x689CE01C, 32, NDPI_PROTOCOL_TOR },
+ { 0x689CE053, 32, NDPI_PROTOCOL_TOR },
+ { 0x689CEE74, 32, NDPI_PROTOCOL_TOR },
+ { 0x689CFD47, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A2167C, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A762FD, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A76304, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A7630C, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A76458, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A764A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A766F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A76734, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A7695C, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A76A2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A76B8E, 32, NDPI_PROTOCOL_TOR },
+ { 0x68A823A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x68AE61BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x68C81056, 32, NDPI_PROTOCOL_TOR },
+ { 0x68C81056, 32, NDPI_PROTOCOL_TOR },
+ { 0x68C812B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x68C812B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x68C8148E, 32, NDPI_PROTOCOL_TOR },
+ { 0x68C81841, 32, NDPI_PROTOCOL_TOR },
+ { 0x68CEC114, 32, NDPI_PROTOCOL_TOR },
+ { 0x68CF802A, 32, NDPI_PROTOCOL_TOR },
+ { 0x68CF846D, 32, NDPI_PROTOCOL_TOR },
+ { 0x68CF84C9, 32, NDPI_PROTOCOL_TOR },
+ { 0x68CF92C8, 32, NDPI_PROTOCOL_TOR },
+ { 0x68CF940C, 32, NDPI_PROTOCOL_TOR },
+ { 0x68DBB8A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x68DD4C83, 32, NDPI_PROTOCOL_TOR },
+ { 0x68E0AF68, 32, NDPI_PROTOCOL_TOR },
+ { 0x68E80163, 32, NDPI_PROTOCOL_TOR },
+ { 0x68E80321, 32, NDPI_PROTOCOL_TOR },
+ { 0x68E80323, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EADC47, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC0067, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC0658, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC084A, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC1197, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC191C, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC239C, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC26E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC27DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC2CD2, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC323E, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC3672, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC5353, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC5629, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC575A, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC5DE1, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC6452, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC6E0D, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC8E5D, 32, NDPI_PROTOCOL_TOR },
+ { 0x68EC95F9, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ECAE0E, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ECB3DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ECB3F0, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ECB847, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ECD5C1, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ECE860, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ECFDEC, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED8054, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED8134, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED8134, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED814E, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED818E, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED818E, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED834B, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED834B, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED836B, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED8D6D, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED8DC1, 32, NDPI_PROTOCOL_TOR },
+ { 0x68ED98C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x68F44B5B, 32, NDPI_PROTOCOL_TOR },
+ { 0x68F4DFCC, 32, NDPI_PROTOCOL_TOR },
+ { 0x68F5274A, 32, NDPI_PROTOCOL_TOR },
+ { 0x68FBD208, 32, NDPI_PROTOCOL_TOR },
+ { 0x699551A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x699AB5D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x69EDDE72, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB91C19, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB91C71, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB91C71, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB91CAA, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB91D5D, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB91EEE, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB91F81, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB91F81, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB92697, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB9273A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB9273A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB930D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x6AB930D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA109A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA1228, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA12F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA1892, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA18FE, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA1C21, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA1D04, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA1D2A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA1E34, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA7229, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA7541, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABA7541, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB23EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB24B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB259E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB259E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB26C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB2974, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB2B6E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB2D9C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB2F11, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB3444, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB37EF, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB5EFE, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB5EFE, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB60FA, 32, NDPI_PROTOCOL_TOR },
+ { 0x6ABB6773, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B021E0D, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B060491, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B14B34B, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B812529, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B9614F1, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B961BC8, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B961F6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B962336, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B96268A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B9635B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B96AA3A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B988F3E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B9B748F, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B9EFF15, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B9EFF15, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B9EFF16, 32, NDPI_PROTOCOL_TOR },
+ { 0x6B9EFF16, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BA150C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BA151BB, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BA151D0, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BA154B9, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BA19E11, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BA1B357, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA2047, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA3234, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA330E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA41C5, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA4E2A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA4F93, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA5C89, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA5CED, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA5D0D, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA5D20, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA5D75, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA60EB, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA676F, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA6CDE, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA72CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA78D6, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA8F75, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA9607, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA9950, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAA9ED4, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAABC9B, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAAC021, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAAC442, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAACC21, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAAE84B, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAAF57F, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAAF6CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAAF721, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BAAFBB6, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BB5A60B, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BB5AE16, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BB613F9, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BB68374, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BB68388, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BB683CF, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BB683D3, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BBF2C9A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BBF2ECC, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BBF3FB8, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BBF6245, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BBF6CCB, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BBF7EB8, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BC4142E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6BCB324B, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C009C8F, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C00C1EF, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C00CFF0, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C00DF0E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C071024, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C0724B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C0CB2EB, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C0E531F, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C137138, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C1D6B46, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C1D75F5, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C1E388E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C1E3970, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C1F2805, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C1FDC6E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C203114, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C2D5D5E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C309E93, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C32EBB6, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C33B8DC, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3504D1, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C35822A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C36A4AF, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C38BD9D, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3A90E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3B02D0, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3B0BE1, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DA16F, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DA1E3, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DA457, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DA539, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DA646, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DA6C7, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DA7F0, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DA82C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DB16E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DB1C3, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DB22E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DB233, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DB2D8, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DB3D8, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DB691, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DB6EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DB91A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DB988, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DBCB4, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DC563, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DC6A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DC6CF, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DC7B0, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DC7CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DD0AB, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DD150, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DD27B, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DD35E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DD466, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DF237, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DFB84, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C3DFCED, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C45A572, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C59AF93, 32, NDPI_PROTOCOL_TOR },
+ { 0x6C6FAA05, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CA6A1BA, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CA6A89E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CA6A8A7, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CA8033C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CAA8A76, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CB49FFC, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CB9E23E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CCC2E0E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CD0E579, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CD20668, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CF0B68C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CF72296, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CF7F4CC, 32, NDPI_PROTOCOL_TOR },
+ { 0x6CF857F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D00AA2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D00DC98, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D163429, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D44AE3C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D44BF85, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D454311, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4565A5, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D49345A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4A0058, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4A9795, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4AC247, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4AC27C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4AC3BE, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4AC865, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4ACC77, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4ACE0C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4ACE15, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4BB84D, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D4BBD44, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D5A17DD, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D5AFAB0, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D5B68E8, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D5B6C94, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D5B7013, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D5B7DC3, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D5E6002, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D5FD279, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D5FD442, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D646686, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D64FC83, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D682CD1, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D696DA2, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D6A38E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D6B239A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D6CDE14, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D6F9E13, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D78943C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D78AD30, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D78B4F5, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D78B611, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D824D50, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D825345, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D984A8C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6D9BDAB1, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA1226E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA3E9A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA3EA02, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA3EA04, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA3EA05, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA3EA07, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA3EA08, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA3EA09, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA3EBF6, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA3EBFC, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA4ECE7, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA78802, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA9001D, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA917CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA921A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DA92DE2, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DAD3BB4, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DB6971F, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DBD0643, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DBD834C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DBD8F96, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DBDB40F, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DBE4755, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DBE6DE4, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC074AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC0CFE9, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC16B54, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC18057, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC2D95A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC41236, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC50D36, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC53F2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC95A10, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC9830B, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC99A8D, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DC9C2DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DCB6C42, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DCEBA61, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DD412CD, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DD414AD, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DDA7515, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DE4963C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DE6E02A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DE6EC59, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DE6EC5F, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DE6ECAD, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DE97B2C, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DE97FE9, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DEB32A3, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DEC568A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DEF301A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DEF3098, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DEF30AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DEF3103, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DEF3C35, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DF150E7, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DF63848, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DFB8A1A, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DFF2ED7, 32, NDPI_PROTOCOL_TOR },
+ { 0x6DFF69AD, 32, NDPI_PROTOCOL_TOR },
+ { 0x6E42E657, 32, NDPI_PROTOCOL_TOR },
+ { 0x6E42E657, 32, NDPI_PROTOCOL_TOR },
+ { 0x6E5D17AA, 32, NDPI_PROTOCOL_TOR },
+ { 0x6EAE2B88, 32, NDPI_PROTOCOL_TOR },
+ { 0x6EAFF9CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x6F458D7B, 32, NDPI_PROTOCOL_TOR },
+ { 0x6F45A280, 32, NDPI_PROTOCOL_TOR },
+ { 0x6F59A849, 32, NDPI_PROTOCOL_TOR },
+ { 0x6F677B5E, 32, NDPI_PROTOCOL_TOR },
+ { 0x6F67ACCD, 32, NDPI_PROTOCOL_TOR },
+ { 0x6F76B165, 32, NDPI_PROTOCOL_TOR },
+ { 0x6FF8167F, 32, NDPI_PROTOCOL_TOR },
+ { 0x70769CA3, 32, NDPI_PROTOCOL_TOR },
+ { 0x7078955A, 32, NDPI_PROTOCOL_TOR },
+ { 0x707899D7, 32, NDPI_PROTOCOL_TOR },
+ { 0x70CDFABD, 32, NDPI_PROTOCOL_TOR },
+ { 0x71A37584, 32, NDPI_PROTOCOL_TOR },
+ { 0x7225CECB, 32, NDPI_PROTOCOL_TOR },
+ { 0x724DE973, 32, NDPI_PROTOCOL_TOR },
+ { 0x72860615, 32, NDPI_PROTOCOL_TOR },
+ { 0x72BD691E, 32, NDPI_PROTOCOL_TOR },
+ { 0x7342A640, 32, NDPI_PROTOCOL_TOR },
+ { 0x7346F182, 32, NDPI_PROTOCOL_TOR },
+ { 0x73BB4A5B, 32, NDPI_PROTOCOL_TOR },
+ { 0x73BB9A6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x75124BEB, 32, NDPI_PROTOCOL_TOR },
+ { 0x751263F9, 32, NDPI_PROTOCOL_TOR },
+ { 0x760C8552, 32, NDPI_PROTOCOL_TOR },
+ { 0x768D03A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x76AC0D55, 32, NDPI_PROTOCOL_TOR },
+ { 0x76C1C25F, 32, NDPI_PROTOCOL_TOR },
+ { 0x76D0C22A, 32, NDPI_PROTOCOL_TOR },
+ { 0x76D0F817, 32, NDPI_PROTOCOL_TOR },
+ { 0x76D3C1BE, 32, NDPI_PROTOCOL_TOR },
+ { 0x76D3C2E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x77092F46, 32, NDPI_PROTOCOL_TOR },
+ { 0x77EDA418, 32, NDPI_PROTOCOL_TOR },
+ { 0x77F64734, 32, NDPI_PROTOCOL_TOR },
+ { 0x781DD933, 32, NDPI_PROTOCOL_TOR },
+ { 0x78339DD3, 32, NDPI_PROTOCOL_TOR },
+ { 0x7839A32E, 32, NDPI_PROTOCOL_TOR },
+ { 0x783B2AC8, 32, NDPI_PROTOCOL_TOR },
+ { 0x783BA789, 32, NDPI_PROTOCOL_TOR },
+ { 0x784AE0A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x7890BEA2, 32, NDPI_PROTOCOL_TOR },
+ { 0x7936AF32, 32, NDPI_PROTOCOL_TOR },
+ { 0x794953C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x7954959D, 32, NDPI_PROTOCOL_TOR },
+ { 0x79623AD3, 32, NDPI_PROTOCOL_TOR },
+ { 0x79628113, 32, NDPI_PROTOCOL_TOR },
+ { 0x7963582E, 32, NDPI_PROTOCOL_TOR },
+ { 0x7963B8C8, 32, NDPI_PROTOCOL_TOR },
+ { 0x7972B51D, 32, NDPI_PROTOCOL_TOR },
+ { 0x797AA193, 32, NDPI_PROTOCOL_TOR },
+ { 0x79D1E5D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x79D34C57, 32, NDPI_PROTOCOL_TOR },
+ { 0x79D3C2E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x7A744433, 32, NDPI_PROTOCOL_TOR },
+ { 0x7B01A089, 32, NDPI_PROTOCOL_TOR },
+ { 0x7B64357A, 32, NDPI_PROTOCOL_TOR },
+ { 0x7B6CE046, 32, NDPI_PROTOCOL_TOR },
+ { 0x7BDDB10E, 32, NDPI_PROTOCOL_TOR },
+ { 0x7C0DAC95, 32, NDPI_PROTOCOL_TOR },
+ { 0x7C18F2DD, 32, NDPI_PROTOCOL_TOR },
+ { 0x7C67D84F, 32, NDPI_PROTOCOL_TOR },
+ { 0x7C6DE896, 32, NDPI_PROTOCOL_TOR },
+ { 0x7C951525, 32, NDPI_PROTOCOL_TOR },
+ { 0x7CA9666D, 32, NDPI_PROTOCOL_TOR },
+ { 0x7CA981CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x7CF8F9F5, 32, NDPI_PROTOCOL_TOR },
+ { 0x7CF8F9F7, 32, NDPI_PROTOCOL_TOR },
+ { 0x7CF8F9FA, 32, NDPI_PROTOCOL_TOR },
+ { 0x7CF8F9FD, 32, NDPI_PROTOCOL_TOR },
+ { 0x7D1E5578, 32, NDPI_PROTOCOL_TOR },
+ { 0x7D352C26, 32, NDPI_PROTOCOL_TOR },
+ { 0x7D83BD18, 32, NDPI_PROTOCOL_TOR },
+ { 0x7D83BD2C, 32, NDPI_PROTOCOL_TOR },
+ { 0x7DECCCB2, 32, NDPI_PROTOCOL_TOR },
+ { 0x7DFF021E, 32, NDPI_PROTOCOL_TOR },
+ { 0x7E08CD97, 32, NDPI_PROTOCOL_TOR },
+ { 0x7E460792, 32, NDPI_PROTOCOL_TOR },
+ { 0x7E57F79D, 32, NDPI_PROTOCOL_TOR },
+ { 0x8006E06B, 32, NDPI_PROTOCOL_TOR },
+ { 0x800CB13B, 32, NDPI_PROTOCOL_TOR },
+ { 0x800CE238, 32, NDPI_PROTOCOL_TOR },
+ { 0x800CE238, 32, NDPI_PROTOCOL_TOR },
+ { 0x800CE252, 32, NDPI_PROTOCOL_TOR },
+ { 0x800CE252, 32, NDPI_PROTOCOL_TOR },
+ { 0x801F0022, 32, NDPI_PROTOCOL_TOR },
+ { 0x801F0022, 32, NDPI_PROTOCOL_TOR },
+ { 0x801F0027, 32, NDPI_PROTOCOL_TOR },
+ { 0x80270844, 32, NDPI_PROTOCOL_TOR },
+ { 0x80278E14, 32, NDPI_PROTOCOL_TOR },
+ { 0x80278E15, 32, NDPI_PROTOCOL_TOR },
+ { 0x80348069, 32, NDPI_PROTOCOL_TOR },
+ { 0x8034A014, 32, NDPI_PROTOCOL_TOR },
+ { 0x80392F1E, 32, NDPI_PROTOCOL_TOR },
+ { 0x803B1279, 32, NDPI_PROTOCOL_TOR },
+ { 0x804490CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x80473391, 32, NDPI_PROTOCOL_TOR },
+ { 0x804910C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x804F35F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x804FBA39, 32, NDPI_PROTOCOL_TOR },
+ { 0x80752B5C, 32, NDPI_PROTOCOL_TOR },
+ { 0x80752B61, 32, NDPI_PROTOCOL_TOR },
+ { 0x80752B61, 32, NDPI_PROTOCOL_TOR },
+ { 0x807F2860, 32, NDPI_PROTOCOL_TOR },
+ { 0x8082CC5B, 32, NDPI_PROTOCOL_TOR },
+ { 0x8087BD74, 32, NDPI_PROTOCOL_TOR },
+ { 0x80AD374E, 32, NDPI_PROTOCOL_TOR },
+ { 0x80B1AA5A, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7227A, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C72305, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C723BF, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C729EE, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C72A6C, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C72C2E, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C72EDC, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C733D0, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C737CF, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C73947, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C73F21, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7404F, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C74471, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C748B6, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C74AE2, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C753BB, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7579B, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C75F79, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C75F7E, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C76AE6, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C77A68, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C77A76, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C77B13, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C782E3, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C78407, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C78548, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7859A, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C78BEC, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C79053, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C794F3, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C797C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C79A84, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7A56E, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7A5D4, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7A88E, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7AEF7, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7AF45, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7B364, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7B654, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7B73B, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7D4DC, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7D647, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7D9F3, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7E434, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7ECBE, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7F0C1, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7F24B, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7F4CE, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7FA9F, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7FCC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x80C7FD9C, 32, NDPI_PROTOCOL_TOR },
+ { 0x80D002E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x80DF5C53, 32, NDPI_PROTOCOL_TOR },
+ { 0x80E81239, 32, NDPI_PROTOCOL_TOR },
+ { 0x80ED9D72, 32, NDPI_PROTOCOL_TOR },
+ { 0x810A78C1, 32, NDPI_PROTOCOL_TOR },
+ { 0x811583C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x81400893, 32, NDPI_PROTOCOL_TOR },
+ { 0x817B0706, 32, NDPI_PROTOCOL_TOR },
+ { 0x817B0706, 32, NDPI_PROTOCOL_TOR },
+ { 0x817B0707, 32, NDPI_PROTOCOL_TOR },
+ { 0x817B0707, 32, NDPI_PROTOCOL_TOR },
+ { 0x817B0708, 32, NDPI_PROTOCOL_TOR },
+ { 0x817B0708, 32, NDPI_PROTOCOL_TOR },
+ { 0x817B0727, 32, NDPI_PROTOCOL_TOR },
+ { 0x817B0727, 32, NDPI_PROTOCOL_TOR },
+ { 0x817FFED5, 32, NDPI_PROTOCOL_TOR },
+ { 0x818200B7, 32, NDPI_PROTOCOL_TOR },
+ { 0x8185081F, 32, NDPI_PROTOCOL_TOR },
+ { 0x81BB3621, 32, NDPI_PROTOCOL_TOR },
+ { 0x81F1A1FA, 32, NDPI_PROTOCOL_TOR },
+ { 0x81F480A9, 32, NDPI_PROTOCOL_TOR },
+ { 0x820FBD2D, 32, NDPI_PROTOCOL_TOR },
+ { 0x82192C69, 32, NDPI_PROTOCOL_TOR },
+ { 0x823FAD7E, 32, NDPI_PROTOCOL_TOR },
+ { 0x824B51FB, 32, NDPI_PROTOCOL_TOR },
+ { 0x824BB225, 32, NDPI_PROTOCOL_TOR },
+ { 0x827B031B, 32, NDPI_PROTOCOL_TOR },
+ { 0x827E8EAB, 32, NDPI_PROTOCOL_TOR },
+ { 0x8284B17E, 32, NDPI_PROTOCOL_TOR },
+ { 0x82950E1F, 32, NDPI_PROTOCOL_TOR },
+ { 0x8295C80C, 32, NDPI_PROTOCOL_TOR },
+ { 0x8295CB6B, 32, NDPI_PROTOCOL_TOR },
+ { 0x8295DC7D, 32, NDPI_PROTOCOL_TOR },
+ { 0x82B417E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x82B43F96, 32, NDPI_PROTOCOL_TOR },
+ { 0x82B84B76, 32, NDPI_PROTOCOL_TOR },
+ { 0x82FD157B, 32, NDPI_PROTOCOL_TOR },
+ { 0x82FF48A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x82FF49CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x82FF49CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x82FF8242, 32, NDPI_PROTOCOL_TOR },
+ { 0x83488818, 32, NDPI_PROTOCOL_TOR },
+ { 0x83488A0B, 32, NDPI_PROTOCOL_TOR },
+ { 0x83AD8008, 32, NDPI_PROTOCOL_TOR },
+ { 0x83BC180E, 32, NDPI_PROTOCOL_TOR },
+ { 0x83BC28BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x83BC28BD, 32, NDPI_PROTOCOL_TOR },
+ { 0x83BC28BD, 32, NDPI_PROTOCOL_TOR },
+ { 0x83D79EED, 32, NDPI_PROTOCOL_TOR },
+ { 0x83D7A8F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x83D7ACD6, 32, NDPI_PROTOCOL_TOR },
+ { 0x83D7B062, 32, NDPI_PROTOCOL_TOR },
+ { 0x84D83602, 32, NDPI_PROTOCOL_TOR },
+ { 0x84E69651, 32, NDPI_PROTOCOL_TOR },
+ { 0x84F81E0C, 32, NDPI_PROTOCOL_TOR },
+ { 0x84FBE6E3, 32, NDPI_PROTOCOL_TOR },
+ { 0x86001A20, 32, NDPI_PROTOCOL_TOR },
+ { 0x86036F77, 32, NDPI_PROTOCOL_TOR },
+ { 0x8603C987, 32, NDPI_PROTOCOL_TOR },
+ { 0x8603EA32, 32, NDPI_PROTOCOL_TOR },
+ { 0x86227D25, 32, NDPI_PROTOCOL_TOR },
+ { 0x86227D44, 32, NDPI_PROTOCOL_TOR },
+ { 0x862293AF, 32, NDPI_PROTOCOL_TOR },
+ { 0x8622D0E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x8631E0BC, 32, NDPI_PROTOCOL_TOR },
+ { 0x865B4E8F, 32, NDPI_PROTOCOL_TOR },
+ { 0x865D88B1, 32, NDPI_PROTOCOL_TOR },
+ { 0x86604111, 32, NDPI_PROTOCOL_TOR },
+ { 0x866370A8, 32, NDPI_PROTOCOL_TOR },
+ { 0x8666C865, 32, NDPI_PROTOCOL_TOR },
+ { 0x866A03FE, 32, NDPI_PROTOCOL_TOR },
+ { 0x867703A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x8679405D, 32, NDPI_PROTOCOL_TOR },
+ { 0x8679436A, 32, NDPI_PROTOCOL_TOR },
+ { 0x86A95CDB, 32, NDPI_PROTOCOL_TOR },
+ { 0x86E2441D, 32, NDPI_PROTOCOL_TOR },
+ { 0x86F993AE, 32, NDPI_PROTOCOL_TOR },
+ { 0x86FFEF3D, 32, NDPI_PROTOCOL_TOR },
+ { 0x88A8C999, 32, NDPI_PROTOCOL_TOR },
+ { 0x88F307AF, 32, NDPI_PROTOCOL_TOR },
+ { 0x88F30E86, 32, NDPI_PROTOCOL_TOR },
+ { 0x88F3E072, 32, NDPI_PROTOCOL_TOR },
+ { 0x88F3E072, 32, NDPI_PROTOCOL_TOR },
+ { 0x898708E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x899306B0, 32, NDPI_PROTOCOL_TOR },
+ { 0x89CD25DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x89CD7C23, 32, NDPI_PROTOCOL_TOR },
+ { 0x89E0E221, 32, NDPI_PROTOCOL_TOR },
+ { 0x89E23B7F, 32, NDPI_PROTOCOL_TOR },
+ { 0x89E2952B, 32, NDPI_PROTOCOL_TOR },
+ { 0x89F87A44, 32, NDPI_PROTOCOL_TOR },
+ { 0x8A640AD1, 32, NDPI_PROTOCOL_TOR },
+ { 0x8A6E2D26, 32, NDPI_PROTOCOL_TOR },
+ { 0x8A807C37, 32, NDPI_PROTOCOL_TOR },
+ { 0x8A80A9EC, 32, NDPI_PROTOCOL_TOR },
+ { 0x8B0E0DEC, 32, NDPI_PROTOCOL_TOR },
+ { 0x8B4E8DF7, 32, NDPI_PROTOCOL_TOR },
+ { 0x8B5B466B, 32, NDPI_PROTOCOL_TOR },
+ { 0x8C716E0B, 32, NDPI_PROTOCOL_TOR },
+ { 0x8C795022, 32, NDPI_PROTOCOL_TOR },
+ { 0x8C79502A, 32, NDPI_PROTOCOL_TOR },
+ { 0x8CB4BEBF, 32, NDPI_PROTOCOL_TOR },
+ { 0x8CBA4630, 32, NDPI_PROTOCOL_TOR },
+ { 0x8CC0DA8B, 32, NDPI_PROTOCOL_TOR },
+ { 0x8D0015F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x8D009B6D, 32, NDPI_PROTOCOL_TOR },
+ { 0x8D00AF95, 32, NDPI_PROTOCOL_TOR },
+ { 0x8D142144, 32, NDPI_PROTOCOL_TOR },
+ { 0x8D142145, 32, NDPI_PROTOCOL_TOR },
+ { 0x8D14214F, 32, NDPI_PROTOCOL_TOR },
+ { 0x8D369FB8, 32, NDPI_PROTOCOL_TOR },
+ { 0x8D466911, 32, NDPI_PROTOCOL_TOR },
+ { 0x8D8A8A88, 32, NDPI_PROTOCOL_TOR },
+ { 0x8D8A8DD0, 32, NDPI_PROTOCOL_TOR },
+ { 0x8D8AC2E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x8DFFA58A, 32, NDPI_PROTOCOL_TOR },
+ { 0x8DFFA77A, 32, NDPI_PROTOCOL_TOR },
+ { 0x8DFFBDA1, 32, NDPI_PROTOCOL_TOR },
+ { 0x8E0420C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x8E0433E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x8E04CF3B, 32, NDPI_PROTOCOL_TOR },
+ { 0x8E04D0A7, 32, NDPI_PROTOCOL_TOR },
+ { 0x8E04D519, 32, NDPI_PROTOCOL_TOR },
+ { 0x8E04D571, 32, NDPI_PROTOCOL_TOR },
+ { 0x8E04D726, 32, NDPI_PROTOCOL_TOR },
+ { 0x8E04D757, 32, NDPI_PROTOCOL_TOR },
+ { 0x8E36B0B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x8E69D044, 32, NDPI_PROTOCOL_TOR },
+ { 0x8FB128C0, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C0626, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C063B, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C0849, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C0B64, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C0E91, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C1DD0, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C1EA7, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C25F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C27CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C2879, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C3225, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C357D, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C3635, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C4042, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C498C, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C5044, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C5B87, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C6007, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C6439, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C6E67, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C6E67, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C7055, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C7EB3, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C7FA5, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C8023, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C832A, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C95CB, 32, NDPI_PROTOCOL_TOR },
+ { 0x904C9C65, 32, NDPI_PROTOCOL_TOR },
+ { 0x904CA35D, 32, NDPI_PROTOCOL_TOR },
+ { 0x904CB037, 32, NDPI_PROTOCOL_TOR },
+ { 0x904CB6CA, 32, NDPI_PROTOCOL_TOR },
+ { 0x904CC3E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x904CC728, 32, NDPI_PROTOCOL_TOR },
+ { 0x904CCB75, 32, NDPI_PROTOCOL_TOR },
+ { 0x904CF413, 32, NDPI_PROTOCOL_TOR },
+ { 0x904CFD04, 32, NDPI_PROTOCOL_TOR },
+ { 0x91DC000F, 32, NDPI_PROTOCOL_TOR },
+ { 0x92002090, 32, NDPI_PROTOCOL_TOR },
+ { 0x92002A3A, 32, NDPI_PROTOCOL_TOR },
+ { 0x92002A6E, 32, NDPI_PROTOCOL_TOR },
+ { 0x920048B4, 32, NDPI_PROTOCOL_TOR },
+ { 0x920049B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x923434C7, 32, NDPI_PROTOCOL_TOR },
+ { 0x9234419F, 32, NDPI_PROTOCOL_TOR },
+ { 0x92344BB3, 32, NDPI_PROTOCOL_TOR },
+ { 0x923490FC, 32, NDPI_PROTOCOL_TOR },
+ { 0x92349273, 32, NDPI_PROTOCOL_TOR },
+ { 0x925A1CB7, 32, NDPI_PROTOCOL_TOR },
+ { 0x9273A850, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B915A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B983AF, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B983EF, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B988DF, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B98D39, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B98F90, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B996DB, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B99939, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B99FF1, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B9A2EB, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B9B440, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B9B70D, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B9B99A, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B9BDC5, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B9FB5A, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B9FDCA, 32, NDPI_PROTOCOL_TOR },
+ { 0x92B9FDCA, 32, NDPI_PROTOCOL_TOR },
+ { 0x92FF39E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x93459FC4, 32, NDPI_PROTOCOL_TOR },
+ { 0x93660115, 32, NDPI_PROTOCOL_TOR },
+ { 0x9366D8F2, 32, NDPI_PROTOCOL_TOR },
+ { 0x93AFBB8F, 32, NDPI_PROTOCOL_TOR },
+ { 0x93DEA58B, 32, NDPI_PROTOCOL_TOR },
+ { 0x93E5081A, 32, NDPI_PROTOCOL_TOR },
+ { 0x946429FB, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB1431, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB2832, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB2BE9, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB2D87, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB431B, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB4566, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB4D64, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB53C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB5884, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB71E6, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB7DD3, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB809C, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FB97BD, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FBBEE5, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FBCE86, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FBCF24, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FBD7E9, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FBD7F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FBE30E, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FBED4F, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FBF597, 32, NDPI_PROTOCOL_TOR },
+ { 0x94FBFEE5, 32, NDPI_PROTOCOL_TOR },
+ { 0x9509001B, 32, NDPI_PROTOCOL_TOR },
+ { 0x9509003B, 32, NDPI_PROTOCOL_TOR },
+ { 0x9509003C, 32, NDPI_PROTOCOL_TOR },
+ { 0x951436DA, 32, NDPI_PROTOCOL_TOR },
+ { 0x958405BD, 32, NDPI_PROTOCOL_TOR },
+ { 0x959A9810, 32, NDPI_PROTOCOL_TOR },
+ { 0x959A9879, 32, NDPI_PROTOCOL_TOR },
+ { 0x959A9A92, 32, NDPI_PROTOCOL_TOR },
+ { 0x959A9D50, 32, NDPI_PROTOCOL_TOR },
+ { 0x959A9E7A, 32, NDPI_PROTOCOL_TOR },
+ { 0x959A9EE4, 32, NDPI_PROTOCOL_TOR },
+ { 0x959A9F57, 32, NDPI_PROTOCOL_TOR },
+ { 0x959A9FAC, 32, NDPI_PROTOCOL_TOR },
+ { 0x95ACC7F4, 32, NDPI_PROTOCOL_TOR },
+ { 0x95D2AB45, 32, NDPI_PROTOCOL_TOR },
+ { 0x95D2ADF7, 32, NDPI_PROTOCOL_TOR },
+ { 0x95D2BAC6, 32, NDPI_PROTOCOL_TOR },
+ { 0x95FF6DC9, 32, NDPI_PROTOCOL_TOR },
+ { 0x96659DFA, 32, NDPI_PROTOCOL_TOR },
+ { 0x968C0522, 32, NDPI_PROTOCOL_TOR },
+ { 0x971B08A4, 32, NDPI_PROTOCOL_TOR },
+ { 0x971DFD3F, 32, NDPI_PROTOCOL_TOR },
+ { 0x971FA3B8, 32, NDPI_PROTOCOL_TOR },
+ { 0x9741F79A, 32, NDPI_PROTOCOL_TOR },
+ { 0x97507745, 32, NDPI_PROTOCOL_TOR },
+ { 0x97507758, 32, NDPI_PROTOCOL_TOR },
+ { 0x9750800C, 32, NDPI_PROTOCOL_TOR },
+ { 0x9750A491, 32, NDPI_PROTOCOL_TOR },
+ { 0x97E04B76, 32, NDPI_PROTOCOL_TOR },
+ { 0x97E2D38D, 32, NDPI_PROTOCOL_TOR },
+ { 0x97E5201B, 32, NDPI_PROTOCOL_TOR },
+ { 0x97E65FF1, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC049E, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC0506, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC061B, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC0670, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC06C2, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC06C6, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC07B1, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC0B72, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC0E61, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC160C, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC171F, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC172C, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC1839, 32, NDPI_PROTOCOL_TOR },
+ { 0x97EC18E4, 32, NDPI_PROTOCOL_TOR },
+ { 0x97ECDA43, 32, NDPI_PROTOCOL_TOR },
+ { 0x97ECDD2C, 32, NDPI_PROTOCOL_TOR },
+ { 0x97ECDE1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x97ECDE1B, 32, NDPI_PROTOCOL_TOR },
+ { 0x97ECDED9, 32, NDPI_PROTOCOL_TOR },
+ { 0x97FC2A46, 32, NDPI_PROTOCOL_TOR },
+ { 0x99782A89, 32, NDPI_PROTOCOL_TOR },
+ { 0x997925A6, 32, NDPI_PROTOCOL_TOR },
+ { 0x997938DD, 32, NDPI_PROTOCOL_TOR },
+ { 0x99793A49, 32, NDPI_PROTOCOL_TOR },
+ { 0x997FFB43, 32, NDPI_PROTOCOL_TOR },
+ { 0x9A23AFE1, 32, NDPI_PROTOCOL_TOR },
+ { 0x9A7F3C42, 32, NDPI_PROTOCOL_TOR },
+ { 0x9A7F3D62, 32, NDPI_PROTOCOL_TOR },
+ { 0x9A7F3D8D, 32, NDPI_PROTOCOL_TOR },
+ { 0x9B5EA7C4, 32, NDPI_PROTOCOL_TOR },
+ { 0x9BD2EF58, 32, NDPI_PROTOCOL_TOR },
+ { 0x9C38FAE3, 32, NDPI_PROTOCOL_TOR },
+ { 0x9D0757B8, 32, NDPI_PROTOCOL_TOR },
+ { 0x9D07CA47, 32, NDPI_PROTOCOL_TOR },
+ { 0x9D07D224, 32, NDPI_PROTOCOL_TOR },
+ { 0x9D07DEE2, 32, NDPI_PROTOCOL_TOR },
+ { 0x9D0EF604, 32, NDPI_PROTOCOL_TOR },
+ { 0x9E3AA97E, 32, NDPI_PROTOCOL_TOR },
+ { 0x9E554D57, 32, NDPI_PROTOCOL_TOR },
+ { 0x9EB53326, 32, NDPI_PROTOCOL_TOR },
+ { 0x9EB552B2, 32, NDPI_PROTOCOL_TOR },
+ { 0x9EB560E3, 32, NDPI_PROTOCOL_TOR },
+ { 0x9EDE8F19, 32, NDPI_PROTOCOL_TOR },
+ { 0x9EFFD4B3, 32, NDPI_PROTOCOL_TOR },
+ { 0x9EFFD729, 32, NDPI_PROTOCOL_TOR },
+ { 0x9F94B55A, 32, NDPI_PROTOCOL_TOR },
+ { 0xA0612F1E, 32, NDPI_PROTOCOL_TOR },
+ { 0xA1357425, 32, NDPI_PROTOCOL_TOR },
+ { 0xA1357898, 32, NDPI_PROTOCOL_TOR },
+ { 0xA135A068, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2D3D985, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2D3E0E9, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2D813ED, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DA417E, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DA760C, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DAD084, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DAE92B, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DB02B1, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DC2FB8, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DC38BA, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DCD94C, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DCDA6D, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DCF1DF, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DDC939, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2DEA01D, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F307B4, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F317DD, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F320CA, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F323FB, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F32725, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F328A1, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F33089, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F33543, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F3354B, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F33EEF, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F348C6, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F3499C, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F35F80, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F364E1, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F3656E, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F367AE, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F371B6, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F37479, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F37734, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F377F6, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F37BDC, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F386E0, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F38B4E, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F38E6B, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F3969C, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F396E5, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F3971B, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F39C7A, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F3A25C, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F3F878, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F3FD76, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F418ED, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F419BA, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F419D6, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F41A09, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F41A9D, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F41D7C, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F422A9, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F52912, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F5D9D0, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F5DC86, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F5DC8C, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F74807, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F7481B, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F748C7, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F748C8, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F748C9, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F748D4, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F748D5, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F748D8, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F748D9, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F7494A, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F749CC, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F749CE, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F809ED, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F80B06, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F80BB0, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F88C65, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F88E67, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F88F29, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F8A033, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F8A053, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F8A090, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F8A097, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F8A1D5, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F8A3CA, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2F8A50E, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2FAE9C2, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2FAEA7D, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2FB463A, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2FB463A, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2FCCC3E, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2FCF079, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2FCF17B, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2FCF20D, 32, NDPI_PROTOCOL_TOR },
+ { 0xA2FE4436, 32, NDPI_PROTOCOL_TOR },
+ { 0xA40FA707, 32, NDPI_PROTOCOL_TOR },
+ { 0xA4272AFE, 32, NDPI_PROTOCOL_TOR },
+ { 0xA57B94C7, 32, NDPI_PROTOCOL_TOR },
+ { 0xA5FEFF10, 32, NDPI_PROTOCOL_TOR },
+ { 0xA5FEFF10, 32, NDPI_PROTOCOL_TOR },
+ { 0xA6460F0E, 32, NDPI_PROTOCOL_TOR },
+ { 0xA6465E6A, 32, NDPI_PROTOCOL_TOR },
+ { 0xA646CF02, 32, NDPI_PROTOCOL_TOR },
+ { 0xA646D4B5, 32, NDPI_PROTOCOL_TOR },
+ { 0xA64E0721, 32, NDPI_PROTOCOL_TOR },
+ { 0xA65215C8, 32, NDPI_PROTOCOL_TOR },
+ { 0xA6540737, 32, NDPI_PROTOCOL_TOR },
+ { 0xA6540794, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7397143, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7582348, 32, NDPI_PROTOCOL_TOR },
+ { 0xA758283F, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7582898, 32, NDPI_PROTOCOL_TOR },
+ { 0xA75828C8, 32, NDPI_PROTOCOL_TOR },
+ { 0xA75829BB, 32, NDPI_PROTOCOL_TOR },
+ { 0xA75829C2, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7582BF6, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7582C32, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7582C33, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7582C34, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7587066, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7587D43, 32, NDPI_PROTOCOL_TOR },
+ { 0xA77202C0, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7720390, 32, NDPI_PROTOCOL_TOR },
+ { 0xA77203A6, 32, NDPI_PROTOCOL_TOR },
+ { 0xA772243E, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7722489, 32, NDPI_PROTOCOL_TOR },
+ { 0xA77229D3, 32, NDPI_PROTOCOL_TOR },
+ { 0xA77229D3, 32, NDPI_PROTOCOL_TOR },
+ { 0xA77229D4, 32, NDPI_PROTOCOL_TOR },
+ { 0xA77229D4, 32, NDPI_PROTOCOL_TOR },
+ { 0xA772423D, 32, NDPI_PROTOCOL_TOR },
+ { 0xA77243CC, 32, NDPI_PROTOCOL_TOR },
+ { 0xA77243D4, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7724418, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7724726, 32, NDPI_PROTOCOL_TOR },
+ { 0xA77247BD, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7726116, 32, NDPI_PROTOCOL_TOR },
+ { 0xA772629A, 32, NDPI_PROTOCOL_TOR },
+ { 0xA772712E, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7727130, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7727288, 32, NDPI_PROTOCOL_TOR },
+ { 0xA77272D1, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7729864, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7A02CC2, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7A02CE2, 32, NDPI_PROTOCOL_TOR },
+ { 0xA7A0A39A, 32, NDPI_PROTOCOL_TOR },
+ { 0xA83ED9D8, 32, NDPI_PROTOCOL_TOR },
+ { 0xA867C3FA, 32, NDPI_PROTOCOL_TOR },
+ { 0xA896FB0F, 32, NDPI_PROTOCOL_TOR },
+ { 0xA8EB91AF, 32, NDPI_PROTOCOL_TOR },
+ { 0xA8EB9238, 32, NDPI_PROTOCOL_TOR },
+ { 0xA8EB9239, 32, NDPI_PROTOCOL_TOR },
+ { 0xA8EB935E, 32, NDPI_PROTOCOL_TOR },
+ { 0xA8EB9361, 32, NDPI_PROTOCOL_TOR },
+ { 0xA8EB9664, 32, NDPI_PROTOCOL_TOR },
+ { 0xA8EB9A60, 32, NDPI_PROTOCOL_TOR },
+ { 0xA8EB9CA2, 32, NDPI_PROTOCOL_TOR },
+ { 0xA9E57D1B, 32, NDPI_PROTOCOL_TOR },
+ { 0xA9E57D1B, 32, NDPI_PROTOCOL_TOR },
+ { 0xAA4BA251, 32, NDPI_PROTOCOL_TOR },
+ { 0xAA4BA257, 32, NDPI_PROTOCOL_TOR },
+ { 0xAA4BA3B4, 32, NDPI_PROTOCOL_TOR },
+ { 0xAB19C109, 32, NDPI_PROTOCOL_TOR },
+ { 0xAB19C114, 32, NDPI_PROTOCOL_TOR },
+ { 0xAB19C14D, 32, NDPI_PROTOCOL_TOR },
+ { 0xAB19C14E, 32, NDPI_PROTOCOL_TOR },
+ { 0xAB19C1EB, 32, NDPI_PROTOCOL_TOR },
+ { 0xAB655D88, 32, NDPI_PROTOCOL_TOR },
+ { 0xAC07A4C5, 32, NDPI_PROTOCOL_TOR },
+ { 0xACF51678, 32, NDPI_PROTOCOL_TOR },
+ { 0xACF520B9, 32, NDPI_PROTOCOL_TOR },
+ { 0xACF520BA, 32, NDPI_PROTOCOL_TOR },
+ { 0xACF521F9, 32, NDPI_PROTOCOL_TOR },
+ { 0xACF52416, 32, NDPI_PROTOCOL_TOR },
+ { 0xACF53C64, 32, NDPI_PROTOCOL_TOR },
+ { 0xACF5DB85, 32, NDPI_PROTOCOL_TOR },
+ { 0xACFE0D7C, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD08664C, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD0B116C, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD0D8D1C, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD10B454, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD12E604, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD16F0E2, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD172ADB, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD1C491B, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD2C23B2, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD2C3ACA, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD2DE436, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD304BF6, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD30B617, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD335037, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD33C620, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD36711E, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD40C757, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD427043, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD45B52A, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD469914, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD46DD71, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD4717F9, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD479C14, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD49717D, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD4CA387, 32, NDPI_PROTOCOL_TOR },
+ { 0xAD5980AC, 32, NDPI_PROTOCOL_TOR },
+ { 0xADA0B4BD, 32, NDPI_PROTOCOL_TOR },
+ { 0xADA103A9, 32, NDPI_PROTOCOL_TOR },
+ { 0xADA48BC3, 32, NDPI_PROTOCOL_TOR },
+ { 0xADA4CEB5, 32, NDPI_PROTOCOL_TOR },
+ { 0xADA4DBFA, 32, NDPI_PROTOCOL_TOR },
+ { 0xADA5F099, 32, NDPI_PROTOCOL_TOR },
+ { 0xADA71245, 32, NDPI_PROTOCOL_TOR },
+ { 0xADC769FE, 32, NDPI_PROTOCOL_TOR },
+ { 0xADD0C4D7, 32, NDPI_PROTOCOL_TOR },
+ { 0xADD0FBB2, 32, NDPI_PROTOCOL_TOR },
+ { 0xADD56C74, 32, NDPI_PROTOCOL_TOR },
+ { 0xADD5719B, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE45AE0, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE45B5B, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE65550, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE68199, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE683CF, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE683CF, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE686EE, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE68ABF, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE68E82, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE694EC, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE69504, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE69A5A, 32, NDPI_PROTOCOL_TOR },
+ { 0xADE69AB8, 32, NDPI_PROTOCOL_TOR },
+ { 0xADECF938, 32, NDPI_PROTOCOL_TOR },
+ { 0xADECFAD3, 32, NDPI_PROTOCOL_TOR },
+ { 0xADECFF8E, 32, NDPI_PROTOCOL_TOR },
+ { 0xADEF4FD2, 32, NDPI_PROTOCOL_TOR },
+ { 0xADF279C7, 32, NDPI_PROTOCOL_TOR },
+ { 0xADF66823, 32, NDPI_PROTOCOL_TOR },
+ { 0xADF6FE86, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFED0A8, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFED842, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFED843, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFED844, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFED845, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFC24D, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFC41E, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFCD71, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFD1B5, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFD2CD, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFD3AF, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFDA6A, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFDCAB, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFDD60, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFE28E, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFE455, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFE459, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFE486, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFE8C0, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFE93C, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFED6B, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFED6B, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFEDA5, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFF217, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFF259, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFF574, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFF64E, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFF6A2, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFF7F7, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFF812, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFF869, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFF9DE, 32, NDPI_PROTOCOL_TOR },
+ { 0xADFFFAF0, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE03A82A, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE064AC1, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE15F745, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE1D40A4, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE2DB58A, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE32F679, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE3E4833, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE3F713C, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE463C5C, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE475A25, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE5F6BA7, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE60D6AE, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE6208CA, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE6328BE, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE6C43BC, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE6D6112, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE7E102D, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE886956, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE8AC693, 32, NDPI_PROTOCOL_TOR },
+ { 0xAE8FF3F7, 32, NDPI_PROTOCOL_TOR },
+ { 0xAF648B8C, 32, NDPI_PROTOCOL_TOR },
+ { 0xAF8741DE, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00901D3, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00904CE, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0090574, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0091051, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0091948, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00926C6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0092E8D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00932F0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB009368E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0095425, 32, NDPI_PROTOCOL_TOR },
+ { 0xB009558D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0095AD7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0096708, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0096714, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0096B68, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00977A7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0097DD1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0098BFC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0098C6C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0098FC8, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0098FD0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00991C2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0099344, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00994B0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0099D4D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB009B42F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB009C0AB, 32, NDPI_PROTOCOL_TOR },
+ { 0xB009ED02, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63C8, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63C8, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63C9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63C9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CA, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CA, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CB, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CB, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CE, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CE, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CF, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63CF, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63D0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63D0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63D1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A63D1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A6BB4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00A74A9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00AFA4F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00AFDDB, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00AFE87, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00C1D0C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00C6B1E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00E717E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00F49B5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB00FBBA1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01C0978, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01C0B2A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01C1F79, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01C305E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01C36D5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01F1C3F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01F2395, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01F323D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01F4255, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01F7158, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01F7494, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01F7827, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01F989F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01F9CC7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01FB509, 32, NDPI_PROTOCOL_TOR },
+ { 0xB01FBF1A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB024237E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0245D6B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB02496F6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0249F29, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0268C0D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03515A2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0357FC2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB035E825, 32, NDPI_PROTOCOL_TOR },
+ { 0xB038EC53, 32, NDPI_PROTOCOL_TOR },
+ { 0xB038ECAD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB038ED5A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB038EDBF, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03A59BC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03A60C7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03A61C9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03A6462, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03A6711, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03A6A59, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03A6AC0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03A7317, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03A7816, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03A799F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03A9FAF, 32, NDPI_PROTOCOL_TOR },
+ { 0xB03D89DD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB043AC1E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB049E604, 32, NDPI_PROTOCOL_TOR },
+ { 0xB04D1A58, 32, NDPI_PROTOCOL_TOR },
+ { 0xB04D226A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB04D2746, 32, NDPI_PROTOCOL_TOR },
+ { 0xB04D29B7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB05019F4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB063C782, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0678035, 32, NDPI_PROTOCOL_TOR },
+ { 0xB06A3636, 32, NDPI_PROTOCOL_TOR },
+ { 0xB06A6B2F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB06CA0F1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB06CA0F2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB06CA0FD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB072F82F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0744531, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0746831, 32, NDPI_PROTOCOL_TOR },
+ { 0xB075128D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB07B065E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB07B0665, 32, NDPI_PROTOCOL_TOR },
+ { 0xB07B1C1F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB07B1C22, 32, NDPI_PROTOCOL_TOR },
+ { 0xB07EF45B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB07EFC0B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB07EFC0C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0BCDE53, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0BD2641, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0BD77B6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0C17D30, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0C20E92, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0C62CC4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0C65C86, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0C6642D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0C67537, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0C7E07F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0C7E590, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0D496A3, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0DD2E35, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0DECAC3, 32, NDPI_PROTOCOL_TOR },
+ { 0xB0E2DAFF, 32, NDPI_PROTOCOL_TOR },
+ { 0xB10648C6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB12F6D15, 32, NDPI_PROTOCOL_TOR },
+ { 0xB15C1B98, 32, NDPI_PROTOCOL_TOR },
+ { 0xB18D1209, 32, NDPI_PROTOCOL_TOR },
+ { 0xB194ACC4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB1BC41E6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB1CD10C8, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2011DB1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB202DFF0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB202E307, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2031B59, 32, NDPI_PROTOCOL_TOR },
+ { 0xB204CFB7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2067327, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2070DE7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB20BA25E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2102D5A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB210D038, 32, NDPI_PROTOCOL_TOR },
+ { 0xB210D039, 32, NDPI_PROTOCOL_TOR },
+ { 0xB211AA0B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB211AA13, 32, NDPI_PROTOCOL_TOR },
+ { 0xB212106C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21211CC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21211EA, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21253D7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2128308, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2143710, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2143712, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2151456, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2157245, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21572B9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2182081, 32, NDPI_PROTOCOL_TOR },
+ { 0xB218CF5C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21944AC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21968A9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2198DE6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21A57B7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21A76A9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21A8269, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21AB707, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21AC341, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21B383A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21B78E5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB21B7ACB, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220225B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2202C9D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2203E91, 32, NDPI_PROTOCOL_TOR },
+ { 0xB22064D7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220784B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2207A41, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2208FAF, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2208FAF, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220B560, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220B561, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220B562, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220B563, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220D861, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220D892, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220DBC5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220DC0C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220DC18, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220DD97, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220DDCF, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220DE15, 32, NDPI_PROTOCOL_TOR },
+ { 0xB220EE9E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2212397, 32, NDPI_PROTOCOL_TOR },
+ { 0xB22170AB, 32, NDPI_PROTOCOL_TOR },
+ { 0xB22EA34B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E0999, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E0E7F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E0E97, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E102A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E12D7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E1384, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E1A53, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E2520, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E27CA, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E2E07, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E3405, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E354B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E36E3, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E38A3, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E3910, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E3A50, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E414D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E4DB6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E4E51, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E507C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E5660, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E56CE, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E5A6F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E5D24, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E5EF3, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E60A0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E64C1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E6892, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E6DA4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E6E8D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E6F30, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E7047, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E769A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E83D8, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E9871, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23E9E9C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EA3E3, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EA7B2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EADCB, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EB2E4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EB893, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EBA9B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EBD4F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EC4B1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EC658, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EC6D5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EC7E2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EC927, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23ECC5B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23ECC63, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23ED1FC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23ED47B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23ED986, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23ED9E9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EDAA0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EDE81, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EE525, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EE5D1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EE707, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EEA99, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EEB68, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EEE78, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EF11E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EF140, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EF877, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EFB08, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EFC52, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23EFCEA, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F00A1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F1030, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F2E61, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F3D43, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F41B3, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F4AC4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F4AF5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F5E90, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F604F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F6122, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F65C5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F6E97, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F749D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F91E2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23F9A5D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23FA2D4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB23FD133, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24021FC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB246D353, 32, NDPI_PROTOCOL_TOR },
+ { 0xB248584D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB249D276, 32, NDPI_PROTOCOL_TOR },
+ { 0xB249D2F0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24A67E4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24D627C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24D7B29, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24ED425, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24EEAC3, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F8540, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F8623, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F86B7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F86B7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F86C4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F88E6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F8B11, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F8B2E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F8D6C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F8EE0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F901C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F901C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F9D24, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F9D24, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F9F93, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24F9FE0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FA039, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FA198, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FA1B1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FA1ED, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FA1ED, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FA3A9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FA515, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FA858, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FAAAD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FAAB5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FAAB5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FB060, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FB072, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FB0B9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FB5E6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB24FBCD4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2520865, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2522270, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2522871, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2524269, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2534549, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2560A58, 32, NDPI_PROTOCOL_TOR },
+ { 0xB281AD8F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB289B71D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB28C33AD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB28C33AD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB28C6812, 32, NDPI_PROTOCOL_TOR },
+ { 0xB28CC54B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB28E0705, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2A23DD6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2A242D4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2A2C21E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2A2C252, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2A2C2D2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2A2C505, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2A746AA, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AA6FC2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AF83C2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AF8B8A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AF8B8A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AF8B8B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AF8B8B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AF8B8C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AF8B8C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AF8B8D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AF8B8D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AF8B8E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2AF8B8E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2BA743C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2BED2D1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2BFC29E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2C0BBAF, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2C3EA94, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2C7EAC0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2C861B6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2C8CBEE, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2C8EE97, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2C92FF5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2C98985, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2C9B19C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2CA6B7B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2CB9302, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2CB9A4F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2CBBF12, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D13297, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D13363, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D134A2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D3238A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D808F5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D83B33, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D85C75, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D9B820, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D9B943, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D9BB05, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D9BB06, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2D9BB27, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2DBF5D6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2EEDF43, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2EEE084, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2EEE16C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2EEE19E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2EEE40C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2EEED2C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2EF3CAC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2EFB113, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FAF3D9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FD60A6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE0615, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE08BB, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE0987, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE1486, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE1486, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE16E4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE193E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE19A5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE1AF4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE1C14, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE1E56, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE1FAD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE1FD1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE23E0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE25C5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE2805, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE2BF4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE2C5B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE2C5B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE2C87, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE2C87, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE2CEA, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE2CEA, 32, NDPI_PROTOCOL_TOR },
+ { 0xB2FE3765, 32, NDPI_PROTOCOL_TOR },
+ { 0xB300C293, 32, NDPI_PROTOCOL_TOR },
+ { 0xB32B8522, 32, NDPI_PROTOCOL_TOR },
+ { 0xB36FE5E8, 32, NDPI_PROTOCOL_TOR },
+ { 0xB3E8F4B7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB4DE4452, 32, NDPI_PROTOCOL_TOR },
+ { 0xB529C599, 32, NDPI_PROTOCOL_TOR },
+ { 0xB529DB75, 32, NDPI_PROTOCOL_TOR },
+ { 0xB52E9531, 32, NDPI_PROTOCOL_TOR },
+ { 0xB5A073AC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB6A70430, 32, NDPI_PROTOCOL_TOR },
+ { 0xB7574B02, 32, NDPI_PROTOCOL_TOR },
+ { 0xB75806AD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8129B07, 32, NDPI_PROTOCOL_TOR },
+ { 0xB812D6D9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8230910, 32, NDPI_PROTOCOL_TOR },
+ { 0xB827A1D3, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8486A34, 32, NDPI_PROTOCOL_TOR },
+ { 0xB84E9433, 32, NDPI_PROTOCOL_TOR },
+ { 0xB85EE222, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8645406, 32, NDPI_PROTOCOL_TOR },
+ { 0xB869CB85, 32, NDPI_PROTOCOL_TOR },
+ { 0xB869DC18, 32, NDPI_PROTOCOL_TOR },
+ { 0xB869EB44, 32, NDPI_PROTOCOL_TOR },
+ { 0xB86A6DF4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB86AD762, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8944B0F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB89BBBCD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8A3447D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8A48472, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8A4F401, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8A4F601, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8AA68F7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8AF118B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8AF2873, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8B07919, 32, NDPI_PROTOCOL_TOR },
+ { 0xB8B705CB, 32, NDPI_PROTOCOL_TOR },
+ { 0xB904E322, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9050983, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9053482, 32, NDPI_PROTOCOL_TOR },
+ { 0xB905355D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB907944E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB908EC83, 32, NDPI_PROTOCOL_TOR },
+ { 0xB908ED1B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB908EDD0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB908EE42, 32, NDPI_PROTOCOL_TOR },
+ { 0xB908EE8B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB908EE8C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90A1DF7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90A4750, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90BA670, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90C0C85, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90C0E76, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90D259E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90D2631, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90D2684, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90D26B9, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90D27C5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90E1C6A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90E1F3B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90EB80D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90EB9F0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB90FF47C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9103C53, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9107C88, 32, NDPI_PROTOCOL_TOR },
+ { 0xB910AC9B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB910AD54, 32, NDPI_PROTOCOL_TOR },
+ { 0xB910AD56, 32, NDPI_PROTOCOL_TOR },
+ { 0xB910C8B0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB910C91C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB911908A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB911B8E4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9129404, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9135724, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9156432, 32, NDPI_PROTOCOL_TOR },
+ { 0xB915671F, 32, NDPI_PROTOCOL_TOR },
+ { 0xB915D8A6, 32, NDPI_PROTOCOL_TOR },
+ { 0xB915D908, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9163F22, 32, NDPI_PROTOCOL_TOR },
+ { 0xB918EBCD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB919D8ED, 32, NDPI_PROTOCOL_TOR },
+ { 0xB91A7CB4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB91A9C1C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB91A9C1D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB91BAF18, 32, NDPI_PROTOCOL_TOR },
+ { 0xB91F644B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9222102, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9246491, 32, NDPI_PROTOCOL_TOR },
+ { 0xB92592AC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB925E2C5, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9262FE0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB928870A, 32, NDPI_PROTOCOL_TOR },
+ { 0xB92DC039, 32, NDPI_PROTOCOL_TOR },
+ { 0xB92DC069, 32, NDPI_PROTOCOL_TOR },
+ { 0xB92DC0BC, 32, NDPI_PROTOCOL_TOR },
+ { 0xB92DC1F2, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9310ED3, 32, NDPI_PROTOCOL_TOR },
+ { 0xB932BFFA, 32, NDPI_PROTOCOL_TOR },
+ { 0xB932E9E0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB935A306, 32, NDPI_PROTOCOL_TOR },
+ { 0xB936EE88, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9385426, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9395219, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D8932, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D8932, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D8949, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D8949, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D942E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D9450, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D945D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D9474, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D948D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D948E, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D94B7, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D94BD, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D94C1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D94E4, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D956D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D9574, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D9576, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D9577, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D95B0, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93D95C1, 32, NDPI_PROTOCOL_TOR },
+ { 0xB93FBC7C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB941C85D, 32, NDPI_PROTOCOL_TOR },
+ { 0xB941CD12, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9453693, 32, NDPI_PROTOCOL_TOR },
+ { 0xB9453744, 32, NDPI_PROTOCOL_TOR },
+ { 0xB948B169, 32, NDPI_PROTOCOL_TOR },
+ { 0xB948E86B, 32, NDPI_PROTOCOL_TOR },
+ { 0xB948F791, 32, NDPI_PROTOCOL_TOR },
+ { 0xB94B382C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB94B382C, 32, NDPI_PROTOCOL_TOR },
+ { 0xB94B3874, 32, NDPI_PROTOCOL_TOR },
+ { 0xB94B3874, 32, NDPI_PROTOCOL_TOR },
+ { 0xB952C8E0, 32, NDPI_PROTOCOL_TOR },
+ { 0xBA160C6E, 32, NDPI_PROTOCOL_TOR },
+ { 0xBA1A4002, 32, NDPI_PROTOCOL_TOR },
+ { 0xBA6B7BAE, 32, NDPI_PROTOCOL_TOR },
+ { 0xBB3B6D26, 32, NDPI_PROTOCOL_TOR },
+ { 0xBB3F6418, 32, NDPI_PROTOCOL_TOR },
+ { 0xBB5F2203, 32, NDPI_PROTOCOL_TOR },
+ { 0xBBD34A78, 32, NDPI_PROTOCOL_TOR },
+ { 0xBBFEE732, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC0262D8, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC04F2B2, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC060D5B, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC06497F, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC18F4FF, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC208F85, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC20F2F4, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC28209A, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC2821D9, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC2825C8, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC2833E8, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC283512, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC283B50, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC283C8E, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC283CF2, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC284C73, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC286345, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC286BCD, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC2880F6, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC2899F2, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC28B34A, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC28CE05, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC28EBD7, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC28F839, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC2AFD0B, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC322E9A, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC3CC333, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC3E5662, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC499110, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC4DD834, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC4ED027, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC553281, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC57A8F9, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC5D117B, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC5DD54B, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC5FF78C, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC603CB8, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC607AC3, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC617F79, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC62D521, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC6450C9, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC67690F, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC676B47, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC6CD29D, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC6D5CC5, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC717278, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC728C79, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC769BEF, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC780C35, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC78EBA5, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC78EFF1, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC78FD27, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC7A05A1, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC7AD504, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC7B2F13, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC7C951D, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC7E5D51, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC7E5D5F, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC817CFA, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC860642, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC860C22, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC860CEC, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC864432, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC864BD3, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8653AB, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A01E5, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A01E5, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A0931, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A0931, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A09D0, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A09D0, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A110F, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A110F, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A5886, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A58A8, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A6574, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A6A8A, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A703C, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A70E2, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A7976, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A7DD1, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8A7DD1, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8D5359, 32, NDPI_PROTOCOL_TOR },
+ { 0xBC8E70F6, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA5033F, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA5033F, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA519D2, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA51A0D, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA51A0D, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA53B2B, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA55E69, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA57B5F, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA57BF4, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA58822, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA58A8D, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA58AB5, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA58AB5, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA5919D, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA5A4A3, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA5A4A3, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA5C181, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA5C88A, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA5D59C, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA5E828, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA5EC12, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA5F1D8, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA609DA, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA60CD4, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA60DE6, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA61250, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA61286, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA6234D, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA624A3, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA625AD, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA625D7, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA62B21, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA62B3D, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA62BC8, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA62D23, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA62EAB, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA63064, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA630B1, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA63152, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA631B4, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA63271, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA63575, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA638B3, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA63C9E, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA63E18, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA73D86, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA745E0, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCA8225A, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCAE49D9, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCAE5D48, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCAEA791, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCAEB379, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCAED97F, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCB55D55, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCB7841D, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCBA10EC, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCC02309, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCC0A86E, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCC1632B, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCC1C8F8, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCC2C9AE, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCC30886, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCC348B3, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCC3D1FD, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCCAFCC1, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCD519EA, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCD58F17, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCD65D16, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCDF3258, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE23EAE, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE294A1, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2957C, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2AB6F, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2ACAA, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2BB8A, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2BD35, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2BE71, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2BF12, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2C030, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2C5E0, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2C7A0, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2C8D8, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2CEC8, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2D6B1, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2D98E, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2DC10, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2DCE2, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2DDF3, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2E196, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2E396, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2E839, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2FA52, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2FDB5, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE2FE59, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE3C986, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE3E068, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE4234B, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE43194, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE63CF6, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE65B87, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE6A6EB, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE6DFB2, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE8B717, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCE94947, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF17195, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF17251, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF18C77, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF18C86, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF18C94, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF18D13, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF18D15, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF18D87, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF18DAA, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF423AB, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF64BB2, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF6CC43, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCF764B8, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCFF1E24, 32, NDPI_PROTOCOL_TOR },
+ { 0xBCFF70E0, 32, NDPI_PROTOCOL_TOR },
+ { 0xBD446D80, 32, NDPI_PROTOCOL_TOR },
+ { 0xBDD4A056, 32, NDPI_PROTOCOL_TOR },
+ { 0xBDF2D9EF, 32, NDPI_PROTOCOL_TOR },
+ { 0xBE03A993, 32, NDPI_PROTOCOL_TOR },
+ { 0xBE589587, 32, NDPI_PROTOCOL_TOR },
+ { 0xBE78E41E, 32, NDPI_PROTOCOL_TOR },
+ { 0xBE7B2D60, 32, NDPI_PROTOCOL_TOR },
+ { 0xBE7B2F74, 32, NDPI_PROTOCOL_TOR },
+ { 0xBEBD7608, 32, NDPI_PROTOCOL_TOR },
+ { 0xBEC0A60C, 32, NDPI_PROTOCOL_TOR },
+ { 0xBEE25D6B, 32, NDPI_PROTOCOL_TOR },
+ { 0xBF151340, 32, NDPI_PROTOCOL_TOR },
+ { 0xBF6502EB, 32, NDPI_PROTOCOL_TOR },
+ { 0xBF6598A6, 32, NDPI_PROTOCOL_TOR },
+ { 0xBFEFD3DC, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0009D29, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0031CF2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0031EDF, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0039416, 32, NDPI_PROTOCOL_TOR },
+ { 0xC003941B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC00396AA, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0039DD4, 32, NDPI_PROTOCOL_TOR },
+ { 0xC003A076, 32, NDPI_PROTOCOL_TOR },
+ { 0xC003A4E3, 32, NDPI_PROTOCOL_TOR },
+ { 0xC003ACEC, 32, NDPI_PROTOCOL_TOR },
+ { 0xC003AD58, 32, NDPI_PROTOCOL_TOR },
+ { 0xC003B1A7, 32, NDPI_PROTOCOL_TOR },
+ { 0xC003B426, 32, NDPI_PROTOCOL_TOR },
+ { 0xC003C9E2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC003C9F9, 32, NDPI_PROTOCOL_TOR },
+ { 0xC003D27D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC00C211A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC00C211B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC01E202C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0223B30, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0223F89, 32, NDPI_PROTOCOL_TOR },
+ { 0xC022E022, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0264C03, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0266D90, 32, NDPI_PROTOCOL_TOR },
+ { 0xC02A7410, 32, NDPI_PROTOCOL_TOR },
+ { 0xC02A74A1, 32, NDPI_PROTOCOL_TOR },
+ { 0xC02BF408, 32, NDPI_PROTOCOL_TOR },
+ { 0xC02BF408, 32, NDPI_PROTOCOL_TOR },
+ { 0xC02BF42A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC02BF42A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC02C1E28, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0405266, 32, NDPI_PROTOCOL_TOR },
+ { 0xC043DE05, 32, NDPI_PROTOCOL_TOR },
+ { 0xC045177C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0455E39, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0479724, 32, NDPI_PROTOCOL_TOR },
+ { 0xC047DAA0, 32, NDPI_PROTOCOL_TOR },
+ { 0xC047F524, 32, NDPI_PROTOCOL_TOR },
+ { 0xC047F589, 32, NDPI_PROTOCOL_TOR },
+ { 0xC047F589, 32, NDPI_PROTOCOL_TOR },
+ { 0xC047F5D7, 32, NDPI_PROTOCOL_TOR },
+ { 0xC049EC12, 32, NDPI_PROTOCOL_TOR },
+ { 0xC049EF53, 32, NDPI_PROTOCOL_TOR },
+ { 0xC051842E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC051DC5B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC051DDA2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC051F91F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0571C1C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0571C52, 32, NDPI_PROTOCOL_TOR },
+ { 0xC057E0BD, 32, NDPI_PROTOCOL_TOR },
+ { 0xC05BEBE6, 32, NDPI_PROTOCOL_TOR },
+ { 0xC05F1A3A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC05F1B8F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC05F2889, 32, NDPI_PROTOCOL_TOR },
+ { 0xC05F2CA9, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0630289, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0630289, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0630620, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0630852, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0630B30, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0630F7A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0630FDC, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063259C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0632B71, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0632B9C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0632BCE, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063681B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063914E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0639A18, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0639A4B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0639A50, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0639AEA, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063A866, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063A93D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063BA5E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063C1C1, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063D48B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063D497, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063F665, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063F7EA, 32, NDPI_PROTOCOL_TOR },
+ { 0xC063FA8F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC07247DE, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0794208, 32, NDPI_PROTOCOL_TOR },
+ { 0xC079AA4B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC07CFA53, 32, NDPI_PROTOCOL_TOR },
+ { 0xC087A8FB, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0965E31, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0979A8E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0999AF4, 32, NDPI_PROTOCOL_TOR },
+ { 0xC09B506F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC09B5365, 32, NDPI_PROTOCOL_TOR },
+ { 0xC09B5736, 32, NDPI_PROTOCOL_TOR },
+ { 0xC09B5874, 32, NDPI_PROTOCOL_TOR },
+ { 0xC09B5D65, 32, NDPI_PROTOCOL_TOR },
+ { 0xC09B5F7A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC09B5F7A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC09B5FDE, 32, NDPI_PROTOCOL_TOR },
+ { 0xC09DC04F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC09DEFF3, 32, NDPI_PROTOCOL_TOR },
+ { 0xC09DFD7D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0A0C16E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0A264D5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0A2650F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0A3E033, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0AB3D72, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0B82075, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0B8502A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0B85175, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0B851A0, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0B85280, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0B8555C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0B858CF, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0B85E6F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0BB6A92, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0C8EC20, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0D28AA3, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0D28AAB, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0D2C7B1, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0D2CC27, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0D2CEBD, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0D2E780, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0D2F0D9, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0E28C77, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0E38B12, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0E38F11, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0E3E71B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0EB4E13, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0EB4EDB, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0EDD411, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F158B5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F183E9, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1863E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F192D5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F19438, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1B238, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1B41B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1B4A3, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1B57A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1C4B2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1C66A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1C7D0, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1CAD6, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1CEAB, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1D063, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1D265, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1D878, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1E9CB, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1E9F2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F1FC3F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F37E51, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F9380B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F93EB7, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F93F97, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0F93F9C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0FC828E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC0FEA81A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC101C19C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC106DE6E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC107B1DF, 32, NDPI_PROTOCOL_TOR },
+ { 0xC10B722B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC10B722D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC10B722E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC10B722F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC10B8978, 32, NDPI_PROTOCOL_TOR },
+ { 0xC10BA4F3, 32, NDPI_PROTOCOL_TOR },
+ { 0xC10BA6C2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC10BA6C2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC10C4907, 32, NDPI_PROTOCOL_TOR },
+ { 0xC10D6125, 32, NDPI_PROTOCOL_TOR },
+ { 0xC10E9FCC, 32, NDPI_PROTOCOL_TOR },
+ { 0xC117F4F4, 32, NDPI_PROTOCOL_TOR },
+ { 0xC118D194, 32, NDPI_PROTOCOL_TOR },
+ { 0xC118D27E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC119019D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC11CE446, 32, NDPI_PROTOCOL_TOR },
+ { 0xC121D817, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1220201, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1233435, 32, NDPI_PROTOCOL_TOR },
+ { 0xC12598C7, 32, NDPI_PROTOCOL_TOR },
+ { 0xC12598F1, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1530139, 32, NDPI_PROTOCOL_TOR },
+ { 0xC15A0C56, 32, NDPI_PROTOCOL_TOR },
+ { 0xC15A0C57, 32, NDPI_PROTOCOL_TOR },
+ { 0xC15A0C58, 32, NDPI_PROTOCOL_TOR },
+ { 0xC15A0C59, 32, NDPI_PROTOCOL_TOR },
+ { 0xC15A0C5A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC15FE4E8, 32, NDPI_PROTOCOL_TOR },
+ { 0xC15FF2D5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC168DC23, 32, NDPI_PROTOCOL_TOR },
+ { 0xC168DC36, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1698632, 32, NDPI_PROTOCOL_TOR },
+ { 0xC169869C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC16B131E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC16B5538, 32, NDPI_PROTOCOL_TOR },
+ { 0xC16B5539, 32, NDPI_PROTOCOL_TOR },
+ { 0xC16B553D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC16B553E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC16E9D97, 32, NDPI_PROTOCOL_TOR },
+ { 0xC16F1A16, 32, NDPI_PROTOCOL_TOR },
+ { 0xC16F8D6E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC188CC75, 32, NDPI_PROTOCOL_TOR },
+ { 0xC189ADD9, 32, NDPI_PROTOCOL_TOR },
+ { 0xC18A7603, 32, NDPI_PROTOCOL_TOR },
+ { 0xC18A7608, 32, NDPI_PROTOCOL_TOR },
+ { 0xC18AD865, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1960E3E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC196791A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1967942, 32, NDPI_PROTOCOL_TOR },
+ { 0xC19A0D98, 32, NDPI_PROTOCOL_TOR },
+ { 0xC19D73FA, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A3DC8F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A48535, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A4D955, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A744, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A745, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A746, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A747, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A748, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A749, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A74A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A74B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A74C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A74D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A74E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A74F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A750, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A751, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A752, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A753, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A754, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A755, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A756, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A757, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A758, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A759, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A75A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A75B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A75C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A75D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1A6A75E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1AE0614, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1B69035, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1B763D5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1BEA835, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1CB312E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1DB24CF, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1E0A32B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC1F66F3E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC20EB3B8, 32, NDPI_PROTOCOL_TOR },
+ { 0xC2173CFA, 32, NDPI_PROTOCOL_TOR },
+ { 0xC230DA31, 32, NDPI_PROTOCOL_TOR },
+ { 0xC2601297, 32, NDPI_PROTOCOL_TOR },
+ { 0xC2680064, 32, NDPI_PROTOCOL_TOR },
+ { 0xC26DCED4, 32, NDPI_PROTOCOL_TOR },
+ { 0xC276346F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC276D253, 32, NDPI_PROTOCOL_TOR },
+ { 0xC27EC6E4, 32, NDPI_PROTOCOL_TOR },
+ { 0xC296A84F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC296A85F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC296A86C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC2A6A031, 32, NDPI_PROTOCOL_TOR },
+ { 0xC313AE72, 32, NDPI_PROTOCOL_TOR },
+ { 0xC313AE73, 32, NDPI_PROTOCOL_TOR },
+ { 0xC31DA8CE, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3236D3D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC325BE55, 32, NDPI_PROTOCOL_TOR },
+ { 0xC328B523, 32, NDPI_PROTOCOL_TOR },
+ { 0xC32EB925, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3409582, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3474454, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3527C6F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC358543B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC35BED96, 32, NDPI_PROTOCOL_TOR },
+ { 0xC36E061F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC36E09E8, 32, NDPI_PROTOCOL_TOR },
+ { 0xC38AF902, 32, NDPI_PROTOCOL_TOR },
+ { 0xC38CFE59, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3947CC7, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A057B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A05CD, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A0937, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A0A9B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A0C42, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A0D0A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A0D60, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A0E28, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A0F75, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A2A65, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A40D6, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A411D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A43E5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A4682, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A4B54, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A4BA5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A4DC8, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A4E71, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A4E73, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A516C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A516E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A51E3, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A51F5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A5258, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A533C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A57E7, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A5B8B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A610A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6111, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A611B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A61A0, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6775, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6886, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6935, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6939, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6B56, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6B97, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6C4E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6D1E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6D34, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6D9D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6DCB, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6DDD, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A6E4C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A7095, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A72B9, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A742B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A74E8, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A75A3, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A76AC, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A7763, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A79C6, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A79EA, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A7BDE, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A7E2B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A7EA5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A7FF6, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A803A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A8097, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39A8879, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39AA671, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39AA671, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39AAF14, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39AB416, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39AD7F0, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39ADDED, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39AE205, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39AE93A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39AF076, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39AFB5E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC39FA2C2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3A6C926, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3A97DE2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3A9C4BC, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3A9CF36, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3A9D8BF, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3B2B57B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3B40BC4, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3BFE9DD, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3C6F2C2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3CAD33B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3D21DED, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3E1D31A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3E42DB0, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3E44B83, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3E6A853, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3EA9856, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3F25002, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3FAA3B1, 32, NDPI_PROTOCOL_TOR },
+ { 0xC3FBFCE2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC4252C59, 32, NDPI_PROTOCOL_TOR },
+ { 0xC55752E7, 32, NDPI_PROTOCOL_TOR },
+ { 0xC5E7DDD3, 32, NDPI_PROTOCOL_TOR },
+ { 0xC60C50BB, 32, NDPI_PROTOCOL_TOR },
+ { 0xC60C5B69, 32, NDPI_PROTOCOL_TOR },
+ { 0xC60C68D0, 32, NDPI_PROTOCOL_TOR },
+ { 0xC60F4FC5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC61799A1, 32, NDPI_PROTOCOL_TOR },
+ { 0xC617B141, 32, NDPI_PROTOCOL_TOR },
+ { 0xC617BB9E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC617F7CC, 32, NDPI_PROTOCOL_TOR },
+ { 0xC61B447E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC61B562B, 32, NDPI_PROTOCOL_TOR },
+ { 0xC61B562D, 32, NDPI_PROTOCOL_TOR },
+ { 0xC61B6D24, 32, NDPI_PROTOCOL_TOR },
+ { 0xC6257224, 32, NDPI_PROTOCOL_TOR },
+ { 0xC62E8E4A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC62E9933, 32, NDPI_PROTOCOL_TOR },
+ { 0xC6329148, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63291CF, 32, NDPI_PROTOCOL_TOR },
+ { 0xC6329228, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63292FC, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63293EF, 32, NDPI_PROTOCOL_TOR },
+ { 0xC632957F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63295A0, 32, NDPI_PROTOCOL_TOR },
+ { 0xC632970A, 32, NDPI_PROTOCOL_TOR },
+ { 0xC6329766, 32, NDPI_PROTOCOL_TOR },
+ { 0xC6329811, 32, NDPI_PROTOCOL_TOR },
+ { 0xC6329C4E, 32, NDPI_PROTOCOL_TOR },
+ { 0xC632B758, 32, NDPI_PROTOCOL_TOR },
+ { 0xC632BF5F, 32, NDPI_PROTOCOL_TOR },
+ { 0xC632E716, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63482DA, 32, NDPI_PROTOCOL_TOR },
+ { 0xC634A041, 32, NDPI_PROTOCOL_TOR },
+ { 0xC634A090, 32, NDPI_PROTOCOL_TOR },
+ { 0xC634C827, 32, NDPI_PROTOCOL_TOR },
+ { 0xC634F4ED, 32, NDPI_PROTOCOL_TOR },
+ { 0xC634F7A0, 32, NDPI_PROTOCOL_TOR },
+ { 0xC634F7A2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC634F7F7, 32, NDPI_PROTOCOL_TOR },
+ { 0xC634F7FA, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A601C, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A6079, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A66EA, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A6793, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A6793, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A6AF5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A6AF5, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A6B34, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A6B34, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A6B35, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A6D52, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A73D2, 32, NDPI_PROTOCOL_TOR },
+ { 0xC63A7FC9, 32, NDPI_PROTOCOL_TOR },
+ { 0xC6475142, 32, NDPI_PROTOCOL_TOR },
+ { 0xC648E7E9, 32, NDPI_PROTOCOL_TOR },
+ { 0xC6493247, 32, NDPI_PROTOCOL_TOR },
+ { 0xC64A38BF, 32, NDPI_PROTOCOL_TOR },
+ { 0xC64A3A10, 32, NDPI_PROTOCOL_TOR },
+{ 0xC64A3ACE, 32, NDPI_PROTOCOL_TOR },
+{ 0xC64A3C1A, 32, NDPI_PROTOCOL_TOR },
+{ 0xC64A3E6B, 32, NDPI_PROTOCOL_TOR },
+{ 0xC654A10C, 32, NDPI_PROTOCOL_TOR },
+{ 0xC654F0E5, 32, NDPI_PROTOCOL_TOR },
+{ 0xC654F96A, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6609B03, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6623103, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6623495, 32, NDPI_PROTOCOL_TOR },
+{ 0xC662358D, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6649014, 32, NDPI_PROTOCOL_TOR },
+{ 0xC664904B, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6649470, 32, NDPI_PROTOCOL_TOR },
+{ 0xC664947B, 32, NDPI_PROTOCOL_TOR },
+{ 0xC664959F, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6649B36, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6649BC2, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6697D25, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6697DB2, 32, NDPI_PROTOCOL_TOR },
+{ 0xC669D0A4, 32, NDPI_PROTOCOL_TOR },
+{ 0xC669DF92, 32, NDPI_PROTOCOL_TOR },
+{ 0xC68F88ED, 32, NDPI_PROTOCOL_TOR },
+{ 0xC693141D, 32, NDPI_PROTOCOL_TOR },
+{ 0xC693174D, 32, NDPI_PROTOCOL_TOR },
+{ 0xC69451A7, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6A7895C, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6A78F95, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6B49609, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6C74845, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6C76BDC, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6C77079, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6C77231, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6C775A4, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6C77A11, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6CD713B, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6D36392, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6D37ABF, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6D37B5C, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6D37CD6, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6D37DF2, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6D37E53, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6F464C8, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6F46963, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6F53294, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6F53C28, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6F53C93, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6F53CC2, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6F53E68, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6F53FE4, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6FC9957, 32, NDPI_PROTOCOL_TOR },
+{ 0xC6FC996B, 32, NDPI_PROTOCOL_TOR },
+{ 0xC710BF3A, 32, NDPI_PROTOCOL_TOR },
+{ 0xC71355FC, 32, NDPI_PROTOCOL_TOR },
+{ 0xC713D5B0, 32, NDPI_PROTOCOL_TOR },
+{ 0xC726567A, 32, NDPI_PROTOCOL_TOR },
+{ 0xC73A530A, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7579AFF, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7737387, 32, NDPI_PROTOCOL_TOR },
+{ 0xC773CDF1, 32, NDPI_PROTOCOL_TOR },
+{ 0xC773CDF2, 32, NDPI_PROTOCOL_TOR },
+{ 0xC773CDF3, 32, NDPI_PROTOCOL_TOR },
+{ 0xC773CDF5, 32, NDPI_PROTOCOL_TOR },
+{ 0xC773CDF8, 32, NDPI_PROTOCOL_TOR },
+{ 0xC77FE240, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7A78088, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7A7A1C3, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7A7C679, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7BC649A, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7BCC235, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7C173D1, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7C1FD31, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7C3C116, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7C3F83C, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7C3F890, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7C3F9D4, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7CA151D, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7FEEE2C, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7FEEE34, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7FEEE34, 32, NDPI_PROTOCOL_TOR },
+{ 0xC7FFDF58, 32, NDPI_PROTOCOL_TOR },
+{ 0xC811D20C, 32, NDPI_PROTOCOL_TOR },
+{ 0xC8628B17, 32, NDPI_PROTOCOL_TOR },
+{ 0xC86CEC4B, 32, NDPI_PROTOCOL_TOR },
+{ 0xC8B55A41, 32, NDPI_PROTOCOL_TOR },
+{ 0xC8DFD4D2, 32, NDPI_PROTOCOL_TOR },
+{ 0xC906897F, 32, NDPI_PROTOCOL_TOR },
+{ 0xC91BEB7F, 32, NDPI_PROTOCOL_TOR },
+{ 0xC9AA12B7, 32, NDPI_PROTOCOL_TOR },
+{ 0xC9D46CB8, 32, NDPI_PROTOCOL_TOR },
+{ 0xC9DA72A2, 32, NDPI_PROTOCOL_TOR },
+{ 0xCA07F408, 32, NDPI_PROTOCOL_TOR },
+{ 0xCA3C4220, 32, NDPI_PROTOCOL_TOR },
+{ 0xCA4A2C0F, 32, NDPI_PROTOCOL_TOR },
+{ 0xCA536AB3, 32, NDPI_PROTOCOL_TOR },
+{ 0xCA55E922, 32, NDPI_PROTOCOL_TOR },
+{ 0xCAAB9C54, 32, NDPI_PROTOCOL_TOR },
+{ 0xCAAC1039, 32, NDPI_PROTOCOL_TOR },
+{ 0xCB56CAA7, 32, NDPI_PROTOCOL_TOR },
+{ 0xCB56CD2E, 32, NDPI_PROTOCOL_TOR },
+{ 0xCB6DE90F, 32, NDPI_PROTOCOL_TOR },
+{ 0xCB71AC95, 32, NDPI_PROTOCOL_TOR },
+{ 0xCB71AC98, 32, NDPI_PROTOCOL_TOR },
+{ 0xCB71AC9A, 32, NDPI_PROTOCOL_TOR },
+{ 0xCB7B3001, 32, NDPI_PROTOCOL_TOR },
+{ 0xCB7E7B52, 32, NDPI_PROTOCOL_TOR },
+{ 0xCB8A63DA, 32, NDPI_PROTOCOL_TOR },
+{ 0xCB98C302, 32, NDPI_PROTOCOL_TOR },
+{ 0xCB99CEA6, 32, NDPI_PROTOCOL_TOR },
+{ 0xCBA16711, 32, NDPI_PROTOCOL_TOR },
+{ 0xCBB2850B, 32, NDPI_PROTOCOL_TOR },
+{ 0xCBCEEDC5, 32, NDPI_PROTOCOL_TOR },
+{ 0xCBD9AD92, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC089C8E, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC093747, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC0B3283, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC1025F4, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC11382A, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC11382A, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC1B382D, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC1B382D, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC1B3ACA, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC2D1E7A, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC2D1E7D, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC2DB6E2, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC534638, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC55BF1E, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC59C10A, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC7C5382, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC7C5382, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC7C5386, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC7C5386, 32, NDPI_PROTOCOL_TOR },
+{ 0xCC91512D, 32, NDPI_PROTOCOL_TOR },
+{ 0xCCC21D04, 32, NDPI_PROTOCOL_TOR },
+{ 0xCCF67A48, 32, NDPI_PROTOCOL_TOR },
+{ 0xCDA85485, 32, NDPI_PROTOCOL_TOR },
+{ 0xCDB973EA, 32, NDPI_PROTOCOL_TOR },
+{ 0xCDB97A98, 32, NDPI_PROTOCOL_TOR },
+{ 0xCE2876E5, 32, NDPI_PROTOCOL_TOR },
+{ 0xCE374A00, 32, NDPI_PROTOCOL_TOR },
+{ 0xCE374A01, 32, NDPI_PROTOCOL_TOR },
+{ 0xCE48C698, 32, NDPI_PROTOCOL_TOR },
+{ 0xCEAE7054, 32, NDPI_PROTOCOL_TOR },
+{ 0xCEBE9906, 32, NDPI_PROTOCOL_TOR },
+{ 0xCF268613, 32, NDPI_PROTOCOL_TOR },
+{ 0xCF6CDABA, 32, NDPI_PROTOCOL_TOR },
+{ 0xCF9E0F72, 32, NDPI_PROTOCOL_TOR },
+{ 0xCFACD159, 32, NDPI_PROTOCOL_TOR },
+{ 0xCFBD72D7, 32, NDPI_PROTOCOL_TOR },
+{ 0xCFC046FA, 32, NDPI_PROTOCOL_TOR },
+{ 0xCFC9DFC3, 32, NDPI_PROTOCOL_TOR },
+{ 0xCFC9DFC4, 32, NDPI_PROTOCOL_TOR },
+{ 0xCFC9DFC5, 32, NDPI_PROTOCOL_TOR },
+{ 0xCFE54199, 32, NDPI_PROTOCOL_TOR },
+{ 0xCFF44B8E, 32, NDPI_PROTOCOL_TOR },
+{ 0xCFF4526D, 32, NDPI_PROTOCOL_TOR },
+{ 0xCFF4526D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD041B5BD, 32, NDPI_PROTOCOL_TOR },
+{ 0xD0421E1B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD049CCE4, 32, NDPI_PROTOCOL_TOR },
+{ 0xD04FD17C, 32, NDPI_PROTOCOL_TOR },
+{ 0xD04FD34D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD0509A27, 32, NDPI_PROTOCOL_TOR },
+{ 0xD0526625, 32, NDPI_PROTOCOL_TOR },
+{ 0xD053DF22, 32, NDPI_PROTOCOL_TOR },
+{ 0xD053DFE5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD0549BCD, 32, NDPI_PROTOCOL_TOR },
+{ 0xD0549BF3, 32, NDPI_PROTOCOL_TOR },
+{ 0xD0549BF7, 32, NDPI_PROTOCOL_TOR },
+{ 0xD056FB58, 32, NDPI_PROTOCOL_TOR },
+{ 0xD05B798E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD065161A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD06F2350, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1063507, 32, NDPI_PROTOCOL_TOR },
+{ 0xD106441D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD10685EE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD111BF75, 32, NDPI_PROTOCOL_TOR },
+{ 0xD12C72B2, 32, NDPI_PROTOCOL_TOR },
+{ 0xD133A319, 32, NDPI_PROTOCOL_TOR },
+{ 0xD133BFBE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1709F3C, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC25, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC25, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC26, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC26, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC27, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC27, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC28, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC28, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC29, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC29, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC2A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD177BC2A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD17BA242, 32, NDPI_PROTOCOL_TOR },
+{ 0xD17E47E9, 32, NDPI_PROTOCOL_TOR },
+{ 0xD17E4854, 32, NDPI_PROTOCOL_TOR },
+{ 0xD17E6907, 32, NDPI_PROTOCOL_TOR },
+{ 0xD18D23E8, 32, NDPI_PROTOCOL_TOR },
+{ 0xD18D242A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD18D2ECC, 32, NDPI_PROTOCOL_TOR },
+{ 0xD18D328A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD18D34EF, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1942E81, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1942E82, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1942E82, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1945576, 32, NDPI_PROTOCOL_TOR },
+{ 0xD19F8A13, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1A221CF, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1B5E383, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1D01A29, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1D04F05, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1D2D215, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1DE08C4, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1DE1EF1, 32, NDPI_PROTOCOL_TOR },
+{ 0xD1FA02FE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD217021E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD23625E2, 32, NDPI_PROTOCOL_TOR },
+{ 0xD2A6194E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD2C33DFC, 32, NDPI_PROTOCOL_TOR },
+{ 0xD2D37ACC, 32, NDPI_PROTOCOL_TOR },
+{ 0xD2FBD989, 32, NDPI_PROTOCOL_TOR },
+{ 0xD31AF36D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD31C8EEF, 32, NDPI_PROTOCOL_TOR },
+{ 0xD31FC4F8, 32, NDPI_PROTOCOL_TOR },
+{ 0xD3CA291F, 32, NDPI_PROTOCOL_TOR },
+{ 0xD407C247, 32, NDPI_PROTOCOL_TOR },
+{ 0xD407DC06, 32, NDPI_PROTOCOL_TOR },
+{ 0xD40A5604, 32, NDPI_PROTOCOL_TOR },
+{ 0xD40CCB27, 32, NDPI_PROTOCOL_TOR },
+{ 0xD41010B8, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4106821, 32, NDPI_PROTOCOL_TOR },
+{ 0xD411664D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD41824CD, 32, NDPI_PROTOCOL_TOR },
+{ 0xD41890BC, 32, NDPI_PROTOCOL_TOR },
+{ 0xD421F581, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE209, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE3AC, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE3AC, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE445, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE459, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE5D1, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE5D1, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE745, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE784, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE80D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE8F6, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FE97E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FEA54, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FEB57, 32, NDPI_PROTOCOL_TOR },
+{ 0xD42FECDB, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4305435, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4339C5A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4339C8F, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4339C9E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4339C9E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4339F4E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4339F72, 32, NDPI_PROTOCOL_TOR },
+{ 0xD438D698, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4402044, 32, NDPI_PROTOCOL_TOR },
+{ 0xD447EECB, 32, NDPI_PROTOCOL_TOR },
+{ 0xD447F805, 32, NDPI_PROTOCOL_TOR },
+{ 0xD447F945, 32, NDPI_PROTOCOL_TOR },
+{ 0xD447F945, 32, NDPI_PROTOCOL_TOR },
+{ 0xD447F981, 32, NDPI_PROTOCOL_TOR },
+{ 0xD447FC6D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD447FC74, 32, NDPI_PROTOCOL_TOR },
+{ 0xD447FDE2, 32, NDPI_PROTOCOL_TOR },
+{ 0xD44AFEF3, 32, NDPI_PROTOCOL_TOR },
+{ 0xD44DE210, 32, NDPI_PROTOCOL_TOR },
+{ 0xD44DE2F5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4532F5B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD45394CD, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4539A21, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4539A21, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4539E05, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4539E14, 32, NDPI_PROTOCOL_TOR },
+{ 0xD453A298, 32, NDPI_PROTOCOL_TOR },
+{ 0xD453A7AF, 32, NDPI_PROTOCOL_TOR },
+{ 0xD453AAFC, 32, NDPI_PROTOCOL_TOR },
+{ 0xD453B07A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD453B07D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD453BECB, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4554F44, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4554F47, 32, NDPI_PROTOCOL_TOR },
+{ 0xD45CDB0F, 32, NDPI_PROTOCOL_TOR },
+{ 0xD467903A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD46A09CE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD46B9591, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4722F34, 32, NDPI_PROTOCOL_TOR },
+{ 0xD472303A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4726D21, 32, NDPI_PROTOCOL_TOR },
+{ 0xD472FA12, 32, NDPI_PROTOCOL_TOR },
+{ 0xD472FE5B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4758F4A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD475B46B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4763E03, 32, NDPI_PROTOCOL_TOR },
+{ 0xD47CB453, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4810454, 32, NDPI_PROTOCOL_TOR },
+{ 0xD48110B6, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4811AF6, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4812A09, 32, NDPI_PROTOCOL_TOR },
+{ 0xD48132F6, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4813431, 32, NDPI_PROTOCOL_TOR },
+{ 0xD495D15B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD49F5B16, 32, NDPI_PROTOCOL_TOR },
+{ 0xD49F70C4, 32, NDPI_PROTOCOL_TOR },
+{ 0xD49F8F53, 32, NDPI_PROTOCOL_TOR },
+{ 0xD49FB1C6, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4A4EF79, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4B733DE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4BA59A2, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4BBC8AA, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4C04A64, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4C04A65, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4C63318, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4C6C924, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4C6E391, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4E054E3, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4E059FD, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4E326F7, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4E38BC3, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4E3F876, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4E81D65, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4FAA0B2, 32, NDPI_PROTOCOL_TOR },
+{ 0xD4FAA0BB, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5095DAE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD52C58EA, 32, NDPI_PROTOCOL_TOR },
+{ 0xD52F2397, 32, NDPI_PROTOCOL_TOR },
+{ 0xD52F4B43, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5317328, 32, NDPI_PROTOCOL_TOR },
+{ 0xD53D957D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD53D957E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD540E2E6, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5430E91, 32, NDPI_PROTOCOL_TOR },
+{ 0xD54951D2, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5497087, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5582A31, 32, NDPI_PROTOCOL_TOR },
+{ 0xD55F1536, 32, NDPI_PROTOCOL_TOR },
+{ 0xD55F153B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD56B4D04, 32, NDPI_PROTOCOL_TOR },
+{ 0xD56C6947, 32, NDPI_PROTOCOL_TOR },
+{ 0xD56C69FD, 32, NDPI_PROTOCOL_TOR },
+{ 0xD56CD7EE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD56FF097, 32, NDPI_PROTOCOL_TOR },
+{ 0xD57086D3, 32, NDPI_PROTOCOL_TOR },
+{ 0xD570C73F, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5713D6A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5717790, 32, NDPI_PROTOCOL_TOR },
+{ 0xD571D5BE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5724869, 32, NDPI_PROTOCOL_TOR },
+{ 0xD57293E0, 32, NDPI_PROTOCOL_TOR },
+{ 0xD572966F, 32, NDPI_PROTOCOL_TOR },
+{ 0xD572E864, 32, NDPI_PROTOCOL_TOR },
+{ 0xD57F85A7, 32, NDPI_PROTOCOL_TOR },
+{ 0xD57F921B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD585639C, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5856D29, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5856DA5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5857B97, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58845ED, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5884715, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5884B2A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5885261, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5885674, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58857F5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5885A9B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5885CA9, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58A653C, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58A66D1, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58A6E58, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58A71E8, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58D8818, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58D8D93, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58D95E3, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58D9EED, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58E2E79, 32, NDPI_PROTOCOL_TOR },
+{ 0xD58F7A02, 32, NDPI_PROTOCOL_TOR },
+{ 0xD59B0490, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5A3482F, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5A348A2, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5A54610, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5A54F22, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5A54FF3, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5A55106, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5A5551E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5A55546, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5A555F9, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5AFD83B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5B39EF1, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5B73821, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5B7388C, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5B9E355, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5BA07E8, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5BB54BE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5BB6FFE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5BC77C9, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5C489E3, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5C5167C, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5C52469, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5D0BCCB, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5D3FC58, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5DE7461, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5E3FAF5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5EFC519, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5EFD329, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5EFD414, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5EFD6AF, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5EFD8DE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5EFD912, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5EFDA14, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5EFDA93, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5EFF9DB, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5F05E3A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5F06C19, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5F53D3D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5FBBB37, 32, NDPI_PROTOCOL_TOR },
+{ 0xD5FBC7AE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD80CC652, 32, NDPI_PROTOCOL_TOR },
+{ 0xD80CC653, 32, NDPI_PROTOCOL_TOR },
+{ 0xD80F0122, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8116382, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8116390, 32, NDPI_PROTOCOL_TOR },
+{ 0xD811654F, 32, NDPI_PROTOCOL_TOR },
+{ 0xD81169CB, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8116EE7, 32, NDPI_PROTOCOL_TOR },
+{ 0xD818AEF5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8425592, 32, NDPI_PROTOCOL_TOR },
+{ 0xD873031A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD873063A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD892E107, 32, NDPI_PROTOCOL_TOR },
+{ 0xD89A71F4, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8A13759, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8BAC1C9, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8BD9264, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8BD9575, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8BD9666, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8BD9718, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8C3851B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8DA860C, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8DAD8C2, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8DD24F4, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8E6E69C, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8E6E6F7, 32, NDPI_PROTOCOL_TOR },
+{ 0xD8F455D3, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90833AD, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90B39E2, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90B7727, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90CC7BE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90CC7D1, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90CCB2E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90CCC59, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90CCC68, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90CCC93, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90CD075, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90D4A29, 32, NDPI_PROTOCOL_TOR },
+{ 0xD90DC505, 32, NDPI_PROTOCOL_TOR },
+{ 0xD910B514, 32, NDPI_PROTOCOL_TOR },
+{ 0xD910B614, 32, NDPI_PROTOCOL_TOR },
+{ 0xD91318D8, 32, NDPI_PROTOCOL_TOR },
+{ 0xD91318E9, 32, NDPI_PROTOCOL_TOR },
+{ 0xD917011B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD91A1259, 32, NDPI_PROTOCOL_TOR },
+{ 0xD91BB67D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD92287E1, 32, NDPI_PROTOCOL_TOR },
+{ 0xD92287E7, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9251373, 32, NDPI_PROTOCOL_TOR },
+{ 0xD92855C2, 32, NDPI_PROTOCOL_TOR },
+{ 0xD928FEB1, 32, NDPI_PROTOCOL_TOR },
+{ 0xD943154D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD945FE58, 32, NDPI_PROTOCOL_TOR },
+{ 0xD946BD91, 32, NDPI_PROTOCOL_TOR },
+{ 0xD946BF0D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD948141E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD94FB23C, 32, NDPI_PROTOCOL_TOR },
+{ 0xD94FB532, 32, NDPI_PROTOCOL_TOR },
+{ 0xD94FB538, 32, NDPI_PROTOCOL_TOR },
+{ 0xD94FB65F, 32, NDPI_PROTOCOL_TOR },
+{ 0xD94FBE19, 32, NDPI_PROTOCOL_TOR },
+{ 0xD954FBD5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD95597B5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD95EEEF5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD970833A, 32, NDPI_PROTOCOL_TOR },
+{ 0xD97293F5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD972DA12, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9730A85, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9730A86, 32, NDPI_PROTOCOL_TOR },
+{ 0xD97729D5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD97BFEEE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD98090A0, 32, NDPI_PROTOCOL_TOR },
+{ 0xD991C735, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9924B24, 32, NDPI_PROTOCOL_TOR },
+{ 0xD99454B4, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9A0122D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9A013EC, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9A05C43, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9A07E32, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9A083B0, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9A276FE, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9AACD71, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9ACB392, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9ACBE13, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9ACBE13, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9ACFFE5, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9AD4A5B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9BCEA09, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9BDC5F4, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9BF49C3, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9BF6813, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9BFF274, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9C3AA91, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9C504DC, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9C553A2, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9C556AD, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9C55B91, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9C55B91, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9C55BA4, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9C5B52D, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9D075D3, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9D11257, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9D27158, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9D28C5F, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9D2A52B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9D39FA1, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9E40B41, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9E46874, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9E76B72, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9E94FC8, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9E94FC8, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9EA6B0B, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9F595B7, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9F63320, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9F76904, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9F7DE9C, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9F7E61F, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9F9203E, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9FBD765, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9FD96F6, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9FD9F48, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9FE3DAC, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9FE47CC, 32, NDPI_PROTOCOL_TOR },
+{ 0xD9FEB60F, 32, NDPI_PROTOCOL_TOR },
+{ 0xDAA1200E, 32, NDPI_PROTOCOL_TOR },
+{ 0xDAE7EBDB, 32, NDPI_PROTOCOL_TOR },
+{ 0xDAE868DC, 32, NDPI_PROTOCOL_TOR },
+{ 0xDAE868DD, 32, NDPI_PROTOCOL_TOR },
+{ 0xDAFAF536, 32, NDPI_PROTOCOL_TOR },
+{ 0xDB4F067A, 32, NDPI_PROTOCOL_TOR },
+{ 0xDB59C4CA, 32, NDPI_PROTOCOL_TOR },
+{ 0xDB6DCB40, 32, NDPI_PROTOCOL_TOR },
+{ 0xDB75CE2E, 32, NDPI_PROTOCOL_TOR },
+{ 0xDB791014, 32, NDPI_PROTOCOL_TOR },
+{ 0xDBA189F3, 32, NDPI_PROTOCOL_TOR },
+{ 0xDBA4C22E, 32, NDPI_PROTOCOL_TOR },
+{ 0xDBAD0E54, 32, NDPI_PROTOCOL_TOR },
+{ 0xDC39428E, 32, NDPI_PROTOCOL_TOR },
+{ 0xDC87FE3F, 32, NDPI_PROTOCOL_TOR },
+{ 0xDC898752, 32, NDPI_PROTOCOL_TOR },
+{ 0xDC9387F3, 32, NDPI_PROTOCOL_TOR },
+{ 0xDC9DC3F3, 32, NDPI_PROTOCOL_TOR },
+{ 0xDCE97BAC, 32, NDPI_PROTOCOL_TOR },
+{ 0xDCE9AF0E, 32, NDPI_PROTOCOL_TOR },
+{ 0xDCFD1CE1, 32, NDPI_PROTOCOL_TOR },
+{ 0xDCFF85C3, 32, NDPI_PROTOCOL_TOR },
+{ 0xDD7132CB, 32, NDPI_PROTOCOL_TOR },
+{ 0xDD9E95C5, 32, NDPI_PROTOCOL_TOR },
+{ 0xDE047C92, 32, NDPI_PROTOCOL_TOR },
+{ 0xDE0C7C9A, 32, NDPI_PROTOCOL_TOR },
+{ 0xDE7294F8, 32, NDPI_PROTOCOL_TOR },
+{ 0xDEEB761A, 32, NDPI_PROTOCOL_TOR },
+{ 0xDF1273E5, 32, NDPI_PROTOCOL_TOR },
+{ 0xDF85F4CA, 32, NDPI_PROTOCOL_TOR },
+{ 0xDFE57B41, 32, NDPI_PROTOCOL_TOR },
+{ 0x0, 0, 0 }
+};
+
+/* ****************************************************** */
+
+/*
+ Host-based match
+
+ HTTP: Server: field
+ HTTPS: Server certificate name
+ */
+
+ndpi_protocol_match host_match[] = {
+ { "amazon.", "Amazon", NDPI_SERVICE_AMAZON, NDPI_PROTOCOL_ACCEPTABLE },
+ { "amazon.com", "Amazon", NDPI_SERVICE_AMAZON, NDPI_PROTOCOL_ACCEPTABLE },
+ { "images-amazon.com", "Amazon", NDPI_SERVICE_AMAZON, NDPI_PROTOCOL_ACCEPTABLE },
+ { "amazonaws.com", "Amazon", NDPI_SERVICE_AMAZON, NDPI_PROTOCOL_ACCEPTABLE },
+ { "amazon-adsystem.com", "Amazon", NDPI_SERVICE_AMAZON, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".apple.com", "Apple", NDPI_SERVICE_APPLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".mzstatic.com", "Apple", NDPI_SERVICE_APPLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".icloud.com", "AppleiCloud", NDPI_SERVICE_APPLE_ICLOUD, NDPI_PROTOCOL_ACCEPTABLE },
+ { "itunes.apple.com", "AppleiTunes", NDPI_SERVICE_APPLE_ITUNES, NDPI_PROTOCOL_FUN },
+ { ".cnn.c", "CNN", NDPI_SERVICE_CNN, NDPI_PROTOCOL_FUN },
+ { ".cnn.net", "CNN", NDPI_SERVICE_CNN, NDPI_PROTOCOL_FUN },
+ { ".dropbox.com", "DropBox", NDPI_SERVICE_DROPBOX, NDPI_PROTOCOL_SAFE },
+ { ".ebay.com", "eBay", NDPI_SERVICE_EBAY, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".ebaystatic.com", "eBay", NDPI_SERVICE_EBAY, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".ebaydesc.com", "eBay", NDPI_SERVICE_EBAY, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".ebayrtm.com", "eBay", NDPI_SERVICE_EBAY, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".facebook.com", "Facebook", NDPI_SERVICE_FACEBOOK, NDPI_PROTOCOL_FUN },
+ { ".fbcdn.net", "Facebook", NDPI_SERVICE_FACEBOOK, NDPI_PROTOCOL_FUN },
+ { "fbcdn-", "Facebook", NDPI_SERVICE_FACEBOOK, NDPI_PROTOCOL_FUN }, /* fbcdn-video-a-akamaihd.net */
+ { ".gstatic.com", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".googlesyndication.com", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".googletagservices.com", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".2mdn.net", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".doubleclick.net", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE }, /* Ads */
+ { "googleads.", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { "google-analytics.", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { "googleusercontent.", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { "googleadservices.", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { "googleapis.com", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { "ggpht.com", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { "maps.google.", "GoogleMaps", NDPI_SERVICE_GOOGLE_MAPS, NDPI_PROTOCOL_ACCEPTABLE },
+ { "maps.gstatic.com", "GoogleMaps", NDPI_SERVICE_GOOGLE_MAPS, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".gmail.", "GMail", NDPI_SERVICE_GMAIL, NDPI_PROTOCOL_SAFE },
+ { "mail.google.", "GMail", NDPI_SERVICE_GMAIL, NDPI_PROTOCOL_SAFE },
+ { ".grooveshark.com", "GrooveShark", NDPI_SERVICE_GROOVESHARK, NDPI_PROTOCOL_FUN },
+ { ".last.fm", "LastFM", NDPI_SERVICE_LASTFM, NDPI_PROTOCOL_FUN },
+ { "msn.com", "MSN", NDPI_SERVICE_MSN, NDPI_PROTOCOL_FUN },
+ { "netflix.com", "NetFlix", NDPI_SERVICE_NETFLIX, NDPI_PROTOCOL_FUN },
+ { "nflxext.com", "NetFlix", NDPI_SERVICE_NETFLIX, NDPI_PROTOCOL_FUN },
+ { "nflximg.com", "NetFlix", NDPI_SERVICE_NETFLIX, NDPI_PROTOCOL_FUN },
+ { "nflximg.net", "NetFlix", NDPI_SERVICE_NETFLIX, NDPI_PROTOCOL_FUN },
+
+ { ".skype.", "Skype", NDPI_SERVICE_SKYPE, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".skypeassets.", "Skype", NDPI_SERVICE_SKYPE, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".skypedata.", "Skype", NDPI_SERVICE_SKYPE, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".skypeecs-", /* no final . */ "Skype", NDPI_SERVICE_SKYPE, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".tuenti.com", "Tuenti", NDPI_SERVICE_TUENTI, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".twttr.com", "Twitter", NDPI_SERVICE_TWITTER, NDPI_PROTOCOL_ACCEPTABLE },
+ { "twitter.", "Twitter", NDPI_SERVICE_TWITTER, NDPI_PROTOCOL_ACCEPTABLE },
+ { "twimg.com", "Twitter", NDPI_SERVICE_TWITTER, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".viber.com", "Viber", NDPI_SERVICE_VIBER, NDPI_PROTOCOL_ACCEPTABLE },
+ { "wikipedia.", "Wikipedia", NDPI_SERVICE_WIKIPEDIA, NDPI_PROTOCOL_ACCEPTABLE },
+ { "wikimedia.", "Wikipedia", NDPI_SERVICE_WIKIPEDIA, NDPI_PROTOCOL_ACCEPTABLE },
+ { "mediawiki.", "Wikipedia", NDPI_SERVICE_WIKIPEDIA, NDPI_PROTOCOL_ACCEPTABLE },
+ { "wikimediafoundation.", "Wikipedia", NDPI_SERVICE_WIKIPEDIA, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".whatsapp.net", "WhatsApp", NDPI_SERVICE_WHATSAPP, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".yahoo.", "Yahoo", NDPI_SERVICE_YAHOO, NDPI_PROTOCOL_ACCEPTABLE },
+ { "yimg.com", "Yahoo", NDPI_SERVICE_YAHOO, NDPI_PROTOCOL_ACCEPTABLE },
+ { "yahooapis.", "Yahoo", NDPI_SERVICE_YAHOO, NDPI_PROTOCOL_ACCEPTABLE },
+ { "youtube.", "YouTube", NDPI_SERVICE_YOUTUBE, NDPI_PROTOCOL_FUN },
+ { ".googlevideo.com", "YouTube", NDPI_SERVICE_YOUTUBE, NDPI_PROTOCOL_FUN },
+ { ".ytimg.com", "YouTube", NDPI_SERVICE_YOUTUBE, NDPI_PROTOCOL_FUN },
+ { "youtube-nocookie.", "YouTube", NDPI_SERVICE_YOUTUBE, NDPI_PROTOCOL_FUN },
+ { ".vevo.com", "Vevo", NDPI_SERVICE_VEVO, NDPI_PROTOCOL_FUN },
+ { ".google.", "Google", NDPI_SERVICE_GOOGLE, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".spotify.", "Spotify", NDPI_PROTOCOL_SPOTIFY, NDPI_PROTOCOL_FUN },
+ { ".pandora.com", "Pandora", NDPI_SERVICE_PANDORA, NDPI_PROTOCOL_FUN },
+ { ".torproject.org", "Tor", NDPI_PROTOCOL_TOR, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS },
+ { NULL, 0 }
+};
+
+
+/*
+ Mime-type content match match
+*/
+ndpi_protocol_match content_match[] = {
+ { "audio/mpeg", NULL, NDPI_CONTENT_MPEG, NDPI_PROTOCOL_FUN },
+ { "audio/x-mpeg", NULL, NDPI_CONTENT_MPEG, NDPI_PROTOCOL_FUN },
+ { "audio/mpeg3", NULL, NDPI_CONTENT_MPEG, NDPI_PROTOCOL_FUN },
+ { "audio/mp4a", NULL, NDPI_CONTENT_MPEG, NDPI_PROTOCOL_FUN },
+ { "video/mpeg", NULL, NDPI_CONTENT_MPEG, NDPI_PROTOCOL_FUN },
+ { "video/nsv", NULL, NDPI_CONTENT_MPEG, NDPI_PROTOCOL_FUN },
+ { "misc/ultravox", NULL, NDPI_CONTENT_MPEG, NDPI_PROTOCOL_FUN },
+ { "audio/ogg", NULL, NDPI_CONTENT_OGG, NDPI_PROTOCOL_FUN },
+ { "video/ogg", NULL, NDPI_CONTENT_OGG, NDPI_PROTOCOL_FUN },
+ { "application/ogg", NULL, NDPI_CONTENT_OGG, NDPI_PROTOCOL_FUN },
+ { "video/flv", NULL, NDPI_CONTENT_FLASH, NDPI_PROTOCOL_FUN },
+ { "video/x-flv", NULL, NDPI_CONTENT_FLASH, NDPI_PROTOCOL_FUN },
+ { "application/x-fcs", NULL, NDPI_CONTENT_FLASH, NDPI_PROTOCOL_FUN },
+ { "application/x-shockwave-flash", NULL, NDPI_CONTENT_FLASH, NDPI_PROTOCOL_ACCEPTABLE },
+ { "video/flash", NULL, NDPI_CONTENT_FLASH, NDPI_PROTOCOL_FUN },
+ { "application/flv", NULL, NDPI_CONTENT_FLASH, NDPI_PROTOCOL_FUN },
+ { "flv-application/octet-stream", NULL, NDPI_CONTENT_FLASH, NDPI_PROTOCOL_FUN },
+ { "application/futuresplash", NULL, NDPI_CONTENT_FLASH, NDPI_PROTOCOL_FUN },
+ { "video/quicktime", NULL, NDPI_CONTENT_QUICKTIME, NDPI_PROTOCOL_FUN },
+ { "video/mp4", NULL, NDPI_CONTENT_QUICKTIME, NDPI_PROTOCOL_FUN },
+ { "video/x-m4v", NULL, NDPI_CONTENT_QUICKTIME, NDPI_PROTOCOL_FUN },
+ { "audio/x-pn-realaudio", NULL, NDPI_CONTENT_REALMEDIA, NDPI_PROTOCOL_FUN },
+ { "application/vnd.rn-realmedia", NULL, NDPI_CONTENT_REALMEDIA, NDPI_PROTOCOL_FUN },
+ { "video/x-ms-", NULL, NDPI_CONTENT_WINDOWSMEDIA, NDPI_PROTOCOL_FUN },
+ { "asf", NULL, NDPI_CONTENT_WINDOWSMEDIA, NDPI_PROTOCOL_FUN },
+ { "asx", NULL, NDPI_CONTENT_WINDOWSMEDIA, NDPI_PROTOCOL_FUN },
+ { "video/x-msvideo", NULL, NDPI_CONTENT_WINDOWSMEDIA, NDPI_PROTOCOL_FUN },
+ { "audio/x-wav", NULL, NDPI_CONTENT_WINDOWSMEDIA, NDPI_PROTOCOL_FUN },
+ { "application/vnd.ms.wms-hdr.asfv1", NULL, NDPI_CONTENT_WINDOWSMEDIA, NDPI_PROTOCOL_FUN },
+ { "NSPlayer/", NULL, NDPI_CONTENT_WINDOWSMEDIA, NDPI_PROTOCOL_FUN },
+ { "application/x-mms-framed", NULL, NDPI_CONTENT_MMS, NDPI_PROTOCOL_FUN },
+ { "Xbox Live Client/", NULL, NDPI_PROTOCOL_XBOX, NDPI_PROTOCOL_FUN },
+ { "Windows-Update-Agent", NULL, NDPI_PROTOCOL_WINDOWS_UPDATE, NDPI_PROTOCOL_FUN },
+ { "audio/webm", NULL, NDPI_CONTENT_WEBM, NDPI_PROTOCOL_FUN },
+ { "video/webm", NULL, NDPI_CONTENT_WEBM, NDPI_PROTOCOL_FUN },
+ { "application/x-rtsp-tunnelled", NULL, NDPI_PROTOCOL_RTSP, NDPI_PROTOCOL_FUN },
+ { NULL, 0 }
+};
+
+/* ****************************************************** */
+
+/*
+ Tor
+ The tor protocol uses SSL to contact peers so it could be exchanged with
+ standard SSL. However the host names such as
+
+ - www.fgd2iwya7vinfutj5wq5we.com
+ - www.qbtxzhetq4s2f.com
+ - www.fgd2iwya7vinfutj5wq5we.net
+
+ In essence www.<name>.com|net
+
+ To do things properly we should check if host name in the certificate
+ exists or if the IP address of the SSL peer resolves to a name. Unfortunately
+ for performance reasons we can't afford to do a DNS lookup in nDPI (however apps
+ can do it if possible) and thus we have created a heuristic algorithm that tries
+ to check the host name (in the SSL certificate) to see if it looks like a
+ random name or a real name. We cannot use a dictionary (how can the kernel read a file?)
+ and this we use bigrams distribution to decide if the string looks like a
+ word or just random chars.
+
+ http://www3.nd.edu/~busiforc/handouts/cryptography/Letter%20Frequencies.html
+*/
+
+static const char *ndpi_en_bigrams[] = {
+ "aa", "ba", "ca", "da", "ea", "fa", "ga", "ha", "ia", "ja", "ka", "la", "ma", "na", "oa", "pa", "qa",
+ "ra", "sa", "ta", "ua", "va", "wa", "xa", "ya", "za", "ab", "bb", "db", "eb", "fb", "gb", "hb", "ib",
+ "kb", "lb", "mb", "nb", "ob", "pb", "rb", "sb", "tb", "ub", "wb", "yb", "ac", "bc", "cc", "dc", "ec",
+ "fc", "gc", "hc", "ic", "kc", "lc", "mc", "nc", "oc", "pc", "rc", "sc", "tc", "uc", "wc", "xc", "yc",
+ "ad", "bd", "cd", "dd", "ed", "fd", "gd", "hd", "id", "kd", "ld", "md", "nd", "od", "pd", "rd", "sd",
+ "td", "ud", "wd", "xd", "yd", "zd", "ae", "be", "ce", "de", "ee", "fe", "ge", "he", "ie", "je", "ke",
+ "le", "me", "ne", "oe", "pe", "re", "se", "te", "ue", "ve", "we", "xe", "ye", "ze", "af", "bf", "df",
+ "ef", "ff", "gf", "hf", "if", "kf", "lf", "mf", "nf", "of", "pf", "rf", "sf", "tf", "uf", "wf", "xf",
+ "yf", "zf", "ag", "bg", "dg", "eg", "fg", "gg", "hg", "ig", "kg", "lg", "ng", "og", "pg", "rg", "sg",
+ "tg", "ug", "wg", "yg", "ah", "bh", "ch", "dh", "eh", "fh", "gh", "hh", "ih", "kh", "lh", "mh", "nh",
+ "oh", "ph", "rh", "sh", "th", "uh", "wh", "xh", "yh", "ai", "bi", "ci", "di", "ei", "fi", "gi", "hi",
+ "ii", "ji", "ki", "li", "mi", "ni", "oi", "pi", "qi", "ri", "si", "ti", "ui", "vi", "wi", "xi", "yi",
+ "zi", "aj", "bj", "dj", "ej", "fj", "gj", "hj", "ij", "jj", "kj", "lj", "nj", "oj", "pj", "rj", "sj",
+ "tj", "uj", "wj", "yj", "ak", "ck", "dk", "ek", "gk", "ik", "kk", "lk", "mk", "nk", "ok", "pk", "rk",
+ "sk", "tk", "uk", "wk", "yk", "zk", "al", "bl", "cl", "dl", "el", "fl", "gl", "hl", "il", "kl", "ll",
+ "ml", "nl", "ol", "pl", "rl", "sl", "tl", "ul", "vl", "wl", "xl", "yl", "zl", "am", "bm", "cm", "dm",
+ "em", "fm", "gm", "hm", "im", "km", "lm", "mm", "nm", "om", "pm", "rm", "sm", "tm", "um", "wm", "xm",
+ "ym", "zm", "an", "bn", "cn", "dn", "en", "fn", "gn", "hn", "in", "kn", "ln", "mn", "nn", "on", "pn",
+ "rn", "sn", "tn", "un", "wn", "xn", "yn", "ao", "bo", "co", "do", "eo", "fo", "go", "ho", "io", "jo",
+ "ko", "lo", "mo", "no", "oo", "po", "ro", "so", "to", "uo", "vo", "wo", "xo", "yo", "zo", "ap", "bp",
+ "dp", "ep", "fp", "gp", "hp", "ip", "kp", "lp", "mp", "np", "op", "pp", "rp", "sp", "tp", "up", "wp",
+ "xp", "yp", "zp", "aq", "cq", "dq", "eq", "hq", "iq", "nq", "oq", "qq", "rq", "sq", "uq", "xq", "ar",
+ "br", "cr", "dr", "er", "fr", "gr", "hr", "ir", "kr", "lr", "mr", "nr", "or", "pr", "rr", "sr", "tr",
+ "ur", "vr", "wr", "xr", "yr", "as", "bs", "cs", "ds", "es", "fs", "gs", "hs", "is", "ks", "ls", "ms",
+ "ns", "os", "ps", "rs", "ss", "ts", "us", "vs", "ws", "xs", "ys", "at", "bt", "ct", "dt", "et", "ft",
+ "gt", "ht", "it", "kt", "lt", "mt", "nt", "ot", "pt", "rt", "st", "tt", "ut", "wt", "xt", "yt", "zt",
+ "au", "bu", "cu", "du", "eu", "fu", "gu", "hu", "iu", "ju", "ku", "lu", "mu", "nu", "ou", "pu", "qu",
+ "ru", "su", "tu", "uu", "vu", "wu", "xu", "yu", "zu", "av", "bv", "dv", "ev", "iv", "lv", "mv", "nv",
+ "ov", "rv", "sv", "tv", "uv", "vv", "zv", "aw", "bw", "dw", "ew", "fw", "gw", "hw", "iw", "kw", "lw",
+ "mw", "nw", "ow", "pw", "rw", "sw", "tw", "uw", "ww", "xw", "yw", "zw", "ax", "ex", "ix", "nx", "ox",
+ "rx", "ux", "xx", "yx", "ay", "by", "cy", "dy", "ey", "fy", "gy", "hy", "ky", "ly", "my", "ny", "oy",
+ "py", "ry", "sy", "ty", "uy", "vy", "wy", "xy", "yy", "zy", "az", "bz", "cz", "dz", "ez", "gz", "iz",
+ "lz", "nz", "oz", "pz", "rz", "tz", "uz", "zz", NULL };
+
+static const char *ndpi_en_impossible_bigrams[] = {
+ "bk", "bq", "bx", "cb", "cf", "cg", "cj", "cp", "cv", "cw", "cx", "dx", "fk", "fq", "fv", "fx", "ee",
+ "fz", "gq", "gv", "gx", "hh", "hk", "hv", "hx", "hz", "iy", "jb", "jc", "jd", "jf", "jg", "jh", "jk",
+ "jl", "jm", "jn", "jp", "jq", "jr", "js", "jt", "jv", "jw", "jx", "jy", "jz", "kg", "kq", "kv", "kx",
+ "kz", "lq", "lx", "mg", "mj", "mq", "mx", "mz", "pq", "pv", "px", "qb", "qc", "qd", "qe", "qf", "ii",
+ "qg", "qh", "qj", "qk", "ql", "qm", "qn", "qo", "qp", "qr", "qs", "qt", "qv", "qw", "qx", "qy", "uu",
+ "qz", "sx", "sz", "tq", "tx", "vb", "vc", "vd", "vf", "vg", "vh", "vj", "vk", "vm", "vn", "vp", "bw",
+ "vq", "vt", "vw", "vx", "vz", "wq", "wv", "wx", "wz", "xb", "xg", "xj", "xk", "xv", "xz", "xw", "yd", "yp",
+ "yj", "yq", "yv", "yz", "yw", "zb", "zc", "zg", "zh", "zj", "zn", "zq", "zr", "zs", "zx", "wh", "wk",
+ "wb", "zk", "kp", "zk", "xy",
+ NULL };
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
new file mode 100644
index 000000000..22892c474
--- /dev/null
+++ b/src/lib/ndpi_main.c
@@ -0,0 +1,5706 @@
+/*
+ * ndpi_main.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Copyright (C) 2009-11 - ipoque GmbH
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifndef __KERNEL__
+#include <stdlib.h>
+#include <errno.h>
+#endif
+
+#include "ahocorasick.h"
+#include "ndpi_api.h"
+
+
+#ifndef __KERNEL__
+#include "../../config.h"
+#endif
+
+// #define DEBUG
+
+#ifdef __KERNEL__
+#include <linux/version.h>
+#define printf printk
+#else
+#include <time.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+#endif
+
+#include "ndpi_content_match.c.inc"
+#include "third_party/include/patricia.h"
+#include "third_party/src/patricia.c"
+
+#ifdef WIN32
+/* http://social.msdn.microsoft.com/Forums/uk/vcgeneral/thread/963aac07-da1a-4612-be4a-faac3f1d65ca */
+#ifndef strtok_r
+#define strtok_r(a,b,c) strtok(a,b)
+#endif
+#endif
+
+#ifdef __KERNEL__
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
+static inline char _tolower(const char c)
+{
+ return c | 0x20;
+}
+
+static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
+{
+ unsigned long long acc;
+ int ok;
+
+ if(base == 0) {
+ if(s[0] == '0') {
+ if(_tolower(s[1]) == 'x' && isxdigit(s[2]))
+ base = 16;
+ else
+ base = 8;
+ } else
+ base = 10;
+ }
+ if(base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
+ s += 2;
+
+ acc = 0;
+ ok = 0;
+ while (*s) {
+ unsigned int val;
+
+ if('0' <= *s && *s <= '9')
+ val = *s - '0';
+ else if('a' <= _tolower(*s) && _tolower(*s) <= 'f')
+ val = _tolower(*s) - 'a' + 10;
+ else if(*s == '\n') {
+ if(*(s + 1) == '\0')
+ break;
+ else
+ return -EINVAL;
+ } else
+ return -EINVAL;
+
+ if(val >= base)
+ return -EINVAL;
+ if(acc > div_u64(ULLONG_MAX - val, base))
+ return -ERANGE;
+ acc = acc * base + val;
+ ok = 1;
+
+ s++;
+ }
+ if(!ok)
+ return -EINVAL;
+ *res = acc;
+ return 0;
+}
+
+int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
+{
+ if(s[0] == '+')
+ s++;
+ return _kstrtoull(s, base, res);
+}
+int kstrtoll(const char *s, unsigned int base, long long *res)
+{
+ unsigned long long tmp;
+ int rv;
+
+ if(s[0] == '-') {
+ rv = _kstrtoull(s + 1, base, &tmp);
+ if(rv < 0)
+ return rv;
+ if((long long)(-tmp) >= 0)
+ return -ERANGE;
+ *res = -tmp;
+ } else {
+ rv = kstrtoull(s, base, &tmp);
+ if(rv < 0)
+ return rv;
+ if((long long)tmp < 0)
+ return -ERANGE;
+ *res = tmp;
+ }
+ return 0;
+}
+int kstrtoint(const char *s, unsigned int base, int *res)
+{
+ long long tmp;
+ int rv;
+
+ rv = kstrtoll(s, base, &tmp);
+ if(rv < 0)
+ return rv;
+ if(tmp != (long long)(int)tmp)
+ return -ERANGE;
+ *res = tmp;
+ return 0;
+}
+#endif
+
+int atoi(const char *str) {
+ int rc;
+
+ if(kstrtoint(str, 0, &rc) == 0 /* Success */)
+ return(rc);
+ else
+ return(0);
+}
+#endif
+
+/* ftp://ftp.cc.uoc.gr/mirrors/OpenBSD/src/lib/libc/stdlib/tsearch.c */
+/* find or insert datum into search tree */
+void *
+ndpi_tsearch(const void *vkey, void **vrootp,
+ int (*compar)(const void *, const void *))
+{
+ ndpi_node *q;
+ char *key = (char *)vkey;
+ ndpi_node **rootp = (ndpi_node **)vrootp;
+
+ if(rootp == (ndpi_node **)0)
+ return ((void *)0);
+ while (*rootp != (ndpi_node *)0) { /* Knuth's T1: */
+ int r;
+
+ if((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
+ return ((void *)*rootp); /* we found it! */
+ rootp = (r < 0) ?
+ &(*rootp)->left : /* T3: follow left branch */
+ &(*rootp)->right; /* T4: follow right branch */
+ }
+ q = (ndpi_node *) ndpi_malloc(sizeof(ndpi_node)); /* T5: key not found */
+ if(q != (ndpi_node *)0) { /* make new node */
+ *rootp = q; /* link new node to old */
+ q->key = key; /* initialize new node */
+ q->left = q->right = (ndpi_node *)0;
+ }
+ return ((void *)q);
+}
+
+/* delete node with given key */
+void *
+ndpi_tdelete(const void *vkey, void **vrootp,
+ int (*compar)(const void *, const void *))
+{
+ ndpi_node **rootp = (ndpi_node **)vrootp;
+ char *key = (char *)vkey;
+ ndpi_node *p = (ndpi_node *)1;
+ ndpi_node *q;
+ ndpi_node *r;
+ int cmp;
+
+ if(rootp == (ndpi_node **)0 || *rootp == (ndpi_node *)0)
+ return ((ndpi_node *)0);
+ while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
+ p = *rootp;
+ rootp = (cmp < 0) ?
+ &(*rootp)->left : /* follow left branch */
+ &(*rootp)->right; /* follow right branch */
+ if(*rootp == (ndpi_node *)0)
+ return ((void *)0); /* key not found */
+ }
+ r = (*rootp)->right; /* D1: */
+ if((q = (*rootp)->left) == (ndpi_node *)0) /* Left (ndpi_node *)0? */
+ q = r;
+ else if(r != (ndpi_node *)0) { /* Right link is null? */
+ if(r->left == (ndpi_node *)0) { /* D2: Find successor */
+ r->left = q;
+ q = r;
+ } else { /* D3: Find (ndpi_node *)0 link */
+ for (q = r->left; q->left != (ndpi_node *)0; q = r->left)
+ r = q;
+ r->left = q->right;
+ q->left = (*rootp)->left;
+ q->right = (*rootp)->right;
+ }
+ }
+ ndpi_free((ndpi_node *) *rootp); /* D4: Free node */
+ *rootp = q; /* link parent to new node */
+ return(p);
+}
+
+/* Walk the nodes of a tree */
+static void
+ndpi_trecurse(ndpi_node *root, void (*action)(const void *, ndpi_VISIT, int, void*), int level, void *user_data)
+{
+ if(root->left == (ndpi_node *)0 && root->right == (ndpi_node *)0)
+ (*action)(root, ndpi_leaf, level, user_data);
+ else {
+ (*action)(root, ndpi_preorder, level, user_data);
+ if(root->left != (ndpi_node *)0)
+ ndpi_trecurse(root->left, action, level + 1, user_data);
+ (*action)(root, ndpi_postorder, level, user_data);
+ if(root->right != (ndpi_node *)0)
+ ndpi_trecurse(root->right, action, level + 1, user_data);
+ (*action)(root, ndpi_endorder, level, user_data);
+ }
+}
+
+/* Walk the nodes of a tree */
+void
+ndpi_twalk(const void *vroot, void (*action)(const void *, ndpi_VISIT, int, void *), void *user_data)
+{
+ ndpi_node *root = (ndpi_node *)vroot;
+
+ if(root != (ndpi_node *)0 && action != (void (*)(const void *, ndpi_VISIT, int, void*))0)
+ ndpi_trecurse(root, action, 0, user_data);
+}
+
+/* find a node, or return 0 */
+void *
+ndpi_tfind(const void *vkey, void *vrootp,
+ int (*compar)(const void *, const void *))
+{
+ char *key = (char *)vkey;
+ ndpi_node **rootp = (ndpi_node **)vrootp;
+
+ if(rootp == (ndpi_node **)0)
+ return ((ndpi_node *)0);
+ while (*rootp != (ndpi_node *)0) { /* T1: */
+ int r;
+ if((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
+ return (*rootp); /* key found */
+ rootp = (r < 0) ?
+ &(*rootp)->left : /* T3: follow left branch */
+ &(*rootp)->right; /* T4: follow right branch */
+ }
+ return (ndpi_node *)0;
+}
+
+/* ****************************************** */
+
+/* Walk the nodes of a tree */
+static void ndpi_tdestroy_recurse(ndpi_node* root, void (*free_action)(void *)) {
+ if(root->left != NULL)
+ ndpi_tdestroy_recurse(root->left, free_action);
+ if(root->right != NULL)
+ ndpi_tdestroy_recurse(root->right, free_action);
+
+ (*free_action) ((void *) root->key);
+ ndpi_free(root);
+}
+
+void ndpi_tdestroy(void *vrootp, void (*freefct)(void *)) {
+ ndpi_node *root = (ndpi_node *) vrootp;
+
+ if(root != NULL)
+ ndpi_tdestroy_recurse(root, freefct);
+}
+
+/* ****************************************** */
+
+u_int8_t ndpi_net_match(u_int32_t ip_to_check,
+ u_int32_t net,
+ u_int32_t num_bits) {
+ u_int32_t mask = 0;
+
+ mask = ~(~mask >> num_bits);
+
+ return(((ip_to_check & mask) == (net & mask)) ? 1 : 0);
+}
+
+u_int8_t ndpi_ips_match(u_int32_t src, u_int32_t dst,
+ u_int32_t net, u_int32_t num_bits) {
+ return(ndpi_net_match(src, net, num_bits) || ndpi_net_match(dst, net, num_bits));
+}
+
+/* ****************************************** */
+
+static void *(*_ndpi_malloc)(unsigned long size);
+static void (*_ndpi_free)(void *ptr);
+
+/* ****************************************** */
+
+#ifdef WIN32
+/* http://opensource.apple.com/source/Libc/Libc-186/string.subproj/strcasecmp.c */
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison. The mappings are
+ * based upon ascii character sequences.
+ */
+static const u_char charmap[] = {
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+ '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+ '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+ '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+ '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+ '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+ '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+ '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+ '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+ '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
+ '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
+ '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
+ '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
+ '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+int
+strcasecmp(s1, s2)
+ const char *s1, *s2;
+{
+ register const u_char *cm = charmap,
+ *us1 = (const u_char *)s1,
+ *us2 = (const u_char *)s2;
+
+ while (cm[*us1] == cm[*us2++])
+ if(*us1++ == '\0')
+ return (0);
+ return (cm[*us1] - cm[*--us2]);
+}
+
+int
+strncasecmp(s1, s2, n)
+ const char *s1, *s2;
+ register size_t n;
+{
+ if(n != 0) {
+ register const u_char *cm = charmap,
+ *us1 = (const u_char *)s1,
+ *us2 = (const u_char *)s2;
+
+ do {
+ if(cm[*us1] != cm[*us2++])
+ return (cm[*us1] - cm[*--us2]);
+ if(*us1++ == '\0')
+ break;
+ } while (--n != 0);
+ }
+ return (0);
+}
+
+#endif
+
+/* ****************************************** */
+
+/* Forward */
+static void addDefaultPort(ndpi_port_range *range,
+ ndpi_proto_defaults_t *def, ndpi_default_ports_tree_node_t **root);
+static int removeDefaultPort(ndpi_port_range *range,
+ ndpi_proto_defaults_t *def, ndpi_default_ports_tree_node_t **root);
+
+/* ****************************************** */
+
+void* ndpi_malloc(unsigned long size) { return(_ndpi_malloc(size)); }
+
+/* ****************************************** */
+
+void* ndpi_calloc(unsigned long count, unsigned long size) {
+ unsigned long len = count*size;
+ void *p = ndpi_malloc(len);
+
+ if(p)
+ memset(p, 0, len);
+
+ return(p);
+}
+
+/* ****************************************** */
+
+void ndpi_free(void *ptr) { _ndpi_free(ptr); }
+
+/* ****************************************** */
+
+void *ndpi_realloc(void *ptr, size_t old_size, size_t new_size) {
+ void *ret = ndpi_malloc(new_size);
+
+ if(!ret)
+ return(ret);
+ else {
+ memcpy(ret, ptr, old_size);
+ ndpi_free(ptr);
+ return(ret);
+ }
+}
+/* ****************************************** */
+
+char *ndpi_strdup(const char *s) {
+ int len = strlen(s);
+ char *m = ndpi_malloc(len+1);
+
+ if(m) {
+ memcpy(m, s, len);
+ m[len] = '\0';
+ }
+
+ return(m);
+}
+
+/* ****************************************** */
+
+u_int32_t ndpi_detection_get_sizeof_ndpi_flow_struct(void)
+{
+ return sizeof(struct ndpi_flow_struct);
+}
+
+/* ****************************************** */
+
+u_int32_t ndpi_detection_get_sizeof_ndpi_id_struct(void)
+{
+ return sizeof(struct ndpi_id_struct);
+}
+
+/* ******************************************************************** */
+
+char* ndpi_get_proto_by_id(struct ndpi_detection_module_struct *ndpi_mod, u_int id) {
+ return((id >= ndpi_mod->ndpi_num_supported_protocols) ? NULL : ndpi_mod->proto_defaults[id].protoName);
+}
+
+/* ******************************************************************** */
+
+ndpi_port_range* ndpi_build_default_ports_range(ndpi_port_range *ports,
+ u_int16_t portA_low, u_int16_t portA_high,
+ u_int16_t portB_low, u_int16_t portB_high,
+ u_int16_t portC_low, u_int16_t portC_high,
+ u_int16_t portD_low, u_int16_t portD_high,
+ u_int16_t portE_low, u_int16_t portE_high) {
+ int i = 0;
+
+ ports[i].port_low = portA_low, ports[i].port_high = portA_high; i++;
+ ports[i].port_low = portB_low, ports[i].port_high = portB_high; i++;
+ ports[i].port_low = portC_low, ports[i].port_high = portC_high; i++;
+ ports[i].port_low = portD_low, ports[i].port_high = portD_high; i++;
+ ports[i].port_low = portE_low, ports[i].port_high = portE_high; i++;
+
+ return(ports);
+}
+
+/* ******************************************************************** */
+
+ndpi_port_range* ndpi_build_default_ports(ndpi_port_range *ports,
+ u_int16_t portA,
+ u_int16_t portB,
+ u_int16_t portC,
+ u_int16_t portD,
+ u_int16_t portE) {
+ int i = 0;
+
+ ports[i].port_low = portA, ports[i].port_high = portA; i++;
+ ports[i].port_low = portB, ports[i].port_high = portB; i++;
+ ports[i].port_low = portC, ports[i].port_high = portC; i++;
+ ports[i].port_low = portD, ports[i].port_high = portD; i++;
+ ports[i].port_low = portE, ports[i].port_high = portE; i++;
+
+ return(ports);
+}
+
+/* ******************************************************************** */
+
+void ndpi_set_proto_defaults(struct ndpi_detection_module_struct *ndpi_mod,
+ ndpi_protocol_breed_t breed, u_int16_t protoId,
+ u_int16_t tcp_master_protoId[2], u_int16_t udp_master_protoId[2],
+ char *protoName,
+ ndpi_port_range *tcpDefPorts, ndpi_port_range *udpDefPorts) {
+ char *name = ndpi_strdup(protoName);
+ int j;
+
+ if(protoId >= NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS) {
+ printf("[NDPI] %s(protoId=%d): INTERNAL ERROR\n", __FUNCTION__, protoId);
+ ndpi_free(name);
+ return;
+ }
+
+ ndpi_mod->proto_defaults[protoId].protoName = name,
+ ndpi_mod->proto_defaults[protoId].protoId = protoId,
+ ndpi_mod->proto_defaults[protoId].protoBreed = breed;
+
+ memcpy(&ndpi_mod->proto_defaults[protoId].master_tcp_protoId, tcp_master_protoId, 2*sizeof(u_int16_t));
+ memcpy(&ndpi_mod->proto_defaults[protoId].master_udp_protoId, udp_master_protoId, 2*sizeof(u_int16_t));
+
+ for(j=0; j<MAX_DEFAULT_PORTS; j++) {
+ if(udpDefPorts[j].port_low != 0) addDefaultPort(&udpDefPorts[j], &ndpi_mod->proto_defaults[protoId], &ndpi_mod->udpRoot);
+ if(tcpDefPorts[j].port_low != 0) addDefaultPort(&tcpDefPorts[j], &ndpi_mod->proto_defaults[protoId], &ndpi_mod->tcpRoot);
+ }
+
+#if 0
+ printf("%s(%d, %s, %p) [%s]\n",
+ __FUNCTION__,
+ protoId,
+ ndpi_mod->proto_defaults[protoId].protoName,
+ ndpi_mod,
+ ndpi_mod->proto_defaults[1].protoName);
+#endif
+}
+
+/* ******************************************************************** */
+
+static int ndpi_default_ports_tree_node_t_cmp(const void *a, const void *b) {
+ ndpi_default_ports_tree_node_t *fa = (ndpi_default_ports_tree_node_t*)a;
+ ndpi_default_ports_tree_node_t *fb = (ndpi_default_ports_tree_node_t*)b;
+
+ //printf("[NDPI] %s(%d, %d)\n", __FUNCTION__, fa->default_port, fb->default_port);
+
+ return((fa->default_port == fb->default_port) ? 0 : ((fa->default_port < fb->default_port) ? -1 : 1));
+}
+
+/* ******************************************************************** */
+
+void ndpi_default_ports_tree_node_t_walker(const void *node, const ndpi_VISIT which, const int depth) {
+ ndpi_default_ports_tree_node_t *f = *(ndpi_default_ports_tree_node_t **)node;
+
+
+ printf("<%d>Walk on node %s (%u)\n",
+ depth,
+ which == ndpi_preorder?"ndpi_preorder":
+ which == ndpi_postorder?"ndpi_postorder":
+ which == ndpi_endorder?"ndpi_endorder":
+ which == ndpi_leaf?"ndpi_leaf": "unknown",
+ f->default_port);
+}
+
+/* ******************************************************************** */
+
+static void addDefaultPort(ndpi_port_range *range,
+ ndpi_proto_defaults_t *def, ndpi_default_ports_tree_node_t **root) {
+ ndpi_default_ports_tree_node_t *ret;
+ u_int16_t port;
+
+ // printf("[NDPI] %s(%d)\n", __FUNCTION__, port);
+
+ for(port=range->port_low; port<=range->port_high; port++) {
+ ndpi_default_ports_tree_node_t *node = (ndpi_default_ports_tree_node_t*)ndpi_malloc(sizeof(ndpi_default_ports_tree_node_t));
+
+ if(!node) {
+ printf("[NDPI] %s(): not enough memory\n", __FUNCTION__);
+ break;
+ }
+
+ node->proto = def, node->default_port = port;
+ ret = *(ndpi_default_ports_tree_node_t**)ndpi_tsearch(node, (void*)root, ndpi_default_ports_tree_node_t_cmp); /* Add it to the tree */
+
+ if(ret != node) {
+ printf("[NDPI] %s(): found duplicate for port %u: overwriting it with new value\n", __FUNCTION__, port);
+
+ ret->proto = def;
+ ndpi_free(node);
+ }
+ }
+}
+
+/* ****************************************************** */
+
+/*
+ NOTE
+
+ This function must be called with a semaphore set, this in order to avoid
+ changing the datastrutures while using them
+*/
+static int removeDefaultPort(ndpi_port_range *range,
+ ndpi_proto_defaults_t *def,
+ ndpi_default_ports_tree_node_t **root) {
+ ndpi_default_ports_tree_node_t node;
+ ndpi_default_ports_tree_node_t *ret;
+ u_int16_t port;
+
+ for(port=range->port_low; port<=range->port_high; port++) {
+ node.proto = def, node.default_port = port;
+ ret = *(ndpi_default_ports_tree_node_t**)ndpi_tdelete(&node, (void*)root,
+ ndpi_default_ports_tree_node_t_cmp); /* Add it to the tree */
+
+ if(ret != NULL) {
+ ndpi_free((ndpi_default_ports_tree_node_t*)ret);
+ return(0);
+ }
+ }
+
+ return(-1);
+}
+
+/* ****************************************************** */
+
+static int ndpi_string_to_automa(struct ndpi_detection_module_struct *ndpi_struct,
+ ndpi_automa *automa,
+ char *value, int protocol_id,
+ ndpi_protocol_breed_t breed) {
+ AC_PATTERN_t ac_pattern;
+
+ if(protocol_id >= (NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) {
+ printf("[NDPI] %s(protoId=%d): INTERNAL ERROR\n", __FUNCTION__, protocol_id);
+ return(-1);
+ }
+
+ if(automa->ac_automa == NULL) return(-2);
+ ac_pattern.astring = value;
+ ac_pattern.rep.number = protocol_id;
+ ac_pattern.length = strlen(ac_pattern.astring);
+ ac_automata_add(((AC_AUTOMATA_t*)automa->ac_automa), &ac_pattern);
+
+ return(0);
+}
+
+/* ****************************************************** */
+
+static int ndpi_add_host_url_subprotocol(struct ndpi_detection_module_struct *ndpi_struct,
+ char *value, int protocol_id,
+ ndpi_protocol_breed_t breed) {
+ return(ndpi_string_to_automa(ndpi_struct, &ndpi_struct->host_automa,
+ value, protocol_id, breed));
+}
+
+/* ****************************************************** */
+
+int ndpi_add_content_subprotocol(struct ndpi_detection_module_struct *ndpi_struct,
+ char *value, int protocol_id,
+ ndpi_protocol_breed_t breed) {
+ return(ndpi_string_to_automa(ndpi_struct, &ndpi_struct->content_automa, value, protocol_id, breed));
+}
+
+/* ****************************************************** */
+
+/*
+ NOTE
+
+ This function must be called with a semaphore set, this in order to avoid
+ changing the datastrutures while using them
+*/
+static int ndpi_remove_host_url_subprotocol(struct ndpi_detection_module_struct *ndpi_struct,
+ char *value, int protocol_id) {
+
+ printf("[NDPI] Missing implementation of %s()\n", __FUNCTION__);
+ return(-1);
+}
+
+/* ******************************************************************** */
+
+static void init_string_based_protocols(struct ndpi_detection_module_struct *ndpi_mod) {
+ int i;
+
+ for(i=0; host_match[i].string_to_match != NULL; i++) {
+ ndpi_add_host_url_subprotocol(ndpi_mod, host_match[i].string_to_match,
+ host_match[i].protocol_id, host_match[i].protocol_breed);
+
+ if(ndpi_mod->proto_defaults[host_match[i].protocol_id].protoName == NULL) {
+ ndpi_mod->proto_defaults[host_match[i].protocol_id].protoName = ndpi_strdup(host_match[i].proto_name);
+ ndpi_mod->proto_defaults[host_match[i].protocol_id].protoId = host_match[i].protocol_id;
+ ndpi_mod->proto_defaults[host_match[i].protocol_id].protoBreed = host_match[i].protocol_breed;
+ }
+ }
+
+ for(i=0; content_match[i].string_to_match != NULL; i++)
+ ndpi_add_content_subprotocol(ndpi_mod, content_match[i].string_to_match,
+ content_match[i].protocol_id,
+ content_match[i].protocol_breed);
+
+ for(i=0; ndpi_en_bigrams[i] != NULL; i++)
+ ndpi_string_to_automa(ndpi_mod, &ndpi_mod->bigrams_automa,
+ (char*)ndpi_en_bigrams[i],
+ 1, NDPI_PROTOCOL_UNRATED);
+
+ for(i=0; ndpi_en_impossible_bigrams[i] != NULL; i++)
+ ndpi_string_to_automa(ndpi_mod, &ndpi_mod->impossible_bigrams_automa,
+ (char*)ndpi_en_impossible_bigrams[i],
+ 1, NDPI_PROTOCOL_UNRATED);
+}
+
+/* ******************************************************************** */
+
+/* This function is used to map protocol name and default ports and it MUST
+ be updated whenever a new protocol is added to NDPI.
+
+ Do NOT add web services (NDPI_SERVICE_xxx) here.
+*/
+static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndpi_mod) {
+ int i;
+ ndpi_port_range ports_a[MAX_DEFAULT_PORTS], ports_b[MAX_DEFAULT_PORTS];
+ u_int16_t no_master[2] = { NDPI_PROTOCOL_NO_MASTER_PROTO, NDPI_PROTOCOL_NO_MASTER_PROTO },
+ custom_master[2], custom_master1[2];
+
+ /* Reset all settings */
+ memset(ndpi_mod->proto_defaults, 0, sizeof(ndpi_mod->proto_defaults));
+
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNRATED, NDPI_PROTOCOL_UNKNOWN,
+ no_master,
+ no_master, "Unknown",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_FTP_CONTROL,
+ no_master,
+ no_master, "FTP_CONTROL",
+ ndpi_build_default_ports(ports_a, 21, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_FTP_DATA,
+ no_master,
+ no_master, "FTP_DATA",
+ ndpi_build_default_ports(ports_a, 20, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_MAIL_POP,
+ no_master,
+ no_master, "POP3",
+ ndpi_build_default_ports(ports_a, 110, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_MAIL_POPS,
+ no_master,
+ no_master, "POPS",
+ ndpi_build_default_ports(ports_a, 995, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_MAIL_SMTP,
+ no_master,
+ no_master, "SMTP",
+ ndpi_build_default_ports(ports_a, 25, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_MAIL_SMTPS,
+ no_master,
+ no_master, "SMTPS",
+ ndpi_build_default_ports(ports_a, 465, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_MAIL_IMAP,
+ no_master,
+ no_master, "IMAP",
+ ndpi_build_default_ports(ports_a, 143, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_MAIL_IMAPS,
+ no_master,
+ no_master, "IMAPS",
+ ndpi_build_default_ports(ports_a, 993, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DNS,
+ no_master,
+ no_master, "DNS",
+ ndpi_build_default_ports(ports_a, 53, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 53, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IPP,
+ no_master,
+ no_master, "IPP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_HTTP,
+ no_master,
+ no_master, "HTTP",
+ ndpi_build_default_ports(ports_a, 80, 0 /* ntop */, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MDNS,
+ no_master,
+ no_master, "MDNS",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 5353, 5354, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NTP,
+ no_master,
+ no_master, "NTP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 123, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NETBIOS,
+ no_master,
+ no_master, "NetBIOS",
+ ndpi_build_default_ports(ports_a, 139, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 137, 138, 139, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NFS,
+ no_master,
+ no_master, "NFS",
+ ndpi_build_default_ports(ports_a, 2049, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 2049, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SSDP,
+ no_master,
+ no_master, "SSDP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_BGP,
+ no_master,
+ no_master, "BGP",
+ ndpi_build_default_ports(ports_a, 2605, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SNMP,
+ no_master,
+ no_master, "SNMP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 161, 162, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_XDMCP,
+ no_master,
+ no_master, "XDMCP",
+ ndpi_build_default_ports(ports_a, 177, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 177, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SMB,
+ no_master,
+ no_master, "SMB",
+ ndpi_build_default_ports(ports_a, 445, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SYSLOG,
+ no_master,
+ no_master, "Syslog",
+ ndpi_build_default_ports(ports_a, 514, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 514, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DHCP,
+ no_master,
+ no_master, "DHCP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 67, 68, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_POSTGRES,
+ no_master,
+ no_master, "PostgreSQL",
+ ndpi_build_default_ports(ports_a, 5432, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MYSQL,
+ no_master,
+ no_master, "MySQL",
+ ndpi_build_default_ports(ports_a, 3306, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNRATED, NDPI_PROTOCOL_TDS,
+ no_master,
+ no_master, "TDS",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK,
+ no_master,
+ no_master, "Direct_Download_Link",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_APPLEJUICE,
+ no_master,
+ no_master, "AppleJuice",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_DIRECTCONNECT,
+ no_master,
+ no_master, "DirectConnect",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_SOCRATES,
+ no_master,
+ no_master, "Socrates",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_WINMX,
+ no_master,
+ no_master, "WinMX",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_VMWARE,
+ no_master,
+ no_master, "VMware",
+ ndpi_build_default_ports(ports_a, 903, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 902, 903, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_FILETOPIA,
+ no_master,
+ no_master, "Filetopia",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_IMESH,
+ no_master,
+ no_master, "iMESH",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_KONTIKI,
+ no_master,
+ no_master, "Kontiki",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_OPENFT,
+ no_master,
+ no_master, "OpenFT",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_FASTTRACK,
+ no_master,
+ no_master, "FastTrack",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_GNUTELLA,
+ no_master,
+ no_master, "Gnutella",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_EDONKEY,
+ no_master,
+ no_master, "eDonkey",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_BITTORRENT,
+ no_master,
+ no_master, "BitTorrent",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_EPP,
+ no_master,
+ no_master, "EPP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_CONTENT_AVI,
+ no_master,
+ no_master, "AVI",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_CONTENT_FLASH,
+ no_master,
+ no_master, "Flash",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_CONTENT_OGG,
+ no_master,
+ no_master, "OggVorbis",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_CONTENT_MPEG,
+ no_master,
+ no_master, "MPEG",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_CONTENT_QUICKTIME,
+ no_master,
+ no_master, "QuickTime",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_CONTENT_REALMEDIA,
+ no_master,
+ no_master, "RealMedia",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_CONTENT_WINDOWSMEDIA,
+ no_master,
+ no_master, "WindowsMedia",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_CONTENT_MMS,
+ no_master,
+ no_master, "MMS",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_XBOX,
+ no_master,
+ no_master, "Xbox",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_QQ,
+ no_master,
+ no_master, "QQ",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_MOVE,
+ no_master,
+ no_master, "Move",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_RTSP,
+ no_master,
+ no_master, "RTSP",
+ ndpi_build_default_ports(ports_a, 554, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 554, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_ICECAST,
+ no_master,
+ no_master, "IceCast",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_PPLIVE,
+ no_master,
+ no_master, "PPLive",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_PPSTREAM,
+ no_master,
+ no_master, "PPStream",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_ZATTOO,
+ no_master,
+ no_master, "Zattoo",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_SHOUTCAST,
+ no_master,
+ no_master, "ShoutCast",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_SOPCAST,
+ no_master,
+ no_master, "Sopcast",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_TVANTS,
+ no_master,
+ no_master, "Tvants",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_TVUPLAYER,
+ no_master,
+ no_master, "TVUplayer",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV,
+ no_master,
+ no_master, "HTTP_APPLICATION_VEOHTV",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_QQLIVE,
+ no_master,
+ no_master, "QQLive",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_THUNDER,
+ no_master,
+ no_master, "Thunder",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_SOULSEEK,
+ no_master,
+ no_master, "Soulseek",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+
+ custom_master[0] = NDPI_PROTOCOL_SSL, custom_master[1] = NDPI_PROTOCOL_UNKNOWN;
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SSL_NO_CERT,
+ custom_master, no_master, "SSL_No_Cert",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IRC,
+ no_master,
+ no_master, "IRC",
+ ndpi_build_default_ports(ports_a, 194, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 194, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_AYIYA,
+ no_master,
+ no_master, "Ayiya",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 5072, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_UNENCRYPED_JABBER,
+ no_master,
+ no_master, "Unencryped_Jabber",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MSN,
+ no_master,
+ no_master, "MSN",
+ ndpi_build_default_ports(ports_a, 1863, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_OSCAR,
+ no_master,
+ no_master, "Oscar",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_YAHOO,
+ no_master,
+ no_master, "Yahoo",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_BATTLEFIELD,
+ no_master,
+ no_master, "BattleField",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_QUAKE,
+ no_master,
+ no_master, "Quake",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_VRRP,
+ no_master,
+ no_master, "VRRP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_STEAM,
+ no_master,
+ no_master, "Steam",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_HALFLIFE2,
+ no_master,
+ no_master, "HalfLife2",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_WORLDOFWARCRAFT,
+ no_master,
+ no_master, "WorldOfWarcraft",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_TELNET,
+ no_master,
+ no_master, "Telnet",
+ ndpi_build_default_ports(ports_a, 23, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+
+ custom_master[0] = NDPI_PROTOCOL_SIP, custom_master[1] = NDPI_PROTOCOL_H323;
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_STUN,
+ no_master, custom_master, "STUN",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_IP_IPSEC,
+ no_master,
+ no_master, "IPsec",
+ ndpi_build_default_ports(ports_a, 500, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 500, 4500, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_GRE,
+ no_master,
+ no_master, "GRE",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_ICMP,
+ no_master,
+ no_master, "ICMP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_IGMP,
+ no_master,
+ no_master, "IGMP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_EGP,
+ no_master,
+ no_master, "EGP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_SCTP,
+ no_master,
+ no_master, "SCTP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_OSPF,
+ no_master,
+ no_master, "OSPF",
+ ndpi_build_default_ports(ports_a, 2604, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_IP_IN_IP,
+ no_master,
+ no_master, "IP_in_IP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RTP,
+ no_master,
+ no_master, "RTP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RDP,
+ no_master,
+ no_master, "RDP",
+ ndpi_build_default_ports(ports_a, 3389, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_VNC,
+ no_master,
+ no_master, "VNC",
+ ndpi_build_default_ports(ports_a, 5900, 5901, 5800, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_PCANYWHERE,
+ no_master,
+ no_master, "PcAnywhere",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+
+ custom_master[0] = NDPI_PROTOCOL_SSL_NO_CERT, custom_master[1] = NDPI_PROTOCOL_UNKNOWN;
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_SSL,
+ no_master, custom_master, "SSL",
+ ndpi_build_default_ports(ports_a, 443, 3001 /* ntop */, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SSH,
+ no_master,
+ no_master, "SSH",
+ ndpi_build_default_ports(ports_a, 22, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_USENET,
+ no_master,
+ no_master, "Usenet",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MGCP,
+ no_master,
+ no_master, "MGCP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IAX,
+ no_master,
+ no_master, "IAX",
+ ndpi_build_default_ports(ports_a, 4569, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 4569, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TFTP,
+ no_master,
+ no_master, "TFTP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_AFP,
+ no_master,
+ no_master, "AFP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_STEALTHNET,
+ no_master,
+ no_master, "Stealthnet",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_AIMINI,
+ no_master,
+ no_master, "Aimini",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SIP,
+ no_master,
+ no_master,
+ "SIP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 5060, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TRUPHONE,
+ no_master,
+ no_master, "TruPhone",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_IP_ICMPV6,
+ no_master,
+ no_master, "ICMPV6",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DHCPV6,
+ no_master,
+ no_master, "DHCPV6",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_ARMAGETRON,
+ no_master,
+ no_master, "Armagetron",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_CROSSFIRE,
+ no_master,
+ no_master, "Crossfire",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_DOFUS,
+ no_master,
+ no_master, "Dofus",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNRATED, NDPI_PROTOCOL_FIESTA,
+ no_master,
+ no_master, "Fiesta",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_FLORENSIA,
+ no_master,
+ no_master, "Florensia",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_GUILDWARS,
+ no_master,
+ no_master, "Guildwars",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_HTTP_APPLICATION_ACTIVESYNC,
+ no_master,
+ no_master, "HTTP_Application_ActiveSync",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_KERBEROS,
+ no_master,
+ no_master, "Kerberos",
+ ndpi_build_default_ports(ports_a, 88, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 88, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_LDAP,
+ no_master,
+ no_master, "LDAP",
+ ndpi_build_default_ports(ports_a, 389, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 389, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_MAPLESTORY,
+ no_master,
+ no_master, "MapleStory",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MSSQL,
+ no_master,
+ no_master, "MsSQL",
+ ndpi_build_default_ports(ports_a, 1433, 1434, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_PPTP,
+ no_master,
+ no_master, "PPTP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_WARCRAFT3,
+ no_master,
+ no_master, "Warcraft3",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_WORLD_OF_KUNG_FU,
+ no_master,
+ no_master, "WorldOfKungFu",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MEEBO,
+ no_master,
+ no_master, "Meebo", /* Remove */
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DROPBOX,
+ no_master,
+ no_master, "DropBox",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 17500, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SKYPE,
+ no_master,
+ no_master, "Skype",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_DCERPC,
+ no_master,
+ no_master, "DCE_RPC",
+ ndpi_build_default_ports(ports_a, 135, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NETFLOW,
+ no_master,
+ no_master, "NetFlow",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 2055, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SFLOW,
+ no_master,
+ no_master, "sFlow",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 6343, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_HTTP_CONNECT,
+ no_master,
+ no_master, "HTTP_Connect",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_HTTP_PROXY,
+ no_master,
+ no_master, "HTTP_Proxy",
+ ndpi_build_default_ports(ports_a, 8080, 3128, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_CITRIX,
+ no_master,
+ no_master, "Citrix",
+ ndpi_build_default_ports(ports_a, 1494, 2598, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SKYFILE_PREPAID,
+ no_master,
+ no_master, "SkyFile_PrePaid",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SKYFILE_RUDICS,
+ no_master,
+ no_master, "SkyFile_Rudics",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SKYFILE_POSTPAID,
+ no_master,
+ no_master, "SkyFile_PostPaid",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_CITRIX_ONLINE,
+ no_master,
+ no_master, "Citrix_Online",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WEBEX,
+ no_master,
+ no_master, "Webex",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RADIUS,
+ no_master,
+ no_master, "Radius",
+ ndpi_build_default_ports(ports_a, 1812, 1813, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 1812, 1813, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WINDOWS_UPDATE,
+ no_master,
+ no_master, "WindowsUpdate",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TEAMVIEWER,
+ no_master,
+ no_master, "TeamViewer",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_LOTUS_NOTES,
+ no_master,
+ no_master, "LotusNotes",
+ ndpi_build_default_ports(ports_a, 1352, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SAP,
+ no_master,
+ no_master, "SAP",
+ ndpi_build_default_ports(ports_a, 3201, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); /* Missing dissector: port based only */
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_GTP,
+ no_master,
+ no_master, "GTP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 2152, 2123, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_UPNP,
+ no_master,
+ no_master, "UPnP",
+ ndpi_build_default_ports(ports_a, 1780, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 1900, 0, 0, 0, 0) /* UDP */); /* Missing dissector: port based only */
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TELEGRAM,
+ no_master,
+ no_master, "Telegram",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+
+ custom_master[0] = NDPI_PROTOCOL_HTTP, custom_master[1] = NDPI_PROTOCOL_UNKNOWN;
+ custom_master1[0] = NDPI_PROTOCOL_DNS, custom_master1[1] = NDPI_PROTOCOL_UNKNOWN;
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE,
+ NDPI_SERVICE_GOOGLE,
+ custom_master, custom_master1,
+ "Google",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+
+ custom_master[0] = NDPI_PROTOCOL_HTTP, custom_master[1] = NDPI_PROTOCOL_UNKNOWN;
+ custom_master1[0] = NDPI_PROTOCOL_DNS, custom_master1[1] = NDPI_PROTOCOL_UNKNOWN;
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE,
+ NDPI_SERVICE_APPLE,
+ custom_master, custom_master1,
+ "Apple",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+
+ custom_master[0] = NDPI_PROTOCOL_HTTP, custom_master[1] = NDPI_PROTOCOL_UNKNOWN;
+ custom_master1[0] = NDPI_PROTOCOL_DNS, custom_master1[1] = NDPI_PROTOCOL_UNKNOWN;
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE,
+ NDPI_SERVICE_APPLE_ICLOUD,
+ custom_master, custom_master1,
+ "AppleiCloud",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+
+ custom_master[0] = NDPI_PROTOCOL_HTTP, custom_master[1] = NDPI_PROTOCOL_UNKNOWN;
+ custom_master1[0] = NDPI_PROTOCOL_DNS, custom_master1[1] = NDPI_PROTOCOL_UNKNOWN;
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN,
+ NDPI_SERVICE_APPLE_ITUNES,
+ custom_master, custom_master1,
+ "AppleiTunes",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+
+ /* http://en.wikipedia.org/wiki/Link-local_Multicast_Name_Resolution */
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_LLMNR,
+ no_master,
+ no_master, "LLMNR",
+ ndpi_build_default_ports(ports_a, 5355, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 5355, 0, 0, 0, 0) /* UDP */); /* Missing dissector: port based only */
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_REMOTE_SCAN,
+ no_master,
+ no_master, "RemoteScan",
+ ndpi_build_default_ports(ports_a, 6077, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 6078, 0, 0, 0, 0) /* UDP */); /* Missing dissector: port based only */
+
+ custom_master[0] = NDPI_PROTOCOL_HTTP, custom_master[1] = NDPI_PROTOCOL_UNKNOWN;
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_SPOTIFY,
+ custom_master, no_master, "Spotify",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 57621, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_CONTENT_WEBM,
+ no_master,
+ no_master, "WebM", /* Courtesy of Shreeram Ramamoorthy Swaminathan <shreeram <shreeram1985@yahoo.co.in> */
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_H323,
+ no_master,
+ no_master,
+ "H323",
+ ndpi_build_default_ports(ports_a, 1719, 1720, 3478, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 1719, 1720, 3478, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_OPENVPN,
+ no_master,
+ no_master, "OpenVPN",
+ ndpi_build_default_ports(ports_a, 1194, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 1194, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_NOE,
+ no_master,
+ no_master, "NOE",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_SAFE, NDPI_PROTOCOL_CISCOVPN,
+ no_master,
+ no_master, "CiscoVPN",
+ ndpi_build_default_ports(ports_a, 10000, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 10000, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TEAMSPEAK,
+ no_master,
+ no_master, "TeamSpeak",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, NDPI_PROTOCOL_TOR,
+ no_master,
+ no_master, "TOR",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SKINNY,
+ no_master,
+ no_master, "CiscoSkinny",
+ ndpi_build_default_ports(ports_a, 2000, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RTCP,
+ no_master,
+ no_master, "RTCP",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RSYNC,
+ no_master,
+ no_master, "RSYNC",
+ ndpi_build_default_ports(ports_a, 873, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_ORACLE,
+ no_master,
+ no_master, "Oracle",
+ ndpi_build_default_ports(ports_a, 1521, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_CORBA,
+ no_master,
+ no_master, "Corba",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_UBUNTUONE,
+ no_master,
+ no_master, "UbuntuONE",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHOIS_DAS,
+ no_master,
+ no_master, "Whois-DAS",
+ ndpi_build_default_ports(ports_a, 43, 4343, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_COLLECTD,
+ no_master,
+ no_master, "Collectd",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 25826, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SOCKS5,
+ no_master,
+ no_master, "SOCKS5",
+ ndpi_build_default_ports(ports_a, 1080, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 1080, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SOCKS4,
+ no_master,
+ no_master, "SOCKS4",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_RTMP,
+ no_master,
+ no_master, "RTMP",
+ ndpi_build_default_ports(ports_a, 1935, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_PANDO,
+ no_master,
+ no_master, "Pando_Media_Booster",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_VIBER,
+ no_master,
+ no_master, "Viber",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MEGACO,
+ no_master,
+ no_master, "Megaco",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 2944 , 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_REDIS,
+ no_master,
+ no_master, "Redis",
+ ndpi_build_default_ports(ports_a, 6379, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0 , 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_ZMQ,
+ no_master,
+ no_master, "ZeroMQ",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0 , 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_SERVICE_TWITTER,
+ no_master,
+ no_master, "Twitter",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0 , 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_VHUA,
+ no_master,
+ no_master, "VHUA",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 58267, 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_SERVICE_FACEBOOK,
+ no_master,
+ no_master, "Facebook",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0 , 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_SERVICE_FACEBOOK_CHAT,
+ no_master,
+ no_master, "FacebookChat",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0 , 0, 0, 0, 0) /* UDP */);
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_SERVICE_PANDORA,
+ no_master,
+ no_master, "Pandora",
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+
+ init_string_based_protocols(ndpi_mod);
+
+ for(i=0; i<(int)ndpi_mod->ndpi_num_supported_protocols; i++) {
+ if(ndpi_mod->proto_defaults[i].protoName == NULL) {
+ printf("[NDPI] %s(missing protoId=%d) INTERNAL ERROR: not all protocols have been initialized\n", __FUNCTION__, i);
+ }
+ }
+}
+
+/* ****************************************************** */
+
+static int ac_match_handler(AC_MATCH_t *m, void *param) {
+ int *matching_protocol_id = (int*)param;
+
+ /* Stopping to the first match. We might consider searching
+ * for the more specific match, paying more cpu cycles. */
+ *matching_protocol_id = m->patterns[0].rep.number;
+
+ return 1; /* 0 to continue searching, !0 to stop */
+}
+
+/* ******************************************************************** */
+
+#ifdef NDPI_PROTOCOL_TOR
+
+static int fill_prefix_v4(prefix_t *p, struct in_addr *a, int b, int mb) {
+ do {
+ if(b < 0 || b > mb)
+ return(-1);
+
+ memcpy(&p->add.sin, a, (mb+7)/8);
+ p->family = AF_INET;
+ p->bitlen = b;
+ p->ref_count = 0;
+ } while (0);
+
+ return(0);
+}
+
+/* ******************************************* */
+
+u_int16_t ndpi_network_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, struct in_addr *pin) {
+ prefix_t prefix;
+ patricia_node_t *node;
+
+ fill_prefix_v4(&prefix, pin, 32, ((patricia_tree_t*)ndpi_struct->protocols_ptree)->maxbits);
+ node = ndpi_patricia_search_best(ndpi_struct->protocols_ptree, &prefix);
+
+ return(node ? node->value.user_value : NDPI_PROTOCOL_UNKNOWN);
+}
+
+/* ******************************************* */
+
+u_int16_t ndpi_host_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t host) {
+ struct in_addr pin;
+
+ pin.s_addr = host;
+
+ return(ndpi_network_ptree_match(ndpi_struct, &pin));
+}
+
+/* ******************************************* */
+
+static u_int8_t tor_ptree_match(struct ndpi_detection_module_struct *ndpi_struct, struct in_addr *pin) {
+ return((ndpi_network_ptree_match(ndpi_struct, pin) == NDPI_PROTOCOL_TOR) ? 1 : 0);
+}
+
+/* ******************************************* */
+
+u_int8_t ndpi_is_tor_flow(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(packet->tcp != NULL) {
+ if(flow->packet.iph) {
+ if(tor_ptree_match(ndpi_struct, (struct in_addr *)&packet->iph->saddr)
+ || tor_ptree_match(ndpi_struct, (struct in_addr *)&packet->iph->daddr)) {
+ return(1);
+ }
+ }
+ }
+
+ return(0);
+}
+
+/* ******************************************* */
+
+static patricia_node_t* add_to_ptree(patricia_tree_t *tree, int family,
+ void *addr, int bits) {
+ prefix_t prefix;
+ patricia_node_t *node;
+
+ fill_prefix_v4(&prefix, (struct in_addr*)addr, bits, tree->maxbits);
+
+ node = ndpi_patricia_lookup(tree, &prefix);
+
+ return(node);
+}
+/* ******************************************* */
+
+static void ndpi_init_ptree_ipv4(struct ndpi_detection_module_struct *ndpi_str,
+ void *ptree, ndpi_network host_list[]) {
+ int i;
+
+ for(i=0; host_list[i].network != 0x0; i++) {
+ struct in_addr pin;
+ patricia_node_t *node;
+
+ pin.s_addr = host_list[i].network;
+ if((node = add_to_ptree(ptree, AF_INET, &pin, host_list[i].cidr /* bits */)) != NULL)
+ node->value.user_value = host_list[i].value;
+ }
+}
+#endif
+
+/* ******************************************************************** */
+
+struct ndpi_detection_module_struct *ndpi_init_detection_module(u_int32_t ticks_per_second,
+ void* (*__ndpi_malloc)(unsigned long size),
+ void (*__ndpi_free)(void *ptr),
+ ndpi_debug_function_ptr ndpi_debug_printf)
+{
+ struct ndpi_detection_module_struct *ndpi_str;
+
+ _ndpi_malloc = __ndpi_malloc;
+ _ndpi_free = __ndpi_free;
+
+ ndpi_str = ndpi_malloc(sizeof(struct ndpi_detection_module_struct));
+
+ if(ndpi_str == NULL) {
+ ndpi_debug_printf(0, NULL, NDPI_LOG_DEBUG, "ndpi_init_detection_module initial malloc failed\n");
+ return NULL;
+ }
+ memset(ndpi_str, 0, sizeof(struct ndpi_detection_module_struct));
+
+ if((ndpi_str->protocols_ptree = ndpi_New_Patricia(32 /* IPv4 */)) != NULL)
+ ndpi_init_ptree_ipv4(ndpi_str, ndpi_str->protocols_ptree, host_protocol_list);
+
+ NDPI_BITMASK_RESET(ndpi_str->detection_bitmask);
+#ifdef NDPI_ENABLE_DEBUG_MESSAGES
+ ndpi_str->ndpi_debug_printf = ndpi_debug_printf;
+ ndpi_str->user_data = NULL;
+#endif
+
+ ndpi_str->match_dns_host_names = 1; /*
+ Set it to 0 to increase library speed avoid
+ matching host names
+ */
+ ndpi_str->ticks_per_second = ticks_per_second;
+ ndpi_str->tcp_max_retransmission_window_size = NDPI_DEFAULT_MAX_TCP_RETRANSMISSION_WINDOW_SIZE;
+ ndpi_str->directconnect_connection_ip_tick_timeout =
+ NDPI_DIRECTCONNECT_CONNECTION_IP_TICK_TIMEOUT * ticks_per_second;
+
+ ndpi_str->rtsp_connection_timeout = NDPI_RTSP_CONNECTION_TIMEOUT * ticks_per_second;
+ ndpi_str->tvants_connection_timeout = NDPI_TVANTS_CONNECTION_TIMEOUT * ticks_per_second;
+ ndpi_str->irc_timeout = NDPI_IRC_CONNECTION_TIMEOUT * ticks_per_second;
+ ndpi_str->gnutella_timeout = NDPI_GNUTELLA_CONNECTION_TIMEOUT * ticks_per_second;
+
+ ndpi_str->battlefield_timeout = NDPI_BATTLEFIELD_CONNECTION_TIMEOUT * ticks_per_second;
+
+ ndpi_str->thunder_timeout = NDPI_THUNDER_CONNECTION_TIMEOUT * ticks_per_second;
+ ndpi_str->yahoo_detect_http_connections = NDPI_YAHOO_DETECT_HTTP_CONNECTIONS;
+
+ ndpi_str->yahoo_lan_video_timeout = NDPI_YAHOO_LAN_VIDEO_TIMEOUT * ticks_per_second;
+ ndpi_str->zattoo_connection_timeout = NDPI_ZATTOO_CONNECTION_TIMEOUT * ticks_per_second;
+ ndpi_str->jabber_stun_timeout = NDPI_JABBER_STUN_TIMEOUT * ticks_per_second;
+ ndpi_str->jabber_file_transfer_timeout = NDPI_JABBER_FT_TIMEOUT * ticks_per_second;
+ ndpi_str->soulseek_connection_ip_tick_timeout = NDPI_SOULSEEK_CONNECTION_IP_TICK_TIMEOUT * ticks_per_second;
+
+ ndpi_str->ndpi_num_supported_protocols = NDPI_MAX_SUPPORTED_PROTOCOLS;
+ ndpi_str->ndpi_num_custom_protocols = 0;
+
+ ndpi_str->host_automa.ac_automa = ac_automata_init(ac_match_handler);
+ ndpi_str->content_automa.ac_automa = ac_automata_init(ac_match_handler);
+ ndpi_str->bigrams_automa.ac_automa = ac_automata_init(ac_match_handler);
+ ndpi_str->impossible_bigrams_automa.ac_automa = ac_automata_init(ac_match_handler);
+
+ ndpi_init_protocol_defaults(ndpi_str);
+ return ndpi_str;
+}
+
+/* *********************************************** */
+
+static void free_ptree_data(void *data) { ; }
+
+/* ****************************************************** */
+
+void ndpi_exit_detection_module(struct ndpi_detection_module_struct
+ *ndpi_struct, void (*ndpi_free) (void *ptr)) {
+ if(ndpi_struct != NULL) {
+ int i;
+
+ for(i=0; i<(int)ndpi_struct->ndpi_num_supported_protocols; i++) {
+ if(ndpi_struct->proto_defaults[i].protoName)
+ ndpi_free(ndpi_struct->proto_defaults[i].protoName);
+ }
+
+ if(ndpi_struct->protocols_ptree)
+ ndpi_Destroy_Patricia((patricia_tree_t*)ndpi_struct->protocols_ptree, free_ptree_data);
+
+ ndpi_tdestroy(ndpi_struct->udpRoot, ndpi_free);
+ ndpi_tdestroy(ndpi_struct->tcpRoot, ndpi_free);
+
+ if(ndpi_struct->host_automa.ac_automa != NULL)
+ ac_automata_release((AC_AUTOMATA_t*)ndpi_struct->host_automa.ac_automa);
+
+ if(ndpi_struct->content_automa.ac_automa != NULL)
+ ac_automata_release((AC_AUTOMATA_t*)ndpi_struct->content_automa.ac_automa);
+
+ if(ndpi_struct->bigrams_automa.ac_automa != NULL)
+ ac_automata_release((AC_AUTOMATA_t*)ndpi_struct->bigrams_automa.ac_automa);
+
+ if(ndpi_struct->impossible_bigrams_automa.ac_automa != NULL)
+ ac_automata_release((AC_AUTOMATA_t*)ndpi_struct->impossible_bigrams_automa.ac_automa);
+
+ ndpi_free(ndpi_struct);
+ }
+}
+
+/* ****************************************************** */
+
+int ndpi_get_protocol_id_master_proto(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int16_t protocol_id,
+ u_int16_t** tcp_master_proto,
+ u_int16_t** udp_master_proto) {
+ if(protocol_id >= (NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) {
+ *tcp_master_proto = *udp_master_proto = NDPI_PROTOCOL_UNKNOWN;
+ return(-1);
+ }
+
+ *tcp_master_proto = ndpi_struct->proto_defaults[protocol_id].master_tcp_protoId,
+ *udp_master_proto = ndpi_struct->proto_defaults[protocol_id].master_udp_protoId;
+
+ return(0);
+}
+
+/* ****************************************************** */
+
+u_int16_t ndpi_guess_protocol_id(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int8_t proto, u_int16_t sport, u_int16_t dport) {
+ const void *ret;
+ ndpi_default_ports_tree_node_t node;
+
+ if(sport && dport) {
+ node.default_port = sport;
+ ret = ndpi_tfind(&node,
+ (proto == IPPROTO_TCP) ? (void*)&ndpi_struct->tcpRoot : (void*)&ndpi_struct->udpRoot,
+ ndpi_default_ports_tree_node_t_cmp);
+
+ if(ret == NULL) {
+ node.default_port = dport;
+ ret = ndpi_tfind(&node,
+ (proto == IPPROTO_TCP) ? (void*)&ndpi_struct->tcpRoot : (void*)&ndpi_struct->udpRoot,
+ ndpi_default_ports_tree_node_t_cmp);
+ }
+
+ if(ret != NULL) {
+ ndpi_default_ports_tree_node_t *found = *(ndpi_default_ports_tree_node_t**)ret;
+
+ return(found->proto->protoId);
+ }
+ } else {
+ /* No TCP/UDP */
+
+ switch(proto) {
+ case NDPI_IPSEC_PROTOCOL_ESP:
+ case NDPI_IPSEC_PROTOCOL_AH:
+ return(NDPI_PROTOCOL_IP_IPSEC);
+ break;
+ case NDPI_GRE_PROTOCOL_TYPE:
+ return(NDPI_PROTOCOL_IP_GRE);
+ break;
+ case NDPI_ICMP_PROTOCOL_TYPE:
+ return(NDPI_PROTOCOL_IP_ICMP);
+ break;
+ case NDPI_IGMP_PROTOCOL_TYPE:
+ return(NDPI_PROTOCOL_IP_IGMP);
+ break;
+ case NDPI_EGP_PROTOCOL_TYPE:
+ return(NDPI_PROTOCOL_IP_EGP);
+ break;
+ case NDPI_SCTP_PROTOCOL_TYPE:
+ return(NDPI_PROTOCOL_IP_SCTP);
+ break;
+ case NDPI_OSPF_PROTOCOL_TYPE:
+ return(NDPI_PROTOCOL_IP_OSPF);
+ break;
+ case NDPI_IPIP_PROTOCOL_TYPE:
+ return(NDPI_PROTOCOL_IP_IP_IN_IP);
+ break;
+ case NDPI_ICMPV6_PROTOCOL_TYPE:
+ return(NDPI_PROTOCOL_IP_ICMPV6);
+ break;
+ case 112:
+ return(NDPI_PROTOCOL_IP_VRRP);
+ break;
+ }
+ }
+
+ return(NDPI_PROTOCOL_UNKNOWN);
+}
+
+/* ******************************************************************** */
+
+#if 0
+#ifndef __KERNEL__
+static int add_proto_default_port(u_int16_t **ports, u_int16_t new_port,
+ ndpi_proto_defaults_t *def,
+ ndpi_default_ports_tree_node_t *root) {
+ u_int num_ports, i;
+
+ if(*ports == NULL) {
+ ndpi_port_range range = { new_port, new_port };
+
+ addDefaultPort(&range, def, &root);
+ return(0);
+ }
+
+ for(num_ports=0; (*ports)[num_ports] != 0; num_ports++)
+ ;
+
+ if(num_ports >= MAX_DEFAULT_PORTS) {
+ printf("Too many ports defined: ignored port %d\n", new_port);
+ return(-1);
+ } else {
+ u_int16_t *new_ports = (u_int16_t*)ndpi_malloc(num_ports+1);
+ ndpi_port_range range;
+
+ if(new_ports == NULL) {
+ printf("Not enough memory\n");
+ return(-2);
+ }
+
+ for(i=0; i<num_ports; i++)
+ new_ports[i] = (*ports)[i];
+
+ new_ports[i++] = new_port;
+ new_ports[i++] = 0;
+
+ ndpi_free(*ports);
+ *ports = new_ports;
+
+ range.port_low = range.port_high = new_port;
+ addDefaultPort(&range, def, &root);
+ return(0);
+ }
+}
+#endif
+#endif
+
+/* ******************************************************************** */
+
+u_int ndpi_get_num_supported_protocols(struct ndpi_detection_module_struct *ndpi_mod) {
+ return(ndpi_mod->ndpi_num_supported_protocols);
+}
+
+/* ******************************************************************** */
+
+int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_mod, char* rule, u_int8_t do_add) {
+ char *at, *proto, *elem;
+ ndpi_proto_defaults_t *def;
+ int subprotocol_id, i;
+
+ at = strrchr(rule, '@');
+ if(at == NULL) {
+ printf("Invalid rule '%s'\n", rule);
+ return(-1);
+ } else
+ at[0] = 0, proto = &at[1];
+
+ for(i=0, def = NULL; i<(int)ndpi_mod->ndpi_num_supported_protocols; i++) {
+ if(strcasecmp(ndpi_mod->proto_defaults[i].protoName, proto) == 0) {
+ def = &ndpi_mod->proto_defaults[i];
+ subprotocol_id = i;
+ break;
+ }
+ }
+
+ if(def == NULL) {
+ if(!do_add) {
+ /* We need to remove a rule */
+ printf("Unable to find protocol '%s': skipping rule '%s'\n", proto, rule);
+ return(-3);
+ } else {
+ ndpi_port_range ports_a[MAX_DEFAULT_PORTS], ports_b[MAX_DEFAULT_PORTS];
+ u_int16_t no_master[2] = { NDPI_PROTOCOL_NO_MASTER_PROTO, NDPI_PROTOCOL_NO_MASTER_PROTO };
+
+ if(ndpi_mod->ndpi_num_custom_protocols >= (NDPI_MAX_NUM_CUSTOM_PROTOCOLS-1)) {
+ printf("Too many protocols defined (%u): skipping protocol %s\n",
+ ndpi_mod->ndpi_num_custom_protocols, proto);
+ return(-2);
+ }
+
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE,
+ ndpi_mod->ndpi_num_supported_protocols,
+ no_master,
+ no_master,
+ ndpi_strdup(proto),
+ ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
+ def = &ndpi_mod->proto_defaults[ndpi_mod->ndpi_num_supported_protocols];
+ subprotocol_id = ndpi_mod->ndpi_num_supported_protocols;
+ ndpi_mod->ndpi_num_supported_protocols++, ndpi_mod->ndpi_num_custom_protocols++;
+ }
+ }
+
+ while((elem = strsep(&rule, ",")) != NULL) {
+ char *attr = elem, *value = NULL;
+ ndpi_port_range range;
+ int is_tcp = 0, is_udp = 0;
+
+ if(strncmp(attr, "tcp:", 4) == 0)
+ is_tcp = 1, value = &attr[4];
+ else if(strncmp(attr, "udp:", 4) == 0)
+ is_udp = 1, value = &attr[4];
+ else if(strncmp(attr, "host:", 5) == 0) {
+ /* host:"<value>",host:"<value>",.....@<subproto> */
+ value = &attr[5];
+ if(value[0] == '"') value++; /* remove leading " */
+ if(value[strlen(value)-1] == '"') value[strlen(value)-1] = '\0'; /* remove trailing " */
+ }
+
+ if(is_tcp || is_udp) {
+ if(sscanf(value, "%u-%u", (unsigned int *)&range.port_low, (unsigned int *)&range.port_high) != 2)
+ range.port_low = range.port_high = atoi(&elem[4]);
+ if(do_add)
+ addDefaultPort(&range, def, is_tcp ? &ndpi_mod->tcpRoot : &ndpi_mod->udpRoot);
+ else
+ removeDefaultPort(&range, def, is_tcp ? &ndpi_mod->tcpRoot : &ndpi_mod->udpRoot);
+ } else {
+ if(do_add)
+ ndpi_add_host_url_subprotocol(ndpi_mod, value, subprotocol_id, NDPI_PROTOCOL_ACCEPTABLE);
+ else
+ ndpi_remove_host_url_subprotocol(ndpi_mod, value, subprotocol_id);
+ }
+ }
+
+ return(0);
+}
+
+/* ******************************************************************** */
+
+/*
+ Format:
+ <tcp|udp>:<port>,<tcp|udp>:<port>,.....@<proto>
+
+ Example:
+ tcp:80,tcp:3128@HTTP
+ udp:139@NETBIOS
+
+*/
+int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, char* path) {
+#ifdef __KERNEL__
+ return(0);
+#else
+ FILE *fd = fopen(path, "r");
+ int i;
+
+ if(fd == NULL) {
+ printf("Unable to open file %s [%s]", path, strerror(errno));
+ return(-1);
+ }
+
+ while(fd) {
+ char buffer[512], *line;
+
+ if(!(line = fgets(buffer, sizeof(buffer), fd)))
+ break;
+
+ if(((i = strlen(line)) <= 1) || (line[0] == '#'))
+ continue;
+ else
+ line[i-1] = '\0';
+
+ ndpi_handle_rule(ndpi_mod, line, 1);
+ }
+
+ fclose(fd);
+
+#if 0
+ printf("\nTCP:\n");
+ ndpi_twalk(ndpi_mod->tcpRoot, ndpi_default_ports_tree_node_t_walker, NULL);
+ printf("\nUDP:\n");
+ ndpi_twalk(ndpi_mod->udpRoot, ndpi_default_ports_tree_node_t_walker, NULL);
+#endif
+#endif
+
+ return(0);
+}
+
+/* ntop */
+void ndpi_set_bitmask_protocol_detection( char * label,
+ struct ndpi_detection_module_struct *ndpi_struct,
+ const NDPI_PROTOCOL_BITMASK * detection_bitmask,
+ const u_int32_t idx,
+ u_int16_t ndpi_protocol_id,
+ void (*func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow),
+ const NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_bitmask,
+ u_int8_t b_save_bitmask_unknow,
+ u_int8_t b_add_detection_bitmask)
+{
+ /*
+ Compare specify protocol bitmask with main detection bitmask
+ */
+ if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(*detection_bitmask, ndpi_protocol_id) != 0) {
+ // #ifdef DEBUG
+ NDPI_LOG(0, ndpi_struct, NDPI_LOG_DEBUG,"[NDPI] ndpi_set_bitmask_protocol_detection: %s : [callback_buffer] idx= %u, [proto_defaults] protocol_id=%u\n", label, idx, ndpi_protocol_id);
+ // #endif
+ /*
+ Set funcition and index protocol within proto_default strcuture for port protocol detection
+ and callback_buffer function for DPI protocol detection
+ */
+ ndpi_struct->proto_defaults[ndpi_protocol_id].protoIdx = idx;
+
+ ndpi_struct->proto_defaults[ndpi_protocol_id].func =
+ ndpi_struct->callback_buffer[idx].func = func;
+ /*
+ Set ndpi_selection_bitmask for protocol
+ */
+ ndpi_struct->callback_buffer[idx].ndpi_selection_bitmask = ndpi_selection_bitmask;
+
+ /*
+ Reset protocol detection bitmask via NDPI_PROTOCOL_UNKNOWN and than add specify protocol bitmast to callback
+ buffer.
+ */
+ if (b_save_bitmask_unknow) NDPI_SAVE_AS_BITMASK(ndpi_struct->callback_buffer[idx].detection_bitmask, NDPI_PROTOCOL_UNKNOWN);
+ if (b_add_detection_bitmask) NDPI_ADD_PROTOCOL_TO_BITMASK(ndpi_struct->callback_buffer[idx].detection_bitmask, ndpi_protocol_id);
+
+ NDPI_SAVE_AS_BITMASK(ndpi_struct->callback_buffer[idx].excluded_protocol_bitmask, ndpi_protocol_id);
+ }
+}
+
+/* ******************************************************************** */
+
+void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_struct,
+ const NDPI_PROTOCOL_BITMASK * dbm)
+{
+ NDPI_PROTOCOL_BITMASK detection_bitmask_local;
+ NDPI_PROTOCOL_BITMASK *detection_bitmask = &detection_bitmask_local;
+ u_int32_t a = 0;
+
+ NDPI_BITMASK_SET(detection_bitmask_local, *dbm);
+ NDPI_BITMASK_SET(ndpi_struct->detection_bitmask, *dbm);
+
+ /* set this here to zero to be interrupt safe */
+ ndpi_struct->callback_buffer_size = 0;
+
+
+#ifdef NDPI_PROTOCOL_HTTP
+ ndpi_set_bitmask_protocol_detection("HTTP",ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_HTTP,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+ ndpi_set_bitmask_protocol_detection("HTTP_PROXY", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_HTTP_PROXY,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+#ifdef NDPI_CONTENT_MPEG
+ ndpi_set_bitmask_protocol_detection("MPEG", ndpi_struct, detection_bitmask, a++,
+ NDPI_CONTENT_MPEG,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_CONTENT_FLASH
+ ndpi_set_bitmask_protocol_detection("FLASH", ndpi_struct, detection_bitmask, a++,
+ NDPI_CONTENT_FLASH,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_CONTENT_QUICKTIME
+ ndpi_set_bitmask_protocol_detection("QUICKTIME", ndpi_struct, detection_bitmask, a++,
+ NDPI_CONTENT_QUICKTIME,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_CONTENT_REALMEDIA
+ ndpi_set_bitmask_protocol_detection("REALMEDIA", ndpi_struct, detection_bitmask, a++,
+ NDPI_CONTENT_REALMEDIA,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_CONTENT_WINDOWSMEDIA
+ ndpi_set_bitmask_protocol_detection("WINDOWSMEDIA", ndpi_struct, detection_bitmask, a++,
+ NDPI_CONTENT_WINDOWSMEDIA,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_CONTENT_MMS
+ ndpi_set_bitmask_protocol_detection("MMS", ndpi_struct, detection_bitmask, a++,
+ NDPI_CONTENT_MMS,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_XBOX
+ ndpi_set_bitmask_protocol_detection("XBOX", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_XBOX,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_WINDOWS_UPDATE
+ ndpi_set_bitmask_protocol_detection("WINDOWS_UPDATE", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_WINDOWS_UPDATE,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_QQ
+ ndpi_set_bitmask_protocol_detection("QQ", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_QQ,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_CONTENT_AVI
+ ndpi_set_bitmask_protocol_detection("AVI", ndpi_struct, detection_bitmask, a++,
+ NDPI_CONTENT_AVI,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_CONTENT_OGG
+ ndpi_set_bitmask_protocol_detection("OGG", ndpi_struct, detection_bitmask, a++,
+ NDPI_CONTENT_OGG,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_MOVE
+ ndpi_set_bitmask_protocol_detection("MOVE", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_MOVE,
+ ndpi_search_http_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+ /*Update excluded protocol bitmask*/
+ NDPI_BITMASK_SET(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask,
+ ndpi_struct->callback_buffer[a].detection_bitmask);
+
+ /*Delete protocol from exluded protocol bitmask*/
+ NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask,
+ NDPI_PROTOCOL_UNKNOWN);
+
+ NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask,
+ NDPI_PROTOCOL_QQ);
+
+#ifdef NDPI_CONTENT_FLASH
+ NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask,
+ NDPI_CONTENT_FLASH);
+#endif
+
+ NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask,
+ NDPI_CONTENT_MMS);
+ // #ifdef NDPI_PROTOCOL_RTSP
+ // NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask,
+ // NDPI_PROTOCOL_RTSP);
+ // #endif
+ NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask,
+ NDPI_PROTOCOL_XBOX);
+
+ NDPI_BITMASK_SET(ndpi_struct->generic_http_packet_bitmask,
+ ndpi_struct->callback_buffer[a].detection_bitmask);
+
+ NDPI_DEL_PROTOCOL_FROM_BITMASK(ndpi_struct->generic_http_packet_bitmask, NDPI_PROTOCOL_UNKNOWN);
+
+ /* Update callback_buffer index */
+ a++;
+#endif
+
+
+#ifdef NDPI_PROTOCOL_SSL
+ ndpi_set_bitmask_protocol_detection("SSL", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_SSL,
+ ndpi_search_ssl_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+
+#ifdef NDPI_PROTOCOL_STUN
+ ndpi_set_bitmask_protocol_detection("STUN", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_STUN,
+ ndpi_search_stun,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_RTP
+ ndpi_set_bitmask_protocol_detection("RTP", ndpi_struct, detection_bitmask,a,
+ NDPI_PROTOCOL_RTP,
+ ndpi_search_rtp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+ /* consider also real protocol for detection select in main loop */
+ ndpi_struct->callback_buffer[a].detection_feature = NDPI_SELECT_DETECTION_WITH_REAL_PROTOCOL;
+ /* Update callback_buffer index */
+ a++;
+#endif
+
+#ifdef NDPI_PROTOCOL_RTSP
+ ndpi_set_bitmask_protocol_detection("RTSP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_RTSP,
+ ndpi_search_rtsp_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_RDP
+ ndpi_set_bitmask_protocol_detection("RDP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_RDP,
+ ndpi_search_rdp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_SIP
+ ndpi_set_bitmask_protocol_detection("SIP", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_SIP,
+ ndpi_search_sip,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,/* Fix courtesy of Miguel Quesada <mquesadab@gmail.com> */
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_BITTORRENT
+ ndpi_set_bitmask_protocol_detection("BITTORRENT", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_BITTORRENT,
+ ndpi_search_bittorrent,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_EDONKEY
+ ndpi_set_bitmask_protocol_detection("EDONKEY", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_EDONKEY,
+ ndpi_search_edonkey,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_FASTTRACK
+ ndpi_set_bitmask_protocol_detection("FASTTRACK", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_FASTTRACK,
+ ndpi_search_fasttrack_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_GNUTELLA
+ ndpi_set_bitmask_protocol_detection("GNUTELLA", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_GNUTELLA,
+ ndpi_search_gnutella,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_WINMX
+ ndpi_set_bitmask_protocol_detection("WINMX", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_WINMX,
+ ndpi_search_winmx_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_DIRECTCONNECT
+ ndpi_set_bitmask_protocol_detection("DIRECTCONNECT", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_DIRECTCONNECT,
+ ndpi_search_directconnect,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_MSN
+
+ NDPI_BITMASK_RESET(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask);
+
+ ndpi_set_bitmask_protocol_detection("MSN", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_MSN,
+ ndpi_search_msn,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_YAHOO
+ ndpi_set_bitmask_protocol_detection("YAHOO", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_YAHOO,
+ ndpi_search_yahoo,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_OSCAR
+ ndpi_set_bitmask_protocol_detection("OSCAR", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_OSCAR,
+ ndpi_search_oscar,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_APPLEJUICE
+ ndpi_set_bitmask_protocol_detection("APPLEJUICE", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_APPLEJUICE,
+ ndpi_search_applejuice_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_SOULSEEK
+ ndpi_set_bitmask_protocol_detection("SOULSEEK", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_SOULSEEK,
+ ndpi_search_soulseek_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_IRC
+ ndpi_set_bitmask_protocol_detection("IRC", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_IRC,
+ ndpi_search_irc_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_UNENCRYPED_JABBER
+ ndpi_set_bitmask_protocol_detection("UNENCRYPED_JABBER", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_UNENCRYPED_JABBER,
+ ndpi_search_jabber_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_MAIL_POP
+ ndpi_set_bitmask_protocol_detection("MAIL_POP", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_MAIL_POP,
+ ndpi_search_mail_pop_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_MAIL_IMAP
+ ndpi_set_bitmask_protocol_detection("MAIL_IMAP", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_MAIL_IMAP,
+ ndpi_search_mail_imap_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_MAIL_SMTP
+ ndpi_set_bitmask_protocol_detection("MAIL_SMTP", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_MAIL_SMTP,
+ ndpi_search_mail_smtp_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_USENET
+ ndpi_set_bitmask_protocol_detection("USENET", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_USENET,
+ ndpi_search_usenet_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_DNS
+ ndpi_set_bitmask_protocol_detection("DNS", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_DNS,
+ ndpi_search_dns,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_FILETOPIA
+ ndpi_set_bitmask_protocol_detection("FILETOPIA", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_FILETOPIA,
+ ndpi_search_filetopia_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_VMWARE
+ ndpi_set_bitmask_protocol_detection("VMWARE", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_VMWARE,
+ ndpi_search_vmware,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_IMESH
+ ndpi_set_bitmask_protocol_detection("IMESH", ndpi_struct, detection_bitmask,a++,
+ NDPI_PROTOCOL_IMESH,
+ ndpi_search_imesh_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_CONTENT_MMS
+ ndpi_set_bitmask_protocol_detection("NDPI_CONTENT_MMS", ndpi_struct, detection_bitmask,a++,
+ NDPI_CONTENT_MMS,
+ ndpi_search_mms_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#if defined(NDPI_PROTOCOL_IP_IPSEC) || defined(NDPI_PROTOCOL_IP_GRE) || defined(NDPI_PROTOCOL_IP_ICMP) || defined(NDPI_PROTOCOL_IP_IGMP) || defined(NDPI_PROTOCOL_IP_EGP) || defined(NDPI_PROTOCOL_IP_SCTP) || defined(NDPI_PROTOCOL_IP_OSPF) || defined(NDPI_PROTOCOL_IP_IP_IN_IP) || defined(NDPI_PROTOCOL_IP_ICMPV6)
+
+ /* always add non tcp/udp if one protocol is compiled in */
+ NDPI_SAVE_AS_BITMASK(ndpi_struct->callback_buffer[a].detection_bitmask, NDPI_PROTOCOL_UNKNOWN);
+
+ ndpi_set_bitmask_protocol_detection("IP_IPSEC", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_IP_IPSEC,
+ ndpi_search_in_non_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+ ndpi_set_bitmask_protocol_detection("IP_GRE", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_IP_GRE,
+ ndpi_search_in_non_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+ ndpi_set_bitmask_protocol_detection("IP_ICMP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_IP_ICMP,
+ ndpi_search_in_non_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+ ndpi_set_bitmask_protocol_detection("IP_IGMP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_IP_IGMP,
+ ndpi_search_in_non_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+ ndpi_set_bitmask_protocol_detection("IP_EGP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_IP_EGP,
+ ndpi_search_in_non_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+ ndpi_set_bitmask_protocol_detection("IP_SCTP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_IP_SCTP,
+ ndpi_search_in_non_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+ ndpi_set_bitmask_protocol_detection("IP_OSPF", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_IP_OSPF,
+ ndpi_search_in_non_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+ ndpi_set_bitmask_protocol_detection("IP_IP_IN_IP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_IP_IP_IN_IP,
+ ndpi_search_in_non_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+ ndpi_set_bitmask_protocol_detection("IP_ICMPV6", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_IP_ICMPV6,
+ ndpi_search_in_non_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6,
+ NO_SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+
+ // NDPI_BITMASK_RESET(ndpi_struct->callback_buffer[a].excluded_protocol_bitmask);
+#endif
+
+
+#ifdef NDPI_PROTOCOL_TVANTS
+ ndpi_set_bitmask_protocol_detection("TVANTS", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_TVANTS,
+ ndpi_search_tvants_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_SOPCAST
+ ndpi_set_bitmask_protocol_detection("SOPCAST", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SOPCAST,
+ ndpi_search_sopcast,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_TVUPLAYER
+ ndpi_set_bitmask_protocol_detection("TVUPLAYER", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_TVUPLAYER,
+ ndpi_search_tvuplayer,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_PPSTREAM
+ ndpi_set_bitmask_protocol_detection("PPSTREAM", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_PPSTREAM,
+ ndpi_search_ppstream,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_PPLIVE
+ ndpi_set_bitmask_protocol_detection("PPLIVE", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_PPLIVE,
+ ndpi_search_pplive,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_IAX
+ ndpi_set_bitmask_protocol_detection("IAX", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_IAX,
+ ndpi_search_iax,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_MGCP
+ ndpi_set_bitmask_protocol_detection("MGCP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_MGCP,
+ ndpi_search_mgcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_ZATTOO
+ ndpi_set_bitmask_protocol_detection("ZATTOO", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_ZATTOO,
+ ndpi_search_zattoo,
+ NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_QQ
+ ndpi_set_bitmask_protocol_detection("QQ", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_QQ,
+ ndpi_search_qq,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_SSH
+ ndpi_set_bitmask_protocol_detection("SSH", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SSH,
+ ndpi_search_ssh_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_AYIYA
+ ndpi_set_bitmask_protocol_detection("AYIYA", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_AYIYA,
+ ndpi_search_ayiya,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_THUNDER
+ ndpi_set_bitmask_protocol_detection("THUNDER", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_THUNDER,
+ ndpi_search_thunder,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_VNC
+ ndpi_set_bitmask_protocol_detection("VNC", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_VNC,
+ ndpi_search_vnc_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_TEAMVIEWER
+ ndpi_set_bitmask_protocol_detection("TEAMVIEWER", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_TEAMVIEWER,
+ ndpi_search_teamview,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_DHCP
+ ndpi_set_bitmask_protocol_detection("DHCP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_DHCP,
+ ndpi_search_dhcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_SOCRATES
+ ndpi_set_bitmask_protocol_detection("SOCRATES", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SOCRATES,
+ ndpi_search_socrates,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_STEAM
+ ndpi_set_bitmask_protocol_detection("STEAM", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_STEAM,
+ ndpi_search_steam,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_HALFLIFE2
+ ndpi_set_bitmask_protocol_detection("HALFLIFE2", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_HALFLIFE2,
+ ndpi_search_halflife2,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_XBOX
+ ndpi_set_bitmask_protocol_detection("XBOX", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_XBOX,
+ ndpi_search_xbox,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_HTTP_APPLICATION_ACTIVESYNC
+ ndpi_set_bitmask_protocol_detection("HTTP_APPLICATION_ACTIVESYNC", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_HTTP_APPLICATION_ACTIVESYNC,
+ ndpi_search_activesync,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_SMB
+ ndpi_set_bitmask_protocol_detection("SMB", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SMB,
+ ndpi_search_smb_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_TELNET
+ ndpi_set_bitmask_protocol_detection("TELNET", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_TELNET,
+ ndpi_search_telnet_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_NTP
+ ndpi_set_bitmask_protocol_detection("NTP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_NTP,
+ ndpi_search_ntp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_NFS
+ ndpi_set_bitmask_protocol_detection("NFS", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_NFS,
+ ndpi_search_nfs,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_SSDP
+ ndpi_set_bitmask_protocol_detection("SSDP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SSDP,
+ ndpi_search_ssdp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_WORLDOFWARCRAFT
+ ndpi_set_bitmask_protocol_detection("WORLDOFWARCRAFT", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_WORLDOFWARCRAFT,
+ ndpi_search_worldofwarcraft,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_POSTGRES
+ ndpi_set_bitmask_protocol_detection("POSTGRES", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_POSTGRES,
+ ndpi_search_postgres_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_MYSQL
+ ndpi_set_bitmask_protocol_detection("MYSQL", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_MYSQL,
+ ndpi_search_mysql_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_BGP
+ ndpi_set_bitmask_protocol_detection("BGP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_BGP,
+ ndpi_search_bgp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_QUAKE
+ ndpi_set_bitmask_protocol_detection("QUAKE", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_QUAKE,
+ ndpi_search_quake,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_BATTLEFIELD
+ ndpi_set_bitmask_protocol_detection("BATTLEFIELD", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_BATTLEFIELD,
+ ndpi_search_battlefield,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_PCANYWHERE
+ ndpi_set_bitmask_protocol_detection("PCANYWHERE", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_PCANYWHERE,
+ ndpi_search_pcanywhere,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_SNMP
+ ndpi_set_bitmask_protocol_detection("SNMP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SNMP,
+ ndpi_search_snmp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_KONTIKI
+ ndpi_set_bitmask_protocol_detection("KONTIKI", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_KONTIKI,
+ ndpi_search_kontiki,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_ICECAST
+ ndpi_set_bitmask_protocol_detection("ICECAST", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_ICECAST,
+ ndpi_search_icecast_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_SHOUTCAST
+ ndpi_set_bitmask_protocol_detection("SHOUTCAST", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SHOUTCAST,
+ ndpi_search_shoutcast_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV
+ ndpi_set_bitmask_protocol_detection("HTTP_APPLICATION_VEOHTV", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV,
+ ndpi_search_veohtv_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_KERBEROS
+ ndpi_set_bitmask_protocol_detection("KERBEROS", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_KERBEROS,
+ ndpi_search_kerberos,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_OPENFT
+ ndpi_set_bitmask_protocol_detection("OPENFT", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_OPENFT,
+ ndpi_search_openft_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_SYSLOG
+ ndpi_set_bitmask_protocol_detection("SYSLOG", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SYSLOG,
+ ndpi_search_syslog,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_TDS
+ ndpi_set_bitmask_protocol_detection("TDS", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_TDS,
+ ndpi_search_tds_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK
+ ndpi_set_bitmask_protocol_detection("DIRECT_DOWNLOAD_LINK", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK,
+ ndpi_search_direct_download_link_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_NETBIOS
+ ndpi_set_bitmask_protocol_detection("NETBIOS", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_NETBIOS,
+ ndpi_search_netbios,
+ NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_MDNS
+ ndpi_set_bitmask_protocol_detection("MDNS", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_MDNS,
+ ndpi_search_mdns,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_IPP
+ ndpi_set_bitmask_protocol_detection("IPP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_IPP,
+ ndpi_search_ipp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_LDAP
+ ndpi_set_bitmask_protocol_detection("LDAP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_LDAP,
+ ndpi_search_ldap,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_WARCRAFT3
+ ndpi_set_bitmask_protocol_detection("WARCRAFT3", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_WARCRAFT3,
+ ndpi_search_warcraft3,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_XDMCP
+ ndpi_set_bitmask_protocol_detection("XDMCP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_XDMCP,
+ ndpi_search_xdmcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_TFTP
+ ndpi_set_bitmask_protocol_detection("TFTP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_TFTP,
+ ndpi_search_tftp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_MSSQL
+ ndpi_set_bitmask_protocol_detection("MSSQL", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_MSSQL,
+ ndpi_search_mssql,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_PPTP
+ ndpi_set_bitmask_protocol_detection("PPTP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_PPTP,
+ ndpi_search_pptp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_STEALTHNET
+ ndpi_set_bitmask_protocol_detection("STEALTHNET", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_STEALTHNET,
+ ndpi_search_stealthnet,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_DHCPV6
+ ndpi_set_bitmask_protocol_detection("DHCPV6", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_DHCPV6,
+ ndpi_search_dhcpv6_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_MEEBO
+ ndpi_set_bitmask_protocol_detection("Meebo", ndpi_struct, detection_bitmask, a,
+ NDPI_PROTOCOL_MEEBO,
+ ndpi_search_meebo,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+ /* Add protocol bitmask dependencies to detected bitmask*/
+#ifdef NDPI_CONTENT_FLASH
+ NDPI_ADD_PROTOCOL_TO_BITMASK(ndpi_struct->callback_buffer[a].detection_bitmask, NDPI_CONTENT_FLASH);
+#endif
+ a++;
+#endif
+
+#ifdef NDPI_PROTOCOL_AFP
+ ndpi_set_bitmask_protocol_detection("AFP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_AFP,
+ ndpi_search_afp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_AIMINI
+ ndpi_set_bitmask_protocol_detection("AIMINI", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_AIMINI,
+ ndpi_search_aimini,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_FLORENSIA
+ ndpi_set_bitmask_protocol_detection("FLORENSIA", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_FLORENSIA,
+ ndpi_search_florensia,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_MAPLESTORY
+ ndpi_set_bitmask_protocol_detection("MAPLESTORY", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_MAPLESTORY,
+ ndpi_search_maplestory,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_DOFUS
+ ndpi_set_bitmask_protocol_detection("DOFUS", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_DOFUS,
+ ndpi_search_dofus,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_WORLD_OF_KUNG_FU
+ ndpi_set_bitmask_protocol_detection("WORLD_OF_KUNG_FU", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_WORLD_OF_KUNG_FU,
+ ndpi_search_world_of_kung_fu,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_FIESTA
+ ndpi_set_bitmask_protocol_detection("FIESTA", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_FIESTA,
+ ndpi_search_fiesta,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_CROSSFIRE
+ ndpi_set_bitmask_protocol_detection("CROSSFIRE", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_CROSSFIRE,
+ ndpi_search_crossfire_tcp_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_GUILDWARS
+ ndpi_set_bitmask_protocol_detection("GUILDWARS", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_GUILDWARS,
+ ndpi_search_guildwars_tcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+#ifdef NDPI_PROTOCOL_ARMAGETRON
+ ndpi_set_bitmask_protocol_detection("ARMAGETRON", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_ARMAGETRON,
+ ndpi_search_armagetron_udp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_DROPBOX
+ ndpi_set_bitmask_protocol_detection("DROPBOX", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_DROPBOX,
+ ndpi_search_dropbox,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_SPOTIFY
+ ndpi_set_bitmask_protocol_detection("SPOTIFY", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SPOTIFY,
+ ndpi_search_spotify,
+ NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_SKYPE
+ ndpi_set_bitmask_protocol_detection("SKYPE", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SKYPE,
+ ndpi_search_skype,
+ NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_RADIUS
+ ndpi_set_bitmask_protocol_detection("RADIUS", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_RADIUS,
+ ndpi_search_radius,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_CITRIX
+ ndpi_set_bitmask_protocol_detection("CITRIX", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_CITRIX,
+ ndpi_search_citrix,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_LOTUS_NOTES
+ ndpi_set_bitmask_protocol_detection("LOTUS_NOTES", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_LOTUS_NOTES,
+ ndpi_search_lotus_notes,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_GTP
+ ndpi_set_bitmask_protocol_detection("GTP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_GTP,
+ ndpi_search_gtp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_DCERPC
+ ndpi_set_bitmask_protocol_detection("DCERPC", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_DCERPC,
+ ndpi_search_dcerpc,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_NETFLOW
+ ndpi_set_bitmask_protocol_detection("NETFLOW", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_NETFLOW,
+ ndpi_search_netflow,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_SFLOW
+ ndpi_set_bitmask_protocol_detection("SFLOW", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SFLOW,
+ ndpi_search_sflow,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_H323
+ ndpi_set_bitmask_protocol_detection("H323", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_H323,
+ ndpi_search_h323,
+ NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_OPENVPN
+ ndpi_set_bitmask_protocol_detection("OPENVPN", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_OPENVPN,
+ ndpi_search_openvpn,
+ NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_NOE
+ ndpi_set_bitmask_protocol_detection("NOE", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_NOE,
+ ndpi_search_noe,
+ NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_CISCOVPN
+ ndpi_set_bitmask_protocol_detection("CISCOVPN", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_CISCOVPN,
+ ndpi_search_ciscovpn,
+ NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_TEAMSPEAK
+ ndpi_set_bitmask_protocol_detection("TEAMSPEAK", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_TEAMSPEAK,
+ ndpi_search_teamspeak,
+ NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_VIBER
+ ndpi_set_bitmask_protocol_detection("VIBER", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_VIBER,
+ ndpi_search_viber,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_TOR
+ ndpi_set_bitmask_protocol_detection("TOR", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_TOR,
+ ndpi_search_tor,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_SKINNY
+ ndpi_set_bitmask_protocol_detection("SKINNY", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_SKINNY,
+ ndpi_search_skinny,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_RTCP
+ ndpi_set_bitmask_protocol_detection("RTCP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_RTCP,
+ ndpi_search_rtcp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_TCP_OR_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_RSYNC
+ ndpi_set_bitmask_protocol_detection("RSYNC", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_RSYNC,
+ ndpi_search_rsync,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_WHOIS_DAS
+ ndpi_set_bitmask_protocol_detection("WHOIS_DAS", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_WHOIS_DAS,
+ ndpi_search_whois_das,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_ORACLE
+ ndpi_set_bitmask_protocol_detection("ORACLE", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_ORACLE,
+ ndpi_search_oracle,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_CORBA
+ ndpi_set_bitmask_protocol_detection("CORBA", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_CORBA,
+ ndpi_search_corba,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_RTMP
+ ndpi_set_bitmask_protocol_detection("RTMP", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_RTMP,
+ ndpi_search_rtmp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_FTP_CONTROL
+ ndpi_set_bitmask_protocol_detection("FTP_CONTROL", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_FTP_CONTROL,
+ ndpi_search_ftp_control,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_FTP_DATA
+ ndpi_set_bitmask_protocol_detection("FTP_DATA", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_FTP_DATA,
+ ndpi_search_ftp_data,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_PANDO
+ ndpi_set_bitmask_protocol_detection("PANDO", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_PANDO,
+ ndpi_search_pando,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_MEGACO
+ ndpi_set_bitmask_protocol_detection("MEGACO", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_MEGACO,
+ ndpi_search_megaco,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_REDIS
+ ndpi_set_bitmask_protocol_detection("REDIS", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_REDIS,
+ ndpi_search_redis,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_VHUA
+ ndpi_set_bitmask_protocol_detection("VHUA", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_VHUA,
+ ndpi_search_vhua,
+ NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_ZMQ
+ ndpi_set_bitmask_protocol_detection("ZMQ", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_ZMQ,
+ ndpi_search_zmq, /* TODO: add UDP support */
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+
+#ifdef NDPI_SERVICE_TWITTER
+ ndpi_set_bitmask_protocol_detection("TWITTER", ndpi_struct, detection_bitmask, a++,
+ NDPI_SERVICE_TWITTER,
+ ndpi_search_twitter,
+ NDPI_SELECTION_BITMASK_PROTOCOL_TCP,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+#ifdef NDPI_PROTOCOL_TELEGRAM
+ ndpi_set_bitmask_protocol_detection("TELEGRAM", ndpi_struct, detection_bitmask, a++,
+ NDPI_PROTOCOL_TELEGRAM,
+ ndpi_search_telegram,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
+#endif
+
+ ndpi_struct->callback_buffer_size = a;
+
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG,
+ "callback_buffer_size is %u\n", ndpi_struct->callback_buffer_size);
+
+ /* now build the specific buffer for tcp, udp and non_tcp_udp */
+ ndpi_struct->callback_buffer_size_tcp_payload = 0;
+ ndpi_struct->callback_buffer_size_tcp_no_payload = 0;
+ for (a = 0; a < ndpi_struct->callback_buffer_size; a++) {
+ if((ndpi_struct->callback_buffer[a].ndpi_selection_bitmask
+ & (NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP |
+ NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP |
+ NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC)) != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG,
+ "callback_buffer_tcp_payload, adding buffer %u as entry %u\n", a,
+ ndpi_struct->callback_buffer_size_tcp_payload);
+
+ memcpy(&ndpi_struct->callback_buffer_tcp_payload[ndpi_struct->callback_buffer_size_tcp_payload],
+ &ndpi_struct->callback_buffer[a], sizeof(struct ndpi_call_function_struct));
+ ndpi_struct->callback_buffer_size_tcp_payload++;
+
+ if((ndpi_struct->
+ callback_buffer[a].ndpi_selection_bitmask & NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG,
+ "\tcallback_buffer_tcp_no_payload, additional adding buffer %u to no_payload process\n", a);
+
+ memcpy(&ndpi_struct->callback_buffer_tcp_no_payload
+ [ndpi_struct->callback_buffer_size_tcp_no_payload], &ndpi_struct->callback_buffer[a],
+ sizeof(struct ndpi_call_function_struct));
+ ndpi_struct->callback_buffer_size_tcp_no_payload++;
+ }
+ }
+ }
+
+ ndpi_struct->callback_buffer_size_udp = 0;
+ for (a = 0; a < ndpi_struct->callback_buffer_size; a++) {
+ if((ndpi_struct->callback_buffer[a].ndpi_selection_bitmask & (NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP |
+ NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP |
+ NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC))
+ != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG,
+ "callback_buffer_size_udp: adding buffer : %u as entry %u\n", a, ndpi_struct->callback_buffer_size_udp);
+
+ memcpy(&ndpi_struct->callback_buffer_udp[ndpi_struct->callback_buffer_size_udp],
+ &ndpi_struct->callback_buffer[a], sizeof(struct ndpi_call_function_struct));
+ ndpi_struct->callback_buffer_size_udp++;
+ }
+ }
+
+ ndpi_struct->callback_buffer_size_non_tcp_udp = 0;
+ for (a = 0; a < ndpi_struct->callback_buffer_size; a++) {
+ if((ndpi_struct->callback_buffer[a].ndpi_selection_bitmask & (NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP |
+ NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP |
+ NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP))
+ == 0
+ || (ndpi_struct->
+ callback_buffer[a].ndpi_selection_bitmask & NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC) != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG,
+ "callback_buffer_non_tcp_udp: adding buffer : %u as entry %u\n", a, ndpi_struct->callback_buffer_size_non_tcp_udp);
+
+ memcpy(&ndpi_struct->callback_buffer_non_tcp_udp[ndpi_struct->callback_buffer_size_non_tcp_udp],
+ &ndpi_struct->callback_buffer[a], sizeof(struct ndpi_call_function_struct));
+ ndpi_struct->callback_buffer_size_non_tcp_udp++;
+ }
+ }
+}
+
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+/* handle extension headers in IPv6 packets
+ * arguments:
+ * l4ptr: pointer to the byte following the initial IPv6 header
+ * l4len: the length of the IPv6 packet excluding the IPv6 header
+ * nxt_hdr: next header value from the IPv6 header
+ * result:
+ * l4ptr: pointer to the start of the actual packet payload
+ * l4len: length of the actual payload
+ * nxt_hdr: protocol of the actual payload
+ * returns 0 upon success and 1 upon failure
+ */
+static int ndpi_handle_ipv6_extension_headers(struct ndpi_detection_module_struct *ndpi_struct,
+ const u_int8_t ** l4ptr, u_int16_t * l4len, u_int8_t * nxt_hdr)
+{
+ while ((*nxt_hdr == 0 || *nxt_hdr == 43 || *nxt_hdr == 44 || *nxt_hdr == 60 || *nxt_hdr == 135 || *nxt_hdr == 59)) {
+ u_int16_t ehdr_len;
+
+ // no next header
+ if(*nxt_hdr == 59) {
+ return 1;
+ }
+ // fragment extension header has fixed size of 8 bytes and the first byte is the next header type
+ if(*nxt_hdr == 44) {
+ if(*l4len < 8) {
+ return 1;
+ }
+ *nxt_hdr = (*l4ptr)[0];
+ *l4len -= 8;
+ (*l4ptr) += 8;
+ continue;
+ }
+ // the other extension headers have one byte for the next header type
+ // and one byte for the extension header length in 8 byte steps minus the first 8 bytes
+ ehdr_len = (*l4ptr)[1];
+ ehdr_len *= 8;
+ ehdr_len += 8;
+
+ if(*l4len < ehdr_len) {
+ return 1;
+ }
+ *nxt_hdr = (*l4ptr)[0];
+ *l4len -= ehdr_len;
+ (*l4ptr) += ehdr_len;
+ }
+ return 0;
+}
+#endif /* NDPI_DETECTION_SUPPORT_IPV6 */
+
+
+static u_int8_t ndpi_iph_is_valid_and_not_fragmented(const struct ndpi_iphdr *iph, const u_int16_t ipsize)
+{
+ //#ifdef REQUIRE_FULL_PACKETS
+ if(ipsize < iph->ihl * 4 ||
+ ipsize < ntohs(iph->tot_len) || ntohs(iph->tot_len) < iph->ihl * 4 || (iph->frag_off & htons(0x1FFF)) != 0) {
+ return 0;
+ }
+ //#endif
+
+ return 1;
+}
+
+static u_int8_t ndpi_detection_get_l4_internal(struct ndpi_detection_module_struct *ndpi_struct,
+ const u_int8_t * l3, u_int16_t l3_len, const u_int8_t ** l4_return, u_int16_t * l4_len_return,
+ u_int8_t * l4_protocol_return, u_int32_t flags)
+{
+ const struct ndpi_iphdr *iph = NULL;
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ const struct ndpi_ipv6hdr *iph_v6 = NULL;
+#endif
+ u_int16_t l4len = 0;
+ const u_int8_t *l4ptr = NULL;
+ u_int8_t l4protocol = 0;
+
+ if(l3 == NULL || l3_len < sizeof(struct ndpi_iphdr))
+ return 1;
+
+ iph = (const struct ndpi_iphdr *) l3;
+
+ if(iph->version == 4 && iph->ihl >= 5) {
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG, "ipv4 header\n");
+ }
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ else if(iph->version == 6 && l3_len >= sizeof(struct ndpi_ipv6hdr)) {
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG, "ipv6 header\n");
+ iph_v6 = (const struct ndpi_ipv6hdr *) iph;
+ iph = NULL;
+ }
+#endif
+ else {
+ return 1;
+ }
+
+ if((flags & NDPI_DETECTION_ONLY_IPV6) && iph != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG, "ipv4 header found but excluded by flag\n");
+ return 1;
+ }
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ else if((flags & NDPI_DETECTION_ONLY_IPV4) && iph_v6 != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG, "ipv6 header found but excluded by flag\n");
+ return 1;
+ }
+#endif
+
+ if(iph != NULL && ndpi_iph_is_valid_and_not_fragmented(iph, l3_len)) {
+ u_int16_t len = ntohs(iph->tot_len);
+ u_int16_t hlen = (iph->ihl * 4);
+
+ l4ptr = (((const u_int8_t *) iph) + iph->ihl * 4);
+
+ if(len == 0) len = l3_len;
+
+ l4len = (len > hlen) ? (len - hlen) : 0;
+ l4protocol = iph->protocol;
+ }
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ else if(iph_v6 != NULL && (l3_len - sizeof(struct ndpi_ipv6hdr)) >= ntohs(iph_v6->payload_len)) {
+ l4ptr = (((const u_int8_t *) iph_v6) + sizeof(struct ndpi_ipv6hdr));
+ l4len = ntohs(iph_v6->payload_len);
+ l4protocol = iph_v6->nexthdr;
+
+ // we need to handle IPv6 extension headers if present
+ if(ndpi_handle_ipv6_extension_headers(ndpi_struct, &l4ptr, &l4len, &l4protocol) != 0) {
+ return 1;
+ }
+
+ }
+#endif
+ else {
+ return 1;
+ }
+
+ if(l4_return != NULL) {
+ *l4_return = l4ptr;
+ }
+
+ if(l4_len_return != NULL) {
+ *l4_len_return = l4len;
+ }
+
+ if(l4_protocol_return != NULL) {
+ *l4_protocol_return = l4protocol;
+ }
+
+ return 0;
+}
+
+#if !defined(WIN32)
+#define ATTRIBUTE_ALWAYS_INLINE static inline
+#else
+__forceinline static
+#endif
+void ndpi_apply_flow_protocol_to_packet(struct ndpi_flow_struct *flow,
+ struct ndpi_packet_struct *packet)
+{
+ memcpy(&packet->detected_protocol_stack[0],
+ &flow->detected_protocol_stack[0], sizeof(packet->detected_protocol_stack));
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+ memcpy(&packet->protocol_stack_info, &flow->protocol_stack_info, sizeof(packet->protocol_stack_info));
+#endif
+}
+
+static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ unsigned short packetlen)
+{
+ const struct ndpi_iphdr *decaps_iph = NULL;
+ u_int16_t l3len;
+ u_int16_t l4len;
+ const u_int8_t *l4ptr;
+ u_int8_t l4protocol;
+ u_int8_t l4_result;
+
+ /* reset payload_packet_len, will be set if ipv4 tcp or udp */
+ flow->packet.payload_packet_len = 0;
+ flow->packet.l4_packet_len = 0;
+ flow->packet.l3_packet_len = packetlen;
+
+ flow->packet.tcp = NULL;
+ flow->packet.udp = NULL;
+ flow->packet.generic_l4_ptr = NULL;
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ flow->packet.iphv6 = NULL;
+#endif /* NDPI_DETECTION_SUPPORT_IPV6 */
+
+ if(flow) {
+ ndpi_apply_flow_protocol_to_packet(flow, &flow->packet);
+ } else {
+ ndpi_int_reset_packet_protocol(&flow->packet);
+ }
+
+ l3len = flow->packet.l3_packet_len;
+
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ if(flow->packet.iph != NULL) {
+#endif /* NDPI_DETECTION_SUPPORT_IPV6 */
+
+ decaps_iph =flow->packet.iph;
+
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ }
+#endif /* NDPI_DETECTION_SUPPORT_IPV6 */
+
+ if(decaps_iph->version == 4 && decaps_iph->ihl >= 5) {
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG, "ipv4 header\n");
+ }
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ else if(decaps_iph->version == 6 && l3len >= sizeof(struct ndpi_ipv6hdr) &&
+ (ndpi_struct->ip_version_limit & NDPI_DETECTION_ONLY_IPV4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG, "ipv6 header\n");
+ flow->packet.iphv6 = (struct ndpi_ipv6hdr *)flow->packet.iph;
+ flow->packet.iph = NULL;
+ }
+#endif
+ else {
+ flow->packet.iph = NULL;
+ return 1;
+ }
+
+
+ /* needed:
+ * - unfragmented packets
+ * - ip header <= packet len
+ * - ip total length >= packet len
+ */
+
+
+ l4ptr = NULL;
+ l4len = 0;
+ l4protocol = 0;
+
+ l4_result =
+ ndpi_detection_get_l4_internal(ndpi_struct, (const u_int8_t *) decaps_iph, l3len, &l4ptr, &l4len, &l4protocol, 0);
+
+ if(l4_result != 0) {
+ return 1;
+ }
+
+ flow->packet.l4_protocol = l4protocol;
+ flow->packet.l4_packet_len = l4len;
+
+ /* tcp / udp detection */
+ if(l4protocol == 6 /* TCP */ &&flow->packet.l4_packet_len >= 20 /* min size of tcp */ ) {
+ /* tcp */
+ flow->packet.tcp = (struct ndpi_tcphdr *) l4ptr;
+
+ if(flow->packet.l4_packet_len >=flow->packet.tcp->doff * 4) {
+ flow->packet.payload_packet_len =
+ flow->packet.l4_packet_len -flow->packet.tcp->doff * 4;
+ flow->packet.actual_payload_len =flow->packet.payload_packet_len;
+ flow->packet.payload = ((u_int8_t *)flow->packet.tcp) + (flow->packet.tcp->doff * 4);
+
+ /* check for new tcp syn packets, here
+ * idea: reset detection state if a connection is unknown
+ */
+ if(flow && flow->packet.tcp->syn != 0
+ && flow->packet.tcp->ack == 0
+ && flow->init_finished != 0
+ && flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
+
+ memset(flow, 0, sizeof(*(flow)));
+
+
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct,
+ NDPI_LOG_DEBUG,
+ "%s:%u: tcp syn packet for unknown protocol, reset detection state\n", __FUNCTION__, __LINE__);
+
+ }
+ } else {
+ /* tcp header not complete */
+ flow->packet.tcp = NULL;
+ }
+ } else if(l4protocol == 17 /* udp */ &&flow->packet.l4_packet_len >= 8 /* size of udp */ ) {
+ flow->packet.udp = (struct ndpi_udphdr *) l4ptr;
+ flow->packet.payload_packet_len =flow->packet.l4_packet_len - 8;
+ flow->packet.payload = ((u_int8_t *)flow->packet.udp) + 8;
+ } else {
+ flow->packet.generic_l4_ptr = l4ptr;
+ }
+ return 0;
+}
+
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ /* const for gcc code optimisation and cleaner code */
+ struct ndpi_packet_struct *packet = &flow->packet;
+ const struct ndpi_iphdr *iph = packet->iph;
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ const struct ndpi_ipv6hdr *iphv6 = packet->iphv6;
+#endif
+ const struct ndpi_tcphdr *tcph = packet->tcp;
+ const struct ndpi_udphdr *udph = flow->packet.udp;
+
+ //struct ndpi_unique_flow_struct unique_flow;
+ //uint8_t new_connection;
+
+ u_int8_t proxy_enabled = 0;
+
+ packet->tcp_retransmission = 0, packet->packet_direction = 0;
+
+ if(ndpi_struct->direction_detect_disable) {
+ packet->packet_direction = flow->packet_direction;
+ } else {
+ if(iph != NULL && iph->saddr < iph->daddr)
+ packet->packet_direction = 1;
+
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ if(iphv6 != NULL && NDPI_COMPARE_IPV6_ADDRESS_STRUCTS(&iphv6->saddr, &iphv6->daddr) != 0)
+ packet->packet_direction = 1;
+#endif
+ }
+
+ packet->packet_lines_parsed_complete = 0;
+ if(flow == NULL)
+ return;
+
+ if(flow->init_finished == 0) {
+ flow->init_finished = 1;
+ flow->setup_packet_direction = packet->packet_direction;
+ }
+
+ if(tcph != NULL) {
+ /* reset retried bytes here before setting it */
+ packet->num_retried_bytes = 0;
+
+ if(!ndpi_struct->direction_detect_disable)
+ packet->packet_direction = (tcph->source < tcph->dest) ? 1 : 0;
+
+ if(tcph->syn != 0 && tcph->ack == 0 && flow->l4.tcp.seen_syn == 0 && flow->l4.tcp.seen_syn_ack == 0
+ && flow->l4.tcp.seen_ack == 0) {
+ flow->l4.tcp.seen_syn = 1;
+ }
+ if(tcph->syn != 0 && tcph->ack != 0 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 0
+ && flow->l4.tcp.seen_ack == 0) {
+ flow->l4.tcp.seen_syn_ack = 1;
+ }
+ if(tcph->syn == 0 && tcph->ack == 1 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 1
+ && flow->l4.tcp.seen_ack == 0) {
+ flow->l4.tcp.seen_ack = 1;
+ }
+ if((flow->next_tcp_seq_nr[0] == 0 && flow->next_tcp_seq_nr[1] == 0)
+ || (proxy_enabled && (flow->next_tcp_seq_nr[0] == 0 || flow->next_tcp_seq_nr[1] == 0))) {
+ /* initalize tcp sequence counters */
+ /* the ack flag needs to be set to get valid sequence numbers from the other
+ * direction. Usually it will catch the second packet syn+ack but it works
+ * also for asymmetric traffic where it will use the first data packet
+ *
+ * if the syn flag is set add one to the sequence number,
+ * otherwise use the payload length.
+ */
+ if(tcph->ack != 0) {
+ flow->next_tcp_seq_nr[flow->packet.packet_direction] =
+ ntohl(tcph->seq) + (tcph->syn ? 1 : packet->payload_packet_len);
+ if(!proxy_enabled) {
+ flow->next_tcp_seq_nr[1 -flow->packet.packet_direction] = ntohl(tcph->ack_seq);
+ }
+ }
+ } else if(packet->payload_packet_len > 0) {
+ /* check tcp sequence counters */
+ if(((u_int32_t)
+ (ntohl(tcph->seq) -
+ flow->next_tcp_seq_nr[packet->packet_direction])) >
+ ndpi_struct->tcp_max_retransmission_window_size) {
+
+ packet->tcp_retransmission = 1;
+
+
+ /*CHECK IF PARTIAL RETRY IS HAPPENENING */
+ if((flow->next_tcp_seq_nr[packet->packet_direction] - ntohl(tcph->seq) < packet->payload_packet_len)) {
+ /* num_retried_bytes actual_payload_len hold info about the partial retry
+ analyzer which require this info can make use of this info
+ Other analyzer can use packet->payload_packet_len */
+ packet->num_retried_bytes = (u_int16_t)(flow->next_tcp_seq_nr[packet->packet_direction] - ntohl(tcph->seq));
+ packet->actual_payload_len = packet->payload_packet_len - packet->num_retried_bytes;
+ flow->next_tcp_seq_nr[packet->packet_direction] = ntohl(tcph->seq) + packet->payload_packet_len;
+ }
+ }
+ /*normal path
+ actual_payload_len is initialized to payload_packet_len during tcp header parsing itself.
+ It will be changed only in case of retransmission */
+ else {
+
+
+ packet->num_retried_bytes = 0;
+ flow->next_tcp_seq_nr[packet->packet_direction] = ntohl(tcph->seq) + packet->payload_packet_len;
+ }
+
+
+ }
+
+ if(tcph->rst) {
+ flow->next_tcp_seq_nr[0] = 0;
+ flow->next_tcp_seq_nr[1] = 0;
+ }
+ } else if(udph != NULL) {
+ if(!ndpi_struct->direction_detect_disable)
+ packet->packet_direction = (udph->source < udph->dest) ? 1 : 0;
+ }
+
+ if(flow->packet_counter < MAX_PACKET_COUNTER && packet->payload_packet_len) {
+ flow->packet_counter++;
+ }
+
+ if(flow->packet_direction_counter[packet->packet_direction] < MAX_PACKET_COUNTER && packet->payload_packet_len) {
+ flow->packet_direction_counter[packet->packet_direction]++;
+ }
+
+ if(flow->byte_counter[packet->packet_direction] + packet->payload_packet_len >
+ flow->byte_counter[packet->packet_direction]) {
+ flow->byte_counter[packet->packet_direction] += packet->payload_packet_len;
+ }
+}
+
+void check_ndpi_other_flow_func(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) {
+ void *func = NULL;
+ u_int32_t a;
+ u_int16_t proto_index = ndpi_struct->proto_defaults[flow->guessed_protocol_id].protoIdx;
+ int16_t proto_id = ndpi_struct->proto_defaults[flow->guessed_protocol_id].protoId;
+ NDPI_PROTOCOL_BITMASK detection_bitmask;
+
+ NDPI_SAVE_AS_BITMASK(detection_bitmask, flow->packet.detected_protocol_stack[0]);
+
+ if((proto_id != NDPI_PROTOCOL_UNKNOWN)
+ && NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask,
+ ndpi_struct->callback_buffer[proto_index].excluded_protocol_bitmask) == 0
+ && NDPI_BITMASK_COMPARE(ndpi_struct->callback_buffer[proto_index].detection_bitmask,
+ detection_bitmask) != 0
+ && (ndpi_struct->callback_buffer[proto_index].ndpi_selection_bitmask
+ & *ndpi_selection_packet) == ndpi_struct->callback_buffer[proto_index].ndpi_selection_bitmask) {
+ if((flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN)
+ && (ndpi_struct->proto_defaults[flow->guessed_protocol_id].func != NULL))
+ ndpi_struct->proto_defaults[flow->guessed_protocol_id].func(ndpi_struct, flow),
+ func = ndpi_struct->proto_defaults[flow->guessed_protocol_id].func;
+ }
+
+ for (a = 0; a < ndpi_struct->callback_buffer_size_non_tcp_udp; a++) {
+ if((func != ndpi_struct->callback_buffer_non_tcp_udp[a].func)
+ && (ndpi_struct->callback_buffer_non_tcp_udp[a].ndpi_selection_bitmask & *ndpi_selection_packet) ==
+ ndpi_struct->callback_buffer_non_tcp_udp[a].ndpi_selection_bitmask
+ && (flow == NULL
+ ||
+ NDPI_BITMASK_COMPARE
+ (flow->excluded_protocol_bitmask,
+ ndpi_struct->callback_buffer_non_tcp_udp[a].excluded_protocol_bitmask) == 0)
+ && NDPI_BITMASK_COMPARE(ndpi_struct->callback_buffer_non_tcp_udp[a].detection_bitmask,
+ detection_bitmask) != 0) {
+
+ if(ndpi_struct->callback_buffer_non_tcp_udp[a].func != NULL)
+ ndpi_struct->callback_buffer_non_tcp_udp[a].func(ndpi_struct, flow);
+
+ if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN)
+ break; /* Stop after detecting the first protocol */
+ }
+ }
+}
+
+
+void check_ndpi_udp_flow_func(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) {
+ void *func = NULL;
+ u_int32_t a;
+ u_int16_t proto_index = ndpi_struct->proto_defaults[flow->guessed_protocol_id].protoIdx;
+ int16_t proto_id = ndpi_struct->proto_defaults[flow->guessed_protocol_id].protoId;
+ NDPI_PROTOCOL_BITMASK detection_bitmask;
+
+ NDPI_SAVE_AS_BITMASK(detection_bitmask, flow->packet.detected_protocol_stack[0]);
+
+ if((proto_id != NDPI_PROTOCOL_UNKNOWN)
+ && NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask,
+ ndpi_struct->callback_buffer[proto_index].excluded_protocol_bitmask) == 0
+ && NDPI_BITMASK_COMPARE(ndpi_struct->callback_buffer[proto_index].detection_bitmask,
+ detection_bitmask) != 0
+ && (ndpi_struct->callback_buffer[proto_index].ndpi_selection_bitmask
+ & *ndpi_selection_packet) == ndpi_struct->callback_buffer[proto_index].ndpi_selection_bitmask) {
+ if((flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN)
+ && (ndpi_struct->proto_defaults[flow->guessed_protocol_id].func != NULL))
+ ndpi_struct->proto_defaults[flow->guessed_protocol_id].func(ndpi_struct, flow),
+ func = ndpi_struct->proto_defaults[flow->guessed_protocol_id].func;
+ }
+
+ for (a = 0; a < ndpi_struct->callback_buffer_size_udp; a++) {
+ if((func != ndpi_struct->callback_buffer_tcp_payload[a].func)
+ && (ndpi_struct->callback_buffer_udp[a].ndpi_selection_bitmask & *ndpi_selection_packet) ==
+ ndpi_struct->callback_buffer_udp[a].ndpi_selection_bitmask
+ && NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask,
+ ndpi_struct->callback_buffer_udp[a].excluded_protocol_bitmask) == 0
+ && NDPI_BITMASK_COMPARE(ndpi_struct->callback_buffer_udp[a].detection_bitmask,
+ detection_bitmask) != 0) {
+ ndpi_struct->callback_buffer_udp[a].func(ndpi_struct, flow);
+ // NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG, "[UDP,CALL] dissector of protocol as callback_buffer idx = %d\n",a);
+ if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN)
+ break; /* Stop after detecting the first protocol */
+ } else
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG,
+ "[UDP,SKIP] dissector of protocol as callback_buffer idx = %d\n",a);
+ }
+}
+
+
+void check_ndpi_tcp_flow_func(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) {
+ void *func = NULL;
+ u_int32_t a;
+ u_int16_t proto_index = ndpi_struct->proto_defaults[flow->guessed_protocol_id].protoIdx;
+ int16_t proto_id = ndpi_struct->proto_defaults[flow->guessed_protocol_id].protoId;
+ NDPI_PROTOCOL_BITMASK detection_bitmask;
+
+ NDPI_SAVE_AS_BITMASK(detection_bitmask, flow->packet.detected_protocol_stack[0]);
+
+ if(flow->packet.payload_packet_len != 0) {
+ if((proto_id != NDPI_PROTOCOL_UNKNOWN)
+ && NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask,
+ ndpi_struct->callback_buffer[proto_index].excluded_protocol_bitmask) == 0
+ && NDPI_BITMASK_COMPARE(ndpi_struct->callback_buffer[proto_index].detection_bitmask,
+ detection_bitmask) != 0
+ && (ndpi_struct->callback_buffer[proto_index].ndpi_selection_bitmask
+ & *ndpi_selection_packet) == ndpi_struct->callback_buffer[proto_index].ndpi_selection_bitmask) {
+ if((flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN)
+ && (ndpi_struct->proto_defaults[flow->guessed_protocol_id].func != NULL))
+ ndpi_struct->proto_defaults[flow->guessed_protocol_id].func(ndpi_struct, flow),
+ func = ndpi_struct->proto_defaults[flow->guessed_protocol_id].func;
+ }
+
+ if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
+ for (a = 0; a < ndpi_struct->callback_buffer_size_tcp_payload; a++) {
+ if((func != ndpi_struct->callback_buffer_tcp_payload[a].func)
+ && (ndpi_struct->callback_buffer_tcp_payload[a].ndpi_selection_bitmask
+ & *ndpi_selection_packet) == ndpi_struct->callback_buffer_tcp_payload[a].ndpi_selection_bitmask
+ && NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask,
+ ndpi_struct->callback_buffer_tcp_payload[a].excluded_protocol_bitmask) == 0
+ && NDPI_BITMASK_COMPARE(ndpi_struct->callback_buffer_tcp_payload[a].detection_bitmask,
+ detection_bitmask) != 0) {
+ ndpi_struct->callback_buffer_tcp_payload[a].func(ndpi_struct, flow);
+
+ if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN)
+ break; /* Stop after detecting the first protocol */
+ }
+ }
+ }
+ } else {
+ /* no payload */
+ if((proto_id != NDPI_PROTOCOL_UNKNOWN)
+ && NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask,
+ ndpi_struct->callback_buffer[proto_index].excluded_protocol_bitmask) == 0
+ && NDPI_BITMASK_COMPARE(ndpi_struct->callback_buffer[proto_index].detection_bitmask,
+ detection_bitmask) != 0
+ && (ndpi_struct->callback_buffer[proto_index].ndpi_selection_bitmask
+ & *ndpi_selection_packet) == ndpi_struct->callback_buffer[proto_index].ndpi_selection_bitmask) {
+ if((flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN)
+ && (ndpi_struct->proto_defaults[flow->guessed_protocol_id].func != NULL)
+ && ((ndpi_struct->callback_buffer[flow->guessed_protocol_id].ndpi_selection_bitmask & NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) == 0))
+ ndpi_struct->proto_defaults[flow->guessed_protocol_id].func(ndpi_struct, flow),
+ func = ndpi_struct->proto_defaults[flow->guessed_protocol_id].func;
+ }
+
+ for (a = 0; a < ndpi_struct->callback_buffer_size_tcp_no_payload; a++) {
+ if((func != ndpi_struct->callback_buffer_tcp_payload[a].func)
+ && (ndpi_struct->callback_buffer_tcp_no_payload[a].ndpi_selection_bitmask & *ndpi_selection_packet) ==
+ ndpi_struct->callback_buffer_tcp_no_payload[a].ndpi_selection_bitmask
+ && NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask,
+ ndpi_struct->
+ callback_buffer_tcp_no_payload[a].excluded_protocol_bitmask) == 0
+ && NDPI_BITMASK_COMPARE(ndpi_struct->callback_buffer_tcp_no_payload[a].detection_bitmask,
+ detection_bitmask) != 0) {
+ ndpi_struct->callback_buffer_tcp_no_payload[a].func(ndpi_struct, flow);
+
+ if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN)
+ break; /* Stop after detecting the first protocol */
+ }
+ }
+ }
+}
+
+void check_ndpi_flow_func(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) {
+ if(flow->packet.tcp != NULL)
+ check_ndpi_tcp_flow_func(ndpi_struct, flow, ndpi_selection_packet);
+ else if(flow->packet.udp != NULL)
+ check_ndpi_udp_flow_func(ndpi_struct, flow, ndpi_selection_packet);
+ else
+ check_ndpi_other_flow_func(ndpi_struct, flow, ndpi_selection_packet);
+}
+
+unsigned int ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ const unsigned char *packet,
+ const unsigned short packetlen,
+ const u_int64_t current_tick_l,
+ struct ndpi_id_struct *src,
+ struct ndpi_id_struct *dst)
+{
+ NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_packet;
+ u_int32_t a;
+
+ if(flow == NULL)
+ return NDPI_PROTOCOL_UNKNOWN;
+
+ if(flow->server_id == NULL) flow->server_id = dst; /* Default */
+ if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN && !flow->no_cache_protocol)
+ return(flow->detected_protocol_stack[0]); /* Stop after detecting the first protocol */
+
+ /* need at least 20 bytes for ip header */
+ if(packetlen < 20) {
+ /* reset protocol which is normally done in init_packet_header */
+ ndpi_int_reset_packet_protocol(&flow->packet);
+
+ return NDPI_PROTOCOL_UNKNOWN;
+ }
+
+ flow->packet.tick_timestamp_l = current_tick_l;
+#ifdef __KERNEL__
+ {
+ u_int64_t d = current_tick_l;
+ do_div(d,1000);
+ flow->packet.tick_timestamp = d;
+ }
+#else
+ flow->packet.tick_timestamp = current_tick_l/1000;
+#endif
+
+ /* parse packet */
+ flow->packet.iph = (struct ndpi_iphdr *) packet;
+ /* we are interested in ipv4 packet */
+
+ if(ndpi_init_packet_header(ndpi_struct, flow, packetlen) != 0)
+ return NDPI_PROTOCOL_UNKNOWN;
+
+ /* detect traffic for tcp or udp only */
+
+ flow->src = src, flow->dst = dst;
+
+ ndpi_connection_tracking(ndpi_struct, flow);
+
+ /* build ndpi_selction packet bitmask */
+ ndpi_selection_packet = NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC;
+ if(flow->packet.iph != NULL) {
+ ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_IP | NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6;
+ }
+ if(flow->packet.tcp != NULL) {
+ ndpi_selection_packet |=
+ (NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP);
+ }
+ if(flow->packet.udp != NULL) {
+ ndpi_selection_packet |=
+ (NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP);
+ }
+ if(flow->packet.payload_packet_len != 0) {
+ ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD;
+ }
+
+ if(flow->packet.tcp_retransmission == 0) {
+ ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION;
+ }
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ if(flow->packet.iphv6 != NULL) {
+ ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6;
+ }
+#endif /* NDPI_DETECTION_SUPPORT_IPV6 */
+
+ if((!flow->protocol_id_already_guessed)
+ && (
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ flow->packet.iphv6 ||
+#endif
+ flow->packet.iph)) {
+ u_int16_t sport, dport;
+ u_int8_t protocol;
+ u_int32_t saddr, daddr;
+
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ if(flow->packet.iphv6 != NULL) {
+ protocol = flow->packet.iphv6->nexthdr, saddr = 0, daddr = 0;
+ } else
+#endif
+ {
+ protocol = flow->packet.iph->protocol;
+ saddr = ntohl(flow->packet.iph->saddr);
+ daddr = ntohl(flow->packet.iph->daddr);
+ }
+
+ if(flow->packet.udp) sport = ntohs(flow->packet.udp->source), dport = ntohs(flow->packet.udp->dest);
+ else if(flow->packet.tcp) sport = ntohs(flow->packet.tcp->source), dport = ntohs(flow->packet.tcp->dest);
+ else sport = dport = 0;
+
+ flow->guessed_protocol_id = (int16_t)ndpi_guess_protocol_id(ndpi_struct, protocol,
+ sport, dport);
+ flow->protocol_id_already_guessed = 1;
+ }
+
+ a = flow->detected_protocol_stack[0];
+ if(a != NDPI_PROTOCOL_UNKNOWN && flow->no_cache_protocol) {
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_TRACE, "PROCESS KNOWN PROTOCOL\n");
+ ndpi_struct->proto_defaults[a].func(ndpi_struct, flow);
+ return a;
+ }
+
+ check_ndpi_flow_func(ndpi_struct, flow, &ndpi_selection_packet);
+
+ a = flow->packet.detected_protocol_stack[0];
+ if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, a) == 0)
+ a = NDPI_PROTOCOL_UNKNOWN;
+
+ if(a != NDPI_PROTOCOL_UNKNOWN) {
+ int i;
+
+ for(i=0; (i<sizeof(flow->host_server_name)) && (flow->host_server_name[i] != '\0'); i++)
+ flow->host_server_name[i] = tolower(flow->host_server_name[i]);
+
+ flow->host_server_name[i] ='\0';
+ }
+
+ return a;
+}
+
+
+u_int32_t ndpi_bytestream_to_number(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read)
+{
+ u_int32_t val;
+ val = 0;
+ // cancel if eof, ' ' or line end chars are reached
+ while (*str >= '0' && *str <= '9' && max_chars_to_read > 0) {
+ val *= 10;
+ val += *str - '0';
+ str++;
+ max_chars_to_read = max_chars_to_read - 1;
+ *bytes_read = *bytes_read + 1;
+ }
+ return (val);
+}
+
+u_int32_t ndpi_bytestream_dec_or_hex_to_number(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read)
+{
+ u_int32_t val;
+ val = 0;
+ if(max_chars_to_read <= 2 || str[0] != '0' || str[1] != 'x') {
+ return ndpi_bytestream_to_number(str, max_chars_to_read, bytes_read);
+ } else {
+ /*use base 16 system */
+ str += 2;
+ max_chars_to_read -= 2;
+ *bytes_read = *bytes_read + 2;
+ while (max_chars_to_read > 0) {
+
+ if(*str >= '0' && *str <= '9') {
+ val *= 16;
+ val += *str - '0';
+ } else if(*str >= 'a' && *str <= 'f') {
+ val *= 16;
+ val += *str + 10 - 'a';
+ } else if(*str >= 'A' && *str <= 'F') {
+ val *= 16;
+ val += *str + 10 - 'A';
+ } else {
+ break;
+ }
+ str++;
+ max_chars_to_read = max_chars_to_read - 1;
+ *bytes_read = *bytes_read + 1;
+ }
+ }
+ return (val);
+}
+
+
+u_int64_t ndpi_bytestream_to_number64(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read)
+{
+ u_int64_t val;
+ val = 0;
+ // cancel if eof, ' ' or line end chars are reached
+ while (max_chars_to_read > 0 && *str >= '0' && *str <= '9') {
+ val *= 10;
+ val += *str - '0';
+ str++;
+ max_chars_to_read = max_chars_to_read - 1;
+ *bytes_read = *bytes_read + 1;
+ }
+ return (val);
+}
+
+u_int64_t ndpi_bytestream_dec_or_hex_to_number64(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read)
+{
+ u_int64_t val;
+ val = 0;
+ if(max_chars_to_read <= 2 || str[0] != '0' || str[1] != 'x') {
+ return ndpi_bytestream_to_number64(str, max_chars_to_read, bytes_read);
+ } else {
+ /*use base 16 system */
+ str += 2;
+ max_chars_to_read -= 2;
+ *bytes_read = *bytes_read + 2;
+ while (max_chars_to_read > 0) {
+
+ if(*str >= '0' && *str <= '9') {
+ val *= 16;
+ val += *str - '0';
+ } else if(*str >= 'a' && *str <= 'f') {
+ val *= 16;
+ val += *str + 10 - 'a';
+ } else if(*str >= 'A' && *str <= 'F') {
+ val *= 16;
+ val += *str + 10 - 'A';
+ } else {
+ break;
+ }
+ str++;
+ max_chars_to_read = max_chars_to_read - 1;
+ *bytes_read = *bytes_read + 1;
+ }
+ }
+ return (val);
+}
+
+
+u_int32_t ndpi_bytestream_to_ipv4(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read)
+{
+ u_int32_t val;
+ u_int16_t read = 0;
+ u_int16_t oldread;
+ u_int32_t c;
+ /* ip address must be X.X.X.X with each X between 0 and 255 */
+ oldread = read;
+ c = ndpi_bytestream_to_number(str, max_chars_to_read, &read);
+ if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.')
+ return 0;
+ read++;
+ val = c << 24;
+ oldread = read;
+ c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read);
+ if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.')
+ return 0;
+ read++;
+ val = val + (c << 16);
+ oldread = read;
+ c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read);
+ if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.')
+ return 0;
+ read++;
+ val = val + (c << 8);
+ oldread = read;
+ c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read);
+ if(c > 255 || oldread == read || max_chars_to_read == read)
+ return 0;
+ val = val + c;
+
+ *bytes_read = *bytes_read + read;
+
+ return htonl(val);
+}
+
+/* internal function for every detection to parse one packet and to increase the info buffer */
+void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ u_int32_t a;
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t end = packet->payload_packet_len - 1;
+ if(packet->packet_lines_parsed_complete != 0)
+ return;
+
+ packet->packet_lines_parsed_complete = 1;
+ packet->parsed_lines = 0;
+
+ packet->empty_line_position_set = 0;
+
+ packet->host_line.ptr = NULL;
+ packet->host_line.len = 0;
+ packet->referer_line.ptr = NULL;
+ packet->referer_line.len = 0;
+ packet->content_line.ptr = NULL;
+ packet->content_line.len = 0;
+ packet->accept_line.ptr = NULL;
+ packet->accept_line.len = 0;
+ packet->user_agent_line.ptr = NULL;
+ packet->user_agent_line.len = 0;
+ packet->http_url_name.ptr = NULL;
+ packet->http_url_name.len = 0;
+ packet->http_encoding.ptr = NULL;
+ packet->http_encoding.len = 0;
+ packet->http_transfer_encoding.ptr = NULL;
+ packet->http_transfer_encoding.len = 0;
+ packet->http_contentlen.ptr = NULL;
+ packet->http_contentlen.len = 0;
+ packet->http_cookie.ptr = NULL;
+ packet->http_cookie.len = 0;
+ packet->http_origin.len = 0;
+ packet->http_origin.ptr = NULL;
+ packet->http_x_session_type.ptr = NULL;
+ packet->http_x_session_type.len = 0;
+ packet->server_line.ptr = NULL;
+ packet->server_line.len = 0;
+ packet->http_method.ptr = NULL;
+ packet->http_method.len = 0;
+ packet->http_response.ptr = NULL;
+ packet->http_response.len = 0;
+
+ if((packet->payload_packet_len == 0)
+ || (packet->payload == NULL))
+ return;
+
+ packet->line[packet->parsed_lines].ptr = packet->payload;
+ packet->line[packet->parsed_lines].len = 0;
+
+ for (a = 0; a < end; a++) {
+ if(get_u_int16_t(packet->payload, a) == ntohs(0x0d0a)) {
+ packet->line[packet->parsed_lines].len = (u_int16_t)(((unsigned long) &packet->payload[a]) - ((unsigned long) packet->line[packet->parsed_lines].ptr));
+
+ if(packet->parsed_lines == 0 && packet->line[0].len >= NDPI_STATICSTRING_LEN("HTTP/1.1 200 ") &&
+ memcmp(packet->line[0].ptr, "HTTP/1.", NDPI_STATICSTRING_LEN("HTTP/1.")) == 0 &&
+ packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.1 ")] > '0' &&
+ packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.1 ")] < '6') {
+ packet->http_response.ptr = &packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.1 ")];
+ packet->http_response.len = packet->line[0].len - NDPI_STATICSTRING_LEN("HTTP/1.1 ");
+ NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG,
+ "ndpi_parse_packet_line_info: HTTP response parsed: \"%.*s\"\n",
+ packet->http_response.len, packet->http_response.ptr);
+ }
+ if(packet->line[packet->parsed_lines].len > NDPI_STATICSTRING_LEN("Server:") + 1
+ && memcmp(packet->line[packet->parsed_lines].ptr, "Server:", NDPI_STATICSTRING_LEN("Server:")) == 0) {
+ // some stupid clients omit a space and place the servername directly after the colon
+ if(packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:")] == ' ') {
+ packet->server_line.ptr =
+ &packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:") + 1];
+ packet->server_line.len =
+ packet->line[packet->parsed_lines].len - (NDPI_STATICSTRING_LEN("Server:") + 1);
+ } else {
+ packet->server_line.ptr = &packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:")];
+ packet->server_line.len = packet->line[packet->parsed_lines].len - NDPI_STATICSTRING_LEN("Server:");
+ }
+ }
+
+ if(packet->line[packet->parsed_lines].len > 6
+ && memcmp(packet->line[packet->parsed_lines].ptr, "Host:", 5) == 0) {
+ // some stupid clients omit a space and place the hostname directly after the colon
+ if(packet->line[packet->parsed_lines].ptr[5] == ' ') {
+ packet->host_line.ptr = &packet->line[packet->parsed_lines].ptr[6];
+ packet->host_line.len = packet->line[packet->parsed_lines].len - 6;
+ } else {
+ packet->host_line.ptr = &packet->line[packet->parsed_lines].ptr[5];
+ packet->host_line.len = packet->line[packet->parsed_lines].len - 5;
+ }
+ }
+
+ if(packet->line[packet->parsed_lines].len > 17
+ && memcmp(packet->line[packet->parsed_lines].ptr, "X-Forwarded-For:", 16) == 0) {
+ // some stupid clients omit a space and place the hostname directly after the colon
+ if(packet->line[packet->parsed_lines].ptr[16] == ' ') {
+ packet->forwarded_line.ptr = &packet->line[packet->parsed_lines].ptr[17];
+ packet->forwarded_line.len = packet->line[packet->parsed_lines].len - 17;
+ } else {
+ packet->forwarded_line.ptr = &packet->line[packet->parsed_lines].ptr[16];
+ packet->forwarded_line.len = packet->line[packet->parsed_lines].len - 16;
+ }
+ }
+
+ if(packet->line[packet->parsed_lines].len > 14
+ &&
+ (memcmp
+ (packet->line[packet->parsed_lines].ptr, "Content-Type: ",
+ 14) == 0 || memcmp(packet->line[packet->parsed_lines].ptr, "Content-type: ", 14) == 0)) {
+ packet->content_line.ptr = &packet->line[packet->parsed_lines].ptr[14];
+ packet->content_line.len = packet->line[packet->parsed_lines].len - 14;
+ }
+
+ if(packet->line[packet->parsed_lines].len > 13
+ && memcmp(packet->line[packet->parsed_lines].ptr, "Content-type:", 13) == 0) {
+ packet->content_line.ptr = &packet->line[packet->parsed_lines].ptr[13];
+ packet->content_line.len = packet->line[packet->parsed_lines].len - 13;
+ }
+
+ if(packet->line[packet->parsed_lines].len > 8
+ && memcmp(packet->line[packet->parsed_lines].ptr, "Accept: ", 8) == 0) {
+ packet->accept_line.ptr = &packet->line[packet->parsed_lines].ptr[8];
+ packet->accept_line.len = packet->line[packet->parsed_lines].len - 8;
+ }
+
+ if(packet->line[packet->parsed_lines].len > 9
+ && memcmp(packet->line[packet->parsed_lines].ptr, "Referer: ", 9) == 0) {
+ packet->referer_line.ptr = &packet->line[packet->parsed_lines].ptr[9];
+ packet->referer_line.len = packet->line[packet->parsed_lines].len - 9;
+ }
+
+ if(packet->line[packet->parsed_lines].len > 12
+ && (memcmp(packet->line[packet->parsed_lines].ptr, "User-Agent: ", 12) == 0 ||
+ memcmp(packet->line[packet->parsed_lines].ptr, "User-agent: ", 12) == 0)) {
+ packet->user_agent_line.ptr = &packet->line[packet->parsed_lines].ptr[12];
+ packet->user_agent_line.len = packet->line[packet->parsed_lines].len - 12;
+ }
+
+ if(packet->line[packet->parsed_lines].len > 18
+ && memcmp(packet->line[packet->parsed_lines].ptr, "Content-Encoding: ", 18) == 0) {
+ packet->http_encoding.ptr = &packet->line[packet->parsed_lines].ptr[18];
+ packet->http_encoding.len = packet->line[packet->parsed_lines].len - 18;
+ }
+
+ if(packet->line[packet->parsed_lines].len > 19
+ && memcmp(packet->line[packet->parsed_lines].ptr, "Transfer-Encoding: ", 19) == 0) {
+ packet->http_transfer_encoding.ptr = &packet->line[packet->parsed_lines].ptr[19];
+ packet->http_transfer_encoding.len = packet->line[packet->parsed_lines].len - 19;
+ }
+ if(packet->line[packet->parsed_lines].len > 16
+ && ((memcmp(packet->line[packet->parsed_lines].ptr, "Content-Length: ", 16) == 0)
+ || (memcmp(packet->line[packet->parsed_lines].ptr, "content-length: ", 16) == 0))) {
+ packet->http_contentlen.ptr = &packet->line[packet->parsed_lines].ptr[16];
+ packet->http_contentlen.len = packet->line[packet->parsed_lines].len - 16;
+ }
+ if(packet->line[packet->parsed_lines].len > 8
+ && memcmp(packet->line[packet->parsed_lines].ptr, "Cookie: ", 8) == 0) {
+ packet->http_cookie.ptr = &packet->line[packet->parsed_lines].ptr[8];
+ packet->http_cookie.len = packet->line[packet->parsed_lines].len - 8;
+ }
+ if(packet->line[packet->parsed_lines].len > 8
+ && memcmp(packet->line[packet->parsed_lines].ptr, "Origin: ", 8) == 0) {
+ packet->http_origin.ptr = &packet->line[packet->parsed_lines].ptr[8];
+ packet->http_origin.len = packet->line[packet->parsed_lines].len - 8;
+ }
+ if(packet->line[packet->parsed_lines].len > 16
+ && memcmp(packet->line[packet->parsed_lines].ptr, "X-Session-Type: ", 16) == 0) {
+ packet->http_x_session_type.ptr = &packet->line[packet->parsed_lines].ptr[16];
+ packet->http_x_session_type.len = packet->line[packet->parsed_lines].len - 16;
+ }
+
+
+ if(packet->line[packet->parsed_lines].len == 0) {
+ packet->empty_line_position = a;
+ packet->empty_line_position_set = 1;
+ }
+
+ if(packet->parsed_lines >= (NDPI_MAX_PARSE_LINES_PER_PACKET - 1)) {
+ return;
+ }
+
+ packet->parsed_lines++;
+ packet->line[packet->parsed_lines].ptr = &packet->payload[a + 2];
+ packet->line[packet->parsed_lines].len = 0;
+
+ if((a + 2) >= packet->payload_packet_len) {
+
+ return;
+ }
+ a++;
+ }
+ }
+
+ if(packet->parsed_lines >= 1) {
+ packet->line[packet->parsed_lines].len
+ = (u_int16_t)(((unsigned long) &packet->payload[packet->payload_packet_len]) -
+ ((unsigned long) packet->line[packet->parsed_lines].ptr));
+ packet->parsed_lines++;
+ }
+}
+
+void ndpi_parse_packet_line_info_any(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t a;
+ u_int16_t end = packet->payload_packet_len;
+ if(packet->packet_lines_parsed_complete != 0)
+ return;
+
+
+
+ packet->packet_lines_parsed_complete = 1;
+ packet->parsed_lines = 0;
+
+ if(packet->payload_packet_len == 0)
+ return;
+
+ packet->line[packet->parsed_lines].ptr = packet->payload;
+ packet->line[packet->parsed_lines].len = 0;
+
+ for (a = 0; a < end; a++) {
+ if(packet->payload[a] == 0x0a) {
+ packet->line[packet->parsed_lines].len = (u_int16_t)(
+ ((unsigned long) &packet->payload[a]) -
+ ((unsigned long) packet->line[packet->parsed_lines].ptr));
+ if(a > 0 && packet->payload[a-1] == 0x0d)
+ packet->line[packet->parsed_lines].len--;
+
+ if(packet->parsed_lines >= (NDPI_MAX_PARSE_LINES_PER_PACKET - 1)) {
+ break;
+ }
+
+ packet->parsed_lines++;
+ packet->line[packet->parsed_lines].ptr = &packet->payload[a + 1];
+ packet->line[packet->parsed_lines].len = 0;
+
+ if((a + 1) >= packet->payload_packet_len) {
+ break;
+ }
+ //a++;
+ }
+ }
+}
+
+
+u_int16_t ndpi_check_for_email_address(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, u_int16_t counter)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "called ndpi_check_for_email_address\n");
+
+ if(packet->payload_packet_len > counter && ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z')
+ || (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z')
+ || (packet->payload[counter] >= '0' && packet->payload[counter] <= '9')
+ || packet->payload[counter] == '-' || packet->payload[counter] == '_')) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "first letter\n");
+ counter++;
+ while (packet->payload_packet_len > counter
+ && ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z')
+ || (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z')
+ || (packet->payload[counter] >= '0' && packet->payload[counter] <= '9')
+ || packet->payload[counter] == '-' || packet->payload[counter] == '_'
+ || packet->payload[counter] == '.')) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "further letter\n");
+ counter++;
+ if(packet->payload_packet_len > counter && packet->payload[counter] == '@') {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "@\n");
+ counter++;
+ while (packet->payload_packet_len > counter
+ && ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z')
+ || (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z')
+ || (packet->payload[counter] >= '0' && packet->payload[counter] <= '9')
+ || packet->payload[counter] == '-' || packet->payload[counter] == '_')) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "letter\n");
+ counter++;
+ if(packet->payload_packet_len > counter && packet->payload[counter] == '.') {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, ".\n");
+ counter++;
+ if(packet->payload_packet_len > counter + 1
+ && ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z')
+ && (packet->payload[counter + 1] >= 'a' && packet->payload[counter + 1] <= 'z'))) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "two letters\n");
+ counter += 2;
+ if(packet->payload_packet_len > counter
+ && (packet->payload[counter] == ' ' || packet->payload[counter] == ';')) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "whitespace1\n");
+ return counter;
+ } else if(packet->payload_packet_len > counter && packet->payload[counter] >= 'a'
+ && packet->payload[counter] <= 'z') {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "one letter\n");
+ counter++;
+ if(packet->payload_packet_len > counter
+ && (packet->payload[counter] == ' ' || packet->payload[counter] == ';')) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "whitespace2\n");
+ return counter;
+ } else if(packet->payload_packet_len > counter && packet->payload[counter] >= 'a'
+ && packet->payload[counter] <= 'z') {
+ counter++;
+ if(packet->payload_packet_len > counter
+ && (packet->payload[counter] == ' ' || packet->payload[counter] == ';')) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "whitespace3\n");
+ return counter;
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ }
+ }
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
+
+#ifdef NDPI_ENABLE_DEBUG_MESSAGES
+void ndpi_debug_get_last_log_function_line(struct ndpi_detection_module_struct
+ *ndpi_struct, const char **file, const char **func, u_int32_t * line)
+{
+ *file = "";
+ *func = "";
+
+ if(ndpi_struct->ndpi_debug_print_file != NULL)
+ *file = ndpi_struct->ndpi_debug_print_file;
+
+ if(ndpi_struct->ndpi_debug_print_function != NULL)
+ *func = ndpi_struct->ndpi_debug_print_function;
+
+ *line = ndpi_struct->ndpi_debug_print_line;
+}
+#endif
+u_int8_t ndpi_detection_get_l4(const u_int8_t * l3, u_int16_t l3_len, const u_int8_t ** l4_return, u_int16_t * l4_len_return,
+ u_int8_t * l4_protocol_return, u_int32_t flags)
+{
+ return ndpi_detection_get_l4_internal(NULL, l3, l3_len, l4_return, l4_len_return, l4_protocol_return, flags);
+}
+
+void ndpi_int_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t detected_protocol, ndpi_protocol_type_t protocol_type)
+{
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ ndpi_int_change_protocol(ndpi_struct, flow, detected_protocol, protocol_type);
+
+ if(src != NULL) {
+ NDPI_ADD_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, detected_protocol);
+ }
+ if(dst != NULL) {
+ NDPI_ADD_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, detected_protocol);
+ }
+}
+
+void ndpi_int_change_flow_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t detected_protocol, ndpi_protocol_type_t protocol_type)
+{
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+ u_int8_t a;
+ u_int8_t stack_size;
+ u_int8_t new_is_real = 0;
+ u_int16_t preserve_bitmask;
+#endif
+
+ if(!flow)
+ return;
+
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+ stack_size = flow->protocol_stack_info.current_stack_size_minus_one + 1;
+
+ /* here are the rules for stack manipulations:
+ * 1.if the new protocol is a real protocol, insert it at the position
+ * of the top-most real protocol or below the last non-unknown correlated
+ * protocol.
+ * 2.if the new protocol is not real, put it on top of stack but if there is
+ * a real protocol in the stack, make sure at least one real protocol remains
+ * in the stack
+ */
+
+ if(protocol_type == NDPI_CORRELATED_PROTOCOL) {
+ u_int16_t saved_real_protocol = NDPI_PROTOCOL_UNKNOWN;
+
+ if(stack_size == NDPI_PROTOCOL_HISTORY_SIZE) {
+ /* check whether we will lost real protocol information due to shifting */
+ u_int16_t real_protocol = flow->protocol_stack_info.entry_is_real_protocol;
+
+ for (a = 0; a < stack_size; a++) {
+ if(real_protocol & 1)
+ break;
+ real_protocol >>= 1;
+ }
+
+ if(a == (stack_size - 1)) {
+ /* oh, only one real protocol at the end, store it and insert it later */
+ saved_real_protocol = flow->detected_protocol_stack[stack_size - 1];
+ }
+ } else {
+ flow->protocol_stack_info.current_stack_size_minus_one++;
+ stack_size++;
+ }
+
+ /* now shift and insert */
+ for (a = stack_size - 1; a > 0; a--) {
+ flow->detected_protocol_stack[a] = flow->detected_protocol_stack[a - 1];
+ }
+
+ flow->protocol_stack_info.entry_is_real_protocol <<= 1;
+
+ /* now set the new protocol */
+
+ flow->detected_protocol_stack[0] = detected_protocol;
+
+ /* restore real protocol */
+ if(saved_real_protocol != NDPI_PROTOCOL_UNKNOWN) {
+ flow->detected_protocol_stack[stack_size - 1] = saved_real_protocol;
+ flow->protocol_stack_info.entry_is_real_protocol |= 1 << (stack_size - 1);
+ }
+ /* done */
+ } else {
+ u_int8_t insert_at = 0;
+
+ if(!(flow->protocol_stack_info.entry_is_real_protocol & 1)) {
+ u_int16_t real_protocol = flow->protocol_stack_info.entry_is_real_protocol;
+
+ for (a = 0; a < stack_size; a++) {
+ if(real_protocol & 1)
+ break;
+ real_protocol >>= 1;
+ }
+
+ insert_at = a;
+ }
+
+ if(insert_at >= stack_size) {
+ /* no real protocol found, insert it at the bottom */
+
+ insert_at = stack_size - 1;
+ }
+
+ if(stack_size < NDPI_PROTOCOL_HISTORY_SIZE) {
+ flow->protocol_stack_info.current_stack_size_minus_one++;
+ stack_size++;
+ }
+
+ /* first shift all stacks */
+ for (a = stack_size - 1; a > insert_at; a--) {
+ flow->detected_protocol_stack[a] = flow->detected_protocol_stack[a - 1];
+ }
+
+ preserve_bitmask = (1 << insert_at) - 1;
+
+ new_is_real = (flow->protocol_stack_info.entry_is_real_protocol & (~preserve_bitmask)) << 1;
+ new_is_real |= flow->protocol_stack_info.entry_is_real_protocol & preserve_bitmask;
+
+ flow->protocol_stack_info.entry_is_real_protocol = new_is_real;
+
+ /* now set the new protocol */
+
+ flow->detected_protocol_stack[insert_at] = detected_protocol;
+
+ /* and finally update the additional stack information */
+
+ flow->protocol_stack_info.entry_is_real_protocol |= 1 << insert_at;
+ }
+#else
+ flow->detected_protocol_stack[0] = detected_protocol;
+ flow->detected_subprotocol_stack[0] = detected_subprotocol;
+#endif
+}
+
+void ndpi_int_change_packet_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t detected_protocol, ndpi_protocol_type_t protocol_type)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ /* NOTE: everything below is identically to change_flow_protocol
+ * except flow->packet If you want to change something here,
+ * don't! Change it for the flow function and apply it here
+ * as well */
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+ u_int8_t a;
+ u_int8_t stack_size;
+ u_int16_t new_is_real = 0;
+ u_int16_t preserve_bitmask;
+#endif
+
+ if(!packet)
+ return;
+
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+ stack_size = packet->protocol_stack_info.current_stack_size_minus_one + 1;
+
+ /* here are the rules for stack manipulations:
+ * 1.if the new protocol is a real protocol, insert it at the position
+ * of the top-most real protocol or below the last non-unknown correlated
+ * protocol.
+ * 2.if the new protocol is not real, put it on top of stack but if there is
+ * a real protocol in the stack, make sure at least one real protocol remains
+ * in the stack
+ */
+
+ if(protocol_type == NDPI_CORRELATED_PROTOCOL) {
+ u_int16_t saved_real_protocol = NDPI_PROTOCOL_UNKNOWN;
+
+ if(stack_size == NDPI_PROTOCOL_HISTORY_SIZE) {
+ /* check whether we will lost real protocol information due to shifting */
+ u_int16_t real_protocol = packet->protocol_stack_info.entry_is_real_protocol;
+
+ for (a = 0; a < stack_size; a++) {
+ if(real_protocol & 1)
+ break;
+ real_protocol >>= 1;
+ }
+
+ if(a == (stack_size - 1)) {
+ /* oh, only one real protocol at the end, store it and insert it later */
+ saved_real_protocol = packet->detected_protocol_stack[stack_size - 1];
+ }
+ } else {
+ packet->protocol_stack_info.current_stack_size_minus_one++;
+ stack_size++;
+ }
+
+ /* now shift and insert */
+ for (a = stack_size - 1; a > 0; a--) {
+ packet->detected_protocol_stack[a] = packet->detected_protocol_stack[a - 1];
+ }
+
+ packet->protocol_stack_info.entry_is_real_protocol <<= 1;
+
+ /* now set the new protocol */
+
+ packet->detected_protocol_stack[0] = detected_protocol;
+
+ /* restore real protocol */
+ if(saved_real_protocol != NDPI_PROTOCOL_UNKNOWN) {
+ packet->detected_protocol_stack[stack_size - 1] = saved_real_protocol;
+ packet->protocol_stack_info.entry_is_real_protocol |= 1 << (stack_size - 1);
+ }
+ /* done */
+ } else {
+ u_int8_t insert_at = 0;
+
+ if(!(packet->protocol_stack_info.entry_is_real_protocol & 1)) {
+ u_int16_t real_protocol = packet->protocol_stack_info.entry_is_real_protocol;
+
+ for (a = 0; a < stack_size; a++) {
+ if(real_protocol & 1)
+ break;
+ real_protocol >>= 1;
+ }
+
+ insert_at = a;
+ }
+
+ if(insert_at >= stack_size) {
+ /* no real protocol found, insert it at the first unknown protocol */
+
+ insert_at = stack_size - 1;
+ }
+
+ if(stack_size < NDPI_PROTOCOL_HISTORY_SIZE) {
+ packet->protocol_stack_info.current_stack_size_minus_one++;
+ stack_size++;
+ }
+
+ /* first shift all stacks */
+ for (a = stack_size - 1; a > insert_at; a--) {
+ packet->detected_protocol_stack[a] = packet->detected_protocol_stack[a - 1];
+ }
+
+ preserve_bitmask = (1 << insert_at) - 1;
+
+ new_is_real = (packet->protocol_stack_info.entry_is_real_protocol & (~preserve_bitmask)) << 1;
+ new_is_real |= packet->protocol_stack_info.entry_is_real_protocol & preserve_bitmask;
+
+ packet->protocol_stack_info.entry_is_real_protocol = (u_int8_t)new_is_real;
+
+ /* now set the new protocol */
+
+ packet->detected_protocol_stack[insert_at] = detected_protocol;
+
+ /* and finally update the additional stack information */
+
+ packet->protocol_stack_info.entry_is_real_protocol |= 1 << insert_at;
+ }
+#else
+ packet->detected_protocol_stack[0] = detected_protocol;
+ packet->detected_subprotocol_stack[0] = detected_subprotocol;
+#endif
+}
+
+
+/*
+ * this function returns the real protocol of the flow. Actually it
+ * accesses the packet stack since this is what leaves the library but
+ * it could also use the flow stack.
+ */
+u_int16_t ndpi_detection_get_real_protocol_of_flow(struct ndpi_detection_module_struct * ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+ u_int8_t a;
+ u_int8_t stack_size;
+ u_int16_t real_protocol;
+#endif
+
+ if(!packet)
+ return NDPI_PROTOCOL_UNKNOWN;
+
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+ stack_size = packet->protocol_stack_info.current_stack_size_minus_one + 1;
+ real_protocol = packet->protocol_stack_info.entry_is_real_protocol;
+
+ for (a = 0; a < stack_size; a++) {
+ if(real_protocol & 1)
+ return packet->detected_protocol_stack[a];
+ real_protocol >>= 1;
+ }
+
+ return NDPI_PROTOCOL_UNKNOWN;
+#else
+ return packet->detected_protocol_stack[0];
+#endif
+}
+
+/*
+ * this function checks whether a protocol can be found in the
+ * history. Actually it accesses the packet stack since this is what
+ * leaves the library but it could also use the flow stack.
+ */
+u_int8_t ndpi_detection_flow_protocol_history_contains_protocol(struct ndpi_detection_module_struct * ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t protocol_id)
+{
+ u_int8_t a;
+ u_int8_t stack_size;
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(!packet)
+ return 0;
+
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+ stack_size = packet->protocol_stack_info.current_stack_size_minus_one + 1;
+#else
+ stack_size = 1;
+#endif
+
+ for (a = 0; a < stack_size; a++) {
+ if(packet->detected_protocol_stack[a] == protocol_id)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* generic function for setting a protocol for a flow
+ *
+ * what it does is:
+ * 1.call ndpi_int_change_protocol
+ * 2.set protocol in detected bitmask for src and dst
+ */
+void ndpi_int_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t detected_protocol, ndpi_protocol_type_t protocol_type);
+
+/* generic function for changing the flow protocol
+ *
+ * what it does is:
+ * 1.update the flow protocol stack with the new protocol
+ */
+void ndpi_int_change_flow_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t detected_protocol, ndpi_protocol_type_t protocol_type);
+
+/* generic function for changing the packetprotocol
+ *
+ * what it does is:
+ * 1.update the packet protocol stack with the new protocol
+ */
+void ndpi_int_change_packet_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t detected_protocol, ndpi_protocol_type_t protocol_type);
+
+/* generic function for changing the protocol
+ *
+ * what it does is:
+ * 1.update the flow protocol stack with the new protocol
+ * 2.update the packet protocol stack with the new protocol
+ */
+void ndpi_int_change_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int16_t detected_protocol,
+ ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_change_flow_protocol(ndpi_struct, flow, detected_protocol, protocol_type);
+ ndpi_int_change_packet_protocol(ndpi_struct, flow, detected_protocol, protocol_type);
+}
+
+
+/* turns a packet back to unknown */
+void ndpi_int_reset_packet_protocol(struct ndpi_packet_struct *packet) {
+ packet->detected_protocol_stack[0] = NDPI_PROTOCOL_UNKNOWN;
+
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+ packet->protocol_stack_info.current_stack_size_minus_one = 0;
+ packet->protocol_stack_info.entry_is_real_protocol = 0;
+#endif
+}
+
+void ndpi_int_reset_protocol(struct ndpi_flow_struct *flow)
+{
+ if(flow) {
+ flow->detected_protocol_stack[0] = NDPI_PROTOCOL_UNKNOWN;
+
+#if NDPI_PROTOCOL_HISTORY_SIZE > 1
+ flow->protocol_stack_info.current_stack_size_minus_one = 0;
+ flow->protocol_stack_info.entry_is_real_protocol = 0;
+#endif
+ }
+}
+
+void NDPI_PROTOCOL_IP_clear(ndpi_ip_addr_t * ip)
+{
+ memset(ip, 0, sizeof(ndpi_ip_addr_t));
+}
+
+/* NTOP */
+int NDPI_PROTOCOL_IP_is_set(const ndpi_ip_addr_t * ip)
+{
+ return memcmp(ip, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(ndpi_ip_addr_t)) != 0;
+}
+
+/* check if the source ip address in packet and ip are equal */
+/* NTOP */
+int ndpi_packet_src_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t * ip)
+{
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ if(packet->iphv6 != NULL) {
+ if(packet->iphv6->saddr.ndpi_v6_u.u6_addr64[0] == ip->ipv6.ndpi_v6_u.u6_addr64[0] &&
+ packet->iphv6->saddr.ndpi_v6_u.u6_addr64[1] == ip->ipv6.ndpi_v6_u.u6_addr64[1]) {
+
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+#endif
+ if(packet->iph->saddr == ip->ipv4) {
+ return 1;
+ }
+ return 0;
+}
+
+/* check if the destination ip address in packet and ip are equal */
+int ndpi_packet_dst_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t * ip)
+{
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ if(packet->iphv6 != NULL) {
+ if(packet->iphv6->daddr.ndpi_v6_u.u6_addr64[0] == ip->ipv6.ndpi_v6_u.u6_addr64[0] &&
+ packet->iphv6->daddr.ndpi_v6_u.u6_addr64[1] == ip->ipv6.ndpi_v6_u.u6_addr64[1]) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+#endif
+ if(packet->iph->daddr == ip->ipv4) {
+ return 1;
+ }
+ return 0;
+}
+
+/* get the source ip address from packet and put it into ip */
+/* NTOP */
+void ndpi_packet_src_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t * ip)
+{
+ NDPI_PROTOCOL_IP_clear(ip);
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ if(packet->iphv6 != NULL) {
+ ip->ipv6.ndpi_v6_u.u6_addr64[0] = packet->iphv6->saddr.ndpi_v6_u.u6_addr64[0];
+ ip->ipv6.ndpi_v6_u.u6_addr64[1] = packet->iphv6->saddr.ndpi_v6_u.u6_addr64[1];
+ } else
+#endif
+ ip->ipv4 = packet->iph->saddr;
+}
+
+/* get the destination ip address from packet and put it into ip */
+/* NTOP */
+void ndpi_packet_dst_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t * ip)
+{
+ NDPI_PROTOCOL_IP_clear(ip);
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ if(packet->iphv6 != NULL) {
+ ip->ipv6.ndpi_v6_u.u6_addr64[0] = packet->iphv6->daddr.ndpi_v6_u.u6_addr64[0];
+ ip->ipv6.ndpi_v6_u.u6_addr64[1] = packet->iphv6->daddr.ndpi_v6_u.u6_addr64[1];
+ } else
+#endif
+ ip->ipv4 = packet->iph->daddr;
+}
+
+#ifdef NDPI_ENABLE_DEBUG_MESSAGES
+/* get the string representation of ip
+ * returns a pointer to a static string
+ * only valid until the next call of this function */
+char *ndpi_get_ip_string(struct ndpi_detection_module_struct *ndpi_struct,
+ const ndpi_ip_addr_t * ip)
+{
+ const u_int8_t *a = (const u_int8_t *) &ip->ipv4;
+
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ if(ip->ipv6.ndpi_v6_u.u6_addr32[1] != 0 || ip->ipv6.ndpi_v6_u.u6_addr64[1] != 0) {
+ const u_int16_t *b = ip->ipv6.ndpi_v6_u.u6_addr16;
+ snprintf(ndpi_struct->ip_string, 32, "%x:%x:%x:%x:%x:%x:%x:%x",
+ ntohs(b[0]), ntohs(b[1]), ntohs(b[2]), ntohs(b[3]),
+ ntohs(b[4]), ntohs(b[5]), ntohs(b[6]), ntohs(b[7]));
+ return ndpi_struct->ip_string;
+ }
+#endif
+ snprintf(ndpi_struct->ip_string, 32, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
+ return ndpi_struct->ip_string;
+
+}
+
+
+/* get the string representation of the source ip address from packet */
+char *ndpi_get_packet_src_ip_string(struct ndpi_detection_module_struct *ndpi_struct,
+ const struct ndpi_packet_struct *packet)
+{
+ ndpi_ip_addr_t ip;
+ ndpi_packet_src_ip_get(packet, &ip);
+ return ndpi_get_ip_string(ndpi_struct, &ip);
+}
+
+/* get the string representation of the destination ip address from packet */
+char *ndpi_get_packet_dst_ip_string(struct ndpi_detection_module_struct *ndpi_struct,
+ const struct ndpi_packet_struct *packet)
+{
+ ndpi_ip_addr_t ip;
+ ndpi_packet_dst_ip_get(packet, &ip);
+ return ndpi_get_ip_string(ndpi_struct, &ip);
+}
+#endif /* NDPI_ENABLE_DEBUG_MESSAGES */
+
+/* ****************************************************** */
+
+u_int16_t ntohs_ndpi_bytestream_to_number(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read)
+{
+ u_int16_t val = ndpi_bytestream_to_number(str, max_chars_to_read, bytes_read);
+ return ntohs(val);
+}
+
+/* ****************************************************** */
+
+#if 0
+#ifndef __KERNEL__
+static u_int is_port(u_int16_t sport, u_int16_t dport, u_int16_t match_port) {
+ return(((match_port == sport) || (match_port == dport)) ? 1 : 0);
+}
+#endif
+#endif
+
+/* ****************************************************** */
+
+unsigned int ndpi_find_port_based_protocol(struct ndpi_detection_module_struct *ndpi_struct /* NOTUSED */,
+ u_int8_t proto,
+ u_int32_t shost, u_int16_t sport,
+ u_int32_t dhost, u_int16_t dport) {
+ /* Skyfile (host 193.252.234.246 or host 10.10.102.80) */
+ if((shost == 0xC1FCEAF6) || (dhost == 0xC1FCEAF6)
+ || (shost == 0x0A0A6650) || (dhost == 0x0A0A6650)) {
+ if((sport == 4708) || (dport == 4708)) return(NDPI_PROTOCOL_SKYFILE_PREPAID);
+ else if((sport == 4709) || (dport == 4709)) return(NDPI_PROTOCOL_SKYFILE_RUDICS);
+ else if((sport == 4710) || (dport == 4710)) return(NDPI_PROTOCOL_SKYFILE_POSTPAID);
+ }
+
+ return(NDPI_PROTOCOL_UNKNOWN);
+}
+
+/* ****************************************************** */
+
+unsigned int ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int8_t proto,
+ u_int32_t shost /* host byte order */, u_int16_t sport,
+ u_int32_t dhost /* host byte order */, u_int16_t dport) {
+ unsigned int rc;
+ struct in_addr addr;
+
+ if((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP)) {
+ rc = ndpi_search_tcp_or_udp_raw(ndpi_struct, proto, shost, dhost, sport, dport);
+ if(rc != NDPI_PROTOCOL_UNKNOWN) return(rc);
+
+ rc = ndpi_guess_protocol_id(ndpi_struct, proto, sport, dport);
+ if(rc != NDPI_PROTOCOL_UNKNOWN) {
+ if(rc == NDPI_PROTOCOL_SSL)
+ goto check_guessed_skype;
+ else
+ return(rc);
+ }
+
+ rc = ndpi_find_port_based_protocol(ndpi_struct, proto, shost, sport, dhost, dport);
+ if(rc != NDPI_PROTOCOL_UNKNOWN) return(rc);
+
+ check_guessed_skype:
+ addr.s_addr = shost;
+ if(ndpi_network_ptree_match(ndpi_struct, &addr) == NDPI_PROTOCOL_SKYPE) return(NDPI_PROTOCOL_SKYPE);
+
+ addr.s_addr = dhost;
+ if(ndpi_network_ptree_match(ndpi_struct, &addr) == NDPI_PROTOCOL_SKYPE) return(NDPI_PROTOCOL_SKYPE);
+
+ return(rc);
+ } else {
+ return(ndpi_guess_protocol_id(ndpi_struct, proto, sport, dport));
+ }
+}
+
+/* ****************************************************** */
+
+char* ndpi_get_proto_name(struct ndpi_detection_module_struct *ndpi_mod, u_int16_t proto_id) {
+ if((proto_id >= ndpi_mod->ndpi_num_supported_protocols)
+ || ((proto_id < (NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS))
+ && (ndpi_mod->proto_defaults[proto_id].protoName == NULL)))
+ proto_id = NDPI_PROTOCOL_UNKNOWN;
+
+ return(ndpi_mod->proto_defaults[proto_id].protoName);
+}
+
+/* ****************************************************** */
+
+ndpi_protocol_breed_t ndpi_get_proto_breed(struct ndpi_detection_module_struct *ndpi_mod,
+ u_int16_t proto_id) {
+ if((proto_id >= ndpi_mod->ndpi_num_supported_protocols)
+ || ((proto_id < (NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS))
+ && (ndpi_mod->proto_defaults[proto_id].protoName == NULL)))
+ proto_id = NDPI_PROTOCOL_UNKNOWN;
+
+ return(ndpi_mod->proto_defaults[proto_id].protoBreed);
+}
+
+/* ****************************************************** */
+
+char* ndpi_get_proto_breed_name(struct ndpi_detection_module_struct *ndpi_mod,
+ ndpi_protocol_breed_t breed_id) {
+ switch(breed_id) {
+ case NDPI_PROTOCOL_SAFE:
+ return("Safe");
+ break;
+ case NDPI_PROTOCOL_ACCEPTABLE:
+ return("Acceptable");
+ break;
+ case NDPI_PROTOCOL_FUN:
+ return("Fun");
+ break;
+ case NDPI_PROTOCOL_UNSAFE:
+ return("Unsafe");
+ break;
+ case NDPI_PROTOCOL_POTENTIALLY_DANGEROUS:
+ return("Dangerous");
+ break;
+
+ case NDPI_PROTOCOL_UNRATED:
+ default:
+ return("Unrated");
+ break;
+ }
+}
+
+/* ****************************************************** */
+
+int ndpi_get_protocol_id(struct ndpi_detection_module_struct *ndpi_mod, char *proto) {
+ int i;
+
+ for(i=0; i<(int)ndpi_mod->ndpi_num_supported_protocols; i++)
+ if(strcasecmp(proto, ndpi_mod->proto_defaults[i].protoName) == 0)
+ return(i);
+
+ return(-1);
+}
+
+/* ****************************************************** */
+
+void ndpi_dump_protocols(struct ndpi_detection_module_struct *ndpi_mod) {
+ int i;
+
+ for(i=0; i<(int)ndpi_mod->ndpi_num_supported_protocols; i++)
+ printf("[%3d] %s\n", i, ndpi_mod->proto_defaults[i].protoName);
+}
+
+/* ****************************************************** */
+
+/*
+ * Find the first occurrence of find in s, where the search is limited to the
+ * first slen characters of s.
+ */
+char* ndpi_strnstr(const char *s, const char *find, size_t slen) {
+ char c, sc;
+ size_t len;
+
+ if((c = *find++) != '\0') {
+ len = strlen(find);
+ do {
+ do {
+ if(slen-- < 1 || (sc = *s++) == '\0')
+ return (NULL);
+ } while (sc != c);
+ if(len > slen)
+ return (NULL);
+ } while (strncmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
+
+/* ****************************************************** */
+
+static int ndpi_automa_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_struct,
+ ndpi_automa *automa,
+ struct ndpi_flow_struct *flow,
+ char *string_to_match, u_int string_to_match_len) {
+ int matching_protocol_id;
+ struct ndpi_packet_struct *packet = &flow->packet;
+ AC_TEXT_t ac_input_text;
+
+ if((automa->ac_automa == NULL) || (string_to_match_len== 0)) return(NDPI_PROTOCOL_UNKNOWN);
+
+ if(!automa->ac_automa_finalized) {
+ ac_automata_finalize((AC_AUTOMATA_t*)automa->ac_automa);
+ automa->ac_automa_finalized = 1;
+ }
+
+ matching_protocol_id = NDPI_PROTOCOL_UNKNOWN;
+
+ ac_input_text.astring = string_to_match, ac_input_text.length = string_to_match_len;
+ ac_automata_search (((AC_AUTOMATA_t*)automa->ac_automa), &ac_input_text, (void*)&matching_protocol_id);
+
+ ac_automata_reset(((AC_AUTOMATA_t*)automa->ac_automa));
+
+#ifdef DEBUG
+ {
+ char m[256];
+ int len = ndpi_min(sizeof(m), string_to_match_len);
+
+ strncpy(m, string_to_match, len);
+ m[len] = '\0';
+
+ printf("[NDPI] ndpi_match_string_subprotocol(%s): %s\n", m, ndpi_struct->proto_defaults[matching_protocol_id].protoName);
+ }
+#endif
+
+ if(matching_protocol_id != NDPI_PROTOCOL_UNKNOWN) {
+ packet->detected_protocol_stack[0] = matching_protocol_id;
+
+ if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN)
+ flow->detected_protocol_stack[0] = packet->detected_protocol_stack[0];
+
+ return(packet->detected_protocol_stack[0]);
+ }
+
+#ifdef DEBUG
+ string_to_match[string_to_match_len] = '\0';
+ printf("[NTOP] Unable to find a match for '%s'\n", string_to_match);
+#endif
+
+ return(NDPI_PROTOCOL_UNKNOWN);
+}
+
+/* ****************************************************** */
+
+int ndpi_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ char *string_to_match, u_int string_to_match_len) {
+ return(ndpi_automa_match_string_subprotocol(ndpi_struct, &ndpi_struct->host_automa,
+ flow, string_to_match, string_to_match_len));
+}
+
+/* ****************************************************** */
+
+int ndpi_match_content_subprotocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ char *string_to_match, u_int string_to_match_len) {
+ return(ndpi_automa_match_string_subprotocol(ndpi_struct, &ndpi_struct->content_automa,
+ flow, string_to_match, string_to_match_len));
+}
+
+/* ****************************************************** */
+
+int ndpi_match_bigram(struct ndpi_detection_module_struct *ndpi_struct,
+ ndpi_automa *automa, char *bigram_to_match) {
+ AC_TEXT_t ac_input_text;
+ int ret = 0;
+
+ if((automa->ac_automa == NULL) || (bigram_to_match == NULL))
+ return(ret);
+
+ if(!automa->ac_automa_finalized) {
+ ac_automata_finalize((AC_AUTOMATA_t*)automa->ac_automa);
+ automa->ac_automa_finalized = 1;
+ }
+
+ ac_input_text.astring = bigram_to_match, ac_input_text.length = 2;
+ ac_automata_search(((AC_AUTOMATA_t*)automa->ac_automa), &ac_input_text, (void*)&ret);
+ ac_automata_reset(((AC_AUTOMATA_t*)automa->ac_automa));
+
+ return(ret);
+}
+
+/* ****************************************************** */
+
+void ndpi_free_flow(struct ndpi_flow_struct *flow) {
+ if(flow) {
+ if(flow->http.url) ndpi_free(flow->http.url);
+ if(flow->http.content_type) ndpi_free(flow->http.content_type);
+ ndpi_free(flow);
+ }
+}
+
+/* ****************************************************** */
+
+#ifndef __KERNEL__
+char* ndpi_revision() {
+ return(NDPI_SVN_RELEASE);
+}
+#endif
+
+/* ****************************************************** */
+
+#ifdef WIN32
+
+/*
+ int pthread_mutex_init(pthread_mutex_t *mutex, void *unused) {
+ unused = NULL;
+ *mutex = CreateMutex(NULL, FALSE, NULL);
+ return *mutex == NULL ? -1 : 0;
+ }
+
+ int pthread_mutex_destroy(pthread_mutex_t *mutex) {
+ return CloseHandle(*mutex) == 0 ? -1 : 0;
+ }
+
+ int pthread_mutex_lock(pthread_mutex_t *mutex) {
+ return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0 ? 0 : -1;
+ }
+
+ int pthread_mutex_unlock(pthread_mutex_t *mutex) {
+ return ReleaseMutex(*mutex) == 0 ? -1 : 0;
+ }
+*/
+/* http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/port/gettimeofday.c;h=75a91993b74414c0a1c13a2a09ce739cb8aa8a08;hb=HEAD */
+int gettimeofday(struct timeval * tp, struct timezone * tzp) {
+ /* FILETIME of Jan 1 1970 00:00:00. */
+ const unsigned __int64 epoch = (__int64)(116444736000000000);
+
+ FILETIME file_time;
+ SYSTEMTIME system_time;
+ ULARGE_INTEGER ularge;
+
+ GetSystemTime(&system_time);
+ SystemTimeToFileTime(&system_time, &file_time);
+ ularge.LowPart = file_time.dwLowDateTime;
+ ularge.HighPart = file_time.dwHighDateTime;
+
+ tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L);
+ tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
+
+ return 0;
+}
+#endif
+
+int NDPI_BITMASK_COMPARE(NDPI_PROTOCOL_BITMASK a, NDPI_PROTOCOL_BITMASK b) {
+ int i;
+
+ for(i=0; i<NDPI_NUM_FDS_BITS; i++) {
+ if(a.fds_bits[i] & b.fds_bits[i])
+ return(1);
+ }
+
+ return(0);
+}
+
+int NDPI_BITMASK_IS_EMPTY(NDPI_PROTOCOL_BITMASK a) {
+ int i;
+
+ for(i=0; i<NDPI_NUM_FDS_BITS; i++)
+ if(a.fds_bits[i] != 0)
+ return(0);
+
+ return(1);
+}
+
+void NDPI_DUMP_BITMASK(NDPI_PROTOCOL_BITMASK a) {
+ int i;
+
+ for(i=0; i<NDPI_NUM_FDS_BITS; i++)
+ printf("[%d=%u]", i, a.fds_bits[i]);
+
+ printf("\n");
+}
+
+
+#ifdef WIN32
+/* http://www.opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/libkern/strsep.c */
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char* strsep(char **stringp, const char *delim) {
+ char *s;
+ const char *spanp;
+ int c, sc;
+ char *tok;
+
+ if((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if((sc = *spanp++) == c) {
+ if(c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
+#endif
+
+
diff --git a/src/lib/protocols/afp.c b/src/lib/protocols/afp.c
new file mode 100644
index 000000000..b400f53c5
--- /dev/null
+++ b/src/lib/protocols/afp.c
@@ -0,0 +1,75 @@
+/*
+ * afp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_AFP
+
+static void ndpi_int_afp_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_AFP, NDPI_REAL_PROTOCOL);
+}
+
+
+void ndpi_search_afp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // struct ndpi_id_struct *src = flow->src;
+// struct ndpi_id_struct *dst = flow->dst;
+
+
+ /*
+ * this will detect the OpenSession command of the Data Stream Interface (DSI) protocol
+ * which is exclusively used by the Apple Filing Protocol (AFP) on TCP/IP networks
+ */
+ if (packet->payload_packet_len >= 22 && get_u_int16_t(packet->payload, 0) == htons(0x0004) &&
+ get_u_int16_t(packet->payload, 2) == htons(0x0001) && get_u_int32_t(packet->payload, 4) == 0 &&
+ get_u_int32_t(packet->payload, 8) == htonl(packet->payload_packet_len - 16) &&
+ get_u_int32_t(packet->payload, 12) == 0 && get_u_int16_t(packet->payload, 16) == htons(0x0104)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_AFP, ndpi_struct, NDPI_LOG_DEBUG, "AFP: DSI OpenSession detected.\n");
+ ndpi_int_afp_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ /*
+ * detection of GetStatus command of DSI protocl
+ */
+ if (packet->payload_packet_len >= 18 && get_u_int16_t(packet->payload, 0) == htons(0x0003) &&
+ get_u_int16_t(packet->payload, 2) == htons(0x0001) && get_u_int32_t(packet->payload, 4) == 0 &&
+ get_u_int32_t(packet->payload, 8) == htonl(packet->payload_packet_len - 16) &&
+ get_u_int32_t(packet->payload, 12) == 0 && get_u_int16_t(packet->payload, 16) == htons(0x0f00)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_AFP, ndpi_struct, NDPI_LOG_DEBUG, "AFP: DSI GetStatus detected.\n");
+ ndpi_int_afp_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+
+ NDPI_LOG(NDPI_PROTOCOL_AFP, ndpi_struct, NDPI_LOG_DEBUG, "AFP excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_AFP);
+}
+
+#endif
diff --git a/src/lib/protocols/aimini.c b/src/lib/protocols/aimini.c
new file mode 100644
index 000000000..165ee2fc4
--- /dev/null
+++ b/src/lib/protocols/aimini.c
@@ -0,0 +1,283 @@
+/*
+ * aimini.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_AIMINI
+
+
+static void ndpi_int_aimini_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow,
+ ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_AIMINI, protocol_type);
+}
+
+
+static u_int8_t is_special_aimini_host(struct ndpi_int_one_line_struct host_line)
+{
+ if (host_line.ptr != NULL && host_line.len >= NDPI_STATICSTRING_LEN("X.X.X.X.aimini.net")) {
+ if ((get_u_int32_t(host_line.ptr, 0) & htonl(0x00ff00ff)) == htonl(0x002e002e) &&
+ (get_u_int32_t(host_line.ptr, 4) & htonl(0x00ff00ff)) == htonl(0x002e002e) &&
+ memcmp(&host_line.ptr[8], "aimini.net", NDPI_STATICSTRING_LEN("aimini.net")) == 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void ndpi_search_aimini(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "search aimini.\n");
+
+ if (packet->udp != NULL) {
+ if (flow->l4.udp.aimini_stage == 0) {
+ if (packet->payload_packet_len == 64 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x010b) {
+ flow->l4.udp.aimini_stage = 1;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 1.\n");
+ return;
+ }
+ if (packet->payload_packet_len == 136
+ && (ntohs(get_u_int16_t(packet->payload, 0)) == 0x01c9 || ntohs(get_u_int16_t(packet->payload, 0)) == 0x0165)) {
+ flow->l4.udp.aimini_stage = 4;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 4.\n");
+ return;
+ }
+ if (packet->payload_packet_len == 88 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0101) {
+ flow->l4.udp.aimini_stage = 7;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 7.\n");
+ return;
+ }
+ if (packet->payload_packet_len == 104 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0102) {
+ flow->l4.udp.aimini_stage = 10;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 10.\n");
+ return;
+ }
+ if (packet->payload_packet_len == 32 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x01ca) {
+ flow->l4.udp.aimini_stage = 13;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 13.\n");
+ return;
+ }
+ if (packet->payload_packet_len == 16 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x010c) {
+ flow->l4.udp.aimini_stage = 16;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 16.\n");
+ return;
+ }
+ }
+ /* first packet chronology: (len, value): (64, 0x010b), (>100, 0x0115), (16, 0x010c || 64, 0x010b || 88, 0x0115),
+ * (16, 0x010c || 64, 0x010b || >100, 0x0115)
+ */
+ if (flow->l4.udp.aimini_stage == 1 && packet->payload_packet_len > 100
+ && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0115) {
+ flow->l4.udp.aimini_stage = 2;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 2.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 2 &&
+ ((packet->payload_packet_len == 16 && get_u_int16_t(packet->payload, 0) == htons(0x010c)) ||
+ (packet->payload_packet_len == 64 && get_u_int16_t(packet->payload, 0) == htons(0x010b)) ||
+ (packet->payload_packet_len == 88 && get_u_int16_t(packet->payload, 0) == ntohs(0x0115)))) {
+ flow->l4.udp.aimini_stage = 3;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 3.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 3
+ && ((packet->payload_packet_len == 16 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x010c)
+ || (packet->payload_packet_len == 64 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x010b)
+ || (packet->payload_packet_len > 100 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0115))) {
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "found aimini (64, 0x010b), (>300, 0x0115), "
+ "(16, 0x010c || 64, 0x010b), (16, 0x010c || 64, 0x010b || >100, 0x0115).\n");
+ ndpi_int_aimini_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ /* second packet chronology: (len, value): (136, 0x01c9), (136, 0x01c9),(136, 0x01c9),(136, 0x01c9 || 32, 0x01ca) */
+
+ if (flow->l4.udp.aimini_stage == 4 && packet->payload_packet_len == 136
+ && (ntohs(get_u_int16_t(packet->payload, 0)) == 0x01c9 || ntohs(get_u_int16_t(packet->payload, 0)) == 0x0165)) {
+ flow->l4.udp.aimini_stage = 5;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 5.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 5 && (packet->payload_packet_len == 136
+ && (ntohs(get_u_int16_t(packet->payload, 0)) == 0x01c9
+ || ntohs(get_u_int16_t(packet->payload, 0)) == 0x0165))) {
+ flow->l4.udp.aimini_stage = 6;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 6.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 6 && ((packet->payload_packet_len == 136
+ && ((ntohs(get_u_int16_t(packet->payload, 0)) == 0x0165)
+ || ntohs(get_u_int16_t(packet->payload, 0)) == 0x01c9))
+ || (packet->payload_packet_len == 32
+ && ntohs(get_u_int16_t(packet->payload, 0)) == 0x01ca))) {
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG,
+ "found aimini (136, 0x01c9), (136, 0x01c9)," "(136, 0x01c9),(136, 0x01c9 || 32, 0x01ca).\n");
+ ndpi_int_aimini_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ /* third packet chronology: (len, value): (88, 0x0101), (88, 0x0101),(88, 0x0101),(88, 0x0101) */
+
+ if (flow->l4.udp.aimini_stage == 7 && packet->payload_packet_len == 88
+ && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0101) {
+ flow->l4.udp.aimini_stage = 8;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 8.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 8
+ && (packet->payload_packet_len == 88 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0101)) {
+ flow->l4.udp.aimini_stage = 9;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 9.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 9
+ && (packet->payload_packet_len == 88 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0101)) {
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG,
+ "found aimini (88, 0x0101), (88, 0x0101)," "(88, 0x0101),(88, 0x0101).\n");
+ ndpi_int_aimini_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ /* fourth packet chronology: (len, value): (104, 0x0102), (104, 0x0102), (104, 0x0102), (104, 0x0102) */
+
+ if (flow->l4.udp.aimini_stage == 10 && packet->payload_packet_len == 104
+ && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0102) {
+ flow->l4.udp.aimini_stage = 11;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 11.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 11
+ && (packet->payload_packet_len == 104 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0102)) {
+ flow->l4.udp.aimini_stage = 12;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 12.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 12
+ && ((packet->payload_packet_len == 104 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0102)
+ || (packet->payload_packet_len == 32 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x01ca))) {
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG,
+ "found aimini (104, 0x0102), (104, 0x0102), " "(104, 0x0102), (104, 0x0102).\n");
+ ndpi_int_aimini_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ /* fifth packet chronology (len, value): (32,0x01ca), (32,0x01ca), (32,0x01ca), ((136, 0x0166) || (32,0x01ca)) */
+
+ if (flow->l4.udp.aimini_stage == 13 && packet->payload_packet_len == 32
+ && ntohs(get_u_int16_t(packet->payload, 0)) == 0x01ca) {
+ flow->l4.udp.aimini_stage = 14;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 14.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 14
+ && ((packet->payload_packet_len == 32 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x01ca)
+ || (packet->payload_packet_len == 136 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0166))) {
+ flow->l4.udp.aimini_stage = 15;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 15.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 15
+ && ((packet->payload_packet_len == 136 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0166)
+ || (packet->payload_packet_len == 32 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x01ca))) {
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG,
+ "found aimini (32,0x01ca), (32,0x01ca), (32,0x01ca), ((136, 0x0166)||(32,0x01ca)).\n");
+ ndpi_int_aimini_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ /* sixth packet chronology (len, value): (16, 0x010c), (16, 0x010c), (16, 0x010c), (16, 0x010c) */
+
+ if (flow->l4.udp.aimini_stage == 16 && packet->payload_packet_len == 16
+ && ntohs(get_u_int16_t(packet->payload, 0)) == 0x010c) {
+ flow->l4.udp.aimini_stage = 17;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 17.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 17
+ && (packet->payload_packet_len == 16 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x010c)) {
+ flow->l4.udp.aimini_stage = 18;
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "stage = 18.\n");
+ return;
+ }
+ if (flow->l4.udp.aimini_stage == 18
+ && (packet->payload_packet_len == 16 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x010c)) {
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG,
+ "found aimini (16, 0x010c), (16, 0x010c), (16, 0x010c), (16, 0x010c).\n");
+ ndpi_int_aimini_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ } else if (packet->tcp != NULL) {
+ if ((packet->payload_packet_len > NDPI_STATICSTRING_LEN("GET /player/") &&
+ (memcmp(packet->payload, "GET /player/", NDPI_STATICSTRING_LEN("GET /player/")) == 0)) ||
+ (packet->payload_packet_len > NDPI_STATICSTRING_LEN("GET /play/?fid=") &&
+ (memcmp(packet->payload, "GET /play/?fid=", NDPI_STATICSTRING_LEN("GET /play/?fid=")) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "HTTP packet detected.\n");
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->host_line.ptr != NULL && packet->host_line.len > 11
+ && (memcmp(&packet->host_line.ptr[packet->host_line.len - 11], ".aimini.net", 11) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "AIMINI HTTP traffic detected.\n");
+ ndpi_int_aimini_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ if (packet->payload_packet_len > 100) {
+ if (memcmp(packet->payload, "GET /", NDPI_STATICSTRING_LEN("GET /")) == 0) {
+ if (memcmp(&packet->payload[NDPI_STATICSTRING_LEN("GET /")], "play/",
+ NDPI_STATICSTRING_LEN("play/")) == 0 ||
+ memcmp(&packet->payload[NDPI_STATICSTRING_LEN("GET /")], "download/",
+ NDPI_STATICSTRING_LEN("download/")) == 0) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (is_special_aimini_host(packet->host_line) == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG,
+ "AIMINI HTTP traffic detected.\n");
+ ndpi_int_aimini_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ } else if (memcmp(packet->payload, "POST /", NDPI_STATICSTRING_LEN("POST /")) == 0) {
+ if (memcmp(&packet->payload[NDPI_STATICSTRING_LEN("POST /")], "upload/",
+ NDPI_STATICSTRING_LEN("upload/")) == 0) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (is_special_aimini_host(packet->host_line) == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG,
+ "AIMINI HTTP traffic detected.\n");
+ ndpi_int_aimini_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_AIMINI, ndpi_struct, NDPI_LOG_DEBUG, "exclude aimini.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_AIMINI);
+
+}
+#endif
diff --git a/src/lib/protocols/applejuice.c b/src/lib/protocols/applejuice.c
new file mode 100644
index 000000000..d989d571b
--- /dev/null
+++ b/src/lib/protocols/applejuice.c
@@ -0,0 +1,57 @@
+/*
+ * applejuice.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_APPLEJUICE
+
+
+static void ndpi_int_applejuice_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_APPLEJUICE, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_applejuice_tcp(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_APPLEJUICE, ndpi_struct, NDPI_LOG_DEBUG, "search applejuice.\n");
+
+ if ((packet->payload_packet_len > 7) && (packet->payload[6] == 0x0d)
+ && (packet->payload[7] == 0x0a)
+ && (memcmp(packet->payload, "ajprot", 6) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_APPLEJUICE, ndpi_struct, NDPI_LOG_DEBUG, "detected applejuice.\n");
+ ndpi_int_applejuice_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_APPLEJUICE, ndpi_struct, NDPI_LOG_DEBUG, "exclude applejuice.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_APPLEJUICE);
+}
+
+#endif
diff --git a/src/lib/protocols/armagetron.c b/src/lib/protocols/armagetron.c
new file mode 100644
index 000000000..6c5064fda
--- /dev/null
+++ b/src/lib/protocols/armagetron.c
@@ -0,0 +1,102 @@
+/*
+ * armagetron.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+/* include files */
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_ARMAGETRON
+
+
+static void ndpi_int_armagetron_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_ARMAGETRON, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_armagetron_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_ARMAGETRON, ndpi_struct, NDPI_LOG_DEBUG, "search armagetron.\n");
+
+
+ if (packet->payload_packet_len > 10) {
+ /* login request */
+ if (get_u_int32_t(packet->payload, 0) == htonl(0x000b0000)) {
+ const u_int16_t dataLength = ntohs(get_u_int16_t(packet->payload, 4));
+ if (dataLength == 0 || dataLength * 2 + 8 != packet->payload_packet_len)
+ goto exclude;
+ if (get_u_int16_t(packet->payload, 6) == htons(0x0008)
+ && get_u_int16_t(packet->payload, packet->payload_packet_len - 2) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_ARMAGETRON, ndpi_struct, NDPI_LOG_DEBUG, "detected armagetron.\n");
+ ndpi_int_armagetron_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ /* sync_msg */
+ if (packet->payload_packet_len == 16 && get_u_int16_t(packet->payload, 0) == htons(0x001c)
+ && get_u_int16_t(packet->payload, 2) != 0) {
+ const u_int16_t dataLength = ntohs(get_u_int16_t(packet->payload, 4));
+ if (dataLength != 4)
+ goto exclude;
+ if (get_u_int32_t(packet->payload, 6) == htonl(0x00000500) && get_u_int32_t(packet->payload, 6 + 4) == htonl(0x00010000)
+ && get_u_int16_t(packet->payload, packet->payload_packet_len - 2) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_ARMAGETRON, ndpi_struct, NDPI_LOG_DEBUG, "detected armagetron.\n");
+ ndpi_int_armagetron_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ /* net_sync combination */
+ if (packet->payload_packet_len > 50 && get_u_int16_t(packet->payload, 0) == htons(0x0018)
+ && get_u_int16_t(packet->payload, 2) != 0) {
+ u_int16_t val;
+ const u_int16_t dataLength = ntohs(get_u_int16_t(packet->payload, 4));
+ if (dataLength == 0 || dataLength * 2 + 8 > packet->payload_packet_len)
+ goto exclude;
+ val = get_u_int16_t(packet->payload, 6 + 2);
+ if (val == get_u_int16_t(packet->payload, 6 + 6)) {
+ val = ntohs(get_u_int16_t(packet->payload, 6 + 8));
+ if ((6 + 10 + val + 4) < packet->payload_packet_len
+ && (get_u_int32_t(packet->payload, 6 + 10 + val) == htonl(0x00010000)
+ || get_u_int32_t(packet->payload, 6 + 10 + val) == htonl(0x00000001))
+ && get_u_int16_t(packet->payload, packet->payload_packet_len - 2) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_ARMAGETRON, ndpi_struct, NDPI_LOG_DEBUG, "detected armagetron.\n");
+ ndpi_int_armagetron_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+ }
+
+ exclude:
+ NDPI_LOG(NDPI_PROTOCOL_ARMAGETRON, ndpi_struct, NDPI_LOG_DEBUG, "exclude armagetron.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_ARMAGETRON);
+}
+
+#endif
diff --git a/src/lib/protocols/attic/flash.c b/src/lib/protocols/attic/flash.c
new file mode 100644
index 000000000..e6b89a185
--- /dev/null
+++ b/src/lib/protocols/attic/flash.c
@@ -0,0 +1,93 @@
+/*
+ * flash.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_FLASH
+
+static void ndpi_int_flash_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_FLASH, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_flash(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (flow->l4.tcp.flash_stage == 0 && packet->payload_packet_len > 0
+ && (packet->payload[0] == 0x03 || packet->payload[0] == 0x06)) {
+ flow->l4.tcp.flash_bytes = packet->payload_packet_len;
+ if (packet->tcp->psh == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_FLASH, ndpi_struct, NDPI_LOG_DEBUG, "FLASH pass 1: \n");
+ flow->l4.tcp.flash_stage = packet->packet_direction + 1;
+
+ NDPI_LOG(NDPI_PROTOCOL_FLASH, ndpi_struct, NDPI_LOG_DEBUG,
+ "FLASH pass 1: flash_stage: %u, flash_bytes: %u\n", flow->l4.tcp.flash_stage,
+ flow->l4.tcp.flash_bytes);
+ return;
+ } else if (packet->tcp->psh != 0 && flow->l4.tcp.flash_bytes == 1537) {
+ NDPI_LOG(NDPI_PROTOCOL_FLASH, ndpi_struct, NDPI_LOG_DEBUG,
+ "FLASH hit: flash_stage: %u, flash_bytes: %u\n", flow->l4.tcp.flash_stage,
+ flow->l4.tcp.flash_bytes);
+ flow->l4.tcp.flash_stage = 3;
+ ndpi_int_flash_add_connection(ndpi_struct, flow);
+ return;
+ }
+ } else if (flow->l4.tcp.flash_stage == 1 + packet->packet_direction) {
+ flow->l4.tcp.flash_bytes += packet->payload_packet_len;
+ if (packet->tcp->psh != 0 && flow->l4.tcp.flash_bytes == 1537) {
+ NDPI_LOG(NDPI_PROTOCOL_FLASH, ndpi_struct, NDPI_LOG_DEBUG,
+ "FLASH hit: flash_stage: %u, flash_bytes: %u\n", flow->l4.tcp.flash_stage,
+ flow->l4.tcp.flash_bytes);
+ flow->l4.tcp.flash_stage = 3;
+ ndpi_int_flash_add_connection(ndpi_struct, flow);
+ return;
+ } else if (packet->tcp->psh == 0 && flow->l4.tcp.flash_bytes < 1537) {
+ NDPI_LOG(NDPI_PROTOCOL_FLASH, ndpi_struct, NDPI_LOG_DEBUG,
+ "FLASH pass 2: flash_stage: %u, flash_bytes: %u\n", flow->l4.tcp.flash_stage,
+ flow->l4.tcp.flash_bytes);
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_FLASH, ndpi_struct, NDPI_LOG_DEBUG,
+ "FLASH might be excluded: flash_stage: %u, flash_bytes: %u, packet_direction: %u\n",
+ flow->l4.tcp.flash_stage, flow->l4.tcp.flash_bytes, packet->packet_direction);
+
+#ifdef NDPI_PROTOCOL_HTTP
+ if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_HTTP) != 0) {
+#endif /* NDPI_PROTOCOL_HTTP */
+ NDPI_LOG(NDPI_PROTOCOL_FLASH, ndpi_struct, NDPI_LOG_DEBUG, "FLASH: exclude\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_FLASH);
+#ifdef NDPI_PROTOCOL_HTTP
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_FLASH, ndpi_struct, NDPI_LOG_DEBUG, "FLASH avoid early exclude from http\n");
+ }
+#endif /* NDPI_PROTOCOL_HTTP */
+
+}
+#endif
diff --git a/src/lib/protocols/attic/ftp.c b/src/lib/protocols/attic/ftp.c
new file mode 100644
index 000000000..f48f3e946
--- /dev/null
+++ b/src/lib/protocols/attic/ftp.c
@@ -0,0 +1,469 @@
+/*
+ * ftp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#include "ndpi_utils.h"
+
+#ifdef NDPI_PROTOCOL_FTP
+
+
+static void ndpi_int_ftp_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_FTP, NDPI_REAL_PROTOCOL);
+}
+
+/**
+ * checks for possible FTP command
+ * not all valid commands are tested, it just need to be 3 or 4 characters followed by a space if the
+ * packet is longer
+ *
+ * this functions is not used to accept, just to not reject
+ */
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+u_int8_t ndpi_int_check_possible_ftp_command(const struct ndpi_packet_struct *packet)
+{
+ if (packet->payload_packet_len < 3)
+ return 0;
+
+ if ((packet->payload[0] < 'a' || packet->payload[0] > 'z') &&
+ (packet->payload[0] < 'A' || packet->payload[0] > 'Z'))
+ return 0;
+ if ((packet->payload[1] < 'a' || packet->payload[1] > 'z') &&
+ (packet->payload[1] < 'A' || packet->payload[1] > 'Z'))
+ return 0;
+ if ((packet->payload[2] < 'a' || packet->payload[2] > 'z') &&
+ (packet->payload[2] < 'A' || packet->payload[2] > 'Z'))
+ return 0;
+
+ if (packet->payload_packet_len > 3) {
+ if ((packet->payload[3] < 'a' || packet->payload[3] > 'z') &&
+ (packet->payload[3] < 'A' || packet->payload[3] > 'Z') && packet->payload[3] != ' ')
+ return 0;
+
+ if (packet->payload_packet_len > 4) {
+ if (packet->payload[3] != ' ' && packet->payload[4] != ' ')
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/**
+ * ftp replies are are 3-digit number followed by space or hyphen
+ */
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+u_int8_t ndpi_int_check_possible_ftp_reply(const struct ndpi_packet_struct *packet)
+{
+ if (packet->payload_packet_len < 5)
+ return 0;
+
+ if (packet->payload[3] != ' ' && packet->payload[3] != '-')
+ return 0;
+
+ if (packet->payload[0] < '0' || packet->payload[0] > '9')
+ return 0;
+ if (packet->payload[1] < '0' || packet->payload[1] > '9')
+ return 0;
+ if (packet->payload[2] < '0' || packet->payload[2] > '9')
+ return 0;
+
+ return 1;
+}
+
+/**
+ * check for continuation replies
+ * there is no real indication whether it is a continuation message, we just
+ * require that there are at least 5 ascii characters
+ */
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+u_int8_t ndpi_int_check_possible_ftp_continuation_reply(const struct ndpi_packet_struct *packet)
+{
+ u_int16_t i;
+
+ if (packet->payload_packet_len < 5)
+ return 0;
+
+ for (i = 0; i < 5; i++) {
+ if (packet->payload[i] < ' ' || packet->payload[i] > 127)
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * these are the commands we tracking and expecting to see
+ */
+enum {
+ FTP_USER_CMD = 1 << 0,
+ FTP_FEAT_CMD = 1 << 1,
+ FTP_COMMANDS = ((1 << 2) - 1),
+ FTP_220_CODE = 1 << 2,
+ FTP_331_CODE = 1 << 3,
+ FTP_211_CODE = 1 << 4,
+ FTP_CODES = ((1 << 5) - 1 - FTP_COMMANDS)
+};
+
+/*
+ return 0 if nothing has been detected
+ return 1 if a pop packet
+*/
+
+static u_int8_t search_ftp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ u_int8_t current_ftp_code = 0;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ /* initiate client direction flag */
+ if (flow->packet_counter == 1) {
+ if (flow->l4.tcp.seen_syn) {
+ flow->l4.tcp.ftp_client_direction = flow->setup_packet_direction;
+ } else {
+ /* no syn flag seen so guess */
+ if (packet->payload_packet_len > 0) {
+ if (packet->payload[0] >= '0' && packet->payload[0] <= '9') {
+ /* maybe server side */
+ flow->l4.tcp.ftp_client_direction = 1 - packet->packet_direction;
+ } else {
+ flow->l4.tcp.ftp_client_direction = packet->packet_direction;
+ }
+ }
+ }
+ }
+
+ if (packet->packet_direction == flow->l4.tcp.ftp_client_direction) {
+ if (packet->payload_packet_len > NDPI_STATICSTRING_LEN("USER ") &&
+ (memcmp(packet->payload, "USER ", NDPI_STATICSTRING_LEN("USER ")) == 0 ||
+ memcmp(packet->payload, "user ", NDPI_STATICSTRING_LEN("user ")) == 0)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP: found USER command\n");
+ flow->l4.tcp.ftp_codes_seen |= FTP_USER_CMD;
+ current_ftp_code = FTP_USER_CMD;
+ } else if (packet->payload_packet_len >= NDPI_STATICSTRING_LEN("FEAT") &&
+ (memcmp(packet->payload, "FEAT", NDPI_STATICSTRING_LEN("FEAT")) == 0 ||
+ memcmp(packet->payload, "feat", NDPI_STATICSTRING_LEN("feat")) == 0)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP: found FEAT command\n");
+ flow->l4.tcp.ftp_codes_seen |= FTP_FEAT_CMD;
+ current_ftp_code = FTP_FEAT_CMD;
+ } else if (!ndpi_int_check_possible_ftp_command(packet)) {
+ return 0;
+ }
+ } else {
+ if (packet->payload_packet_len > NDPI_STATICSTRING_LEN("220 ") &&
+ (memcmp(packet->payload, "220 ", NDPI_STATICSTRING_LEN("220 ")) == 0 ||
+ memcmp(packet->payload, "220-", NDPI_STATICSTRING_LEN("220-")) == 0)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP: found 220 reply code\n");
+ flow->l4.tcp.ftp_codes_seen |= FTP_220_CODE;
+ current_ftp_code = FTP_220_CODE;
+ } else if (packet->payload_packet_len > NDPI_STATICSTRING_LEN("331 ") &&
+ (memcmp(packet->payload, "331 ", NDPI_STATICSTRING_LEN("331 ")) == 0 ||
+ memcmp(packet->payload, "331-", NDPI_STATICSTRING_LEN("331-")) == 0)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP: found 331 reply code\n");
+ flow->l4.tcp.ftp_codes_seen |= FTP_331_CODE;
+ current_ftp_code = FTP_331_CODE;
+ } else if (packet->payload_packet_len > NDPI_STATICSTRING_LEN("211 ") &&
+ (memcmp(packet->payload, "211 ", NDPI_STATICSTRING_LEN("211 ")) == 0 ||
+ memcmp(packet->payload, "211-", NDPI_STATICSTRING_LEN("211-")) == 0)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP: found 211reply code\n");
+ flow->l4.tcp.ftp_codes_seen |= FTP_211_CODE;
+ current_ftp_code = FTP_211_CODE;
+ } else if (!ndpi_int_check_possible_ftp_reply(packet)) {
+ if ((flow->l4.tcp.ftp_codes_seen & FTP_CODES) == 0 ||
+ (!ndpi_int_check_possible_ftp_continuation_reply(packet))) {
+ return 0;
+ }
+ }
+ }
+
+ if ((flow->l4.tcp.ftp_codes_seen & FTP_COMMANDS) != 0 && (flow->l4.tcp.ftp_codes_seen & FTP_CODES) != 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP detected\n");
+ ndpi_int_ftp_add_connection(ndpi_struct, flow);
+ return 1;
+ }
+
+ /* if no valid code has been seen for the first packets reject */
+ if (flow->l4.tcp.ftp_codes_seen == 0 && flow->packet_counter > 3)
+ return 0;
+
+ /* otherwise wait more packets, wait more for traffic on known ftp port */
+ if ((packet->packet_direction == flow->setup_packet_direction && packet->tcp && packet->tcp->dest == htons(21)) ||
+ (packet->packet_direction != flow->setup_packet_direction && packet->tcp && packet->tcp->source == htons(21))) {
+ /* flow to known ftp port */
+
+ /* wait much longer if this was a 220 code, initial messages might be long */
+ if (current_ftp_code == FTP_220_CODE) {
+ if (flow->packet_counter > 40)
+ return 0;
+ } else {
+ if (flow->packet_counter > 20)
+ return 0;
+ }
+ } else {
+ /* wait much longer if this was a 220 code, initial messages might be long */
+ if (current_ftp_code == FTP_220_CODE) {
+ if (flow->packet_counter > 20)
+ return 0;
+ } else {
+ if (flow->packet_counter > 10)
+ return 0;
+ }
+ }
+
+ return 2;
+}
+
+
+static void search_passive_ftp_mode(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *dst = flow->dst;
+ struct ndpi_id_struct *src = flow->src;
+ u_int16_t plen;
+ u_int8_t i;
+ u_int32_t ftp_ip;
+
+
+ // TODO check if normal passive mode also needs adaption for ipv6
+ if (packet->payload_packet_len > 3 && ndpi_mem_cmp(packet->payload, "227 ", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP passive mode initial string\n");
+
+ plen = 4; //=4 for "227 "
+ while (1) {
+ if (plen >= packet->payload_packet_len) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "plen >= packet->payload_packet_len, return\n");
+ return;
+ }
+ if (packet->payload[plen] == '(') {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "found (. break.\n");
+ break;
+ }
+ /* if (!isalnum(packet->payload[plen])) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "no alpha numeric symbol --> break.\n");
+ return;
+ }*/
+ plen++;
+ }
+ plen++;
+
+ if (plen >= packet->payload_packet_len)
+ return;
+
+
+ ftp_ip = 0;
+ for (i = 0; i < 4; i++) {
+ u_int16_t oldplen = plen;
+ ftp_ip =
+ (ftp_ip << 8) +
+ ndpi_bytestream_to_number(&packet->payload[plen], packet->payload_packet_len - plen, &plen);
+ if (oldplen == plen || plen >= packet->payload_packet_len) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP passive mode %u value parse failed\n",
+ i);
+ return;
+ }
+ if (packet->payload[plen] != ',') {
+
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "FTP passive mode %u value parse failed, char ',' is missing\n", i);
+ return;
+ }
+ plen++;
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "FTP passive mode %u value parsed, ip is now: %u\n", i, ftp_ip);
+
+ }
+ if (dst != NULL) {
+ dst->ftp_ip.ipv4 = htonl(ftp_ip);
+ dst->ftp_timer = packet->tick_timestamp;
+ dst->ftp_timer_set = 1;
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "saved ftp_ip, ftp_timer, ftp_timer_set to dst");
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP PASSIVE MODE FOUND: use Server %s\n",
+ ndpi_get_ip_string(ndpi_struct, &dst->ftp_ip));
+ }
+ if (src != NULL) {
+ src->ftp_ip.ipv4 = packet->iph->daddr;
+ src->ftp_timer = packet->tick_timestamp;
+ src->ftp_timer_set = 1;
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "saved ftp_ip, ftp_timer, ftp_timer_set to src");
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP PASSIVE MODE FOUND: use Server %s\n",
+ ndpi_get_ip_string(ndpi_struct, &src->ftp_ip));
+ }
+ return;
+ }
+
+ if (packet->payload_packet_len > 34 && ndpi_mem_cmp(packet->payload, "229 Entering Extended Passive Mode", 34) == 0) {
+ if (dst != NULL) {
+ ndpi_packet_src_ip_get(packet, &dst->ftp_ip);
+ dst->ftp_timer = packet->tick_timestamp;
+ dst->ftp_timer_set = 1;
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "saved ftp_ip, ftp_timer, ftp_timer_set to dst");
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "FTP Extended PASSIVE MODE FOUND: use Server %s\n", ndpi_get_ip_string(ndpi_struct, &dst->ftp_ip));
+ }
+ if (src != NULL) {
+ ndpi_packet_dst_ip_get(packet, &src->ftp_ip);
+ src->ftp_timer = packet->tick_timestamp;
+ src->ftp_timer_set = 1;
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "saved ftp_ip, ftp_timer, ftp_timer_set to src");
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "FTP Extended PASSIVE MODE FOUND: use Server %s\n", ndpi_get_ip_string(ndpi_struct, &src->ftp_ip));
+ }
+ return;
+ }
+}
+
+
+static void search_active_ftp_mode(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ if (packet->payload_packet_len > 5
+ && (ndpi_mem_cmp(packet->payload, "PORT ", 5) == 0 || ndpi_mem_cmp(packet->payload, "EPRT ", 5) == 0)) {
+
+ //src->local_ftp_data_port = htons(data_port_number);
+ if (src != NULL) {
+ ndpi_packet_dst_ip_get(packet, &src->ftp_ip);
+ src->ftp_timer = packet->tick_timestamp;
+ src->ftp_timer_set = 1;
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP ACTIVE MODE FOUND, command is %.*s\n", 4,
+ packet->payload);
+ }
+ if (dst != NULL) {
+ ndpi_packet_src_ip_get(packet, &dst->ftp_ip);
+ dst->ftp_timer = packet->tick_timestamp;
+ dst->ftp_timer_set = 1;
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "FTP ACTIVE MODE FOUND, command is %.*s\n", 4,
+ packet->payload);
+ }
+ }
+ return;
+}
+
+
+void ndpi_search_ftp_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+
+
+ if (src != NULL && ndpi_packet_dst_ip_eql(packet, &src->ftp_ip)
+ && packet->tcp->syn != 0 && packet->tcp->ack == 0
+ && packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask,
+ NDPI_PROTOCOL_FTP) != 0 && src->ftp_timer_set != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "possible ftp data, src!= 0.\n");
+
+ if (((u_int32_t)
+ (packet->tick_timestamp - src->ftp_timer)) >= ndpi_struct->ftp_connection_timeout) {
+ src->ftp_timer_set = 0;
+ } else if (ntohs(packet->tcp->dest) > 1024
+ && (ntohs(packet->tcp->source) > 1024 || ntohs(packet->tcp->source) == 20)) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "detected FTP data stream.\n");
+ ndpi_int_ftp_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ if (dst != NULL && ndpi_packet_src_ip_eql(packet, &dst->ftp_ip)
+ && packet->tcp->syn != 0 && packet->tcp->ack == 0
+ && packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask,
+ NDPI_PROTOCOL_FTP) != 0 && dst->ftp_timer_set != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "possible ftp data; dst!= 0.\n");
+
+ if (((u_int32_t)
+ (packet->tick_timestamp - dst->ftp_timer)) >= ndpi_struct->ftp_connection_timeout) {
+ dst->ftp_timer_set = 0;
+
+ } else if (ntohs(packet->tcp->dest) > 1024
+ && (ntohs(packet->tcp->source) > 1024 || ntohs(packet->tcp->source) == 20)) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "detected FTP data stream.\n");
+ ndpi_int_ftp_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ // ftp data asymmetrically
+
+
+ /* skip packets without payload */
+ if (packet->payload_packet_len == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "FTP test skip because of data connection or zero byte packet_payload.\n");
+ return;
+ }
+ /* skip excluded connections */
+
+ // we test for FTP connection and search for passive mode
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_FTP) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "detected ftp command mode. going to test data mode.\n");
+ search_passive_ftp_mode(ndpi_struct, flow);
+
+ search_active_ftp_mode(ndpi_struct, flow);
+ return;
+ }
+
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN && search_ftp(ndpi_struct, flow) != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "unknown. need next packet.\n");
+
+ return;
+ }
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_FTP);
+ NDPI_LOG(NDPI_PROTOCOL_FTP, ndpi_struct, NDPI_LOG_DEBUG, "exclude ftp.\n");
+
+}
+
+#endif
diff --git a/src/lib/protocols/attic/manolito.c b/src/lib/protocols/attic/manolito.c
new file mode 100644
index 000000000..f4ffba0cc
--- /dev/null
+++ b/src/lib/protocols/attic/manolito.c
@@ -0,0 +1,180 @@
+/*
+ * manolito.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_MANOLITO
+
+static void ndpi_int_manolito_add_connection(struct
+ ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MANOLITO, NDPI_REAL_PROTOCOL);
+
+
+ if (src != NULL) {
+ if (packet->udp != NULL) {
+ src->manolito_last_pkt_arrival_time = packet->tick_timestamp;
+ }
+ }
+ if (dst != NULL) {
+ if (packet->udp != NULL) {
+ dst->manolito_last_pkt_arrival_time = packet->tick_timestamp;
+ }
+ }
+}
+
+/*
+ return 0 if nothing has been detected
+ return 1 if it is a megaupload packet
+*/
+u_int8_t search_manolito_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+u_int8_t search_manolito_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src = flow->src;
+ // struct ndpi_id_struct *dst = flow->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_MANOLITO, ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO TCP DETECTION\n");
+
+ if (flow->l4.tcp.manolito_stage == 0 && packet->payload_packet_len > 6) {
+ if (memcmp(packet->payload, "SIZ ", 4) != 0)
+ goto end_manolito_nothing_found;
+
+ flow->l4.tcp.manolito_stage = 1 + packet->packet_direction;
+ NDPI_LOG(NDPI_PROTOCOL_MANOLITO, ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO Stage 1.\n");
+ goto end_manolito_maybe_hit;
+
+ } else if ((flow->l4.tcp.manolito_stage == 2 - packet->packet_direction)
+ && packet->payload_packet_len > 4) {
+ if (memcmp(packet->payload, "STR ", 4) != 0)
+ goto end_manolito_nothing_found;
+ NDPI_LOG(NDPI_PROTOCOL_MANOLITO, ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO Stage 2.\n");
+ flow->l4.tcp.manolito_stage = 3 + packet->packet_direction;
+ goto end_manolito_maybe_hit;
+
+ } else if ((flow->l4.tcp.manolito_stage == 4 - packet->packet_direction) && packet->payload_packet_len > 5) {
+ if (memcmp(packet->payload, "MD5 ", 4) != 0)
+ goto end_manolito_nothing_found;
+ NDPI_LOG(NDPI_PROTOCOL_MANOLITO, ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO Stage 3.\n");
+ flow->l4.tcp.manolito_stage = 5 + packet->packet_direction;
+ goto end_manolito_maybe_hit;
+
+ } else if ((flow->l4.tcp.manolito_stage == 6 - packet->packet_direction) && packet->payload_packet_len == 4) {
+
+ if (memcmp(packet->payload, "GO!!", 4) != 0)
+ goto end_manolito_nothing_found;
+ NDPI_LOG(NDPI_PROTOCOL_MANOLITO, ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO Stage 4.\n");
+ goto end_manolito_found;
+ }
+ //NDPI_LOG(NDPI_PROTOCOL_MANOLITO,ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO FLOW STAGE %d\n", flow->l4.tcp.manolito_stage);
+ goto end_manolito_nothing_found;
+
+ end_manolito_found:
+ NDPI_LOG(NDPI_PROTOCOL_MANOLITO, ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO FOUND\n");
+ ndpi_int_manolito_add_connection(ndpi_struct, flow);
+ return 1;
+
+ end_manolito_maybe_hit:
+ NDPI_LOG(NDPI_PROTOCOL_MANOLITO, ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO maybe hit.\n");
+ return 2;
+
+ end_manolito_nothing_found:
+ NDPI_LOG(NDPI_PROTOCOL_MANOLITO, ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO NOTHING FOUND\n");
+ return 0;
+}
+
+void ndpi_search_manolito_tcp_udp(struct
+ ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+
+ if (packet->tcp != NULL) {
+ if (search_manolito_tcp(ndpi_struct, flow) != 0)
+ return;
+ } else if (packet->udp != NULL) {
+ if (flow->detected_protocol_stack[0] == NDPI_PROTOCOL_MANOLITO) {
+ if (src != NULL) {
+ src->manolito_last_pkt_arrival_time = packet->tick_timestamp;
+ }
+ if (dst != NULL) {
+ dst->manolito_last_pkt_arrival_time = packet->tick_timestamp;
+ }
+ return;
+ } else if (packet->udp->source == htons(41170)
+ || packet->udp->dest == htons(41170)) {
+ if (src != NULL && src->manolito_last_pkt_arrival_time != 0
+ && (packet->tick_timestamp - src->manolito_last_pkt_arrival_time <
+ ndpi_struct->manolito_subscriber_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_MANOLITO, ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO: UDP detected \n");
+ ndpi_int_manolito_add_connection(ndpi_struct, flow);
+ return;
+ } else if (src != NULL
+ && (packet->tick_timestamp - src->manolito_last_pkt_arrival_time) >=
+ ndpi_struct->manolito_subscriber_timeout) {
+ src->manolito_last_pkt_arrival_time = 0;
+ }
+
+ if (dst != NULL && dst->manolito_last_pkt_arrival_time != 0
+ && (packet->tick_timestamp - dst->manolito_last_pkt_arrival_time <
+ ndpi_struct->manolito_subscriber_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_MANOLITO, ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO: UDP detected \n");
+ ndpi_int_manolito_add_connection(ndpi_struct, flow);
+ return;
+ } else if (dst != NULL
+ && (packet->tick_timestamp - dst->manolito_last_pkt_arrival_time) >=
+ ndpi_struct->manolito_subscriber_timeout) {
+ dst->manolito_last_pkt_arrival_time = 0;
+ }
+
+ if ((packet->payload_packet_len == 20 && htons(0x3d4b) == get_u_int16_t(packet->payload, 0)
+ && packet->payload[2] == 0xd9 && htons(0xedbb) == get_u_int16_t(packet->payload, 16))
+ || (packet->payload_packet_len == 25 && htons(0x3e4a) == get_u_int16_t(packet->payload, 0)
+ && htons(0x092f) == get_u_int16_t(packet->payload, 20) && packet->payload[22] == 0x20)
+ || (packet->payload_packet_len == 20 && !get_u_int16_t(packet->payload, 2) && !get_u_int32_t(packet->payload, 8)
+ && !get_u_int16_t(packet->payload, 18) && get_u_int16_t(packet->payload, 0))
+ ) { //20B pkt is For PING
+ NDPI_LOG(NDPI_PROTOCOL_MANOLITO, ndpi_struct, NDPI_LOG_DEBUG, "MANOLITO: UDP detected \n");
+ ndpi_int_manolito_add_connection(ndpi_struct, flow);
+ return;
+ } else if (flow->packet_counter < 7) {
+ return;
+ }
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MANOLITO);
+}
+#endif
diff --git a/src/lib/protocols/attic/popo.c b/src/lib/protocols/attic/popo.c
new file mode 100644
index 000000000..b5c45ea2b
--- /dev/null
+++ b/src/lib/protocols/attic/popo.c
@@ -0,0 +1,86 @@
+/*
+ * popo.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_POPO
+
+static void ndpi_int_popo_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_POPO, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_popo_tcp_udp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ if (packet->tcp != NULL) {
+ if ((packet->payload_packet_len == 20)
+ && get_u_int32_t(packet->payload, 0) == htonl(0x0c000000)
+ && get_u_int32_t(packet->payload, 4) == htonl(0x01010000)
+ && get_u_int32_t(packet->payload, 8) == htonl(0x06000000)
+ && get_u_int32_t(packet->payload, 12) == 0 && get_u_int32_t(packet->payload, 16) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_POPO, ndpi_struct, NDPI_LOG_DEBUG, "POPO detected\n");
+ ndpi_int_popo_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ if (NDPI_SRC_OR_DST_HAS_PROTOCOL(src, dst, NDPI_PROTOCOL_POPO) != 0) {
+#define NDPI_POPO_IP_SUBNET_START ( (220 << 24) + (181 << 16) + (28 << 8) + 220)
+#define NDPI_POPO_IP_SUBNET_END ( (220 << 24) + (181 << 16) + (28 << 8) + 238)
+
+ /* may match the first payload ip packet only ... */
+
+ if (ntohl(packet->iph->daddr) >= NDPI_POPO_IP_SUBNET_START
+ && ntohl(packet->iph->daddr) <= NDPI_POPO_IP_SUBNET_END) {
+ NDPI_LOG(NDPI_PROTOCOL_POPO, ndpi_struct, NDPI_LOG_DEBUG, "POPO ip subnet detected\n");
+ ndpi_int_popo_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+
+ if (packet->payload_packet_len > 13 && packet->payload_packet_len == get_l32(packet->payload, 0)
+ && !get_l16(packet->payload, 12)) {
+ register u_int16_t ii;
+ for (ii = 14; ii < 50 && ii < packet->payload_packet_len - 8; ++ii) {
+ if (packet->payload[ii] == '@')
+ if (!memcmp(&packet->payload[ii + 1], "163.com", 7)
+ || (ii <= packet->payload_packet_len - 13 && !memcmp(&packet->payload[ii + 1], "popo.163.com", 12))) {
+ NDPI_LOG(NDPI_PROTOCOL_POPO, ndpi_struct, NDPI_LOG_DEBUG, "POPO detected.\n");
+ ndpi_int_popo_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_POPO);
+}
+
+#endif
diff --git a/src/lib/protocols/attic/secondlife.c b/src/lib/protocols/attic/secondlife.c
new file mode 100644
index 000000000..1d43231e0
--- /dev/null
+++ b/src/lib/protocols/attic/secondlife.c
@@ -0,0 +1,123 @@
+/*
+ * secondlife.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_utils.h"
+#ifdef NDPI_PROTOCOL_SECONDLIFE
+
+static void ndpi_int_secondlife_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SECONDLIFE, protocol_type);
+}
+
+void ndpi_search_secondlife(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ // if ((ntohs(packet->udp->dest) == 12035 || ntohs(packet->udp->dest) == 12036 || (ntohs(packet->udp->dest) >= 13000 && ntohs(packet->udp->dest) <= 13050)) //port
+ // && packet->payload_packet_len > 6 // min length with no extra header, high frequency and 1 byte message body
+ // && get_u_int8_t(packet->payload, 0) == 0x40 // reliable packet
+ // && ntohl(get_u_int32_t(packet->payload, 1)) == 0x00000001 // sequence number equals 1
+ // //ntohl (get_u_int32_t (packet->payload, 5)) == 0x00FFFF00 // no extra header, low frequency message - can't use, message may have higher frequency
+ // ) {
+ // NDPI_LOG(NDPI_PROTOCOL_SECONDLIFE, ndpi_struct, NDPI_LOG_DEBUG, "Second Life detected.\n");
+ // ndpi_int_secondlife_add_connection(ndpi_struct, flow);
+ // return;
+ // }
+
+ if (packet->tcp != NULL) {
+ if (packet->payload_packet_len > NDPI_STATICSTRING_LEN("GET /")
+ && memcmp(packet->payload, "GET /", NDPI_STATICSTRING_LEN("GET /")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SECONDLIFE, ndpi_struct, NDPI_LOG_DEBUG, "Second Life HTTP 'GET /'' found.\n");
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->user_agent_line.ptr != NULL
+ && packet->user_agent_line.len >
+ NDPI_STATICSTRING_LEN
+ ("Mozilla/5.0 (Windows; U; Windows NT 6.1; de-DE) AppleWebKit/532.4 (KHTML, like Gecko) SecondLife/")
+ && memcmp(&packet->user_agent_line.ptr[NDPI_STATICSTRING_LEN
+ ("Mozilla/5.0 (Windows; U; Windows NT 6.1; de-DE) AppleWebKit/532.4 (KHTML, like Gecko) ")],
+ "SecondLife/", NDPI_STATICSTRING_LEN("SecondLife/")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SECONDLIFE, ndpi_struct, NDPI_LOG_DEBUG,
+ "Second Life TCP HTTP User Agent detected.\n");
+ ndpi_int_secondlife_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ if (packet->host_line.ptr != NULL && packet->host_line.len > NDPI_STATICSTRING_LEN(".agni.lindenlab.com:")) {
+ u_int8_t x;
+ for (x = 2; x < 6; x++) {
+ if (packet->host_line.ptr[packet->host_line.len - (1 + x)] == ':') {
+ if ((1 + x + NDPI_STATICSTRING_LEN(".agni.lindenlab.com")) < packet->host_line.len
+ && memcmp(&packet->host_line.ptr[packet->host_line.len -
+ (1 + x + NDPI_STATICSTRING_LEN(".agni.lindenlab.com"))],
+ ".agni.lindenlab.com", NDPI_STATICSTRING_LEN(".agni.lindenlab.com")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SECONDLIFE, ndpi_struct, NDPI_LOG_DEBUG,
+ "Second Life TCP HTTP Host detected.\n");
+ ndpi_int_secondlife_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (packet->udp != NULL) {
+ if (packet->payload_packet_len == 46
+ && memcmp(packet->payload, "\x40\x00\x00\x00\x01\x00\xff\xff\x00\x03", 10) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SECONDLIFE, ndpi_struct, NDPI_LOG_DEBUG, "Second Life 0xffff0003 detected.\n");
+ ndpi_int_secondlife_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 54
+ && memcmp(packet->payload, "\x40\x00\x00\x00\x01\x00\xff\xff\x00\x52", 10) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SECONDLIFE, ndpi_struct, NDPI_LOG_DEBUG, "Second Life 0xffff0052 detected.\n");
+ ndpi_int_secondlife_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 58
+ && memcmp(packet->payload, "\x40\x00\x00\x00\x01\x00\xff\xff\x00\xa9", 10) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SECONDLIFE, ndpi_struct, NDPI_LOG_DEBUG, "Second Life 0xffff00a9 detected.\n");
+ ndpi_int_secondlife_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len > 54 && memcmp(packet->payload, "\x40\x00\x00\x00\x01\x00\x08", 7) == 0 &&
+ get_u_int32_t(packet->payload, packet->payload_packet_len - 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SECONDLIFE, ndpi_struct, NDPI_LOG_DEBUG, "Second Life 0x08 detected.\n");
+ ndpi_int_secondlife_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+
+ NDPI_LOG(NDPI_PROTOCOL_SECONDLIFE, ndpi_struct, NDPI_LOG_DEBUG, "Second Life excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SECONDLIFE);
+}
+
+#endif
diff --git a/src/lib/protocols/ayiya.c b/src/lib/protocols/ayiya.c
new file mode 100644
index 000000000..c4d1a26ad
--- /dev/null
+++ b/src/lib/protocols/ayiya.c
@@ -0,0 +1,67 @@
+/*
+ * ayiya.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ http://en.wikipedia.org/wiki/Anything_In_Anything
+ http://tools.ietf.org/html/rfc4891
+*/
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_AYIYA
+
+struct ayiya {
+ u_int8_t flags[3];
+ u_int8_t next_header;
+ u_int32_t epoch;
+ u_int8_t identity[16];
+ u_int8_t signature[20];
+};
+
+void ndpi_search_ayiya(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(packet->udp && (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN)) {
+ /* Ayiya is udp based, port 5072 */
+ if ((packet->udp->source == htons(5072) || packet->udp->dest == htons(5072))
+ /* check for ayiya new packet */
+ && (packet->payload_packet_len > 44)
+ ) {
+ /* FINISH */
+ struct ayiya *a = (struct ayiya*)packet->payload;
+ u_int32_t epoch = ntohl(a->epoch), now;
+ u_int32_t fireyears = 86400 * 365 * 5;
+
+ now = flow->packet.tick_timestamp;
+
+ if((epoch >= (now - fireyears)) && (epoch <= (now+86400 /* 1 day */)))
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_AYIYA, NDPI_REAL_PROTOCOL);
+
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_AYIYA);
+ }
+}
+#endif
diff --git a/src/lib/protocols/battlefield.c b/src/lib/protocols/battlefield.c
new file mode 100644
index 000000000..374dcb61b
--- /dev/null
+++ b/src/lib/protocols/battlefield.c
@@ -0,0 +1,118 @@
+/*
+ * battlefield.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_BATTLEFIELD
+
+
+static void ndpi_int_battlefield_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_BATTLEFIELD, NDPI_REAL_PROTOCOL);
+
+ if (src != NULL) {
+ src->battlefield_ts = packet->tick_timestamp;
+ }
+ if (dst != NULL) {
+ dst->battlefield_ts = packet->tick_timestamp;
+ }
+}
+
+void ndpi_search_battlefield(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_BATTLEFIELD) {
+ if (src != NULL && ((u_int32_t)
+ (packet->tick_timestamp - src->battlefield_ts) < ndpi_struct->battlefield_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_BATTLEFIELD, ndpi_struct, NDPI_LOG_DEBUG,
+ "battlefield : save src connection packet detected\n");
+ src->battlefield_ts = packet->tick_timestamp;
+ } else if (dst != NULL && ((u_int32_t)
+ (packet->tick_timestamp - dst->battlefield_ts) < ndpi_struct->battlefield_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_BATTLEFIELD, ndpi_struct, NDPI_LOG_DEBUG,
+ "battlefield : save dst connection packet detected\n");
+ dst->battlefield_ts = packet->tick_timestamp;
+ }
+ return;
+ }
+
+ if (NDPI_SRC_OR_DST_HAS_PROTOCOL(src, dst, NDPI_PROTOCOL_BATTLEFIELD)) {
+ if (flow->l4.udp.battlefield_stage == 0 || flow->l4.udp.battlefield_stage == 1 + packet->packet_direction) {
+ if (packet->payload_packet_len > 8 && get_u_int16_t(packet->payload, 0) == htons(0xfefd)) {
+ flow->l4.udp.battlefield_msg_id = get_u_int32_t(packet->payload, 2);
+ flow->l4.udp.battlefield_stage = 1 + packet->packet_direction;
+ return;
+ }
+ } else if (flow->l4.udp.battlefield_stage == 2 - packet->packet_direction) {
+ if (packet->payload_packet_len > 8 && get_u_int32_t(packet->payload, 0) == flow->l4.udp.battlefield_msg_id) {
+ NDPI_LOG(NDPI_PROTOCOL_BATTLEFIELD, ndpi_struct,
+ NDPI_LOG_DEBUG, "Battlefield message and reply detected.\n");
+ ndpi_int_battlefield_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+
+ if (flow->l4.udp.battlefield_stage == 0) {
+ if (packet->payload_packet_len == 46 && packet->payload[2] == 0 && packet->payload[4] == 0
+ && get_u_int32_t(packet->payload, 7) == htonl(0x98001100)) {
+ flow->l4.udp.battlefield_stage = 3 + packet->packet_direction;
+ return;
+ }
+ } else if (flow->l4.udp.battlefield_stage == 4 - packet->packet_direction) {
+ if (packet->payload_packet_len == 7
+ && (packet->payload[0] == 0x02 || packet->payload[packet->payload_packet_len - 1] == 0xe0)) {
+ NDPI_LOG(NDPI_PROTOCOL_BATTLEFIELD, ndpi_struct, NDPI_LOG_DEBUG,
+ "Battlefield message and reply detected.\n");
+ ndpi_int_battlefield_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ if (packet->payload_packet_len == 18 && memcmp(&packet->payload[5], "battlefield2\x00", 13) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_BATTLEFIELD, ndpi_struct, NDPI_LOG_DEBUG, "Battlefield 2 hello packet detected.\n");
+ ndpi_int_battlefield_add_connection(ndpi_struct, flow);
+ return;
+ } else if (packet->payload_packet_len > 10 &&
+ (memcmp(packet->payload, "\x11\x20\x00\x01\x00\x00\x50\xb9\x10\x11", 10) == 0
+ || memcmp(packet->payload, "\x11\x20\x00\x01\x00\x00\x30\xb9\x10\x11", 10) == 0
+ || memcmp(packet->payload, "\x11\x20\x00\x01\x00\x00\xa0\x98\x00\x11", 10) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_BATTLEFIELD, ndpi_struct, NDPI_LOG_DEBUG, "Battlefield safe pattern detected.\n");
+ ndpi_int_battlefield_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_BATTLEFIELD);
+ return;
+}
+
+#endif
diff --git a/src/lib/protocols/bgp.c b/src/lib/protocols/bgp.c
new file mode 100644
index 000000000..8d4f00ab4
--- /dev/null
+++ b/src/lib/protocols/bgp.c
@@ -0,0 +1,57 @@
+/*
+ * bgp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_BGP
+
+
+static void ndpi_int_bgp_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_BGP, NDPI_REAL_PROTOCOL);
+}
+
+/* this detection also works asymmetrically */
+void ndpi_search_bgp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len > 18 &&
+ get_u_int64_t(packet->payload, 0) == 0xffffffffffffffffULL &&
+ get_u_int64_t(packet->payload, 8) == 0xffffffffffffffffULL &&
+ ntohs(get_u_int16_t(packet->payload, 16)) <= packet->payload_packet_len &&
+ (packet->tcp->dest == htons(179) || packet->tcp->source == htons(179))
+ && packet->payload[18] < 5) {
+ NDPI_LOG(NDPI_PROTOCOL_BGP, ndpi_struct, NDPI_LOG_DEBUG, "BGP detected.\n");
+ ndpi_int_bgp_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_BGP);
+}
+
+#endif
diff --git a/src/lib/protocols/bittorrent.c b/src/lib/protocols/bittorrent.c
new file mode 100644
index 000000000..4be42548f
--- /dev/null
+++ b/src/lib/protocols/bittorrent.c
@@ -0,0 +1,469 @@
+/*
+ * bittorrent.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_BITTORRENT
+#define NDPI_PROTOCOL_UNSAFE_DETECTION 0
+#define NDPI_PROTOCOL_SAFE_DETECTION 1
+
+#define NDPI_PROTOCOL_PLAIN_DETECTION 0
+#define NDPI_PROTOCOL_WEBSEED_DETECTION 2
+static void ndpi_add_connection_as_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow,
+ const u_int8_t save_detection, const u_int8_t encrypted_connection,
+ ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_change_protocol(ndpi_struct, flow, NDPI_PROTOCOL_BITTORRENT, protocol_type);
+}
+
+static u_int8_t ndpi_int_search_bittorrent_tcp_zero(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src = flow->src;
+ // struct ndpi_id_struct *dst = flow->dst;
+
+ u_int16_t a = 0;
+
+ if (packet->payload_packet_len == 1 && packet->payload[0] == 0x13) {
+ /* reset stage back to 0 so we will see the next packet here too */
+ flow->bittorrent_stage = 0;
+ return 0;
+ }
+ if (flow->packet_counter == 2 && packet->payload_packet_len > 20) {
+
+ if (memcmp(&packet->payload[0], "BitTorrent protocol", 19) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT,
+ ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
+ NDPI_REAL_PROTOCOL);
+ return 1;
+ }
+ }
+
+
+ if (packet->payload_packet_len > 20) {
+ /* test for match 0x13+"BitTorrent protocol" */
+ if (packet->payload[0] == 0x13) {
+ if (memcmp(&packet->payload[1], "BitTorrent protocol", 19) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT,
+ ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
+ NDPI_REAL_PROTOCOL);
+ return 1;
+ }
+ }
+ }
+
+ if (packet->payload_packet_len > 23 && memcmp(packet->payload, "GET /webseed?info_hash=", 23) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
+ NDPI_LOG_TRACE, "BT: plain webseed BitTorrent protocol detected\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION,
+ NDPI_CORRELATED_PROTOCOL);
+ return 1;
+ }
+ /* seen Azureus as server for webseed, possibly other servers existing, to implement */
+ /* is Server: hypertracker Bittorrent? */
+ /* no asymmetric detection possible for answer of pattern "GET /data?fid=". */
+ if (packet->payload_packet_len > 60
+ && memcmp(packet->payload, "GET /data?fid=", 14) == 0 && memcmp(&packet->payload[54], "&size=", 6) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
+ NDPI_LOG_TRACE, "BT: plain Bitcomet persistent seed protocol detected\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION,
+ NDPI_CORRELATED_PROTOCOL);
+ return 1;
+ }
+
+
+ if (packet->payload_packet_len > 90 && (memcmp(packet->payload, "GET ", 4) == 0
+ || memcmp(packet->payload, "POST ", 5) == 0)) {
+ const u_int8_t *ptr = &packet->payload[4];
+ u_int16_t len = packet->payload_packet_len - 4;
+ a = 0;
+
+
+ /* parse complete get packet here into line structure elements */
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ /* answer to this pattern is HTTP....Server: hypertracker */
+ if (packet->user_agent_line.ptr != NULL
+ && ((packet->user_agent_line.len > 8 && memcmp(packet->user_agent_line.ptr, "Azureus ", 8) == 0)
+ || (packet->user_agent_line.len >= 10 && memcmp(packet->user_agent_line.ptr, "BitTorrent", 10) == 0)
+ || (packet->user_agent_line.len >= 11 && memcmp(packet->user_agent_line.ptr, "BTWebClient", 11) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
+ NDPI_LOG_TRACE, "Azureus /Bittorrent user agent line detected\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION,
+ NDPI_CORRELATED_PROTOCOL);
+ return 1;
+ }
+
+ if (packet->user_agent_line.ptr != NULL
+ && (packet->user_agent_line.len >= 9 && memcmp(packet->user_agent_line.ptr, "Shareaza ", 9) == 0)
+ && (packet->parsed_lines > 8 && packet->line[8].ptr != 0
+ && packet->line[8].len >= 9 && memcmp(packet->line[8].ptr, "X-Queue: ", 9) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
+ NDPI_LOG_TRACE, "Bittorrent Shareaza detected.\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION,
+ NDPI_CORRELATED_PROTOCOL);
+ return 1;
+ }
+
+ /* this is a self built client, not possible to catch asymmetrically */
+ if ((packet->parsed_lines == 10 || (packet->parsed_lines == 11 && packet->line[11].len == 0))
+ && packet->user_agent_line.ptr != NULL
+ && packet->user_agent_line.len > 12
+ && memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 ",
+ 12) == 0
+ && packet->host_line.ptr != NULL
+ && packet->host_line.len >= 7
+ && packet->line[2].ptr != NULL
+ && packet->line[2].len > 14
+ && memcmp(packet->line[2].ptr, "Keep-Alive: 300", 15) == 0
+ && packet->line[3].ptr != NULL
+ && packet->line[3].len > 21
+ && memcmp(packet->line[3].ptr, "Connection: Keep-alive", 22) == 0
+ && packet->line[4].ptr != NULL
+ && packet->line[4].len > 10
+ && (memcmp(packet->line[4].ptr, "Accpet: */*", 11) == 0
+ || memcmp(packet->line[4].ptr, "Accept: */*", 11) == 0)
+
+ && packet->line[5].ptr != NULL
+ && packet->line[5].len > 12
+ && memcmp(packet->line[5].ptr, "Range: bytes=", 13) == 0
+ && packet->line[7].ptr != NULL
+ && packet->line[7].len > 15
+ && memcmp(packet->line[7].ptr, "Pragma: no-cache", 16) == 0
+ && packet->line[8].ptr != NULL
+ && packet->line[8].len > 22 && memcmp(packet->line[8].ptr, "Cache-Control: no-cache", 23) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "Bitcomet LTS detected\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
+ NDPI_CORRELATED_PROTOCOL);
+ return 1;
+
+ }
+
+ /* FlashGet pattern */
+ if (packet->parsed_lines == 8
+ && packet->user_agent_line.ptr != NULL
+ && packet->user_agent_line.len > (sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1)
+ && memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 (compatible; MSIE 6.0;",
+ sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1) == 0
+ && packet->host_line.ptr != NULL
+ && packet->host_line.len >= 7
+ && packet->line[2].ptr != NULL
+ && packet->line[2].len == 11
+ && memcmp(packet->line[2].ptr, "Accept: */*", 11) == 0
+ && packet->line[3].ptr != NULL && packet->line[3].len >= (sizeof("Referer: ") - 1)
+ && memcmp(packet->line[3].ptr, "Referer: ", sizeof("Referer: ") - 1) == 0
+ && packet->line[5].ptr != NULL
+ && packet->line[5].len > 13
+ && memcmp(packet->line[5].ptr, "Range: bytes=", 13) == 0
+ && packet->line[6].ptr != NULL
+ && packet->line[6].len > 21 && memcmp(packet->line[6].ptr, "Connection: Keep-Alive", 22) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "FlashGet detected\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
+ NDPI_CORRELATED_PROTOCOL);
+ return 1;
+
+ }
+ if (packet->parsed_lines == 7
+ && packet->user_agent_line.ptr != NULL
+ && packet->user_agent_line.len > (sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1)
+ && memcmp(packet->user_agent_line.ptr, "Mozilla/4.0 (compatible; MSIE 6.0;",
+ sizeof("Mozilla/4.0 (compatible; MSIE 6.0;") - 1) == 0
+ && packet->host_line.ptr != NULL
+ && packet->host_line.len >= 7
+ && packet->line[2].ptr != NULL
+ && packet->line[2].len == 11
+ && memcmp(packet->line[2].ptr, "Accept: */*", 11) == 0
+ && packet->line[3].ptr != NULL && packet->line[3].len >= (sizeof("Referer: ") - 1)
+ && memcmp(packet->line[3].ptr, "Referer: ", sizeof("Referer: ") - 1) == 0
+ && packet->line[5].ptr != NULL
+ && packet->line[5].len > 21 && memcmp(packet->line[5].ptr, "Connection: Keep-Alive", 22) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_TRACE, "FlashGet detected\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_UNSAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
+ NDPI_CORRELATED_PROTOCOL);
+ return 1;
+
+ }
+
+ /* answer to this pattern is not possible to implement asymmetrically */
+ while (1) {
+ if (len < 50 || ptr[0] == 0x0d) {
+ goto ndpi_end_bt_tracker_check;
+ }
+ if (memcmp(ptr, "info_hash=", 10) == 0) {
+ break;
+ }
+ len--;
+ ptr++;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
+ NDPI_LOG_TRACE, " BT stat: tracker info hash found\n");
+
+ /* len is > 50, so save operation here */
+ len -= 10;
+ ptr += 10;
+
+ /* parse bt hash */
+ for (a = 0; a < 20; a++) {
+ if (len < 3) {
+ goto ndpi_end_bt_tracker_check;
+ }
+ if (*ptr == '%') {
+ u_int8_t x1 = 0xFF;
+ u_int8_t x2 = 0xFF;
+
+
+ if (ptr[1] >= '0' && ptr[1] <= '9') {
+ x1 = ptr[1] - '0';
+ }
+ if (ptr[1] >= 'a' && ptr[1] <= 'f') {
+ x1 = 10 + ptr[1] - 'a';
+ }
+ if (ptr[1] >= 'A' && ptr[1] <= 'F') {
+ x1 = 10 + ptr[1] - 'A';
+ }
+
+ if (ptr[2] >= '0' && ptr[2] <= '9') {
+ x2 = ptr[2] - '0';
+ }
+ if (ptr[2] >= 'a' && ptr[2] <= 'f') {
+ x2 = 10 + ptr[2] - 'a';
+ }
+ if (ptr[2] >= 'A' && ptr[2] <= 'F') {
+ x2 = 10 + ptr[2] - 'A';
+ }
+
+ if (x1 == 0xFF || x2 == 0xFF) {
+ goto ndpi_end_bt_tracker_check;
+ }
+ ptr += 3;
+ len -= 3;
+ } else if (*ptr >= 32 && *ptr < 127) {
+ ptr++;
+ len--;
+ } else {
+ goto ndpi_end_bt_tracker_check;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
+ NDPI_LOG_TRACE, " BT stat: tracker info hash parsed\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
+ NDPI_CORRELATED_PROTOCOL);
+ return 1;
+ }
+
+ ndpi_end_bt_tracker_check:
+
+ if (packet->payload_packet_len == 80) {
+ /* Warez 80 Bytes Packet
+ * +----------------+---------------+-----------------+-----------------+
+ * |20 BytesPattern | 32 Bytes Value| 12 BytesPattern | 16 Bytes Data |
+ * +----------------+---------------+-----------------+-----------------+
+ * 20 BytesPattern : 4c 00 00 00 ff ff ff ff 57 00 00 00 00 00 00 00 20 00 00 00
+ * 12 BytesPattern : 28 23 00 00 01 00 00 00 10 00 00 00
+ * */
+ static const char pattern_20_bytes[20] = { 0x4c, 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0x57, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00
+ };
+ static const char pattern_12_bytes[12] = { 0x28, 0x23, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00
+ };
+
+ /* did not see this pattern anywhere */
+ if ((memcmp(&packet->payload[0], pattern_20_bytes, 20) == 0)
+ && (memcmp(&packet->payload[52], pattern_12_bytes, 12) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct,
+ NDPI_LOG_TRACE, "BT: Warez - Plain BitTorrent protocol detected\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
+ NDPI_REAL_PROTOCOL);
+ return 1;
+ }
+ }
+
+ else if (packet->payload_packet_len > 50) {
+ if (memcmp(packet->payload, "GET", 3) == 0) {
+
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ /* haven't fount this pattern anywhere */
+ if (packet->host_line.ptr != NULL
+ && packet->host_line.len >= 9 && memcmp(packet->host_line.ptr, "ip2p.com:", 9) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT,
+ ndpi_struct, NDPI_LOG_TRACE,
+ "BT: Warez - Plain BitTorrent protocol detected due to Host: ip2p.com: pattern\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_WEBSEED_DETECTION,
+ NDPI_CORRELATED_PROTOCOL);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*Search for BitTorrent commands*/
+static void ndpi_int_search_bittorrent_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if (packet->payload_packet_len == 0) {
+ return;
+ }
+
+ if (flow->bittorrent_stage == 0 && packet->payload_packet_len != 0) {
+ /* exclude stage 0 detection from next run */
+ flow->bittorrent_stage = 1;
+ if (ndpi_int_search_bittorrent_tcp_zero(ndpi_struct, flow) != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_DEBUG,
+ "stage 0 has detected something, returning\n");
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT, ndpi_struct, NDPI_LOG_DEBUG,
+ "stage 0 has no direct detection, fall through\n");
+ }
+ return;
+}
+
+void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ /* This is broadcast */
+ if(packet->iph
+ && ((packet->iph->saddr == 0xFFFFFFFF) || (packet->iph->daddr == 0xFFFFFFFF)))
+ return;
+
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_BITTORRENT) {
+ /* check for tcp retransmission here */
+
+ if ((packet->tcp != NULL)
+ && (packet->tcp_retransmission == 0 || packet->num_retried_bytes)) {
+ ndpi_int_search_bittorrent_tcp(ndpi_struct, flow);
+ }
+ else if(packet->udp != NULL) {
+ if((ntohs(packet->udp->source) < 1024)
+ || (ntohs(packet->udp->dest) < 1024) /* High ports only */)
+ return;
+
+ /*
+ Check for uTP http://www.bittorrent.org/beps/bep_0029.html
+
+ wireshark/epan/dissectors/packet-bt-utp.c
+ */
+
+ if(packet->payload_packet_len >= 23 /* min header size */) {
+ /* Check if this is protocol v0 */
+ u_int8_t v0_extension = packet->payload[17];
+ u_int8_t v0_flags = packet->payload[18];
+
+ /* Check if this is protocol v1 */
+ u_int8_t v1_version = packet->payload[0];
+ u_int8_t v1_extension = packet->payload[1];
+ u_int32_t v1_window_size = *((u_int32_t*)&packet->payload[12]);
+
+ if((packet->payload[0]== 0x60)
+ && (packet->payload[1]== 0x0)
+ && (packet->payload[2]== 0x0)
+ && (packet->payload[3]== 0x0)
+ && (packet->payload[4]== 0x0)) {
+ /* Heuristic */
+ goto bittorrent_found;
+ } else if(((v1_version & 0x0f) == 1)
+ && ((v1_version >> 4) < 5 /* ST_NUM_STATES */)
+ && (v1_extension < 3 /* EXT_NUM_EXT */)
+ && (v1_window_size < 32768 /* 32k */)
+ ) {
+ goto bittorrent_found;
+ } else if((v0_flags < 6 /* ST_NUM_STATES */)
+ && (v0_extension < 3 /* EXT_NUM_EXT */)) {
+ u_int32_t ts = ntohl(*((u_int32_t*)&(packet->payload[4])));
+ u_int32_t now;
+
+#ifndef __KERNEL__
+ now = (u_int32_t)time(NULL);
+#else
+ struct timespec t;
+
+ getnstimeofday(&t);
+ now = t.tv_sec;
+#endif
+
+ if((ts < (now+86400)) && (ts > (now-86400))) {
+ goto bittorrent_found;
+ }
+ }
+ }
+
+ flow->bittorrent_stage++;
+
+ if(flow->bittorrent_stage < 10) {
+ if(packet->payload_packet_len > 19 /* min size */) {
+ if(ndpi_strnstr((const char *)packet->payload, ":target20:", packet->payload_packet_len)
+ || ndpi_strnstr((const char *)packet->payload, ":find_node1:", packet->payload_packet_len)
+ || ndpi_strnstr((const char *)packet->payload, "d1:ad2:id20:", packet->payload_packet_len)
+ || ndpi_strnstr((const char *)packet->payload, ":info_hash20:", packet->payload_packet_len)
+ || ndpi_strnstr((const char *)packet->payload, ":filter64", packet->payload_packet_len)
+ || ndpi_strnstr((const char *)packet->payload, "d1:rd2:id20:", packet->payload_packet_len)
+ || ndpi_strnstr((const char *)packet->payload, "BitTorrent protocol", packet->payload_packet_len)
+ ) {
+ bittorrent_found:
+ NDPI_LOG(NDPI_PROTOCOL_BITTORRENT,
+ ndpi_struct, NDPI_LOG_TRACE, "BT: plain BitTorrent protocol detected\n");
+ ndpi_add_connection_as_bittorrent(ndpi_struct, flow,
+ NDPI_PROTOCOL_SAFE_DETECTION, NDPI_PROTOCOL_PLAIN_DETECTION,
+ NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_BITTORRENT);
+ }
+ }
+}
+#endif
diff --git a/src/lib/protocols/btlib.c b/src/lib/protocols/btlib.c
new file mode 100644
index 000000000..6442c7db7
--- /dev/null
+++ b/src/lib/protocols/btlib.c
@@ -0,0 +1,509 @@
+/*
+ * btlib.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Contributed by Vitaly Lavrov <vel21ripn@gmail.com>
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef NDPI_NO_STD_INC
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+
+typedef unsigned char u_int8_t;
+typedef unsigned short int u_int16_t;
+typedef unsigned long long int u_int64_t;
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#endif
+
+typedef signed long long int i_int64_t;
+
+#include "btlib.h"
+
+#ifndef __KERNEL__
+
+int bt_parse_debug = 0;
+
+static char *printXb(char *s,const u_int8_t *b,int l) {
+ int i;
+ for(i=0; i < l; i++)
+ snprintf(&s[i*2],41,"%02x",b[i]);
+ return s;
+}
+
+static char *print20b(char *s,const u_int8_t *b) {
+ snprintf(s,41,"%08x%08x%08x%08x%08x",
+ htonl(*(u_int32_t*)b),
+ htonl(*(u_int32_t*)(b+4)),
+ htonl(*(u_int32_t*)(b+8)),
+ htonl(*(u_int32_t*)(b+12)),
+ htonl(*(u_int32_t*)(b+16)));
+ return s;
+}
+
+static char *print_id_ip_p(char *s, const struct bt_nodes_data *b) {
+ u_int8_t *p = (void*)b;
+ print20b(s,b->id);
+ snprintf(s+40,39," %d.%d.%d.%d:%u",
+ p[20], p[21], p[22], p[23], htons(b->port));
+ return s;
+}
+
+static char *print_ip_p(char *s, const struct bt_ipv4p *b,int np) {
+ const u_int8_t *p = (const void*)b;
+ snprintf(s,39,!np ? "%d.%d.%d.%d:%u":"%d.%d.%d.%d",
+ p[0], p[1], p[2], p[3], htons(b->port));
+ return s;
+}
+
+static char *print_ip6_p(char *s, const struct bt_ipv6p *b,int np) {
+ u_int16_t *p = (void*)b;
+ snprintf(s,79,!np ? "%x:%x:%x:%x:%x:%x:%x:%x.%u":"%x:%x:%x:%x:%x:%x:%x:%x",
+ htons(p[0]), htons(p[1]), htons(p[2]), htons(p[3]),
+ htons(p[4]), htons(p[5]), htons(p[6]), htons(p[7]),
+ htons(b->port));
+ return s;
+}
+
+static char *print_id_ip6_p(char *s,const struct bt_nodes6_data *b) {
+ return print_ip6_p(s,(struct bt_ipv6p *)&b->ip,0);
+}
+
+
+void dump_bt_proto_struct(struct bt_parse_protocol *p) {
+ char b20h[128];
+ int i;
+
+ if(p->y_e && p->e_msg) {
+ printf("Error %s/%u\n", p->e_msg, p->e_len);
+ }
+ if(p->y_q) {
+ printf("Query ");
+ if(p->q_ping) printf("ping\n");
+ if(p->q_g_peers) printf("get_peers\n");
+ if(p->q_f_node) printf("find_node\n");
+ if(p->q_a_peer) printf("announce_peer\n");
+ }
+ if(p->y_r)
+ printf("Reply\n");
+
+ if(p->t) printf("\tt\t%llx\n",p->t);
+ if(p->v) printf("\tv\t%llx\n",p->v);
+ if(p->ip) printf("\tIP\t%s\n",print_ip_p(b20h,p->ip,0));
+
+ if(p->a.port) printf("\tport\t%d\n",htons(p->a.port));
+ if(p->a.id) printf("\tID\t%s\n",print20b(b20h,p->a.id));
+ if(p->a.target) printf("\ttarget\t%s\n",print20b(b20h,p->a.target));
+ if(p->a.token) printf("\ttoken\t%s\n",printXb(b20h,p->a.token,p->a.t_len));
+ if(p->a.info_hash) printf("\ti_hash\t%s\n",print20b(b20h,p->a.info_hash));
+ if(p->a.name && p->a.name_len) printf("\tname\t%.*s\n",p->a.name_len,p->a.name);
+
+ if(p->r.ip) printf("\tip\t%s\n",print_ip_p(b20h,p->r.ip,1));
+ if(p->r.port) printf("\tport\t%d\n",htons(p->r.port));
+ if(p->r.id) printf("\tID\t%s\n",print20b(b20h,p->r.id));
+ if(p->r.token) printf("\ttoken\t%s\n",printXb(b20h,p->r.token,p->r.t_len));
+ if(p->r.name && p->r.name_len) printf("\tname\t%.*s\n",p->r.name_len,p->r.name);
+ if(p->r.values && p->r.nv) {
+ struct bt_ipv4p2 *n = (struct bt_ipv4p2 *)p->r.values;
+ for(i=0;i < p->r.nv; i++,n++) {
+ printf("\tvalues\t%s\n", print_ip_p(b20h,&n->d,0));
+ }
+ }
+ if(p->r.values6 && p->r.nv6) {
+ struct bt_ipv6p2 *n = (struct bt_ipv6p2 *)p->r.values6;
+ for(i=0;i < p->r.nv6; i++,n++) {
+ printf("\tvalues6\t%s\n", print_ip6_p(b20h,&n->d,0));
+ }
+ }
+ if(p->r.nodes && p->r.nn) {
+ for(i=0;i < p->r.nn; i++) {
+ printf("\tnodes\t%s\n",print_id_ip_p(b20h,p->r.nodes+i));
+ }
+ }
+ if(p->r.nodes6 && p->r.nn6) {
+ for(i=0;i < p->r.nn6; i++) {
+ printf("\tnodes6\t%s\n",print_id_ip6_p(b20h,p->r.nodes6+i));
+ }
+ }
+
+ if(p->peers && p->n_peers) {
+ for(i=0;i < p->n_peers; i++) {
+ printf("\tpeers\t%s\n",print_ip_p(b20h,p->peers+i,0));
+ }
+ }
+
+ if(p->interval) printf("\tinterval\t%d\n",p->interval);
+ if(p->min_interval) printf("\tmin interval\t%d\n",p->min_interval);
+}
+
+static void _print_safe_str(char *msg,char *k,const u_int8_t *s,size_t l) {
+ static const char *th="0123456789abcdef?";
+ char *buf = (char*)ndpi_malloc((size_t)(l*3+2));
+
+ int sl = l;
+ if(buf) {
+ char *b = buf;
+ for(;l > 0; s++,l--) {
+ if(*s < ' ' || *s >= 127) {
+ *b++ = '%';
+ *b++ = th[(*s >> 4)&0xf];
+ *b++ = th[(*s)&0xf];
+ } else *b++ = *s;
+ }
+ *b = 0;
+
+ printf("%s %s %s len %d\n",msg,k,buf ? buf:"",sl);
+
+ ndpi_free(buf);
+ }
+}
+
+static void print_safe_str(char *msg,bt_parse_data_cb_t *cbd) {
+ _print_safe_str(msg,cbd->buf,cbd->v.s.s,cbd->v.s.l);
+}
+#define DEBUG_TRACE(cmd) { if(bt_parse_debug) cmd; }
+#else
+#define DEBUG_TRACE(cmd,args...)
+#endif /* __KERNEL */
+
+#define STREQ(a,b) !strcmp(a,b)
+
+
+void cb_data(bt_parse_data_cb_t *cbd,int *ret) {
+ struct bt_parse_protocol *p = &(cbd->p);
+ const u_int8_t *s;
+ const char *ss;
+
+ if(cbd->t == 0) return;
+
+ if(cbd->t == 1) {
+
+ DEBUG_TRACE(printf("%s %lld\n",cbd->buf,cbd->v.i));
+
+ if(STREQ(cbd->buf,"a.port")) {
+ p->a.port = (u_int16_t)(cbd->v.i & 0xffff);
+ return;
+ }
+ if(
+ STREQ(cbd->buf,"a.implied_port") ||
+ STREQ(cbd->buf,"a.noseed") ||
+ STREQ(cbd->buf,"a.scrape") ||
+ STREQ(cbd->buf,"a.seed") ||
+ STREQ(cbd->buf,"a.vote")
+ ) {
+ return;
+ }
+ if(STREQ(cbd->buf,"r.port") || STREQ(cbd->buf,"r.p")) {
+ p->r.port = (u_int16_t)(cbd->v.i & 0xffff);
+ return;
+ }
+ if(STREQ(cbd->buf,"interval")) {
+ p->interval = (u_int16_t)(cbd->v.i & 0x7fffffff);
+ p->h_int = 1;
+ return;
+ }
+ if(STREQ(cbd->buf,"min interval")) {
+ p->min_interval = (u_int16_t)(cbd->v.i & 0x7fffffff);
+ p->h_mint = 1;
+ return;
+ }
+ DEBUG_TRACE(printf("UNKNOWN %s %lld\n",cbd->buf,cbd->v.i));
+ return;
+ }
+ if(cbd->t != 2) {
+ DEBUG_TRACE(printf("BUG! t=%d %s\n",cbd->t,cbd->buf));
+ return;
+ }
+ DEBUG_TRACE(print_safe_str("",cbd));
+
+ s = cbd->v.s.s;
+ ss = (char *)s;
+
+ if(STREQ(cbd->buf,"a.id")) {
+ p->a.id = s;
+ return;
+ }
+ if(STREQ(cbd->buf,"a.info_hash")) {
+ p->a.info_hash = s;
+ return;
+ }
+ if(STREQ(cbd->buf,"a.target")) {
+ p->a.target = s;
+ return;
+ }
+ if(STREQ(cbd->buf,"a.token")) {
+ p->a.token = s;
+ p->a.t_len = cbd->v.s.l;
+ return;
+ }
+ if(STREQ(cbd->buf,"a.name")) {
+ p->a.name = s;
+ p->a.name_len = cbd->v.s.l;
+ return;
+ }
+ if(STREQ(cbd->buf,"a.want")) {
+ return;
+ }
+
+ if(STREQ(cbd->buf,"r.id")) {
+ p->r.id = s;
+ return;
+ }
+ if(STREQ(cbd->buf,"r.ip")) {
+ if(cbd->v.s.l != 4) {
+ DEBUG_TRACE(printf("BUG! r.ip with port\n"));
+ return;
+ }
+ p->r.ip = (struct bt_ipv4p *)s;
+ return;
+ }
+ if(STREQ(cbd->buf,"r.token")) {
+ p->r.token = s;
+ p->r.t_len = cbd->v.s.l;
+ return;
+ }
+ if(STREQ(cbd->buf,"r.values")) {
+ if(cbd->v.s.l == 18) {
+ if(!p->r.values6) {
+ p->r.values6 = s;
+ p->r.nv6 = 1;
+ } else {
+ if(s != p->r.values6+(p->r.nv6*21)) {
+ // DEBUG_TRACE(printf("BUG! r.values6 not in list! %08x %08x \n", p->r.values+(p->r.nv6*21),s));
+ return;
+ }
+ p->r.nv6++;
+ }
+ return;
+ }
+ if(cbd->v.s.l == 6) {
+ if(!p->r.values) {
+ p->r.values = s;
+ p->r.nv = 1;
+ } else {
+ if(s != p->r.values+(p->r.nv*8)) {
+ // DEBUG_TRACE(printf("BUG! r.values not in list! %u \n",s-p->r.values+(p->r.nv*8)));
+ return;
+ }
+ p->r.nv++;
+ }
+ return;
+ }
+ return;
+ }
+
+ if(STREQ(cbd->buf,"r.name") || STREQ(cbd->buf,"r.n")) {
+ p->r.name = s;
+ p->r.name_len = cbd->v.s.l;
+ return;
+ }
+ if(STREQ(cbd->buf,"r.nodes")) {
+ if(cbd->v.s.l % 26) {
+ // DEBUG_TRACE(printf("BUG! r.nodes length %d not %% 26\n",cbd->v.s.l));
+ return;
+ }
+ p->r.nodes = (struct bt_nodes_data *)s;
+ p->r.nn = cbd->v.s.l / 26;
+ return;
+ }
+ if(STREQ(cbd->buf,"r.nodes6")) {
+ if(cbd->v.s.l % 38) {
+ // DEBUG_TRACE(printf("BUG! r.nodes length %d not %% 38\n",cbd->v.s.l));
+ return;
+ }
+ p->r.nodes6 = (struct bt_nodes6_data *)s;
+ p->r.nn6 = cbd->v.s.l / 38;
+ return;
+ }
+
+ if(cbd->buf[0] == 'y' && !cbd->buf[1]) {
+ if(cbd->v.s.l != 1) return;
+ if(*ss == 'q') { p->y_q = 1; return; }
+ if(*ss == 'r') { p->y_r = 1; return; }
+ if(*ss == 'e') { p->y_e = 1; return; }
+ return;
+ }
+ if(cbd->buf[0] == 'q' && !cbd->buf[1]) {
+ if(!strncmp(ss,"announce_peer",13)) {
+ p->q_a_peer = 1;
+ return;
+ }
+ if(!strncmp(ss,"find_node",9)) {
+ p->q_f_node = 1;
+ return;
+ }
+ if(!strncmp(ss,"get_peers",9)) {
+ p->q_g_peers = 1;
+ return;
+ }
+ if(!strncmp(ss,"ping",4)) {
+ p->q_ping = 1;
+ return;
+ }
+ if(!strncmp(ss,"vote",4)) {
+ return;
+ }
+ }
+ if(STREQ(cbd->buf,"ip")) {
+ if(cbd->v.s.l != 6) {
+ // DEBUG_TRACE(printf("BUG! r.ip w/o port\n"));
+ }
+ p->ip = (struct bt_ipv4p *)s;
+ p->h_ip = 1;
+ return;
+ }
+ if(STREQ(cbd->buf,"peers")) {
+ if(cbd->v.s.l % 6) return;
+ p->peers = (struct bt_ipv4p *)s;
+ p->n_peers = cbd->v.s.l / 6;
+ return;
+ }
+ if((*cbd->buf == 't' || *cbd->buf == 'v') && !cbd->buf[1]) {
+ u_int64_t d = *(u_int64_t*)s;
+ switch(cbd->v.s.l) {
+ case 2:
+ d &= 0xffffllu; d = htons(d); break;
+ case 4:
+ d &= 0xffffffffllu; d = htonl(d); break;
+ case 6:
+ d &= 0xffffffffffffllu; d = (htonl(d & 0xffffffff) << 16) |
+ (htons(d >> 32) & 0xffff);
+ break;
+ case 8: d = ((u_int64_t)htonl(d & 0xffffffff) << 32) |
+ htonl(d >> 32);
+ break;
+ default: d = 0;
+ }
+ if(*cbd->buf == 'v') cbd->p.v = d;
+ else cbd->p.t = d;
+ return;
+ }
+
+ if(cbd->buf[0] == 'e' && !cbd->buf[0]) {
+ p->e_msg = s;
+ p->e_len = cbd->v.s.l;
+ return;
+ }
+ // DEBUG_TRACE(print_safe_str("UKNOWN",cbd));
+}
+
+
+const u_int8_t *bt_decode(const u_int8_t *b, size_t *l, int *ret, bt_parse_data_cb_t *cbd) {
+
+ unsigned int n=0,neg=0;
+ i_int64_t d = 0;
+ register u_int8_t c;
+
+ if(*l == 0) return NULL;
+ if(cbd->level > BDEC_MAXDEPT) goto bad_data;
+ c = *b++; (*l)--;
+ if(c == 'i') { // integer
+ while(*l) {
+ c = *b++; (*l)--;
+ n++;
+ if(c == '-') {
+ if(n != 1) goto bad_data;
+ n--;
+ neg=1;
+ continue;
+ }
+ if(c >= '0' && c <= '9') {
+ if(c == '0' && n > 1 && !d && *b != 'e') goto bad_data;
+ d *= 10;
+ d += c-'0';
+ continue;
+ }
+ if(c != 'e') goto bad_data;
+ break;
+ }
+ if(neg) d=-d;
+ cbd->t = 1;
+ cbd->v.i = neg ? -d:d;
+ return b;
+ }
+ if(c >= '1' && c <= '9') { //string
+ d=c-'0';
+ while(*l) {
+ c = *b++; (*l)--;
+ n++;
+ if(c >= '0' && c <= '9') {
+ if(c == '0' && n > 1 && d == 0) goto bad_data;
+ d *= 10;
+ d += c-'0';
+ continue;
+ }
+ if(c != ':') goto bad_data;
+ break;
+ }
+ if(d > *l) goto bad_data;
+ cbd->t = 2;
+ cbd->v.s.s = b;
+ cbd->v.s.l = d;
+ b += d;
+ *l -= d;
+ return b;
+ }
+ if(c == 'l') {
+ cbd->level++;
+ do {
+ b = bt_decode(b,l,ret,cbd);
+ if(*ret < 0 || *l == 0) goto bad_data;
+ cb_data(cbd,ret);
+ if(*ret < 0) goto bad_data;
+ cbd->t = 0;
+ } while (*b != 'e' && *l != 0);
+ b++; (*l)--;
+ cbd->level--;
+ return b;
+ }
+ if(c == 'd') {
+ cbd->level++;
+ do {
+ char *ls = cbd->buf + strlen(cbd->buf);
+ int l1 = ls != cbd->buf ? 1:0;
+ if(!(*b >= '1' && *b <= '9')) goto bad_data;
+ b = bt_decode(b,l,ret,cbd);
+ if(*ret < 0 || *l == 0) goto bad_data;
+ if(ls+cbd->v.s.l+l1 < &cbd->buf[sizeof(cbd->buf)-1]) {
+ if(l1) ls[0]='.';
+ strncpy(ls+l1,(char *)cbd->v.s.s,cbd->v.s.l);
+ ls[cbd->v.s.l+l1]=0;
+ }
+ b = bt_decode(b,l,ret,cbd);
+ if(*ret < 0 || *l == 0) goto bad_data;
+ cb_data(cbd,ret);
+ if(*ret < 0) goto bad_data;
+ cbd->t = 0;
+ *ls = 0;
+ } while (*b != 'e' && l != 0);
+
+ b++; (*l)--;
+ cbd->level--;
+ return b;
+ }
+ bad_data:
+ *ret=-1;
+ return b;
+}
diff --git a/src/lib/protocols/btlib.h b/src/lib/protocols/btlib.h
new file mode 100644
index 000000000..cc2928155
--- /dev/null
+++ b/src/lib/protocols/btlib.h
@@ -0,0 +1,147 @@
+/*
+ * btlib.h
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ * Contributed by Vitaly Lavrov <vel21ripn@gmail.com>
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#define BDEC_MAXDEPT 8
+
+
+typedef struct b_elem_s {
+ const u_int8_t *s;
+ size_t l;
+} b_elem_s_t;
+
+struct __attribute__ ((__packed__)) bt_nodes_data {
+ u_int8_t id[20] ;
+ u_int32_t ip;
+ u_int16_t port;
+};
+
+struct __attribute__ ((__packed__)) bt_ipv4p {
+ u_int32_t ip;
+ u_int16_t port;
+};
+
+struct __attribute__ ((__packed__)) bt_ipv4p2 {
+ struct bt_ipv4p d;
+ u_int8_t pad[2];
+};
+
+struct __attribute__ ((__packed__)) bt_nodes6_data {
+ u_int8_t id[20] ;
+ u_int32_t ip[4];
+ u_int16_t port;
+};
+
+struct __attribute__ ((__packed__)) bt_ipv6p {
+ u_int32_t ip[4];
+ u_int16_t port;
+};
+
+struct __attribute__ ((__packed__)) bt_ipv6p2 {
+ struct bt_ipv6p d;
+ u_int8_t pad[3];
+};
+
+/*
+
+ a.id S r.id S
+ a.info_hash S r.ip ipv4
+ a.name S r.nodes x(id,ipv4,port)
+ -a.noseed 0|1 r.n S name of file
+ a.port N r.p port
+ -a.scrape 0|1 r.token S
+ -a.seed 0|1 r.values x(ipv4,port)
+ a.target S
+ a.token S -a.vote N
+ -a.want n4|n6
+
+ q announce_peer q find_node
+ q get_peers q ping
+ -q vote
+
+ ip ipv4+port interval N
+ min interval N peers x(ipv4,port)
+ t 2/4/8b v 4/6b
+
+ e S y e y r y q
+
+ */
+
+struct bt_parse_protocol {
+ u_int16_t y_e:1, y_r:1, y_q:1,
+ q_a_peer:1,q_f_node:1,
+ q_g_peers:1,q_ping:1,
+ h_int:1,h_mint:1,h_ip:1;
+ struct {
+ const u_int8_t *id, // 20
+ *info_hash, // 20
+ *target, // 20
+ *token, // 20|8
+ *name; // varlen
+ u_int16_t name_len;
+ u_int16_t port;
+ u_int16_t t_len;
+ } a;
+ struct {
+ const u_int8_t *id, // 20
+ *token, // 20|8
+ *values, // (6+2)*x
+ *values6, // (18_3)*x
+ *name; // varlen
+ struct bt_ipv4p *ip;
+ struct bt_nodes_data *nodes;
+ struct bt_nodes6_data *nodes6;
+ u_int16_t name_len;
+ u_int16_t nn; // nodes num
+ u_int16_t nv; // valuse num
+ u_int16_t nn6; // nodes6 num
+ u_int16_t nv6; // valuse6 num
+ u_int16_t port;
+ u_int16_t t_len;
+ } r;
+ int interval,min_interval;
+ struct bt_ipv4p *peers;
+ int n_peers;
+ struct bt_ipv4p *ip;
+ const u_int8_t *e_msg;
+ u_int16_t e_len;
+ u_int64_t t,v;
+};
+
+typedef struct bt_parse_data_cb {
+ struct bt_parse_protocol p;
+ char buf[64];
+ int level;
+ int t;
+ union {
+ i_int64_t i;
+ b_elem_s_t s;
+ } v;
+} bt_parse_data_cb_t;
+
+#ifndef __KERNEL__
+extern int bt_parse_debug;
+void dump_bt_proto_struct(struct bt_parse_protocol *p);
+#endif
+const u_int8_t *bt_decode(const u_int8_t *b, size_t *l, int *ret, bt_parse_data_cb_t *cbd);
+
diff --git a/src/lib/protocols/ciscovpn.c b/src/lib/protocols/ciscovpn.c
new file mode 100644
index 000000000..9245a6aaa
--- /dev/null
+++ b/src/lib/protocols/ciscovpn.c
@@ -0,0 +1,70 @@
+/*
+ * ciscovpn.c
+ * Copyright (C) 2013 by Remy Mudingay <mudingay@ill.fr>
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_CISCOVPN
+
+static void ndpi_int_ciscovpn_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_CISCOVPN, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_ciscovpn(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t udport = 0, usport = 0;
+ u_int16_t tdport = 0, tsport = 0;
+
+
+ NDPI_LOG(NDPI_PROTOCOL_CISCOVPN, ndpi_struct, NDPI_LOG_DEBUG, "search CISCOVPN.\n");
+
+ if(packet->tcp != NULL) {
+ tsport = ntohs(packet->tcp->source), tdport = ntohs(packet->tcp->dest);
+ NDPI_LOG(NDPI_PROTOCOL_CISCOVPN, ndpi_struct, NDPI_LOG_DEBUG, "calculated CISCOVPN over tcp ports.\n");
+ }
+ if(packet->udp != NULL) {
+ usport = ntohs(packet->udp->source), udport = ntohs(packet->udp->dest);
+ NDPI_LOG(NDPI_PROTOCOL_CISCOVPN, ndpi_struct, NDPI_LOG_DEBUG, "calculated CISCOVPN over udp ports.\n");
+ }
+
+ if((tdport == 10000 && tsport == 10000) ||
+ ((tsport == 443 || tdport == 443) &&
+ (packet->payload[0] == 0x17 &&
+ packet->payload[1] == 0x01 &&
+ packet->payload[2] == 0x00 &&
+ packet->payload[3] == 0x00)
+ )
+ )
+
+ {
+ /* This is a good query 17010000*/
+ NDPI_LOG(NDPI_PROTOCOL_CISCOVPN, ndpi_struct, NDPI_LOG_DEBUG, "found CISCOVPN.\n");
+ ndpi_int_ciscovpn_add_connection(ndpi_struct, flow);
+ }
+ else if(
+ (
+ (usport == 10000 && udport == 10000)
+ &&
+ (packet->payload[0] == 0xfe &&
+ packet->payload[1] == 0x57 &&
+ packet->payload[2] == 0x7e &&
+ packet->payload[3] == 0x2b)
+ )
+ )
+ {
+
+
+ /* This is a good query fe577e2b */
+ NDPI_LOG(NDPI_PROTOCOL_CISCOVPN, ndpi_struct, NDPI_LOG_DEBUG, "found CISCOVPN.\n");
+ ndpi_int_ciscovpn_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_CISCOVPN, ndpi_struct, NDPI_LOG_DEBUG, "exclude CISCOVPN.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_CISCOVPN);
+ }
+
+}
+#endif
diff --git a/src/lib/protocols/citrix.c b/src/lib/protocols/citrix.c
new file mode 100644
index 000000000..1cae9f9e5
--- /dev/null
+++ b/src/lib/protocols/citrix.c
@@ -0,0 +1,93 @@
+/*
+ * citrix.c
+ *
+ * Copyright (C) 2012-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_CITRIX
+
+/* ************************************ */
+
+static void ndpi_check_citrix(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+#if 0
+ printf("[len=%u][%02X %02X %02X %02X]\n", payload_len,
+ packet->payload[0] & 0xFF,
+ packet->payload[1] & 0xFF,
+ packet->payload[2] & 0xFF,
+ packet->payload[3] & 0xFF);
+#endif
+
+ if(packet->tcp != NULL) {
+ flow->l4.tcp.citrix_packet_id++;
+
+ if((flow->l4.tcp.citrix_packet_id == 3)
+ /* We have seen the 3-way handshake */
+ && flow->l4.tcp.seen_syn
+ && flow->l4.tcp.seen_syn_ack
+ && flow->l4.tcp.seen_ack) {
+ if(payload_len == 6) {
+ char citrix_header[] = { 0x07, 0x07, 0x49, 0x43, 0x41, 0x00 };
+
+ if(memcmp(packet->payload, citrix_header, sizeof(citrix_header)) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_CITRIX, ndpi_struct, NDPI_LOG_DEBUG, "Found citrix.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_CITRIX, NDPI_REAL_PROTOCOL);
+ }
+
+ return;
+ } else if(payload_len > 4) {
+ char citrix_header[] = { 0x1a, 0x43, 0x47, 0x50, 0x2f, 0x30, 0x31 };
+
+ if((memcmp(packet->payload, citrix_header, sizeof(citrix_header)) == 0)
+ || (ndpi_strnstr((const char *)packet->payload, "Citrix.TcpProxyService", payload_len) != NULL)) {
+ NDPI_LOG(NDPI_PROTOCOL_CITRIX, ndpi_struct, NDPI_LOG_DEBUG, "Found citrix.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_CITRIX, NDPI_REAL_PROTOCOL);
+ }
+
+ return;
+ }
+
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_CITRIX);
+ } else if(flow->l4.tcp.citrix_packet_id > 3)
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_CITRIX);
+
+ return;
+ }
+}
+
+void ndpi_search_citrix(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_CITRIX, ndpi_struct, NDPI_LOG_DEBUG, "citrix detection...\n");
+
+ /* skip marked packets */
+ if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_CITRIX)
+ ndpi_check_citrix(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/collectd.c b/src/lib/protocols/collectd.c
new file mode 100644
index 000000000..eee805d5c
--- /dev/null
+++ b/src/lib/protocols/collectd.c
@@ -0,0 +1,53 @@
+/*
+ * collectd.c
+ *
+ * Copyright (C) 2014 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_COLLECTD
+
+void ndpi_search_collectd(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int len = 0;
+
+ NDPI_LOG(NDPI_PROTOCOL_COLLECTD, ndpi_struct, NDPI_LOG_DEBUG, "search collectd.\n");
+
+ if (packet->udp == NULL) return;
+
+
+ while(len < packet->payload_packet_len) {
+ // u_int16_t elem_type = ntohs(*((u_int16_t*)&packet->payload[len]));
+ u_int16_t elem_len = ntohs(*((u_int16_t*)&packet->payload[len+2]));
+
+ if (elem_len == 0) break;
+
+ len += elem_len;
+ }
+
+ if(len == packet->payload_packet_len) {
+ NDPI_LOG(NDPI_PROTOCOL_COLLECTD, ndpi_struct, NDPI_LOG_DEBUG, "found COLLECTD.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_COLLECTD, NDPI_REAL_PROTOCOL);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_COLLECTD, ndpi_struct, NDPI_LOG_DEBUG, "exclude COLLECTD.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_COLLECTD);
+ }
+}
+#endif
diff --git a/src/lib/protocols/corba.c b/src/lib/protocols/corba.c
new file mode 100644
index 000000000..050d1035d
--- /dev/null
+++ b/src/lib/protocols/corba.c
@@ -0,0 +1,48 @@
+/*
+ * corba.c
+ *
+ * Copyright (C) 2013 Remy Mudingay <mudingay@ill.fr>
+ *
+ * This module is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This module 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_CORBA
+static void ndpi_int_corba_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_CORBA, NDPI_CORRELATED_PROTOCOL);
+}
+void ndpi_search_corba(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_CORBA, ndpi_struct, NDPI_LOG_DEBUG, "search for CORBA.\n");
+ if(packet->tcp != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_CORBA, ndpi_struct, NDPI_LOG_DEBUG, "calculating CORBA over tcp.\n");
+ /* Corba General Inter-ORB Protocol -> GIOP */
+ if ((packet->payload_packet_len >= 24 && packet->payload_packet_len <= 144) &&
+ memcmp(packet->payload, "GIOP", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_CORBA, ndpi_struct, NDPI_LOG_DEBUG, "found corba.\n");
+ ndpi_int_corba_add_connection(ndpi_struct, flow);
+ }
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_CORBA, ndpi_struct, NDPI_LOG_DEBUG, "exclude CORBA.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_CORBA);
+ }
+}
+#endif
diff --git a/src/lib/protocols/crossfire.c b/src/lib/protocols/crossfire.c
new file mode 100644
index 000000000..cb5b3520f
--- /dev/null
+++ b/src/lib/protocols/crossfire.c
@@ -0,0 +1,85 @@
+/*
+ * crossfire.c
+ *
+ * Copyright (C) 2012-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+/* include files */
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_CROSSFIRE
+
+
+static void ndpi_int_crossfire_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, ndpi_protocol_type_t protocol_type)
+{
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_CROSSFIRE, protocol_type);
+}
+
+void ndpi_search_crossfire_tcp_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_CROSSFIRE, ndpi_struct, NDPI_LOG_DEBUG, "search crossfire.\n");
+
+
+ if (packet->udp != 0) {
+ if (packet->payload_packet_len == 25 && get_u_int32_t(packet->payload, 0) == ntohl(0xc7d91999)
+ && get_u_int16_t(packet->payload, 4) == ntohs(0x0200)
+ && get_u_int16_t(packet->payload, 22) == ntohs(0x7d00)
+ ) {
+ NDPI_LOG(NDPI_PROTOCOL_CROSSFIRE, ndpi_struct, NDPI_LOG_DEBUG, "Crossfire: found udp packet.\n");
+ ndpi_int_crossfire_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ } else if (packet->tcp != 0) {
+
+ if (packet->payload_packet_len > 4 && memcmp(packet->payload, "GET /", 5) == 0) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->parsed_lines == 8
+ && (packet->line[0].ptr != NULL && packet->line[0].len >= 30
+ && (memcmp(&packet->payload[5], "notice/login_big", 16) == 0
+ || memcmp(&packet->payload[5], "notice/login_small", 18) == 0))
+ && memcmp(&packet->payload[packet->line[0].len - 19], "/index.asp HTTP/1.", 18) == 0
+ && (packet->host_line.ptr != NULL && packet->host_line.len >= 13
+ && (memcmp(packet->host_line.ptr, "crossfire", 9) == 0
+ || memcmp(packet->host_line.ptr, "www.crossfire", 13) == 0))
+ ) {
+ NDPI_LOG(NDPI_PROTOCOL_CROSSFIRE, ndpi_struct, NDPI_LOG_DEBUG, "Crossfire: found HTTP request.\n");
+ ndpi_int_crossfire_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_CROSSFIRE, ndpi_struct, NDPI_LOG_DEBUG, "exclude crossfire.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_CROSSFIRE);
+}
+
+
+
+#endif
diff --git a/src/lib/protocols/dcerpc.c b/src/lib/protocols/dcerpc.c
new file mode 100644
index 000000000..5879aec6d
--- /dev/null
+++ b/src/lib/protocols/dcerpc.c
@@ -0,0 +1,54 @@
+/*
+ * dcerpc.c
+ *
+ * Copyright (C) 2011-13 by ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_DCERPC
+
+static void ndpi_int_dcerpc_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_DCERPC, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_dcerpc(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+ if((packet->tcp != NULL)
+ && (packet->payload_packet_len > 64)
+ && ((ntohs(packet->tcp->source) == 135) || (ntohs(packet->tcp->dest) == 135))
+ && (packet->payload[0] == 0x05) /* version 5 */
+ && (packet->payload[2] < 16) /* Packet type */
+ ) {
+ NDPI_LOG(NDPI_PROTOCOL_DCERPC, ndpi_struct, NDPI_LOG_DEBUG, "DCERPC match\n");
+ ndpi_int_dcerpc_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DCERPC);
+}
+
+#endif
diff --git a/src/lib/protocols/dhcp.c b/src/lib/protocols/dhcp.c
new file mode 100644
index 000000000..b623a6a15
--- /dev/null
+++ b/src/lib/protocols/dhcp.c
@@ -0,0 +1,60 @@
+/*
+ * dhcp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_DHCP
+
+static void ndpi_int_dhcp_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_DHCP, NDPI_REAL_PROTOCOL);
+}
+
+
+void ndpi_search_dhcp_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ /* this detection also works for asymmetric dhcp traffic */
+
+ /*check standard DHCP 0.0.0.0:68 -> 255.255.255.255:67 */
+ if (packet->payload_packet_len >= 244 && (packet->udp->source == htons(67)
+ || packet->udp->source == htons(68))
+ && (packet->udp->dest == htons(67) || packet->udp->dest == htons(68))
+ && get_u_int32_t(packet->payload, 236) == htonl(0x63825363)
+ && get_u_int16_t(packet->payload, 240) == htons(0x3501)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_DHCP, ndpi_struct, NDPI_LOG_DEBUG, "DHCP request\n");
+
+ ndpi_int_dhcp_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DHCP);
+}
+#endif
diff --git a/src/lib/protocols/dhcpv6.c b/src/lib/protocols/dhcpv6.c
new file mode 100644
index 000000000..b0c23c9c9
--- /dev/null
+++ b/src/lib/protocols/dhcpv6.c
@@ -0,0 +1,60 @@
+/*
+ * dhcpv6.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+/* include files */
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_DHCPV6
+
+static void ndpi_int_dhcpv6_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_DHCPV6, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_dhcpv6_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len >= 4 &&
+ (packet->udp->source == htons(546) || packet->udp->source == htons(547)) &&
+ (packet->udp->dest == htons(546) || packet->udp->dest == htons(547)) &&
+ packet->payload[0] >= 1 && packet->payload[0] <= 13) {
+
+ NDPI_LOG(NDPI_PROTOCOL_DHCPV6, ndpi_struct, NDPI_LOG_DEBUG, "DHCPv6 detected.\n");
+ ndpi_int_dhcpv6_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_DHCPV6, ndpi_struct, NDPI_LOG_DEBUG, "DHCPv6 excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DHCPV6);
+}
+
+#endif
diff --git a/src/lib/protocols/directconnect.c b/src/lib/protocols/directconnect.c
new file mode 100644
index 000000000..624f57e58
--- /dev/null
+++ b/src/lib/protocols/directconnect.c
@@ -0,0 +1,474 @@
+/*
+ * directconnect.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_DIRECTCONNECT
+
+//#define NDPI_DEBUG_DIRECTCONNECT
+//#define NDPI_DIRECTCONNECT_PORT_DEBUG
+//#define NDPI_DEBUG_DIRECTCONNECT_CONN
+
+
+#define DIRECT_CONNECT_TYPE_HUB 0
+#define DIRECT_CONNECT_TYPE_PEER 1
+#define DIRECT_CONNECT_ADC_PEER 2
+
+static u_int32_t skip_unknown_headers(const u_int8_t * payload, u_int32_t payload_len, u_int32_t pos)
+{
+ u_int32_t i = pos;
+ while (i < payload_len && payload[i] != 0x0a)
+ i++;
+
+ i++;
+ return i;
+
+}
+
+static u_int16_t parse_binf_message(struct ndpi_detection_module_struct
+ *ndpi_struct, const u_int8_t * payload, int payload_len)
+{
+ u_int32_t i = 4;
+ u_int16_t bytes_read = 0;
+ u_int16_t ssl_port = 0;
+ while (i < payload_len) {
+ i = skip_unknown_headers(payload, payload_len, i);
+ if ((i + 30) < payload_len) {
+ if (memcmp(&payload[i], "DCTM", 4) == 0) {
+ if (memcmp(&payload[i + 15], "ADCS", 4) == 0) {
+ ssl_port = ntohs_ndpi_bytestream_to_number(&payload[i + 25], 5, &bytes_read);
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "directconnect ssl port parsed %d", ssl_port);
+
+ }
+ }
+ } else {
+ break;
+ }
+
+ }
+ return ssl_port;
+}
+
+static void ndpi_int_directconnect_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ const u_int8_t connection_type)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_DIRECTCONNECT, NDPI_REAL_PROTOCOL);
+
+ if (src != NULL) {
+ src->directconnect_last_safe_access_time = packet->tick_timestamp;
+ if (connection_type == DIRECT_CONNECT_TYPE_PEER) {
+ if (packet->tcp != NULL
+ && flow->setup_packet_direction != packet->packet_direction && src->detected_directconnect_port == 0) {
+ src->detected_directconnect_port = packet->tcp->source;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "directconnect tcp PORT %u for src\n", ntohs(src->detected_directconnect_port));
+ }
+ if (packet->udp != NULL && src->detected_directconnect_udp_port == 0) {
+ src->detected_directconnect_udp_port = packet->udp->source;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "directconnect udp PORT %u for src\n", ntohs(src->detected_directconnect_port));
+
+ }
+ }
+
+ }
+ if (dst != NULL) {
+ dst->directconnect_last_safe_access_time = packet->tick_timestamp;
+ if (connection_type == DIRECT_CONNECT_TYPE_PEER) {
+ if (packet->tcp != NULL
+ && flow->setup_packet_direction == packet->packet_direction && dst->detected_directconnect_port == 0) {
+ /* DST PORT MARKING CAN LEAD TO PORT MISSDETECTIONS
+ * seen at large customer http servers, where someone has send faked DC tcp packets
+ * to the server
+ */
+
+ /*
+ dst->detected_directconnect_port = packet->tcp->dest;
+ NDPI_LOG (NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "directconnect tcp PORT %u for dst\n",
+ ntohs (dst->detected_directconnect_port));
+ */
+ }
+ }
+ }
+}
+
+static void ndpi_search_directconnect_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ if (flow->detected_protocol_stack[0] == NDPI_PROTOCOL_DIRECTCONNECT) {
+ if (packet->payload_packet_len >= 40 && memcmp(&packet->payload[0], "BINF", 4) == 0) {
+ u_int16_t ssl_port = 0;
+ ssl_port = parse_binf_message(ndpi_struct, &packet->payload[4], packet->payload_packet_len - 4);
+ if (dst != NULL && ssl_port) {
+ dst->detected_directconnect_ssl_port = ssl_port;
+ }
+ if (src != NULL && ssl_port) {
+ src->detected_directconnect_ssl_port = ssl_port;
+ }
+
+
+ }
+ if ((packet->payload_packet_len >= 38 && packet->payload_packet_len <= 42)
+ && memcmp(&packet->payload[0], "DCTM", 4) == 0 && memcmp(&packet->payload[15], "ADCS", 4) == 0) {
+ u_int16_t bytes_read = 0;
+ if (dst != NULL) {
+ dst->detected_directconnect_ssl_port =
+ ntohs_ndpi_bytestream_to_number(&packet->payload[25], 5, &bytes_read);
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "directconnect ssl port parsed %d", ntohs(dst->detected_directconnect_ssl_port));
+ }
+ if (src != NULL) {
+ src->detected_directconnect_ssl_port =
+ ntohs_ndpi_bytestream_to_number(&packet->payload[25], 5, &bytes_read);
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "directconnect ssl port parsed %d", ntohs(src->detected_directconnect_ssl_port));
+ }
+
+
+ }
+ return;
+
+ }
+ if (src != NULL) {
+ if (src->detected_directconnect_port == packet->tcp->source) {
+ if ((u_int32_t)
+ (packet->tick_timestamp -
+ src->directconnect_last_safe_access_time) < ndpi_struct->directconnect_connection_ip_tick_timeout) {
+ ndpi_int_change_protocol(ndpi_struct, flow, NDPI_PROTOCOL_DIRECTCONNECT, NDPI_REAL_PROTOCOL);
+ src->directconnect_last_safe_access_time = packet->tick_timestamp;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "marking using dc port\n %d", ntohs(src->detected_directconnect_port));
+ return;
+ } else {
+ src->detected_directconnect_port = 0;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "resetting src port due to timeout");
+ return;
+ }
+ }
+ if (src->detected_directconnect_ssl_port == packet->tcp->dest) {
+ if ((u_int32_t)
+ (packet->tick_timestamp -
+ src->directconnect_last_safe_access_time) < ndpi_struct->directconnect_connection_ip_tick_timeout) {
+ ndpi_int_change_protocol(ndpi_struct, flow, NDPI_PROTOCOL_DIRECTCONNECT, NDPI_REAL_PROTOCOL);
+ src->directconnect_last_safe_access_time = packet->tick_timestamp;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "marking using dc port\n %d", ntohs(src->detected_directconnect_ssl_port));
+ return;
+ } else {
+ src->detected_directconnect_ssl_port = 0;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "resetting src port due to timeout");
+ return;
+ }
+ }
+
+ }
+
+ if (dst != NULL) {
+ if (dst->detected_directconnect_port == packet->tcp->dest) {
+ if ((u_int32_t)
+ (packet->tick_timestamp -
+ dst->directconnect_last_safe_access_time) < ndpi_struct->directconnect_connection_ip_tick_timeout) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_DIRECTCONNECT, NDPI_REAL_PROTOCOL);
+ dst->directconnect_last_safe_access_time = packet->tick_timestamp;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "marking using dc port\n %d", ntohs(dst->detected_directconnect_port));
+ return;
+ } else {
+ dst->detected_directconnect_port = 0;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "resetting dst port due to timeout");
+ return;
+ }
+ }
+ if (dst->detected_directconnect_ssl_port == packet->tcp->dest) {
+ if ((u_int32_t)
+ (packet->tick_timestamp -
+ dst->directconnect_last_safe_access_time) < ndpi_struct->directconnect_connection_ip_tick_timeout) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_DIRECTCONNECT, NDPI_REAL_PROTOCOL);
+ dst->directconnect_last_safe_access_time = packet->tick_timestamp;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "marking using dc port\n %d", ntohs(dst->detected_directconnect_ssl_port));
+
+ return;
+ } else {
+ dst->detected_directconnect_ssl_port = 0;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "resetting dst port due to timeout");
+ return;
+ }
+ }
+
+ }
+
+ if (flow->directconnect_stage == 0) {
+
+ if (packet->payload_packet_len > 6) {
+ if (packet->payload[0] == '$'
+ && packet->payload[packet->payload_packet_len - 1] == '|'
+ && (memcmp(&packet->payload[1], "Lock ", 5) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "maybe first dc connect to hub detected\n");
+ flow->directconnect_stage = 1;
+ return;
+ }
+ if (packet->payload_packet_len > 7
+ && packet->payload[0] == '$'
+ && packet->payload[packet->payload_packet_len - 1] == '|'
+ && (memcmp(&packet->payload[1], "MyNick ", 7) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "maybe first dc connect between peers detected\n");
+ flow->directconnect_stage = 2;
+ return;
+ }
+
+ }
+ if (packet->payload_packet_len >= 11) {
+ /* did not see this pattern in any trace */
+ if (memcmp(&packet->payload[0], "HSUP ADBAS0", 11) == 0
+ || memcmp(&packet->payload[0], "HSUP ADBASE", 11) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "found directconnect HSUP ADBAS0 E\n");
+ ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_HUB);
+ return;
+ /* did not see this pattern in any trace */
+ } else if (memcmp(&packet->payload[0], "CSUP ADBAS0", 11) == 0 ||
+ memcmp(&packet->payload[0], "CSUP ADBASE", 11) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "found directconnect CSUP ADBAS0 E\n");
+ ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_ADC_PEER);
+ return;
+
+ }
+
+ }
+
+ } else if (flow->directconnect_stage == 1) {
+ if (packet->payload_packet_len >= 11) {
+ /* did not see this pattern in any trace */
+ if (memcmp(&packet->payload[0], "HSUP ADBAS0", 11) == 0
+ || memcmp(&packet->payload[0], "HSUP ADBASE", 11) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "found directconnect HSUP ADBAS E in second packet\n");
+ ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_HUB);
+
+ return;
+ /* did not see this pattern in any trace */
+ } else if (memcmp(&packet->payload[0], "CSUP ADBAS0", 11) == 0 ||
+ memcmp(&packet->payload[0], "CSUP ADBASE", 11) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "found directconnect HSUP ADBAS0 E in second packet\n");
+ ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_ADC_PEER);
+
+
+ return;
+
+ }
+ }
+ /* get client hello answer or server message */
+ if (packet->payload_packet_len > 6) {
+ if ((packet->payload[0] == '$' || packet->payload[0] == '<')
+ && packet->payload[packet->payload_packet_len - 1] == '|') {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct, NDPI_LOG_DEBUG, "second dc detected\n");
+ ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_HUB);
+
+ return;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct, NDPI_LOG_DEBUG, "second dc not detected\n");
+ }
+
+ }
+ } else if (flow->directconnect_stage == 2) {
+ /* get client hello answer or server message */
+ if (packet->payload_packet_len > 6) {
+ if (packet->payload[0] == '$' && packet->payload[packet->payload_packet_len - 1] == '|') {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "second dc between peers detected\n");
+
+
+ ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_PEER);
+
+ return;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "second dc between peers not detected\n");
+ }
+ }
+
+ }
+
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DIRECTCONNECT);
+
+}
+
+static void ndpi_search_directconnect_udp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+ int pos, count = 0;
+
+
+ if (dst != NULL && dst->detected_directconnect_udp_port == packet->udp->dest) {
+ if ((u_int32_t)
+ (packet->tick_timestamp -
+ dst->directconnect_last_safe_access_time) < ndpi_struct->directconnect_connection_ip_tick_timeout) {
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_DIRECTCONNECT, NDPI_REAL_PROTOCOL);
+ dst->directconnect_last_safe_access_time = packet->tick_timestamp;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "marking using dc udp port\n %d", ntohs(dst->detected_directconnect_udp_port));
+ return;
+ } else {
+ dst->detected_directconnect_udp_port = 0;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "resetting dst udp port due to timeout");
+ return;
+ }
+ }
+
+ if (packet->payload_packet_len > 58) {
+ if (src != NULL
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, NDPI_PROTOCOL_DIRECTCONNECT)) {
+ if (packet->payload[0] == '$'
+ && packet->payload[packet->payload_packet_len - 1] == '|'
+ && memcmp(&packet->payload[1], "SR ", 3) == 0) {
+ pos = packet->payload_packet_len - 2;
+ if (packet->payload[pos] == ')') {
+ while (pos > 0 && packet->payload[pos] != '(' && count < 21) {
+ pos--;
+ count++;
+ }
+ if (packet->payload[pos] == '(') {
+ pos = pos - 44;
+ if (pos > 2 && memcmp(&packet->payload[pos], "TTH:", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct, NDPI_LOG_DEBUG, "dc udp detected\n");
+ ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_PEER);
+ return;
+ }
+ }
+ }
+ flow->directconnect_stage++;
+
+ if (flow->directconnect_stage < 3) {
+
+
+ return;
+ }
+
+ }
+
+ }
+ if (dst != NULL
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, NDPI_PROTOCOL_DIRECTCONNECT)) {
+ if (packet->payload[0] == '$'
+ && packet->payload[packet->payload_packet_len - 1] == '|'
+ && memcmp(&packet->payload[1], "SR ", 3) == 0) {
+ pos = packet->payload_packet_len - 2;
+ if (packet->payload[pos] == ')') {
+ while (pos > 0 && packet->payload[pos] != '(' && count < 21) {
+ pos--;
+ count++;
+ }
+ if (packet->payload[pos] == '(') {
+ pos = pos - 44;
+ if (pos > 2 && memcmp(&packet->payload[pos], "TTH:", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct, NDPI_LOG_DEBUG, "dc udp detected\n");
+ ndpi_int_directconnect_add_connection(ndpi_struct, flow, DIRECT_CONNECT_TYPE_PEER);
+ return;
+ }
+ }
+ }
+ flow->directconnect_stage++;
+ if (flow->directconnect_stage < 3)
+ return;
+
+ }
+ }
+
+ }
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct, NDPI_LOG_DEBUG,
+ "excluded at stage %d \n", flow->directconnect_stage);
+
+
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DIRECTCONNECT);
+
+
+}
+
+void ndpi_search_directconnect(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_DIRECTCONNECT) {
+ if (src != NULL && ((u_int32_t)
+ (packet->tick_timestamp -
+ src->directconnect_last_safe_access_time) <
+ ndpi_struct->directconnect_connection_ip_tick_timeout)) {
+ src->directconnect_last_safe_access_time = packet->tick_timestamp;
+
+ } else if (dst != NULL && ((u_int32_t)
+ (packet->tick_timestamp -
+ dst->directconnect_last_safe_access_time) <
+ ndpi_struct->directconnect_connection_ip_tick_timeout)) {
+ dst->directconnect_last_safe_access_time = packet->tick_timestamp;
+ } else {
+ packet->detected_protocol_stack[0] = NDPI_PROTOCOL_UNKNOWN;
+ NDPI_LOG(NDPI_PROTOCOL_DIRECTCONNECT, ndpi_struct,
+ NDPI_LOG_DEBUG, "directconnect: skipping as unknown due to timeout\n");
+ }
+ return;
+ }
+
+ if (packet->tcp != NULL) {
+ ndpi_search_directconnect_tcp(ndpi_struct, flow);
+ } else if (packet->udp != NULL) {
+ ndpi_search_directconnect_udp(ndpi_struct, flow);
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/directdownloadlink.c b/src/lib/protocols/directdownloadlink.c
new file mode 100644
index 000000000..5c8de52c0
--- /dev/null
+++ b/src/lib/protocols/directdownloadlink.c
@@ -0,0 +1,737 @@
+/*
+ * directdownloadlink.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-14svn - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK
+
+
+#ifdef NDPI_DEBUG_DIRECT_DOWNLOAD_LINK
+//#define NDPI_DEBUG_DIRECT_DOWNLOAD_LINK_NOTHING_FOUND
+//#define NDPI_DEBUG_DIRECT_DOWNLOAD_LINK_PACKET_TOO_SMALL
+#define NDPI_DEBUG_DIRECT_DOWNLOAD_LINK_IP
+#endif
+
+static void ndpi_int_direct_download_link_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, NDPI_CORRELATED_PROTOCOL);
+
+ flow->l4.tcp.ddlink_server_direction = packet->packet_direction;
+}
+
+
+
+/*
+ return 0 if nothing has been detected
+ return 1 if it is a megaupload packet
+*/
+u_int8_t search_ddl_domains(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ u_int16_t filename_start = 0;
+ u_int8_t i = 1;
+ u_int16_t host_line_len_without_port;
+
+ if (packet->payload_packet_len < 100) {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, ndpi_struct, NDPI_LOG_DEBUG, "DDL: Packet too small.\n");
+ goto end_ddl_nothing_found;
+ }
+
+
+
+ if (memcmp(packet->payload, "POST ", 5) == 0) {
+ filename_start = 5; // POST
+ NDPI_LOG(NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, ndpi_struct, NDPI_LOG_DEBUG, "DDL: POST FOUND\n");
+ } else if (memcmp(packet->payload, "GET ", 4) == 0) {
+ filename_start = 4; // GET
+ NDPI_LOG(NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, ndpi_struct, NDPI_LOG_DEBUG, "DDL: GET FOUND\n");
+ } else {
+ goto end_ddl_nothing_found;
+ }
+ // parse packet
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if (packet->host_line.ptr == NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, ndpi_struct, NDPI_LOG_DEBUG, "DDL: NO HOST FOUND\n");
+ goto end_ddl_nothing_found;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, ndpi_struct, NDPI_LOG_DEBUG, "DDL: Host: found\n");
+
+ if (packet->line[0].len < 9 + filename_start
+ || memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, ndpi_struct,
+ NDPI_LOG_DEBUG, "DDL: PACKET NOT HTTP CONFORM.\nXXX%.*sXXX\n",
+ 8, &packet->line[0].ptr[packet->line[0].len - 9]);
+ goto end_ddl_nothing_found;
+ }
+ // BEGIN OF AUTOMATED CODE GENERATION
+ // first see if we have ':port' at the end of the line
+ host_line_len_without_port = packet->host_line.len;
+ if (host_line_len_without_port >= i && packet->host_line.ptr[host_line_len_without_port - i] >= '0'
+ && packet->host_line.ptr[packet->host_line.len - i] <= '9') {
+ i = 2;
+ while (host_line_len_without_port >= i && packet->host_line.ptr[host_line_len_without_port - i] >= '0'
+ && packet->host_line.ptr[host_line_len_without_port - i] <= '9') {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, ndpi_struct, NDPI_LOG_DEBUG, "DDL: number found\n");
+ i++;
+ }
+ if (host_line_len_without_port >= i && packet->host_line.ptr[host_line_len_without_port - i] == ':') {
+ NDPI_LOG(NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, ndpi_struct, NDPI_LOG_DEBUG, "DDL: ':' found\n");
+ host_line_len_without_port = host_line_len_without_port - i;
+ }
+ }
+ // then start automated code generation
+
+ if (host_line_len_without_port >= 0 + 4
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 0 - 4], ".com", 4) == 0) {
+ if (host_line_len_without_port >= 4 + 1 && packet->host_line.ptr[host_line_len_without_port - 4 - 1] == 'd') {
+ if (host_line_len_without_port >= 5 + 6 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 6], "4share", 6) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 6 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 6 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 8 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 8], "fileclou", 8) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 8 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 8 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 5
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 5], "uploa", 5) == 0) {
+ if (host_line_len_without_port >= 10 + 6 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 10 - 6], "files-", 6) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 10 - 6 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 10 - 6 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 10 + 4 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 10 - 4], "mega", 4) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 10 - 4 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 10 - 4 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 10 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 10 - 5], "rapid", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 10 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 10 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 10 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 10 - 5], "turbo", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 10 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 10 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 4 + 1 && packet->host_line.ptr[host_line_len_without_port - 4 - 1] == 'o') {
+ if (host_line_len_without_port >= 5 + 6 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 6], "badong", 6) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 6 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 6 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 5], "fileh", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 4 + 1 && packet->host_line.ptr[host_line_len_without_port - 4 - 1] == 'g') {
+ if (host_line_len_without_port >= 5 + 2
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 2], "in", 2) == 0) {
+ if (host_line_len_without_port >= 7 + 4
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 7 - 4], "shar", 4) == 0) {
+ if (host_line_len_without_port >= 11 + 4 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 11 - 4], "best", 4) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 11 - 4 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 11 - 4 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 11 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 11 - 5], "quick", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 11 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 11 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 7 + 6 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 7 - 6], "upload", 6) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 7 - 6 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 7 - 6 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 5 + 7 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 7], "sharebi", 7) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 7 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 7 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 4 + 8 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 4 - 8], "bigfilez", 8) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 4 - 8 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 4 - 8 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 4 + 1 && packet->host_line.ptr[host_line_len_without_port - 4 - 1] == 'e') {
+ if (host_line_len_without_port >= 5 + 3
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 3], "fil", 3) == 0) {
+ if (host_line_len_without_port >= 8 + 2
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 8 - 2], "mo", 2) == 0) {
+ if (host_line_len_without_port >= 10 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 10 - 5], "china", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 10 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 10 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 8 + 2 + 1
+ && (packet->host_line.ptr[host_line_len_without_port - 8 - 2 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 8 - 2 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ }
+ if (host_line_len_without_port >= 8 + 3 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 8 - 3], "hot", 3) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 8 - 3 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 8 - 3 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 8 + 6 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 8 - 6], "keepmy", 6) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 8 - 6 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 8 - 6 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 8 + 1
+ && packet->host_line.ptr[host_line_len_without_port - 8 - 1] == 'e') {
+ if (host_line_len_without_port >= 9 + 3 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 9 - 3], "sav", 3) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 9 - 3 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 9 - 3 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 9 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 9 - 5], "sendm", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 9 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 9 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 8 + 8 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 8 - 8], "sharebig", 8) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 8 - 8 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 8 - 8 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 8 + 3 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 8 - 3], "up-", 3) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 8 - 3 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 8 - 3 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 5 + 1 && packet->host_line.ptr[host_line_len_without_port - 5 - 1] == 'r') {
+ if (host_line_len_without_port >= 6 + 3
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 6 - 3], "sha", 3) == 0) {
+ if (host_line_len_without_port >= 9 + 1
+ && packet->host_line.ptr[host_line_len_without_port - 9 - 1] == '-') {
+ if (host_line_len_without_port >= 10 + 4 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 10 - 4], "easy",
+ 4) == 0 && (packet->host_line.ptr[host_line_len_without_port - 10 - 4 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 10 - 4 - 1] ==
+ '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 10 + 4 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 10 - 4], "fast",
+ 4) == 0 && (packet->host_line.ptr[host_line_len_without_port - 10 - 4 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 10 - 4 - 1] ==
+ '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 10 + 4 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 10 - 4], "live",
+ 4) == 0 && (packet->host_line.ptr[host_line_len_without_port - 10 - 4 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 10 - 4 - 1] ==
+ '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 9 + 4 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 9 - 4], "ftp2", 4) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 9 - 4 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 9 - 4 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 9 + 4 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 9 - 4], "gige", 4) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 9 - 4 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 9 - 4 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 9 + 4 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 9 - 4], "mega", 4) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 9 - 4 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 9 - 4 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 9 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 9 - 5], "rapid", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 9 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 9 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 6 + 7 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 6 - 7], "mediafi", 7) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 6 - 7 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 6 - 7 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 5 + 7 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 7], "gigasiz", 7) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 7 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 7 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 8 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 8], "sendspac", 8) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 8 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 8 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 7 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 7], "sharebe", 7) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 7 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 7 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 11 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 11], "sharebigfli", 11) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 11 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 11 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 8 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 8], "fileserv", 8) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 8 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 8 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 4 + 1 && packet->host_line.ptr[host_line_len_without_port - 4 - 1] == 's') {
+ if (host_line_len_without_port >= 5 + 1 && packet->host_line.ptr[host_line_len_without_port - 5 - 1] == 'e') {
+ if (host_line_len_without_port >= 6 + 10 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 6 - 10], "depositfil",
+ 10) == 0 && (packet->host_line.ptr[host_line_len_without_port - 6 - 10 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 6 - 10 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 6 + 8 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 6 - 8], "megashar", 8) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 6 - 8 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 6 - 8 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 5 + 10 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 10], "fileupyour", 10) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 10 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 10 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 4 + 11 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 4 - 11], "filefactory", 11) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 4 - 11 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 4 - 11 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 4 + 1 && packet->host_line.ptr[host_line_len_without_port - 4 - 1] == 't') {
+ if (host_line_len_without_port >= 5 + 8 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 8], "filefron", 8) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 8 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 8 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 10 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 10], "uploadingi", 10) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 10 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 10 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 11 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 11], "yourfilehos", 11) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 11 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 11 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 4 + 1 && packet->host_line.ptr[host_line_len_without_port - 4 - 1] == 'r') {
+ if (host_line_len_without_port >= 5 + 8 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 8], "mytempdi", 8) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 8 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 8 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 10 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 10], "uploadpowe", 10) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 10 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 10 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 4 + 9 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 4 - 9], "mega.1280", 9) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 4 - 9 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 4 - 9 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 4 + 9 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 4 - 9], "filesonic", 9) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 4 - 9 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 4 - 9 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 0 + 4
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 0 - 4], ".net", 4) == 0) {
+ if (host_line_len_without_port >= 4 + 7 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 4 - 7], "badongo", 7) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 4 - 7 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 4 - 7 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 4 + 1 && packet->host_line.ptr[host_line_len_without_port - 4 - 1] == 'd') {
+ if (host_line_len_without_port >= 5 + 3
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 3], "loa", 3) == 0) {
+ if (host_line_len_without_port >= 8 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 8 - 5], "fast-", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 8 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 8 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 8 + 2
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 8 - 2], "up", 2) == 0) {
+ if (host_line_len_without_port >= 10 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 10 - 5], "file-", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 10 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 10 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 10 + 6 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 10 - 6], "simple",
+ 6) == 0 && (packet->host_line.ptr[host_line_len_without_port - 10 - 6 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 10 - 6 - 1] ==
+ '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 10 + 3 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 10 - 3], "wii", 3) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 10 - 3 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 10 - 3 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 5 + 7 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 7], "filesen", 7) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 7 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 7 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 4 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 4 - 5], "filer", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 4 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 4 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 4 + 9 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 4 - 9], "livedepot", 9) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 4 - 9 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 4 - 9 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 4 + 1 && packet->host_line.ptr[host_line_len_without_port - 4 - 1] == 'e') {
+ if (host_line_len_without_port >= 5 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 5], "mofil", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 17 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 17], "odsiebie.najlepsz",
+ 17) == 0 && (packet->host_line.ptr[host_line_len_without_port - 5 - 17 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 17 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 5 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 5 - 5], "zshar", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 5 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 5 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 0 + 1 && packet->host_line.ptr[host_line_len_without_port - 0 - 1] == 'u') {
+ if (host_line_len_without_port >= 1 + 6 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 1 - 6], "data.h", 6) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 1 - 6 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 1 - 6 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 1 + 2
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 1 - 2], ".r", 2) == 0) {
+ if (host_line_len_without_port >= 3 + 10 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 3 - 10], "filearchiv", 10) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 3 - 10 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 3 - 10 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 3 + 8 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 3 - 8], "filepost", 8) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 3 - 8 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 3 - 8 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 3 + 7 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 3 - 7], "ifolder", 7) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 3 - 7 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 3 - 7 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 0 + 11 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 0 - 11], "filehost.tv", 11) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 0 - 11 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 0 - 11 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 0 + 3
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 0 - 3], ".to", 3) == 0) {
+ if (host_line_len_without_port >= 3 + 1 && packet->host_line.ptr[host_line_len_without_port - 3 - 1] == 'e') {
+ if (host_line_len_without_port >= 4 + 7 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 4 - 7], "filesaf", 7) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 4 - 7 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 4 - 7 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 4 + 8 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 4 - 8], "sharebas", 8) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 4 - 8 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 4 - 8 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 3 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 3 - 5], "files", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 3 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 3 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 3 + 1 && packet->host_line.ptr[host_line_len_without_port - 3 - 1] == 'd') {
+ if (host_line_len_without_port >= 4 + 3
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 4 - 3], "loa", 3) == 0) {
+ if (host_line_len_without_port >= 7 + 7 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 7 - 7], "file-up", 7) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 7 - 7 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 7 - 7 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 4 + 3 + 1
+ && (packet->host_line.ptr[host_line_len_without_port - 4 - 3 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 4 - 3 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ }
+ if (host_line_len_without_port >= 4 + 7 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 4 - 7], "uploade", 7) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 4 - 7 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 4 - 7 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 0 + 1 && packet->host_line.ptr[host_line_len_without_port - 0 - 1] == 'z') {
+ if (host_line_len_without_port >= 1 + 14 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 1 - 14], "leteckaposta.c", 14) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 1 - 14 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 1 - 14 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 1 + 12 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 1 - 12], "yourfiles.bi", 12) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 1 - 12 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 1 - 12 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 0 + 1 && packet->host_line.ptr[host_line_len_without_port - 0 - 1] == 'n') {
+ if (host_line_len_without_port >= 1 + 9 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 1 - 9], "netload.i", 9) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 1 - 9 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 1 - 9 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 1 + 2
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 1 - 2], ".v", 2) == 0) {
+ if (host_line_len_without_port >= 3 + 7 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 3 - 7], "4shared", 7) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 3 - 7 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 3 - 7 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 3 + 9 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 3 - 9], "megashare", 9) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 3 - 9 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 3 - 9 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 0 + 3
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 0 - 3], ".de", 3) == 0) {
+ if (host_line_len_without_port >= 3 + 5
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 3 - 5], "share", 5) == 0) {
+ if (host_line_len_without_port >= 8 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 8 - 5], "rapid", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 8 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 8 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ if (host_line_len_without_port >= 8 + 5 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 8 - 5], "ultra", 5) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 8 - 5 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 8 - 5 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 3 + 15 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 3 - 15], "uploadyourfiles", 15) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 3 - 15 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 3 - 15 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ goto end_ddl_nothing_found;
+ }
+ if (host_line_len_without_port >= 0 + 14 + 1
+ && memcmp((void *) &packet->host_line.ptr[host_line_len_without_port - 0 - 14], "speedshare.org", 14) == 0
+ && (packet->host_line.ptr[host_line_len_without_port - 0 - 14 - 1] == ' '
+ || packet->host_line.ptr[host_line_len_without_port - 0 - 14 - 1] == '.')) {
+ goto end_ddl_found;
+ }
+ // END OF AUTOMATED CODE GENERATION
+
+ /* This is the hard way. We do this in order to find the download of services when other
+ domains are involved. This is not significant if ddl is blocked. --> then the link can not be started because
+ the ads are not viewed. But when ddl is only limited then the download is the important part.
+ */
+
+ end_ddl_nothing_found:
+ NDPI_LOG(NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, ndpi_struct, NDPI_LOG_DEBUG,
+ "Nothing Found\n");
+ return 0;
+
+ end_ddl_found:
+ NDPI_LOG(NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK, ndpi_struct, NDPI_LOG_DEBUG, "DDL: DIRECT DOWNLOAD LINK FOUND\n");
+ ndpi_int_direct_download_link_add_connection(ndpi_struct, flow);
+ return 1;
+}
+
+
+void ndpi_search_direct_download_link_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+#if 0
+ if (ndpi_struct->direct_download_link_counter_callback != NULL) {
+ if (packet->detected_protocol == NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK) {
+ /* skip packets not requests from the client to the server */
+ if (packet->packet_direction == flow->l4.tcp.ddlink_server_direction) {
+ search_ddl_domains(ndpi_struct, flow); // do the detection again in order to get the URL in keep alive streams
+ } else {
+ // just count the packet
+ ndpi_struct->direct_download_link_counter_callback(flow->hash_id_number, packet->l3_packet_len);
+ }
+ }
+ return;
+ }
+#endif
+ // do not detect again if it is already ddl
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK) {
+ if (search_ddl_domains(ndpi_struct, flow) != 0) {
+ return;
+ }
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DIRECT_DOWNLOAD_LINK);
+ }
+
+}
+#endif
diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c
new file mode 100644
index 000000000..071039340
--- /dev/null
+++ b/src/lib/protocols/dns.c
@@ -0,0 +1,300 @@
+/*
+ * dns.c
+ *
+ * Copyright (C) 2012-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_DNS
+
+static u_int getNameLength(u_int i, const u_int8_t *payload, u_int payloadLen) {
+ if(payload[i] == 0x00)
+ return(1);
+ else if(payload[i] == 0xC0)
+ return(2);
+ else {
+ u_int8_t len = payload[i];
+ u_int8_t off = len + 1;
+
+ if(off == 0) /* Bad packet */
+ return(0);
+ else
+ return(off + getNameLength(i+off, payload, payloadLen));
+ }
+}
+
+/* *********************************************** */
+
+static char* ndpi_intoa_v4(unsigned int addr, char* buf, u_short bufLen) {
+ char *cp, *retStr;
+ uint byte;
+ int n;
+
+ cp = &buf[bufLen];
+ *--cp = '\0';
+
+ n = 4;
+ do {
+ byte = addr & 0xff;
+ *--cp = byte % 10 + '0';
+ byte /= 10;
+ if(byte > 0) {
+ *--cp = byte % 10 + '0';
+ byte /= 10;
+ if(byte > 0)
+ *--cp = byte + '0';
+ }
+ *--cp = '.';
+ addr >>= 8;
+ } while (--n > 0);
+
+ /* Convert the string to lowercase */
+ retStr = (char*)(cp+1);
+
+ return(retStr);
+}
+
+/* *********************************************** */
+
+static u_int16_t get16(int *i, const u_int8_t *payload) {
+ u_int16_t v = *(u_int16_t*)&payload[*i];
+
+ (*i) += 2;
+
+ return(ntohs(v));
+}
+
+/* *********************************************** */
+
+struct dns_packet_header {
+ u_int16_t transaction_id, flags, num_queries, answer_rrs, authority_rrs, additional_rrs;
+} __attribute__((packed));
+
+void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t dport = 0, sport = 0;
+
+#define NDPI_MAX_DNS_REQUESTS 16
+
+ NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "search DNS.\n");
+
+ if (packet->udp != NULL) {
+ sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest);
+ NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "calculated dport over UDP.\n");
+ } else if(packet->tcp != NULL) {
+ sport = ntohs(packet->tcp->source), dport = ntohs(packet->tcp->dest);
+ NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "calculated dport over tcp.\n");
+ }
+
+ if(((dport == 53) || (sport == 53) || (dport == 5355))
+ && (packet->payload_packet_len > sizeof(struct dns_packet_header))) {
+ int i = packet->tcp ? 2 : 0;
+ struct dns_packet_header header, *dns = (struct dns_packet_header*)&packet->payload[i];
+ u_int8_t is_query, ret_code, is_dns = 0;
+ u_int32_t a_record[NDPI_MAX_DNS_REQUESTS] = { 0 }, query_offset, num_a_records = 0;
+
+ header.flags = ntohs(dns->flags);
+ header.transaction_id = ntohs(dns->transaction_id);
+ header.num_queries = ntohs(dns->num_queries);
+ header.answer_rrs = ntohs(dns->answer_rrs);
+ header.authority_rrs = ntohs(dns->authority_rrs);
+ header.additional_rrs = ntohs(dns->additional_rrs);
+ is_query = (header.flags & 0x8000) ? 0 : 1;
+ ret_code = is_query ? 0 : (header.flags & 0x0F);
+ i += sizeof(struct dns_packet_header);
+ query_offset = i;
+
+ if(is_query) {
+ /* DNS Request */
+ if((header.num_queries > 0) && (header.num_queries <= NDPI_MAX_DNS_REQUESTS)
+ && (((header.flags & 0x2800) == 0x2800 /* Dynamic DNS Update */)
+ || ((header.answer_rrs == 0) && (header.authority_rrs == 0)))) {
+ /* This is a good query */
+ is_dns = 1;
+
+ if(header.num_queries > 0) {
+ while(i < packet->payload_packet_len) {
+ if(packet->payload[i] == '\0') {
+ i++;
+ flow->protos.dns.query_type = get16(&i, packet->payload);
+ break;
+ } else
+ i++;
+ }
+ }
+ }
+ } else {
+ /* DNS Reply */
+
+ flow->server_id = flow->dst;
+
+ if((header.num_queries <= NDPI_MAX_DNS_REQUESTS) /* Don't assume that num_queries must be zero */
+ && (((header.answer_rrs > 0) && (header.answer_rrs <= NDPI_MAX_DNS_REQUESTS))
+ || ((header.authority_rrs > 0) && (header.authority_rrs <= NDPI_MAX_DNS_REQUESTS))
+ || ((header.additional_rrs > 0) && (header.additional_rrs <= NDPI_MAX_DNS_REQUESTS)))
+ ) {
+ /* This is a good reply */
+ is_dns = 1;
+
+ i++;
+
+ if(packet->payload[i] != '\0') {
+ while((i < packet->payload_packet_len)
+ && (packet->payload[i] != '\0')) {
+ i++;
+ }
+
+ i++;
+ }
+
+ i += 4;
+
+ if(header.answer_rrs > 0) {
+ u_int16_t rsp_type /*, rsp_class */;
+ u_int16_t num;
+
+ for(num = 0; num < header.answer_rrs; num++) {
+ u_int16_t data_len;
+
+ if((i+6) >= packet->payload_packet_len) {
+ break;
+ }
+
+ if((data_len = getNameLength(i, packet->payload, packet->payload_packet_len)) == 0) {
+ break;
+ } else
+ i += data_len;
+
+ rsp_type = get16(&i, packet->payload);
+ // rsp_class = get16(&i, packet->payload);
+
+ i += 4;
+ data_len = get16(&i, packet->payload);
+
+ if((data_len <= 1) || (data_len > (packet->payload_packet_len-i))) {
+ break;
+ }
+
+ flow->protos.dns.rsp_type = rsp_type;
+
+ if(rsp_type == 1 /* A */) {
+ if(data_len == 4) {
+ u_int32_t v = ntohl(*((u_int32_t*)&packet->payload[i]));
+
+ if(num_a_records < (NDPI_MAX_DNS_REQUESTS-1))
+ a_record[num_a_records++] = v;
+ else
+ break; /* One record is enough */
+ }
+ }
+
+ if(data_len == 0) {
+ break;
+ }
+
+ i += data_len;
+ } /* for */
+ }
+ }
+
+ if((header.num_queries <= NDPI_MAX_DNS_REQUESTS)
+ && ((header.answer_rrs == 0)
+ || (header.authority_rrs == 0)
+ || (header.additional_rrs == 0))
+ && (ret_code != 0 /* 0 == OK */)
+ ) {
+ /* This is a good reply */
+ is_dns = 1;
+ }
+ }
+
+ if(is_dns) {
+ int j = 0;
+
+ flow->protos.dns.num_queries = (u_int8_t)header.num_queries,
+ flow->protos.dns.num_answers = (u_int8_t)(header.answer_rrs+header.authority_rrs+header.additional_rrs),
+ flow->protos.dns.ret_code = ret_code;
+
+ i = query_offset+1;
+
+ while((i < packet->payload_packet_len)
+ && (j < (sizeof(flow->host_server_name)-1))
+ && (packet->payload[i] != '\0')) {
+ flow->host_server_name[j] = tolower(packet->payload[i]);
+ if(flow->host_server_name[j] < ' ')
+ flow->host_server_name[j] = '.';
+ j++, i++;
+ }
+
+ if(a_record != 0) {
+ char a_buf[32];
+ int i;
+
+ for(i=0; i<num_a_records; i++) {
+ j += snprintf((char*)&flow->host_server_name[j], sizeof(flow->host_server_name)-1-j, "%s%s",
+ (i == 0) ? "@" : ";",
+ ndpi_intoa_v4(a_record[i], a_buf, sizeof(a_buf)));
+ }
+ }
+
+ flow->host_server_name[j] = '\0';
+
+ if(j > 0) {
+#ifdef DEBUG
+ printf("==> %s\n", flow->host_server_name);
+#endif
+
+ if(ndpi_struct->match_dns_host_names)
+ ndpi_match_string_subprotocol(ndpi_struct, flow,
+ (char *)flow->host_server_name,
+ strlen((const char*)flow->host_server_name));
+ }
+
+ i++;
+
+ memcpy(&flow->protos.dns.query_type, &packet->payload[i], 2);
+ flow->protos.dns.query_type = ntohs(flow->protos.dns.query_type), i += 2;
+
+ memcpy(&flow->protos.dns.query_class, &packet->payload[i], 2);
+ flow->protos.dns.query_class = ntohs(flow->protos.dns.query_class), i += 2;
+
+#ifdef DEBUG
+ printf("%s [type=%04X][class=%04X]\n", flow->host_server_name, flow->protos.dns.query_type, flow->protos.dns.query_class);
+#endif
+
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
+ /*
+ Do not set the protocol with DNS if ndpi_match_string_subprotocol() has
+ matched a subprotocol
+ */
+ NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "found DNS.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, (dport == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_REAL_PROTOCOL);
+ }
+ } else {
+ flow->protos.dns.bad_packet = 1;
+ NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "exclude DNS.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DNS);
+ }
+ }
+}
+#endif
diff --git a/src/lib/protocols/dofus.c b/src/lib/protocols/dofus.c
new file mode 100644
index 000000000..43d9c9f73
--- /dev/null
+++ b/src/lib/protocols/dofus.c
@@ -0,0 +1,149 @@
+/*
+ * dofus.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_DOFUS
+
+static void ndpi_dofus_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_DOFUS, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_dofus(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ /* Dofus v 1.x.x */
+ if (packet->payload_packet_len == 13 && get_u_int16_t(packet->payload, 1) == ntohs(0x0508)
+ && get_u_int16_t(packet->payload, 5) == ntohs(0x04a0)
+ && get_u_int16_t(packet->payload, packet->payload_packet_len - 2) == ntohs(0x0194)) {
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "found dofus.\n");
+ ndpi_dofus_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (flow->l4.tcp.dofus_stage == 0 && packet->payload_packet_len == 3 && memcmp(packet->payload, "HG", 2) == 0
+ && packet->payload[packet->payload_packet_len - 1] == 0) {
+ flow->l4.tcp.dofus_stage = 1;
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "maybe dofus.\n");
+ return;
+ }
+ if (flow->l4.tcp.dofus_stage == 0 && packet->payload_packet_len == 35 && memcmp(packet->payload, "HC", 2) == 0
+ && packet->payload[packet->payload_packet_len - 1] == 0) {
+ flow->l4.tcp.dofus_stage = 1;
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "maybe dofus.\n");
+ return;
+ }
+ if (flow->l4.tcp.dofus_stage == 0 && packet->payload_packet_len > 2 && packet->payload[0] == 'A'
+ && (packet->payload[1] == 'x' || packet->payload[1] == 'X')
+ && packet->payload[packet->payload_packet_len - 1] == 0) {
+ flow->l4.tcp.dofus_stage = 1;
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "maybe dofus.\n");
+ return;
+ }
+ if (flow->l4.tcp.dofus_stage == 0 && packet->payload_packet_len == 12 && memcmp(packet->payload, "Af", 2) == 0
+ && packet->payload[packet->payload_packet_len - 1] == 0) {
+ flow->l4.tcp.dofus_stage = 1;
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "maybe dofus.\n");
+ return;
+ }
+ if (flow->l4.tcp.dofus_stage == 0 && packet->payload_packet_len > 2 && memcmp(packet->payload, "Ad", 2)
+ && packet->payload[packet->payload_packet_len - 1] == 0) {
+ flow->l4.tcp.dofus_stage = 1;
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "maybe dofus.\n");
+ return;
+ }
+ if (packet->payload_packet_len == 11 && memcmp(packet->payload, "AT", 2) == 0 && packet->payload[10] == 0x00) {
+ if (flow->l4.tcp.dofus_stage == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "found dofus.\n");
+ ndpi_dofus_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ if (flow->l4.tcp.dofus_stage == 1 && packet->payload_packet_len == 5
+ && packet->payload[0] == 'A' && packet->payload[4] == 0x00 && (packet->payload[1] == 'T'
+ || packet->payload[1] == 'k')) {
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "found dofus asym.\n");
+ ndpi_dofus_add_connection(ndpi_struct, flow);
+ return;
+ }
+ /* end Dofus 1.x.x */
+
+
+ /* Dofus 2.0 */
+ if ((packet->payload_packet_len == 11 || packet->payload_packet_len == 13 || packet->payload_packet_len == 49)
+ && get_u_int32_t(packet->payload, 0) == ntohl(0x00050800)
+ && get_u_int16_t(packet->payload, 4) == ntohs(0x0005)
+ && get_u_int16_t(packet->payload, 8) == ntohs(0x0005)
+ && packet->payload[10] == 0x18) {
+ if (packet->payload_packet_len == 13
+ && get_u_int16_t(packet->payload, packet->payload_packet_len - 2) != ntohs(0x0194)) {
+ goto exclude;
+ }
+ if (packet->payload_packet_len == 49 && ntohs(get_u_int16_t(packet->payload, 15)) + 17 != packet->payload_packet_len) {
+ goto exclude;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "found dofus.\n");
+ ndpi_dofus_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len >= 41 && get_u_int16_t(packet->payload, 0) == ntohs(0x01b9) && packet->payload[2] == 0x26) {
+ u_int16_t len, len2;
+ len = ntohs(get_u_int16_t(packet->payload, 3));
+ if ((len + 5 + 2) > packet->payload_packet_len)
+ goto exclude;
+ len2 = ntohs(get_u_int16_t(packet->payload, 5 + len));
+ if (5 + len + 2 + len2 == packet->payload_packet_len) {
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "found dofus.\n");
+ ndpi_dofus_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ if (packet->payload_packet_len == 56
+ && memcmp(packet->payload, "\x00\x11\x35\x02\x03\x00\x93\x96\x01\x00", 10) == 0) {
+ u_int16_t len, len2;
+ len = ntohs(get_u_int16_t(packet->payload, 10));
+ if ((len + 12 + 2) > packet->payload_packet_len)
+ goto exclude;
+ len2 = ntohs(get_u_int16_t(packet->payload, 12 + len));
+ if ((12 + len + 2 + len2 + 1) > packet->payload_packet_len)
+ goto exclude;
+ if (12 + len + 2 + len2 + 1 == packet->payload_packet_len && packet->payload[12 + len + 2 + len2] == 0x01) {
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "found dofus.\n");
+ ndpi_dofus_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ exclude:
+ NDPI_LOG(NDPI_PROTOCOL_DOFUS, ndpi_struct, NDPI_LOG_DEBUG, "exclude dofus.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DOFUS);
+}
+
+#endif
diff --git a/src/lib/protocols/dropbox.c b/src/lib/protocols/dropbox.c
new file mode 100644
index 000000000..e4ef2e0ce
--- /dev/null
+++ b/src/lib/protocols/dropbox.c
@@ -0,0 +1,77 @@
+/*
+ * dropbox.c
+ *
+ * Copyright (C) 2011-13 by ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_DROPBOX
+static void ndpi_int_dropbox_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int8_t due_to_correlation)
+{
+ ndpi_int_add_connection(ndpi_struct, flow,
+ NDPI_PROTOCOL_DROPBOX,
+ due_to_correlation ? NDPI_CORRELATED_PROTOCOL : NDPI_REAL_PROTOCOL);
+}
+
+
+static void ndpi_check_dropbox(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // const u_int8_t *packet_payload = packet->payload;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ if(packet->udp != NULL) {
+ u_int16_t dropbox_port = htons(17500);
+
+ if((packet->udp->source == dropbox_port)
+ && (packet->udp->dest == dropbox_port)) {
+ if(payload_len > 2) {
+ if(strncmp((const char *)packet->payload, "{\"", 2) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_DROPBOX, ndpi_struct, NDPI_LOG_DEBUG, "Found dropbox.\n");
+ ndpi_int_dropbox_add_connection(ndpi_struct, flow, 0);
+ return;
+ }
+ }
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_DROPBOX, ndpi_struct, NDPI_LOG_DEBUG, "exclude dropbox.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_DROPBOX);
+}
+
+void ndpi_search_dropbox(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_DROPBOX, ndpi_struct, NDPI_LOG_DEBUG, "dropbox detection...\n");
+
+ /* skip marked packets */
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_DROPBOX) {
+ if (packet->tcp_retransmission == 0) {
+ ndpi_check_dropbox(ndpi_struct, flow);
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/edonkey.c b/src/lib/protocols/edonkey.c
new file mode 100644
index 000000000..d452c7348
--- /dev/null
+++ b/src/lib/protocols/edonkey.c
@@ -0,0 +1,211 @@
+/*
+ * edonkey.c
+ *
+ * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk>
+ *
+ * The signature is based on the Libprotoident library.
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_EDONKEY
+static void ndpi_int_edonkey_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_EDONKEY, NDPI_REAL_PROTOCOL);
+}
+
+static int ndpi_edonkey_payload_check(const u_int8_t *data, u_int32_t len) {
+
+ if ((len >= 4) && (data[0] == 0xe3) && (data[2] == 0x00) && (data[3] == 0x00))
+ return 1;
+
+ if ((len >= 4) && (data[0] == 0xc5) && (data[2] == 0x00) && (data[3] == 0x00))
+ return 1;
+
+ if ((len >= 2) && (data[0] == 0xe5) && (data[1] == 0x43))
+ return 1;
+
+ if ((len >= 4) && (data[0] == 0xe5) && (data[1] == 0x08) && (data[2] == 0x78) && (data[3] == 0xda))
+ return 1;
+
+ if ((len >= 4) && (data[0] == 0xe5) && (data[1] == 0x28) && (data[2] == 0x78) && (data[3] == 0xda))
+ return 1;
+
+ if ((len >= 2) && (data[0] == 0xc5) && (data[1] == 0x90))
+ return 1;
+
+ if ((len >= 2) && (data[0] == 0xc5) && (data[1] == 0x91))
+ return 1;
+
+ if ((len == 2) && (data[0] == 0xc5) && (data[1] == 0x92))
+ return 1;
+
+ if ((len == 2) && (data[0] == 0xc5) && (data[1] == 0x93))
+ return 1;
+
+ if ((len >= 38 && len <= 70) && (data[0] == 0xc5) && (data[1] == 0x94))
+ return 1;
+
+ if ((len >= 2) && (data[0] == 0xe3) && (data[1] == 0x9a))
+ return 1;
+
+ if ((len >= 2) && (data[0] == 0xe3) && (data[1] == 0x9b))
+ return 1;
+
+ if ((len == 6) && (data[0] == 0xe3) && (data[1] == 0x96))
+ return 1;
+
+ if ((len <= 34 && ((len - 2) % 4 == 0)) && (data[0] == 0xe3) && (data[1] == 0x97))
+ return 1;
+
+ if ((len >= 2) && (data[0] == 0xe3) && (data[1] == 0x92))
+ return 1;
+
+ if ((len >= 2) && (data[0] == 0xe3) && (data[1] == 0x94))
+ return 1;
+
+ if ((len >= 2) && (data[0] == 0xe3) && (data[1] == 0x98))
+ return 1;
+
+ if ((len >= 2) && (data[0] == 0xe3) && (data[1] == 0x99))
+ return 1;
+
+ if ((len == 6) && (data[0] == 0xe3) && (data[1] == 0xa2))
+ return 1;
+
+ if ((len >= 2) && (data[0] == 0xe3) && (data[1] == 0xa3))
+ return 1;
+
+ if ((len == 27) && (data[0] == 0xe4) && (data[1] == 0x00))
+ return 1;
+
+ if ((len == 529) && (data[0] == 0xe4) && (data[1] == 0x08))
+ return 1;
+
+ if ((len == 18) && (data[0] == 0xe4) && (data[1] == 0x01) && (data[2] == 0x00) && (data[3] == 0x00))
+ return 1;
+
+ if ((len == 523) && (data[0] == 0xe4) && (data[1] == 0x09))
+ return 1;
+
+ if ((len == 35) && (data[0] == 0xe4) && (data[1] == 0x21))
+ return 1;
+
+ if ((len == 19) && (data[0] == 0xe4) && (data[1] == 0x4b))
+ return 1;
+
+ if ((len >= 2) && (data[0] == 0xe4) && (data[1] == 0x11))
+ return 1;
+
+ if ((len == 22 || len == 38 || len == 28) && (data[0] == 0xe4) && (data[1] == 0x19))
+ return 1;
+
+ if ((len == 35) && (data[0] == 0xe4) && (data[1] == 0x20))
+ return 1;
+
+ if ((len == 27) && (data[0] == 0xe4) && (data[1] == 0x18))
+ return 1;
+
+ if ((len == 27) && (data[0] == 0xe4) && (data[1] == 0x10))
+ return 1;
+
+ if ((len == 6) && (data[0] == 0xe4) && (data[1] == 0x58))
+ return 1;
+
+ if ((len == 4) && (data[0] == 0xe4) && (data[1] == 0x50))
+ return 1;
+
+ if ((len == 36) && (data[0] == 0xe4) && (data[1] == 0x52))
+ return 1;
+
+ if ((len == 48) && (data[0] == 0xe4) && (data[1] == 0x40))
+ return 1;
+
+ if ((len == 225) && (data[0] == 0xe4) && (data[1] == 0x43))
+ return 1;
+
+ if ((len == 19) && (data[0] == 0xe4) && (data[1] == 0x48))
+ return 1;
+
+ if ((len == 119 || len == 69 || len == 294) && (data[0] == 0xe4) && (data[1] == 0x29))
+ return 1;
+
+ if ((len == 119 || len == 69 || len == 294 || len == 44 || len == 269) && (data[0] == 0xe4) && (data[1] == 0x28))
+ return 1;
+
+ return 0;
+}
+
+static void ndpi_check_edonkey(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Break after 20 packets. */
+ if (flow->packet_counter > 20) {
+ NDPI_LOG(NDPI_PROTOCOL_EDONKEY, ndpi_struct, NDPI_LOG_DEBUG, "Exclude EDONKEY.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_EDONKEY);
+ return;
+ }
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->edonkey_stage == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_EDONKEY, ndpi_struct, NDPI_LOG_DEBUG, "EDONKEY stage 0: \n");
+
+ if (ndpi_edonkey_payload_check(packet->payload, payload_len)) {
+ NDPI_LOG(NDPI_PROTOCOL_EDONKEY, ndpi_struct, NDPI_LOG_DEBUG, "Possible EDONKEY request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->edonkey_stage = packet->packet_direction + 1;
+ }
+
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_EDONKEY, ndpi_struct, NDPI_LOG_DEBUG, "EDONKEY stage %u: \n", flow->edonkey_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->edonkey_stage - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len == 0) || (ndpi_edonkey_payload_check(packet->payload, payload_len))) {
+ NDPI_LOG(NDPI_PROTOCOL_EDONKEY, ndpi_struct, NDPI_LOG_DEBUG, "Found EDONKEY.\n");
+ ndpi_int_edonkey_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_EDONKEY, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to EDONKEY, resetting the stage to 0...\n");
+ flow->edonkey_stage = 0;
+ }
+
+ }
+}
+
+void ndpi_search_edonkey(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_EDONKEY, ndpi_struct, NDPI_LOG_DEBUG, "EDONKEY detection...\n");
+
+ /* skip marked packets */
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_EDONKEY) {
+ if (packet->tcp_retransmission == 0) {
+ ndpi_check_edonkey(ndpi_struct, flow);
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/fasttrack.c b/src/lib/protocols/fasttrack.c
new file mode 100644
index 000000000..0e0ff1988
--- /dev/null
+++ b/src/lib/protocols/fasttrack.c
@@ -0,0 +1,82 @@
+/*
+ * fasttrack.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_FASTTRACK
+
+
+
+static void ndpi_int_fasttrack_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_FASTTRACK, NDPI_CORRELATED_PROTOCOL);
+}
+
+
+void ndpi_search_fasttrack_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len > 6 && ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0d0a) {
+ NDPI_LOG(NDPI_PROTOCOL_FASTTRACK, ndpi_struct, NDPI_LOG_TRACE, "detected 0d0a at the end of the packet.\n");
+
+ if (memcmp(packet->payload, "GIVE ", 5) == 0 && packet->payload_packet_len >= 8) {
+ u_int16_t i;
+ for (i = 5; i < (packet->payload_packet_len - 2); i++) {
+ // make shure that the argument to GIVE is numeric
+ if (!(packet->payload[i] >= '0' && packet->payload[i] <= '9')) {
+ goto exclude_fasttrack;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_FASTTRACK, ndpi_struct, NDPI_LOG_TRACE, "FASTTRACK GIVE DETECTED\n");
+ ndpi_int_fasttrack_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ if (packet->payload_packet_len > 50 && memcmp(packet->payload, "GET /", 5) == 0) {
+ u_int8_t a = 0;
+ NDPI_LOG(NDPI_PROTOCOL_FASTTRACK, ndpi_struct, NDPI_LOG_TRACE, "detected GET /. \n");
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ for (a = 0; a < packet->parsed_lines; a++) {
+ if ((packet->line[a].len > 17 && memcmp(packet->line[a].ptr, "X-Kazaa-Username: ", 18) == 0)
+ || (packet->line[a].len > 23 && memcmp(packet->line[a].ptr, "User-Agent: PeerEnabler/", 24) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_FASTTRACK, ndpi_struct, NDPI_LOG_TRACE,
+ "detected X-Kazaa-Username: || User-Agent: PeerEnabler/\n");
+ ndpi_int_fasttrack_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+ }
+
+ exclude_fasttrack:
+ NDPI_LOG(NDPI_PROTOCOL_FASTTRACK, ndpi_struct, NDPI_LOG_TRACE, "fasttrack/kazaa excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_FASTTRACK);
+}
+#endif
diff --git a/src/lib/protocols/fiesta.c b/src/lib/protocols/fiesta.c
new file mode 100644
index 000000000..2b09ac9f7
--- /dev/null
+++ b/src/lib/protocols/fiesta.c
@@ -0,0 +1,97 @@
+/*
+ * fiesta.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+/* include files */
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_FIESTA
+
+
+static void ndpi_int_fiesta_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_FIESTA, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_fiesta(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "search fiesta.\n");
+
+ if (flow->l4.tcp.fiesta_stage == 0 && packet->payload_packet_len == 5
+ && get_u_int16_t(packet->payload, 0) == ntohs(0x0407)
+ && (packet->payload[2] == 0x08)
+ && (packet->payload[4] == 0x00 || packet->payload[4] == 0x01)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "maybe fiesta symmetric, first packet.\n");
+ flow->l4.tcp.fiesta_stage = 1 + packet->packet_direction;
+ goto maybe_fiesta;
+ }
+ if (flow->l4.tcp.fiesta_stage == (2 - packet->packet_direction)
+ && ((packet->payload_packet_len > 1 && packet->payload_packet_len - 1 == packet->payload[0])
+ || (packet->payload_packet_len > 3 && packet->payload[0] == 0
+ && get_l16(packet->payload, 1) == packet->payload_packet_len - 3))) {
+ NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "Maybe fiesta.\n");
+ goto maybe_fiesta;
+ }
+ if (flow->l4.tcp.fiesta_stage == (1 + packet->packet_direction)) {
+ if (packet->payload_packet_len == 4 && get_u_int32_t(packet->payload, 0) == htonl(0x03050c01)) {
+ goto add_fiesta;
+ }
+ if (packet->payload_packet_len == 5 && get_u_int32_t(packet->payload, 0) == htonl(0x04030c01)
+ && packet->payload[4] == 0) {
+ goto add_fiesta;
+ }
+ if (packet->payload_packet_len == 6 && get_u_int32_t(packet->payload, 0) == htonl(0x050e080b)) {
+ goto add_fiesta;
+ }
+ if (packet->payload_packet_len == 100 && packet->payload[0] == 0x63 && packet->payload[61] == 0x52
+ && packet->payload[81] == 0x5a && get_u_int16_t(packet->payload, 1) == htons(0x3810)
+ && get_u_int16_t(packet->payload, 62) == htons(0x6f75)) {
+ goto add_fiesta;
+ }
+ if (packet->payload_packet_len > 3 && packet->payload_packet_len - 1 == packet->payload[0]
+ && get_u_int16_t(packet->payload, 1) == htons(0x140c)) {
+ goto add_fiesta;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "exclude fiesta.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_FIESTA);
+ return;
+
+ maybe_fiesta:
+ NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "Stage is set to %d.\n", flow->l4.tcp.fiesta_stage);
+ return;
+
+ add_fiesta:
+ NDPI_LOG(NDPI_PROTOCOL_FIESTA, ndpi_struct, NDPI_LOG_DEBUG, "detected fiesta.\n");
+ ndpi_int_fiesta_add_connection(ndpi_struct, flow);
+ return;
+}
+#endif
diff --git a/src/lib/protocols/filetopia.c b/src/lib/protocols/filetopia.c
new file mode 100644
index 000000000..d9ba1e820
--- /dev/null
+++ b/src/lib/protocols/filetopia.c
@@ -0,0 +1,83 @@
+/*
+ * filetopia.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_FILETOPIA
+
+
+static void ndpi_int_filetopia_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_FILETOPIA, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_filetopia_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (flow->l4.tcp.filetopia_stage == 0) {
+ if (packet->payload_packet_len >= 50 && packet->payload_packet_len <= 70
+ && packet->payload[0] == 0x03 && packet->payload[1] == 0x9a
+ && packet->payload[3] == 0x22 && packet->payload[packet->payload_packet_len - 1] == 0x2b) {
+ NDPI_LOG(NDPI_PROTOCOL_FILETOPIA, ndpi_struct, NDPI_LOG_DEBUG, "Filetopia stage 1 detected\n");
+ flow->l4.tcp.filetopia_stage = 1;
+ return;
+ }
+
+ } else if (flow->l4.tcp.filetopia_stage == 1) {
+ if (packet->payload_packet_len >= 100 && packet->payload[0] == 0x03
+ && packet->payload[1] == 0x9a && (packet->payload[3] == 0x22 || packet->payload[3] == 0x23)) {
+
+ int i;
+ for (i = 0; i < 10; i++) { // check 10 bytes for valid ASCII printable characters
+ if (!(packet->payload[5 + i] >= 0x20 && packet->payload[5 + i] <= 0x7e)) {
+ goto end_filetopia_nothing_found;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_FILETOPIA, ndpi_struct, NDPI_LOG_DEBUG, "Filetopia stage 2 detected\n");
+ flow->l4.tcp.filetopia_stage = 2;
+ return;
+ }
+
+
+ } else if (flow->l4.tcp.filetopia_stage == 2) {
+ if (packet->payload_packet_len >= 4 && packet->payload_packet_len <= 100
+ && packet->payload[0] == 0x03 && packet->payload[1] == 0x9a
+ && (packet->payload[3] == 0x22 || packet->payload[3] == 0x23)) {
+ NDPI_LOG(NDPI_PROTOCOL_FILETOPIA, ndpi_struct, NDPI_LOG_DEBUG, "Filetopia detected\n");
+ ndpi_int_filetopia_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ }
+
+ end_filetopia_nothing_found:
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_FILETOPIA);
+}
+
+#endif
diff --git a/src/lib/protocols/florensia.c b/src/lib/protocols/florensia.c
new file mode 100644
index 000000000..7f253cb6f
--- /dev/null
+++ b/src/lib/protocols/florensia.c
@@ -0,0 +1,122 @@
+/*
+ * florensia.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_FLORENSIA
+
+
+static void ndpi_florensia_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_FLORENSIA, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_florensia(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "search florensia.\n");
+
+ if (packet->tcp != NULL) {
+ if (packet->payload_packet_len == 5 && get_l16(packet->payload, 0) == packet->payload_packet_len
+ && packet->payload[2] == 0x65 && packet->payload[4] == 0xff) {
+ if (flow->florensia_stage == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "found florensia.\n");
+ ndpi_florensia_add_connection(ndpi_struct, flow);
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "maybe florensia -> stage is set to 1.\n");
+ flow->florensia_stage = 1;
+ return;
+ }
+ if (packet->payload_packet_len > 8 && get_l16(packet->payload, 0) == packet->payload_packet_len
+ && get_u_int16_t(packet->payload, 2) == htons(0x0201) && get_u_int32_t(packet->payload, 4) == htonl(0xFFFFFFFF)) {
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "maybe florensia -> stage is set to 1.\n");
+ flow->florensia_stage = 1;
+ return;
+ }
+ if (packet->payload_packet_len == 406 && get_l16(packet->payload, 0) == packet->payload_packet_len
+ && packet->payload[2] == 0x63) {
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "maybe florensia -> stage is set to 1.\n");
+ flow->florensia_stage = 1;
+ return;
+ }
+ if (packet->payload_packet_len == 12 && get_l16(packet->payload, 0) == packet->payload_packet_len
+ && get_u_int16_t(packet->payload, 2) == htons(0x0301)) {
+ if (flow->florensia_stage == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "found florensia.\n");
+ ndpi_florensia_add_connection(ndpi_struct, flow);
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "maybe florensia -> stage is set to 1.\n");
+ flow->florensia_stage = 1;
+ return;
+ }
+
+ if (flow->florensia_stage == 1) {
+ if (packet->payload_packet_len == 8 && get_l16(packet->payload, 0) == packet->payload_packet_len
+ && get_u_int16_t(packet->payload, 2) == htons(0x0302) && get_u_int32_t(packet->payload, 4) == htonl(0xFFFFFFFF)) {
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "found florensia asymmetrically.\n");
+ ndpi_florensia_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len == 24 && get_l16(packet->payload, 0) == packet->payload_packet_len
+ && get_u_int16_t(packet->payload, 2) == htons(0x0202)
+ && get_u_int32_t(packet->payload, packet->payload_packet_len - 4) == htonl(0xFFFFFFFF)) {
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "found florensia.\n");
+ ndpi_florensia_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (flow->packet_counter < 10 && get_l16(packet->payload, 0) == packet->payload_packet_len) {
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "maybe florensia.\n");
+ return;
+ }
+ }
+ }
+
+ if (packet->udp != NULL) {
+ if (flow->florensia_stage == 0 && packet->payload_packet_len == 6
+ && get_u_int16_t(packet->payload, 0) == ntohs(0x0503) && get_u_int32_t(packet->payload, 2) == htonl(0xFFFF0000)) {
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "maybe florensia -> stage is set to 1.\n");
+ flow->florensia_stage = 1;
+ return;
+ }
+ if (flow->florensia_stage == 1 && packet->payload_packet_len == 8
+ && get_u_int16_t(packet->payload, 0) == ntohs(0x0500) && get_u_int16_t(packet->payload, 4) == htons(0x4191)) {
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "found florensia.\n");
+ ndpi_florensia_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_FLORENSIA, ndpi_struct, NDPI_LOG_DEBUG, "exclude florensia.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_FLORENSIA);
+}
+
+#endif
diff --git a/src/lib/protocols/ftp_control.c b/src/lib/protocols/ftp_control.c
new file mode 100644
index 000000000..a757902dc
--- /dev/null
+++ b/src/lib/protocols/ftp_control.c
@@ -0,0 +1,999 @@
+/*
+ * ftp_control.c
+ *
+ * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk>
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_FTP_CONTROL
+
+static void ndpi_int_ftp_control_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_FTP_CONTROL, NDPI_REAL_PROTOCOL);
+}
+
+static int ndpi_ftp_control_check_request(const u_int8_t *payload) {
+
+ if (match_first_bytes(payload, "ABOR")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "ACCT")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "ADAT")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "ALLO")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "APPE")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "AUTH")) {
+ return 1;
+ }
+ if (match_first_bytes(payload, "CCC")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "CDUP")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "CONF")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "CWD")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "DELE")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "ENC")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "EPRT")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "EPSV")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "FEAT")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "HELP")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "LANG")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "LIST")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "LPRT")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "LPSV")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "MDTM")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "MIC")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "MKD")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "MLSD")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "MLST")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "MODE")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "NLST")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "NOOP")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "OPTS")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "PASS")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "PASV")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "PBSZ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "PORT")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "PROT")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "PWD")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "QUIT")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "REIN")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "REST")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "RETR")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "RMD")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "RNFR")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "RNTO")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "SITE")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "SIZE")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "SMNT")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "STAT")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "STOR")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "STOU")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "STRU")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "SYST")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "TYPE")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "USER")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "XCUP")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "XMKD")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "XPWD")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "XRCP")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "XRMD")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "XRSQ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "XSEM")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "XSEN")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "HOST")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "abor")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "acct")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "adat")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "allo")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "appe")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "auth")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "ccc")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "cdup")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "conf")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "cwd")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "dele")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "enc")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "eprt")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "epsv")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "feat")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "help")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "lang")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "list")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "lprt")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "lpsv")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "mdtm")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "mic")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "mkd")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "mlsd")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "mlst")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "mode")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "nlst")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "noop")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "opts")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "pass")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "pasv")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "pbsz")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "port")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "prot")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "pwd")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "quit")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "rein")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "rest")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "retr")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "rmd")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "rnfr")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "rnto")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "site")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "size")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "smnt")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "stat")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "stor")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "stou")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "stru")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "syst")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "type")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "user")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "xcup")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "xmkd")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "xpwd")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "xrcp")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "xrmd")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "xrsq")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "xsem")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "xsen")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "host")) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int ndpi_ftp_control_check_response(const u_int8_t *payload) {
+
+ if (match_first_bytes(payload, "110-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "120-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "125-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "150-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "202-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "211-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "212-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "213-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "214-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "215-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "220-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "221-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "225-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "226-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "227-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "228-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "229-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "230-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "231-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "232-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "250-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "257-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "331-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "332-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "350-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "421-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "425-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "426-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "430-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "434-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "450-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "451-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "452-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "501-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "502-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "503-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "504-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "530-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "532-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "550-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "551-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "552-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "553-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "631-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "632-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "633-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "10054-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "10060-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "10061-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "10066-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "10068-")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "110 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "120 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "125 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "150 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "202 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "211 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "212 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "213 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "214 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "215 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "220 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "221 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "225 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "226 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "227 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "228 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "229 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "230 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "231 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "232 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "250 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "257 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "331 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "332 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "350 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "421 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "425 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "426 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "430 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "434 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "450 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "451 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "452 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "501 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "502 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "503 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "504 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "530 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "532 ")) {
+ return 1;
+ }
+ if (match_first_bytes(payload, "550 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "551 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "552 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "553 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "631 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "632 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "633 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "10054 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "10060 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "10061 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "10066 ")) {
+ return 1;
+ }
+
+ if (match_first_bytes(payload, "10068 ")) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static void ndpi_check_ftp_control(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Exclude SMTP, which uses similar commands. */
+ if (packet->tcp->dest == htons(25) || packet->tcp->source == htons(25)) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_CONTROL, ndpi_struct, NDPI_LOG_DEBUG, "Exclude FTP_CONTROL.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_FTP_CONTROL);
+ return;
+ }
+
+ /* Break after 20 packets. */
+ if (flow->packet_counter > 20) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_CONTROL, ndpi_struct, NDPI_LOG_DEBUG, "Exclude FTP_CONTROL.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_FTP_CONTROL);
+ return;
+ }
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->ftp_control_stage == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_CONTROL, ndpi_struct, NDPI_LOG_DEBUG, "FTP_CONTROL stage 0: \n");
+
+ if ((payload_len > 0) && ndpi_ftp_control_check_request(packet->payload)) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_CONTROL, ndpi_struct, NDPI_LOG_DEBUG, "Possible FTP_CONTROL request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->ftp_control_stage = packet->packet_direction + 1;
+ }
+
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_CONTROL, ndpi_struct, NDPI_LOG_DEBUG, "FTP_CONTROL stage %u: \n", flow->ftp_control_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->ftp_control_stage - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len > 0) && ndpi_ftp_control_check_response(packet->payload)) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_CONTROL, ndpi_struct, NDPI_LOG_DEBUG, "Found FTP_CONTROL.\n");
+ ndpi_int_ftp_control_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_CONTROL, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to FTP_CONTROL, resetting the stage to 0...\n");
+ flow->ftp_control_stage = 0;
+ }
+
+ }
+}
+
+void ndpi_search_ftp_control(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_FTP_CONTROL, ndpi_struct, NDPI_LOG_DEBUG, "FTP_CONTROL detection...\n");
+
+ /* skip marked packets */
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_FTP_CONTROL) {
+ if (packet->tcp_retransmission == 0) {
+ ndpi_check_ftp_control(ndpi_struct, flow);
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/ftp_data.c b/src/lib/protocols/ftp_data.c
new file mode 100644
index 000000000..2bb77e1ec
--- /dev/null
+++ b/src/lib/protocols/ftp_data.c
@@ -0,0 +1,275 @@
+/*
+ * ftp_data.c
+ *
+ * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk>
+ * Copyright (C) 2014 - ntop.org
+ *
+ * The signature is based on the Libprotoident library.
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_FTP_DATA
+static void ndpi_int_ftp_data_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_FTP_DATA, NDPI_REAL_PROTOCOL);
+}
+
+static int ndpi_match_ftp_data_port(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(packet->tcp->dest == htons(20) || packet->tcp->source == htons(20)) {
+ return 1;
+ }
+
+ return 0;
+
+}
+
+static int ndpi_match_ftp_data_directory(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ if((payload_len >= 4)
+ && ((packet->payload[0] == '-') || (packet->payload[0] == 'd'))
+ && ((packet->payload[1] == '-') || (packet->payload[1] == 'r'))
+ && ((packet->payload[2] == '-') || (packet->payload[2] == 'w'))
+ && ((packet->payload[3] == '-') || (packet->payload[3] == 'x'))) {
+
+ return 1;
+ }
+
+ return 0;
+
+}
+
+static int ndpi_match_file_header(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ /* A FTP packet is pretty long so 256 is a bit consrvative but it should be OK */
+ if(packet->payload_packet_len < 256)
+ return 0;
+
+ /* RIFF is a meta-format for storing AVI and WAV files */
+ if(match_first_bytes(packet->payload, "RIFF"))
+ return 1;
+
+ /* MZ is a .exe file */
+ if((packet->payload[0] == 'M') && (packet->payload[1] == 'Z') && (packet->payload[3] == 0x00))
+ return 1;
+
+ /* Ogg files */
+ if(match_first_bytes(packet->payload, "OggS"))
+ return 1;
+
+ /* ZIP files */
+ if((packet->payload[0] == 'P') && (packet->payload[1] == 'K') && (packet->payload[2] == 0x03) && (packet->payload[3] == 0x04))
+ return 1;
+
+ /* MPEG files */
+ if((packet->payload[0] == 0x00) && (packet->payload[1] == 0x00) && (packet->payload[2] == 0x01) && (packet->payload[3] == 0xba))
+ return 1;
+
+ /* RAR files */
+ if(match_first_bytes(packet->payload, "Rar!"))
+ return 1;
+
+ /* EBML */
+ if((packet->payload[0] == 0x1a) && (packet->payload[1] == 0x45) && (packet->payload[2] == 0xdf) && (packet->payload[3] == 0xa3))
+ return 1;
+
+ /* JPG */
+ if((packet->payload[0] == 0xff) && (packet->payload[1] ==0xd8))
+ return 1;
+
+ /* GIF */
+ if(match_first_bytes(packet->payload, "GIF8"))
+ return 1;
+
+ /* PHP scripts */
+ if((packet->payload[0] == 0x3c) && (packet->payload[1] == 0x3f) && (packet->payload[2] == 0x70) && (packet->payload[3] == 0x68))
+ return 1;
+
+ /* Unix scripts */
+ if((packet->payload[0] == 0x23) && (packet->payload[1] == 0x21) && (packet->payload[2] == 0x2f) && (packet->payload[3] == 0x62))
+ return 1;
+
+ /* PDFs */
+ if(match_first_bytes(packet->payload, "%PDF"))
+ return 1;
+
+ /* PNG */
+ if((packet->payload[0] == 0x89) && (packet->payload[1] == 'P') && (packet->payload[2] == 'N') && (packet->payload[3] == 'G'))
+ return 1;
+
+ /* HTML */
+ if(match_first_bytes(packet->payload, "<htm"))
+ return 1;
+ if((packet->payload[0] == 0x0a) && (packet->payload[1] == '<') && (packet->payload[2] == '!') && (packet->payload[3] == 'D'))
+ return 1;
+
+ /* 7zip */
+ if((packet->payload[0] == 0x37) && (packet->payload[1] == 0x7a) && (packet->payload[2] == 0xbc) && (packet->payload[3] == 0xaf))
+ return 1;
+
+ /* gzip */
+ if((packet->payload[0] == 0x1f) && (packet->payload[1] == 0x8b) && (packet->payload[2] == 0x08))
+ return 1;
+
+ /* XML */
+ if(match_first_bytes(packet->payload, "<!DO"))
+ return 1;
+
+ /* FLAC */
+ if(match_first_bytes(packet->payload, "fLaC"))
+ return 1;
+
+ /* MP3 */
+ if((packet->payload[0] == 'I') && (packet->payload[1] == 'D') && (packet->payload[2] == '3') && (packet->payload[3] == 0x03))
+ return 1;
+ if(match_first_bytes(packet->payload, "\xff\xfb\x90\xc0"))
+ return 1;
+
+ /* RPM */
+ if((packet->payload[0] == 0xed) && (packet->payload[1] == 0xab) && (packet->payload[2] == 0xee) && (packet->payload[3] == 0xdb))
+ return 1;
+
+ /* Wz Patch */
+ if(match_first_bytes(packet->payload, "WzPa"))
+ return 1;
+
+ /* Flash Video */
+ if((packet->payload[0] == 'F') && (packet->payload[1] == 'L') && (packet->payload[2] == 'V') && (packet->payload[3] == 0x01))
+ return 1;
+
+ /* .BKF (Microsoft Tape Format) */
+ if(match_first_bytes(packet->payload, "TAPE"))
+ return 1;
+
+ /* MS Office Doc file - this is unpleasantly geeky */
+ if((packet->payload[0] == 0xd0) && (packet->payload[1] == 0xcf) && (packet->payload[2] == 0x11) && (packet->payload[3] == 0xe0))
+ return 1;
+
+ /* ASP */
+ if((packet->payload[0] == 0x3c) && (packet->payload[1] == 0x25) && (packet->payload[2] == 0x40) && (packet->payload[3] == 0x20))
+ return 1;
+
+ /* WMS file */
+ if((packet->payload[0] == 0x3c) && (packet->payload[1] == 0x21) && (packet->payload[2] == 0x2d) && (packet->payload[3] == 0x2d))
+ return 1;
+
+ /* ar archive, typically .deb files */
+ if(match_first_bytes(packet->payload, "!<ar"))
+ return 1;
+
+ /* Raw XML (skip jabber-like traffic as this is not FTP but unencrypted jabber) */
+ if((match_first_bytes(packet->payload, "<?xm"))
+ && (ndpi_strnstr((const char *)packet->payload, "jabber", packet->payload_packet_len) == NULL))
+ return 1;
+
+ if(match_first_bytes(packet->payload, "<iq "))
+ return 1;
+
+ /* SPF */
+ if(match_first_bytes(packet->payload, "SPFI"))
+ return 1;
+
+ /* ABIF - Applied Biosystems */
+ if(match_first_bytes(packet->payload, "ABIF"))
+ return 1;
+
+ /* bzip2 - other digits are also possible instead of 9 */
+ if((packet->payload[0] == 'B') && (packet->payload[1] == 'Z') && (packet->payload[2] == 'h') && (packet->payload[3] == '9'))
+ return 1;
+
+ /* Some other types of files */
+
+ if((packet->payload[0] == '<') && (packet->payload[1] == 'c') && (packet->payload[2] == 'f'))
+ return 1;
+ if((packet->payload[0] == '<') && (packet->payload[1] == 'C') && (packet->payload[2] == 'F'))
+ return 1;
+ if(match_first_bytes(packet->payload, ".tem"))
+ return 1;
+ if(match_first_bytes(packet->payload, ".ite"))
+ return 1;
+ if(match_first_bytes(packet->payload, ".lef"))
+ return 1;
+
+ return 0;
+}
+
+static void ndpi_check_ftp_data(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if(flow->ftp_data_stage == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_DATA, ndpi_struct, NDPI_LOG_DEBUG, "FTP_DATA stage 0: \n");
+
+ if((payload_len > 0) && (ndpi_match_file_header(ndpi_struct, flow) || ndpi_match_ftp_data_directory(ndpi_struct, flow) || ndpi_match_ftp_data_port(ndpi_struct, flow))) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_DATA, ndpi_struct, NDPI_LOG_DEBUG, "Possible FTP_DATA request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->ftp_data_stage = packet->packet_direction + 1;
+ }
+
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_DATA, ndpi_struct, NDPI_LOG_DEBUG, "FTP_DATA stage %u: \n", flow->ftp_data_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if((flow->ftp_data_stage - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if(payload_len == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_DATA, ndpi_struct, NDPI_LOG_DEBUG, "Found FTP_DATA.\n");
+ ndpi_int_ftp_data_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_DATA, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to FTP_DATA, resetting the stage to 0...\n");
+ flow->ftp_data_stage = 0;
+ }
+
+ }
+}
+
+void ndpi_search_ftp_data(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ /* Break after 20 packets. */
+ if(flow->packet_counter > 20) {
+ NDPI_LOG(NDPI_PROTOCOL_FTP_DATA, ndpi_struct, NDPI_LOG_DEBUG, "Exclude FTP_DATA.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_FTP_DATA);
+ return;
+ }
+
+ /* skip marked or retransmitted packets */
+ if(packet->tcp_retransmission != 0) {
+ return;
+ }
+
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_FTP_DATA) {
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_FTP_DATA, ndpi_struct, NDPI_LOG_DEBUG, "FTP_DATA detection...\n");
+ ndpi_check_ftp_data(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/gnutella.c b/src/lib/protocols/gnutella.c
new file mode 100644
index 000000000..022df6e3d
--- /dev/null
+++ b/src/lib/protocols/gnutella.c
@@ -0,0 +1,375 @@
+/*
+ * gnutella.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+/* include files */
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_GNUTELLA
+
+static void ndpi_int_gnutella_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ ndpi_protocol_type_t protocol_type)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_GNUTELLA, protocol_type);
+
+ if (src != NULL) {
+ src->gnutella_ts = packet->tick_timestamp;
+ if (packet->udp != NULL) {
+ if (!src->detected_gnutella_udp_port1) {
+ src->detected_gnutella_udp_port1 = (packet->udp->source);
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
+ NDPI_LOG_DEBUG, "GNUTELLA UDP PORT1 DETECTED as %u\n",
+ src->detected_gnutella_udp_port1);
+
+ } else if ((ntohs(packet->udp->source) != src->detected_gnutella_udp_port1)
+ && !src->detected_gnutella_udp_port2) {
+ src->detected_gnutella_udp_port2 = (packet->udp->source);
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
+ NDPI_LOG_DEBUG, "GNUTELLA UDP PORT2 DETECTED as %u\n",
+ src->detected_gnutella_udp_port2);
+
+ }
+ }
+ }
+ if (dst != NULL) {
+ dst->gnutella_ts = packet->tick_timestamp;
+ }
+}
+
+void ndpi_search_gnutella(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ u_int16_t c;
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_GNUTELLA) {
+ if (src != NULL && ((u_int32_t)
+ (packet->tick_timestamp - src->gnutella_ts) < ndpi_struct->gnutella_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
+ NDPI_LOG_DEBUG, "gnutella : save src connection packet detected\n");
+ src->gnutella_ts = packet->tick_timestamp;
+ } else if (dst != NULL && ((u_int32_t)
+ (packet->tick_timestamp - dst->gnutella_ts) < ndpi_struct->gnutella_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
+ NDPI_LOG_DEBUG, "gnutella : save dst connection packet detected\n");
+ dst->gnutella_ts = packet->tick_timestamp;
+ }
+ if (src != NULL && (packet->tick_timestamp - src->gnutella_ts) > ndpi_struct->gnutella_timeout) {
+ src->detected_gnutella_udp_port1 = 0;
+ src->detected_gnutella_udp_port2 = 0;
+ }
+ if (dst != NULL && (packet->tick_timestamp - dst->gnutella_ts) > ndpi_struct->gnutella_timeout) {
+ dst->detected_gnutella_udp_port1 = 0;
+ dst->detected_gnutella_udp_port2 = 0;
+ }
+
+ return;
+ }
+
+ /* skip packets without payload */
+ if (packet->payload_packet_len < 2) {
+ return;
+ }
+ if (packet->tcp != NULL) {
+ /* this case works asymmetrically */
+ if (packet->payload_packet_len > 10 && memcmp(packet->payload, "GNUTELLA/", 9) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "GNUTELLA DETECTED\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ /* this case works asymmetrically */
+ if (packet->payload_packet_len > 17 && memcmp(packet->payload, "GNUTELLA CONNECT/", 17) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "GNUTELLA DETECTED\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ if (packet->payload_packet_len > 50 && ((memcmp(packet->payload, "GET /get/", 9) == 0)
+ || (memcmp(packet->payload, "GET /uri-res/", 13) == 0)
+ )) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ for (c = 0; c < packet->parsed_lines; c++) {
+ if ((packet->line[c].len > 19 && memcmp(packet->line[c].ptr, "User-Agent: Gnutella", 20) == 0)
+ || (packet->line[c].len > 10 && memcmp(packet->line[c].ptr, "X-Gnutella-", 11) == 0)
+ || (packet->line[c].len > 7 && memcmp(packet->line[c].ptr, "X-Queue:", 8) == 0)
+ || (packet->line[c].len > 36 && memcmp(packet->line[c].ptr,
+ "Content-Type: application/x-gnutella-", 37) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG, "DETECTED GNUTELLA GET.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+ if (packet->payload_packet_len > 50 && ((memcmp(packet->payload, "GET / HTTP", 9) == 0))) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if ((packet->user_agent_line.ptr != NULL && packet->user_agent_line.len > 15
+ && memcmp(packet->user_agent_line.ptr, "BearShare Lite ", 15) == 0)
+ || (packet->accept_line.ptr != NULL && packet->accept_line.len > 24
+ && memcmp(packet->accept_line.ptr, "application n/x-gnutella", 24) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG, "DETECTED GNUTELLA GET.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ }
+
+ }
+ /* haven't found this pattern in any trace. */
+ if (packet->payload_packet_len > 50 && ((memcmp(packet->payload, "GET /get/", 9) == 0)
+ || (memcmp(packet->payload, "GET /uri-res/", 13) == 0))) {
+ c = 8;
+ while (c < (packet->payload_packet_len - 9)) {
+ if (packet->payload[c] == '?')
+ break;
+ c++;
+ }
+
+ if (c < (packet->payload_packet_len - 9) && memcmp(&packet->payload[c], "urn:sha1:", 9) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE,
+ "detected GET /get/ or GET /uri-res/.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ }
+
+ }
+
+ /* answer to this packet is HTTP/1.1 ..... Content-Type: application/x-gnutella-packets,
+ * it is searched in the upper paragraph. */
+ if (packet->payload_packet_len > 30 && memcmp(packet->payload, "HEAD /gnutella/push-proxy?", 26) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "detected HEAD /gnutella/push-proxy?\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ /* haven't found any trace with this pattern */
+ if (packet->payload_packet_len == 46
+ && memcmp(packet->payload, "\x50\x55\x53\x48\x20\x67\x75\x69\x64\x3a", 10) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE,
+ "detected \x50\x55\x53\x48\x20\x67\x75\x69\x64\x3a\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ /* haven't found any trace with this pattern */
+ if (packet->payload_packet_len > 250 && memcmp(packet->payload, "GET /gnutella/", 14) == 0)
+ //PATTERN IS :: GET /gnutella/tigertree/v3?urn:tree:tiger/:
+ {
+ const u_int16_t end = packet->payload_packet_len - 3;
+
+ c = 13;
+ while (c < end) {
+ if ((memcmp(&packet->payload[14], "tigertree/", 10) == 0)
+ || (end - c > 18 && memcmp(&packet->payload[c], "\r\nUser-Agent: Foxy", 18) == 0)
+ || (end - c > 44
+ && memcmp(&packet->payload[c],
+ "\r\nAccept: application/tigertree-breadthfirst",
+ 44) == 0) || (end - c > 10 && memcmp(&packet->payload[c], "\r\nX-Queue:", 10) == 0)
+ || (end - c > 13 && memcmp(&packet->payload[c], "\r\nX-Features:", 13) == 0)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA,
+ ndpi_struct, NDPI_LOG_TRACE, "FOXY :: GNUTELLA GET 2 DETECTED\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+
+ c++;
+ }
+ }
+ /* haven't found any trace with this pattern */
+ if (packet->payload_packet_len > 1 && packet->payload[packet->payload_packet_len - 1] == 0x0a
+ && packet->payload[packet->payload_packet_len - 2] == 0x0a) {
+ if (packet->payload_packet_len > 3 && memcmp(packet->payload, "GIV", 3) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "MORPHEUS GIV DETECTED\n");
+ /* Not Excludeing the flow now.. We shall Check the next Packet too for Gnutella Patterns */
+ return;
+ }
+ }
+ /* might be super tricky new ssl gnutella transmission, but the certificate is strange... */
+ if (packet->payload_packet_len == 46 && get_u_int32_t(packet->payload, 0) == htonl(0x802c0103) &&
+ get_u_int32_t(packet->payload, 4) == htonl(0x01000300) && get_u_int32_t(packet->payload, 8) == htonl(0x00002000) &&
+ get_u_int16_t(packet->payload, 12) == htons(0x0034)) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "detected gnutella len == 46.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 49 &&
+ memcmp(packet->payload, "\x80\x2f\x01\x03\x01\x00\x06\x00\x00\x00\x20\x00\x00\x34\x00\x00\xff\x4d\x6c",
+ 19) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "detected gnutella len == 49.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 89 && memcmp(&packet->payload[43], "\x20\x4d\x6c", 3) == 0 &&
+ memcmp(packet->payload, "\x16\x03\x01\x00\x54\x01\x00\x00\x50\x03\x01\x4d\x6c", 13) == 0 &&
+ memcmp(&packet->payload[76], "\x00\x02\x00\x34\x01\x00\x00\x05", 8) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE,
+ "detected gnutella asymmetrically len == 388.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ } else if (packet->payload_packet_len == 82) {
+ if (get_u_int32_t(packet->payload, 0) == htonl(0x16030100)
+ && get_u_int32_t(packet->payload, 4) == htonl(0x4d010000)
+ && get_u_int16_t(packet->payload, 8) == htons(0x4903)
+ && get_u_int16_t(packet->payload, 76) == htons(0x0002)
+ && get_u_int32_t(packet->payload, 78) == htonl(0x00340100)) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_TRACE, "detected len == 82.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ } else if (packet->udp != NULL) {
+ if (src != NULL && (packet->udp->source == src->detected_gnutella_udp_port1 ||
+ packet->udp->source == src->detected_gnutella_udp_port2) &&
+ (packet->tick_timestamp - src->gnutella_ts) < ndpi_struct->gnutella_timeout) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG, "port based detection\n\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ }
+ /* observations:
+ * all the following patterns send out many packets which are the only ones of their flows,
+ * often on the very beginning of the traces, or flows with many packets in one direction only.
+ * but then suddenly, one gets an answer as you can see in netpeker-gnutella-rpc.pcap packet 11483.
+ * Maybe gnutella tries to send out keys?
+ */
+ if (packet->payload_packet_len == 23 && packet->payload[15] == 0x00
+ && packet->payload[16] == 0x41 && packet->payload[17] == 0x01
+ && packet->payload[18] == 0x00 && packet->payload[19] == 0x00
+ && packet->payload[20] == 0x00 && packet->payload[21] == 0x00 && packet->payload[22] == 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
+ "detected gnutella udp, len = 23.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+
+ return;
+ }
+ if (packet->payload_packet_len == 35 && packet->payload[25] == 0x49
+ && packet->payload[26] == 0x50 && packet->payload[27] == 0x40
+ && packet->payload[28] == 0x83 && packet->payload[29] == 0x53
+ && packet->payload[30] == 0x43 && packet->payload[31] == 0x50 && packet->payload[32] == 0x41) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
+ "detected gnutella udp, len = 35.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 32
+ && (memcmp(&packet->payload[16], "\x31\x01\x00\x09\x00\x00\x00\x4c\x49\x4d\x45", 11) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
+ "detected gnutella udp, len = 32.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 34 && (memcmp(&packet->payload[25], "SCP@", 4) == 0)
+ && (memcmp(&packet->payload[30], "DNA@", 4) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
+ "detected gnutella udp, len = 34.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if ((packet->payload_packet_len == 73 || packet->payload_packet_len == 96)
+ && memcmp(&packet->payload[32], "urn:sha1:", 9) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
+ "detected gnutella udp, len = 73,96.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ if (memcmp(packet->payload, "GND", 3) == 0) {
+ if ((packet->payload_packet_len == 8 && (memcmp(&packet->payload[6], "\x01\x00", 2) == 0))
+ || (packet->payload_packet_len == 11 && (memcmp(&packet->payload[6], "\x01\x01\x08\x50\x49", 5)
+ == 0)) || (packet->payload_packet_len == 17
+ &&
+ (memcmp
+ (&packet->payload[6], "\x01\x01\x4c\x05\x50",
+ 5) == 0))
+ || (packet->payload_packet_len == 28
+ && (memcmp(&packet->payload[6], "\x01\x01\x54\x0f\x51\x4b\x52\x50\x06\x52", 10) == 0))
+ || (packet->payload_packet_len == 41
+ && (memcmp(&packet->payload[6], "\x01\x01\x5c\x1b\x50\x55\x53\x48\x48\x10", 10) == 0))
+ || (packet->payload_packet_len > 200 && packet->payload_packet_len < 300 && packet->payload[3] == 0x03)
+ || (packet->payload_packet_len > 300 && (packet->payload[3] == 0x01 || packet->payload[3] == 0x03))) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
+ "detected gnutella udp, GND.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+ if ((packet->payload_packet_len == 32)
+ && memcmp(&packet->payload[16], "\x31\x01\x00\x09\x00\x00\x00", 7) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
+ "detected gnutella udp, len = 32 ii.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if ((packet->payload_packet_len == 23)
+ && memcmp(&packet->payload[16], "\x00\x01\x00\x00\x00\x00\x00", 7) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct, NDPI_LOG_DEBUG,
+ "detected gnutella udp, len = 23 ii.\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ //neonet detection follows
+
+ /* haven't found any trace with this pattern */
+ if (packet->tcp != NULL && ntohs(packet->tcp->source) >= 1024 && ntohs(packet->tcp->dest) >= 1024) {
+ if (flow->l4.tcp.gnutella_stage == 0) {
+ if (flow->packet_counter == 1
+ && (packet->payload_packet_len == 11
+ || packet->payload_packet_len == 33 || packet->payload_packet_len == 37)) {
+ flow->l4.tcp.gnutella_msg_id[0] = packet->payload[4];
+ flow->l4.tcp.gnutella_msg_id[1] = packet->payload[6];
+ flow->l4.tcp.gnutella_msg_id[2] = packet->payload[8];
+ flow->l4.tcp.gnutella_stage = 1 + packet->packet_direction;
+ return;
+ }
+ } else if (flow->l4.tcp.gnutella_stage == 1 + packet->packet_direction) {
+ if (flow->packet_counter == 2 && (packet->payload_packet_len == 33 || packet->payload_packet_len == 22)
+ && flow->l4.tcp.gnutella_msg_id[0] == packet->payload[0]
+ && flow->l4.tcp.gnutella_msg_id[1] == packet->payload[2]
+ && flow->l4.tcp.gnutella_msg_id[2] == packet->payload[4]
+ && NDPI_SRC_OR_DST_HAS_PROTOCOL(src, dst, NDPI_PROTOCOL_GNUTELLA)) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
+ NDPI_LOG_TRACE, "GNUTELLA DETECTED due to message ID match (NEONet protocol)\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ } else if (flow->l4.tcp.gnutella_stage == 2 - packet->packet_direction) {
+ if (flow->packet_counter == 2 && (packet->payload_packet_len == 10 || packet->payload_packet_len == 75)
+ && flow->l4.tcp.gnutella_msg_id[0] == packet->payload[0]
+ && flow->l4.tcp.gnutella_msg_id[1] == packet->payload[2]
+ && flow->l4.tcp.gnutella_msg_id[2] == packet->payload[4]
+ && NDPI_SRC_OR_DST_HAS_PROTOCOL(src, dst, NDPI_PROTOCOL_GNUTELLA)) {
+ NDPI_LOG(NDPI_PROTOCOL_GNUTELLA, ndpi_struct,
+ NDPI_LOG_TRACE, "GNUTELLA DETECTED due to message ID match (NEONet protocol)\n");
+ ndpi_int_gnutella_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_GNUTELLA);
+}
+#endif
diff --git a/src/lib/protocols/gtp.c b/src/lib/protocols/gtp.c
new file mode 100644
index 000000000..b9aee7a97
--- /dev/null
+++ b/src/lib/protocols/gtp.c
@@ -0,0 +1,85 @@
+/*
+ * gtp.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_GTP
+
+struct gtp_header_generic {
+ u_int8_t flags, message_type;
+ u_int16_t message_len;
+ u_int32_t teid;
+};
+
+static void ndpi_check_gtp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // const u_int8_t *packet_payload = packet->payload;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+#if 0
+ printf("[len=%u][%02X %02X %02X %02X]\n", payload_len,
+ packet->payload[0] & 0xFF,
+ packet->payload[1] & 0xFF,
+ packet->payload[2] & 0xFF,
+ packet->payload[3] & 0xFF);
+#endif
+
+ if((packet->udp != NULL) && (payload_len > sizeof(struct gtp_header_generic))) {
+ u_int32_t gtp_u = ntohs(2152);
+ u_int32_t gtp_c = ntohs(2123);
+ u_int32_t gtp_v0 = ntohs(3386);
+
+ if((packet->udp->source == gtp_u) || (packet->udp->dest == gtp_u)
+ || (packet->udp->source == gtp_c) || (packet->udp->dest == gtp_c)
+ || (packet->udp->source == gtp_v0) || (packet->udp->dest == gtp_v0)
+ ) {
+ struct gtp_header_generic *gtp = (struct gtp_header_generic*)packet->payload;
+ u_int8_t gtp_version = (gtp->flags & 0xE0) >> 5;
+
+ if((gtp_version == 0) || (gtp_version == 1) || (gtp_version == 2)) {
+ u_int16_t message_len = ntohs(gtp->message_len);
+
+ if(message_len <= (payload_len-sizeof(struct gtp_header_generic))) {
+ NDPI_LOG(NDPI_PROTOCOL_GTP, ndpi_struct, NDPI_LOG_DEBUG, "Found gtp.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_GTP, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_GTP);
+ return;
+}
+
+void ndpi_search_gtp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_GTP, ndpi_struct, NDPI_LOG_DEBUG, "gtp detection...\n");
+
+ /* skip marked packets */
+ if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_GTP)
+ ndpi_check_gtp(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/guildwars.c b/src/lib/protocols/guildwars.c
new file mode 100644
index 000000000..b5dda0cdf
--- /dev/null
+++ b/src/lib/protocols/guildwars.c
@@ -0,0 +1,71 @@
+/*
+ * guildwars.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+/* include files */
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_GUILDWARS
+
+
+static void ndpi_int_guildwars_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_GUILDWARS, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_guildwars_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_GUILDWARS, ndpi_struct, NDPI_LOG_DEBUG, "search guildwars.\n");
+
+ if (packet->payload_packet_len == 64 && get_u_int16_t(packet->payload, 1) == ntohs(0x050c)
+ && memcmp(&packet->payload[50], "@2&P", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_GUILDWARS, ndpi_struct, NDPI_LOG_DEBUG, "GuildWars version 29.350: found.\n");
+ ndpi_int_guildwars_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len == 16 && get_u_int16_t(packet->payload, 1) == ntohs(0x040c)
+ && get_u_int16_t(packet->payload, 4) == ntohs(0xa672)
+ && packet->payload[8] == 0x01 && packet->payload[12] == 0x04) {
+ NDPI_LOG(NDPI_PROTOCOL_GUILDWARS, ndpi_struct, NDPI_LOG_DEBUG, "GuildWars version 29.350: found.\n");
+ ndpi_int_guildwars_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len == 21 && get_u_int16_t(packet->payload, 0) == ntohs(0x0100)
+ && get_u_int32_t(packet->payload, 5) == ntohl(0xf1001000)
+ && packet->payload[9] == 0x01) {
+ NDPI_LOG(NDPI_PROTOCOL_GUILDWARS, ndpi_struct, NDPI_LOG_DEBUG, "GuildWars version 216.107.245.50: found.\n");
+ ndpi_int_guildwars_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_GUILDWARS, ndpi_struct, NDPI_LOG_DEBUG, "exclude guildwars.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_GUILDWARS);
+}
+
+#endif
diff --git a/src/lib/protocols/h323.c b/src/lib/protocols/h323.c
new file mode 100644
index 000000000..9d2fac8c8
--- /dev/null
+++ b/src/lib/protocols/h323.c
@@ -0,0 +1,97 @@
+/*
+ * h323.c
+ *
+ * Copyright (C) 2015 ntop.org
+ * Copyright (C) 2013 Remy Mudingay <mudingay@ill.fr>
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_H323
+
+struct tpkt {
+ u_int8_t version, reserved;
+ u_int16_t len;
+};
+
+void ndpi_search_h323(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t dport = 0, sport = 0;
+
+ NDPI_LOG(NDPI_PROTOCOL_H323, ndpi_struct, NDPI_LOG_DEBUG, "search H323.\n");
+
+ if(packet->tcp != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_H323, ndpi_struct, NDPI_LOG_DEBUG, "calculated dport over tcp.\n");
+
+ /* H323 */
+ if((packet->payload[0] == 0x03)
+ && (packet->payload[1] == 0x00)
+ && (packet->payload[2] == 0x00)) {
+ struct tpkt *t = (struct tpkt*)packet->payload;
+ u_int16_t len = ntohs(t->len);
+
+ if(packet->payload_packet_len == len) {
+ /*
+ We need to check if this packet is in reality
+ a RDP (Remote Desktop) packet encapsulated on TPTK
+ */
+
+ if(packet->payload[4] == (packet->payload_packet_len - sizeof(struct tpkt) - 1)) {
+ /* ISO 8073/X.224 */
+ if((packet->payload[5] == 0xE0 /* CC Connect Request */)
+ || (packet->payload[5] == 0xD0 /* CC Connect Confirm */)) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_RDP, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+ flow->l4.tcp.h323_valid_packets++;
+
+ if(flow->l4.tcp.h323_valid_packets >= 2) {
+ NDPI_LOG(NDPI_PROTOCOL_H323, ndpi_struct, NDPI_LOG_DEBUG, "found H323 broadcast.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_H323, NDPI_REAL_PROTOCOL);
+ }
+ } else {
+ /* This is not H.323 */
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_H323);
+ }
+ }
+ } else if(packet->udp != NULL) {
+ sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest);
+ NDPI_LOG(NDPI_PROTOCOL_H323, ndpi_struct, NDPI_LOG_DEBUG, "calculated dport over udp.\n");
+
+ if(packet->payload[0] == 0x80 && packet->payload[1] == 0x08 && (packet->payload[2] == 0xe7 || packet->payload[2] == 0x26) &&
+ packet->payload[4] == 0x00 && packet->payload[5] == 0x00)
+ {
+ NDPI_LOG(NDPI_PROTOCOL_H323, ndpi_struct, NDPI_LOG_DEBUG, "found H323 broadcast.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_H323, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ /* H323 */
+ if(sport == 1719 || dport == 1719)
+ {
+ if(packet->payload[0] == 0x16 && packet->payload[1] == 0x80 && packet->payload[4] == 0x06 && packet->payload[5] == 0x00)
+ {
+ NDPI_LOG(NDPI_PROTOCOL_H323, ndpi_struct, NDPI_LOG_DEBUG, "found H323 broadcast.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_H323, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ else if(packet->payload_packet_len >= 20 || packet->payload_packet_len <= 117)
+ {
+ NDPI_LOG(NDPI_PROTOCOL_H323, ndpi_struct, NDPI_LOG_DEBUG, "found H323 broadcast.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_H323, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ else
+ {
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_H323);
+ return;
+ }
+ }
+ }
+
+}
+#endif
diff --git a/src/lib/protocols/halflife2_and_mods.c b/src/lib/protocols/halflife2_and_mods.c
new file mode 100644
index 000000000..2644950c9
--- /dev/null
+++ b/src/lib/protocols/halflife2_and_mods.c
@@ -0,0 +1,65 @@
+/*
+ * halflife2_and_mods.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_HALFLIFE2
+
+
+static void ndpi_int_halflife2_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HALFLIFE2, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_halflife2(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (flow->l4.udp.halflife2_stage == 0) {
+ if (packet->payload_packet_len >= 20
+ && get_u_int32_t(packet->payload, 0) == 0xFFFFFFFF
+ && get_u_int32_t(packet->payload, packet->payload_packet_len - 4) == htonl(0x30303000)) {
+ flow->l4.udp.halflife2_stage = 1 + packet->packet_direction;
+ NDPI_LOG(NDPI_PROTOCOL_HALFLIFE2, ndpi_struct, NDPI_LOG_DEBUG,
+ "halflife2 client req detected, waiting for server reply\n");
+ return;
+ }
+ } else if (flow->l4.udp.halflife2_stage == 2 - packet->packet_direction) {
+ if (packet->payload_packet_len >= 20
+ && get_u_int32_t(packet->payload, 0) == 0xFFFFFFFF
+ && get_u_int32_t(packet->payload, packet->payload_packet_len - 4) == htonl(0x30303000)) {
+ ndpi_int_halflife2_add_connection(ndpi_struct, flow);
+ NDPI_LOG(NDPI_PROTOCOL_HALFLIFE2, ndpi_struct, NDPI_LOG_DEBUG, "halflife2 server reply detected\n");
+ return;
+ }
+ }
+
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_HALFLIFE2);
+}
+
+#endif
diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c
new file mode 100644
index 000000000..3c4cfe128
--- /dev/null
+++ b/src/lib/protocols/http.c
@@ -0,0 +1,981 @@
+/*
+ * http.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_HTTP
+
+static void ndpi_int_http_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int32_t protocol) {
+
+ if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
+ /* This is HTTP and it is not a sub protocol (e.g. skype or dropbox) */
+
+ ndpi_search_tcp_or_udp(ndpi_struct, flow);
+
+ /* If no custom protocol has been detected */
+ if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
+ if(protocol != NDPI_PROTOCOL_HTTP) {
+ ndpi_search_tcp_or_udp(ndpi_struct, flow);
+ ndpi_int_add_connection(ndpi_struct, flow, protocol, NDPI_CORRELATED_PROTOCOL);
+ } else {
+ ndpi_int_reset_protocol(flow);
+ ndpi_int_add_connection(ndpi_struct, flow, protocol, NDPI_REAL_PROTOCOL);
+ }
+ }
+
+ flow->http_detected = 1;
+ }
+
+}
+
+#ifdef NDPI_CONTENT_FLASH
+static void flash_check_http_payload(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ const u_int8_t *pos;
+
+ if(packet->empty_line_position_set == 0 || (packet->empty_line_position + 10) > (packet->payload_packet_len))
+ return;
+
+ pos = &packet->payload[packet->empty_line_position] + 2;
+
+
+ if(memcmp(pos, "FLV", 3) == 0 && pos[3] == 0x01 && (pos[4] == 0x01 || pos[4] == 0x04 || pos[4] == 0x05)
+ && pos[5] == 0x00 && pos[6] == 0x00 && pos[7] == 0x00 && pos[8] == 0x09) {
+
+ NDPI_LOG(NDPI_CONTENT_FLASH, ndpi_struct, NDPI_LOG_DEBUG, "Flash content in http detected\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_CONTENT_FLASH);
+ }
+}
+#endif
+
+#ifdef NDPI_CONTENT_AVI
+static void avi_check_http_payload(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+ NDPI_LOG(NDPI_CONTENT_AVI, ndpi_struct, NDPI_LOG_DEBUG, "called avi_check_http_payload: %u %u %u\n",
+ packet->empty_line_position_set, flow->l4.tcp.http_empty_line_seen, packet->empty_line_position);
+
+ if(packet->empty_line_position_set == 0 && flow->l4.tcp.http_empty_line_seen == 0)
+ return;
+
+ if(packet->empty_line_position_set != 0 && ((packet->empty_line_position + 20) > (packet->payload_packet_len))
+ && flow->l4.tcp.http_empty_line_seen == 0) {
+ flow->l4.tcp.http_empty_line_seen = 1;
+ return;
+ }
+
+ if(flow->l4.tcp.http_empty_line_seen == 1) {
+ if(packet->payload_packet_len > 20 && memcmp(packet->payload, "RIFF", 4) == 0
+ && memcmp(packet->payload + 8, "AVI LIST", 8) == 0) {
+ NDPI_LOG(NDPI_CONTENT_AVI, ndpi_struct, NDPI_LOG_DEBUG, "Avi content in http detected\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_CONTENT_AVI);
+ }
+ flow->l4.tcp.http_empty_line_seen = 0;
+ return;
+ }
+
+ if(packet->empty_line_position_set != 0) {
+ // check for avi header
+ // for reference see http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/htm/avirifffilereference.asp
+ u_int32_t p = packet->empty_line_position + 2;
+
+ NDPI_LOG(NDPI_CONTENT_AVI, ndpi_struct, NDPI_LOG_DEBUG, "p = %u\n", p);
+
+ if((p + 16) <= packet->payload_packet_len && memcmp(&packet->payload[p], "RIFF", 4) == 0
+ && memcmp(&packet->payload[p + 8], "AVI LIST", 8) == 0) {
+ NDPI_LOG(NDPI_CONTENT_AVI, ndpi_struct, NDPI_LOG_DEBUG, "Avi content in http detected\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_CONTENT_AVI);
+ }
+ }
+}
+#endif
+
+#ifdef NDPI_PROTOCOL_TEAMVIEWER
+static void teamviewer_check_http_payload(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ const u_int8_t *pos;
+
+ NDPI_LOG(NDPI_PROTOCOL_TEAMVIEWER, ndpi_struct, NDPI_LOG_DEBUG, "called teamviewer_check_http_payload: %u %u %u\n",
+ packet->empty_line_position_set, flow->l4.tcp.http_empty_line_seen, packet->empty_line_position);
+
+ if(packet->empty_line_position_set == 0 || (packet->empty_line_position + 5) > (packet->payload_packet_len))
+ return;
+
+ pos = &packet->payload[packet->empty_line_position] + 2;
+
+ if(pos[0] == 0x17 && pos[1] == 0x24) {
+ NDPI_LOG(NDPI_PROTOCOL_TEAMVIEWER, ndpi_struct, NDPI_LOG_DEBUG, "TeamViewer content in http detected\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TEAMVIEWER);
+ }
+}
+#endif
+
+
+#ifdef NDPI_PROTOCOL_RTSP
+static void rtsp_parse_packet_acceptline(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(packet->accept_line.len >= 28 && memcmp(packet->accept_line.ptr, "application/x-rtsp-tunnelled", 28) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_RTSP, ndpi_struct, NDPI_LOG_DEBUG, "RTSP accept line detected\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_RTSP);
+ }
+}
+#endif
+
+static void setHttpUserAgent(struct ndpi_flow_struct *flow, char *ua) {
+ if(!strcmp(ua, "Windows NT 5.0")) ua = "Windows 2000";
+ else if(!strcmp(ua, "Windows NT 5.1")) ua = "Windows XP";
+ else if(!strcmp(ua, "Windows NT 5.2")) ua = "Windows Server 2003";
+ else if(!strcmp(ua, "Windows NT 6.0")) ua = "Windows Vista";
+ // else if(!strcmp(ua, "Windows NT 7.0")) ua = "Windows 7";
+ else if(!strcmp(ua, "Windows NT 6.1")) ua = "Windows 7";
+ else if(!strcmp(ua, "Windows NT 6.2")) ua = "Windows 8";
+ else if(!strcmp(ua, "Windows NT 6.3")) ua = "Windows 8.1";
+
+ //printf("==> %s\n", ua);
+ snprintf((char*)flow->detected_os, sizeof(flow->detected_os), "%s", ua);
+}
+
+static void parseHttpSubprotocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ // int i = 0;
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(packet->iph /* IPv4 only */) {
+ /*
+ Twitter Inc. TWITTER-NETWORK (NET-199-59-148-0-1) 199.59.148.0 - 199.59.151.255
+ 199.59.148.0/22
+ */
+ if(((ntohl(packet->iph->saddr) & 0xFFFFFC00 /* 255.255.252.0 */) == 0xC73B9400 /* 199.59.148.0 */)
+ || ((ntohl(packet->iph->daddr) & 0xFFFFFC00 /* 255.255.252.0 */) == 0xC73B9400 /* 199.59.148.0 */)) {
+ packet->detected_protocol_stack[0] = NDPI_SERVICE_TWITTER;
+ return;
+ }
+
+ /*
+ CIDR: 69.53.224.0/19
+ OriginAS: AS2906
+ NetName: NETFLIX-INC
+ */
+ if(((ntohl(packet->iph->saddr) & 0xFFFFE000 /* 255.255.224.0 */) == 0x4535E000 /* 69.53.224.0 */)
+ || ((ntohl(packet->iph->daddr) & 0xFFFFE000 /* 255.255.224.0 */) == 0x4535E000 /* 69.53.224.0 */)) {
+ packet->detected_protocol_stack[0] = NDPI_SERVICE_NETFLIX;
+ return;
+ }
+ }
+
+ if((flow->l4.tcp.http_stage == 0)
+ || (flow->http.url && flow->http_detected)) {
+ /* Try matching subprotocols */
+ // ndpi_match_string_subprotocol(ndpi_struct, flow, (char*)packet->host_line.ptr, packet->host_line.len);
+
+ if(ndpi_struct->http_dissect_response) {
+ if(flow->http.url && flow->http_detected)
+ ndpi_match_string_subprotocol(ndpi_struct, flow, (char *)&flow->http.url[7], strlen((const char *)&flow->http.url[7]));
+ } else
+ ndpi_match_string_subprotocol(ndpi_struct, flow, (char *)flow->host_server_name, strlen((const char *)flow->host_server_name));
+ }
+}
+
+/*
+ NOTE
+
+ ndpi_parse_packet_line_info @ ndpi_main.c
+ is the code that parses the packet
+*/
+static void check_content_type_and_change_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+#ifdef NDPI_CONTENT_MPEG
+ struct ndpi_packet_struct *packet = &flow->packet;
+#endif
+#ifdef NDPI_CONTENT_AVI
+#endif
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ u_int8_t a;
+
+ if(ndpi_struct->http_dissect_response) {
+ if((flow->http.url == NULL)
+ && (packet->http_url_name.len > 0)
+ && (packet->host_line.len > 0)) {
+ int len = packet->http_url_name.len + packet->host_line.len + 7 + 1; /* "http://" */
+
+ flow->http.url = ndpi_malloc(len);
+ if(flow->http.url) {
+ strncpy(flow->http.url, "http://", 7);
+ strncpy(&flow->http.url[7], (char*)packet->host_line.ptr, packet->host_line.len);
+ strncpy(&flow->http.url[7+packet->host_line.len], (char*)packet->http_url_name.ptr,
+ packet->http_url_name.len);
+ flow->http.url[len-1] = '\0';
+ }
+
+ if(flow->packet.http_method.len < 3)
+ flow->http.method = HTTP_METHOD_UNKNOWN;
+ else {
+ switch(flow->packet.http_method.ptr[0]) {
+ case 'O': flow->http.method = HTTP_METHOD_OPTIONS; break;
+ case 'G': flow->http.method = HTTP_METHOD_GET; break;
+ case 'H': flow->http.method = HTTP_METHOD_HEAD; break;
+
+ case 'P':
+ switch(flow->packet.http_method.ptr[1]) {
+ case 'O': flow->http.method = HTTP_METHOD_POST; break;
+ case 'U': flow->http.method = HTTP_METHOD_PUT; break;
+ }
+ break;
+
+ case 'D': flow->http.method = HTTP_METHOD_DELETE; break;
+ case 'T': flow->http.method = HTTP_METHOD_TRACE; break;
+ case 'C': flow->http.method = HTTP_METHOD_CONNECT; break;
+ default:
+ flow->http.method = HTTP_METHOD_UNKNOWN;
+ break;
+ }
+ }
+ }
+
+ if((flow->http.content_type == NULL) && (packet->content_line.len > 0)) {
+ int len = packet->content_line.len + 1;
+
+ flow->http.content_type = ndpi_malloc(len);
+ if(flow->http.content_type) {
+ strncpy(flow->http.content_type, (char*)packet->content_line.ptr,
+ packet->content_line.len);
+ flow->http.content_type[packet->content_line.len] = '\0';
+ }
+ }
+ }
+
+ if(packet->user_agent_line.ptr != NULL && packet->user_agent_line.len != 0) {
+ /* Format:
+ Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) ....
+ */
+ if(packet->user_agent_line.len > 7) {
+ char ua[256];
+ u_int mlen = ndpi_min(packet->user_agent_line.len, sizeof(ua)-1);
+
+ strncpy(ua, (const char *)packet->user_agent_line.ptr, mlen);
+ ua[mlen] = '\0';
+
+ if(strncmp(ua, "Mozilla", 7) == 0) {
+ char *parent = strchr(ua, '(');
+
+ if(parent) {
+ char *token, *end;
+
+ parent++;
+ end = strchr(parent, ')');
+ if(end) end[0] = '\0';
+
+ token = strsep(&parent, ";");
+ if(token) {
+ if((strcmp(token, "X11") == 0)
+ || (strcmp(token, "compatible") == 0)
+ || (strcmp(token, "Linux") == 0)
+ || (strcmp(token, "Macintosh") == 0)
+ ) {
+ token = strsep(&parent, ";");
+ if(token && (token[0] == ' ')) token++; /* Skip space */
+
+ if(token
+ && ((strcmp(token, "U") == 0)
+ || (strncmp(token, "MSIE", 4) == 0))) {
+ token = strsep(&parent, ";");
+ if(token && (token[0] == ' ')) token++; /* Skip space */
+
+ if(token && (strncmp(token, "Update", 6) == 0)) {
+ token = strsep(&parent, ";");
+
+ if(token && (token[0] == ' ')) token++; /* Skip space */
+
+ if(token && (strncmp(token, "AOL", 3) == 0)) {
+ token = strsep(&parent, ";");
+
+ if(token && (token[0] == ' ')) token++; /* Skip space */
+ }
+ }
+ }
+ }
+
+ if(token)
+ setHttpUserAgent(flow, token);
+ }
+ }
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "User Agent Type Line found %.*s\n",
+ packet->user_agent_line.len, packet->user_agent_line.ptr);
+
+ if((!ndpi_struct->http_dissect_response) || flow->http_detected)
+ ndpi_match_content_subprotocol(ndpi_struct, flow,
+ (char*)packet->user_agent_line.ptr,
+ packet->user_agent_line.len);
+ }
+
+ /* check for host line */
+ if(packet->host_line.ptr != NULL) {
+ u_int len;
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HOST Line found %.*s\n",
+ packet->host_line.len, packet->host_line.ptr);
+
+ if((!ndpi_struct->http_dissect_response) || flow->http_detected)
+ ndpi_match_content_subprotocol(ndpi_struct, flow,
+ (char*)packet->host_line.ptr,
+ packet->host_line.len);
+
+ /* Copy result for nDPI apps */
+ len = ndpi_min(packet->host_line.len, sizeof(flow->host_server_name)-1);
+ strncpy((char*)flow->host_server_name, (char*)packet->host_line.ptr, len);
+ flow->host_server_name[len] = '\0', flow->server_id = flow->dst;
+
+ len = ndpi_min(packet->forwarded_line.len, sizeof(flow->nat_ip)-1);
+ strncpy((char*)flow->nat_ip, (char*)packet->forwarded_line.ptr, len);
+ flow->nat_ip[len] = '\0';
+
+ if(!ndpi_struct->http_dissect_response)
+ parseHttpSubprotocol(ndpi_struct, flow);
+
+ if((flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN)
+ && ((!ndpi_struct->http_dissect_response) || flow->http_detected))
+ ndpi_match_string_subprotocol(ndpi_struct, flow,
+ (char *)flow->host_server_name,
+ strlen((const char *)flow->host_server_name));
+
+ if((flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN)
+ && ((!ndpi_struct->http_dissect_response) || flow->http_detected)
+ && (packet->http_origin.len > 0))
+ ndpi_match_string_subprotocol(ndpi_struct, flow,
+ (char *)packet->http_origin.ptr,
+ packet->http_origin.len);
+
+ if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) {
+ if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_HTTP) {
+ ndpi_int_http_add_connection(ndpi_struct, flow, packet->detected_protocol_stack[0]);
+ return; /* We have identified a sub-protocol so we're done */
+ }
+ }
+ }
+
+ if(ndpi_struct->http_dissect_response && flow->http_detected)
+ parseHttpSubprotocol(ndpi_struct, flow);
+
+ /* check for accept line */
+ if(packet->accept_line.ptr != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "Accept Line found %.*s\n",
+ packet->accept_line.len, packet->accept_line.ptr);
+#ifdef NDPI_PROTOCOL_RTSP
+ if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_RTSP) != 0) {
+ rtsp_parse_packet_acceptline(ndpi_struct, flow);
+ }
+#endif
+ }
+
+ /* search for line startin with "Icy-MetaData" */
+#ifdef NDPI_CONTENT_MPEG
+ for (a = 0; a < packet->parsed_lines; a++) {
+ if(packet->line[a].len > 11 && memcmp(packet->line[a].ptr, "Icy-MetaData", 12) == 0) {
+ NDPI_LOG(NDPI_CONTENT_MPEG, ndpi_struct, NDPI_LOG_DEBUG, "MPEG: Icy-MetaData found.\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_CONTENT_MPEG);
+ return;
+ }
+ }
+#ifdef NDPI_CONTENT_AVI
+#endif
+#endif
+
+ if(packet->content_line.ptr != NULL && packet->content_line.len != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "Content Type Line found %.*s\n",
+ packet->content_line.len, packet->content_line.ptr);
+
+ if((!ndpi_struct->http_dissect_response) || flow->http_detected)
+ ndpi_match_content_subprotocol(ndpi_struct, flow, (char*)packet->content_line.ptr, packet->content_line.len);
+ }
+
+ /* check user agent here too */
+}
+
+static void check_http_payload(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "called check_http_payload.\n");
+
+#ifdef NDPI_CONTENT_FLASH
+ if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_CONTENT_FLASH) != 0)
+ flash_check_http_payload(ndpi_struct, flow);
+#endif
+#ifdef NDPI_CONTENT_AVI
+ if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_CONTENT_AVI) != 0)
+ avi_check_http_payload(ndpi_struct, flow);
+#endif
+#ifdef NDPI_PROTOCOL_TEAMVIEWER
+ teamviewer_check_http_payload(ndpi_struct, flow);
+#endif
+
+}
+
+/**
+ * this functions checks whether the packet begins with a valid http request
+ * @param ndpi_struct
+ * @returnvalue 0 if no valid request has been found
+ * @returnvalue >0 indicates start of filename but not necessarily in packet limit
+ */
+static u_int16_t http_request_url_offset(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "====>>>> HTTP: %c%c%c%c [len: %u]\n",
+ packet->payload[0], packet->payload[1], packet->payload[2], packet->payload[3],
+ packet->payload_packet_len);
+
+ /* FIRST PAYLOAD PACKET FROM CLIENT */
+ /* check if the packet starts with POST or GET */
+ if(packet->payload_packet_len >= 4 && memcmp(packet->payload, "GET ", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP: GET FOUND\n");
+ return 4;
+ } else if(packet->payload_packet_len >= 5 && memcmp(packet->payload, "POST ", 5) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP: POST FOUND\n");
+ return 5;
+ } else if(packet->payload_packet_len >= 8 && memcmp(packet->payload, "OPTIONS ", 8) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP: OPTIONS FOUND\n");
+ return 8;
+ } else if(packet->payload_packet_len >= 5 && memcmp(packet->payload, "HEAD ", 5) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP: HEAD FOUND\n");
+ return 5;
+ } else if(packet->payload_packet_len >= 4 && memcmp(packet->payload, "PUT ", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP: PUT FOUND\n");
+ return 4;
+ } else if(packet->payload_packet_len >= 7 && memcmp(packet->payload, "DELETE ", 7) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP: DELETE FOUND\n");
+ return 7;
+ } else if(packet->payload_packet_len >= 8 && memcmp(packet->payload, "CONNECT ", 8) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP: CONNECT FOUND\n");
+ return 8;
+ } else if(packet->payload_packet_len >= 9 && memcmp(packet->payload, "PROPFIND ", 9) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP: PROFIND FOUND\n");
+ return 9;
+ } else if(packet->payload_packet_len >= 7 && memcmp(packet->payload, "REPORT ", 7) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP: REPORT FOUND\n");
+ return 7;
+ }
+
+ return 0;
+}
+
+static void http_bitmask_exclude(struct ndpi_flow_struct *flow)
+{
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_HTTP);
+#ifdef NDPI_PROTOCOL_WINDOWS_UPDATE
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_WINDOWS_UPDATE);
+#endif
+#ifdef NDPI_CONTENT_MPEG
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_MPEG);
+#endif
+#ifdef NDPI_CONTENT_QUICKTIME
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_QUICKTIME);
+#endif
+#ifdef NDPI_CONTENT_WINDOWSMEDIA
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_WINDOWSMEDIA);
+#endif
+#ifdef NDPI_CONTENT_REALMEDIA
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_REALMEDIA);
+#endif
+#ifdef NDPI_CONTENT_AVI
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_AVI);
+#endif
+#ifdef NDPI_CONTENT_OGG
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_OGG);
+#endif
+#ifdef NDPI_PROTOCOL_MOVE
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MOVE);
+#endif
+#ifdef NDPI_PROTOCOL_XBOX
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_XBOX);
+#endif
+}
+
+void _org_ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ u_int16_t filename_start;
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "search http\n");
+
+ /* set client-server_direction */
+ if(flow->l4.tcp.http_setup_dir == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "initializes http to stage: 1 \n");
+ flow->l4.tcp.http_setup_dir = 1 + packet->packet_direction;
+ }
+
+ if(NDPI_COMPARE_PROTOCOL_TO_BITMASK
+ (ndpi_struct->generic_http_packet_bitmask, packet->detected_protocol_stack[0]) != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "protocol might be detected earlier as http jump to payload type detection\n");
+ goto http_parse_detection;
+ }
+
+ if(flow->l4.tcp.http_setup_dir == 1 + packet->packet_direction) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "http stage: 1\n");
+
+ if(flow->l4.tcp.http_wait_for_retransmission) {
+ if(!packet->tcp_retransmission) {
+ if(flow->packet_counter <= 5) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "still waiting for retransmission\n");
+ return;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "retransmission not found, exclude\n");
+ http_bitmask_exclude(flow);
+ return;
+ }
+ }
+ }
+
+ if(flow->l4.tcp.http_stage == 0) {
+ filename_start = http_request_url_offset(ndpi_struct, flow);
+ if(filename_start == 0) {
+ if(packet->payload_packet_len >= 7 && memcmp(packet->payload, "HTTP/1.", 7) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP response found (truncated flow ?)\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "filename not found, exclude\n");
+ http_bitmask_exclude(flow);
+ return;
+ }
+ // parse packet
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if(packet->parsed_lines <= 1) {
+ /* parse one more packet .. */
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "just one line, search next packet\n");
+
+ packet->http_method.ptr = packet->line[0].ptr;
+ packet->http_method.len = filename_start - 1;
+ flow->l4.tcp.http_stage = 1;
+ return;
+ }
+ // parsed_lines > 1 here
+ if(packet->line[0].len >= (9 + filename_start)
+ && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) {
+ u_int16_t proto_id;
+
+ packet->http_url_name.ptr = &packet->payload[filename_start];
+ packet->http_url_name.len = packet->line[0].len - (filename_start + 9);
+
+ packet->http_method.ptr = packet->line[0].ptr;
+ packet->http_method.len = filename_start - 1;
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "http structure detected, adding\n");
+
+ if(filename_start == 8 && (memcmp(packet->payload, "CONNECT ", 8) == 0)) /* nathan@getoffmalawn.com */
+ proto_id = NDPI_PROTOCOL_HTTP_CONNECT;
+ else {
+ if((packet->http_url_name.len > 7) && (!strncmp((const char*)packet->http_url_name.ptr, "http://", 7)))
+ proto_id = NDPI_PROTOCOL_HTTP_PROXY;
+ else {
+ proto_id = NDPI_PROTOCOL_HTTP;
+ }
+ }
+
+ ndpi_int_http_add_connection(ndpi_struct, flow, proto_id);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+ /* HTTP found, look for host... */
+ if(packet->host_line.ptr != NULL) {
+ /* aaahh, skip this direction and wait for a server reply here */
+ flow->l4.tcp.http_stage = 2;
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP START HOST found\n");
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP START HOST found\n");
+
+ /* host not found, check in next packet after */
+ flow->l4.tcp.http_stage = 1;
+ return;
+ }
+ } else if(flow->l4.tcp.http_stage == 1) {
+ /* SECOND PAYLOAD TRAFFIC FROM CLIENT, FIRST PACKET MIGHT HAVE BEEN HTTP... */
+ /* UNKNOWN TRAFFIC, HERE FOR HTTP again.. */
+ // parse packet
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if(packet->parsed_lines <= 1) {
+ /* wait some packets in case request is split over more than 2 packets */
+ if(flow->packet_counter < 5) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "line still not finished, search next packet\n");
+ return;
+ } else {
+ /* stop parsing here */
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "HTTP: PACKET DOES NOT HAVE A LINE STRUCTURE\n");
+ http_bitmask_exclude(flow);
+ return;
+ }
+ }
+ // http://www.slideshare.net/DSPIP/rtsp-analysis-wireshark
+ if(packet->line[0].len >= 9 && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) {
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "HTTP START HTTP found in 2. packet, check host here...\n");
+ /* HTTP found, look for host... */
+ flow->l4.tcp.http_stage = 2;
+
+ return;
+ }
+ }
+ } else {
+ /* We have received a response for a previously identified partial HTTP request */
+
+ if((packet->parsed_lines == 1) && (packet->packet_direction == 1 /* server -> client */)) {
+ /*
+ In apache if you do "GET /\n\n" the response comes without any header so we can assume that
+ this can be the case
+ */
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
+ return;
+ }
+
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP: REQUEST NOT HTTP CONFORM\n");
+ http_bitmask_exclude(flow);
+ return;
+
+ http_parse_detection:
+ if(flow->l4.tcp.http_setup_dir == 1 + packet->packet_direction) {
+ /* we have something like http here, so check for host and content type if possible */
+ if(flow->l4.tcp.http_stage == 0 || flow->l4.tcp.http_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP RUN MAYBE NEXT GET/POST...\n");
+ // parse packet
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ /* check for url here */
+ filename_start = http_request_url_offset(ndpi_struct, flow);
+ if(filename_start != 0 && packet->parsed_lines > 1 && packet->line[0].len >= (9 + filename_start)
+ && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) {
+ packet->http_url_name.ptr = &packet->payload[filename_start];
+ packet->http_url_name.len = packet->line[0].len - (filename_start + 9);
+
+ packet->http_method.ptr = packet->line[0].ptr;
+ packet->http_method.len = filename_start - 1;
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "next http action, "
+ "resetting to http and search for other protocols later.\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
+ }
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+ /* HTTP found, look for host... */
+ if(packet->host_line.ptr != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "HTTP RUN MAYBE NEXT HOST found, skipping all packets from this direction\n");
+ /* aaahh, skip this direction and wait for a server reply here */
+ flow->l4.tcp.http_stage = 2;
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "HTTP RUN MAYBE NEXT HOST NOT found, scanning one more packet from this direction\n");
+ flow->l4.tcp.http_stage = 1;
+ } else if(flow->l4.tcp.http_stage == 1) {
+ // parse packet and maybe find a packet info with host ptr,...
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP RUN second packet scanned\n");
+ /* HTTP found, look for host... */
+ flow->l4.tcp.http_stage = 2;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "HTTP skipping client packets after second packet\n");
+ return;
+ }
+ /* server response */
+ if(flow->l4.tcp.http_stage > 0) {
+ /* first packet from server direction, might have a content line */
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+
+ if(packet->empty_line_position_set != 0 || flow->l4.tcp.http_empty_line_seen == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "empty line. check_http_payload.\n");
+ check_http_payload(ndpi_struct, flow);
+ }
+
+ if(flow->l4.tcp.http_stage == 2) {
+ flow->l4.tcp.http_stage = 3;
+ } else {
+ flow->l4.tcp.http_stage = 0;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "HTTP response first or second packet scanned,new stage is: %u\n", flow->l4.tcp.http_stage);
+ return;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP response next packet skipped\n");
+ }
+}
+
+/*************************************************************************************************/
+
+static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t filename_start;
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->l4.tcp.http_stage == 0) {
+ flow->http_detected = 0;
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP stage %d: \n",
+ flow->l4.tcp.http_stage);
+
+ filename_start = http_request_url_offset(ndpi_struct, flow);
+
+
+ if (filename_start == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "Filename HTTP not found, we look for possible truncate flow...\n");
+ if (packet->payload_packet_len >= 7 && memcmp(packet->payload, "HTTP/1.", 7) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "HTTP response found (truncated flow ?)\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "Exclude HTTP\n");
+ http_bitmask_exclude(flow);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "Filename HTTP found: %d, we look for line info..\n", filename_start);
+
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if (packet->parsed_lines <= 1) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "Found just one line, we will look further for the next packet...\n");
+
+ packet->http_method.ptr = packet->line[0].ptr;
+ packet->http_method.len = filename_start - 1;
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->l4.tcp.http_stage = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "Found more than one line, we look further for the next packet...\n");
+
+ if(packet->line[0].len >= (9 + filename_start)
+ && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) {
+
+ packet->http_url_name.ptr = &packet->payload[filename_start];
+ packet->http_url_name.len = packet->line[0].len - (filename_start + 9);
+
+ packet->http_method.ptr = packet->line[0].ptr;
+ packet->http_method.len = filename_start - 1;
+
+ if((packet->http_url_name.len > 7)
+ && (!strncmp((const char*) packet->http_url_name.ptr, "http://", 7))) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP_PROXY Found.\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP_PROXY);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+ }
+
+ if(filename_start == 8 && (memcmp(packet->payload, "CONNECT ", 8) == 0)) /* nathan@getoffmalawn.com */
+ {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP_CONNECT Found.\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP_CONNECT);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "HTTP START Found, we will look for sub-protocols (content and host)...\n");
+
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+
+ if(packet->host_line.ptr != NULL) {
+ /*
+ nDPI is pretty scrupoulous about HTTP so it waits until the
+ HTTP response is received just to check that it conforms
+ with the HTTP specs. However this might be a waste of time as
+ in 99.99% of the cases is like that.
+ */
+
+ if(!ndpi_struct->http_dissect_response) {
+ if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) /* No subprotocol found */
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
+ } else {
+ flow->http_detected = 1;
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "HTTP START Found, we will look further for the response...\n");
+ flow->l4.tcp.http_stage = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
+ }
+
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP: REQUEST NOT HTTP CONFORM\n");
+ http_bitmask_exclude(flow);
+ } else if ((flow->l4.tcp.http_stage == 1) || (flow->l4.tcp.http_stage == 2)) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP stage %u: \n",
+ flow->l4.tcp.http_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, if http is detected do nothing now and return,
+ * otherwise check the second packet for the http request . */
+ if ((flow->l4.tcp.http_stage - packet->packet_direction) == 1) {
+
+ if (flow->http_detected)
+ return;
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ " SECOND PAYLOAD TRAFFIC FROM CLIENT, FIRST PACKET MIGHT HAVE BEEN HTTP...UNKNOWN TRAFFIC, HERE FOR HTTP again.. \n");
+
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if (packet->parsed_lines <= 1) {
+ /* wait some packets in case request is split over more than 2 packets */
+ if (flow->packet_counter < 5) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "line still not finished, search next packet\n");
+ return;
+ } else {
+ /* stop parsing here */
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "HTTP: PACKET DOES NOT HAVE A LINE STRUCTURE\n");
+ http_bitmask_exclude(flow);
+ return;
+ }
+ }
+ // http://www.slideshare.net/DSPIP/rtsp-analysis-wireshark
+ if (packet->line[0].len >= 9
+ && memcmp(&packet->line[0].ptr[packet->line[0].len - 9], " HTTP/1.", 8) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "Found HTTP.\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "HTTP START Found in 2. packet, we will look further for the response....\n");
+ flow->http_detected = 1;
+ }
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ /* We have received a response for a previously identified partial HTTP request */
+
+ if ((packet->parsed_lines == 1) && (packet->packet_direction == 1 /* server -> client */)) {
+ /*
+ In apache if you do "GET /\n\n" the response comes without any header so we can assume that
+ this can be the case
+ */
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "Found HTTP. (apache)\n");
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+ return;
+ }
+
+ /* If we already detected the http request, we can add the connection and then check for the sub-protocol*/
+ if (flow->http_detected)
+ ndpi_int_http_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP);
+
+ /* Parse packet line and we look for the subprotocols */
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ check_content_type_and_change_protocol(ndpi_struct, flow);
+
+ if (packet->empty_line_position_set != 0 || flow->l4.tcp.http_empty_line_seen == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "empty line. check_http_payload.\n");
+ check_http_payload(ndpi_struct, flow);
+ }
+
+ flow->l4.tcp.http_stage = 0;
+ return;
+ }
+
+}
+
+void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ /* Break after 20 packets. */
+ if (flow->packet_counter > 20) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "Exclude HTTP.\n");
+ http_bitmask_exclude(flow);
+ return;
+ }
+
+ if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) {
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP, ndpi_struct, NDPI_LOG_DEBUG, "HTTP detection...\n");
+ ndpi_check_http_tcp(ndpi_struct, flow);
+}
+
+/* ********************************* */
+
+ndpi_http_method ndpi_get_http_method(struct ndpi_detection_module_struct *ndpi_mod,
+ struct ndpi_flow_struct *flow) {
+ if(!flow)
+ return(HTTP_METHOD_UNKNOWN);
+ else
+ return(flow->http.method);
+}
+
+/* ********************************* */
+
+char* ndpi_get_http_url(struct ndpi_detection_module_struct *ndpi_mod,
+ struct ndpi_flow_struct *flow) {
+ if((!flow) || (!flow->http.url))
+ return("");
+ else
+ return(flow->http.url);
+}
+
+/* ********************************* */
+
+char* ndpi_get_http_content_type(struct ndpi_detection_module_struct *ndpi_mod,
+ struct ndpi_flow_struct *flow) {
+ if((!flow) || (!flow->http.content_type))
+ return("");
+ else
+ return(flow->http.content_type);
+}
+
+#endif
diff --git a/src/lib/protocols/http_activesync.c b/src/lib/protocols/http_activesync.c
new file mode 100644
index 000000000..fd115ced6
--- /dev/null
+++ b/src/lib/protocols/http_activesync.c
@@ -0,0 +1,54 @@
+/*
+ * http_activesync.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_HTTP_APPLICATION_ACTIVESYNC
+static void ndpi_int_activesync_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP_APPLICATION_ACTIVESYNC, NDPI_CORRELATED_PROTOCOL);
+}
+
+void ndpi_search_activesync(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if (packet->tcp != NULL) {
+
+ if (packet->payload_packet_len > 150
+ && ((memcmp(packet->payload, "OPTIONS /Microsoft-Server-ActiveSync?", 37) == 0)
+ || (memcmp(packet->payload, "POST /Microsoft-Server-ActiveSync?", 34) == 0))) {
+ ndpi_int_activesync_add_connection(ndpi_struct, flow);
+ NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_ACTIVESYNC, ndpi_struct, NDPI_LOG_DEBUG,
+ " flow marked as ActiveSync \n");
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_ACTIVESYNC, ndpi_struct, NDPI_LOG_DEBUG, "exclude activesync\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_HTTP_APPLICATION_ACTIVESYNC);
+
+}
+#endif
diff --git a/src/lib/protocols/iax.c b/src/lib/protocols/iax.c
new file mode 100644
index 000000000..d7a01b51c
--- /dev/null
+++ b/src/lib/protocols/iax.c
@@ -0,0 +1,94 @@
+/*
+ * iax.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_IAX
+
+#define NDPI_IAX_MAX_INFORMATION_ELEMENTS 15
+
+static void ndpi_int_iax_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_IAX, NDPI_REAL_PROTOCOL);
+}
+
+static void ndpi_search_setup_iax(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int8_t i;
+ u_int16_t packet_len;
+
+ if ( /* 1. iax is udp based, port 4569 */
+ (packet->udp->source == htons(4569) || packet->udp->dest == htons(4569))
+ /* check for iax new packet */
+ && packet->payload_packet_len >= 12
+ /* check for dst call id == 0, do not check for highest bit (packet retransmission) */
+ // && (ntohs(get_u_int16_t(packet->payload, 2)) & 0x7FFF) == 0
+ /* check full IAX packet */
+ && (packet->payload[0] & 0x80) != 0
+ /* outbound seq == 0 */
+ && packet->payload[8] == 0
+ /* inbound seq == 0 || 1 */
+ && (packet->payload[9] == 0 || packet->payload[9] == 0x01)
+ /* */
+ && packet->payload[10] == 0x06
+ /* IAX type: 0-15 */
+ && packet->payload[11] <= 15) {
+
+ if (packet->payload_packet_len == 12) {
+ NDPI_LOG(NDPI_PROTOCOL_IAX, ndpi_struct, NDPI_LOG_DEBUG, "found IAX.\n");
+ ndpi_int_iax_add_connection(ndpi_struct, flow);
+ return;
+ }
+ packet_len = 12;
+ for (i = 0; i < NDPI_IAX_MAX_INFORMATION_ELEMENTS; i++) {
+ packet_len = packet_len + 2 + packet->payload[packet_len + 1];
+ if (packet_len == packet->payload_packet_len) {
+ NDPI_LOG(NDPI_PROTOCOL_IAX, ndpi_struct, NDPI_LOG_DEBUG, "found IAX.\n");
+ ndpi_int_iax_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet_len > packet->payload_packet_len) {
+ break;
+ }
+ }
+
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_IAX);
+
+}
+
+void ndpi_search_iax(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // struct ndpi_flow_struct *flow=ndpi_struct->flow;
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if(packet->udp
+ && (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN))
+ ndpi_search_setup_iax(ndpi_struct, flow);
+}
+#endif
diff --git a/src/lib/protocols/icecast.c b/src/lib/protocols/icecast.c
new file mode 100644
index 000000000..49c6f5fc5
--- /dev/null
+++ b/src/lib/protocols/icecast.c
@@ -0,0 +1,91 @@
+/*
+ * icecast.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_ICECAST
+
+static void ndpi_int_icecast_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_ICECAST, NDPI_CORRELATED_PROTOCOL);
+}
+
+void ndpi_search_icecast_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int8_t i;
+
+ NDPI_LOG(NDPI_PROTOCOL_ICECAST, ndpi_struct, NDPI_LOG_DEBUG, "search icecast.\n");
+
+ if ((packet->payload_packet_len < 500 &&
+ packet->payload_packet_len >= 7 && memcmp(packet->payload, "SOURCE ", 7) == 0)
+ || flow->l4.tcp.icecast_stage) {
+ ndpi_parse_packet_line_info_any(ndpi_struct, flow);
+ NDPI_LOG(NDPI_PROTOCOL_ICECAST, ndpi_struct, NDPI_LOG_DEBUG, "Icecast lines=%d\n", packet->parsed_lines);
+ for (i = 0; i < packet->parsed_lines; i++) {
+ if (packet->line[i].ptr != NULL && packet->line[i].len > 4
+ && memcmp(packet->line[i].ptr, "ice-", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_ICECAST, ndpi_struct, NDPI_LOG_DEBUG, "Icecast detected.\n");
+ ndpi_int_icecast_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ if (packet->parsed_lines < 1 && !flow->l4.tcp.icecast_stage) {
+ flow->l4.tcp.icecast_stage = 1;
+ return;
+ }
+ }
+#ifdef NDPI_PROTOCOL_HTTP
+ if (NDPI_FLOW_PROTOCOL_EXCLUDED(ndpi_struct, flow, NDPI_PROTOCOL_HTTP)) {
+ goto icecast_exclude;
+ }
+#endif
+
+ if (packet->packet_direction == flow->setup_packet_direction && flow->packet_counter < 10) {
+ return;
+ }
+
+ if (packet->packet_direction != flow->setup_packet_direction) {
+ /* server answer, now test Server for Icecast */
+
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if (packet->server_line.ptr != NULL && packet->server_line.len > NDPI_STATICSTRING_LEN("Icecast") &&
+ memcmp(packet->server_line.ptr, "Icecast", NDPI_STATICSTRING_LEN("Icecast")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_ICECAST, ndpi_struct, NDPI_LOG_DEBUG, "Icecast detected.\n");
+ /* TODO maybe store the previous protocol type as subtype?
+ * e.g. ogg or mpeg
+ */
+ ndpi_int_icecast_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ icecast_exclude:
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_ICECAST);
+ NDPI_LOG(NDPI_PROTOCOL_ICECAST, ndpi_struct, NDPI_LOG_DEBUG, "Icecast excluded.\n");
+}
+#endif
diff --git a/src/lib/protocols/imesh.c b/src/lib/protocols/imesh.c
new file mode 100644
index 000000000..1e2238fca
--- /dev/null
+++ b/src/lib/protocols/imesh.c
@@ -0,0 +1,294 @@
+/*
+ * imesh.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_IMESH
+
+
+static void ndpi_int_imesh_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_IMESH, protocol_type);
+}
+
+
+void ndpi_search_imesh_tcp_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if (packet->udp != NULL) {
+
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "UDP FOUND\n");
+
+ // this is the login packet
+ if (packet->payload_packet_len == 28 && (get_u_int32_t(packet->payload, 0)) == htonl(0x02000000) &&
+ get_u_int32_t(packet->payload, 24) == 0 &&
+ (packet->udp->dest == htons(1864) || packet->udp->source == htons(1864))) {
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "iMesh Login detected\n");
+ ndpi_int_imesh_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 36) {
+ if (get_u_int32_t(packet->payload, 0) == htonl(0x02000000) && packet->payload[4] != 0 &&
+ packet->payload[5] == 0 && get_u_int16_t(packet->payload, 6) == htons(0x0083) &&
+ get_u_int32_t(packet->payload, 24) == htonl(0x40000000) &&
+ (packet->payload[packet->payload_packet_len - 1] == packet->payload[packet->payload_packet_len - 5] ||
+ packet->payload[packet->payload_packet_len - 1] - 1 == packet->payload[packet->payload_packet_len - 5]
+ || packet->payload[packet->payload_packet_len - 1] ==
+ packet->payload[packet->payload_packet_len - 5] - 1)) {
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "iMesh detected\n");
+ ndpi_int_imesh_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (get_u_int16_t(packet->payload, 0) == htons(0x0200) && get_u_int16_t(packet->payload, 2) != 0 &&
+ get_u_int32_t(packet->payload, 4) == htonl(0x02000083) && get_u_int32_t(packet->payload, 24) == htonl(0x40000000) &&
+ (packet->payload[packet->payload_packet_len - 1] == packet->payload[packet->payload_packet_len - 5] ||
+ packet->payload[packet->payload_packet_len - 1] - 1 == packet->payload[packet->payload_packet_len - 5]
+ || packet->payload[packet->payload_packet_len - 1] ==
+ packet->payload[packet->payload_packet_len - 5] - 1)) {
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "iMesh detected\n");
+ ndpi_int_imesh_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ if (packet->payload_packet_len == 24 && get_u_int16_t(packet->payload, 0) == htons(0x0200)
+ && get_u_int16_t(packet->payload, 2) != 0 && get_u_int32_t(packet->payload, 4) == htonl(0x03000084) &&
+ (packet->payload[packet->payload_packet_len - 1] == packet->payload[packet->payload_packet_len - 5] ||
+ packet->payload[packet->payload_packet_len - 1] - 1 == packet->payload[packet->payload_packet_len - 5] ||
+ packet->payload[packet->payload_packet_len - 1] == packet->payload[packet->payload_packet_len - 5] - 1)) {
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "iMesh detected\n");
+ ndpi_int_imesh_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 32 && get_u_int32_t(packet->payload, 0) == htonl(0x02000000) &&
+ get_u_int16_t(packet->payload, 21) == 0 && get_u_int16_t(packet->payload, 26) == htons(0x0100)) {
+ if (get_u_int32_t(packet->payload, 4) == htonl(0x00000081) && packet->payload[11] == packet->payload[15] &&
+ get_l16(packet->payload, 24) == htons(packet->udp->source)) {
+ /* packet->payload[28] = source address */
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "iMesh detected\n");
+ ndpi_int_imesh_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (get_u_int32_t(packet->payload, 4) == htonl(0x01000082)) {
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "iMesh detected\n");
+ ndpi_int_imesh_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "iMesh UDP packetlen: %d\n",
+ packet->payload_packet_len);
+
+ }
+
+ if (packet->tcp != NULL) {
+ if (packet->payload_packet_len == 64 && get_u_int32_t(packet->payload, 0) == htonl(0x40000000) &&
+ get_u_int32_t(packet->payload, 4) == 0 && get_u_int32_t(packet->payload, 8) == htonl(0x0000fcff) &&
+ get_u_int32_t(packet->payload, 12) == htonl(0x04800100) && get_u_int32_t(packet->payload, 45) == htonl(0xff020000) &&
+ get_u_int16_t(packet->payload, 49) == htons(0x001a)) {
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "found imesh.\n");
+ ndpi_int_imesh_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 95 && get_u_int32_t(packet->payload, 0) == htonl(0x5f000000) &&
+ get_u_int16_t(packet->payload, 4) == 0 && get_u_int16_t(packet->payload, 7) == htons(0x0004) &&
+ get_u_int32_t(packet->payload, 20) == 0 && get_u_int32_t(packet->payload, 28) == htonl(0xc8000400) &&
+ packet->payload[9] == 0x80 && get_u_int32_t(packet->payload, 10) == get_u_int32_t(packet->payload, 24)) {
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "found imesh.\n");
+ ndpi_int_imesh_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 28 && get_u_int32_t(packet->payload, 0) == htonl(0x1c000000) &&
+ get_u_int16_t(packet->payload, 10) == htons(0xfcff) && get_u_int32_t(packet->payload, 12) == htonl(0x07801800) &&
+ (get_u_int16_t(packet->payload, packet->payload_packet_len - 2) == htons(0x1900) ||
+ get_u_int16_t(packet->payload, packet->payload_packet_len - 2) == htons(0x1a00))) {
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "found imesh.\n");
+ ndpi_int_imesh_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "TCP FOUND :: Payload %u\n",
+ packet->payload_packet_len);
+
+ if (packet->actual_payload_len == 0) {
+ return;
+ }
+ if ((packet->actual_payload_len == 8 || packet->payload_packet_len == 10) /* PATTERN:: 04 00 00 00 00 00 00 00 [00 00] */
+ &&get_u_int32_t(packet->payload, 0) == htonl(0x04000000)
+ && get_u_int32_t(packet->payload, 4) == 0) {
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if (packet->actual_payload_len == 10 /* PATTERN:: ?? ?? 04|00 00 64|00 00 */
+ && (packet->payload[2] == 0x04 || packet->payload[2] == 0x00)
+ && packet->payload[3] == 0x00 && (packet->payload[4] == 0x00 || packet->payload[4] == 0x64)
+ && packet->payload[5] == 0x00
+ && (packet->payload[2] != packet->payload[4]) /* We do not want that the packet is ?? ?? 00 00 00 00 */
+ ) {
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if (packet->actual_payload_len == 2 && packet->payload[0] == 0x06 && packet->payload[1] == 0x00) {
+ flow->l4.tcp.imesh_stage++;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if (packet->actual_payload_len == 10 /* PATTERN:: 06 00 04|00 00 01|00 00 01|00 00 ?? 00 */
+ && packet->payload[0] == 0x06
+ && packet->payload[1] == 0x00 && (packet->payload[2] == 0x04 || packet->payload[2] == 0x00)
+ && packet->payload[3] == 0x00 && (packet->payload[4] == 0x00 || packet->payload[4] == 0x01)
+ && packet->payload[5] == 0x00 && (packet->payload[6] == 0x01 || packet->payload[6] == 0x00)
+ && packet->payload[7] == 0x00 && packet->payload[9] == 0x00
+ && (packet->payload[2] || packet->payload[4] || packet->payload[6]) /* We do not want that the packet is all 06 00 00 ... */
+ ) {
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if (packet->actual_payload_len == 24 && packet->payload[0] == 0x06 // PATTERN :: 06 00 12 00 00 00 34 00 00
+ && packet->payload[1] == 0x00
+ && packet->payload[2] == 0x12
+ && packet->payload[3] == 0x00
+ && packet->payload[4] == 0x00
+ && packet->payload[5] == 0x00
+ && packet->payload[6] == 0x34 && packet->payload[7] == 0x00 && packet->payload[8] == 0x00) {
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if (packet->actual_payload_len == 8 /* PATTERN:: 06|00 00 02 00 00 00 33 00 */
+ && (packet->payload[0] == 0x06 || packet->payload[0] == 0x00)
+ && packet->payload[1] == 0x00
+ && packet->payload[2] == 0x02
+ && packet->payload[3] == 0x00
+ && packet->payload[4] == 0x00
+ && packet->payload[5] == 0x00 && packet->payload[6] == 0x33 && packet->payload[7] == 0x00) {
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if (packet->payload_packet_len == 6 /* PATTERN:: 02 00 00 00 33 00 */
+ && packet->payload[0] == 0x02
+ && packet->payload[1] == 0x00
+ && packet->payload[2] == 0x00
+ && packet->payload[3] == 0x00 && packet->payload[4] == 0x33 && packet->payload[5] == 0x00) {
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if (packet->actual_payload_len == 12 && packet->payload[0] == 0x06 // PATTERN : 06 00 06 00 00 00 64 00
+ && packet->payload[1] == 0x00
+ && packet->payload[2] == 0x06
+ && packet->payload[3] == 0x00
+ && packet->payload[4] == 0x00
+ && packet->payload[5] == 0x00 && packet->payload[6] == 0x64 && packet->payload[7] == 0x00) {
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if (packet->actual_payload_len == 10 /* PATTERN:: 06 00 04|01 00 00 00 01|00 00 ?? 00 */
+ && packet->payload[0] == 0x06
+ && packet->payload[1] == 0x00 && (packet->payload[2] == 0x04 || packet->payload[2] == 0x01)
+ && packet->payload[3] == 0x00
+ && packet->payload[4] == 0x00
+ && packet->payload[5] == 0x00 && (packet->payload[6] == 0x01 || packet->payload[6] == 0x00)
+ && packet->payload[7] == 0x00
+ /* && packet->payload[8]==0x00 */
+ && packet->payload[9] == 0x00) {
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if ((packet->actual_payload_len == 64 || packet->actual_payload_len == 52 /* PATTERN:: [len] 00 00 00 00 */
+ || packet->actual_payload_len == 95)
+ && get_u_int16_t(packet->payload, 0) == (packet->actual_payload_len)
+ && packet->payload[1] == 0x00 && packet->payload[2] == 0x00
+ && packet->payload[3] == 0x00 && packet->payload[4] == 0x00) {
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if (packet->actual_payload_len == 6 && packet->payload[0] == 0x06 // PATTERN : 06 00 04|6c 00|01 00 00
+ && packet->payload[1] == 0x00 && (packet->payload[2] == 0x04 || packet->payload[2] == 0x6c)
+ && (packet->payload[3] == 0x00 || packet->payload[3] == 0x01)
+ && packet->payload[4] == 0x00 && packet->payload[5] == 0x00) {
+
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if (packet->actual_payload_len == 6 /* PATTERN:: [len] ?? ee 00 00 00 */
+ && get_u_int16_t(packet->payload, 0) == (packet->actual_payload_len)
+ && packet->payload[2] == 0xee
+ && packet->payload[3] == 0x00 && packet->payload[4] == 0x00 && packet->payload[5] == 0x00) {
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ } else if (packet->actual_payload_len == 10 /* PATTERN:: 06 00 00 00 00 00 00 00 */
+ && packet->payload[0] == 0x06
+ && packet->payload[1] == 0x00
+ && packet->payload[2] == 0x00
+ && packet->payload[3] == 0x00
+ && packet->payload[4] == 0x00
+ && packet->payload[5] == 0x00 && packet->payload[6] == 0x00 && packet->payload[7] == 0x00) {
+ flow->l4.tcp.imesh_stage += 2;
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG,
+ "IMESH FOUND :: Payload %u\n", packet->actual_payload_len);
+ }
+
+
+ /* http login */
+ if (packet->payload_packet_len > NDPI_STATICSTRING_LEN("POST /registration") &&
+ memcmp(packet->payload, "POST /registration", NDPI_STATICSTRING_LEN("POST /registration")) == 0) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->parsed_lines > 6 &&
+ packet->host_line.ptr != NULL &&
+ packet->host_line.len == NDPI_STATICSTRING_LEN("login.bearshare.com") &&
+ packet->line[1].ptr != NULL &&
+ packet->line[1].len == NDPI_STATICSTRING_LEN("Authorization: Basic Og==") &&
+ packet->line[4].ptr != NULL &&
+ packet->line[4].len == NDPI_STATICSTRING_LEN("Accept-Encoding: identity") &&
+ memcmp(packet->line[1].ptr, "Authorization: Basic Og==",
+ NDPI_STATICSTRING_LEN("Authorization: Basic Og==")) == 0 &&
+ memcmp(packet->host_line.ptr, "login.bearshare.com",
+ NDPI_STATICSTRING_LEN("login.bearshare.com")) == 0 &&
+ memcmp(packet->line[4].ptr, "Accept-Encoding: identity",
+ NDPI_STATICSTRING_LEN("Accept-Encoding: identity")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "iMesh Login detected\n");
+ ndpi_int_imesh_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ /*give one packet tolerance for detection */
+ if((flow->l4.tcp.imesh_stage >= 4)
+ && (flow->l4.tcp.seen_syn && flow->l4.tcp.seen_syn_ack && flow->l4.tcp.seen_ack) /* We have seen the 3-way handshake */)
+ {
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "found imesh.\n");
+ ndpi_int_imesh_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+ if ((flow->packet_counter < 5) || packet->actual_payload_len == 0) {
+ return;
+ }
+ //imesh_not_found_end:
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_IMESH);
+ NDPI_LOG(NDPI_PROTOCOL_IMESH, ndpi_struct, NDPI_LOG_DEBUG, "iMesh excluded at stage %d\n",
+ packet->tcp != NULL ? flow->l4.tcp.imesh_stage : 0);
+
+}
+#endif
diff --git a/src/lib/protocols/ipp.c b/src/lib/protocols/ipp.c
new file mode 100644
index 000000000..72a75bc2a
--- /dev/null
+++ b/src/lib/protocols/ipp.c
@@ -0,0 +1,112 @@
+/*
+ * ipp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_IPP
+
+static void ndpi_int_ipp_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_IPP, protocol_type);
+}
+
+void ndpi_search_ipp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ u_int8_t i;
+
+ NDPI_LOG(NDPI_PROTOCOL_IPP, ndpi_struct, NDPI_LOG_DEBUG, "search ipp\n");
+ if (packet->payload_packet_len > 20) {
+
+ NDPI_LOG(NDPI_PROTOCOL_IPP, ndpi_struct, NDPI_LOG_DEBUG,
+ "searching for a payload with a pattern like 'number(1to8)blanknumber(1to3)ipp://.\n");
+ /* this pattern means that there is a printer saying that his state is idle,
+ * means that he is not printing anything at the moment */
+ i = 0;
+
+ if (packet->payload[i] < '0' || packet->payload[i] > '9') {
+ NDPI_LOG(NDPI_PROTOCOL_IPP, ndpi_struct, NDPI_LOG_DEBUG, "payload does not begin with a number.\n");
+ goto search_for_next_pattern;
+ }
+
+ for (;;) {
+ i++;
+ if (!((packet->payload[i] >= '0' && packet->payload[i] <= '9') ||
+ (packet->payload[i] >= 'a' && packet->payload[i] <= 'f') ||
+ (packet->payload[i] >= 'A' && packet->payload[i] <= 'F')) || i > 8) {
+ NDPI_LOG(NDPI_PROTOCOL_IPP, ndpi_struct, NDPI_LOG_DEBUG,
+ "read symbols while the symbol is a number.\n");
+ break;
+ }
+ }
+
+ if (packet->payload[i++] != ' ') {
+ NDPI_LOG(NDPI_PROTOCOL_IPP, ndpi_struct, NDPI_LOG_DEBUG, "there is no blank following the number.\n");
+ goto search_for_next_pattern;
+ }
+
+ if (packet->payload[i] < '0' || packet->payload[i] > '9') {
+ NDPI_LOG(NDPI_PROTOCOL_IPP, ndpi_struct, NDPI_LOG_DEBUG, "no number following the blank.\n");
+ goto search_for_next_pattern;
+ }
+
+ for (;;) {
+ i++;
+ if (packet->payload[i] < '0' || packet->payload[i] > '9' || i > 12) {
+ NDPI_LOG(NDPI_PROTOCOL_IPP, ndpi_struct, NDPI_LOG_DEBUG,
+ "read symbols while the symbol is a number.\n");
+ break;
+ }
+ }
+
+ if (memcmp(&packet->payload[i], " ipp://", 7) != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_IPP, ndpi_struct, NDPI_LOG_DEBUG, "the string ' ipp://' does not follow.\n");
+ goto search_for_next_pattern;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_IPP, ndpi_struct, NDPI_LOG_DEBUG, "found ipp\n");
+ ndpi_int_ipp_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ search_for_next_pattern:
+
+ if (packet->payload_packet_len > 3 && memcmp(packet->payload, "POST", 4) == 0) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->content_line.ptr != NULL && packet->content_line.len > 14
+ && memcmp(packet->content_line.ptr, "application/ipp", 15) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_IPP, ndpi_struct, NDPI_LOG_DEBUG, "found ipp via POST ... application/ipp.\n");
+ ndpi_int_ipp_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ NDPI_LOG(NDPI_PROTOCOL_IPP, ndpi_struct, NDPI_LOG_DEBUG, "no ipp detected.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_IPP);
+}
+
+#endif
diff --git a/src/lib/protocols/irc.c b/src/lib/protocols/irc.c
new file mode 100644
index 000000000..1947c3ac9
--- /dev/null
+++ b/src/lib/protocols/irc.c
@@ -0,0 +1,804 @@
+/*
+ * irc.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_IRC
+#define NDPI_IRC_FIND_LESS(time_err,less) {int t1 = 0; \
+ u_int32_t timestamp = time_err[0]; \
+ for(t1=0;t1 < NDPI_PROTOCOL_IRC_MAXPORT;t1++) { \
+ if(timestamp > time_err[t1]) { \
+ timestamp = time_err[t1]; \
+ less = t1;}}}
+
+static void ndpi_int_irc_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_IRC, NDPI_REAL_PROTOCOL);
+}
+
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+u_int8_t ndpi_is_duplicate(struct ndpi_id_struct *id_t, u_int16_t port)
+{
+ int index = 0;
+ while (index < id_t->irc_number_of_port) {
+ if (port == id_t->irc_port[index])
+ return 1;
+ index++;
+ }
+ return 0;
+}
+
+static u_int8_t ndpi_check_for_NOTICE_or_PRIVMSG(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+ //
+ u_int16_t i;
+ u_int8_t number_of_lines_to_be_searched_for = 0;
+ for (i = 0; i < packet->payload_packet_len - 7; i++) {
+ if (packet->payload[i] == 'N' || packet->payload[i] == 'P') {
+ if (memcmp(&packet->payload[i + 1], "OTICE ", 6) == 0 || memcmp(&packet->payload[i + 1], "RIVMSG ", 7) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "found NOTICE or PRIVMSG\n");
+ return 1;
+ }
+ }
+ if (packet->payload[i] == 0x0a) {
+ number_of_lines_to_be_searched_for++;
+ if (number_of_lines_to_be_searched_for == 2) {
+ return 0;
+ }
+ }
+ }
+ return 0;
+
+}
+
+static u_int8_t ndpi_check_for_Nickname(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t i, packetl = packet->payload_packet_len;
+
+ if (packetl < 4) {
+ return 0;
+ }
+
+ for (i = 0; i < (packetl - 4); i++) {
+ if (packet->payload[i] == 'N' || packet->payload[i] == 'n') {
+ if ((((packetl - (i + 1)) >= 4) && memcmp(&packet->payload[i + 1], "ick=", 4) == 0)
+ || (((packetl - (i + 1)) >= 8) && (memcmp(&packet->payload[i + 1], "ickname=", 8) == 0))
+ || (((packetl - (i + 1)) >= 8) && (memcmp(&packet->payload[i + 1], "ickName=", 8) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "found HTTP IRC Nickname pattern\n");
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static u_int8_t ndpi_check_for_cmd(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t i;
+
+ if (packet->payload_packet_len < 4) {
+ return 0;
+ }
+
+ for (i = 0; i < packet->payload_packet_len - 4; i++) {
+ if (packet->payload[i] == 'c') {
+ if (memcmp(&packet->payload[i + 1], "md=", 3) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "found HTTP IRC cmd pattern \n");
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static u_int8_t ndpi_check_for_IRC_traces(const u_int8_t * ptr, u_int16_t len)
+{
+ u_int16_t i;
+
+ if (len < 4) {
+ return 0;
+ }
+
+ for (i = 0; i < len - 4; i++) {
+ if (ptr[i] == 'i') {
+ if (memcmp(&ptr[i + 1], "rc.", 3) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+u_int8_t ndpi_search_irc_ssl_detect_ninty_percent_but_very_fast(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG,
+ "called ndpi_search_irc_ssl_detect_ninty_percent_but_very_fast\n");
+
+ /* case 1: len 1460, len 1460, len 1176 several times in one direction, than len = 4, 4096, 8192 in the other direction */
+ if (packet->payload_packet_len == 1460
+ && ((flow->l4.tcp.irc_stage2 == 0 && flow->l4.tcp.irc_direction == 0) || (flow->l4.tcp.irc_stage2 == 3
+ && flow->l4.tcp.irc_direction ==
+ 1 + packet->packet_direction))) {
+ flow->l4.tcp.irc_stage2 = 1;
+ flow->l4.tcp.irc_direction = 1 + packet->packet_direction;
+ return 1;
+ }
+ if (packet->payload_packet_len == 1460 && flow->l4.tcp.irc_stage2 == 1
+ && flow->l4.tcp.irc_direction == 1 + packet->packet_direction) {
+ flow->l4.tcp.irc_stage2 = 2;
+ return 1;
+ }
+ if (packet->payload_packet_len == 1176 && flow->l4.tcp.irc_stage2 == 2
+ && flow->l4.tcp.irc_direction == 1 + packet->packet_direction) {
+ flow->l4.tcp.irc_stage2 = 3;
+ flow->l4.tcp.irc_0x1000_full = 1;
+ return 1;
+ }
+ if (packet->payload_packet_len == 4 && (flow->l4.tcp.irc_stage2 == 3 || flow->l4.tcp.irc_0x1000_full == 1)
+ && flow->l4.tcp.irc_direction == 2 - packet->packet_direction && (ntohs(get_u_int16_t(packet->payload, 2)) == 0x1000
+ || ntohs(get_u_int16_t(packet->payload, 2)) ==
+ 0x2000)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "IRC SSL detected: ->1460,1460,1176,<-4096||8192");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return 1;
+ }
+ /* case 2: len 1448, len 1448, len 1200 several times in one direction, than len = 4, 4096, 8192 in the other direction */
+ if (packet->payload_packet_len == 1448
+ && ((flow->l4.tcp.irc_stage2 == 0 && flow->l4.tcp.irc_direction == 0) || (flow->l4.tcp.irc_stage2 == 6
+ && flow->l4.tcp.irc_direction ==
+ 1 + packet->packet_direction))) {
+ flow->l4.tcp.irc_stage2 = 4;
+ flow->l4.tcp.irc_direction = 1 + packet->packet_direction;
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "len = 1448 first\n");
+ return 1;
+ }
+ if (packet->payload_packet_len == 1448 && flow->l4.tcp.irc_stage2 == 4
+ && flow->l4.tcp.irc_direction == 1 + packet->packet_direction) {
+ flow->l4.tcp.irc_stage2 = 5;
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "len = 1448 second \n");
+ return 1;
+ }
+ if (packet->payload_packet_len == 1200 && flow->l4.tcp.irc_stage2 == 5
+ && flow->l4.tcp.irc_direction == 1 + packet->packet_direction) {
+ flow->l4.tcp.irc_stage2 = 6;
+ flow->l4.tcp.irc_0x1000_full = 1;
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "len = 1200 \n");
+ return 1;
+ }
+ if (packet->payload_packet_len == 4 && (flow->l4.tcp.irc_stage2 == 6 || flow->l4.tcp.irc_0x1000_full == 1)
+ && flow->l4.tcp.irc_direction == 2 - packet->packet_direction && (ntohs(get_u_int16_t(packet->payload, 2)) == 0x1000
+ || ntohs(get_u_int16_t(packet->payload, 2)) ==
+ 0x2000)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "IRC SSL detected: ->1448,1448,1200,<-4096||8192");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return 1;
+ }
+ /* case 3: several packets with len 1380, 1200, 1024, 1448, 1248,
+ * than one packet in the other direction with the len or two times the len. */
+ if (packet->payload_packet_len == 1380 && ((flow->l4.tcp.irc_stage2 == 0 && flow->l4.tcp.irc_direction == 0)
+ || (flow->l4.tcp.irc_stage2 == 7
+ && flow->l4.tcp.irc_direction == 1 + packet->packet_direction))) {
+ flow->l4.tcp.irc_stage2 = 7;
+ flow->l4.tcp.irc_direction = 1 + packet->packet_direction;
+ return 1;
+ }
+ if (packet->payload_packet_len == 4 && flow->l4.tcp.irc_stage2 == 7
+ && flow->l4.tcp.irc_direction == 2 - packet->packet_direction && (ntohs(get_u_int16_t(packet->payload, 2)) == 1380
+ || ntohs(get_u_int16_t(packet->payload, 2)) ==
+ 2760)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "IRC SSL detected: ->1380,<-1380||2760");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return 1;
+ }
+ if (packet->payload_packet_len == 1200 && ((flow->l4.tcp.irc_stage2 == 0 && flow->l4.tcp.irc_direction == 0)
+ || (flow->l4.tcp.irc_stage2 == 8
+ && flow->l4.tcp.irc_direction == 1 + packet->packet_direction))) {
+ flow->l4.tcp.irc_stage2 = 8;
+ flow->l4.tcp.irc_direction = 1 + packet->packet_direction;
+ return 1;
+ }
+ if (packet->payload_packet_len == 4 && flow->l4.tcp.irc_stage2 == 8
+ && flow->l4.tcp.irc_direction == 2 - packet->packet_direction && (ntohs(get_u_int16_t(packet->payload, 2)) == 1200
+ || ntohs(get_u_int16_t(packet->payload, 2)) ==
+ 2400)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "IRC SSL detected: ->1200,<-1200||2400");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return 1;
+ }
+ if (packet->payload_packet_len == 1024 && ((flow->l4.tcp.irc_stage2 == 0 && flow->l4.tcp.irc_direction == 0)
+ || (flow->l4.tcp.irc_stage2 == 9
+ && flow->l4.tcp.irc_direction == 1 + packet->packet_direction))) {
+ flow->l4.tcp.irc_stage2 = 9;
+ flow->l4.tcp.irc_direction = 1 + packet->packet_direction;
+ return 1;
+ }
+ if (packet->payload_packet_len == 4 && (flow->l4.tcp.irc_stage2 == 9 || flow->l4.tcp.irc_stage2 == 15)
+ && flow->l4.tcp.irc_direction == 2 - packet->packet_direction && (ntohs(get_u_int16_t(packet->payload, 2)) == 1024
+ || ntohs(get_u_int16_t(packet->payload, 2)) ==
+ 2048)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "IRC SSL detected: ->1024,<-1024||2048");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return 1;
+ }
+ if (packet->payload_packet_len == 1248 && ((flow->l4.tcp.irc_stage2 == 0 && flow->l4.tcp.irc_direction == 0)
+ || (flow->l4.tcp.irc_stage2 == 10
+ && flow->l4.tcp.irc_direction == 1 + packet->packet_direction))) {
+ flow->l4.tcp.irc_stage2 = 10;
+ flow->l4.tcp.irc_direction = 1 + packet->packet_direction;
+ return 1;
+ }
+ if (packet->payload_packet_len == 4 && flow->l4.tcp.irc_stage2 == 10
+ && flow->l4.tcp.irc_direction == 2 - packet->packet_direction && (ntohs(get_u_int16_t(packet->payload, 2)) == 1248
+ || ntohs(get_u_int16_t(packet->payload, 2)) ==
+ 2496)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "IRC SSL detected: ->1248,<-1248||2496");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return 1;
+ }
+ if (packet->payload_packet_len == 1448
+ && (flow->l4.tcp.irc_stage2 == 5 && flow->l4.tcp.irc_direction == 1 + packet->packet_direction)) {
+ flow->l4.tcp.irc_stage2 = 11;
+ return 1;
+ }
+ if (packet->payload_packet_len == 4
+ && (flow->l4.tcp.irc_stage2 == 4 || flow->l4.tcp.irc_stage2 == 5 || flow->l4.tcp.irc_stage2 == 11
+ || flow->l4.tcp.irc_stage2 == 13)
+ && flow->l4.tcp.irc_direction == 2 - packet->packet_direction && (ntohs(get_u_int16_t(packet->payload, 2)) == 1448
+ || ntohs(get_u_int16_t(packet->payload, 2)) ==
+ 2896)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "IRC SSL detected: ->1448,<-1448||2896");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return 1;
+ }
+ /* case 4 : five packets with len = 1448, one with len 952, than one packet from other direction len = 8192 */
+ if (packet->payload_packet_len == 1448
+ && (flow->l4.tcp.irc_stage2 == 11 && flow->l4.tcp.irc_direction == 1 + packet->packet_direction)) {
+ flow->l4.tcp.irc_stage2 = 12;
+ return 1;
+ }
+ if (packet->payload_packet_len == 1448
+ && (flow->l4.tcp.irc_stage2 == 12 && flow->l4.tcp.irc_direction == 1 + packet->packet_direction)) {
+ flow->l4.tcp.irc_stage2 = 13;
+ return 1;
+ }
+ if (packet->payload_packet_len == 952
+ && (flow->l4.tcp.irc_stage2 == 13 && flow->l4.tcp.irc_direction == 1 + packet->packet_direction)) {
+ flow->l4.tcp.irc_stage2 = 14;
+ return 1;
+ }
+ if (packet->payload_packet_len == 4
+ && flow->l4.tcp.irc_stage2 == 14
+ && flow->l4.tcp.irc_direction == 2 - packet->packet_direction && ntohs(get_u_int16_t(packet->payload, 2)) == 8192) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "IRC SSL detected: ->1448,1448,1448,1448,1448,952,<-8192");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return 1;
+ }
+ /* case 5: len 1024, len 1448, len 1448, len 1200, len 1448, len 600 */
+ if (packet->payload_packet_len == 1448
+ && (flow->l4.tcp.irc_stage2 == 9 && flow->l4.tcp.irc_direction == 1 + packet->packet_direction)) {
+ flow->l4.tcp.irc_stage2 = 15;
+ return 1;
+ }
+ if (packet->payload_packet_len == 1448
+ && (flow->l4.tcp.irc_stage2 == 15 && flow->l4.tcp.irc_direction == 1 + packet->packet_direction)) {
+ flow->l4.tcp.irc_stage2 = 16;
+ return 1;
+ }
+ if (packet->payload_packet_len == 1200
+ && (flow->l4.tcp.irc_stage2 == 16 && flow->l4.tcp.irc_direction == 1 + packet->packet_direction)) {
+ flow->l4.tcp.irc_stage2 = 17;
+ return 1;
+ }
+ if (packet->payload_packet_len == 1448
+ && (flow->l4.tcp.irc_stage2 == 17 && flow->l4.tcp.irc_direction == 1 + packet->packet_direction)) {
+ flow->l4.tcp.irc_stage2 = 18;
+ return 1;
+ }
+ if (packet->payload_packet_len == 600
+ && (flow->l4.tcp.irc_stage2 == 18 && flow->l4.tcp.irc_direction == 1 + packet->packet_direction)) {
+ flow->l4.tcp.irc_stage2 = 19;
+ return 1;
+ }
+ if (packet->payload_packet_len == 4
+ && flow->l4.tcp.irc_stage2 == 19
+ && flow->l4.tcp.irc_direction == 2 - packet->packet_direction && ntohs(get_u_int16_t(packet->payload, 2)) == 7168) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "IRC SSL detected: ->1024,1448,1448,1200,1448,600,<-7168");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return 1;
+ }
+ /* -> 1024, 1380, -> 2404 */
+ if (packet->payload_packet_len == 1380
+ && (flow->l4.tcp.irc_stage2 == 9 && flow->l4.tcp.irc_direction == 1 + packet->packet_direction)) {
+ flow->l4.tcp.irc_stage2 = 20;
+ return 1;
+ }
+ if (packet->payload_packet_len == 4
+ && flow->l4.tcp.irc_stage2 == 20
+ && flow->l4.tcp.irc_direction == 2 - packet->packet_direction && ntohs(get_u_int16_t(packet->payload, 2)) == 2404) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "IRC SSL detected: ->1024,1380 <-2404");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return 1;
+
+ }
+ return 0;
+}
+
+
+void ndpi_search_irc_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+ int less;
+ u_int16_t c = 0;
+ u_int16_t c1 = 0;
+ u_int16_t port = 0;
+ u_int16_t sport = 0;
+ u_int16_t dport = 0;
+ u_int16_t counter = 0;
+ u_int16_t i = 0;
+ u_int16_t j = 0;
+ u_int16_t k = 0;
+ u_int16_t h;
+ u_int16_t http_content_ptr_len = 0;
+ u_int8_t space = 0;
+
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "irc : search irc\n");
+ if (flow->detected_protocol_stack[0] != NDPI_PROTOCOL_IRC && flow->packet_counter > 70) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "exclude irc, packet_counter > 70\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_IRC);
+ return;
+ }
+ if (flow->detected_protocol_stack[0] != NDPI_PROTOCOL_IRC && flow->packet_counter > 30 &&
+ flow->l4.tcp.irc_stage2 == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "packet_counter > 30, exclude irc.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_IRC);
+ return;
+ }
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_IRC) {
+ if (src != NULL && ((u_int32_t)
+ (packet->tick_timestamp - src->irc_ts) < ndpi_struct->irc_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "irc : save src connection packet detected\n");
+ src->irc_ts = packet->tick_timestamp;
+ } else if (dst != NULL && ((u_int32_t)
+ (packet->tick_timestamp - dst->irc_ts) < ndpi_struct->irc_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "irc : save dst connection packet detected\n");
+ dst->irc_ts = packet->tick_timestamp;
+ }
+ }
+
+ if (((dst != NULL && NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, NDPI_PROTOCOL_IRC)
+ && ((u_int32_t)
+ (packet->tick_timestamp - dst->irc_ts)) <
+ ndpi_struct->irc_timeout)) || (src != NULL
+ &&
+ NDPI_COMPARE_PROTOCOL_TO_BITMASK
+ (src->detected_protocol_bitmask, NDPI_PROTOCOL_IRC)
+ && ((u_int32_t)
+ (packet->tick_timestamp - src->irc_ts)) < ndpi_struct->irc_timeout)) {
+ if (packet->tcp != NULL) {
+ sport = packet->tcp->source;
+ dport = packet->tcp->dest;
+ }
+ if (dst != NULL) {
+ for (counter = 0; counter < dst->irc_number_of_port; counter++) {
+ if (dst->irc_port[counter] == sport || dst->irc_port[counter] == dport) {
+ dst->last_time_port_used[counter] = packet->tick_timestamp;
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "dest port matched with the DCC port and the flow is marked as IRC");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+ if (src != NULL) {
+ for (counter = 0; counter < src->irc_number_of_port; counter++) {
+ if (src->irc_port[counter] == sport || src->irc_port[counter] == dport) {
+ src->last_time_port_used[counter] = packet->tick_timestamp;
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "Source port matched with the DCC port and the flow is marked as IRC");
+ return;
+ }
+ }
+ }
+ }
+
+
+
+ if (flow->detected_protocol_stack[0] != NDPI_PROTOCOL_IRC
+ && flow->packet_counter == 2 && (packet->payload_packet_len > 400 && packet->payload_packet_len < 1381)) {
+ for (c1 = 50; c1 < packet->payload_packet_len - 23; c1++) {
+ if (packet->payload[c1] == 'i' || packet->payload[c1] == 'd') {
+ if ((memcmp(&packet->payload[c1], "irc.hackthissite.org0", 21)
+ == 0)
+ || (memcmp(&packet->payload[c1], "irc.gamepad.ca1", 15) == 0)
+ || (memcmp(&packet->payload[c1], "dungeon.axenet.org0", 19)
+ == 0)
+ || (memcmp(&packet->payload[c1], "dazed.nuggethaus.net", 20)
+ == 0)
+ || (memcmp(&packet->payload[c1], "irc.indymedia.org", 17)
+ == 0)
+ || (memcmp(&packet->payload[c1], "irc.cccp-project.net", 20)
+ == 0)
+ || (memcmp(&packet->payload[c1], "dirc.followell.net0", 19)
+ == 0)
+ || (memcmp(&packet->payload[c1], "irc.discostars.de1", 18)
+ == 0)
+ || (memcmp(&packet->payload[c1], "irc.rizon.net", 13) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "IRC SSL detected with :- irc.hackthissite.org0 | irc.gamepad.ca1 | dungeon.axenet.org0 "
+ "| dazed.nuggethaus.net | irc.indymedia.org | irc.discostars.de1 ");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ break;
+ }
+ }
+ }
+ }
+ if (flow->detected_protocol_stack[0] != NDPI_PROTOCOL_IRC &&
+ ndpi_search_irc_ssl_detect_ninty_percent_but_very_fast(ndpi_struct, flow) != 0) {
+ return;
+ }
+
+ if (flow->detected_protocol_stack[0] != NDPI_PROTOCOL_IRC && flow->packet_counter < 20
+ && packet->payload_packet_len >= 8) {
+ if (get_u_int8_t(packet->payload, packet->payload_packet_len - 1) == 0x0a
+ || (ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0a00)) {
+ if (memcmp(packet->payload, ":", 1) == 0) {
+ if (packet->payload[packet->payload_packet_len - 2] != 0x0d
+ && packet->payload[packet->payload_packet_len - 1] == 0x0a) {
+ ndpi_parse_packet_line_info_any(ndpi_struct, flow);
+ } else if (packet->payload[packet->payload_packet_len - 2] == 0x0d) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ } else {
+ flow->l4.tcp.irc_3a_counter++;
+ }
+ for (i = 0; i < packet->parsed_lines; i++) {
+ if (packet->line[i].ptr[0] == ':') {
+ flow->l4.tcp.irc_3a_counter++;
+ if (flow->l4.tcp.irc_3a_counter == 7) { /* ':' == 0x3a */
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "0x3a. seven times. found irc.");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ goto detected_irc;
+ }
+ }
+ }
+ if (flow->l4.tcp.irc_3a_counter == 7) { /* ':' == 0x3a */
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "0x3a. seven times. found irc.");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ goto detected_irc;
+ }
+ }
+ if ((memcmp(packet->payload, "USER ", 5) == 0)
+ || (memcmp(packet->payload, "NICK ", 5) == 0)
+ || (memcmp(packet->payload, "PASS ", 5) == 0)
+ || (memcmp(packet->payload, ":", 1) == 0 && ndpi_check_for_NOTICE_or_PRIVMSG(ndpi_struct, flow) != 0)
+ || (memcmp(packet->payload, "PONG ", 5) == 0)
+ || (memcmp(packet->payload, "PING ", 5) == 0)
+ || (memcmp(packet->payload, "JOIN ", 5) == 0)
+ || (memcmp(packet->payload, "NOTICE ", 7) == 0)
+ || (memcmp(packet->payload, "PRIVMSG ", 8) == 0)
+ || (memcmp(packet->payload, "VERSION ", 8) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "USER, NICK, PASS, NOTICE, PRIVMSG one time");
+ if (flow->l4.tcp.irc_stage == 2) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "found irc");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ flow->l4.tcp.irc_stage = 3;
+ }
+ if (flow->l4.tcp.irc_stage == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "second time, stage=2");
+ flow->l4.tcp.irc_stage = 2;
+ }
+ if (flow->l4.tcp.irc_stage == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "first time, stage=1");
+ flow->l4.tcp.irc_stage = 1;
+ }
+ /* irc packets can have either windows line breaks (0d0a) or unix line breaks (0a) */
+ if (packet->payload[packet->payload_packet_len - 2] == 0x0d
+ && packet->payload[packet->payload_packet_len - 1] == 0x0a) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->parsed_lines > 1) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "packet contains more than one line");
+ for (c = 1; c < packet->parsed_lines; c++) {
+ if (packet->line[c].len > 4 && (memcmp(packet->line[c].ptr, "NICK ", 5) == 0
+ || memcmp(packet->line[c].ptr, "USER ", 5) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct,
+ NDPI_LOG_TRACE, "two icq signal words in the same packet");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ flow->l4.tcp.irc_stage = 3;
+ return;
+ }
+ }
+ }
+
+ } else if (packet->payload[packet->payload_packet_len - 1] == 0x0a) {
+ ndpi_parse_packet_line_info_any(ndpi_struct, flow);
+ if (packet->parsed_lines > 1) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "packet contains more than one line");
+ for (c = 1; c < packet->parsed_lines; c++) {
+ if (packet->line[c].len > 4 && (memcmp(packet->line[c].ptr, "NICK ", 5) == 0
+ || memcmp(packet->line[c].ptr, "USER ",
+ 5) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "two icq signal words in the same packet");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ flow->l4.tcp.irc_stage = 3;
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Trying to primarily detect the HTTP Web based IRC chat patterns based on the HTTP headers
+ * during the User login time.When the HTTP data gets posted using the POST method ,patterns
+ * will be searched in the HTTP content.
+ */
+ if ((flow->detected_protocol_stack[0] != NDPI_PROTOCOL_IRC) && (flow->l4.tcp.irc_stage == 0)
+ && (packet->payload_packet_len > 5)) {
+ //HTTP POST Method being employed
+ if (memcmp(packet->payload, "POST ", 5) == 0) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->parsed_lines) {
+ u_int16_t http_header_len = (packet->line[packet->parsed_lines - 1].ptr - packet->payload) + 2;
+ if (packet->payload_packet_len > http_header_len) {
+ http_content_ptr_len = packet->payload_packet_len - http_header_len;
+ }
+ if ((ndpi_check_for_IRC_traces(packet->line[0].ptr, packet->line[0].len))
+ || ((packet->http_url_name.ptr)
+ && (ndpi_check_for_IRC_traces(packet->http_url_name.ptr, packet->http_url_name.len)))
+ || ((packet->referer_line.ptr)
+ && (ndpi_check_for_IRC_traces(packet->referer_line.ptr, packet->referer_line.len)))) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "IRC detected from the Http URL/ Referer header ");
+ flow->l4.tcp.irc_stage = 1;
+ // HTTP POST Request body is not in the same packet.
+ if (!http_content_ptr_len) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ if ((flow->detected_protocol_stack[0] != NDPI_PROTOCOL_IRC) && (flow->l4.tcp.irc_stage == 1)) {
+ if ((((packet->payload_packet_len - http_content_ptr_len) > 10)
+ && (memcmp(packet->payload + http_content_ptr_len, "interface=", 10) == 0)
+ && (ndpi_check_for_Nickname(ndpi_struct, flow) != 0))
+ || (((packet->payload_packet_len - http_content_ptr_len) > 5)
+ && (memcmp(packet->payload + http_content_ptr_len, "item=", 5) == 0)
+ && (ndpi_check_for_cmd(ndpi_struct, flow) != 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "IRC Nickname, cmd, one time");
+ ndpi_int_irc_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ detected_irc:
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "detected_irc:");
+
+ if (flow->detected_protocol_stack[0] == NDPI_PROTOCOL_IRC) {
+ /* maybe this can be deleted at the end */
+
+ if (packet->payload[packet->payload_packet_len - 2] != 0x0d
+ && packet->payload[packet->payload_packet_len - 1] == 0x0a) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG,
+ "ndpi_parse_packet_line_info_any(ndpi_struct, flow);");
+ ndpi_parse_packet_line_info_any(ndpi_struct, flow);
+ } else if (packet->payload[packet->payload_packet_len - 2] == 0x0d) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ } else {
+ return;
+ }
+ for (i = 0; i < packet->parsed_lines; i++) {
+ if (packet->line[i].len > 6 && memcmp(packet->line[i].ptr, "NOTICE ", 7) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "NOTICE");
+ for (j = 7; j < packet->line[i].len - 8; j++) {
+ if (packet->line[i].ptr[j] == ':') {
+ if (memcmp(&packet->line[i].ptr[j + 1], "DCC SEND ", 9) == 0
+ || memcmp(&packet->line[i].ptr[j + 1], "DCC CHAT ", 9) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "found NOTICE and DCC CHAT or DCC SEND.");
+ }
+ }
+ }
+ }
+ if (packet->payload_packet_len > 0 && packet->payload[0] == 0x3a /* 0x3a = ':' */ ) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "3a");
+ for (j = 1; j < packet->line[i].len - 9; j++) {
+ if (packet->line[i].ptr[j] == ' ') {
+ j++;
+ if (packet->line[i].ptr[j] == 'P') {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "P");
+ j++;
+ if (memcmp(&packet->line[i].ptr[j], "RIVMSG ", 7) == 0)
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "RIVMSG");
+ h = j + 7;
+ goto read_privmsg;
+ }
+ }
+ }
+ }
+ if (packet->line[i].len > 7 && (memcmp(packet->line[i].ptr, "PRIVMSG ", 8) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG, "PRIVMSG ");
+ h = 7;
+ read_privmsg:
+ for (j = h; j < packet->line[i].len - 9; j++) {
+ if (packet->line[i].ptr[j] == ':') {
+ if (memcmp(&packet->line[i].ptr[j + 1], "xdcc ", 5) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "xdcc should match.");
+ }
+ j += 2;
+ if (memcmp(&packet->line[i].ptr[j], "DCC ", 4) == 0) {
+ j += 4;
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "found DCC.");
+ if (memcmp(&packet->line[i].ptr[j], "SEND ", 5) == 0
+ || (memcmp(&packet->line[i].ptr[j], "CHAT", 4) == 0)
+ || (memcmp(&packet->line[i].ptr[j], "chat", 4) == 0)
+ || (memcmp(&packet->line[i].ptr[j], "sslchat", 7) == 0)
+ || (memcmp(&packet->line[i].ptr[j], "TSEND", 5) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "found CHAT,chat,sslchat,TSEND.");
+ j += 4;
+
+ while (packet->line[i].len > j &&
+ ((packet->line[i].ptr[j] >= 'a' && packet->line[i].ptr[j] <= 'z')
+ || (packet->line[i].ptr[j] >= 'A' && packet->line[i].ptr[j] <= 'Z')
+ || (packet->line[i].ptr[j] >= '0' && packet->line[i].ptr[j] <= '9')
+ || (packet->line[i].ptr[j] >= ' ')
+ || (packet->line[i].ptr[j] >= '.')
+ || (packet->line[i].ptr[j] >= '-'))) {
+
+ if (packet->line[i].ptr[j] == ' ') {
+ space++;
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "space %u.", space);
+ }
+ if (space == 3) {
+ j++;
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "read port.");
+ if (src != NULL) {
+ k = j;
+ port =
+ ntohs_ndpi_bytestream_to_number
+ (&packet->line[i].ptr[j], packet->payload_packet_len - j, &j);
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "port %u.",
+ port);
+ j = k;
+ // hier jetzt überlegen, wie die ports abgespeichert werden sollen
+ if (src->irc_number_of_port < NDPI_PROTOCOL_IRC_MAXPORT)
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE,
+ "src->irc_number_of_port < NDPI_PROTOCOL_IRC_MAXPORT.");
+ if (src->irc_number_of_port < NDPI_PROTOCOL_IRC_MAXPORT && port != 0) {
+ if (!ndpi_is_duplicate(src, port)) {
+ src->irc_port[src->irc_number_of_port]
+ = port;
+ src->irc_number_of_port++;
+ NDPI_LOG
+ (NDPI_PROTOCOL_IRC,
+ ndpi_struct,
+ NDPI_LOG_DEBUG, "found port=%d",
+ ntohs(get_u_int16_t(src->irc_port, 0)));
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG,
+ "jjeeeeeeeeeeeeeeeeeeeeeeeee");
+ }
+ src->irc_ts = packet->tick_timestamp;
+ } else if (port != 0 && src->irc_number_of_port == NDPI_PROTOCOL_IRC_MAXPORT) {
+ if (!ndpi_is_duplicate(src, port)) {
+ less = 0;
+ NDPI_IRC_FIND_LESS(src->last_time_port_used, less);
+ src->irc_port[less] = port;
+ NDPI_LOG
+ (NDPI_PROTOCOL_IRC,
+ ndpi_struct,
+ NDPI_LOG_DEBUG, "found port=%d",
+ ntohs(get_u_int16_t(src->irc_port, 0)));
+ }
+ src->irc_ts = packet->tick_timestamp;
+ }
+ if (dst == NULL) {
+ break;
+ }
+ }
+ if (dst != NULL) {
+ port = ntohs_ndpi_bytestream_to_number
+ (&packet->line[i].ptr[j], packet->payload_packet_len - j, &j);
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_TRACE, "port %u.",
+ port);
+ // hier das gleiche wie oben.
+ /* hier werden NDPI_PROTOCOL_IRC_MAXPORT ports pro irc flows mitgespeichert. könnte man denn nicht ein-
+ * fach an die dst oder src einen flag setzten, dass dieser port für eine bestimmte
+ * zeit ein irc-port bleibt?
+ */
+ if (dst->irc_number_of_port < NDPI_PROTOCOL_IRC_MAXPORT && port != 0) {
+ if (!ndpi_is_duplicate(dst, port)) {
+ dst->irc_port[dst->irc_number_of_port]
+ = port;
+ dst->irc_number_of_port++;
+ NDPI_LOG
+ (NDPI_PROTOCOL_IRC,
+ ndpi_struct,
+ NDPI_LOG_DEBUG, "found port=%d",
+ ntohs(get_u_int16_t(dst->irc_port, 0)));
+ NDPI_LOG(NDPI_PROTOCOL_IRC, ndpi_struct, NDPI_LOG_DEBUG,
+ "juuuuuuuuuuuuuuuu");
+ }
+ dst->irc_ts = packet->tick_timestamp;
+ } else if (port != 0 && dst->irc_number_of_port == NDPI_PROTOCOL_IRC_MAXPORT) {
+ if (!ndpi_is_duplicate(dst, port)) {
+ less = 0;
+ NDPI_IRC_FIND_LESS(dst->last_time_port_used, less);
+ dst->irc_port[less] = port;
+
+ NDPI_LOG
+ (NDPI_PROTOCOL_IRC,
+ ndpi_struct,
+ NDPI_LOG_DEBUG, "found port=%d",
+ ntohs(get_u_int16_t(dst->irc_port, 0)));
+ }
+ dst->irc_ts = packet->tick_timestamp;
+ }
+
+ break;
+ }
+ }
+
+
+ j++;
+ }
+
+ }
+ }
+ }
+ }
+
+ }
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/jabber.c b/src/lib/protocols/jabber.c
new file mode 100644
index 000000000..7b78febb1
--- /dev/null
+++ b/src/lib/protocols/jabber.c
@@ -0,0 +1,311 @@
+/*
+ * jabber.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_UNENCRYPED_JABBER
+struct jabber_string {
+ char *string;
+ u_int ndpi_protocol;
+};
+
+static struct jabber_string jabber_strings[] = {
+#ifdef NDPI_PROTOCOL_TRUPHONE
+ { "='im.truphone.com'", NDPI_PROTOCOL_TRUPHONE },
+ { "=\"im.truphone.com\"", NDPI_PROTOCOL_TRUPHONE },
+#endif
+
+#ifdef NDPI_SERVICE_FACEBOOK_CHAT
+ { "to='chat.facebook.com'", NDPI_SERVICE_FACEBOOK_CHAT },
+#endif
+ { NULL, 0 }
+};
+
+static void ndpi_int_jabber_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int32_t protocol, ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, protocol, protocol_type);
+}
+
+static void check_content_type_and_change_protocol(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, u_int16_t x)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ int i, left = packet->payload_packet_len-x;
+
+ if(left <= 0) return;
+
+ for(i=0; jabber_strings[i].string != NULL; i++) {
+ if(ndpi_strnstr((const char*)&packet->payload[x], jabber_strings[i].string, left) != NULL) {
+ ndpi_int_jabber_add_connection(ndpi_struct, flow, jabber_strings[i].ndpi_protocol, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+}
+
+void ndpi_search_jabber_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ u_int16_t x;
+
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_TRACE, "JABBER detection....\n");
+
+ /* search for jabber file transfer */
+ /* this part is working asymmetrically */
+ if (packet->tcp != NULL && packet->tcp->syn != 0 && packet->payload_packet_len == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "check jabber syn\n");
+ if (src != NULL && src->jabber_file_transfer_port[0] != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG,
+ "src jabber ft port set, ports are: %u, %u\n", ntohs(src->jabber_file_transfer_port[0]),
+ ntohs(src->jabber_file_transfer_port[1]));
+ if (((u_int32_t)
+ (packet->tick_timestamp - src->jabber_stun_or_ft_ts)) >= ndpi_struct->jabber_file_transfer_timeout) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct,
+ NDPI_LOG_DEBUG, "JABBER src stun timeout %u %u\n", src->jabber_stun_or_ft_ts,
+ packet->tick_timestamp);
+ src->jabber_file_transfer_port[0] = 0;
+ src->jabber_file_transfer_port[1] = 0;
+ } else if (src->jabber_file_transfer_port[0] == packet->tcp->dest
+ || src->jabber_file_transfer_port[0] == packet->tcp->source
+ || src->jabber_file_transfer_port[1] == packet->tcp->dest
+ || src->jabber_file_transfer_port[1] == packet->tcp->source) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG,
+ "found jabber file transfer.\n");
+
+ ndpi_int_jabber_add_connection(ndpi_struct, flow,
+ NDPI_PROTOCOL_UNENCRYPED_JABBER, NDPI_CORRELATED_PROTOCOL);
+ }
+ }
+ if (dst != NULL && dst->jabber_file_transfer_port[0] != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG,
+ "dst jabber ft port set, ports are: %u, %u\n", ntohs(dst->jabber_file_transfer_port[0]),
+ ntohs(dst->jabber_file_transfer_port[1]));
+ if (((u_int32_t)
+ (packet->tick_timestamp - dst->jabber_stun_or_ft_ts)) >= ndpi_struct->jabber_file_transfer_timeout) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct,
+ NDPI_LOG_DEBUG, "JABBER dst stun timeout %u %u\n", dst->jabber_stun_or_ft_ts,
+ packet->tick_timestamp);
+ dst->jabber_file_transfer_port[0] = 0;
+ dst->jabber_file_transfer_port[1] = 0;
+ } else if (dst->jabber_file_transfer_port[0] == packet->tcp->dest
+ || dst->jabber_file_transfer_port[0] == packet->tcp->source
+ || dst->jabber_file_transfer_port[1] == packet->tcp->dest
+ || dst->jabber_file_transfer_port[1] == packet->tcp->source) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG,
+ "found jabber file transfer.\n");
+
+ ndpi_int_jabber_add_connection(ndpi_struct, flow,
+ NDPI_PROTOCOL_UNENCRYPED_JABBER, NDPI_CORRELATED_PROTOCOL);
+ }
+ }
+ return;
+ }
+
+ if (packet->tcp != 0 && packet->payload_packet_len == 0) {
+ return;
+ }
+
+
+ /* this part parses a packet and searches for port=. it works asymmetrically. */
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNENCRYPED_JABBER) {
+ u_int16_t lastlen;
+ u_int16_t j_port = 0;
+ /* check for google jabber voip connections ... */
+ /* need big packet */
+ if (packet->payload_packet_len < 100) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "packet too small, return.\n");
+ return;
+ }
+ /* need message to or type for file-transfer */
+ if (memcmp(packet->payload, "<iq from=\"", 8) == 0 || memcmp(packet->payload, "<iq from=\'", 8) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER <iq from=\".\n");
+ lastlen = packet->payload_packet_len - 11;
+ for (x = 10; x < lastlen; x++) {
+ if (packet->payload[x] == 'p') {
+ if (memcmp(&packet->payload[x], "port=", 5) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "port=\n");
+ if (src != NULL) {
+ src->jabber_stun_or_ft_ts = packet->tick_timestamp;
+ }
+
+ if (dst != NULL) {
+ dst->jabber_stun_or_ft_ts = packet->tick_timestamp;
+ }
+ x += 6;
+ j_port = ntohs_ndpi_bytestream_to_number(&packet->payload[x], packet->payload_packet_len, &x);
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct,
+ NDPI_LOG_DEBUG, "JABBER port : %u\n", ntohs(j_port));
+ if (src != NULL) {
+ if (src->jabber_file_transfer_port[0] == 0 || src->jabber_file_transfer_port[0] == j_port) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct,
+ NDPI_LOG_DEBUG, "src->jabber_file_transfer_port[0] = j_port = %u;\n",
+ ntohs(j_port));
+ src->jabber_file_transfer_port[0] = j_port;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct,
+ NDPI_LOG_DEBUG, "src->jabber_file_transfer_port[1] = j_port = %u;\n",
+ ntohs(j_port));
+ src->jabber_file_transfer_port[1] = j_port;
+ }
+ }
+ if (dst != NULL) {
+ if (dst->jabber_file_transfer_port[0] == 0 || dst->jabber_file_transfer_port[0] == j_port) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct,
+ NDPI_LOG_DEBUG, "dst->jabber_file_transfer_port[0] = j_port = %u;\n",
+ ntohs(j_port));
+ dst->jabber_file_transfer_port[0] = j_port;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct,
+ NDPI_LOG_DEBUG, "dst->jabber_file_transfer_port[1] = j_port = %u;\n",
+ ntohs(j_port));
+ dst->jabber_file_transfer_port[1] = j_port;
+ }
+ }
+ }
+
+
+ }
+ }
+
+ } else if (memcmp(packet->payload, "<iq to=\"", 8) == 0 || memcmp(packet->payload, "<iq to=\'", 8) == 0
+ || memcmp(packet->payload, "<iq type=", 9) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER <iq to=\"/type=\"\n");
+ lastlen = packet->payload_packet_len - 21;
+ for (x = 8; x < lastlen; x++) {
+ /* invalid character */
+ if (packet->payload[x] < 32 || packet->payload[x] > 127) {
+ return;
+ }
+ if (packet->payload[x] == '@') {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "JABBER @\n");
+ break;
+ }
+ }
+ if (x >= lastlen) {
+ return;
+ }
+
+ lastlen = packet->payload_packet_len - 10;
+ for (; x < lastlen; x++) {
+ if (packet->payload[x] == 'p') {
+ if (memcmp(&packet->payload[x], "port=", 5) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "port=\n");
+ if (src != NULL) {
+ src->jabber_stun_or_ft_ts = packet->tick_timestamp;
+ }
+
+ if (dst != NULL) {
+ dst->jabber_stun_or_ft_ts = packet->tick_timestamp;
+ }
+
+ x += 6;
+ j_port = ntohs_ndpi_bytestream_to_number(&packet->payload[x], packet->payload_packet_len, &x);
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct,
+ NDPI_LOG_DEBUG, "JABBER port : %u\n", ntohs(j_port));
+
+ if (src != NULL && src->jabber_voice_stun_used_ports < JABBER_MAX_STUN_PORTS - 1) {
+ if (packet->payload[5] == 'o') {
+ src->jabber_voice_stun_port[src->jabber_voice_stun_used_ports++]
+ = j_port;
+ } else {
+ if (src->jabber_file_transfer_port[0] == 0
+ || src->jabber_file_transfer_port[0] == j_port) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG,
+ "src->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port));
+ src->jabber_file_transfer_port[0] = j_port;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct,
+ NDPI_LOG_DEBUG, "src->jabber_file_transfer_port[1] = j_port = %u;\n",
+ ntohs(j_port));
+ src->jabber_file_transfer_port[1] = j_port;
+ }
+ }
+ }
+
+ if (dst != NULL && dst->jabber_voice_stun_used_ports < JABBER_MAX_STUN_PORTS - 1) {
+ if (packet->payload[5] == 'o') {
+ dst->jabber_voice_stun_port[dst->jabber_voice_stun_used_ports++]
+ = j_port;
+ } else {
+ if (dst->jabber_file_transfer_port[0] == 0
+ || dst->jabber_file_transfer_port[0] == j_port) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG,
+ "dst->jabber_file_transfer_port[0] = j_port = %u;\n", ntohs(j_port));
+ dst->jabber_file_transfer_port[0] = j_port;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct,
+ NDPI_LOG_DEBUG, "dst->jabber_file_transfer_port[1] = j_port = %u;\n",
+ ntohs(j_port));
+ dst->jabber_file_transfer_port[1] = j_port;
+ }
+ }
+ }
+ return;
+ }
+ }
+ }
+ }
+ return;
+ }
+
+
+ /* search for jabber here */
+ /* this part is working asymmetrically */
+ if ((packet->payload_packet_len > 13 && memcmp(packet->payload, "<?xml version=", 14) == 0)
+ || (packet->payload_packet_len >= NDPI_STATICSTRING_LEN("<stream:stream ")
+ && memcmp(packet->payload, "<stream:stream ", NDPI_STATICSTRING_LEN("<stream:stream ")) == 0)) {
+ int start = packet->payload_packet_len-13;
+
+ if(ndpi_strnstr((const char *)&packet->payload[13], "xmlns:stream='http://etherx.jabber.org/streams'", start)
+ || ndpi_strnstr((const char *)&packet->payload[13], "xmlns:stream=\"http://etherx.jabber.org/streams\"", start)) {
+
+ /* Protocol family */
+ ndpi_int_jabber_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPED_JABBER, NDPI_REAL_PROTOCOL);
+
+ /* search for subprotocols */
+ check_content_type_and_change_protocol(ndpi_struct, flow, 13);
+ return;
+ }
+ }
+
+ if (flow->packet_counter < 3) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct,
+ NDPI_LOG_DEBUG, "packet_counter: %u\n", flow->packet_counter);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_TRACE, "JABBER Excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_UNENCRYPED_JABBER);
+
+#ifdef NDPI_PROTOCOL_TRUPHONE
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TRUPHONE);
+#endif
+}
+
+#endif
diff --git a/src/lib/protocols/kerberos.c b/src/lib/protocols/kerberos.c
new file mode 100644
index 000000000..b04265fc5
--- /dev/null
+++ b/src/lib/protocols/kerberos.c
@@ -0,0 +1,82 @@
+/*
+ * kerberos.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+/* include files */
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_KERBEROS
+
+static void ndpi_int_kerberos_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_KERBEROS, NDPI_REAL_PROTOCOL);
+}
+
+
+void ndpi_search_kerberos(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ /* I have observed 0a,0c,0d,0e at packet->payload[19/21], maybe there are other possibilities */
+ if (packet->payload_packet_len >= 4 && ntohl(get_u_int32_t(packet->payload, 0)) == packet->payload_packet_len - 4) {
+ if (packet->payload_packet_len > 19 &&
+ packet->payload[14] == 0x05 &&
+ (packet->payload[19] == 0x0a ||
+ packet->payload[19] == 0x0c || packet->payload[19] == 0x0d || packet->payload[19] == 0x0e)) {
+ NDPI_LOG(NDPI_PROTOCOL_KERBEROS, ndpi_struct, NDPI_LOG_DEBUG, "found KERBEROS\n");
+ ndpi_int_kerberos_add_connection(ndpi_struct, flow);
+ return;
+
+ }
+ if (packet->payload_packet_len > 21 &&
+ packet->payload[16] == 0x05 &&
+ (packet->payload[21] == 0x0a ||
+ packet->payload[21] == 0x0c || packet->payload[21] == 0x0d || packet->payload[21] == 0x0e)) {
+ NDPI_LOG(NDPI_PROTOCOL_KERBEROS, ndpi_struct, NDPI_LOG_DEBUG, "found KERBEROS\n");
+ ndpi_int_kerberos_add_connection(ndpi_struct, flow);
+ return;
+
+ }
+
+
+
+ }
+
+
+
+
+
+
+
+
+ NDPI_LOG(NDPI_PROTOCOL_KERBEROS, ndpi_struct, NDPI_LOG_DEBUG, "no KERBEROS detected.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_KERBEROS);
+}
+
+#endif
diff --git a/src/lib/protocols/kontiki.c b/src/lib/protocols/kontiki.c
new file mode 100644
index 000000000..72ba1acab
--- /dev/null
+++ b/src/lib/protocols/kontiki.c
@@ -0,0 +1,65 @@
+/*
+ * kontiki.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_KONTIKI
+
+static void ndpi_int_kontiki_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_KONTIKI, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_kontiki(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ if (packet->payload_packet_len == 4 && (get_u_int32_t(packet->payload, 0) == htonl(0x02010100))) {
+ NDPI_LOG(NDPI_PROTOCOL_KONTIKI, ndpi_struct, NDPI_LOG_DEBUG, "Kontiki UDP detected.\n");
+ ndpi_int_kontiki_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len > 0 && packet->payload[0] == 0x02) {
+
+ if (packet->payload_packet_len == 20 && (get_u_int32_t(packet->payload, 16) == htonl(0x02040100))) {
+ NDPI_LOG(NDPI_PROTOCOL_KONTIKI, ndpi_struct, NDPI_LOG_DEBUG, "Kontiki UDP detected.\n");
+ ndpi_int_kontiki_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len == 16 && (get_u_int32_t(packet->payload, 12) == htonl(0x000004e4))) {
+ NDPI_LOG(NDPI_PROTOCOL_KONTIKI, ndpi_struct, NDPI_LOG_DEBUG, "Kontiki UDP detected.\n");
+ ndpi_int_kontiki_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_KONTIKI);
+}
+
+#endif
diff --git a/src/lib/protocols/ldap.c b/src/lib/protocols/ldap.c
new file mode 100644
index 000000000..44313156e
--- /dev/null
+++ b/src/lib/protocols/ldap.c
@@ -0,0 +1,101 @@
+/*
+ * ldap.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+/* include files */
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_LDAP
+
+static void ndpi_int_ldap_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_LDAP, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_ldap(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+// u_int16_t dport;
+
+
+
+ NDPI_LOG(NDPI_PROTOCOL_LDAP, ndpi_struct, NDPI_LOG_DEBUG, "search ldap\n");
+
+
+ if (packet->payload_packet_len >= 14 && packet->payload[0] == 0x30) {
+
+ // simple type
+ if (packet->payload[1] == 0x0c && packet->payload_packet_len == 14 &&
+ packet->payload[packet->payload_packet_len - 1] == 0x00 && packet->payload[2] == 0x02) {
+
+ if (packet->payload[3] == 0x01 &&
+ (packet->payload[5] == 0x60 || packet->payload[5] == 0x61) && packet->payload[6] == 0x07) {
+ NDPI_LOG(NDPI_PROTOCOL_LDAP, ndpi_struct, NDPI_LOG_DEBUG, "found ldap simple type 1\n");
+ ndpi_int_ldap_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ if (packet->payload[3] == 0x02 &&
+ (packet->payload[6] == 0x60 || packet->payload[6] == 0x61) && packet->payload[7] == 0x07) {
+ NDPI_LOG(NDPI_PROTOCOL_LDAP, ndpi_struct, NDPI_LOG_DEBUG, "found ldap simple type 2\n");
+ ndpi_int_ldap_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ // normal type
+ if (packet->payload[1] == 0x84 && packet->payload_packet_len >= 0x84 &&
+ packet->payload[2] == 0x00 && packet->payload[3] == 0x00 && packet->payload[6] == 0x02) {
+
+ if (packet->payload[7] == 0x01 &&
+ (packet->payload[9] == 0x60 || packet->payload[9] == 0x61 || packet->payload[9] == 0x63 ||
+ packet->payload[9] == 0x64) && packet->payload[10] == 0x84) {
+
+ NDPI_LOG(NDPI_PROTOCOL_LDAP, ndpi_struct, NDPI_LOG_DEBUG, "found ldap type 1\n");
+ ndpi_int_ldap_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ if (packet->payload[7] == 0x02 &&
+ (packet->payload[10] == 0x60 || packet->payload[10] == 0x61 || packet->payload[10] == 0x63 ||
+ packet->payload[10] == 0x64) && packet->payload[11] == 0x84) {
+
+ NDPI_LOG(NDPI_PROTOCOL_LDAP, ndpi_struct, NDPI_LOG_DEBUG, "found ldap type 2\n");
+ ndpi_int_ldap_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+
+
+ NDPI_LOG(NDPI_PROTOCOL_LDAP, ndpi_struct, NDPI_LOG_DEBUG, "ldap excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_LDAP);
+}
+
+#endif
diff --git a/src/lib/protocols/lotus_notes.c b/src/lib/protocols/lotus_notes.c
new file mode 100644
index 000000000..6294bce20
--- /dev/null
+++ b/src/lib/protocols/lotus_notes.c
@@ -0,0 +1,87 @@
+/*
+ * lotus_notes.c
+ *
+ * Copyright (C) 2012-15 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_LOTUS_NOTES
+
+/* ************************************ */
+
+static void ndpi_check_lotus_notes(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // const u_int8_t *packet_payload = packet->payload;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ if(packet->tcp != NULL) {
+ flow->l4.tcp.lotus_notes_packet_id++;
+
+#if 0
+ printf("[lotus_notes_packet_id: %u][len=%u][%02X %02X %02X %02X %02X %02X %02X %02X]\n",
+ flow->l4.tcp.lotus_notes_packet_id, payload_len,
+ packet->payload[6] & 0xFF,
+ packet->payload[7] & 0xFF,
+ packet->payload[8] & 0xFF,
+ packet->payload[9] & 0xFF,
+ packet->payload[10] & 0xFF,
+ packet->payload[11] & 0xFF,
+ packet->payload[12] & 0xFF,
+ packet->payload[13] & 0xFF
+ );
+#endif
+
+ if((flow->l4.tcp.lotus_notes_packet_id == 1)
+ /* We have seen the 3-way handshake */
+ && flow->l4.tcp.seen_syn
+ && flow->l4.tcp.seen_syn_ack
+ && flow->l4.tcp.seen_ack) {
+ if(payload_len > 16) {
+ char lotus_notes_header[] = { 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x02, 0x0F };
+
+ if(memcmp(&packet->payload[6], lotus_notes_header, sizeof(lotus_notes_header)) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_LOTUS_NOTES, ndpi_struct, NDPI_LOG_DEBUG, "Found lotus_notes.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_LOTUS_NOTES, NDPI_REAL_PROTOCOL);
+ }
+
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_LOTUS_NOTES);
+ } else if(flow->l4.tcp.lotus_notes_packet_id > 3)
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_LOTUS_NOTES);
+
+ return;
+ }
+}
+
+void ndpi_search_lotus_notes(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_LOTUS_NOTES, ndpi_struct, NDPI_LOG_DEBUG, "lotus_notes detection...\n");
+
+ /* skip marked packets */
+ if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_LOTUS_NOTES)
+ ndpi_check_lotus_notes(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/mail_imap.c b/src/lib/protocols/mail_imap.c
new file mode 100644
index 000000000..11a02a8f5
--- /dev/null
+++ b/src/lib/protocols/mail_imap.c
@@ -0,0 +1,293 @@
+/*
+ * mail_imap.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_MAIL_IMAP
+
+static void ndpi_int_mail_imap_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_IMAP, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_mail_imap_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t i = 0;
+ u_int16_t space_pos = 0;
+ u_int16_t command_start = 0;
+ u_int8_t saw_command = 0;
+ /* const u_int8_t *command = 0; */
+
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_IMAP, ndpi_struct, NDPI_LOG_DEBUG, "search IMAP.\n");
+
+ if (packet->payload_packet_len >= 4 && ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0d0a) {
+ // the DONE command appears without a tag
+ if (packet->payload_packet_len == 6 && ((packet->payload[0] == 'D' || packet->payload[0] == 'd')
+ && (packet->payload[1] == 'O' || packet->payload[1] == 'o')
+ && (packet->payload[2] == 'N' || packet->payload[2] == 'n')
+ && (packet->payload[3] == 'E' || packet->payload[3] == 'e'))) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ } else {
+
+ if (flow->l4.tcp.mail_imap_stage < 4) {
+ // search for the first space character (end of the tag)
+ while (i < 20 && i < packet->payload_packet_len) {
+ if (i > 0 && packet->payload[i] == ' ') {
+ space_pos = i;
+ break;
+ }
+ if (!((packet->payload[i] >= 'a' && packet->payload[i] <= 'z') ||
+ (packet->payload[i] >= 'A' && packet->payload[i] <= 'Z') ||
+ (packet->payload[i] >= '0' && packet->payload[i] <= '9') || packet->payload[i] == '*')) {
+ goto imap_excluded;
+ }
+ i++;
+ }
+ if (space_pos == 0 || space_pos == (packet->payload_packet_len - 1)) {
+ goto imap_excluded;
+ }
+ // now walk over a possible mail number to the next space
+ i++;
+ if (i < packet->payload_packet_len && (packet->payload[i] >= '0' && packet->payload[i] <= '9')) {
+ while (i < 20 && i < packet->payload_packet_len) {
+ if (i > 0 && packet->payload[i] == ' ') {
+ space_pos = i;
+ break;
+ }
+ if (!(packet->payload[i] >= '0' && packet->payload[i] <= '9')) {
+ goto imap_excluded;
+ }
+ i++;
+ }
+ if (space_pos == 0 || space_pos == (packet->payload_packet_len - 1)) {
+ goto imap_excluded;
+ }
+ }
+ command_start = space_pos + 1;
+ /* command = &(packet->payload[command_start]); */
+ } else {
+ command_start = 0;
+ /* command = &(packet->payload[command_start]); */
+ }
+
+ if ((command_start + 3) < packet->payload_packet_len) {
+ if ((packet->payload[command_start] == 'O' || packet->payload[command_start] == 'o')
+ && (packet->payload[command_start + 1] == 'K' || packet->payload[command_start + 1] == 'k')
+ && packet->payload[command_start + 2] == ' ') {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ } else if ((packet->payload[command_start] == 'U' || packet->payload[command_start] == 'u')
+ && (packet->payload[command_start + 1] == 'I' || packet->payload[command_start + 1] == 'i')
+ && (packet->payload[command_start + 2] == 'D' || packet->payload[command_start + 2] == 'd')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ }
+ }
+ if ((command_start + 10) < packet->payload_packet_len) {
+ if ((packet->payload[command_start] == 'C' || packet->payload[command_start] == 'c')
+ && (packet->payload[command_start + 1] == 'A' || packet->payload[command_start + 1] == 'a')
+ && (packet->payload[command_start + 2] == 'P' || packet->payload[command_start + 2] == 'p')
+ && (packet->payload[command_start + 3] == 'A' || packet->payload[command_start + 3] == 'a')
+ && (packet->payload[command_start + 4] == 'B' || packet->payload[command_start + 4] == 'b')
+ && (packet->payload[command_start + 5] == 'I' || packet->payload[command_start + 5] == 'i')
+ && (packet->payload[command_start + 6] == 'L' || packet->payload[command_start + 6] == 'l')
+ && (packet->payload[command_start + 7] == 'I' || packet->payload[command_start + 7] == 'i')
+ && (packet->payload[command_start + 8] == 'T' || packet->payload[command_start + 8] == 't')
+ && (packet->payload[command_start + 9] == 'Y' || packet->payload[command_start + 9] == 'y')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ }
+ }
+ if ((command_start + 8) < packet->payload_packet_len) {
+ if ((packet->payload[command_start] == 'S' || packet->payload[command_start] == 's')
+ && (packet->payload[command_start + 1] == 'T' || packet->payload[command_start + 1] == 't')
+ && (packet->payload[command_start + 2] == 'A' || packet->payload[command_start + 2] == 'a')
+ && (packet->payload[command_start + 3] == 'R' || packet->payload[command_start + 3] == 'r')
+ && (packet->payload[command_start + 4] == 'T' || packet->payload[command_start + 4] == 't')
+ && (packet->payload[command_start + 5] == 'T' || packet->payload[command_start + 5] == 't')
+ && (packet->payload[command_start + 6] == 'L' || packet->payload[command_start + 6] == 'l')
+ && (packet->payload[command_start + 7] == 'S' || packet->payload[command_start + 7] == 's')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ }
+ }
+ if ((command_start + 5) < packet->payload_packet_len) {
+ if ((packet->payload[command_start] == 'L' || packet->payload[command_start] == 'l')
+ && (packet->payload[command_start + 1] == 'O' || packet->payload[command_start + 1] == 'o')
+ && (packet->payload[command_start + 2] == 'G' || packet->payload[command_start + 2] == 'g')
+ && (packet->payload[command_start + 3] == 'I' || packet->payload[command_start + 3] == 'i')
+ && (packet->payload[command_start + 4] == 'N' || packet->payload[command_start + 4] == 'n')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ } else if ((packet->payload[command_start] == 'F' || packet->payload[command_start] == 'f')
+ && (packet->payload[command_start + 1] == 'E' || packet->payload[command_start + 1] == 'e')
+ && (packet->payload[command_start + 2] == 'T' || packet->payload[command_start + 2] == 't')
+ && (packet->payload[command_start + 3] == 'C' || packet->payload[command_start + 3] == 'c')
+ && (packet->payload[command_start + 4] == 'H' || packet->payload[command_start + 4] == 'h')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ } else if ((packet->payload[command_start] == 'F' || packet->payload[command_start] == 'f')
+ && (packet->payload[command_start + 1] == 'L' || packet->payload[command_start + 1] == 'l')
+ && (packet->payload[command_start + 2] == 'A' || packet->payload[command_start + 2] == 'a')
+ && (packet->payload[command_start + 3] == 'G' || packet->payload[command_start + 3] == 'g')
+ && (packet->payload[command_start + 4] == 'S' || packet->payload[command_start + 4] == 's')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ } else if ((packet->payload[command_start] == 'C' || packet->payload[command_start] == 'c')
+ && (packet->payload[command_start + 1] == 'H' || packet->payload[command_start + 1] == 'h')
+ && (packet->payload[command_start + 2] == 'E' || packet->payload[command_start + 2] == 'e')
+ && (packet->payload[command_start + 3] == 'C' || packet->payload[command_start + 3] == 'c')
+ && (packet->payload[command_start + 4] == 'K' || packet->payload[command_start + 4] == 'k')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ } else if ((packet->payload[command_start] == 'S' || packet->payload[command_start] == 's')
+ && (packet->payload[command_start + 1] == 'T' || packet->payload[command_start + 1] == 't')
+ && (packet->payload[command_start + 2] == 'O' || packet->payload[command_start + 2] == 'o')
+ && (packet->payload[command_start + 3] == 'R' || packet->payload[command_start + 3] == 'r')
+ && (packet->payload[command_start + 4] == 'E' || packet->payload[command_start + 4] == 'e')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ }
+ }
+ if ((command_start + 12) < packet->payload_packet_len) {
+ if ((packet->payload[command_start] == 'A' || packet->payload[command_start] == 'a')
+ && (packet->payload[command_start + 1] == 'U' || packet->payload[command_start + 1] == 'u')
+ && (packet->payload[command_start + 2] == 'T' || packet->payload[command_start + 2] == 't')
+ && (packet->payload[command_start + 3] == 'H' || packet->payload[command_start + 3] == 'h')
+ && (packet->payload[command_start + 4] == 'E' || packet->payload[command_start + 4] == 'e')
+ && (packet->payload[command_start + 5] == 'N' || packet->payload[command_start + 5] == 'n')
+ && (packet->payload[command_start + 6] == 'T' || packet->payload[command_start + 6] == 't')
+ && (packet->payload[command_start + 7] == 'I' || packet->payload[command_start + 7] == 'i')
+ && (packet->payload[command_start + 8] == 'C' || packet->payload[command_start + 8] == 'c')
+ && (packet->payload[command_start + 9] == 'A' || packet->payload[command_start + 9] == 'a')
+ && (packet->payload[command_start + 10] == 'T' || packet->payload[command_start + 10] == 't')
+ && (packet->payload[command_start + 11] == 'E' || packet->payload[command_start + 11] == 'e')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ }
+ }
+ if ((command_start + 9) < packet->payload_packet_len) {
+ if ((packet->payload[command_start] == 'N' || packet->payload[command_start] == 'n')
+ && (packet->payload[command_start + 1] == 'A' || packet->payload[command_start + 1] == 'a')
+ && (packet->payload[command_start + 2] == 'M' || packet->payload[command_start + 2] == 'm')
+ && (packet->payload[command_start + 3] == 'E' || packet->payload[command_start + 3] == 'e')
+ && (packet->payload[command_start + 4] == 'S' || packet->payload[command_start + 4] == 's')
+ && (packet->payload[command_start + 5] == 'P' || packet->payload[command_start + 5] == 'p')
+ && (packet->payload[command_start + 6] == 'A' || packet->payload[command_start + 6] == 'a')
+ && (packet->payload[command_start + 7] == 'C' || packet->payload[command_start + 7] == 'c')
+ && (packet->payload[command_start + 8] == 'E' || packet->payload[command_start + 8] == 'e')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ }
+ }
+ if ((command_start + 4) < packet->payload_packet_len) {
+ if ((packet->payload[command_start] == 'L' || packet->payload[command_start] == 'l')
+ && (packet->payload[command_start + 1] == 'S' || packet->payload[command_start + 1] == 's')
+ && (packet->payload[command_start + 2] == 'U' || packet->payload[command_start + 2] == 'u')
+ && (packet->payload[command_start + 3] == 'B' || packet->payload[command_start + 3] == 'b')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ } else if ((packet->payload[command_start] == 'L' || packet->payload[command_start] == 'l')
+ && (packet->payload[command_start + 1] == 'I' || packet->payload[command_start + 1] == 'i')
+ && (packet->payload[command_start + 2] == 'S' || packet->payload[command_start + 2] == 's')
+ && (packet->payload[command_start + 3] == 'T' || packet->payload[command_start + 3] == 't')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ } else if ((packet->payload[command_start] == 'N' || packet->payload[command_start] == 'n')
+ && (packet->payload[command_start + 1] == 'O' || packet->payload[command_start + 1] == 'o')
+ && (packet->payload[command_start + 2] == 'O' || packet->payload[command_start + 2] == 'o')
+ && (packet->payload[command_start + 3] == 'P' || packet->payload[command_start + 3] == 'p')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ } else if ((packet->payload[command_start] == 'I' || packet->payload[command_start] == 'i')
+ && (packet->payload[command_start + 1] == 'D' || packet->payload[command_start + 1] == 'd')
+ && (packet->payload[command_start + 2] == 'L' || packet->payload[command_start + 2] == 'l')
+ && (packet->payload[command_start + 3] == 'E' || packet->payload[command_start + 3] == 'e')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ }
+ }
+ if ((command_start + 6) < packet->payload_packet_len) {
+ if ((packet->payload[command_start] == 'S' || packet->payload[command_start] == 's')
+ && (packet->payload[command_start + 1] == 'E' || packet->payload[command_start + 1] == 'e')
+ && (packet->payload[command_start + 2] == 'L' || packet->payload[command_start + 2] == 'l')
+ && (packet->payload[command_start + 3] == 'E' || packet->payload[command_start + 3] == 'e')
+ && (packet->payload[command_start + 4] == 'C' || packet->payload[command_start + 4] == 'c')
+ && (packet->payload[command_start + 5] == 'T' || packet->payload[command_start + 5] == 't')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ } else if ((packet->payload[command_start] == 'E' || packet->payload[command_start] == 'e')
+ && (packet->payload[command_start + 1] == 'X' || packet->payload[command_start + 1] == 'x')
+ && (packet->payload[command_start + 2] == 'I' || packet->payload[command_start + 2] == 'i')
+ && (packet->payload[command_start + 3] == 'S' || packet->payload[command_start + 3] == 's')
+ && (packet->payload[command_start + 4] == 'T' || packet->payload[command_start + 4] == 't')
+ && (packet->payload[command_start + 5] == 'S' || packet->payload[command_start + 5] == 's')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ } else if ((packet->payload[command_start] == 'A' || packet->payload[command_start] == 'a')
+ && (packet->payload[command_start + 1] == 'P' || packet->payload[command_start + 1] == 'p')
+ && (packet->payload[command_start + 2] == 'P' || packet->payload[command_start + 2] == 'p')
+ && (packet->payload[command_start + 3] == 'E' || packet->payload[command_start + 3] == 'e')
+ && (packet->payload[command_start + 4] == 'N' || packet->payload[command_start + 4] == 'n')
+ && (packet->payload[command_start + 5] == 'D' || packet->payload[command_start + 5] == 'd')) {
+ flow->l4.tcp.mail_imap_stage += 1;
+ saw_command = 1;
+ }
+ }
+
+ }
+
+ if (saw_command == 1) {
+ if (flow->l4.tcp.mail_imap_stage == 3 || flow->l4.tcp.mail_imap_stage == 5) {
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_IMAP, ndpi_struct, NDPI_LOG_DEBUG, "mail imap identified\n");
+ ndpi_int_mail_imap_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+
+ if (packet->payload_packet_len > 1 && packet->payload[packet->payload_packet_len - 1] == ' ') {
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_IMAP, ndpi_struct, NDPI_LOG_DEBUG,
+ "maybe a split imap command -> need next packet and imap_stage is set to 4.\n");
+ flow->l4.tcp.mail_imap_stage = 4;
+ return;
+ }
+
+ imap_excluded:
+
+ // skip over possible authentication hashes etc. that cannot be identified as imap commands or responses
+ // if the packet count is low enough and at least one command or response was seen before
+ if ((packet->payload_packet_len >= 2 && ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0d0a)
+ && flow->packet_counter < 6 && flow->l4.tcp.mail_imap_stage >= 1) {
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_IMAP, ndpi_struct, NDPI_LOG_DEBUG,
+ "no imap command or response but packet count < 6 and imap stage >= 1 -> skip\n");
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_IMAP, ndpi_struct, NDPI_LOG_DEBUG, "exclude IMAP.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MAIL_IMAP);
+}
+#endif
diff --git a/src/lib/protocols/mail_pop.c b/src/lib/protocols/mail_pop.c
new file mode 100644
index 000000000..522d4948e
--- /dev/null
+++ b/src/lib/protocols/mail_pop.c
@@ -0,0 +1,204 @@
+/*
+ * mail_pop.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_MAIL_POP
+
+#define POP_BIT_AUTH 0x0001
+#define POP_BIT_APOP 0x0002
+#define POP_BIT_USER 0x0004
+#define POP_BIT_PASS 0x0008
+#define POP_BIT_CAPA 0x0010
+#define POP_BIT_LIST 0x0020
+#define POP_BIT_STAT 0x0040
+#define POP_BIT_UIDL 0x0080
+#define POP_BIT_RETR 0x0100
+#define POP_BIT_DELE 0x0200
+#define POP_BIT_STLS 0x0400
+
+
+static void ndpi_int_mail_pop_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_POP, NDPI_REAL_PROTOCOL);
+}
+
+
+static int ndpi_int_mail_pop_check_for_client_commands(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len > 4) {
+ if ((packet->payload[0] == 'A' || packet->payload[0] == 'a')
+ && (packet->payload[1] == 'U' || packet->payload[1] == 'u')
+ && (packet->payload[2] == 'T' || packet->payload[2] == 't')
+ && (packet->payload[3] == 'H' || packet->payload[3] == 'h')) {
+ flow->l4.tcp.pop_command_bitmask |= POP_BIT_AUTH;
+ return 1;
+ } else if ((packet->payload[0] == 'A' || packet->payload[0] == 'a')
+ && (packet->payload[1] == 'P' || packet->payload[1] == 'p')
+ && (packet->payload[2] == 'O' || packet->payload[2] == 'o')
+ && (packet->payload[3] == 'P' || packet->payload[3] == 'p')) {
+ flow->l4.tcp.pop_command_bitmask |= POP_BIT_APOP;
+ return 1;
+ } else if ((packet->payload[0] == 'U' || packet->payload[0] == 'u')
+ && (packet->payload[1] == 'S' || packet->payload[1] == 's')
+ && (packet->payload[2] == 'E' || packet->payload[2] == 'e')
+ && (packet->payload[3] == 'R' || packet->payload[3] == 'r')) {
+ flow->l4.tcp.pop_command_bitmask |= POP_BIT_USER;
+ return 1;
+ } else if ((packet->payload[0] == 'P' || packet->payload[0] == 'p')
+ && (packet->payload[1] == 'A' || packet->payload[1] == 'a')
+ && (packet->payload[2] == 'S' || packet->payload[2] == 's')
+ && (packet->payload[3] == 'S' || packet->payload[3] == 's')) {
+ flow->l4.tcp.pop_command_bitmask |= POP_BIT_PASS;
+ return 1;
+ } else if ((packet->payload[0] == 'C' || packet->payload[0] == 'c')
+ && (packet->payload[1] == 'A' || packet->payload[1] == 'a')
+ && (packet->payload[2] == 'P' || packet->payload[2] == 'p')
+ && (packet->payload[3] == 'A' || packet->payload[3] == 'a')) {
+ flow->l4.tcp.pop_command_bitmask |= POP_BIT_CAPA;
+ return 1;
+ } else if ((packet->payload[0] == 'L' || packet->payload[0] == 'l')
+ && (packet->payload[1] == 'I' || packet->payload[1] == 'i')
+ && (packet->payload[2] == 'S' || packet->payload[2] == 's')
+ && (packet->payload[3] == 'T' || packet->payload[3] == 't')) {
+ flow->l4.tcp.pop_command_bitmask |= POP_BIT_LIST;
+ return 1;
+ } else if ((packet->payload[0] == 'S' || packet->payload[0] == 's')
+ && (packet->payload[1] == 'T' || packet->payload[1] == 't')
+ && (packet->payload[2] == 'A' || packet->payload[2] == 'a')
+ && (packet->payload[3] == 'T' || packet->payload[3] == 't')) {
+ flow->l4.tcp.pop_command_bitmask |= POP_BIT_STAT;
+ return 1;
+ } else if ((packet->payload[0] == 'U' || packet->payload[0] == 'u')
+ && (packet->payload[1] == 'I' || packet->payload[1] == 'i')
+ && (packet->payload[2] == 'D' || packet->payload[2] == 'd')
+ && (packet->payload[3] == 'L' || packet->payload[3] == 'l')) {
+ flow->l4.tcp.pop_command_bitmask |= POP_BIT_UIDL;
+ return 1;
+ } else if ((packet->payload[0] == 'R' || packet->payload[0] == 'r')
+ && (packet->payload[1] == 'E' || packet->payload[1] == 'e')
+ && (packet->payload[2] == 'T' || packet->payload[2] == 't')
+ && (packet->payload[3] == 'R' || packet->payload[3] == 'r')) {
+ flow->l4.tcp.pop_command_bitmask |= POP_BIT_RETR;
+ return 1;
+ } else if ((packet->payload[0] == 'D' || packet->payload[0] == 'd')
+ && (packet->payload[1] == 'E' || packet->payload[1] == 'e')
+ && (packet->payload[2] == 'L' || packet->payload[2] == 'l')
+ && (packet->payload[3] == 'E' || packet->payload[3] == 'e')) {
+ flow->l4.tcp.pop_command_bitmask |= POP_BIT_DELE;
+ return 1;
+ } else if ((packet->payload[0] == 'S' || packet->payload[0] == 's')
+ && (packet->payload[1] == 'T' || packet->payload[1] == 't')
+ && (packet->payload[2] == 'L' || packet->payload[2] == 'l')
+ && (packet->payload[3] == 'S' || packet->payload[3] == 's')) {
+ flow->l4.tcp.pop_command_bitmask |= POP_BIT_STLS;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+
+void ndpi_search_mail_pop_tcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+ u_int8_t a = 0;
+ u_int8_t bit_count = 0;
+
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_POP, ndpi_struct, NDPI_LOG_DEBUG, "search mail_pop\n");
+
+
+
+ if ((packet->payload_packet_len > 3
+ && (packet->payload[0] == '+' && (packet->payload[1] == 'O' || packet->payload[1] == 'o')
+ && (packet->payload[2] == 'K' || packet->payload[2] == 'k')))
+ || (packet->payload_packet_len > 4
+ && (packet->payload[0] == '-' && (packet->payload[1] == 'E' || packet->payload[1] == 'e')
+ && (packet->payload[2] == 'R' || packet->payload[2] == 'r')
+ && (packet->payload[3] == 'R' || packet->payload[3] == 'r')))) {
+ // +OK or -ERR seen
+ flow->l4.tcp.mail_pop_stage += 1;
+ } else if (!ndpi_int_mail_pop_check_for_client_commands(ndpi_struct, flow)) {
+ goto maybe_split_pop;
+ }
+
+ if (packet->payload_packet_len > 2 && ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0d0a) {
+
+ // count the bits set in the bitmask
+ if (flow->l4.tcp.pop_command_bitmask != 0) {
+ for (a = 0; a < 16; a++) {
+ bit_count += (flow->l4.tcp.pop_command_bitmask >> a) & 0x01;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_POP, ndpi_struct, NDPI_LOG_DEBUG,
+ "mail_pop +OK/-ERR responses: %u, unique commands: %u\n", flow->l4.tcp.mail_pop_stage, bit_count);
+
+ if ((bit_count + flow->l4.tcp.mail_pop_stage) >= 3) {
+ if (flow->l4.tcp.mail_pop_stage > 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_POP, ndpi_struct, NDPI_LOG_DEBUG, "mail_pop identified\n");
+ ndpi_int_mail_pop_add_connection(ndpi_struct, flow);
+ return;
+ } else {
+ return;
+ }
+ } else {
+ return;
+ }
+
+ } else {
+ // first part of a split packet
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_POP, ndpi_struct, NDPI_LOG_DEBUG,
+ "mail_pop command without line ending -> skip\n");
+ return;
+ }
+
+
+ maybe_split_pop:
+
+ if (((packet->payload_packet_len > 2 && ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0d0a)
+ || flow->l4.tcp.pop_command_bitmask != 0 || flow->l4.tcp.mail_pop_stage != 0) && flow->packet_counter < 12) {
+ // maybe part of a split pop packet
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_POP, ndpi_struct, NDPI_LOG_DEBUG,
+ "maybe part of split mail_pop packet -> skip\n");
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_POP, ndpi_struct, NDPI_LOG_DEBUG, "exclude mail_pop\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MAIL_POP);
+}
+#endif
diff --git a/src/lib/protocols/mail_smtp.c b/src/lib/protocols/mail_smtp.c
new file mode 100644
index 000000000..e6ee4b1c8
--- /dev/null
+++ b/src/lib/protocols/mail_smtp.c
@@ -0,0 +1,180 @@
+/*
+ * mail_smtp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_MAIL_SMTP
+
+#define SMTP_BIT_220 0x01
+#define SMTP_BIT_250 0x02
+#define SMTP_BIT_235 0x04
+#define SMTP_BIT_334 0x08
+#define SMTP_BIT_354 0x10
+#define SMTP_BIT_HELO_EHLO 0x20
+#define SMTP_BIT_MAIL 0x40
+#define SMTP_BIT_RCPT 0x80
+#define SMTP_BIT_AUTH 0x100
+#define SMTP_BIT_STARTTLS 0x200
+#define SMTP_BIT_DATA 0x400
+#define SMTP_BIT_NOOP 0x800
+#define SMTP_BIT_RSET 0x1000
+#define SMTP_BIT_TlRM 0x2000
+
+static void ndpi_int_mail_smtp_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MAIL_SMTP, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_mail_smtp_tcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_SMTP, ndpi_struct, NDPI_LOG_DEBUG, "search mail_smtp.\n");
+
+
+ if (packet->payload_packet_len > 2 && ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0d0a) {
+ u_int8_t a;
+ u_int8_t bit_count = 0;
+
+ NDPI_PARSE_PACKET_LINE_INFO(ndpi_struct, flow,packet);
+ for (a = 0; a < packet->parsed_lines; a++) {
+
+ // expected server responses
+ if (packet->line[a].len >= 3) {
+ if (memcmp(packet->line[a].ptr, "220", 3) == 0) {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_220;
+ } else if (memcmp(packet->line[a].ptr, "250", 3) == 0) {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_250;
+ } else if (memcmp(packet->line[a].ptr, "235", 3) == 0) {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_235;
+ } else if (memcmp(packet->line[a].ptr, "334", 3) == 0) {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_334;
+ } else if (memcmp(packet->line[a].ptr, "354", 3) == 0) {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_354;
+ }
+ }
+ // expected client requests
+ if (packet->line[a].len >= 5) {
+ if ((((packet->line[a].ptr[0] == 'H' || packet->line[a].ptr[0] == 'h')
+ && (packet->line[a].ptr[1] == 'E' || packet->line[a].ptr[1] == 'e'))
+ || ((packet->line[a].ptr[0] == 'E' || packet->line[a].ptr[0] == 'e')
+ && (packet->line[a].ptr[1] == 'H' || packet->line[a].ptr[1] == 'h')))
+ && (packet->line[a].ptr[2] == 'L' || packet->line[a].ptr[2] == 'l')
+ && (packet->line[a].ptr[3] == 'O' || packet->line[a].ptr[3] == 'o')
+ && packet->line[a].ptr[4] == ' ') {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_HELO_EHLO;
+ } else if ((packet->line[a].ptr[0] == 'M' || packet->line[a].ptr[0] == 'm')
+ && (packet->line[a].ptr[1] == 'A' || packet->line[a].ptr[1] == 'a')
+ && (packet->line[a].ptr[2] == 'I' || packet->line[a].ptr[2] == 'i')
+ && (packet->line[a].ptr[3] == 'L' || packet->line[a].ptr[3] == 'l')
+ && packet->line[a].ptr[4] == ' ') {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_MAIL;
+ } else if ((packet->line[a].ptr[0] == 'R' || packet->line[a].ptr[0] == 'r')
+ && (packet->line[a].ptr[1] == 'C' || packet->line[a].ptr[1] == 'c')
+ && (packet->line[a].ptr[2] == 'P' || packet->line[a].ptr[2] == 'p')
+ && (packet->line[a].ptr[3] == 'T' || packet->line[a].ptr[3] == 't')
+ && packet->line[a].ptr[4] == ' ') {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_RCPT;
+ } else if ((packet->line[a].ptr[0] == 'A' || packet->line[a].ptr[0] == 'a')
+ && (packet->line[a].ptr[1] == 'U' || packet->line[a].ptr[1] == 'u')
+ && (packet->line[a].ptr[2] == 'T' || packet->line[a].ptr[2] == 't')
+ && (packet->line[a].ptr[3] == 'H' || packet->line[a].ptr[3] == 'h')
+ && packet->line[a].ptr[4] == ' ') {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_AUTH;
+ }
+ }
+
+ if (packet->line[a].len >= 8) {
+ if ((packet->line[a].ptr[0] == 'S' || packet->line[a].ptr[0] == 's')
+ && (packet->line[a].ptr[1] == 'T' || packet->line[a].ptr[1] == 't')
+ && (packet->line[a].ptr[2] == 'A' || packet->line[a].ptr[2] == 'a')
+ && (packet->line[a].ptr[3] == 'R' || packet->line[a].ptr[3] == 'r')
+ && (packet->line[a].ptr[4] == 'T' || packet->line[a].ptr[0] == 't')
+ && (packet->line[a].ptr[5] == 'T' || packet->line[a].ptr[1] == 't')
+ && (packet->line[a].ptr[6] == 'L' || packet->line[a].ptr[2] == 'l')
+ && (packet->line[a].ptr[7] == 'S' || packet->line[a].ptr[3] == 's')) {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_STARTTLS;
+ }
+ }
+
+ if (packet->line[a].len >= 4) {
+ if ((packet->line[a].ptr[0] == 'D' || packet->line[a].ptr[0] == 'd')
+ && (packet->line[a].ptr[1] == 'A' || packet->line[a].ptr[1] == 'a')
+ && (packet->line[a].ptr[2] == 'T' || packet->line[a].ptr[2] == 't')
+ && (packet->line[a].ptr[3] == 'A' || packet->line[a].ptr[3] == 'a')) {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_DATA;
+ } else if ((packet->line[a].ptr[0] == 'N' || packet->line[a].ptr[0] == 'n')
+ && (packet->line[a].ptr[1] == 'O' || packet->line[a].ptr[1] == 'o')
+ && (packet->line[a].ptr[2] == 'O' || packet->line[a].ptr[2] == 'o')
+ && (packet->line[a].ptr[3] == 'P' || packet->line[a].ptr[3] == 'p')) {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_NOOP;
+ } else if ((packet->line[a].ptr[0] == 'R' || packet->line[a].ptr[0] == 'r')
+ && (packet->line[a].ptr[1] == 'S' || packet->line[a].ptr[1] == 's')
+ && (packet->line[a].ptr[2] == 'E' || packet->line[a].ptr[2] == 'e')
+ && (packet->line[a].ptr[3] == 'T' || packet->line[a].ptr[3] == 't')) {
+ flow->l4.tcp.smtp_command_bitmask |= SMTP_BIT_RSET;
+ }
+ }
+
+ }
+
+ // now count the bits set in the bitmask
+ if (flow->l4.tcp.smtp_command_bitmask != 0) {
+ for (a = 0; a < 16; a++) {
+ bit_count += (flow->l4.tcp.smtp_command_bitmask >> a) & 0x01;
+ }
+ }
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_SMTP, ndpi_struct, NDPI_LOG_DEBUG, "seen smtp commands and responses: %u.\n",
+ bit_count);
+
+ if (bit_count >= 3) {
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_SMTP, ndpi_struct, NDPI_LOG_DEBUG, "mail smtp identified\n");
+ ndpi_int_mail_smtp_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (bit_count >= 1 && flow->packet_counter < 12) {
+ return;
+ }
+ }
+ /* when the first or second packets are split into two packets, those packets are ignored. */
+ if (flow->packet_counter <= 4 &&
+ packet->payload_packet_len >= 4 &&
+ (ntohs(get_u_int16_t(packet->payload, packet->payload_packet_len - 2)) == 0x0d0a
+ || memcmp(packet->payload, "220", 3) == 0 || memcmp(packet->payload, "EHLO", 4) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_SMTP, ndpi_struct, NDPI_LOG_DEBUG, "maybe SMTP, need next packet.\n");
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_MAIL_SMTP, ndpi_struct, NDPI_LOG_DEBUG, "exclude smtp\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MAIL_SMTP);
+
+}
+#endif
diff --git a/src/lib/protocols/maplestory.c b/src/lib/protocols/maplestory.c
new file mode 100644
index 000000000..e9d89d1da
--- /dev/null
+++ b/src/lib/protocols/maplestory.c
@@ -0,0 +1,87 @@
+/*
+ * maplestory.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_MAPLESTORY
+
+static void ndpi_int_maplestory_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow,
+ ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MAPLESTORY, protocol_type);
+}
+
+
+void ndpi_search_maplestory(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+
+ if (packet->payload_packet_len == 16
+ && (ntohl(get_u_int32_t(packet->payload, 0)) == 0x0e003a00 || ntohl(get_u_int32_t(packet->payload, 0)) == 0x0e003b00
+ || ntohl(get_u_int32_t(packet->payload, 0)) == 0x0e004200)
+ && ntohs(get_u_int16_t(packet->payload, 4)) == 0x0100 && (packet->payload[6] == 0x32 || packet->payload[6] == 0x33)) {
+ NDPI_LOG(NDPI_PROTOCOL_MAPLESTORY, ndpi_struct, NDPI_LOG_DEBUG, "found maplestory.\n");
+ ndpi_int_maplestory_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ if (packet->payload_packet_len > NDPI_STATICSTRING_LEN("GET /maple")
+ && memcmp(packet->payload, "GET /maple", NDPI_STATICSTRING_LEN("GET /maple")) == 0) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ /* Maplestory update */
+ if (packet->payload_packet_len > NDPI_STATICSTRING_LEN("GET /maple/patch")
+ && packet->payload[NDPI_STATICSTRING_LEN("GET /maple")] == '/') {
+ if (packet->user_agent_line.ptr != NULL && packet->host_line.ptr != NULL
+ && packet->user_agent_line.len == NDPI_STATICSTRING_LEN("Patcher")
+ && packet->host_line.len > NDPI_STATICSTRING_LEN("patch.")
+ && memcmp(&packet->payload[NDPI_STATICSTRING_LEN("GET /maple/")], "patch",
+ NDPI_STATICSTRING_LEN("patch")) == 0
+ && memcmp(packet->user_agent_line.ptr, "Patcher", NDPI_STATICSTRING_LEN("Patcher")) == 0
+ && memcmp(packet->host_line.ptr, "patch.", NDPI_STATICSTRING_LEN("patch.")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MAPLESTORY, ndpi_struct, NDPI_LOG_DEBUG, "found maplestory update.\n");
+ ndpi_int_maplestory_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ } else if (packet->user_agent_line.ptr != NULL && packet->user_agent_line.len == NDPI_STATICSTRING_LEN("AspINet")
+ && memcmp(&packet->payload[NDPI_STATICSTRING_LEN("GET /maple")], "story/",
+ NDPI_STATICSTRING_LEN("story/")) == 0
+ && memcmp(packet->user_agent_line.ptr, "AspINet", NDPI_STATICSTRING_LEN("AspINet")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MAPLESTORY, ndpi_struct, NDPI_LOG_DEBUG, "found maplestory update.\n");
+ ndpi_int_maplestory_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_MAPLESTORY, ndpi_struct, NDPI_LOG_DEBUG, "exclude maplestory.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MAPLESTORY);
+
+}
+#endif
diff --git a/src/lib/protocols/mdns.c b/src/lib/protocols/mdns.c
new file mode 100644
index 000000000..9b9b72582
--- /dev/null
+++ b/src/lib/protocols/mdns.c
@@ -0,0 +1,146 @@
+/*
+ * mdns.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_MDNS
+
+#define NDPI_MAX_MDNS_REQUESTS 128
+
+/*
+This module should detect MDNS
+*/
+
+static void ndpi_int_mdns_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MDNS, NDPI_REAL_PROTOCOL);
+}
+
+static int ndpi_int_check_mdns_payload(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if ((packet->payload[2] & 0x80) == 0 &&
+ ntohs(get_u_int16_t(packet->payload, 4)) <= NDPI_MAX_MDNS_REQUESTS &&
+ ntohs(get_u_int16_t(packet->payload, 6)) <= NDPI_MAX_MDNS_REQUESTS) {
+
+ NDPI_LOG(NDPI_PROTOCOL_MDNS, ndpi_struct, NDPI_LOG_DEBUG, "found MDNS with question query.\n");
+
+ return 1;
+ } else if ((packet->payload[2] & 0x80) != 0 &&
+ ntohs(get_u_int16_t(packet->payload, 4)) == 0 &&
+ ntohs(get_u_int16_t(packet->payload, 6)) <= NDPI_MAX_MDNS_REQUESTS &&
+ ntohs(get_u_int16_t(packet->payload, 6)) != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MDNS, ndpi_struct, NDPI_LOG_DEBUG, "found MDNS with answer query.\n");
+
+ return 1;
+ }
+
+ return 0;
+}
+
+void ndpi_search_mdns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ u_int16_t dport;
+// const u_int16_t sport=ntohs(packet->udp->source);
+
+ /* check if UDP and */
+ if (packet->udp != NULL) {
+ /*read destination port */
+ dport = ntohs(packet->udp->dest);
+
+ NDPI_LOG(NDPI_PROTOCOL_MDNS, ndpi_struct, NDPI_LOG_DEBUG, "MDNS udp start \n");
+
+
+
+ /*check standard MDNS to port 5353 */
+ /*took this information from http://www.it-administrator.de/lexikon/multicast-dns.html */
+
+ if (dport == 5353 && packet->payload_packet_len >= 12) {
+
+ NDPI_LOG(NDPI_PROTOCOL_MDNS, ndpi_struct, NDPI_LOG_DEBUG, "found MDNS with destination port 5353\n");
+
+ /* MDNS header is similar to dns header */
+ /* dns header
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ID |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QDCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ANCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | NSCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ARCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ *
+ * dns query check: query: QR set, ancount = 0, nscount = 0, QDCOUNT < MAX_MDNS, ARCOUNT < MAX_MDNS
+ *
+ */
+
+ /* mdns protocol must have destination address 224.0.0.251 */
+ /* took this information from http://www.it-administrator.de/lexikon/multicast-dns.html */
+
+ if (packet->iph != NULL && ntohl(packet->iph->daddr) == 0xe00000fb) {
+
+ NDPI_LOG(NDPI_PROTOCOL_MDNS, ndpi_struct,
+ NDPI_LOG_DEBUG, "found MDNS with destination address 224.0.0.251 (=0xe00000fb)\n");
+
+ if (ndpi_int_check_mdns_payload(ndpi_struct, flow) == 1) {
+ ndpi_int_mdns_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ if (packet->iphv6 != NULL) {
+ const u_int32_t *daddr = packet->iphv6->daddr.ndpi_v6_u.u6_addr32;
+ if (daddr[0] == htonl(0xff020000) && daddr[1] == 0 && daddr[2] == 0 && daddr[3] == htonl(0xfb)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_MDNS, ndpi_struct,
+ NDPI_LOG_DEBUG, "found MDNS with destination address ff02::fb\n");
+
+ if (ndpi_int_check_mdns_payload(ndpi_struct, flow) == 1) {
+ ndpi_int_mdns_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+#endif
+
+ }
+ }
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MDNS);
+}
+#endif
diff --git a/src/lib/protocols/meebo.c b/src/lib/protocols/meebo.c
new file mode 100644
index 000000000..a54cb311e
--- /dev/null
+++ b/src/lib/protocols/meebo.c
@@ -0,0 +1,165 @@
+/*
+ * meebo.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_MEEBO
+
+static void ndpi_int_meebo_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MEEBO, NDPI_CORRELATED_PROTOCOL);
+}
+
+
+
+
+void ndpi_search_meebo(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "search meebo.\n");
+
+ /* catch audio/video flows which are flash (rtmp) */
+ if (
+#ifdef NDPI_CONTENT_FLASH
+ packet->detected_protocol_stack[0] == NDPI_CONTENT_FLASH
+#else
+ (packet->tcp->source == htons(1935) || packet->tcp->dest == htons(1935))
+#endif
+ ) {
+
+ /* TODO: once we have an amf decoder we can more directly access the rtmp fields
+ * if so, we may also exclude earlier */
+ if (packet->payload_packet_len > 900) {
+ if (memcmp(packet->payload + 116, "tokbox/", NDPI_STATICSTRING_LEN("tokbox/")) == 0 ||
+ memcmp(packet->payload + 316, "tokbox/", NDPI_STATICSTRING_LEN("tokbox/")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "found meebo/tokbox flash flow.\n");
+ ndpi_int_meebo_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ if (flow->packet_counter < 16 && flow->packet_direction_counter[flow->setup_packet_direction] < 6) {
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "need next packet.\n");
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "exclude meebo.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MEEBO);
+ return;
+ }
+
+ if ((
+#ifdef NDPI_PROTOCOL_HTTP
+ packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP ||
+#endif
+ ((packet->payload_packet_len > 3 && memcmp(packet->payload, "GET ", 4) == 0)
+ || (packet->payload_packet_len > 4 && memcmp(packet->payload, "POST ", 5) == 0))
+ ) && flow->packet_counter == 1) {
+ u_int8_t host_or_referer_match = 0;
+
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->host_line.ptr != NULL
+ && packet->host_line.len >= 9
+ && memcmp(&packet->host_line.ptr[packet->host_line.len - 9], "meebo.com", 9) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "Found Meebo host\n");
+ host_or_referer_match = 1;
+ } else if (packet->host_line.ptr != NULL
+ && packet->host_line.len >= 10
+ && memcmp(&packet->host_line.ptr[packet->host_line.len - 10], "tokbox.com", 10) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "Found tokbox host\n");
+ /* set it to 2 to avoid having plain tokbox traffic detected as meebo */
+ host_or_referer_match = 2;
+ } else if (packet->host_line.ptr != NULL && packet->host_line.len >= NDPI_STATICSTRING_LEN("74.114.28.110")
+ && memcmp(&packet->host_line.ptr[packet->host_line.len - NDPI_STATICSTRING_LEN("74.114.28.110")],
+ "74.114.28.110", NDPI_STATICSTRING_LEN("74.114.28.110")) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "Found meebo IP\n");
+ host_or_referer_match = 1;
+ } else if (packet->referer_line.ptr != NULL &&
+ packet->referer_line.len >= NDPI_STATICSTRING_LEN("http://www.meebo.com/") &&
+ memcmp(packet->referer_line.ptr, "http://www.meebo.com/",
+ NDPI_STATICSTRING_LEN("http://www.meebo.com/")) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "Found meebo referer\n");
+ host_or_referer_match = 1;
+ } else if (packet->referer_line.ptr != NULL &&
+ packet->referer_line.len >= NDPI_STATICSTRING_LEN("http://mee.tokbox.com/") &&
+ memcmp(packet->referer_line.ptr, "http://mee.tokbox.com/",
+ NDPI_STATICSTRING_LEN("http://mee.tokbox.com/")) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "Found tokbox referer\n");
+ host_or_referer_match = 1;
+ } else if (packet->referer_line.ptr != NULL &&
+ packet->referer_line.len >= NDPI_STATICSTRING_LEN("http://74.114.28.110/") &&
+ memcmp(packet->referer_line.ptr, "http://74.114.28.110/",
+ NDPI_STATICSTRING_LEN("http://74.114.28.110/")) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "Found meebo IP referer\n");
+ host_or_referer_match = 1;
+ }
+
+ if (host_or_referer_match) {
+ if (host_or_referer_match == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG,
+ "Found Meebo traffic based on host/referer\n");
+ ndpi_int_meebo_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_MEEBO) {
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG,
+ "in case that ssl meebo has been detected return.\n");
+ return;
+ }
+
+ if (flow->packet_counter < 5 && packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SSL) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "ssl not yet excluded. need next packet.\n");
+ return;
+ }
+#ifdef NDPI_CONTENT_FLASH
+ if (flow->packet_counter < 5 && packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN &&
+ !NDPI_FLOW_PROTOCOL_EXCLUDED(ndpi_struct, flow, NDPI_CONTENT_FLASH)) {
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "flash not yet excluded. need next packet.\n");
+ return;
+ }
+#endif
+
+ NDPI_LOG(NDPI_PROTOCOL_MEEBO, ndpi_struct, NDPI_LOG_DEBUG, "exclude meebo.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MEEBO);
+}
+#endif
diff --git a/src/lib/protocols/megaco.c b/src/lib/protocols/megaco.c
new file mode 100644
index 000000000..ca8d26380
--- /dev/null
+++ b/src/lib/protocols/megaco.c
@@ -0,0 +1,49 @@
+/*
+ * megaco.c
+ *
+ * Copyright (C) 2014 by Gianluca Costa http://www.capanalysis.net
+ * Copyright (C) 2012-15 - ntop.org
+ *
+ * This module is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This module 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License.
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_MEGACO
+
+void ndpi_search_megaco(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_MEGACO, ndpi_struct, NDPI_LOG_DEBUG, "search for MEGACO.\n");
+
+ if(packet->udp != NULL) {
+ if((packet->payload_packet_len > 4 && packet->payload[0] == '!' && packet->payload[1] == '/' &&
+ packet->payload[2] == '1' && packet->payload[3] == ' ' && packet->payload[4] == '[')
+ || (packet->payload_packet_len > 9 && packet->payload[0] == 'M' && packet->payload[1] == 'E' &&
+ packet->payload[2] == 'G' && packet->payload[3] == 'A' && packet->payload[4] == 'C' &&
+ packet->payload[5] == 'O' && packet->payload[6] == '/' &&
+ packet->payload[7] == '1' && packet->payload[8] == ' ' && packet->payload[9] == '[')) {
+ NDPI_LOG(NDPI_PROTOCOL_MEGACO, ndpi_struct, NDPI_LOG_DEBUG, "found MEGACO.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MEGACO, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_MEGACO, ndpi_struct, NDPI_LOG_DEBUG, "exclude MEGACO.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MEGACO);
+}
+
+#endif
diff --git a/src/lib/protocols/mgcp.c b/src/lib/protocols/mgcp.c
new file mode 100644
index 000000000..c749f007b
--- /dev/null
+++ b/src/lib/protocols/mgcp.c
@@ -0,0 +1,102 @@
+/*
+ * mgcp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_MGCP
+
+static void ndpi_int_mgcp_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MGCP, NDPI_REAL_PROTOCOL);
+}
+
+
+
+#if !defined(WIN32)
+ static inline
+#else
+__forceinline static
+#endif
+ void ndpi_search_mgcp_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ /* information about MGCP taken from http://en.wikipedia.org/wiki/MGCP */
+
+ u_int16_t pos = 4;
+
+ if (packet->payload_packet_len < 8) {
+ goto mgcp_excluded;
+ }
+
+ /* packet must end with 0x0d0a or with 0x0a */
+ if (packet->payload[packet->payload_packet_len - 1] != 0x0a
+ && get_u_int16_t(packet->payload, packet->payload_packet_len - 2) != htons(0x0d0a)) {
+ goto mgcp_excluded;
+ }
+
+
+
+ if (packet->payload[0] != 'A' && packet->payload[0] != 'C' && packet->payload[0] != 'D' &&
+ packet->payload[0] != 'E' && packet->payload[0] != 'M' && packet->payload[0] != 'N' &&
+ packet->payload[0] != 'R') {
+ goto mgcp_excluded;
+ }
+ if (memcmp(packet->payload, "AUEP ", 5) != 0 && memcmp(packet->payload, "AUCX ", 5) != 0 &&
+ memcmp(packet->payload, "CRCX ", 5) != 0 && memcmp(packet->payload, "DLCX ", 5) != 0 &&
+ memcmp(packet->payload, "EPCF ", 5) != 0 && memcmp(packet->payload, "MDCX ", 5) != 0 &&
+ memcmp(packet->payload, "NTFY ", 5) != 0 && memcmp(packet->payload, "RQNT ", 5) != 0 &&
+ memcmp(packet->payload, "RSIP ", 5) != 0) {
+ goto mgcp_excluded;
+ }
+ // now search for string "MGCP " in the rest of the message
+ while ((pos + 5) < packet->payload_packet_len) {
+ if (memcmp(&packet->payload[pos], "MGCP ", 5) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MGCP, ndpi_struct, NDPI_LOG_DEBUG, "MGCP match.\n");
+ ndpi_int_mgcp_add_connection(ndpi_struct, flow);
+ return;
+ }
+ pos++;
+ }
+
+ mgcp_excluded:
+ NDPI_LOG(NDPI_PROTOCOL_MGCP, ndpi_struct, NDPI_LOG_DEBUG, "exclude MGCP.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MGCP);
+}
+
+
+void ndpi_search_mgcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+ ndpi_search_mgcp_connection(ndpi_struct, flow);
+
+}
+#endif
diff --git a/src/lib/protocols/mms.c b/src/lib/protocols/mms.c
new file mode 100644
index 000000000..00f2cb764
--- /dev/null
+++ b/src/lib/protocols/mms.c
@@ -0,0 +1,80 @@
+/*
+ * mms.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_CONTENT_MMS
+
+
+static void ndpi_int_mms_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_CONTENT_MMS, NDPI_REAL_PROTOCOL);
+}
+
+
+void ndpi_search_mms_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ /* search MSMMS packets */
+ if (packet->payload_packet_len >= 20) {
+ if (flow->l4.tcp.mms_stage == 0 && packet->payload[4] == 0xce
+ && packet->payload[5] == 0xfa && packet->payload[6] == 0x0b
+ && packet->payload[7] == 0xb0 && packet->payload[12] == 0x4d
+ && packet->payload[13] == 0x4d && packet->payload[14] == 0x53 && packet->payload[15] == 0x20) {
+ NDPI_LOG(NDPI_CONTENT_MMS, ndpi_struct, NDPI_LOG_DEBUG, "MMS: MSMMS Request found \n");
+ flow->l4.tcp.mms_stage = 1 + packet->packet_direction;
+ return;
+ }
+
+ if (flow->l4.tcp.mms_stage == 2 - packet->packet_direction
+ && packet->payload[4] == 0xce && packet->payload[5] == 0xfa
+ && packet->payload[6] == 0x0b && packet->payload[7] == 0xb0
+ && packet->payload[12] == 0x4d && packet->payload[13] == 0x4d
+ && packet->payload[14] == 0x53 && packet->payload[15] == 0x20) {
+ NDPI_LOG(NDPI_CONTENT_MMS, ndpi_struct, NDPI_LOG_DEBUG, "MMS: MSMMS Response found \n");
+ ndpi_int_mms_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+#ifdef NDPI_PROTOCOL_HTTP
+ if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_HTTP) != 0) {
+#endif /* NDPI_PROTOCOL_HTTP */
+ NDPI_LOG(NDPI_CONTENT_MMS, ndpi_struct, NDPI_LOG_DEBUG, "MMS: exclude\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_CONTENT_MMS);
+
+#ifdef NDPI_PROTOCOL_HTTP
+ } else {
+ NDPI_LOG(NDPI_CONTENT_MMS, ndpi_struct, NDPI_LOG_DEBUG, "MMS avoid early exclude from http\n");
+ }
+#endif /* NDPI_PROTOCOL_HTTP */
+
+}
+#endif
diff --git a/src/lib/protocols/msn.c b/src/lib/protocols/msn.c
new file mode 100644
index 000000000..a34367071
--- /dev/null
+++ b/src/lib/protocols/msn.c
@@ -0,0 +1,563 @@
+/*
+ * msn.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_MSN
+
+#define MAX_PACKETS_FOR_MSN 100
+static void ndpi_int_msn_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow,
+ ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MSN, protocol_type);
+}
+
+static u_int8_t ndpi_int_find_xmsn(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if (packet->parsed_lines > 3) {
+ u_int16_t i;
+ for (i = 2; i < packet->parsed_lines; i++) {
+ if (packet->line[i].ptr != NULL && packet->line[i].len > NDPI_STATICSTRING_LEN("X-MSN") &&
+ memcmp(packet->line[i].ptr, "X-MSN", NDPI_STATICSTRING_LEN("X-MSN")) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+static void ndpi_search_msn_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ u_int16_t plen;
+ u_int16_t status = 0;
+
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "MSN tcp detection...\n");
+#ifdef NDPI_PROTOCOL_SSL
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "msn ssl ft test\n");
+ if (flow->packet_counter < 10) {
+ }
+
+ if (flow->packet_counter == 7 && packet->payload_packet_len > 300) {
+ if (memcmp(packet->payload + 24, "MSNSLP", 6) == 0
+ || (get_u_int32_t(packet->payload, 0) == htonl(0x30000000) && get_u_int32_t(packet->payload, 4) == 0x00000000)) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "detected MSN File Transfer, ifdef ssl.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ if (flow->packet_counter >= 5 && flow->packet_counter <= 10 && (get_u_int32_t(packet->payload, 0) == htonl(0x18000000)
+ && get_u_int32_t(packet->payload, 4) == 0x00000000)) {
+ flow->l4.tcp.msn_ssl_ft++;
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "increased msn ft ssl stage to: %u at packet nr: %u\n", flow->l4.tcp.msn_ssl_ft,
+ flow->packet_counter);
+ if (flow->l4.tcp.msn_ssl_ft == 2) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "detected MSN File Transfer, ifdef ssl 2.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ }
+ return;
+ }
+ }
+#endif
+
+
+
+ /* we detect the initial connection only ! */
+ /* match: "VER " ..... "CVR" x 0x0d 0x0a
+ * len should be small, lets say less than 100 bytes
+ * x is now "0", but can be increased
+ */
+ /* now we have a look at the first packet only. */
+ if (flow->packet_counter == 1
+#ifdef NDPI_PROTOCOL_SSL
+ || ((packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) && flow->packet_counter <= 3)
+#endif
+ ) {
+
+ /* this part is working asymmetrically */
+ if (packet->payload_packet_len > 32 && (packet->payload[0] == 0x02 || packet->payload[0] == 0x00)
+ && (ntohl(get_u_int32_t(packet->payload, 8)) == 0x2112a442 || ntohl(get_u_int32_t(packet->payload, 4)) == 0x2112a442)
+ && ((ntohl(get_u_int32_t(packet->payload, 24)) == 0x000f0004 && ntohl(get_u_int32_t(packet->payload, 28)) == 0x72c64bc6)
+ || (ntohl(get_u_int32_t(packet->payload, 20)) == 0x000f0004
+ && ntohl(get_u_int32_t(packet->payload, 24)) == 0x72c64bc6))) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "found MSN in packets that also contain voice.messenger.live.com.\n");
+
+ /* TODO this is an alternative pattern for video detection */
+ /* if (packet->payload_packet_len > 100 &&
+ get_u_int16_t(packet->payload, 86) == htons(0x05dc)) { */
+ if (packet->payload_packet_len > 101 && packet->payload[101] == 0x02) {
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ } else {
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ }
+
+ return;
+ }
+
+ /* this case works asymmetrically */
+ if (packet->payload_packet_len > 10 && packet->payload_packet_len < 100) {
+ if (get_u_int8_t(packet->payload, packet->payload_packet_len - 2) == 0x0d
+ && get_u_int8_t(packet->payload, packet->payload_packet_len - 1) == 0x0a) {
+ /* The MSNP string is used in XBOX clients. */
+ if (memcmp(packet->payload, "VER ", 4) == 0) {
+
+ if (memcmp(&packet->payload[packet->payload_packet_len - 6], "CVR",
+ 3) == 0 || memcmp(&packet->payload[packet->payload_packet_len - 8], "MSNP", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "found MSN by pattern VER...CVR/MSNP ODOA.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (memcmp(&packet->payload[4], "MSNFT", 5) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "found MSN FT by pattern VER MSNFT...0d0a.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ }
+ }
+
+ if (
+#ifdef NDPI_PROTOCOL_HTTP
+ packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP ||
+#endif
+ memcmp(packet->payload, "GET ", NDPI_STATICSTRING_LEN("GET ")) == 0 ||
+ memcmp(packet->payload, "POST ", NDPI_STATICSTRING_LEN("POST ")) == 0) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->user_agent_line.ptr != NULL &&
+ packet->user_agent_line.len > NDPI_STATICSTRING_LEN("Messenger/") &&
+ memcmp(packet->user_agent_line.ptr, "Messenger/", NDPI_STATICSTRING_LEN("Messenger/")) == 0) {
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+#ifdef NDPI_PROTOCOL_HTTP
+ /* we have to examine two http packets */
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP) {
+ }
+#endif
+ /* not seen this pattern in any trace */
+ /* now test for http login, at least 100 a bytes packet */
+ if (packet->payload_packet_len > 100) {
+ if (
+#ifdef NDPI_PROTOCOL_HTTP
+ packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP ||
+#endif
+ memcmp(packet->payload, "POST http://", 12) == 0) {
+ /* scan packet if not already done... */
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if (packet->content_line.ptr != NULL &&
+ ((packet->content_line.len == NDPI_STATICSTRING_LEN("application/x-msn-messenger") &&
+ memcmp(packet->content_line.ptr, "application/x-msn-messenger",
+ NDPI_STATICSTRING_LEN("application/x-msn-messenger")) == 0) ||
+ (packet->content_line.len >= NDPI_STATICSTRING_LEN("text/x-msnmsgr") &&
+ memcmp(packet->content_line.ptr, "text/x-msnmsgr",
+ NDPI_STATICSTRING_LEN("text/x-msnmsgr")) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "found MSN by pattern POST http:// .... application/x-msn-messenger.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+
+ /* now test for http login that uses a gateway, at least 400 a bytes packet */
+ /* for this case the asymmetric detection is asym (1) */
+ if (packet->payload_packet_len > 400) {
+ if ((
+#ifdef NDPI_PROTOCOL_HTTP
+ packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP ||
+#endif
+ (memcmp(packet->payload, "POST ", 5) == 0))) {
+ u_int16_t c;
+ if (memcmp(&packet->payload[5], "http://", 7) == 0) {
+ /*
+ * We are searching for a paten "POST http://gateway.messenger.hotmail.com/gateway/gateway.dll" or
+ * "POST http://<some ip addres here like 172.0.0.0>/gateway/gateway.dll"
+ * POST http:// is 12 byte so we are searching for 13 to 70 byte for this paten.
+ */
+ for (c = 13; c < 50; c++) {
+ if (memcmp(&packet->payload[c], "/", 1) == 0) {
+ if (memcmp(&packet->payload[c], "/gateway/gateway.dll", 20) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "found pattern http://.../gateway/gateway.ddl.\n");
+ status = 1;
+ break;
+ }
+ }
+ }
+ } else if ((memcmp(&packet->payload[5], "/gateway/gateway.dll", 20) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "found pattern http://.../gateway/gateway.ddl.\n");
+ status = 1;
+ }
+ }
+ if (status) {
+ u_int16_t a;
+
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if (packet->content_line.ptr != NULL
+ &&
+ ((packet->content_line.len == 23
+ && memcmp(packet->content_line.ptr, "text/xml; charset=utf-8", 23) == 0)
+ ||
+ (packet->content_line.len == 24
+ && memcmp(packet->content_line.ptr, "text/html; charset=utf-8", 24) == 0)
+ ||
+ (packet->content_line.len == 33
+ && memcmp(packet->content_line.ptr, "application/x-www-form-urlencoded", 33) == 0)
+ )) {
+ if ((src != NULL
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, NDPI_PROTOCOL_MSN)
+ != 0) || (dst != NULL
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask,
+ NDPI_PROTOCOL_MSN)
+ != 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "found MSN with pattern text/xml; charset=utf-8.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ for (a = 0; a < packet->parsed_lines; a++) {
+ if (packet->line[a].len >= 4 &&
+ (memcmp(packet->line[a].ptr, "CVR ", 4) == 0
+ || memcmp(packet->line[a].ptr, "VER ",
+ 4) == 0 || memcmp(packet->line[a].ptr, "ANS ", 4) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "found MSN with pattern text/sml; charset0utf-8.\n");
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct,
+ NDPI_LOG_TRACE, "MSN xml CVS / VER / ANS found\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+ }
+ }
+ /* asym (1) ; possibly occurs in symmetric cases also. */
+ if (flow->packet_counter <= 10 &&
+ (flow->packet_direction_counter[0] <= 2 || flow->packet_direction_counter[1] <= 2)
+ && packet->payload_packet_len > 100) {
+ /* not necessary to check the length, because this has been done : >400. */
+ if (
+#ifdef NDPI_PROTOCOL_HTTP
+ packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP ||
+#endif
+ (memcmp(packet->payload, "HTTP/1.0 200 OK", 15) == 0) ||
+ (memcmp(packet->payload, "HTTP/1.1 200 OK", 15) == 0)
+ ) {
+
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if (packet->content_line.ptr != NULL &&
+ ((packet->content_line.len == NDPI_STATICSTRING_LEN("application/x-msn-messenger") &&
+ memcmp(packet->content_line.ptr, "application/x-msn-messenger",
+ NDPI_STATICSTRING_LEN("application/x-msn-messenger")) == 0) ||
+ (packet->content_line.len >= NDPI_STATICSTRING_LEN("text/x-msnmsgr") &&
+ memcmp(packet->content_line.ptr, "text/x-msnmsgr",
+ NDPI_STATICSTRING_LEN("text/x-msnmsgr")) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "HTTP/1.0 200 OK .... application/x-msn-messenger.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ if (ndpi_int_find_xmsn(ndpi_struct, flow) == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "HTTP/1.0 200 OK .... X-MSN.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+
+
+ /* did not find any trace with this pattern !!!!! */
+ /* now block proxy connection */
+ if (packet->payload_packet_len >= 42) {
+ if (memcmp(packet->payload, "CONNECT messenger.hotmail.com:1863 HTTP/1.", 42) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "found MSN with pattern CONNECT messenger.hotmail.com:1863 HTTP/1..\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+
+ if (packet->payload_packet_len >= 18) {
+
+ if (memcmp(packet->payload, "USR ", 4) == 0 || memcmp(packet->payload, "ANS ", 4) == 0) {
+ /* now we must see a number */
+ const u_int16_t endlen = packet->payload_packet_len - 12;
+ plen = 4;
+ while (1) {
+ if (packet->payload[plen] == ' ') {
+ break;
+ }
+ if (packet->payload[plen] < '0' || packet->payload[plen] > '9') {
+ goto ndpi_msn_exclude;
+ }
+ plen++;
+ if (plen >= endlen) {
+ goto ndpi_msn_exclude;
+ }
+ }
+
+ while (plen < endlen) {
+ if (ndpi_check_for_email_address(ndpi_struct, flow, plen) != 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "found mail address\n");
+ break;
+ }
+ if (packet->payload_packet_len > plen + 1
+ && (packet->payload[plen] < 20 || packet->payload[plen] > 128)) {
+ goto ndpi_msn_exclude;
+ }
+ plen++;
+ if (plen >= endlen) {
+ goto ndpi_msn_exclude;
+ }
+
+ }
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "found MSN with pattern USR/ANS ...mail_address.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ }
+
+ /* finished examining the first packet only. */
+
+
+ /* asym (1) ; possibly occurs in symmetric cases also. */
+ if (flow->packet_counter <= 10 &&
+ (flow->packet_direction_counter[0] <= 2 || flow->packet_direction_counter[1] <= 2) &&
+ packet->payload_packet_len > 100) {
+ /* not necessary to check the length, because this has been done : >400. */
+ if (
+#ifdef NDPI_PROTOCOL_HTTP
+ packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP ||
+#endif
+ (memcmp(packet->payload, "HTTP/1.0 200 OK", 15) == 0) ||
+ (memcmp(packet->payload, "HTTP/1.1 200 OK", 15) == 0)
+ ) {
+
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if (packet->content_line.ptr != NULL &&
+ ((packet->content_line.len == NDPI_STATICSTRING_LEN("application/x-msn-messenger") &&
+ memcmp(packet->content_line.ptr, "application/x-msn-messenger",
+ NDPI_STATICSTRING_LEN("application/x-msn-messenger")) == 0) ||
+ (packet->content_line.len >= NDPI_STATICSTRING_LEN("text/x-msnmsgr") &&
+ memcmp(packet->content_line.ptr, "text/x-msnmsgr", NDPI_STATICSTRING_LEN("text/x-msnmsgr")) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE,
+ "HTTP/1.0 200 OK .... application/x-msn-messenger.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ if (ndpi_int_find_xmsn(ndpi_struct, flow) == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "HTTP/1.0 200 OK .... X-MSN.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+
+
+
+
+ /* finished examining the secone packet only */
+ /* direct user connection (file transfer,...) */
+
+ if ((src != NULL && NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, NDPI_PROTOCOL_MSN) != 0)
+ || (dst != NULL
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, NDPI_PROTOCOL_MSN) != 0)) {
+ if (flow->packet_counter == 1 &&
+ packet->payload_packet_len > 12 && memcmp(packet->payload, "recipientid=", 12) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "detected file transfer.\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+ /* MSN File Transfer of MSN 8.1 and 8.5
+ * first packet with length 4 and pattern 0x04000000
+ * second packet (in the same direction), with length 56 and pattern 0x00000000 from payload[16]
+ * third packet (in the opposite direction to 1 & 2), with length 4 and pattern 0x30000000
+ */
+ if (flow->l4.tcp.msn_stage == 0) {
+ /* asymmetric detection to this pattern is asym (2) */
+ if ((packet->payload_packet_len == 4 || packet->payload_packet_len == 8)
+ && get_u_int32_t(packet->payload, 0) == htonl(0x04000000)) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "maybe first TCP MSN detected\n");
+
+ if (packet->payload_packet_len == 8 && get_u_int32_t(packet->payload, 4) == htonl(0x666f6f00)) {
+ flow->l4.tcp.msn_stage = 5 + packet->packet_direction;
+ return;
+ }
+
+ flow->l4.tcp.msn_stage = 1 + packet->packet_direction;
+ return;
+ }
+ /* asymmetric detection to this pattern is asym (2) */
+ } else if (flow->l4.tcp.msn_stage == 1 + packet->packet_direction) {
+ if (packet->payload_packet_len > 10 && get_u_int32_t(packet->payload, 0) == htonl(0x666f6f00)) {
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "MSN File Transfer detected 1\n");
+ return;
+ }
+ /* did not see this pattern in any trace */
+ if (packet->payload_packet_len == 56 && get_u_int32_t(packet->payload, 16) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "maybe Second TCP MSN detected\n");
+ flow->l4.tcp.msn_stage = 3 + packet->packet_direction;
+ return;
+ }
+
+
+ } else if (flow->l4.tcp.msn_stage == 2 - packet->packet_direction
+ && packet->payload_packet_len == 4 && get_u_int32_t(packet->payload, 0) == htonl(0x30000000)) {
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "MSN File Transfer detected 2\n");
+ return;
+ } else if ((flow->l4.tcp.msn_stage == 3 + packet->packet_direction)
+ || (flow->l4.tcp.msn_stage == 4 - packet->packet_direction)) {
+ if (packet->payload_packet_len == 4 && get_u_int32_t(packet->payload, 0) == htonl(0x30000000)) {
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "MSN File Transfer detected 2\n");
+ return;
+ }
+ } else if (flow->l4.tcp.msn_stage == 6 - packet->packet_direction) {
+ if ((packet->payload_packet_len == 4) &&
+ (get_u_int32_t(packet->payload, 0) == htonl(0x10000000) || get_u_int32_t(packet->payload, 0) == htonl(0x30000000))) {
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "MSN File Transfer detected 3\n");
+ return;
+ }
+ } else if (flow->l4.tcp.msn_stage == 5 + packet->packet_direction) {
+ if ((packet->payload_packet_len == 20) && get_u_int32_t(packet->payload, 0) == htonl(0x10000000)) {
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "MSN File Transfer detected 3\n");
+ return;
+ }
+ }
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_DEBUG, "msn 7.\n");
+ if (flow->packet_counter <= MAX_PACKETS_FOR_MSN) {
+ if (packet->tcp->source == htons(443)
+ || packet->tcp->dest == htons(443)) {
+ if (packet->payload_packet_len > 300) {
+ if (memcmp(&packet->payload[40], "INVITE MSNMSGR", 14) == 0
+ || memcmp(&packet->payload[56], "INVITE MSNMSGR", 14) == 0
+ || memcmp(&packet->payload[172], "INVITE MSNMSGR", 14) == 0) {
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "MSN File Transfer detected 3\n");
+ return;
+ }
+ }
+ return;
+ }
+ /* For no
+ n port 443 flows exclude flow bitmask after first packet itself */
+ }
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "MSN tcp excluded.\n");
+ ndpi_msn_exclude:
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MSN);
+}
+
+
+
+static void ndpi_search_udp_msn_misc(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+
+ /* do we have an msn login ? */
+ if ((src == NULL || NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, NDPI_PROTOCOL_MSN) == 0)
+ && (dst == NULL
+ || NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, NDPI_PROTOCOL_MSN) == 0)) {
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MSN);
+ return;
+ }
+
+ /* asymmetric ft detection works */
+ if (packet->payload_packet_len == 20
+ && get_u_int32_t(packet->payload, 4) == 0 && packet->payload[9] == 0
+ && get_u_int16_t(packet->payload, 10) == htons(0x0100)) {
+ NDPI_LOG(NDPI_PROTOCOL_MSN, ndpi_struct, NDPI_LOG_TRACE, "msn udp misc data connection detected\n");
+ ndpi_int_msn_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ }
+
+ /* asymmetric detection working. */
+ return;
+ //}
+}
+
+
+void ndpi_search_msn(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ /* this if request should always be true */
+ if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MSN) == 0) {
+ /* we deal with tcp now */
+ if (packet->tcp != NULL) {
+ /* msn can use http or ssl for connection. That's why every http, ssl and ukn packet must enter in the msn detection */
+ /* the detection can swich out the http or the ssl detection. In this case we need not check those protocols */
+ // need to do the ceck when protocol == http too (POST /gateway ...)
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN
+#if defined(NDPI_PROTOCOL_HTTP)
+ || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP
+#endif
+#if defined(NDPI_PROTOCOL_SSL)
+ || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL
+#endif
+#if defined(NDPI_PROTOCOL_STUN)
+ || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN
+#endif
+ ) {
+ ndpi_search_msn_tcp(ndpi_struct, flow);
+ }
+ } else if (packet->udp != NULL) {
+ ndpi_search_udp_msn_misc(ndpi_struct, flow);
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/mssql.c b/src/lib/protocols/mssql.c
new file mode 100644
index 000000000..15f2ab210
--- /dev/null
+++ b/src/lib/protocols/mssql.c
@@ -0,0 +1,61 @@
+/*
+ * mssql.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+/* include files */
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_MSSQL
+
+static void ndpi_int_mssql_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MSSQL, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_mssql(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+
+
+ NDPI_LOG(NDPI_PROTOCOL_MSSQL, ndpi_struct, NDPI_LOG_DEBUG, "search mssql.\n");
+
+
+ if (packet->payload_packet_len > 51 && ntohs(get_u_int32_t(packet->payload, 0)) == 0x1201
+ && ntohs(get_u_int16_t(packet->payload, 2)) == packet->payload_packet_len
+ && ntohl(get_u_int32_t(packet->payload, 4)) == 0x00000100 && memcmp(&packet->payload[41], "sqlexpress", 10) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_MSSQL, ndpi_struct, NDPI_LOG_DEBUG, "found mssql.\n");
+ ndpi_int_mssql_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+
+ NDPI_LOG(NDPI_PROTOCOL_MSSQL, ndpi_struct, NDPI_LOG_DEBUG, "exclude mssql.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MSSQL);
+}
+#endif
diff --git a/src/lib/protocols/mysql.c b/src/lib/protocols/mysql.c
new file mode 100644
index 000000000..107b1888e
--- /dev/null
+++ b/src/lib/protocols/mysql.c
@@ -0,0 +1,70 @@
+/*
+ * mysql.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_MYSQL
+
+static void ndpi_int_mysql_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_MYSQL, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_mysql_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len > 37 //min length
+ && get_u_int16_t(packet->payload, 0) == packet->payload_packet_len - 4 //first 3 bytes are length
+ && get_u_int8_t(packet->payload, 2) == 0x00 //3rd byte of packet length
+ && get_u_int8_t(packet->payload, 3) == 0x00 //packet sequence number is 0 for startup packet
+ && get_u_int8_t(packet->payload, 5) > 0x30 //server version > 0
+ && get_u_int8_t(packet->payload, 5) < 0x37 //server version < 7
+ && get_u_int8_t(packet->payload, 6) == 0x2e //dot
+ ) {
+ u_int32_t a;
+ for (a = 7; a + 31 < packet->payload_packet_len; a++) {
+ if (packet->payload[a] == 0x00) {
+ if (get_u_int8_t(packet->payload, a + 13) == 0x00 //filler byte
+ && get_u_int64_t(packet->payload, a + 19) == 0x0ULL //13 more
+ && get_u_int32_t(packet->payload, a + 27) == 0x0 //filler bytes
+ && get_u_int8_t(packet->payload, a + 31) == 0x0) {
+ NDPI_LOG(NDPI_PROTOCOL_MYSQL, ndpi_struct, NDPI_LOG_DEBUG, "MySQL detected.\n");
+ ndpi_int_mysql_add_connection(ndpi_struct, flow);
+ return;
+ }
+ break;
+ }
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_MYSQL);
+
+}
+
+#endif
diff --git a/src/lib/protocols/netbios.c b/src/lib/protocols/netbios.c
new file mode 100644
index 000000000..41f13b0f6
--- /dev/null
+++ b/src/lib/protocols/netbios.c
@@ -0,0 +1,368 @@
+/*
+ * netbios.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_NETBIOS
+
+/* The function below has been inherited by tcpdump */
+static int netbios_name_interpret(char *in, char *out, u_int out_len) {
+ int ret, len;
+ char *b;
+
+ len = (*in++)/2;
+ b = out;
+ *out=0;
+
+ if(len > (out_len-1) || len < 1)
+ return(-1);
+
+ while (len--) {
+ if(in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
+ *out = 0;
+ return(-1);
+ }
+
+ *out = ((in[0]-'A')<<4) + (in[1]-'A');
+ in += 2;
+ out++;
+ }
+ ret = *(--out);
+ *out = 0;
+
+ /* Courtesy of Roberto F. De Luca <deluca@tandar.cnea.gov.ar> */
+ /* Trim trailing whitespace from the returned string */
+ for(out--; out>=b && *out==' '; out--) *out = '\0';
+
+ return(ret);
+}
+
+
+static void ndpi_int_netbios_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_NETBIOS, NDPI_REAL_PROTOCOL);
+}
+
+
+void ndpi_search_netbios(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ u_int16_t dport;
+
+ if (packet->udp != NULL) {
+ dport = ntohs(packet->udp->dest);
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG, "netbios udp start\n");
+
+ /*check standard NETBIOS over udp to port 137 */
+ if ((dport == 137 || 0) && packet->payload_packet_len >= 50) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG, "found netbios port 137 and payload_packet_len 50\n");
+
+ if (ntohs(get_u_int16_t(packet->payload, 2)) == 0 &&
+ ntohs(get_u_int16_t(packet->payload, 4)) == 1 &&
+ ntohs(get_u_int16_t(packet->payload, 6)) == 0 &&
+ ntohs(get_u_int16_t(packet->payload, 8)) == 0 && ntohs(get_u_int16_t(packet->payload, 10)) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG, "found netbios with questions = 1 and answers = 0, authority = 0 \n");
+
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload[2] == 0x80 &&
+ ntohs(get_u_int16_t(packet->payload, 4)) == 1 &&
+ ntohs(get_u_int16_t(packet->payload, 6)) == 0 &&
+ ntohs(get_u_int16_t(packet->payload, 8)) == 0 && ntohs(get_u_int16_t(packet->payload, 10)) == 1) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG, "found netbios with questions = 1 and answers, authority, additional = 0 \n");
+
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (ntohs(get_u_int16_t(packet->payload, 2)) == 0x4000 &&
+ ntohs(get_u_int16_t(packet->payload, 4)) == 1 &&
+ ntohs(get_u_int16_t(packet->payload, 6)) == 0 &&
+ ntohs(get_u_int16_t(packet->payload, 8)) == 0 && ntohs(get_u_int16_t(packet->payload, 10)) == 1) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG, "found netbios with questions = 1 and answers = 0, authority = 0 \n");
+
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (ntohs(get_u_int16_t(packet->payload, 2)) == 0x8400 &&
+ ntohs(get_u_int16_t(packet->payload, 4)) == 0 &&
+ ntohs(get_u_int16_t(packet->payload, 6)) == 1 &&
+ ntohs(get_u_int16_t(packet->payload, 8)) == 0 && ntohs(get_u_int16_t(packet->payload, 10)) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG,
+ "found netbios with flag 8400 questions = 0 and answers = 1, authority, additional = 0 \n");
+
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (ntohs(get_u_int16_t(packet->payload, 2)) == 0x8500 &&
+ ntohs(get_u_int16_t(packet->payload, 4)) == 0 &&
+ ntohs(get_u_int16_t(packet->payload, 6)) == 1 &&
+ ntohs(get_u_int16_t(packet->payload, 8)) == 0 && ntohs(get_u_int16_t(packet->payload, 10)) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG,
+ "found netbios with flag 8500 questions = 0 and answers = 1, authority, additional = 0 \n");
+
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (ntohs(get_u_int16_t(packet->payload, 2)) == 0x2910 &&
+ ntohs(get_u_int16_t(packet->payload, 4)) == 1 &&
+ ntohs(get_u_int16_t(packet->payload, 6)) == 0 &&
+ ntohs(get_u_int16_t(packet->payload, 8)) == 0 && ntohs(get_u_int16_t(packet->payload, 10)) == 1) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG,
+ "found netbios with flag 2910, questions = 1 and answers, authority=0, additional = 1 \n");
+
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (ntohs(get_u_int16_t(packet->payload, 2)) == 0xAD86 &&
+ ntohs(get_u_int16_t(packet->payload, 4)) == 0 &&
+ ntohs(get_u_int16_t(packet->payload, 6)) == 1 &&
+ ntohs(get_u_int16_t(packet->payload, 8)) == 0 && ntohs(get_u_int16_t(packet->payload, 10)) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG,
+ "found netbios with flag ad86 questions = 0 and answers = 1, authority, additional = 0 \n");
+
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (ntohs(get_u_int16_t(packet->payload, 2)) == 0x0110 &&
+ ntohs(get_u_int16_t(packet->payload, 4)) == 1 &&
+ ntohs(get_u_int16_t(packet->payload, 6)) == 0 &&
+ ntohs(get_u_int16_t(packet->payload, 8)) == 0 && ntohs(get_u_int16_t(packet->payload, 10)) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG,
+ "found netbios with flag 0110 questions = 1 and answers = 0, authority, additional = 0 \n");
+
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ if ((ntohs(get_u_int16_t(packet->payload, 2)) & 0xf800) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG, "possible netbios name query request\n");
+
+ if (get_u_int16_t(packet->payload, 4) == htons(1) &&
+ get_u_int16_t(packet->payload, 6) == 0 &&
+ get_u_int16_t(packet->payload, 8) == 0 && get_u_int16_t(packet->payload, 10) == 0) {
+
+ /* name is encoded as described in rfc883 */
+ u_int8_t name_length = packet->payload[12];
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "possible netbios name query request, one question\n");
+
+ if (packet->payload_packet_len == 12 + 1 + name_length + 1 + 2 + 2) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "possible netbios name query request, length matches\n");
+
+ /* null terminated? */
+ if (packet->payload[12 + name_length + 1] == 0 &&
+ get_u_int16_t(packet->payload, 12 + name_length + 2) == htons(0x0020) &&
+ get_u_int16_t(packet->payload, 12 + name_length + 4) == htons(0x0001)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "found netbios name query request\n");
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+ } else if ((ntohs(get_u_int16_t(packet->payload, 2)) & 0xf800) == 0x8000) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "possible netbios name query response\n");
+
+ if (get_u_int16_t(packet->payload, 4) == 0 &&
+ get_u_int16_t(packet->payload, 6) == htons(1) &&
+ get_u_int16_t(packet->payload, 8) == 0 && get_u_int16_t(packet->payload, 10) == 0) {
+
+ /* name is encoded as described in rfc883 */
+ u_int8_t name_length = packet->payload[12];
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "possible netbios positive name query response, one answer\n");
+
+ if (packet->payload_packet_len >= 12 + 1 + name_length + 1 + 2 + 2) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "possible netbios name query response, length matches\n");
+
+ /* null terminated? */
+ if (packet->payload[12 + name_length + 1] == 0 &&
+ get_u_int16_t(packet->payload, 12 + name_length + 2) == htons(0x0020) &&
+ get_u_int16_t(packet->payload, 12 + name_length + 4) == htons(0x0001)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "found netbios name query response\n");
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ } else if (get_u_int16_t(packet->payload, 4) == 0 &&
+ get_u_int16_t(packet->payload, 6) == 0 &&
+ get_u_int16_t(packet->payload, 8) == 0 && get_u_int16_t(packet->payload, 10) == 0) {
+
+ /* name is encoded as described in rfc883 */
+ u_int8_t name_length = packet->payload[12];
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "possible netbios negative name query response, one answer\n");
+
+ if (packet->payload_packet_len >= 12 + 1 + name_length + 1 + 2 + 2) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "possible netbios name query response, length matches\n");
+
+ /* null terminated? */
+ if (packet->payload[12 + name_length + 1] == 0 &&
+ get_u_int16_t(packet->payload, 12 + name_length + 2) == htons(0x000A) &&
+ get_u_int16_t(packet->payload, 12 + name_length + 4) == htons(0x0001)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "found netbios name query response\n");
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ } else if (get_u_int16_t(packet->payload, 4) == 0 &&
+ get_u_int16_t(packet->payload, 6) == 0 &&
+ get_u_int16_t(packet->payload, 8) == htons(1) && get_u_int16_t(packet->payload, 10) == htons(1)) {
+
+ /* name is encoded as described in rfc883 */
+ u_int8_t name_length = packet->payload[12];
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "possible netbios redirect name query response, one answer\n");
+
+ if (packet->payload_packet_len >= 12 + 1 + name_length + 1 + 2 + 2) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "possible netbios name query response, length matches\n");
+
+ /* null terminated? */
+ if (packet->payload[12 + name_length + 1] == 0 &&
+ get_u_int16_t(packet->payload, 12 + name_length + 2) == htons(0x0002) &&
+ get_u_int16_t(packet->payload, 12 + name_length + 4) == htons(0x0001)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG,
+ "found netbios name query response\n");
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+ }
+ /* TODO: extend according to rfc1002 */
+ }
+
+ /*check standard NETBIOS over udp to port 138 */
+
+ /*netbios header token from http://www.protocolbase.net/protocols/protocol_NBDGM.php */
+
+ if ((dport == 138) &&
+ packet->payload_packet_len >= 14 &&
+ ntohs(get_u_int16_t(packet->payload, 10)) == packet->payload_packet_len - 14) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG, "found netbios port 138 and payload length >= 112 \n");
+
+ if (packet->payload[0] >= 0x11 && packet->payload[0] <= 0x16) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG, "found netbios with MSG-type 0x11,0x12,0x13,0x14,0x15 or 0x16\n");
+
+ if (ntohl(get_u_int32_t(packet->payload, 4)) == ntohl(packet->iph->saddr)) {
+ char name[32];
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG, "found netbios with checked ip-address.\n");
+
+ if(netbios_name_interpret((char*)&packet->payload[14], name, sizeof(name)) > 0)
+ snprintf((char*)flow->host_server_name, sizeof(flow->host_server_name), "%s", name);
+
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+ }
+
+ if (packet->tcp != NULL) {
+ dport = ntohs(packet->tcp->dest);
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG, "netbios tcp start\n");
+
+ /* destination port must be 139 */
+ if (dport == 139) {
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG, "found netbios with destination port 139\n");
+
+ /* payload_packet_len must be 72 */
+ if (packet->payload_packet_len == 72) {
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG, "found netbios with payload_packen_len = 72. \n");
+
+ if (packet->payload[0] == 0x81 && packet->payload[1] == 0 && ntohs(get_u_int16_t(packet->payload, 2)) == 68) {
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct,
+ NDPI_LOG_DEBUG,
+ "found netbios with session request = 81, flags=0 and length od following bytes = 68. \n");
+
+ ndpi_int_netbios_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_NETBIOS, ndpi_struct, NDPI_LOG_DEBUG, "exclude netbios\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_NETBIOS);
+
+}
+#endif
diff --git a/src/lib/protocols/netflow.c b/src/lib/protocols/netflow.c
new file mode 100644
index 000000000..ccf275a8b
--- /dev/null
+++ b/src/lib/protocols/netflow.c
@@ -0,0 +1,93 @@
+/*
+ * netflow.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_NETFLOW
+
+#ifndef __KERNEL__
+#ifdef WIN32
+extern int gettimeofday(struct timeval * tp, struct timezone * tzp);
+#endif
+#define do_gettimeofday(a) gettimeofday(a, NULL)
+#endif
+
+static void ndpi_check_netflow(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // const u_int8_t *packet_payload = packet->payload;
+ u_int32_t payload_len = packet->payload_packet_len;
+ time_t now;
+ struct timeval now_tv;
+
+ if((packet->udp != NULL) && (payload_len >= 24)) {
+ u_int16_t version = (packet->payload[0] << 8) + packet->payload[1], uptime_offset;
+ u_int32_t when, *_when;
+ u_int16_t n = (packet->payload[2] << 8) + packet->payload[3];
+
+ switch(version) {
+ case 1:
+ case 5:
+ case 7:
+ case 9:
+ {
+ u_int16_t num_flows = n;
+
+ if((num_flows == 0) || (num_flows > 30))
+ return;
+ }
+ uptime_offset = 8;
+ break;
+ case 10: /* IPFIX */
+ {
+ u_int16_t ipfix_len = n;
+
+ if(ipfix_len != payload_len)
+ return;
+ }
+ uptime_offset = 4;
+ break;
+ default:
+ return;
+ }
+
+ _when = (u_int32_t*)&packet->payload[uptime_offset]; /* Sysuptime */
+ when = ntohl(*_when);
+
+ do_gettimeofday(&now_tv);
+ now = now_tv.tv_sec;
+
+ if(((version == 1) && (when == 0))
+ || ((when >= 946684800 /* 1/1/2000 */) && (when <= now))) {
+ NDPI_LOG(NDPI_PROTOCOL_NETFLOW, ndpi_struct, NDPI_LOG_DEBUG, "Found netflow.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_NETFLOW, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+}
+
+void ndpi_search_netflow(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ NDPI_LOG(NDPI_PROTOCOL_NETFLOW, ndpi_struct, NDPI_LOG_DEBUG, "netflow detection...\n");
+ ndpi_check_netflow(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/nfs.c b/src/lib/protocols/nfs.c
new file mode 100644
index 000000000..0a3fde84b
--- /dev/null
+++ b/src/lib/protocols/nfs.c
@@ -0,0 +1,86 @@
+/*
+ * nfs.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_NFS
+
+static void ndpi_int_nfs_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_NFS, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_nfs(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ u_int8_t offset = 0;
+ if (packet->tcp != NULL)
+ offset = 4;
+
+ if (packet->payload_packet_len < (40 + offset))
+ goto exclude_nfs;
+
+ NDPI_LOG(NDPI_PROTOCOL_NFS, ndpi_struct, NDPI_LOG_DEBUG, "NFS user match stage 1\n");
+
+
+ if (offset != 0 && get_u_int32_t(packet->payload, 0) != htonl(0x80000000 + packet->payload_packet_len - 4))
+ goto exclude_nfs;
+
+ NDPI_LOG(NDPI_PROTOCOL_NFS, ndpi_struct, NDPI_LOG_DEBUG, "NFS user match stage 2\n");
+
+ if (get_u_int32_t(packet->payload, 4 + offset) != 0)
+ goto exclude_nfs;
+
+ NDPI_LOG(NDPI_PROTOCOL_NFS, ndpi_struct, NDPI_LOG_DEBUG, "NFS user match stage 3\n");
+
+ if (get_u_int32_t(packet->payload, 8 + offset) != htonl(0x02))
+ goto exclude_nfs;
+
+ NDPI_LOG(NDPI_PROTOCOL_NFS, ndpi_struct, NDPI_LOG_DEBUG, "NFS match stage 3\n");
+
+ if (get_u_int32_t(packet->payload, 12 + offset) != htonl(0x000186a5)
+ && get_u_int32_t(packet->payload, 12 + offset) != htonl(0x000186a3)
+ && get_u_int32_t(packet->payload, 12 + offset) != htonl(0x000186a0))
+ goto exclude_nfs;
+
+ NDPI_LOG(NDPI_PROTOCOL_NFS, ndpi_struct, NDPI_LOG_DEBUG, "NFS match stage 4\n");
+
+ if (ntohl(get_u_int32_t(packet->payload, 16 + offset)) > 4)
+ goto exclude_nfs;
+
+ NDPI_LOG(NDPI_PROTOCOL_NFS, ndpi_struct, NDPI_LOG_DEBUG, "NFS match\n");
+
+ ndpi_int_nfs_add_connection(ndpi_struct, flow);
+ return;
+
+ exclude_nfs:
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_NFS);
+}
+
+#endif
diff --git a/src/lib/protocols/noe.c b/src/lib/protocols/noe.c
new file mode 100644
index 000000000..218201b9a
--- /dev/null
+++ b/src/lib/protocols/noe.c
@@ -0,0 +1,52 @@
+/*
+ * noe.c (Alcatel new office environment)
+ *
+ * Copyright (C) 2013 Remy Mudingay <mudingay@ill.fr>
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+
+#ifdef NDPI_PROTOCOL_NOE
+static void ndpi_int_noe_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_NOE, NDPI_CORRELATED_PROTOCOL);
+}
+
+void ndpi_search_noe(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_NOE, ndpi_struct, NDPI_LOG_DEBUG, "search for NOE.\n");
+
+ if(packet->udp != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_NOE, ndpi_struct, NDPI_LOG_DEBUG, "calculating dport over udp.\n");
+
+ if (packet->payload_packet_len == 1 && ( packet->payload[0] == 0x05 || packet->payload[0] == 0x04 )) {
+ NDPI_LOG(NDPI_PROTOCOL_NOE, ndpi_struct, NDPI_LOG_DEBUG, "found noe.\n");
+ ndpi_int_noe_add_connection(ndpi_struct, flow);
+ return;
+ } else if((packet->payload_packet_len == 5 || packet->payload_packet_len == 12) &&
+ (packet->payload[0] == 0x07 ) &&
+ (packet->payload[1] == 0x00 ) &&
+ (packet->payload[2] != 0x00 ) &&
+ (packet->payload[3] == 0x00 )) {
+ NDPI_LOG(NDPI_PROTOCOL_NOE, ndpi_struct, NDPI_LOG_DEBUG, "found noe.\n");
+ ndpi_int_noe_add_connection(ndpi_struct, flow);
+ } else if((packet->payload_packet_len >= 25) &&
+ (packet->payload[0] == 0x00 &&
+ packet->payload[1] == 0x06 &&
+ packet->payload[2] == 0x62 &&
+ packet->payload[3] == 0x6c)) {
+ NDPI_LOG(NDPI_PROTOCOL_NOE, ndpi_struct, NDPI_LOG_DEBUG, "found noe.\n");
+ ndpi_int_noe_add_connection(ndpi_struct, flow);
+ }
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_NOE, ndpi_struct, NDPI_LOG_DEBUG, "exclude NOE.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_NOE);
+ }
+}
+#endif
diff --git a/src/lib/protocols/non_tcp_udp.c b/src/lib/protocols/non_tcp_udp.c
new file mode 100644
index 000000000..bb48b88a2
--- /dev/null
+++ b/src/lib/protocols/non_tcp_udp.c
@@ -0,0 +1,108 @@
+/*
+ * non_tcp_udp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#if defined(NDPI_PROTOCOL_IP_IPSEC) || defined(NDPI_PROTOCOL_IP_GRE) || defined(NDPI_PROTOCOL_IP_ICMP) || defined(NDPI_PROTOCOL_IP_IGMP) || defined(NDPI_PROTOCOL_IP_EGP) || defined(NDPI_PROTOCOL_IP_SCTP) || defined(NDPI_PROTOCOL_IP_OSPF) || defined(NDPI_PROTOCOL_IP_IP_IN_IP)
+
+#define set_protocol_and_bmask(nprot) \
+ { \
+ if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask,nprot) != 0) \
+ { \
+ ndpi_int_add_connection(ndpi_struct, flow, \
+ nprot, \
+ NDPI_REAL_PROTOCOL); \
+ } \
+ }
+
+
+void ndpi_search_in_non_tcp_udp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if (packet->iph == NULL) {
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ if (packet->iphv6 == NULL)
+#endif
+ return;
+ }
+
+ switch (packet->l4_protocol) {
+#ifdef NDPI_PROTOCOL_IP_IPSEC
+ case NDPI_IPSEC_PROTOCOL_ESP:
+ case NDPI_IPSEC_PROTOCOL_AH:
+ set_protocol_and_bmask(NDPI_PROTOCOL_IP_IPSEC);
+ break;
+#endif /* NDPI_PROTOCOL_IP_IPSEC */
+#ifdef NDPI_PROTOCOL_IP_GRE
+ case NDPI_GRE_PROTOCOL_TYPE:
+ set_protocol_and_bmask(NDPI_PROTOCOL_IP_GRE);
+ break;
+#endif /* NDPI_PROTOCOL_IP_GRE */
+#ifdef NDPI_PROTOCOL_IP_ICMP
+ case NDPI_ICMP_PROTOCOL_TYPE:
+ set_protocol_and_bmask(NDPI_PROTOCOL_IP_ICMP);
+ break;
+#endif /* NDPI_PROTOCOL_IP_ICMP */
+#ifdef NDPI_PROTOCOL_IP_IGMP
+ case NDPI_IGMP_PROTOCOL_TYPE:
+ set_protocol_and_bmask(NDPI_PROTOCOL_IP_IGMP);
+ break;
+#endif /* NDPI_PROTOCOL_IP_IGMP */
+#ifdef NDPI_PROTOCOL_IP_EGP
+ case NDPI_EGP_PROTOCOL_TYPE:
+ set_protocol_and_bmask(NDPI_PROTOCOL_IP_EGP);
+ break;
+#endif /* NDPI_PROTOCOL_IP_EGP */
+#ifdef NDPI_PROTOCOL_IP_SCTP
+ case NDPI_SCTP_PROTOCOL_TYPE:
+ set_protocol_and_bmask(NDPI_PROTOCOL_IP_SCTP);
+ break;
+#endif /* NDPI_PROTOCOL_IP_SCTP */
+#ifdef NDPI_PROTOCOL_IP_OSPF
+ case NDPI_OSPF_PROTOCOL_TYPE:
+ set_protocol_and_bmask(NDPI_PROTOCOL_IP_OSPF);
+ break;
+#endif /* NDPI_PROTOCOL_IP_OSPF */
+#ifdef NDPI_PROTOCOL_IP_IP_IN_IP
+ case NDPI_IPIP_PROTOCOL_TYPE:
+ set_protocol_and_bmask(NDPI_PROTOCOL_IP_IP_IN_IP);
+ break;
+#endif /* NDPI_PROTOCOL_IP_IP_IN_IP */
+#ifdef NDPI_PROTOCOL_IP_ICMPV6
+ case NDPI_ICMPV6_PROTOCOL_TYPE:
+ set_protocol_and_bmask(NDPI_PROTOCOL_IP_ICMPV6);
+ break;
+#endif /* NDPI_PROTOCOL_IP_ICMPV6 */
+#ifdef NDPI_PROTOCOL_IP_VRRP
+ case 112:
+ set_protocol_and_bmask(NDPI_PROTOCOL_IP_VRRP);
+ break;
+#endif /* NDPI_PROTOCOL_IP_VRRP */
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/ntp.c b/src/lib/protocols/ntp.c
new file mode 100644
index 000000000..7d19968c5
--- /dev/null
+++ b/src/lib/protocols/ntp.c
@@ -0,0 +1,68 @@
+/*
+ * ntp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_NTP
+
+static void ndpi_int_ntp_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_NTP, NDPI_REAL_PROTOCOL);
+}
+
+/* detection also works asymmetrically */
+
+void ndpi_search_ntp_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (!(packet->udp->dest == htons(123) || packet->udp->source == htons(123)))
+ goto exclude_ntp;
+
+ NDPI_LOG(NDPI_PROTOCOL_NTP, ndpi_struct, NDPI_LOG_DEBUG, "NTP port detected\n");
+
+ if (packet->payload_packet_len != 48)
+ goto exclude_ntp;
+
+ NDPI_LOG(NDPI_PROTOCOL_NTP, ndpi_struct, NDPI_LOG_DEBUG, "NTP length detected\n");
+
+
+ if ((((packet->payload[0] & 0x38) >> 3) <= 4)) {
+ NDPI_LOG(NDPI_PROTOCOL_NTP, ndpi_struct, NDPI_LOG_DEBUG, "detected NTP.");
+ ndpi_int_ntp_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+
+
+ exclude_ntp:
+ NDPI_LOG(NDPI_PROTOCOL_NTP, ndpi_struct, NDPI_LOG_DEBUG, "NTP excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_NTP);
+}
+
+#endif
diff --git a/src/lib/protocols/openft.c b/src/lib/protocols/openft.c
new file mode 100644
index 000000000..6f4e94bc5
--- /dev/null
+++ b/src/lib/protocols/openft.c
@@ -0,0 +1,56 @@
+/*
+ * openft.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_OPENFT
+
+static void ndpi_int_openft_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OPENFT, NDPI_CORRELATED_PROTOCOL);
+}
+
+void ndpi_search_openft_tcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len > 5 && memcmp(packet->payload, "GET /", 5) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_OPENFT, ndpi_struct, NDPI_LOG_DEBUG, "HTTP packet detected.\n");
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->parsed_lines >= 2
+ && packet->line[1].len > 13 && memcmp(packet->line[1].ptr, "X-OpenftAlias:", 14) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_OPENFT, ndpi_struct, NDPI_LOG_DEBUG, "OpenFT detected.\n");
+ ndpi_int_openft_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_OPENFT);
+}
+#endif
diff --git a/src/lib/protocols/openvpn.c b/src/lib/protocols/openvpn.c
new file mode 100644
index 000000000..df13356ff
--- /dev/null
+++ b/src/lib/protocols/openvpn.c
@@ -0,0 +1,69 @@
+/*
+ * h323.c
+ *
+ * Copyright (C) 2013 Remy Mudingay <mudingay@ill.fr>
+ *
+ */
+
+#include "ndpi_api.h"
+
+
+#ifdef NDPI_PROTOCOL_OPENVPN
+
+void ndpi_search_openvpn(struct ndpi_detection_module_struct* ndpi_struct,
+ struct ndpi_flow_struct* flow) {
+ struct ndpi_packet_struct* packet = &flow->packet;
+ u_int16_t dport = 0, sport = 0;
+
+ if (packet->udp != NULL) {
+
+ sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest);
+
+ if ((packet->payload_packet_len >= 25) && (sport == 443 || dport == 443) &&
+ (packet->payload[0] == 0x17 && packet->payload[1] == 0x01 &&
+ packet->payload[2] == 0x00 && packet->payload[3] == 0x00)) {
+ NDPI_LOG(NDPI_PROTOCOL_OPENVPN, ndpi_struct, NDPI_LOG_DEBUG,
+ "found openvpn udp 443.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OPENVPN,
+ NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ if ( ( (packet->payload_packet_len > 40) ||
+ (packet->payload_packet_len <= 14) ) && // hard-reset
+ (sport == 1194 || dport == 1194) &&
+ (packet->payload[0] == 0x30 || packet->payload[0] == 0x31 ||
+ packet->payload[0] == 0x32 || packet->payload[0] == 0x33 ||
+ packet->payload[0] == 0x34 || packet->payload[0] == 0x35 ||
+ packet->payload[0] == 0x36 || packet->payload[0] == 0x37 ||
+ packet->payload[0] == 0x38 || packet->payload[0] == 0x39)) {
+ NDPI_LOG(NDPI_PROTOCOL_OPENVPN, ndpi_struct, NDPI_LOG_DEBUG,
+ "found openvpn broadcast udp STD.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OPENVPN,
+ NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ }
+
+ if (packet->tcp != NULL) {
+
+ sport = ntohs(packet->tcp->source), dport = ntohs(packet->tcp->dest);
+
+ if ((packet->payload_packet_len >= 40) &&
+ (sport == 1194 || dport == 1194) &&
+ ((packet->payload[0] == 0x00) && (packet->payload[1] == 0x2a) &&
+ (packet->payload[2] == 0x38))) {
+ NDPI_LOG(NDPI_PROTOCOL_OPENVPN, ndpi_struct, NDPI_LOG_DEBUG,
+ "found openvpn broadcast udp STD.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OPENVPN,
+ NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask,
+ NDPI_PROTOCOL_OPENVPN);
+}
+
+#endif
diff --git a/src/lib/protocols/oracle.c b/src/lib/protocols/oracle.c
new file mode 100644
index 000000000..e6df77930
--- /dev/null
+++ b/src/lib/protocols/oracle.c
@@ -0,0 +1,62 @@
+/*
+ * oracle.c
+ *
+ * Copyright (C) 2013 Remy Mudingay <mudingay@ill.fr>
+ *
+ * This module is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This module 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+
+#ifdef NDPI_PROTOCOL_ORACLE
+static void ndpi_int_oracle_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_ORACLE, NDPI_CORRELATED_PROTOCOL);
+}
+
+void ndpi_search_oracle(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t dport = 0, sport = 0;
+
+ NDPI_LOG(NDPI_PROTOCOL_ORACLE, ndpi_struct, NDPI_LOG_DEBUG, "search for ORACLE.\n");
+
+ if(packet->tcp != NULL) {
+ sport = ntohs(packet->tcp->source), dport = ntohs(packet->tcp->dest);
+ NDPI_LOG(NDPI_PROTOCOL_ORACLE, ndpi_struct, NDPI_LOG_DEBUG, "calculating ORACLE over tcp.\n");
+ /* Oracle Database 9g,10g,11g */
+ if ((dport == 1521 || sport == 1521)
+ && (((packet->payload[0] == 0x07) && (packet->payload[1] == 0xff) && (packet->payload[2] == 0x00))
+ || ((packet->payload_packet_len >= 232) && ((packet->payload[0] == 0x00) || (packet->payload[0] == 0x01))
+ && (packet->payload[1] != 0x00)
+ && (packet->payload[2] == 0x00)
+ && (packet->payload[3] == 0x00)))) {
+ NDPI_LOG(NDPI_PROTOCOL_ORACLE, ndpi_struct, NDPI_LOG_DEBUG, "found oracle.\n");
+ ndpi_int_oracle_add_connection(ndpi_struct, flow);
+ } else if (packet->payload_packet_len == 213 && packet->payload[0] == 0x00 &&
+ packet->payload[1] == 0xd5 && packet->payload[2] == 0x00 &&
+ packet->payload[3] == 0x00 ) {
+ NDPI_LOG(NDPI_PROTOCOL_ORACLE, ndpi_struct, NDPI_LOG_DEBUG, "found oracle.\n");
+ ndpi_int_oracle_add_connection(ndpi_struct, flow);
+ }
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_ORACLE, ndpi_struct, NDPI_LOG_DEBUG, "exclude ORACLE.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_ORACLE);
+ }
+}
+#endif
diff --git a/src/lib/protocols/oscar.c b/src/lib/protocols/oscar.c
new file mode 100644
index 000000000..c9ec58eba
--- /dev/null
+++ b/src/lib/protocols/oscar.c
@@ -0,0 +1,273 @@
+/*
+ * oscar.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+
+#ifdef NDPI_PROTOCOL_OSCAR
+
+static void ndpi_int_oscar_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, ndpi_protocol_type_t protocol_type)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OSCAR, protocol_type);
+
+ if (src != NULL) {
+ src->oscar_last_safe_access_time = packet->tick_timestamp;
+ }
+ if (dst != NULL) {
+ dst->oscar_last_safe_access_time = packet->tick_timestamp;
+ }
+}
+
+static void ndpi_search_oscar_tcp_connect(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+ if (packet->payload_packet_len >= 10 && packet->payload[0] == 0x2a) {
+
+ /* if is a oscar connection, 10 bytes long */
+
+ /* OSCAR Connection :: Connection detected at initial packets only
+ * +----+----+------+------+---------------+
+ * |0x2a|Code|SeqNum|PktLen|ProtcolVersion |
+ * +----+----+------+------+---------------+
+ * Code 1 Byte : 0x01 Oscar Connection
+ * SeqNum and PktLen are 2 Bytes each and ProtcolVersion: 0x00000001
+ * */
+ if (get_u_int8_t(packet->payload, 1) == 0x01 && get_u_int16_t(packet->payload, 4) == htons(packet->payload_packet_len - 6)
+ && get_u_int32_t(packet->payload, 6) == htonl(0x0000000001)) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR Connection FOUND \n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ /* OSCAR IM
+ * +----+----+------+------+----------+-----------+
+ * |0x2a|Code|SeqNum|PktLen|FNACfamily|FNACsubtype|
+ * +----+----+------+------+----------+-----------+
+ * Code 1 Byte : 0x02 SNAC Header Code;
+ * SeqNum and PktLen are 2 Bytes each
+ * FNACfamily 2 Byte : 0x0004 IM Messaging
+ * FNACEsubtype 2 Byte : 0x0006 IM Outgoing Message, 0x000c IM Message Acknowledgment
+ * */
+ if (packet->payload[1] == 0x02
+ && ntohs(get_u_int16_t(packet->payload, 4)) >=
+ packet->payload_packet_len - 6 && get_u_int16_t(packet->payload, 6) == htons(0x0004)
+ && (get_u_int16_t(packet->payload, 8) == htons(0x0006)
+ || get_u_int16_t(packet->payload, 8) == htons(0x000c))) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR IM Detected \n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+
+ /* detect http connections */
+ if (packet->payload_packet_len >= 18) {
+ if ((packet->payload[0] == 'P') && (memcmp(packet->payload, "POST /photo/upload", 18) == 0)) {
+ NDPI_PARSE_PACKET_LINE_INFO(ndpi_struct, flow, packet);
+ if (packet->host_line.len >= 18 && packet->host_line.ptr != NULL) {
+ if (memcmp(packet->host_line.ptr, "lifestream.aol.com", 18) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG,
+ "OSCAR over HTTP found, POST method\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+ }
+ if (packet->payload_packet_len > 40) {
+ if ((packet->payload[0] == 'G') && (memcmp(packet->payload, "GET /", 5) == 0)) {
+ if ((memcmp(&packet->payload[5], "aim/fetchEvents?aimsid=", 23) == 0) ||
+ (memcmp(&packet->payload[5], "aim/startSession?", 17) == 0) ||
+ (memcmp(&packet->payload[5], "aim/gromit/aim_express", 22) == 0) ||
+ (memcmp(&packet->payload[5], "b/ss/aolwpaim", 13) == 0) ||
+ (memcmp(&packet->payload[5], "hss/storage/aimtmpshare", 23) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR over HTTP found, GET /aim/\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+
+ if ((memcmp(&packet->payload[5], "aim", 3) == 0) || (memcmp(&packet->payload[5], "im", 2) == 0)) {
+ NDPI_PARSE_PACKET_LINE_INFO(ndpi_struct, flow, packet);
+ if (packet->user_agent_line.len > 15 && packet->user_agent_line.ptr != NULL &&
+ ((memcmp(packet->user_agent_line.ptr, "mobileAIM/", 10) == 0) ||
+ (memcmp(packet->user_agent_line.ptr, "ICQ/", 4) == 0) ||
+ (memcmp(packet->user_agent_line.ptr, "mobileICQ/", 10) == 0) ||
+ (memcmp(packet->user_agent_line.ptr, "AIM%20Free/", NDPI_STATICSTRING_LEN("AIM%20Free/")) == 0) ||
+ (memcmp(packet->user_agent_line.ptr, "AIM/", 4) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR over HTTP found\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ NDPI_PARSE_PACKET_LINE_INFO(ndpi_struct, flow, packet);
+ if (packet->referer_line.ptr != NULL && packet->referer_line.len >= 22) {
+
+ if (memcmp(&packet->referer_line.ptr[packet->referer_line.len - NDPI_STATICSTRING_LEN("WidgetMain.swf")],
+ "WidgetMain.swf", NDPI_STATICSTRING_LEN("WidgetMain.swf")) == 0) {
+ u_int16_t i;
+ for (i = 0; i < (packet->referer_line.len - 22); i++) {
+ if (packet->referer_line.ptr[i] == 'a') {
+ if (memcmp(&packet->referer_line.ptr[i + 1], "im/gromit/aim_express", 21) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG,
+ "OSCAR over HTTP found : aim/gromit/aim_express\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (memcmp(packet->payload, "CONNECT ", 8) == 0) {
+ if (memcmp(packet->payload, "CONNECT login.icq.com:443 HTTP/1.", 33) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR ICQ-HTTP FOUND\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ if (memcmp(packet->payload, "CONNECT login.oscar.aol.com:5190 HTTP/1.", 40) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR AIM-HTTP FOUND\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+
+ }
+ }
+
+ if (packet->payload_packet_len > 43
+ && memcmp(packet->payload, "GET http://http.proxy.icq.com/hello HTTP/1.", 43) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR ICQ-HTTP PROXY FOUND\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+
+ if (packet->payload_packet_len > 46
+ && memcmp(packet->payload, "GET http://aimhttp.oscar.aol.com/hello HTTP/1.", 46) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR AIM-HTTP PROXY FOUND\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+
+ if (packet->payload_packet_len > 5 && get_u_int32_t(packet->payload, 0) == htonl(0x05010003)) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "Maybe OSCAR Picturetransfer\n");
+ return;
+ }
+
+ if (packet->payload_packet_len == 10 && get_u_int32_t(packet->payload, 0) == htonl(0x05000001) &&
+ get_u_int32_t(packet->payload, 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "Maybe OSCAR Picturetransfer\n");
+ return;
+ }
+
+ if (packet->payload_packet_len >= 70 &&
+ memcmp(&packet->payload[packet->payload_packet_len - 26],
+ "\x67\x00\x65\x00\x74\x00\x43\x00\x61\x00\x74\x00\x61\x00\x6c\x00\x6f\x00\x67", 19) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR PICTURE TRANSFER\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ if (NDPI_SRC_OR_DST_HAS_PROTOCOL(src, dst, NDPI_PROTOCOL_OSCAR) != 0) {
+
+ if (flow->packet_counter == 1
+ &&
+ ((packet->payload_packet_len == 9
+ && memcmp(packet->payload, "\x00\x09\x00\x00\x83\x01\xc0\x00\x00", 9) == 0)
+ || (packet->payload_packet_len == 13
+ && (memcmp(packet->payload, "\x00\x0d\x00\x87\x01\xc0", 6) == 0
+ || memcmp(packet->payload, "\x00\x0d\x00\x87\x01\xc1", 6) == 0)))) {
+ flow->oscar_video_voice = 1;
+ }
+ if (flow->oscar_video_voice && ntohs(get_u_int16_t(packet->payload, 0)) == packet->payload_packet_len
+ && packet->payload[2] == 0x00 && packet->payload[3] == 0x00) {
+ }
+
+ if (packet->payload_packet_len >= 70 && ntohs(get_u_int16_t(packet->payload, 4)) == packet->payload_packet_len) {
+ if (memcmp(packet->payload, "OFT", 3) == 0 &&
+ ((packet->payload[3] == '3' && ((memcmp(&packet->payload[4], "\x01\x00\x01\x01", 4) == 0)
+ || (memcmp(&packet->payload[6], "\x01\x01\x00", 3) == 0)))
+ || (packet->payload[3] == '2' && ((memcmp(&packet->payload[6], "\x01\x01", 2)
+ == 0)
+ )))) {
+ // FILE TRANSFER PATTERN:: OFT3 or OFT2
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR FILE TRANSFER\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ if (memcmp(packet->payload, "ODC2", 4) == 0 && memcmp(&packet->payload[6], "\x00\x01\x00\x06", 4) == 0) {
+ //PICTURE TRANSFER PATTERN EXMAPLE::
+ //4f 44 43 32 00 4c 00 01 00 06 00 00 00 00 00 00 ODC2.L..........
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR PICTURE TRANSFER\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ if (packet->payload_packet_len > 40 && (memcmp(&packet->payload[2], "\x04\x4a\x00", 3) == 0)
+ && (memcmp(&packet->payload[6], "\x00\x00", 2) == 0)
+ && packet->payload[packet->payload_packet_len - 15] == 'F'
+ && packet->payload[packet->payload_packet_len - 12] == 'L'
+ && (memcmp(&packet->payload[packet->payload_packet_len - 6], "DEST", 4) == 0)
+ && (memcmp(&packet->payload[packet->payload_packet_len - 2], "\x00\x00", 2) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR PICTURE TRANSFER\n");
+ ndpi_int_oscar_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ if (ntohs(packet->tcp->dest) == 443 || ntohs(packet->tcp->source) == 443) {
+ flow->oscar_ssl_voice_stage = 1;
+ }
+ return;
+
+ }
+ }
+ if (flow->packet_counter < 3 && packet->payload_packet_len > 11 && (memcmp(packet->payload, "\x00\x37\x04\x4a", 4)
+ || memcmp(packet->payload, "\x00\x0a\x04\x4a",
+ 4))) {
+ return;
+ }
+
+
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_OSCAR) {
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_OSCAR);
+ return;
+ }
+}
+
+void ndpi_search_oscar(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ if (packet->tcp != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR :: TCP\n");
+ ndpi_search_oscar_tcp_connect(ndpi_struct, flow);
+ }
+}
+#endif
diff --git a/src/lib/protocols/pando.c b/src/lib/protocols/pando.c
new file mode 100644
index 000000000..c409982de
--- /dev/null
+++ b/src/lib/protocols/pando.c
@@ -0,0 +1,157 @@
+/*
+ * pando.c
+ *
+ * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk>
+ *
+ * The signature is based on the Libprotoident library.
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_PANDO
+static void ndpi_int_pando_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_PANDO, NDPI_REAL_PROTOCOL);
+}
+
+static void ndpi_check_pando_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "\x0ePan")) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "Found PANDO.\n");
+ ndpi_int_pando_add_connection(ndpi_struct, flow);
+ }
+}
+
+static void ndpi_check_pando_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->pando_stage == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "PANDO stage 0: \n");
+
+ if ((payload_len >= 4) && (packet->payload[0] == 0x00) && (packet->payload[1] == 0x00) && (packet->payload[2] == 0x00) && (packet->payload[3] == 0x09)) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "Possible PANDO request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->pando_stage = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
+ return;
+ }
+
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "UDPA")) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "Possible PANDO request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->pando_stage = packet->packet_direction + 3; // packet_direction 0: stage 3, packet_direction 1: stage 4
+ return;
+ }
+
+ if ((payload_len > 0) && (match_first_bytes(packet->payload, "UDPR") || match_first_bytes(packet->payload, "UDPE"))) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "Possible PANDO request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->pando_stage = packet->packet_direction + 5; // packet_direction 0: stage 5, packet_direction 1: stage 6
+ return;
+ }
+
+ } else if ((flow->pando_stage == 1) || (flow->pando_stage == 2)) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "PANDO stage %u: \n", flow->pando_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->pando_stage - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len == 0) || ((payload_len >= 4) && (packet->payload[0] == 0x00) && (packet->payload[1] == 0x00) && (packet->payload[2] == 0x00) && (packet->payload[3] == 0x09))) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "Found PANDO.\n");
+ ndpi_int_pando_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to PANDO, resetting the stage to 0...\n");
+ flow->pando_stage = 0;
+ }
+
+ } else if ((flow->pando_stage == 3) || (flow->pando_stage == 4)) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "PANDO stage %u: \n", flow->pando_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->pando_stage - packet->packet_direction) == 3) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len == 0) || match_first_bytes(packet->payload, "UDPR") || match_first_bytes(packet->payload, "UDPE")) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "Found PANDO.\n");
+ ndpi_int_pando_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to PANDO, resetting the stage to 0...\n");
+ flow->pando_stage = 0;
+ }
+
+ } else if ((flow->pando_stage == 5) || (flow->pando_stage == 6)) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "PANDO stage %u: \n", flow->pando_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->pando_stage - packet->packet_direction) == 5) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "UDPA")) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "Found PANDO.\n");
+ ndpi_int_pando_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to PANDO, resetting the stage to 0...\n");
+ flow->pando_stage = 0;
+ }
+ }
+}
+
+void ndpi_search_pando(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ /* Break after 20 packets. */
+ if (flow->packet_counter > 20) {
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_TRACE, "PANDO excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_PANDO);
+ return;
+ }
+
+ /* skip marked or retransmitted packets */
+ if (packet->tcp_retransmission != 0) {
+ return;
+ }
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_PANDO) {
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_PANDO, ndpi_struct, NDPI_LOG_TRACE, "PANDO detection...\n");
+ ndpi_check_pando_tcp(ndpi_struct, flow);
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_PANDO) {
+ return;
+ }
+
+ ndpi_check_pando_udp(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/pcanywhere.c b/src/lib/protocols/pcanywhere.c
new file mode 100644
index 000000000..a86785cd2
--- /dev/null
+++ b/src/lib/protocols/pcanywhere.c
@@ -0,0 +1,55 @@
+/*
+ * pcanywhere.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_PCANYWHERE
+
+static void ndpi_int_pcanywhere_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_PCANYWHERE, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_pcanywhere(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->udp != NULL && packet->udp->dest == htons(5632)
+ && packet->payload_packet_len == 2
+ && (memcmp(packet->payload, "NQ", 2) == 0 || memcmp(packet->payload, "ST", 2) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_PCANYWHERE, ndpi_struct, NDPI_LOG_DEBUG,
+ "PC Anywhere name or status query detected.\n");
+ ndpi_int_pcanywhere_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_PCANYWHERE);
+}
+
+#endif
diff --git a/src/lib/protocols/postgres.c b/src/lib/protocols/postgres.c
new file mode 100644
index 000000000..bd078d8cd
--- /dev/null
+++ b/src/lib/protocols/postgres.c
@@ -0,0 +1,120 @@
+/*
+ * postgres.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_POSTGRES
+
+
+static void ndpi_int_postgres_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_POSTGRES, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_postgres_tcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ u_int16_t size;
+
+ if (flow->l4.tcp.postgres_stage == 0) {
+ //SSL
+ if (packet->payload_packet_len > 7 &&
+ packet->payload[4] == 0x04 &&
+ packet->payload[5] == 0xd2 &&
+ packet->payload[6] == 0x16 &&
+ packet->payload[7] == 0x2f && ntohl(get_u_int32_t(packet->payload, 0)) == packet->payload_packet_len) {
+ flow->l4.tcp.postgres_stage = 1 + packet->packet_direction;
+ return;
+ }
+ //no SSL
+ if (packet->payload_packet_len > 7 &&
+ //protocol version number - to be updated
+ ntohl(get_u_int32_t(packet->payload, 4)) < 0x00040000 &&
+ ntohl(get_u_int32_t(packet->payload, 0)) == packet->payload_packet_len) {
+ flow->l4.tcp.postgres_stage = 3 + packet->packet_direction;
+ return;
+ }
+ } else {
+ if (flow->l4.tcp.postgres_stage == 2 - packet->packet_direction) {
+ //SSL accepted
+ if (packet->payload_packet_len == 1 && packet->payload[0] == 'S') {
+ NDPI_LOG(NDPI_PROTOCOL_POSTGRES, ndpi_struct, NDPI_LOG_DEBUG, "PostgreSQL detected, SSL accepted.\n");
+ ndpi_int_postgres_add_connection(ndpi_struct, flow);
+ return;
+ }
+ //SSL denied
+ if (packet->payload_packet_len == 1 && packet->payload[0] == 'N') {
+ NDPI_LOG(NDPI_PROTOCOL_POSTGRES, ndpi_struct, NDPI_LOG_DEBUG, "PostgreSQL detected, SSL denied.\n");
+ ndpi_int_postgres_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ //no SSL
+ if (flow->l4.tcp.postgres_stage == 4 - packet->packet_direction)
+ if (packet->payload_packet_len > 8 &&
+ ntohl(get_u_int32_t(packet->payload, 5)) < 10 &&
+ ntohl(get_u_int32_t(packet->payload, 1)) == packet->payload_packet_len - 1 && packet->payload[0] == 0x52) {
+ NDPI_LOG(NDPI_PROTOCOL_POSTGRES, ndpi_struct, NDPI_LOG_DEBUG, "PostgreSQL detected, no SSL.\n");
+ ndpi_int_postgres_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (flow->l4.tcp.postgres_stage == 6
+ && ntohl(get_u_int32_t(packet->payload, 1)) == packet->payload_packet_len - 1 && packet->payload[0] == 'p') {
+ NDPI_LOG(NDPI_PROTOCOL_POSTGRES, ndpi_struct, NDPI_LOG_DEBUG, "found postgres asymmetrically.\n");
+ ndpi_int_postgres_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (flow->l4.tcp.postgres_stage == 5 && packet->payload[0] == 'R') {
+ if (ntohl(get_u_int32_t(packet->payload, 1)) == packet->payload_packet_len - 1) {
+ NDPI_LOG(NDPI_PROTOCOL_POSTGRES, ndpi_struct, NDPI_LOG_DEBUG, "found postgres asymmetrically.\n");
+ ndpi_int_postgres_add_connection(ndpi_struct, flow);
+ return;
+ }
+ size = (u_int16_t)ntohl(get_u_int32_t(packet->payload, 1)) + 1;
+ if (packet->payload[size - 1] == 'S') {
+ if ((size + get_u_int32_t(packet->payload, (size + 1))) == packet->payload_packet_len) {
+ NDPI_LOG(NDPI_PROTOCOL_POSTGRES, ndpi_struct, NDPI_LOG_DEBUG, "found postgres asymmetrically.\n");
+ ndpi_int_postgres_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ size += get_u_int32_t(packet->payload, (size + 1)) + 1;
+ if (packet->payload[size - 1] == 'S') {
+ NDPI_LOG(NDPI_PROTOCOL_POSTGRES, ndpi_struct, NDPI_LOG_DEBUG, "found postgres asymmetrically.\n");
+ ndpi_int_postgres_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_POSTGRES);
+}
+
+#endif
diff --git a/src/lib/protocols/pplive.c b/src/lib/protocols/pplive.c
new file mode 100644
index 000000000..1cd880503
--- /dev/null
+++ b/src/lib/protocols/pplive.c
@@ -0,0 +1,220 @@
+/*
+ * pplive.c
+ *
+ * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk>
+ *
+ * The signature is mostly based on the Libprotoident library
+ * except the detection of HTTP Steam flows.
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_PPLIVE
+static void ndpi_int_pplive_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_PPLIVE, NDPI_REAL_PROTOCOL);
+}
+
+static void ndpi_check_pplive_udp1(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->pplive_stage1 == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "PPLIVE stage 0: \n");
+
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "\xe9\x03\x41\x01")) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "Possible PPLIVE request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->pplive_stage1 = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
+ return;
+ }
+
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "\xe9\x03\x42\x01")) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "Possible PPLIVE request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->pplive_stage1 = packet->packet_direction + 3; // packet_direction 0: stage 3, packet_direction 1: stage 4
+ return;
+ }
+
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "\x1c\x1c\x32\x01")) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "Possible PPLIVE request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->pplive_stage1 = packet->packet_direction + 5; // packet_direction 0: stage 5, packet_direction 1: stage 6
+ return;
+ }
+
+ } else if ((flow->pplive_stage1 == 1) || (flow->pplive_stage1 == 2)) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "PPLIVE stage %u: \n", flow->pplive_stage1);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->pplive_stage1 - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len > 0) && (match_first_bytes(packet->payload, "\xe9\x03\x42\x01") || match_first_bytes(packet->payload, "\xe9\x03\x41\x01"))) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "Found PPLIVE.\n");
+ ndpi_int_pplive_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to PPLIVE, resetting the stage to 0...\n");
+ flow->pplive_stage1 = 0;
+ }
+
+ } else if ((flow->pplive_stage1 == 3) || (flow->pplive_stage1 == 4)) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "PPLIVE stage %u: \n", flow->pplive_stage1);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->pplive_stage1 - packet->packet_direction) == 3) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "\xe9\x03\x41\x01")) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "Found PPLIVE.\n");
+ ndpi_int_pplive_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to PPLIVE, resetting the stage to 0...\n");
+ flow->pplive_stage1 = 0;
+ }
+ } else if ((flow->pplive_stage1 == 5) || (flow->pplive_stage1 == 6)) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "PPLIVE stage %u: \n", flow->pplive_stage1);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->pplive_stage1 - packet->packet_direction) == 5) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "\x1c\x1c\x32\x01")) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "Found PPLIVE.\n");
+ ndpi_int_pplive_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to PPLIVE, resetting the stage to 0...\n");
+ flow->pplive_stage1 = 0;
+ }
+ }
+
+}
+
+static void ndpi_check_pplive_udp2(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->pplive_stage2 == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "PPLIVE stage 0: \n");
+
+ if ((payload_len == 57) && match_first_bytes(packet->payload, "\xe9\x03\x41\x01")) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "Possible PPLIVE request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->pplive_stage2 = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
+ }
+
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "PPLIVE stage %u: \n", flow->pplive_stage2);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->pplive_stage2 - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if (payload_len == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "Found PPLIVE.\n");
+ ndpi_int_pplive_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to PPLIVE, resetting the stage to 0...\n");
+ flow->pplive_stage2 = 0;
+ }
+
+ }
+}
+
+static void ndpi_check_pplive_udp3(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->pplive_stage3 == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "PPLIVE stage 0: \n");
+
+ if ((payload_len == 94) && (packet->udp->dest == htons(5041) || packet->udp->source == htons(5041) || packet->udp->dest == htons(8303) || packet->udp->source == htons(8303))) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "Possible PPLIVE request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->pplive_stage3 = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
+ return;
+ }
+
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "PPLIVE stage %u: \n", flow->pplive_stage3);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->pplive_stage3 - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len == 0) || (payload_len == 49) ||(payload_len == 94)) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "Found PPLIVE.\n");
+ ndpi_int_pplive_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to PPLIVE, resetting the stage to 0...\n");
+ flow->pplive_stage3 = 0;
+ }
+ }
+
+}
+
+void ndpi_search_pplive(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ /* Break after 20 packets. */
+ if (flow->packet_counter > 20) {
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "Exclude PPLIVE.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_PPLIVE);
+ return;
+ }
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_PPLIVE) {
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_PPLIVE, ndpi_struct, NDPI_LOG_DEBUG, "PPLIVE detection...\n");
+ ndpi_check_pplive_udp1(ndpi_struct, flow);
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_PPLIVE) {
+ return;
+ }
+
+ ndpi_check_pplive_udp2(ndpi_struct, flow);
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_PPLIVE) {
+ return;
+ }
+
+ ndpi_check_pplive_udp3(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/ppstream.c b/src/lib/protocols/ppstream.c
new file mode 100644
index 000000000..06c3c4045
--- /dev/null
+++ b/src/lib/protocols/ppstream.c
@@ -0,0 +1,105 @@
+/*
+ * ppstream.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_PPSTREAM
+
+static void ndpi_int_ppstream_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_PPSTREAM, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_ppstream(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+
+ /* check TCP Connections -> Videodata */
+ if (packet->tcp != NULL) {
+ if (packet->payload_packet_len >= 60 && get_u_int32_t(packet->payload, 52) == 0
+ && memcmp(packet->payload, "PSProtocol\x0", 11) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_PPSTREAM, ndpi_struct, NDPI_LOG_DEBUG, "found ppstream over tcp.\n");
+ ndpi_int_ppstream_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ if (packet->udp != NULL) {
+ if (packet->payload_packet_len > 2 && packet->payload[2] == 0x43
+ && ((packet->payload_packet_len - 4 == get_l16(packet->payload, 0))
+ || (packet->payload_packet_len == get_l16(packet->payload, 0))
+ || (packet->payload_packet_len >= 6 && packet->payload_packet_len - 6 == get_l16(packet->payload, 0)))) {
+ flow->l4.udp.ppstream_stage++;
+ if (flow->l4.udp.ppstream_stage == 5) {
+ NDPI_LOG(NDPI_PROTOCOL_PPSTREAM, ndpi_struct, NDPI_LOG_DEBUG,
+ "found ppstream over udp pattern len, 43.\n");
+ ndpi_int_ppstream_add_connection(ndpi_struct, flow);
+ return;
+ }
+ return;
+ }
+
+ if (flow->l4.udp.ppstream_stage == 0
+ && packet->payload_packet_len > 4 && ((packet->payload_packet_len - 4 == get_l16(packet->payload, 0))
+ || (packet->payload_packet_len == get_l16(packet->payload, 0))
+ || (packet->payload_packet_len >= 6
+ && packet->payload_packet_len - 6 == get_l16(packet->payload,
+ 0)))) {
+
+ if (packet->payload[2] == 0x00 && packet->payload[3] == 0x00 && packet->payload[4] == 0x03) {
+ flow->l4.udp.ppstream_stage = 7;
+ NDPI_LOG(NDPI_PROTOCOL_PPSTREAM, ndpi_struct, NDPI_LOG_DEBUG, "need next packet I.\n");
+ return;
+ }
+ }
+
+ if (flow->l4.udp.ppstream_stage == 7
+ && packet->payload_packet_len > 4 && packet->payload[3] == 0x00
+ && ((packet->payload_packet_len - 4 == get_l16(packet->payload, 0))
+ || (packet->payload_packet_len == get_l16(packet->payload, 0))
+ || (packet->payload_packet_len >= 6 && packet->payload_packet_len - 6 == get_l16(packet->payload, 0)))
+ && (packet->payload[2] == 0x00 && packet->payload[4] == 0x03)) {
+ NDPI_LOG(NDPI_PROTOCOL_PPSTREAM, ndpi_struct, NDPI_LOG_DEBUG,
+ "found ppstream over udp with pattern Vb.\n");
+ ndpi_int_ppstream_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+
+
+
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_PPSTREAM, ndpi_struct, NDPI_LOG_DEBUG, "exclude ppstream.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_PPSTREAM);
+}
+#endif
diff --git a/src/lib/protocols/pptp.c b/src/lib/protocols/pptp.c
new file mode 100644
index 000000000..c5ad6c8b9
--- /dev/null
+++ b/src/lib/protocols/pptp.c
@@ -0,0 +1,61 @@
+/*
+ * pptp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+/* include files */
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_PPTP
+
+static void ndpi_int_pptp_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_PPTP, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_pptp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len >= 10 && get_u_int16_t(packet->payload, 0) == htons(packet->payload_packet_len)
+ && get_u_int16_t(packet->payload, 2) == htons(0x0001) /* message type: control message */
+ &&get_u_int32_t(packet->payload, 4) == htonl(0x1a2b3c4d) /* cookie: correct */
+ &&(get_u_int16_t(packet->payload, 8) == htons(0x0001) /* control type: start-control-connection-request */
+ )) {
+
+ NDPI_LOG(NDPI_PROTOCOL_PPTP, ndpi_struct, NDPI_LOG_DEBUG, "found pptp.\n");
+ ndpi_int_pptp_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_PPTP, ndpi_struct, NDPI_LOG_DEBUG, "exclude pptp.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_PPTP);
+}
+#endif
diff --git a/src/lib/protocols/qq.c b/src/lib/protocols/qq.c
new file mode 100644
index 000000000..17c5268d9
--- /dev/null
+++ b/src/lib/protocols/qq.c
@@ -0,0 +1,665 @@
+/*
+ * qq.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_QQ
+
+static void ndpi_int_qq_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_QQ, protocol_type);
+}
+
+
+/*
+ * a qq client packet looks like this:
+ *
+ * TCP packets starts with 16 bit length, then the normal packets follows
+ *
+ * 0 1 byte packet tag (usually 0x02)
+ * 1 2 byte client tag (client version)
+ * 3 2 byte command
+ * 5 2 byte sequence number
+ * 7 4 byte userid
+ * 11 x bytes data
+ * LAST 1 byte packet tail (usually 0x03)
+ *
+ * a qq server packet looks like this:
+ *
+ * TCP packets starts with 16 bit length, then the normal packets follows
+ *
+ * 0 1 byte packet tag (usually 0x02)
+ * 1 2 byte source tag (client version, might also be a server id)
+ * 3 2 byte command (usually reply to client request, so same command id)
+ * 5 2 byte sequence number
+ * LAST 1 byte packet tail (usually 0x03)
+ *
+ * NOTE: there are other qq versions which uses different packet types!
+ */
+
+/*
+ * these are some currently known client ids (or server ids)
+ * new ids might be added here if the traffic is really QQ
+ */
+static const u_int16_t ndpi_valid_qq_versions[] = {
+ 0x0100, 0x05a5, 0x062e, 0x06d5, 0x072e, 0x0801, 0x087d, 0x08d2, 0x0961,
+ 0x0a1d, 0x0b07, 0x0b2f, 0x0b35, 0x0b37, 0x0c0b, 0x0c0d, 0x0c21, 0x0c49,
+ 0x0d05, 0x0d51, 0x0d55, 0x0d61, 0x0e1b, 0x0e35, 0x0f15, 0x0f4b, 0x0f5f,
+ 0x1105, 0x111b, 0x111d, 0x1131, 0x113f, 0x115b, 0x1203, 0x1205, 0x120b,
+ 0x1251, 0x1412, 0x1441, 0x1501, 0x1549, 0x163a, 0x1801, 0x180d, 0x1c27,
+ 0x1e0d
+};
+
+/**
+ * this functions checks whether the packet is a valid qq packet
+ * it can handle tcp and udp packets
+ */
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+u_int8_t ndpi_is_valid_qq_packet(const struct ndpi_packet_struct *packet)
+{
+ u_int8_t real_start = 0;
+ u_int16_t command;
+ u_int8_t ids, found = 0;
+ u_int16_t version_id;
+
+ if (packet->payload_packet_len < 9)
+ return 0;
+
+ /* for tcp the length is prefixed */
+ if (packet->tcp) {
+ if (ntohs(get_u_int16_t(packet->payload, 0)) != packet->payload_packet_len) {
+ return 0;
+ }
+ real_start = 2;
+ }
+
+ /* packet usually starts with 0x02 */
+ if (packet->payload[real_start] != 0x02) {
+ return 0;
+ }
+
+ /* packet usually ends with 0x03 */
+ if (packet->payload[packet->payload_packet_len - 1] != 0x03) {
+ return 0;
+ }
+
+ version_id = ntohs(get_u_int16_t(packet->payload, real_start + 1));
+
+ if (version_id == 0) {
+ return 0;
+ }
+
+ /* check for known version id */
+ for (ids = 0; ids < sizeof(ndpi_valid_qq_versions) / sizeof(ndpi_valid_qq_versions[0]); ids++) {
+ if (version_id == ndpi_valid_qq_versions[ids]) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ return 0;
+
+ command = ntohs(get_u_int16_t(packet->payload, real_start + 3));
+
+ /* these are some known commands, not all need to be checked
+ since many are used with already established connections */
+
+ switch (command) {
+ case 0x0091: /* get server */
+ case 0x00ba: /* login token */
+ case 0x00dd: /* password verify */
+ case 0x00e5:
+ case 0x00a4:
+ case 0x0030:
+ case 0x001d:
+ case 0x0001:
+ case 0x0062:
+ case 0x0002:
+ case 0x0022:
+ case 0x0029:
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ return 1;
+}
+
+/*
+ * some file transfer packets look like this
+ *
+ * 0 1 byte packet tag (usually 0x04)
+ * 1 2 byte client tag (client version)
+ * 3 2 byte length (this is speculative)
+ * LAST 1 byte packet tail (usually 0x03)
+ *
+ */
+/**
+ * this functions checks whether the packet is a valid qq file transfer packet
+ * it can handle tcp and udp packets
+ */
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+u_int8_t ndpi_is_valid_qq_ft_packet(const struct ndpi_packet_struct *packet)
+{
+ u_int8_t ids, found = 0;
+ u_int16_t version_id;
+
+ if (packet->payload_packet_len < 9)
+ return 0;
+
+ /* file transfer packets may start with 0x00 (control), 0x03 (data), 0x04 (agent) */
+
+ if (packet->payload[0] != 0x04 && packet->payload[0] != 0x03 && packet->payload[0] != 0x00) {
+ return 0;
+ }
+
+ version_id = ntohs(get_u_int16_t(packet->payload, 1));
+
+ if (version_id == 0) {
+ return 0;
+ }
+
+ /* check for known version id */
+ for (ids = 0; ids < sizeof(ndpi_valid_qq_versions) / sizeof(ndpi_valid_qq_versions[0]); ids++) {
+ if (version_id == ndpi_valid_qq_versions[ids]) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ return 0;
+
+ if (packet->payload[0] == 0x04) {
+
+ if (ntohs(get_u_int16_t(packet->payload, 3)) != packet->payload_packet_len) {
+ return 0;
+ }
+
+ /* packet usually ends with 0x03 */
+ if (packet->payload[packet->payload_packet_len - 1] != 0x03) {
+ return 0;
+ }
+ } else if (packet->payload[0] == 0x03) {
+ /* TODO currently not detected */
+ return 0;
+ } else if (packet->payload[0] == 0x00) {
+
+ /* packet length check, there might be other lengths */
+ if (packet->payload_packet_len != 84) {
+ return 0;
+ }
+
+ /* packet usually ends with 0x0c ? */
+ if (packet->payload[packet->payload_packet_len - 1] != 0x0c) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void ndpi_search_qq_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ static const u_int16_t p8000_patt_02[12] = // maybe version numbers
+ { 0x1549, 0x1801, 0x180d, 0x0961, 0x01501, 0x0e35, 0x113f, 0x0b37, 0x1131, 0x163a, 0x1e0d };
+ u_int16_t no_of_patterns = 11, index = 0;
+
+
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "search qq udp.\n");
+
+
+ if (flow->qq_stage <= 3) {
+ if ((packet->payload_packet_len == 27 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0300
+ && packet->payload[2] == 0x01)
+ || (packet->payload_packet_len == 84 && ((ntohs(get_u_int16_t(packet->payload, 0)) == 0x000e
+ && packet->payload[2] == 0x35)
+ || (ntohs(get_u_int16_t(packet->payload, 0)) == 0x0015
+ && packet->payload[2] == 0x01)
+ || (ntohs(get_u_int16_t(packet->payload, 0)) == 0x000b
+ && packet->payload[2] == 0x37)
+ || (ntohs(get_u_int16_t(packet->payload, 0)) == 0x0015
+ && packet->payload[2] == 0x49)))
+ || (packet->payload_packet_len > 10
+ && ((get_u_int16_t(packet->payload, 0) == htons(0x000b) && packet->payload[2] == 0x37)
+ || (get_u_int32_t(packet->payload, 0) == htonl(0x04163a00)
+ && packet->payload[packet->payload_packet_len - 1] == 0x03
+ && packet->payload[4] == packet->payload_packet_len)))) {
+ /*
+ if (flow->qq_stage == 3 && flow->detected_protocol == NDPI_PROTOCOL_QQ) {
+ if (flow->packet_direction_counter[0] > 0 && flow->packet_direction_counter[1] > 0) {
+ flow->protocol_subtype = NDPI_PROTOCOL_QQ_SUBTYPE_AUDIO;
+ return;
+ } else if (flow->packet_counter < 10) {
+ return;
+ }
+ } */
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,
+ "found qq udp pattern 030001 or 000e35 four times.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+ if (packet->payload_packet_len > 2 && (packet->payload[0] == 0x02 || packet->payload[0] == 0x04)) {
+ u_int16_t pat = ntohs(get_u_int16_t(packet->payload, 1));
+ for (index = 0; index < no_of_patterns; index++) {
+ if (pat == p8000_patt_02[index] && packet->payload[packet->payload_packet_len - 1] == 0x03) {
+ flow->qq_stage++;
+ // maybe we can test here packet->payload[4] == packet->payload_packet_len
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,
+ "found qq udp pattern 02 ... 03 four times.\n");
+ /*
+ if (packet->payload[0] == 0x04) {
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ } */
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+ }
+ }
+ if (packet->payload_packet_len == 84 && (packet->payload[0] == 0 || packet->payload[0] == 0x03)) {
+ u_int16_t pat = ntohs(get_u_int16_t(packet->payload, 1));
+ for (index = 0; index < no_of_patterns; index++) {
+ if (pat == p8000_patt_02[index]) {
+ flow->qq_stage++;
+ /*
+ if (flow->qq_stage == 3 && flow->packet_direction_counter[0] > 0 &&
+ flow->packet_direction_counter[1] > 0) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq udp pattern four times.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ } else */ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq udp pattern four times.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+ }
+ }
+ if (packet->payload_packet_len > 2 && packet->payload[0] == 0x04
+ && ((ntohs(get_u_int16_t(packet->payload, 1)) == 0x1549
+ || ntohs(get_u_int16_t(packet->payload, 1)) == 0x1801 || ntohs(get_u_int16_t(packet->payload, 1)) == 0x0961)
+ ||
+ (packet->payload_packet_len > 16
+ && (ntohs(get_u_int16_t(packet->payload, 1)) == 0x180d || ntohs(get_u_int16_t(packet->payload, 1)) == 0x096d)
+ && ntohl(get_u_int32_t(packet->payload, 12)) == 0x28000000
+ && ntohs(get_u_int16_t(packet->payload, 3)) == packet->payload_packet_len))
+ && packet->payload[packet->payload_packet_len - 1] == 0x03) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,
+ "found qq udp pattern 04 1159 ... 03 four times.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+ if (packet->payload_packet_len > 2 && (packet->payload[0] == 0x06 || packet->payload[0] == 0x02)
+ && ntohs(get_u_int16_t(packet->payload, 1)) == 0x0100
+ && (packet->payload[packet->payload_packet_len - 1] == 0x00
+ || packet->payload[packet->payload_packet_len - 1] == 0x03)) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,
+ "found qq udp pattern 02/06 0100 ... 03/00 four times.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+
+ if (packet->payload_packet_len > 2 && (packet->payload[0] == 0x02)
+ && ntohs(get_u_int16_t(packet->payload, 1)) == 0x1131 && packet->payload[packet->payload_packet_len - 1] == 0x03) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,
+ "found qq udp pattern 02 1131 ... 03 four times.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+
+ if (packet->payload_packet_len > 5 && get_u_int16_t(packet->payload, 0) == htons(0x0203) &&
+ ntohs(get_u_int16_t(packet->payload, 2)) == packet->payload_packet_len &&
+ get_u_int16_t(packet->payload, 4) == htons(0x0b0b)) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,
+ "found qq udp pattern 0203[packet_length_0b0b] three times.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+
+ if (packet->udp->dest == htons(9000) || packet->udp->source == htons(9000)) {
+ if (packet->payload_packet_len > 3
+ && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0202
+ && ntohs(get_u_int16_t(packet->payload, 2)) == packet->payload_packet_len) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,
+ "found qq udp pattern 02 02 <length> four times.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+
+ }
+ }
+
+ if (ndpi_is_valid_qq_packet(packet)) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq over udp.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq packet stage %d\n", flow->qq_stage);
+ return;
+ }
+
+ if (ndpi_is_valid_qq_ft_packet(packet)) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq ft over udp.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+
+ if (flow->qq_stage && flow->packet_counter <= 5) {
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "QQ excluded\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_QQ);
+}
+
+
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+void ndpi_search_qq_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+
+ u_int16_t i = 0;
+ // u_int16_t a = 0;
+
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "search qq tcp.\n");
+
+ if (packet->payload_packet_len == 39 && get_u_int32_t(packet->payload, 0) == htonl(0x27000000) &&
+ get_u_int16_t(packet->payload, 4) == htons(0x0014) && get_u_int32_t(packet->payload, 11) != 0 &&
+ get_u_int16_t(packet->payload, packet->payload_packet_len - 2) == htons(0x0000)) {
+ if (flow->qq_stage == 4) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq over tcp - maybe ft/audio/video.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ flow->qq_stage = 4;
+ return;
+ }
+
+ if ((packet->payload_packet_len > 4 && ntohs(get_u_int16_t(packet->payload, 0)) == packet->payload_packet_len
+ && get_u_int16_t(packet->payload, 2) == htons(0x0212) && packet->payload[4] == 0x0b)
+ || (packet->payload_packet_len > 6 && packet->payload[0] == 0x02
+ && packet->payload[packet->payload_packet_len - 1] == 0x03
+ && ntohs(get_u_int16_t(packet->payload, 1)) == packet->payload_packet_len
+ && (get_u_int16_t(packet->payload, 3) == htons(0x0605) || get_u_int16_t(packet->payload, 3) == htons(0x0608))
+ && packet->payload[5] == 0x00)
+ || (packet->payload_packet_len > 9 && get_u_int32_t(packet->payload, 0) == htonl(0x04154900)
+ && get_l16(packet->payload, 4) == packet->payload_packet_len
+ && packet->payload[packet->payload_packet_len - 1] == 0x03)
+ || (packet->payload_packet_len > 9 && get_u_int32_t(packet->payload, 0) == htonl(0x040e3500)
+ && get_l16(packet->payload, 4) == packet->payload_packet_len
+ && packet->payload[9] == 0x33 && packet->payload[packet->payload_packet_len - 1] == 0x03)
+ || (packet->payload_packet_len > 9 && get_u_int32_t(packet->payload, 0) == htonl(0x040e0215)
+ && get_l16(packet->payload, 4) == packet->payload_packet_len
+ && packet->payload[9] == 0x33 && packet->payload[packet->payload_packet_len - 1] == 0x03)
+ || (packet->payload_packet_len > 6 && get_u_int32_t(packet->payload, 2) == htonl(0x020d5500)
+ && ntohs(get_u_int16_t(packet->payload, 0)) == packet->payload_packet_len
+ && packet->payload[packet->payload_packet_len - 1] == 0x03)
+ || (packet->payload_packet_len > 6 && get_u_int16_t(packet->payload, 0) == htons(0x0418)
+ && packet->payload[2] == 0x01
+ && ntohs(get_u_int16_t(packet->payload, 3)) == packet->payload_packet_len
+ && packet->payload[packet->payload_packet_len - 1] == 0x03)
+ || (packet->payload_packet_len > 6 && get_u_int16_t(packet->payload, 0) == htons(0x0411)
+ && packet->payload[2] == 0x31
+ && ntohs(get_u_int16_t(packet->payload, 3)) == packet->payload_packet_len
+ && packet->payload[packet->payload_packet_len - 1] == 0x03)
+ || (packet->payload_packet_len > 6 && ntohs(get_u_int16_t(packet->payload, 0)) == packet->payload_packet_len
+ && get_u_int16_t(packet->payload, 2) == htons(0x0211) && packet->payload[4] == 0x31
+ && packet->payload[packet->payload_packet_len - 1] == 0x03)
+ || (packet->payload_packet_len > 6 && ntohs(get_u_int16_t(packet->payload, 0)) == packet->payload_packet_len
+ && get_u_int16_t(packet->payload, 2) == htons(0x0218) && packet->payload[4] == 0x01
+ && packet->payload[packet->payload_packet_len - 1] == 0x03)
+ || (packet->payload_packet_len > 10 && get_u_int32_t(packet->payload, 0) == htonl(0x04163a00)
+ && packet->payload[packet->payload_packet_len - 1] == 0x03
+ && packet->payload[4] == packet->payload_packet_len)
+ ) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq over tcp.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+
+ if (ndpi_is_valid_qq_packet(packet)) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq over tcp.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+
+ if (ndpi_is_valid_qq_ft_packet(packet)) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq ft over tcp.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+
+ if (packet->payload_packet_len == 2) {
+ flow->l4.tcp.qq_nxt_len = ntohs(get_u_int16_t(packet->payload, 0));
+ return;
+ }
+ if (packet->payload_packet_len > 5 && (((flow->l4.tcp.qq_nxt_len == packet->payload_packet_len + 2)
+ && packet->payload[0] == 0x02
+ && packet->payload[packet->payload_packet_len - 1] == 0x03
+ && get_u_int16_t(packet->payload, 1) == htons(0x0f5f))
+ || (ntohs(get_u_int16_t(packet->payload, 0)) == packet->payload_packet_len
+ && packet->payload[2] == 0x02
+ && packet->payload[packet->payload_packet_len - 1] == 0x03
+ && get_u_int16_t(packet->payload, 3) == htons(0x0f5f)))) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq udp pattern 02 ... 03 four times.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+
+ }
+ if (packet->payload_packet_len > 2 && packet->payload[0] == 0x04 && ((get_u_int16_t(packet->payload, 1) == htons(0x1549)
+ || get_u_int16_t(packet->payload,
+ 1) == htons(0x1801)
+ || get_u_int16_t(packet->payload,
+ 1) == htons(0x0961))
+ || (packet->payload_packet_len > 16
+ && (get_u_int16_t(packet->payload, 1) ==
+ htons(0x180d)
+ || get_u_int16_t(packet->payload,
+ 1) == htons(0x096d))
+ && get_u_int32_t(packet->payload,
+ 12) == htonl(0x28000000)
+ && ntohs(get_u_int16_t(packet->payload, 3)) ==
+ packet->payload_packet_len))
+ && packet->payload[packet->payload_packet_len - 1] == 0x03) {
+ flow->qq_stage++;
+ if (flow->qq_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG,
+ "found qq udp pattern 04 1159 ... 03 four times.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ return;
+ }
+
+
+
+ if (packet->payload_packet_len > 100
+ && ((memcmp(packet->payload, "GET", 3) == 0) || (memcmp(packet->payload, "POST", 4) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found GET or POST.\n");
+ if (memcmp(packet->payload, "GET /qqfile/qq", 14) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq over tcp GET /qqfile/qq.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if (packet->user_agent_line.ptr != NULL
+ && (packet->user_agent_line.len > 7 && memcmp(packet->user_agent_line.ptr, "QQClient", 8) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq over tcp GET...QQClient\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ for (i = 0; i < packet->parsed_lines; i++) {
+ if (packet->line[i].len > 3 && memcmp(packet->line[i].ptr, "QQ: ", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq over tcp GET...QQ: \n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ if (packet->host_line.ptr != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "host line ptr\n");
+ if (packet->host_line.len > 11 && memcmp(&packet->host_line.ptr[0], "www.qq.co.za", 12) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq over tcp Host: www.qq.co.za\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+ if (flow->qq_stage == 0 && packet->payload_packet_len == 82
+ && get_u_int32_t(packet->payload, 0) == htonl(0x0000004e) && get_u_int32_t(packet->payload, 4) == htonl(0x01010000)) {
+ for (i = 8; i < 82; i++) {
+ if (packet->payload[i] != 0x00) {
+ break;
+ }
+ if (i == 81) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq Mail.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ }
+ if (flow->qq_stage == 0 && packet->payload_packet_len == 182 && get_u_int32_t(packet->payload, 0) == htonl(0x000000b2)
+ && get_u_int32_t(packet->payload, 4) == htonl(0x01020000)
+ && get_u_int32_t(packet->payload, 8) == htonl(0x04015151) && get_u_int32_t(packet->payload, 12) == htonl(0x4d61696c)) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq Mail.\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 204 && flow->qq_stage == 0 && get_u_int32_t(packet->payload, 200) == htonl(0xfbffffff)) {
+ for (i = 0; i < 200; i++) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "i = %u\n", i);
+ if (packet->payload[i] != 0) {
+ break;
+ }
+ if (i == 199) {
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "found qq chat or file transfer\n");
+ ndpi_int_qq_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ }
+#ifdef NDPI_PROTOCOL_HTTP
+ if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_HTTP) != 0) {
+#endif /* NDPI_PROTOCOL_HTTP */
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_QQ);
+ NDPI_LOG(NDPI_PROTOCOL_QQ, ndpi_struct, NDPI_LOG_DEBUG, "QQ tcp excluded; len %u\n",
+ packet->payload_packet_len);
+
+#ifdef NDPI_PROTOCOL_HTTP
+ }
+#endif /* NDPI_PROTOCOL_HTTP */
+
+}
+
+
+void ndpi_search_qq(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if (packet->udp != NULL && flow->detected_protocol_stack[0] != NDPI_PROTOCOL_QQ)
+ ndpi_search_qq_udp(ndpi_struct, flow);
+
+ if (packet->tcp != NULL && flow->detected_protocol_stack[0] != NDPI_PROTOCOL_QQ)
+ ndpi_search_qq_tcp(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/quake.c b/src/lib/protocols/quake.c
new file mode 100644
index 000000000..18a027970
--- /dev/null
+++ b/src/lib/protocols/quake.c
@@ -0,0 +1,91 @@
+/*
+ * quake.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_QUAKE
+
+static void ndpi_int_quake_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_QUAKE, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_quake(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if ((packet->payload_packet_len == 14
+ && get_u_int16_t(packet->payload, 0) == 0xffff && memcmp(&packet->payload[2], "getInfo", 7) == 0)
+ || (packet->payload_packet_len == 17
+ && get_u_int16_t(packet->payload, 0) == 0xffff && memcmp(&packet->payload[2], "challenge", 9) == 0)
+ || (packet->payload_packet_len > 20
+ && packet->payload_packet_len < 30
+ && get_u_int16_t(packet->payload, 0) == 0xffff && memcmp(&packet->payload[2], "getServers", 10) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_QUAKE, ndpi_struct, NDPI_LOG_DEBUG, "Quake IV detected.\n");
+ ndpi_int_quake_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ /* Quake III/Quake Live */
+ if (packet->payload_packet_len == 15 && get_u_int32_t(packet->payload, 0) == 0xffffffff
+ && memcmp(&packet->payload[4], "getinfo", NDPI_STATICSTRING_LEN("getinfo")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_QUAKE, ndpi_struct, NDPI_LOG_DEBUG, "Quake III Arena/Quake Live detected.\n");
+ ndpi_int_quake_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len == 16 && get_u_int32_t(packet->payload, 0) == 0xffffffff
+ && memcmp(&packet->payload[4], "getchallenge", NDPI_STATICSTRING_LEN("getchallenge")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_QUAKE, ndpi_struct, NDPI_LOG_DEBUG, "Quake III Arena/Quake Live detected.\n");
+ ndpi_int_quake_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len > 20 && packet->payload_packet_len < 30
+ && get_u_int32_t(packet->payload, 0) == 0xffffffff
+ && memcmp(&packet->payload[4], "getservers", NDPI_STATICSTRING_LEN("getservers")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_QUAKE, ndpi_struct, NDPI_LOG_DEBUG, "Quake III Arena/Quake Live detected.\n");
+ ndpi_int_quake_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+
+
+ /* ports for startup packet:
+ Quake I 26000 (starts with 0x8000)
+ Quake II 27910
+ Quake III 27960 (increases with each player)
+ Quake IV 27650
+ Quake World 27500
+ Quake Wars ?????
+ */
+
+ NDPI_LOG(NDPI_PROTOCOL_QUAKE, ndpi_struct, NDPI_LOG_DEBUG, "Quake excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_QUAKE);
+}
+
+#endif
diff --git a/src/lib/protocols/radius.c b/src/lib/protocols/radius.c
new file mode 100644
index 000000000..0b7698a94
--- /dev/null
+++ b/src/lib/protocols/radius.c
@@ -0,0 +1,76 @@
+/*
+ * radius.c
+ *
+ * Copyright (C) 2012-15 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_RADIUS
+
+struct radius_header {
+ u_int8_t code;
+ u_int8_t packet_id;
+ u_int16_t len;
+};
+
+static void ndpi_check_radius(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // const u_int8_t *packet_payload = packet->payload;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+#if 0
+ printf("[len=%u][%02X %02X %02X %02X]\n", payload_len,
+ packet->payload[0] & 0xFF,
+ packet->payload[1] & 0xFF,
+ packet->payload[2] & 0xFF,
+ packet->payload[3] & 0xFF);
+#endif
+
+ if(packet->udp != NULL) {
+ struct radius_header *h = (struct radius_header*)packet->payload;
+ u_int len = ntohs(h->len);
+
+ if((payload_len > sizeof(struct radius_header))
+ && (h->code > 0)
+ && (h->code <= 5)
+ && (len == payload_len)) {
+ NDPI_LOG(NDPI_PROTOCOL_RADIUS, ndpi_struct, NDPI_LOG_DEBUG, "Found radius.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_RADIUS, NDPI_REAL_PROTOCOL);
+
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RADIUS);
+ return;
+ }
+}
+
+void ndpi_search_radius(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_RADIUS, ndpi_struct, NDPI_LOG_DEBUG, "radius detection...\n");
+
+ /* skip marked packets */
+ if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_RADIUS)
+ ndpi_check_radius(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/rdp.c b/src/lib/protocols/rdp.c
new file mode 100644
index 000000000..02bbb86e5
--- /dev/null
+++ b/src/lib/protocols/rdp.c
@@ -0,0 +1,56 @@
+/*
+ * rdp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_RDP
+
+static void ndpi_int_rdp_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_RDP, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_rdp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len > 10
+ && get_u_int8_t(packet->payload, 0) > 0
+ && get_u_int8_t(packet->payload, 0) < 4 && get_u_int16_t(packet->payload, 2) == ntohs(packet->payload_packet_len)
+ && get_u_int8_t(packet->payload, 4) == packet->payload_packet_len - 5
+ && get_u_int8_t(packet->payload, 5) == 0xe0
+ && get_u_int16_t(packet->payload, 6) == 0 && get_u_int16_t(packet->payload, 8) == 0 && get_u_int8_t(packet->payload, 10) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_RDP, ndpi_struct, NDPI_LOG_DEBUG, "RDP detected.\n");
+ ndpi_int_rdp_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RDP);
+}
+
+#endif
diff --git a/src/lib/protocols/redis.c b/src/lib/protocols/redis.c
new file mode 100644
index 000000000..a47778b48
--- /dev/null
+++ b/src/lib/protocols/redis.c
@@ -0,0 +1,92 @@
+/*
+ * redis.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_REDIS
+
+static void ndpi_int_redis_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_REDIS, NDPI_REAL_PROTOCOL);
+}
+
+
+static void ndpi_check_redis(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ if(payload_len == 0) return; /* Shouldn't happen */
+
+ /* Break after 20 packets. */
+ if(flow->packet_counter > 20) {
+ NDPI_LOG(NDPI_PROTOCOL_REDIS, ndpi_struct, NDPI_LOG_DEBUG, "Exclude Redis.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_REDIS);
+ return;
+ }
+
+ if(packet->packet_direction == 0)
+ flow->redis_s2d_first_char = packet->payload[0];
+ else
+ flow->redis_d2s_first_char = packet->payload[0];
+
+ if((flow->redis_s2d_first_char != '\0') && (flow->redis_d2s_first_char != '\0')) {
+ /*
+ *1
+ $4
+ PING
+ +PONG
+ *3
+ $3
+ SET
+ $19
+ dns.cache.127.0.0.1
+ $9
+ localhost
+ +OK
+ */
+
+ if(((flow->redis_s2d_first_char == '*')
+ && ((flow->redis_d2s_first_char == '+') || (flow->redis_d2s_first_char == ':')))
+ || ((flow->redis_d2s_first_char == '*')
+ && ((flow->redis_s2d_first_char == '+') || (flow->redis_s2d_first_char == ':')))) {
+ NDPI_LOG(NDPI_PROTOCOL_REDIS, ndpi_struct, NDPI_LOG_DEBUG, "Found Redis.\n");
+ ndpi_int_redis_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_REDIS, ndpi_struct, NDPI_LOG_DEBUG, "Exclude Redis.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_REDIS);
+ }
+ } else
+ return; /* Too early */
+}
+
+void ndpi_search_redis(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_REDIS, ndpi_struct, NDPI_LOG_DEBUG, "Redis detection...\n");
+
+ /* skip marked packets */
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_REDIS) {
+ if (packet->tcp_retransmission == 0) {
+ ndpi_check_redis(ndpi_struct, flow);
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/rsync.c b/src/lib/protocols/rsync.c
new file mode 100644
index 000000000..7caa09e0a
--- /dev/null
+++ b/src/lib/protocols/rsync.c
@@ -0,0 +1,56 @@
+/*
+ * rsync.c
+ *
+ * Copyright (C) 2013 Remy Mudingay <mudingay@ill.fr>
+ *
+ * This module is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This module 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+
+#ifdef NDPI_PROTOCOL_RSYNC
+static void ndpi_int_rsync_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_RSYNC, NDPI_CORRELATED_PROTOCOL);
+}
+
+void ndpi_search_rsync(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_RSYNC, ndpi_struct, NDPI_LOG_DEBUG, "search for RSYNC.\n");
+
+ if(packet->tcp != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_RSYNC, ndpi_struct, NDPI_LOG_DEBUG, "calculating RSYNC over tcp.\n");
+ /*
+ * Should match: memcmp(packet->payload, "@RSYN NCD: 28", 14) == 0)
+ */
+ if (packet->payload_packet_len == 12 && packet->payload[0] == 0x40 &&
+ packet->payload[1] == 0x52 && packet->payload[2] == 0x53 &&
+ packet->payload[3] == 0x59 && packet->payload[4] == 0x4e &&
+ packet->payload[5] == 0x43 && packet->payload[6] == 0x44 &&
+ packet->payload[7] == 0x3a ) {
+ NDPI_LOG(NDPI_PROTOCOL_RSYNC, ndpi_struct, NDPI_LOG_DEBUG, "found rsync.\n");
+ ndpi_int_rsync_add_connection(ndpi_struct, flow);
+ }
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_RSYNC, ndpi_struct, NDPI_LOG_DEBUG, "exclude RSYNC.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RSYNC);
+ }
+}
+#endif
diff --git a/src/lib/protocols/rtcp.c b/src/lib/protocols/rtcp.c
new file mode 100644
index 000000000..02875648a
--- /dev/null
+++ b/src/lib/protocols/rtcp.c
@@ -0,0 +1,52 @@
+/*
+ * rtcp.c (RTP Control Protocol)
+ *
+ * Copyright (C) 2013 Remy Mudingay <mudingay@ill.fr>
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_RTCP
+static void ndpi_int_rtcp_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_RTCP, NDPI_CORRELATED_PROTOCOL);
+}
+
+void ndpi_search_rtcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t dport = 0, sport = 0;
+
+ NDPI_LOG(NDPI_PROTOCOL_RTCP, ndpi_struct, NDPI_LOG_DEBUG, "search for RTCP.\n");
+
+ if(packet->tcp != NULL) {
+ sport = ntohs(packet->tcp->source), dport = ntohs(packet->tcp->dest);
+ NDPI_LOG(NDPI_PROTOCOL_RTCP, ndpi_struct, NDPI_LOG_DEBUG, "calculating dport over tcp.\n");
+
+ if(packet->payload_packet_len > 13 && (sport == 554 || dport == 554) &&
+ packet->payload[0] == 0x00 && packet->payload[1] == 0x00 &&
+ packet->payload[2] == 0x01 && packet->payload[3] == 0x01 &&
+ packet->payload[4] == 0x08 && packet->payload[5] == 0x0a &&
+ packet->payload[6] == 0x00 && packet->payload[7] == 0x01) {
+ NDPI_LOG(NDPI_PROTOCOL_RTCP, ndpi_struct, NDPI_LOG_DEBUG, "found rtcp.\n");
+ ndpi_int_rtcp_add_connection(ndpi_struct, flow);
+ }
+ } else if(packet->udp != NULL) {
+ sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest);
+ NDPI_LOG(NDPI_PROTOCOL_RTCP, ndpi_struct, NDPI_LOG_DEBUG, "calculating dport over udp.\n");
+ if(((packet->payload_packet_len >= 28 || packet->payload_packet_len <= 1200) &&
+ ((packet->payload[0] == 0x80) && ((packet->payload[1] == 0xc8) || (packet->payload[1] == 0xc9)) && (packet->payload[2] == 0x00)))
+ || (((packet->payload[0] == 0x81) && ((packet->payload[1] == 0xc8) || (packet->payload[1] == 0xc9))
+ && (packet->payload[2] == 0x00)))) {
+ NDPI_LOG(NDPI_PROTOCOL_RTCP, ndpi_struct, NDPI_LOG_DEBUG, "found rtcp.\n");
+ ndpi_int_rtcp_add_connection(ndpi_struct, flow);
+ }
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_RTCP, ndpi_struct, NDPI_LOG_DEBUG, "exclude RTCP.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RTCP);
+ }
+}
+#endif
diff --git a/src/lib/protocols/rtmp.c b/src/lib/protocols/rtmp.c
new file mode 100644
index 000000000..6ebb5ebf2
--- /dev/null
+++ b/src/lib/protocols/rtmp.c
@@ -0,0 +1,92 @@
+/*
+ * rtmp.c
+ *
+ * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk>
+ *
+ * The signature is based on the Libprotoident library.
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_RTMP
+static void ndpi_int_rtmp_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_RTMP, NDPI_REAL_PROTOCOL);
+}
+
+static void ndpi_check_rtmp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Break after 20 packets. */
+ if (flow->packet_counter > 20) {
+ NDPI_LOG(NDPI_PROTOCOL_RTMP, ndpi_struct, NDPI_LOG_DEBUG, "Exclude RTMP.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RTMP);
+ return;
+ }
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->rtmp_stage == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_RTMP, ndpi_struct, NDPI_LOG_DEBUG, "RTMP stage 0: \n");
+
+ if ((payload_len >= 4) && ((packet->payload[0] == 0x03) || (packet->payload[0] == 0x06))) {
+ NDPI_LOG(NDPI_PROTOCOL_RTMP, ndpi_struct, NDPI_LOG_DEBUG, "Possible RTMP request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->rtmp_stage = packet->packet_direction + 1;
+ }
+
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_RTMP, ndpi_struct, NDPI_LOG_DEBUG, "RTMP stage %u: \n", flow->rtmp_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->rtmp_stage - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len >= 4) && ((packet->payload[0] == 0x03) || (packet->payload[0] == 0x06) || (packet->payload[0] == 0x08) || (packet->payload[0] == 0x09) || (packet->payload[0] == 0x0a))) {
+ NDPI_LOG(NDPI_PROTOCOL_RTMP, ndpi_struct, NDPI_LOG_DEBUG, "Found RTMP.\n");
+ ndpi_int_rtmp_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_RTMP, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to RTMP, resetting the stage to 0...\n");
+ flow->rtmp_stage = 0;
+ }
+
+ }
+}
+
+void ndpi_search_rtmp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_RTMP, ndpi_struct, NDPI_LOG_DEBUG, "RTMP detection...\n");
+
+ /* skip marked packets */
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_RTMP) {
+ if (packet->tcp_retransmission == 0) {
+ ndpi_check_rtmp(ndpi_struct, flow);
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/rtp.c b/src/lib/protocols/rtp.c
new file mode 100644
index 000000000..1e1a82a8b
--- /dev/null
+++ b/src/lib/protocols/rtp.c
@@ -0,0 +1,325 @@
+/*
+ * rtp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_RTP
+
+
+static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ const u_int8_t * payload, const u_int16_t payload_len)
+{
+ //struct ndpi_packet_struct *packet = &flow->packet;
+ u_int8_t payload_type = payload[1] & 0x7F;
+ u_int32_t *ssid = (u_int32_t*)&payload[8];
+
+ /* Check whether this is an RTP flow */
+ if((payload_len >= 12)
+ && ((payload[0] & 0xFF) == 0x80) /* RTP magic byte[1] */
+ && ((payload_type < 72) || (payload_type > 76))
+ && (payload_type < 128 /* http://anonsvn.wireshark.org/wireshark/trunk/epan/dissectors/packet-rtp.c */)
+ && (*ssid != 0)
+ ) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "Found rtp.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_RTP, NDPI_REAL_PROTOCOL);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "exclude rtp.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RTP);
+ }
+}
+
+void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if((packet->udp != NULL)
+ && (ntohs(packet->udp->source) > 1023)
+ && (ntohs(packet->udp->dest) > 1023))
+ ndpi_rtp_search(ndpi_struct, flow, packet->payload, packet->payload_packet_len);
+}
+
+#if 0
+/* Original (messy) OpenDPI code */
+
+#define RTP_MAX_OUT_OF_ORDER 11
+
+static void ndpi_int_rtp_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_RTP, NDPI_REAL_PROTOCOL);
+}
+
+/*
+ * maintenance of current highest sequence number, cycle count, packet counter
+ * adapted from RFC3550 Appendix A.1
+ *
+ * In their formulation, it is not possible to represent "no packets sent yet". This is fixed here by defining
+ * baseseq to be the sequence number of the first packet minus 1 (in other words, the sequence number of the
+ * zeroth packet).
+ *
+ * Note: As described in the RFC, the number of packets received includes retransmitted packets.
+ * This means the "packets lost" count (seq_num-isn+1)-received can become negative.
+ *
+ * include_current_packet should be
+ * 1, if the current packet should count towards the total, or
+ * 0, if it it regarded as belonging to the previous reporting interval
+ */
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+void init_seq(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow,
+ u_int8_t direction, u_int16_t seq, u_int8_t include_current_packet)
+{
+ flow->rtp_seqnum[direction] = seq;
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "rtp_seqnum[%u] = %u\n", direction, seq);
+}
+
+/* returns difference between old and new highest sequence number */
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+u_int16_t update_seq(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow,
+ u_int8_t direction, u_int16_t seq)
+{
+ u_int16_t delta = seq - flow->rtp_seqnum[direction];
+
+
+ if (delta < RTP_MAX_OUT_OF_ORDER) { /* in order, with permissible gap */
+ flow->rtp_seqnum[direction] = seq;
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "rtp_seqnum[%u] = %u (increased by %u)\n",
+ direction, seq, delta);
+ return delta;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "retransmission (dir %u, seqnum %u)\n",
+ direction, seq);
+ return 0;
+ }
+}
+
+static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ const u_int8_t * payload, const u_int16_t payload_len)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ u_int8_t stage;
+ u_int16_t seqnum = ntohs(get_u_int16_t(payload, 2));
+
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "search rtp.\n");
+
+ if (payload_len == 4 && get_u_int32_t(packet->payload, 0) == 0 && flow->packet_counter < 8) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "need next packet, maybe ClearSea out calls.\n");
+ return;
+ }
+
+ if (payload_len == 5 && memcmp(payload, "hello", 5) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "need next packet, initial hello packet of SIP out calls.\n");
+ return;
+ }
+
+ if (payload_len == 1 && payload[0] == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "need next packet, payload_packet_len == 1 && payload[0] == 0.\n");
+ return;
+ }
+
+ if (payload_len == 3 && memcmp(payload, "png", 3) == 0) {
+ /* weird packet found in Ninja GlobalIP trace */
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "skipping packet with len = 3 and png payload.\n");
+ return;
+ }
+
+ if (payload_len < 12) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "minimal packet size for rtp packets: 12.\n");
+ goto exclude_rtp;
+ }
+
+ if (payload_len == 12 && get_u_int32_t(payload, 0) == 0 && get_u_int32_t(payload, 4) == 0 && get_u_int32_t(payload, 8) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "skipping packet with len = 12 and only 0-bytes.\n");
+ return;
+ }
+
+ if ((payload[0] & 0xc0) == 0xc0 || (payload[0] & 0xc0) == 0x40 || (payload[0] & 0xc0) == 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "version = 3 || 1 || 0, maybe first rtp packet.\n");
+ return;
+ }
+
+ if ((payload[0] & 0xc0) != 0x80) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct,
+ NDPI_LOG_DEBUG, "rtp version must be 2, first two bits of a packets must be 10.\n");
+ goto exclude_rtp;
+ }
+
+ /* rtp_payload_type are the last seven bits of the second byte */
+ if (flow->rtp_payload_type[packet->packet_direction] != (payload[1] & 0x7F)) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "payload_type has changed, reset stages.\n");
+ packet->packet_direction == 0 ? (flow->rtp_stage1 = 0) : (flow->rtp_stage2 = 0);
+ }
+ /* first bit of first byte is not part of payload_type */
+ flow->rtp_payload_type[packet->packet_direction] = payload[1] & 0x7F;
+
+ stage = (packet->packet_direction == 0 ? flow->rtp_stage1 : flow->rtp_stage2);
+
+ if (stage > 0) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct,
+ NDPI_LOG_DEBUG, "stage = %u.\n", packet->packet_direction == 0 ? flow->rtp_stage1 : flow->rtp_stage2);
+ if (flow->rtp_ssid[packet->packet_direction] != get_u_int32_t(payload, 8)) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "ssid has changed, goto exclude rtp.\n");
+ goto exclude_rtp;
+ }
+
+ if (seqnum == flow->rtp_seqnum[packet->packet_direction]) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "maybe \"retransmission\", need next packet.\n");
+ return;
+ } else if ((u_int16_t) (seqnum - flow->rtp_seqnum[packet->packet_direction]) < RTP_MAX_OUT_OF_ORDER) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "new packet has larger sequence number (within valid range)\n");
+ update_seq(ndpi_struct, flow, packet->packet_direction, seqnum);
+ } else if ((u_int16_t) (flow->rtp_seqnum[packet->packet_direction] - seqnum) < RTP_MAX_OUT_OF_ORDER) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "new packet has smaller sequence number (within valid range)\n");
+ init_seq(ndpi_struct, flow, packet->packet_direction, seqnum, 1);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "sequence number diff is too big, goto exclude rtp.\n");
+ goto exclude_rtp;
+ }
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct,
+ NDPI_LOG_DEBUG, "rtp_ssid[%u] = %u.\n", packet->packet_direction,
+ flow->rtp_ssid[packet->packet_direction]);
+ flow->rtp_ssid[packet->packet_direction] = get_u_int32_t(payload, 8);
+ if (flow->packet_counter < 3) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "packet_counter < 3, need next packet.\n");
+ }
+ init_seq(ndpi_struct, flow, packet->packet_direction, seqnum, 1);
+ }
+ if (seqnum <= 3) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct,
+ NDPI_LOG_DEBUG, "sequence_number = %u, too small, need next packet, return.\n", seqnum);
+ return;
+ }
+
+ if (stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "add connection I.\n");
+ ndpi_int_rtp_add_connection(ndpi_struct, flow);
+ } else {
+ packet->packet_direction == 0 ? flow->rtp_stage1++ : flow->rtp_stage2++;
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "stage[%u]++; need next packet.\n",
+ packet->packet_direction);
+ }
+ return;
+
+ exclude_rtp:
+#ifdef NDPI_PROTOCOL_STUN
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN
+ || packet->real_protocol_read_only == NDPI_PROTOCOL_STUN) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "STUN: is detected, need next packet.\n");
+ return;
+ }
+#endif /* NDPI_PROTOCOL_STUN */
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "exclude rtp.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RTP);
+}
+
+
+void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+ if (packet->udp) {
+ ndpi_rtp_search(ndpi_struct, flow, packet->payload, packet->payload_packet_len);
+ } else if (packet->tcp) {
+
+ /* skip special packets seen at yahoo traces */
+ if (packet->payload_packet_len >= 20 && ntohs(get_u_int16_t(packet->payload, 2)) + 20 == packet->payload_packet_len &&
+ packet->payload[0] == 0x90 && packet->payload[1] >= 0x01 && packet->payload[1] <= 0x07) {
+ if (flow->packet_counter == 2)
+ flow->l4.tcp.rtp_special_packets_seen = 1;
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG,
+ "skipping STUN-like, special yahoo packets with payload[0] == 0x90.\n");
+ return;
+ }
+#ifdef NDPI_PROTOCOL_STUN
+ /* TODO the rtp detection sometimes doesn't exclude rtp
+ * so for TCP flows only run the detection if STUN has been
+ * detected (or RTP is already detected)
+ * If flows will be seen which start directly with RTP
+ * we can remove this restriction
+ */
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN
+ || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_RTP) {
+
+ /* RTP may be encapsulated in TCP packets */
+
+ if (packet->payload_packet_len >= 2 && ntohs(get_u_int16_t(packet->payload, 0)) + 2 == packet->payload_packet_len) {
+
+ /* TODO there could be several RTP packets in a single TCP packet so maybe the detection could be
+ * improved by checking only the RTP packet of given length */
+
+ ndpi_rtp_search(ndpi_struct, flow, packet->payload + 2, packet->payload_packet_len - 2);
+
+ return;
+ }
+ }
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN && flow->l4.tcp.rtp_special_packets_seen == 1) {
+
+ if (packet->payload_packet_len >= 4 && ntohl(get_u_int32_t(packet->payload, 0)) + 4 == packet->payload_packet_len) {
+
+ /* TODO there could be several RTP packets in a single TCP packet so maybe the detection could be
+ * improved by checking only the RTP packet of given length */
+
+ ndpi_rtp_search(ndpi_struct, flow, packet->payload + 4, packet->payload_packet_len - 4);
+
+ return;
+ }
+ }
+
+ if (NDPI_FLOW_PROTOCOL_EXCLUDED(ndpi_struct, flow, NDPI_PROTOCOL_STUN)) {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "exclude rtp.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RTP);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "STUN not yet excluded, need next packet.\n");
+ }
+#else
+ NDPI_LOG(NDPI_PROTOCOL_RTP, ndpi_struct, NDPI_LOG_DEBUG, "exclude rtp.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RTP);
+#endif
+ }
+}
+#endif
+
+#endif /* NDPI_PROTOCOL_RTP */
+
diff --git a/src/lib/protocols/rtsp.c b/src/lib/protocols/rtsp.c
new file mode 100644
index 000000000..2614f0c6f
--- /dev/null
+++ b/src/lib/protocols/rtsp.c
@@ -0,0 +1,120 @@
+/*
+ * rtsp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_RTSP
+#ifndef NDPI_PROTOCOL_RTP
+#error RTSP requires RTP detection to work correctly
+#endif
+#ifndef NDPI_PROTOCOL_RTSP
+#error RTSP requires RTSP detection to work correctly
+#endif
+#ifndef NDPI_PROTOCOL_RDP
+#error RTSP requires RDP detection to work correctly
+#endif
+
+static void ndpi_int_rtsp_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_RTSP, protocol_type);
+}
+
+/* this function searches for a rtsp-"handshake" over tcp or udp. */
+void ndpi_search_rtsp_tcp_udp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_RTSP, ndpi_struct, NDPI_LOG_TRACE, "RTSP detection...\n");
+
+ if (flow->rtsprdt_stage == 0
+#ifdef NDPI_PROTOCOL_RTCP
+ && !(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_RTCP)
+#endif
+ ) {
+ flow->rtsprdt_stage = 1 + packet->packet_direction;
+ NDPI_LOG(NDPI_PROTOCOL_RTSP, ndpi_struct, NDPI_LOG_DEBUG, "maybe handshake 1; need next packet, return.\n");
+ return;
+ }
+
+ if (flow->packet_counter < 3 && flow->rtsprdt_stage == 1 + packet->packet_direction) {
+
+ NDPI_LOG(NDPI_PROTOCOL_RTSP, ndpi_struct, NDPI_LOG_DEBUG, "maybe handshake 2; need next packet.\n");
+ return;
+ }
+
+ if (packet->payload_packet_len > 20 && flow->rtsprdt_stage == 2 - packet->packet_direction) {
+ char buf[32] = { 0 };
+ u_int len = packet->payload_packet_len;
+
+ if(len >= (sizeof(buf)-1)) len = sizeof(buf)-1;
+ strncpy(buf, (const char*)packet->payload, len);
+
+ // RTSP Server Message
+ if((memcmp(packet->payload, "RTSP/1.0 ", 9) == 0)
+ || (strstr(buf, "rtsp://") != NULL)) {
+ NDPI_LOG(NDPI_PROTOCOL_RTSP, ndpi_struct, NDPI_LOG_TRACE, "found RTSP/1.0 .\n");
+ if (dst != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_RTSP, ndpi_struct, NDPI_LOG_TRACE, "found dst.\n");
+ ndpi_packet_src_ip_get(packet, &dst->rtsp_ip_address);
+ dst->rtsp_timer = packet->tick_timestamp;
+ dst->rtsp_ts_set = 1;
+ }
+ if (src != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_RTSP, ndpi_struct, NDPI_LOG_TRACE, "found src.\n");
+ ndpi_packet_dst_ip_get(packet, &src->rtsp_ip_address);
+ src->rtsp_timer = packet->tick_timestamp;
+ src->rtsp_ts_set = 1;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_RTSP, ndpi_struct, NDPI_LOG_TRACE, "RTSP detected.\n");
+ flow->rtsp_control_flow = 1;
+ ndpi_int_rtsp_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ if (packet->udp != NULL && packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN
+ && ((NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RTP) == 0)
+#ifdef NDPI_PROTOCOL_RTCP
+ || (NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RTCP) == 0)
+#endif
+ )) {
+ NDPI_LOG(NDPI_PROTOCOL_RTSP, ndpi_struct, NDPI_LOG_DEBUG,
+ "maybe RTSP RTP, RTSP RTCP, RDT; need next packet.\n");
+ return;
+ }
+
+
+ NDPI_LOG(NDPI_PROTOCOL_RTSP, ndpi_struct, NDPI_LOG_DEBUG, "didn't find handshake, exclude.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_RTSP);
+ return;
+}
+
+
+#endif
diff --git a/src/lib/protocols/sflow.c b/src/lib/protocols/sflow.c
new file mode 100644
index 000000000..980867634
--- /dev/null
+++ b/src/lib/protocols/sflow.c
@@ -0,0 +1,49 @@
+/*
+ * sflow.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_SFLOW
+
+static void ndpi_check_sflow(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // const u_int8_t *packet_payload = packet->payload;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ if((packet->udp != NULL)
+ && (payload_len >= 24)
+ /* Version */
+ && (packet->payload[0] == 0) && (packet->payload[1] == 0) && (packet->payload[2] == 0)
+ && ((packet->payload[3] == 2) || (packet->payload[3] == 5))) {
+ NDPI_LOG(NDPI_PROTOCOL_SFLOW, ndpi_struct, NDPI_LOG_DEBUG, "Found sflow.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SFLOW, NDPI_REAL_PROTOCOL);
+ return;
+ }
+}
+
+void ndpi_search_sflow(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ NDPI_LOG(NDPI_PROTOCOL_SFLOW, ndpi_struct, NDPI_LOG_DEBUG, "sflow detection...\n");
+ ndpi_check_sflow(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/shoutcast.c b/src/lib/protocols/shoutcast.c
new file mode 100644
index 000000000..f700db330
--- /dev/null
+++ b/src/lib/protocols/shoutcast.c
@@ -0,0 +1,107 @@
+/*
+ * shoutcast.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_SHOUTCAST
+
+static void ndpi_int_shoutcast_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SHOUTCAST, NDPI_CORRELATED_PROTOCOL);
+}
+
+void ndpi_search_shoutcast_tcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+ NDPI_LOG(NDPI_PROTOCOL_SHOUTCAST, ndpi_struct, NDPI_LOG_DEBUG, "search shoutcast.\n");
+
+ if (flow->packet_counter == 1) {
+/* this case in paul_upload_oddcast_002.pcap */
+ if (packet->payload_packet_len >= 6
+ && packet->payload_packet_len < 80 && memcmp(packet->payload, "123456", 6) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SHOUTCAST, ndpi_struct, NDPI_LOG_DEBUG, "Shoutcast stage 1, \"123456\".\n");
+ return;
+ }
+ if (flow->packet_counter < 3
+#ifdef NDPI_PROTOCOL_HTTP
+ && packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP
+#endif
+ ) {
+ NDPI_LOG(NDPI_PROTOCOL_SHOUTCAST, ndpi_struct, NDPI_LOG_DEBUG,
+ "http detected, need next packet for shoutcast detection.\n");
+ if (packet->payload_packet_len > 4
+ && get_u_int32_t(packet->payload, packet->payload_packet_len - 4) != htonl(0x0d0a0d0a)) {
+ NDPI_LOG(NDPI_PROTOCOL_SHOUTCAST, ndpi_struct, NDPI_LOG_DEBUG, "segmented packet found.\n");
+ flow->l4.tcp.shoutcast_stage = 1 + packet->packet_direction;
+ }
+ return;
+ }
+
+
+ /* else
+ goto exclude_shoutcast; */
+
+ }
+ /* evtl. für asym detection noch User-Agent:Winamp dazunehmen. */
+ if (packet->payload_packet_len > 11 && memcmp(packet->payload, "ICY 200 OK\x0d\x0a", 12) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SHOUTCAST, ndpi_struct, NDPI_LOG_DEBUG, "found shoutcast by ICY 200 OK.\n");
+ ndpi_int_shoutcast_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (flow->l4.tcp.shoutcast_stage == 1 + packet->packet_direction
+ && flow->packet_direction_counter[packet->packet_direction] < 5) {
+ return;
+ }
+
+ if (flow->packet_counter == 2) {
+ if (packet->payload_packet_len == 2 && memcmp(packet->payload, "\x0d\x0a", 2) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SHOUTCAST, ndpi_struct, NDPI_LOG_DEBUG, "Shoutcast stage 1 continuation.\n");
+ return;
+ } else if (packet->payload_packet_len > 3 && memcmp(&packet->payload[0], "OK2", 3) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SHOUTCAST, ndpi_struct, NDPI_LOG_DEBUG, "Shoutcast stage 2, OK2 found.\n");
+ return;
+ } else
+ goto exclude_shoutcast;
+ } else if (flow->packet_counter == 3 || flow->packet_counter == 4) {
+ if (packet->payload_packet_len > 3 && memcmp(&packet->payload[0], "OK2", 3) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SHOUTCAST, ndpi_struct, NDPI_LOG_DEBUG, "Shoutcast stage 2, OK2 found.\n");
+ return;
+ } else if (packet->payload_packet_len > 4 && memcmp(&packet->payload[0], "icy-", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SHOUTCAST, ndpi_struct, NDPI_LOG_DEBUG, "Shoutcast detected.\n");
+ ndpi_int_shoutcast_add_connection(ndpi_struct, flow);
+ return;
+ } else
+ goto exclude_shoutcast;
+ }
+
+ exclude_shoutcast:
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SHOUTCAST);
+ NDPI_LOG(NDPI_PROTOCOL_SHOUTCAST, ndpi_struct, NDPI_LOG_DEBUG, "Shoutcast excluded.\n");
+}
+#endif
diff --git a/src/lib/protocols/sip.c b/src/lib/protocols/sip.c
new file mode 100644
index 000000000..201d2b23f
--- /dev/null
+++ b/src/lib/protocols/sip.c
@@ -0,0 +1,200 @@
+/*
+ * sip.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_SIP
+static void ndpi_int_sip_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int8_t due_to_correlation)
+{
+
+ ndpi_int_add_connection(ndpi_struct, flow,
+ NDPI_PROTOCOL_SIP,
+ due_to_correlation ? NDPI_CORRELATED_PROTOCOL : NDPI_REAL_PROTOCOL);
+}
+
+
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+void ndpi_search_sip_handshake(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+ const u_int8_t *packet_payload = packet->payload;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+
+ if (payload_len > 4) {
+ /* search for STUN Turn ChannelData Prefix */
+ u_int16_t message_len = ntohs(get_u_int16_t(packet->payload, 2));
+ if (payload_len - 4 == message_len) {
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found STUN TURN ChannelData prefix.\n");
+ payload_len -= 4;
+ packet_payload += 4;
+ }
+ }
+#ifndef NDPI_PROTOCOL_YAHOO
+ if (payload_len >= 14 && packet_payload[payload_len - 2] == 0x0d && packet_payload[payload_len - 1] == 0x0a)
+#endif
+#ifdef NDPI_PROTOCOL_YAHOO
+ if (payload_len >= 14)
+#endif
+ {
+
+ if ((memcmp(packet_payload, "NOTIFY ", 7) == 0 || memcmp(packet_payload, "notify ", 7) == 0)
+ && (memcmp(&packet_payload[7], "SIP:", 4) == 0 || memcmp(&packet_payload[7], "sip:", 4) == 0)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found sip NOTIFY.\n");
+ ndpi_int_sip_add_connection(ndpi_struct, flow, 0);
+ return;
+ }
+
+ if ((memcmp(packet_payload, "REGISTER ", 9) == 0 || memcmp(packet_payload, "register ", 9) == 0)
+ && (memcmp(&packet_payload[9], "SIP:", 4) == 0 || memcmp(&packet_payload[9], "sip:", 4) == 0)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found sip REGISTER.\n");
+ ndpi_int_sip_add_connection(ndpi_struct, flow, 0);
+ return;
+ }
+
+ if ((memcmp(packet_payload, "INVITE ", 7) == 0 || memcmp(packet_payload, "invite ", 7) == 0)
+ && (memcmp(&packet_payload[7], "SIP:", 4) == 0 || memcmp(&packet_payload[7], "sip:", 4) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found sip INVITE.\n");
+ ndpi_int_sip_add_connection(ndpi_struct, flow, 0);
+ return;
+ }
+
+ /* seen this in second direction on the third position,
+ * maybe it could be deleted, if somebody sees it in the first direction,
+ * please delete this comment.
+ */
+
+ /*
+ if (memcmp(packet_payload, "SIP/2.0 200 OK", 14) == 0 || memcmp(packet_payload, "sip/2.0 200 OK", 14) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found sip SIP/2.0 0K.\n");
+ ndpi_int_sip_add_connection(ndpi_struct, flow, 0);
+ return;
+ }
+ */
+ if (memcmp(packet_payload, "SIP/2.0 ", 8) == 0 || memcmp(packet_payload, "sip/2.0 ", 8) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found sip SIP/2.0 *.\n");
+ ndpi_int_sip_add_connection(ndpi_struct, flow, 0);
+ return;
+ }
+
+ if ((memcmp(packet_payload, "BYE ", 4) == 0 || memcmp(packet_payload, "bye ", 4) == 0)
+ && (memcmp(&packet_payload[4], "SIP:", 4) == 0 || memcmp(&packet_payload[4], "sip:", 4) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found sip BYE.\n");
+ ndpi_int_sip_add_connection(ndpi_struct, flow, 0);
+ return;
+ }
+
+ if ((memcmp(packet_payload, "ACK ", 4) == 0 || memcmp(packet_payload, "ack ", 4) == 0)
+ && (memcmp(&packet_payload[4], "SIP:", 4) == 0 || memcmp(&packet_payload[4], "sip:", 4) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found sip ACK.\n");
+ ndpi_int_sip_add_connection(ndpi_struct, flow, 0);
+ return;
+ }
+
+ if ((memcmp(packet_payload, "CANCEL ", 7) == 0 || memcmp(packet_payload, "cancel ", 7) == 0)
+ && (memcmp(&packet_payload[4], "SIP:", 7) == 0 || memcmp(&packet_payload[4], "sip:", 7) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found sip CANCEL.\n");
+ ndpi_int_sip_add_connection(ndpi_struct, flow, 0);
+ return;
+ }
+
+ /* Courtesy of Miguel Quesada <mquesadab@gmail.com> */
+ if ((memcmp(packet_payload, "OPTIONS ", 8) == 0
+ || memcmp(packet_payload, "options ", 8) == 0)
+ && (memcmp(&packet_payload[8], "SIP:", 4) == 0
+ || memcmp(&packet_payload[8], "sip:", 4) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "found sip OPTIONS.\n");
+ ndpi_int_sip_add_connection(ndpi_struct, flow, 0);
+ return;
+ }
+ }
+
+ /* add bitmask for tcp only, some stupid udp programs
+ * send a very few (< 10 ) packets before invite (mostly a 0x0a0x0d, but just search the first 3 payload_packets here */
+ if (packet->udp != NULL && flow->packet_counter < 20) {
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "need next packet.\n");
+ return;
+ }
+#ifdef NDPI_PROTOCOL_STUN
+ /* for STUN flows we need some more packets */
+ if (packet->udp != NULL && flow->detected_protocol_stack[0] == NDPI_PROTOCOL_STUN && flow->packet_counter < 40) {
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "need next STUN packet.\n");
+ return;
+ }
+#endif
+
+ if (payload_len == 4 && get_u_int32_t(packet_payload, 0) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "maybe sip. need next packet.\n");
+ return;
+ }
+#ifdef NDPI_PROTOCOL_YAHOO
+ if (payload_len > 30 && packet_payload[0] == 0x90
+ && packet_payload[3] == payload_len - 20 && get_u_int32_t(packet_payload, 4) == 0
+ && get_u_int32_t(packet_payload, 8) == 0) {
+ flow->sip_yahoo_voice = 1;
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "maybe sip yahoo. need next packet.\n");
+ }
+ if (flow->sip_yahoo_voice && flow->packet_counter < 10) {
+ return;
+ }
+#endif
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "exclude sip.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SIP);
+ return;
+
+
+}
+
+void ndpi_search_sip(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // struct ndpi_flow_struct *flow = ndpi_struct->flow;
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_SIP, ndpi_struct, NDPI_LOG_DEBUG, "sip detection...\n");
+
+ /* skip marked packets */
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_SIP) {
+ if (packet->tcp_retransmission == 0) {
+ ndpi_search_sip_handshake(ndpi_struct, flow);
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/skinny.c b/src/lib/protocols/skinny.c
new file mode 100644
index 000000000..5e35f11f5
--- /dev/null
+++ b/src/lib/protocols/skinny.c
@@ -0,0 +1,63 @@
+/*
+ * skinny.c
+ *
+ * Copyright (C) 2013 Remy Mudingay <mudingay@ill.fr>
+ *
+ * This module is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This module 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+
+#ifdef NDPI_PROTOCOL_SKINNY
+static void ndpi_int_skinny_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SKINNY, NDPI_CORRELATED_PROTOCOL);
+}
+
+void ndpi_search_skinny(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t dport = 0, sport = 0;
+ const char pattern_9_bytes[9] = { 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ const char pattern_8_bytes[8] = { 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ const char keypadmsg_8_bytes[8] = { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ const char selectmsg_8_bytes[8] = { 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ NDPI_LOG(NDPI_PROTOCOL_SKINNY, ndpi_struct, NDPI_LOG_DEBUG, "search for SKINNY.\n");
+
+ if(packet->tcp != NULL) {
+ sport = ntohs(packet->tcp->source), dport = ntohs(packet->tcp->dest);
+ NDPI_LOG(NDPI_PROTOCOL_SKINNY, ndpi_struct, NDPI_LOG_DEBUG, "calculating SKINNY over tcp.\n");
+ if (dport == 2000 && ((packet->payload_packet_len == 24 &&
+ memcmp(&packet->payload[0], keypadmsg_8_bytes, 8) == 0)
+ || ((packet->payload_packet_len == 64) && memcmp(&packet->payload[0], pattern_8_bytes, 8) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_SKINNY, ndpi_struct, NDPI_LOG_DEBUG, "found skinny.\n");
+ ndpi_int_skinny_add_connection(ndpi_struct, flow);
+ } else if (sport == 2000 && ((packet->payload_packet_len == 28 &&
+ memcmp(&packet->payload[0], selectmsg_8_bytes, 8) == 0 ) ||
+ (packet->payload_packet_len == 44 &&
+ memcmp(&packet->payload[0], pattern_9_bytes, 9) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_SKINNY, ndpi_struct, NDPI_LOG_DEBUG, "found skinny.\n");
+ ndpi_int_skinny_add_connection(ndpi_struct, flow);
+ }
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_SKINNY, ndpi_struct, NDPI_LOG_DEBUG, "exclude SKINNY.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SKINNY);
+ }
+}
+#endif
diff --git a/src/lib/protocols/skype.c b/src/lib/protocols/skype.c
new file mode 100644
index 000000000..8d2a3a72b
--- /dev/null
+++ b/src/lib/protocols/skype.c
@@ -0,0 +1,122 @@
+/*
+ * skype.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_SKYPE
+
+
+static u_int8_t is_skype_host(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t host) {
+ struct in_addr pin;
+
+ pin.s_addr = host;
+
+ return((ndpi_network_ptree_match(ndpi_struct, &pin) == NDPI_PROTOCOL_SKYPE) ? 1 : 0);
+}
+
+u_int8_t is_skype_flow(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(packet->iph) {
+ /*
+ Skype connections are identified by some SSL-like communications
+ without SSL certificate being exchanged
+ */
+ if(is_skype_host(ndpi_struct, ntohl(packet->iph->saddr))
+ || is_skype_host(ndpi_struct, ntohl(packet->iph->daddr))) {
+ return(1);
+ }
+ }
+
+ return(0);
+}
+
+static void ndpi_check_skype(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // const u_int8_t *packet_payload = packet->payload;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /*
+ Skype AS8220
+ 212.161.8.0/24
+ */
+ if(is_skype_flow(ndpi_struct, flow)) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ if(packet->udp != NULL) {
+ flow->l4.udp.skype_packet_id++;
+
+ if(flow->l4.udp.skype_packet_id < 5) {
+ /* skype-to-skype */
+ if(((payload_len == 3) && ((packet->payload[2] & 0x0F)== 0x0d))
+ || ((payload_len >= 16)
+ && (packet->payload[0] != 0x30) /* Avoid invalid SNMP detection */
+ && (packet->payload[2] == 0x02))) {
+ NDPI_LOG(NDPI_PROTOCOL_SKYPE, ndpi_struct, NDPI_LOG_DEBUG, "Found skype.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE, NDPI_REAL_PROTOCOL);
+ }
+
+ return;
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SKYPE);
+ return;
+ } else if(packet->tcp != NULL) {
+ flow->l4.tcp.skype_packet_id++;
+
+ if(flow->l4.tcp.skype_packet_id < 3) {
+ ; /* Too early */
+ } else if((flow->l4.tcp.skype_packet_id == 3)
+ /* We have seen the 3-way handshake */
+ && flow->l4.tcp.seen_syn
+ && flow->l4.tcp.seen_syn_ack
+ && flow->l4.tcp.seen_ack) {
+ if((payload_len == 8) || (payload_len == 3)) {
+ //printf("[SKYPE] %u/%u\n", ntohs(packet->tcp->source), ntohs(packet->tcp->dest));
+
+ NDPI_LOG(NDPI_PROTOCOL_SKYPE, ndpi_struct, NDPI_LOG_DEBUG, "Found skype.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE, NDPI_REAL_PROTOCOL);
+ }
+
+ /* printf("[SKYPE] [id: %u][len: %d]\n", flow->l4.tcp.skype_packet_id, payload_len); */
+ } else
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SKYPE);
+
+ return;
+ }
+}
+
+void ndpi_search_skype(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_SKYPE, ndpi_struct, NDPI_LOG_DEBUG, "skype detection...\n");
+
+ /* skip marked packets */
+ if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_SKYPE)
+ ndpi_check_skype(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/smb.c b/src/lib/protocols/smb.c
new file mode 100644
index 000000000..031572ead
--- /dev/null
+++ b/src/lib/protocols/smb.c
@@ -0,0 +1,57 @@
+/*
+ * smb.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_SMB
+
+static void ndpi_int_smb_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SMB, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_smb_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(packet && packet->tcp) {
+ NDPI_LOG(NDPI_PROTOCOL_SMB, ndpi_struct, NDPI_LOG_DEBUG, "search SMB.\n");
+
+ if (packet->tcp->dest == htons(445)
+ && packet->payload_packet_len > (32 + 4 + 4)
+ && (packet->payload_packet_len - 4) == ntohl(get_u_int32_t(packet->payload, 0))
+ && get_u_int32_t(packet->payload, 4) == htonl(0xff534d42)) {
+ NDPI_LOG(NDPI_PROTOCOL_SMB, ndpi_struct, NDPI_LOG_DEBUG, "found SMB.\n");
+ ndpi_int_smb_add_connection(ndpi_struct, flow);
+ return;
+
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_SMB, ndpi_struct, NDPI_LOG_DEBUG, "exclude SMB.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SMB);
+}
+
+#endif
diff --git a/src/lib/protocols/snmp.c b/src/lib/protocols/snmp.c
new file mode 100644
index 000000000..2ddf21229
--- /dev/null
+++ b/src/lib/protocols/snmp.c
@@ -0,0 +1,126 @@
+/*
+ * snmp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_SNMP
+
+static void ndpi_int_snmp_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SNMP, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_snmp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len > 32 && packet->payload[0] == 0x30) {
+ int offset;
+ switch (packet->payload[1]) {
+ case 0x81:
+ offset = 3;
+ break;
+ case 0x82:
+ offset = 4;
+ break;
+ default:
+ if (packet->payload[1] > 0x82) {
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG, "SNMP excluded, second byte is > 0x82\n");
+ goto excl;
+ }
+ offset = 2;
+ }
+
+ if (get_u_int16_t(packet->payload, offset) != htons(0x0201)) {
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG, "SNMP excluded, 0x0201 pattern not found\n");
+ goto excl;
+ }
+
+ if (packet->payload[offset + 2] >= 0x04) {
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG, "SNMP excluded, version > 3\n");
+ goto excl;
+ }
+
+ if (flow->l4.udp.snmp_stage == 0) {
+ if (packet->udp->dest == htons(161) || packet->udp->dest == htons(162)) {
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG, "SNMP detected due to port.\n");
+ ndpi_int_snmp_add_connection(ndpi_struct, flow);
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG, "SNMP stage 0.\n");
+ if (packet->payload[offset + 2] == 3) {
+ flow->l4.udp.snmp_msg_id = ntohs(get_u_int32_t(packet->payload, offset + 8));
+ } else if (packet->payload[offset + 2] == 0) {
+ flow->l4.udp.snmp_msg_id = get_u_int8_t(packet->payload, offset + 15);
+ } else {
+ flow->l4.udp.snmp_msg_id = ntohs(get_u_int16_t(packet->payload, offset + 15));
+ }
+ flow->l4.udp.snmp_stage = 1 + packet->packet_direction;
+ return;
+ } else if (flow->l4.udp.snmp_stage == 1 + packet->packet_direction) {
+ if (packet->payload[offset + 2] == 0) {
+ if (flow->l4.udp.snmp_msg_id != get_u_int8_t(packet->payload, offset + 15) - 1) {
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG,
+ "SNMP v1 excluded, message ID doesn't match\n");
+ goto excl;
+ }
+ }
+ } else if (flow->l4.udp.snmp_stage == 2 - packet->packet_direction) {
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG, "SNMP stage 1-2.\n");
+ if (packet->payload[offset + 2] == 3) {
+ if (flow->l4.udp.snmp_msg_id != ntohs(get_u_int32_t(packet->payload, offset + 8))) {
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG,
+ "SNMP v3 excluded, message ID doesn't match\n");
+ goto excl;
+ }
+ } else if (packet->payload[offset + 2] == 0) {
+ if (flow->l4.udp.snmp_msg_id != get_u_int8_t(packet->payload, offset + 15)) {
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG,
+ "SNMP v1 excluded, message ID doesn't match\n");
+ goto excl;
+ }
+ } else {
+ if (flow->l4.udp.snmp_msg_id != ntohs(get_u_int16_t(packet->payload, offset + 15))) {
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG,
+ "SNMP v2 excluded, message ID doesn't match\n");
+ goto excl;
+ }
+ }
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG, "SNMP detected.\n");
+ ndpi_int_snmp_add_connection(ndpi_struct, flow);
+ return;
+ }
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_SNMP, ndpi_struct, NDPI_LOG_DEBUG, "SNMP excluded.\n");
+ }
+ excl:
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SNMP);
+
+}
+
+#endif
diff --git a/src/lib/protocols/socks4.c b/src/lib/protocols/socks4.c
new file mode 100644
index 000000000..e89f7050c
--- /dev/null
+++ b/src/lib/protocols/socks4.c
@@ -0,0 +1,96 @@
+/*
+ * socks4.c
+ *
+ * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk>
+ *
+ * The signature is based on the Libprotoident library.
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_SOCKS4
+static void ndpi_int_socks4_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SOCKS4, NDPI_REAL_PROTOCOL);
+}
+
+static void ndpi_check_socks4(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Break after 20 packets. */
+ if (flow->packet_counter > 20) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "Exclude SOCKS4.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOCKS4);
+ return;
+ }
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->socks4_stage == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS4 stage 0: \n");
+
+ /*Octets 3 and 4 contain the port number, port 80 and 25 for now. */
+ if ((payload_len == 9) &&
+ (((packet->payload[0] == 0x04) && (packet->payload[1] == 0x01) && (packet->payload[2] == 0x00) && (packet->payload[3] == 0x50))
+ ||
+ ((packet->payload[0] == 0x04) && (packet->payload[1] == 0x01) && (packet->payload[2] == 0x00) && (packet->payload[3] == 0x19)))) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "Possible SOCKS4 request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->socks4_stage = packet->packet_direction + 1;
+ }
+
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS4 stage %u: \n", flow->socks4_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->socks4_stage - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if (payload_len == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "Found SOCKS4.\n");
+ ndpi_int_socks4_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to SOCKS4, resetting the stage to 0...\n");
+ flow->socks4_stage = 0;
+ }
+
+ }
+}
+
+void ndpi_search_socks4(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS4, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS4 detection...\n");
+
+ /* skip marked packets */
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_SOCKS4) {
+ if (packet->tcp_retransmission == 0) {
+ ndpi_check_socks4(ndpi_struct, flow);
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/socks5.c b/src/lib/protocols/socks5.c
new file mode 100644
index 000000000..7aa4c90a1
--- /dev/null
+++ b/src/lib/protocols/socks5.c
@@ -0,0 +1,92 @@
+/*
+ * socks5.c
+ *
+ * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk>
+ *
+ * The signature is based on the Libprotoident library.
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_SOCKS5
+static void ndpi_int_socks5_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SOCKS5, NDPI_REAL_PROTOCOL);
+}
+
+static void ndpi_check_socks5(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Break after 20 packets. */
+ if (flow->packet_counter > 20) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "Exclude SOCKS5.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOCKS5);
+ return;
+ }
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->socks5_stage == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS5 stage 0: \n");
+
+ if ((payload_len == 3) && (packet->payload[0] == 0x05) && (packet->payload[1] == 0x01) && (packet->payload[2] == 0x00)) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "Possible SOCKS5 request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->socks5_stage = packet->packet_direction + 1;
+ }
+
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS5 stage %u: \n", flow->socks5_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->socks5_stage - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len == 0) || ((payload_len == 2) && (packet->payload[0] == 0x05) && (packet->payload[1] == 0x00))) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "Found SOCKS5.\n");
+ ndpi_int_socks5_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to SOCKS5, resetting the stage to 0...\n");
+ flow->socks5_stage = 0;
+ }
+
+ }
+}
+
+void ndpi_search_socks5(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_SOCKS5, ndpi_struct, NDPI_LOG_DEBUG, "SOCKS5 detection...\n");
+
+ /* skip marked packets */
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_SOCKS5) {
+ if (packet->tcp_retransmission == 0) {
+ ndpi_check_socks5(ndpi_struct, flow);
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/socrates.c b/src/lib/protocols/socrates.c
new file mode 100644
index 000000000..c433580fc
--- /dev/null
+++ b/src/lib/protocols/socrates.c
@@ -0,0 +1,80 @@
+/*
+ * socrates.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_SOCRATES
+
+
+static void ndpi_socrates_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SOCRATES, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_socrates(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+
+ NDPI_LOG(NDPI_PROTOCOL_SOCRATES, ndpi_struct, NDPI_LOG_DEBUG, "search socrates.\n");
+ if (packet->udp != NULL) {
+ if (packet->payload_packet_len > 9 && packet->payload[0] == 0xfe
+ && packet->payload[packet->payload_packet_len - 1] == 0x05) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCRATES, ndpi_struct, NDPI_LOG_DEBUG, "found fe.\n");
+
+ NDPI_LOG(NDPI_PROTOCOL_SOCRATES, ndpi_struct, NDPI_LOG_DEBUG, "len match.\n");
+ if (memcmp(&packet->payload[2], "socrates", 8) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCRATES, ndpi_struct, NDPI_LOG_DEBUG, "found socrates udp.\n");
+ ndpi_socrates_add_connection(ndpi_struct, flow);
+ }
+
+ }
+ } else if (packet->tcp != NULL) {
+ if (packet->payload_packet_len > 13 && packet->payload[0] == 0xfe
+ && packet->payload[packet->payload_packet_len - 1] == 0x05) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCRATES, ndpi_struct, NDPI_LOG_DEBUG, "found fe.\n");
+ if (packet->payload_packet_len == ntohl(get_u_int32_t(packet->payload, 2))) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCRATES, ndpi_struct, NDPI_LOG_DEBUG, "len match.\n");
+ if (memcmp(&packet->payload[6], "socrates", 8) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SOCRATES, ndpi_struct, NDPI_LOG_DEBUG, "found socrates tcp.\n");
+ ndpi_socrates_add_connection(ndpi_struct, flow);
+ }
+ }
+ }
+ }
+
+
+
+
+ NDPI_LOG(NDPI_PROTOCOL_SOCRATES, ndpi_struct, NDPI_LOG_DEBUG, "exclude socrates.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOCRATES);
+}
+
+#endif
diff --git a/src/lib/protocols/sopcast.c b/src/lib/protocols/sopcast.c
new file mode 100644
index 000000000..363caba42
--- /dev/null
+++ b/src/lib/protocols/sopcast.c
@@ -0,0 +1,219 @@
+/*
+ * sopcast.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_SOPCAST
+
+
+static void ndpi_int_sopcast_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SOPCAST, NDPI_REAL_PROTOCOL);
+}
+
+/**
+ * this function checks for sopcast tcp pattern
+ *
+ * NOTE: if you add more patterns please keep the number of if levels
+ * low, it is already complex enough
+ */
+
+#if !defined(WIN32)
+ static inline
+#else
+__forceinline static
+#endif
+ u_int8_t ndpi_int_is_sopcast_tcp(const u_int8_t * payload, const u_int16_t payload_len)
+{
+ if (payload_len != 54)
+ return 0;
+
+ if (payload[2] != payload[3] - 4 && payload[2] != payload[3] + 4)
+ return 0;
+
+ if (payload[2] != payload[4] - 1 && payload[2] != payload[4] + 1)
+ return 0;
+
+ if (payload[25] != payload[25 + 16 - 1] + 1 && payload[25] != payload[25 + 16 - 1] - 1) {
+
+ if (payload[3] != payload[25] &&
+ payload[3] != payload[25] - 4 && payload[3] != payload[25] + 4 && payload[3] != payload[25] - 21) {
+ return 0;
+ }
+ }
+
+ if (payload[4] != payload[28] ||
+ payload[28] != payload[30] ||
+ payload[30] != payload[31] ||
+ get_u_int16_t(payload, 30) != get_u_int16_t(payload, 32) || get_u_int16_t(payload, 32) != get_u_int16_t(payload, 34)) {
+
+ if ((payload[2] != payload[5] - 1 && payload[2] != payload[5] + 1) ||
+ payload[2] != payload[25] ||
+ payload[4] != payload[28] ||
+ payload[4] != payload[31] ||
+ payload[4] != payload[32] ||
+ payload[4] != payload[33] ||
+ payload[4] != payload[34] ||
+ payload[4] != payload[35] || payload[4] != payload[30] || payload[2] != payload[36]) {
+ return 0;
+ }
+ }
+
+ if (payload[42] != payload[53])
+ return 0;
+
+ if (payload[45] != payload[46] + 1 && payload[45] != payload[46] - 1)
+ return 0;
+
+ if (payload[45] != payload[49] || payload[46] != payload[50] || payload[47] != payload[51])
+ return 0;
+
+ return 1;
+}
+
+static void ndpi_search_sopcast_tcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if (flow->packet_counter == 1 && packet->payload_packet_len == 54 && get_u_int16_t(packet->payload, 0) == ntohs(0x0036)) {
+ if (ndpi_int_is_sopcast_tcp(packet->payload, packet->payload_packet_len)) {
+ NDPI_LOG(NDPI_PROTOCOL_SOPCAST, ndpi_struct, NDPI_LOG_DEBUG, "found sopcast TCP \n");
+ ndpi_int_sopcast_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_SOPCAST, ndpi_struct, NDPI_LOG_DEBUG, "exclude sopcast TCP. \n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOPCAST);
+
+
+}
+
+static void ndpi_search_sopcast_udp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_SOPCAST, ndpi_struct, NDPI_LOG_DEBUG, "search sopcast. \n");
+
+
+ if (packet->payload_packet_len == 52 && packet->payload[0] == 0xff
+ && packet->payload[1] == 0xff && packet->payload[2] == 0x01
+ && packet->payload[8] == 0x02 && packet->payload[9] == 0xff
+ && packet->payload[10] == 0x00 && packet->payload[11] == 0x2c
+ && packet->payload[12] == 0x00 && packet->payload[13] == 0x00 && packet->payload[14] == 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_SOPCAST, ndpi_struct, NDPI_LOG_DEBUG, "found sopcast with if I. \n");
+ ndpi_int_sopcast_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if ((packet->payload_packet_len == 80 || packet->payload_packet_len == 28 || packet->payload_packet_len == 94)
+ && packet->payload[0] == 0x00 && (packet->payload[2] == 0x02 || packet->payload[2] == 0x01)
+ && packet->payload[8] == 0x01 && packet->payload[9] == 0xff
+ && packet->payload[10] == 0x00 && packet->payload[11] == 0x14
+ && packet->payload[12] == 0x00 && packet->payload[13] == 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_SOPCAST, ndpi_struct, NDPI_LOG_DEBUG, "found sopcast with if II. \n");
+ ndpi_int_sopcast_add_connection(ndpi_struct, flow);
+ return;
+ }
+ /* this case has been seen once. Please revome this comment, if you see it another time */
+ if (packet->payload_packet_len == 60 && packet->payload[0] == 0x00
+ && packet->payload[2] == 0x01
+ && packet->payload[8] == 0x03 && packet->payload[9] == 0xff
+ && packet->payload[10] == 0x00 && packet->payload[11] == 0x34
+ && packet->payload[12] == 0x00 && packet->payload[13] == 0x00 && packet->payload[14] == 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_SOPCAST, ndpi_struct, NDPI_LOG_DEBUG, "found sopcast with if III. \n");
+ ndpi_int_sopcast_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len == 42 && packet->payload[0] == 0x00
+ && packet->payload[1] == 0x02 && packet->payload[2] == 0x01
+ && packet->payload[3] == 0x07 && packet->payload[4] == 0x03
+ && packet->payload[8] == 0x06
+ && packet->payload[9] == 0x01 && packet->payload[10] == 0x00
+ && packet->payload[11] == 0x22 && packet->payload[12] == 0x00 && packet->payload[13] == 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_SOPCAST, ndpi_struct, NDPI_LOG_DEBUG, "found sopcast with if IV. \n");
+ ndpi_int_sopcast_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len == 28 && packet->payload[0] == 0x00
+ && packet->payload[1] == 0x0c && packet->payload[2] == 0x01
+ && packet->payload[3] == 0x07 && packet->payload[4] == 0x00
+ && packet->payload[8] == 0x01
+ && packet->payload[9] == 0x01 && packet->payload[10] == 0x00
+ && packet->payload[11] == 0x14 && packet->payload[12] == 0x00 && packet->payload[13] == 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_SOPCAST, ndpi_struct, NDPI_LOG_DEBUG, "found sopcast with if V. \n");
+ ndpi_int_sopcast_add_connection(ndpi_struct, flow);
+ return;
+ }
+ /* this case has been seen once. Please revome this comment, if you see it another time */
+ if (packet->payload_packet_len == 286 && packet->payload[0] == 0x00
+ && packet->payload[1] == 0x02 && packet->payload[2] == 0x01
+ && packet->payload[3] == 0x07 && packet->payload[4] == 0x03
+ && packet->payload[8] == 0x06
+ && packet->payload[9] == 0x01 && packet->payload[10] == 0x01
+ && packet->payload[11] == 0x16 && packet->payload[12] == 0x00 && packet->payload[13] == 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_SOPCAST, ndpi_struct, NDPI_LOG_DEBUG, "found sopcast with if VI. \n");
+ ndpi_int_sopcast_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len == 76 && packet->payload[0] == 0xff
+ && packet->payload[1] == 0xff && packet->payload[2] == 0x01
+ && packet->payload[8] == 0x0c && packet->payload[9] == 0xff
+ && packet->payload[10] == 0x00 && packet->payload[11] == 0x44
+ && packet->payload[16] == 0x01 && packet->payload[15] == 0x01
+ && packet->payload[12] == 0x00 && packet->payload[13] == 0x00 && packet->payload[14] == 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_SOPCAST, ndpi_struct, NDPI_LOG_DEBUG, "found sopcast with if VII. \n");
+ ndpi_int_sopcast_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ /* Attention please: no asymmetric detection necessary. This detection works asymmetrically as well. */
+
+ NDPI_LOG(NDPI_PROTOCOL_SOPCAST, ndpi_struct, NDPI_LOG_DEBUG, "exclude sopcast. \n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOPCAST);
+
+
+
+}
+
+void ndpi_search_sopcast(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if (packet->udp != NULL)
+ ndpi_search_sopcast_udp(ndpi_struct, flow);
+ if (packet->tcp != NULL)
+ ndpi_search_sopcast_tcp(ndpi_struct, flow);
+
+}
+#endif
diff --git a/src/lib/protocols/soulseek.c b/src/lib/protocols/soulseek.c
new file mode 100644
index 000000000..061acfa51
--- /dev/null
+++ b/src/lib/protocols/soulseek.c
@@ -0,0 +1,286 @@
+/*
+ * soulseek.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_SOULSEEK
+
+static void ndpi_int_soulseek_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SOULSEEK, NDPI_REAL_PROTOCOL);
+
+ if (src != NULL) {
+ src->soulseek_last_safe_access_time = packet->tick_timestamp;
+ }
+ if (dst != NULL) {
+ dst->soulseek_last_safe_access_time = packet->tick_timestamp;
+ }
+
+ return;
+}
+
+void ndpi_search_soulseek_tcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "Soulseek: search soulseec tcp \n");
+
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SOULSEEK) {
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "packet marked as Soulseek\n");
+ if (src != NULL)
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG,
+ " SRC bitmask: %u, packet tick %llu , last safe access timestamp: %llu\n",
+ NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, NDPI_PROTOCOL_SOULSEEK)
+ != 0 ? 1 : 0, (u_int64_t) packet->tick_timestamp, (u_int64_t) src->soulseek_last_safe_access_time);
+ if (dst != NULL)
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG,
+ " DST bitmask: %u, packet tick %llu , last safe ts: %llu\n",
+ NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, NDPI_PROTOCOL_SOULSEEK)
+ != 0 ? 1 : 0, (u_int64_t) packet->tick_timestamp, (u_int64_t) dst->soulseek_last_safe_access_time);
+
+ if (packet->payload_packet_len == 431) {
+ if (dst != NULL) {
+ dst->soulseek_last_safe_access_time = packet->tick_timestamp;
+ }
+ return;
+ }
+ if (packet->payload_packet_len == 12 && get_l32(packet->payload, 4) == 0x02) {
+ if (src != NULL) {
+ src->soulseek_last_safe_access_time = packet->tick_timestamp;
+ if (packet->tcp != NULL && src->soulseek_listen_port == 0) {
+ src->soulseek_listen_port = get_l32(packet->payload, 8);
+ return;
+ }
+ }
+ }
+
+ if (src != NULL && ((u_int32_t)
+ (packet->tick_timestamp -
+ src->soulseek_last_safe_access_time) <
+ ndpi_struct->soulseek_connection_ip_tick_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG,
+ "Soulseek: SRC update last safe access time and SKIP_FOR_TIME \n");
+ src->soulseek_last_safe_access_time = packet->tick_timestamp;
+ }
+
+ if (dst != NULL && ((u_int32_t)
+ (packet->tick_timestamp -
+ dst->soulseek_last_safe_access_time) <
+ ndpi_struct->soulseek_connection_ip_tick_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG,
+ "Soulseek: DST update last safe access time and SKIP_FOR_TIME \n");
+ dst->soulseek_last_safe_access_time = packet->tick_timestamp;
+ }
+ }
+
+
+ if (dst != NULL && dst->soulseek_listen_port != 0 && dst->soulseek_listen_port == ntohs(packet->tcp->dest)
+ && ((u_int32_t)
+ (packet->tick_timestamp - dst->soulseek_last_safe_access_time) <
+ ndpi_struct->soulseek_connection_ip_tick_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG,
+ "Soulseek: Plain detection on Port : %u packet_tick_timestamp: %u soulseeek_last_safe_access_time: %u soulseek_connection_ip_ticktimeout: %u\n",
+ dst->soulseek_listen_port, packet->tick_timestamp,
+ dst->soulseek_last_safe_access_time, ndpi_struct->soulseek_connection_ip_tick_timeout);
+ ndpi_int_soulseek_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ if (flow->l4.tcp.soulseek_stage == 0) {
+
+ u_int32_t index = 0;
+
+ if (packet->payload_packet_len >= 12 && packet->payload_packet_len < 300 && get_l32(packet->payload, 4) == 1) {
+ while (!get_u_int16_t(packet->payload, index + 2)
+ && (index + get_l32(packet->payload, index)) < packet->payload_packet_len - 4) {
+ if (get_l32(packet->payload, index) < 8) /*Minimum soulsek login msg is 8B */
+ break;
+
+ if (index + get_l32(packet->payload, index) + 4 <= index) {
+ /* avoid overflow */
+ break;
+ }
+
+ index += get_l32(packet->payload, index) + 4;
+ }
+ if (index + get_l32(packet->payload, index) ==
+ packet->payload_packet_len - 4 && !get_u_int16_t(packet->payload, 10)) {
+ /*This structure seems to be soulseek proto */
+ index = get_l32(packet->payload, 8) + 12; // end of "user name"
+ if ((index + 4) <= packet->payload_packet_len && !get_u_int16_t(packet->payload, index + 2)) // for passwd len
+ {
+ index += get_l32(packet->payload, index) + 4; //end of "Passwd"
+ if ((index + 4 + 4) <= packet->payload_packet_len && !get_u_int16_t(packet->payload, index + 6)) // to read version,hashlen
+ {
+ index += get_l32(packet->payload, index + 4) + 8; // enf of "hash value"
+ if (index == get_l32(packet->payload, 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK,
+ ndpi_struct, NDPI_LOG_DEBUG, "Soulseek Login Detected\n");
+ ndpi_int_soulseek_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+ }
+ }
+ if (packet->payload_packet_len > 8
+ && packet->payload_packet_len < 200 && get_l32(packet->payload, 0) == packet->payload_packet_len - 4) {
+ //Server Messages:
+ const u_int32_t msgcode = get_l32(packet->payload, 4);
+
+ if (msgcode == 0x7d) {
+ flow->l4.tcp.soulseek_stage = 1 + packet->packet_direction;
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "Soulseek Messages Search\n");
+ return;
+ } else if (msgcode == 0x02 && packet->payload_packet_len == 12) {
+ const u_int32_t soulseek_listen_port = get_l32(packet->payload, 8);
+
+ if (src != NULL) {
+ src->soulseek_last_safe_access_time = packet->tick_timestamp;
+
+ if (packet->tcp != NULL && src->soulseek_listen_port == 0) {
+ src->soulseek_listen_port = soulseek_listen_port;
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct,
+ NDPI_LOG_DEBUG, "\n Listen Port Saved : %u", src->soulseek_listen_port);
+ ndpi_int_soulseek_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ }
+ //Peer Messages : Peer Init Message Detection
+ if (get_l32(packet->payload, 0) == packet->payload_packet_len - 4) {
+ const u_int32_t typelen = get_l32(packet->payload, packet->payload_packet_len - 9);
+ const u_int8_t type = packet->payload[packet->payload_packet_len - 5];
+ const u_int32_t namelen = get_l32(packet->payload, 5);
+ if (packet->payload[4] == 0x01 && typelen == 1
+ && namelen <= packet->payload_packet_len
+ && (4 + 1 + 4 + namelen + 4 + 1 + 4) ==
+ packet->payload_packet_len && (type == 'F' || type == 'P' || type == 'D')) {
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected\n");
+ ndpi_int_soulseek_add_connection(ndpi_struct, flow);
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "1\n");
+ }
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "3\n");
+ //Peer Message : Pierce Firewall
+ if (packet->payload_packet_len == 9 && get_l32(packet->payload, 0) == 5
+ && packet->payload[4] <= 0x10 && get_u_int32_t(packet->payload, 5) != 0x00000000) {
+ flow->l4.tcp.soulseek_stage = 1 + packet->packet_direction;
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_TRACE, "Soulseek Size 9 Pierce Firewall\n");
+ return;
+ }
+
+ }
+
+ if (packet->payload_packet_len > 25 && packet->payload[4] == 0x01 && !get_u_int16_t(packet->payload, 7)
+ && !get_u_int16_t(packet->payload, 2)) {
+ const u_int32_t usrlen = get_l32(packet->payload, 5);
+
+ if (usrlen <= packet->payload_packet_len - 4 + 1 + 4 + 4 + 1 + 4) {
+ const u_int32_t typelen = get_l32(packet->payload, 4 + 1 + 4 + usrlen);
+ const u_int8_t type = packet->payload[4 + 1 + 4 + usrlen + 4];
+ if (typelen == 1 && (type == 'F' || type == 'P' || type == 'D')) {
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct,
+ NDPI_LOG_DEBUG, "soulseek detected Pattern command(D|P|F).\n");
+ ndpi_int_soulseek_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+
+ } else if (flow->l4.tcp.soulseek_stage == 2 - packet->packet_direction) {
+ if (packet->payload_packet_len > 8) {
+ if ((packet->payload[0] || packet->payload[1]) && get_l32(packet->payload, 4) == 9) {
+ /* 9 is search result */
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected Second Pkt\n");
+ ndpi_int_soulseek_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (get_l32(packet->payload, 0) == packet->payload_packet_len - 4) {
+ const u_int32_t msgcode = get_l32(packet->payload, 4);
+ if (msgcode == 0x03 && packet->payload_packet_len >= 12) //Server Message : Get Peer Address
+ {
+ const u_int32_t usrlen = get_l32(packet->payload, 8);
+ if (usrlen <= packet->payload_packet_len && 4 + 4 + 4 + usrlen == packet->payload_packet_len) {
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct,
+ NDPI_LOG_DEBUG, "Soulseek Request Get Peer Address Detected\n");
+ ndpi_int_soulseek_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+ }
+
+ if (packet->payload_packet_len == 8 && get_l32(packet->payload, 4) == 0x00000004) {
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected\n");
+ ndpi_int_soulseek_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ if (packet->payload_packet_len == 4
+ && get_u_int16_t(packet->payload, 2) == 0x00 && get_u_int16_t(packet->payload, 0) != 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected\n");
+ ndpi_int_soulseek_add_connection(ndpi_struct, flow);
+ return;
+ } else if (packet->payload_packet_len == 4) {
+ flow->l4.tcp.soulseek_stage = 3;
+ return;
+ }
+ } else if (flow->l4.tcp.soulseek_stage == 1 + packet->packet_direction) {
+ if (packet->payload_packet_len > 8) {
+ if (packet->payload[4] == 0x03 && get_l32(packet->payload, 5) == 0x00000031) {
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct,
+ NDPI_LOG_DEBUG, "soulseek detected Second Pkt with SIGNATURE :: 0x0331000000 \n");
+ ndpi_int_soulseek_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+ if (flow->l4.tcp.soulseek_stage == 3 && packet->payload_packet_len == 8 && !get_u_int32_t(packet->payload, 4)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_SOULSEEK, ndpi_struct, NDPI_LOG_DEBUG, "soulseek detected bcz of 8B pkt\n");
+ ndpi_int_soulseek_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (flow->l4.tcp.soulseek_stage && flow->packet_counter < 11) {
+ } else {
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOULSEEK);
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/spotify.c b/src/lib/protocols/spotify.c
new file mode 100644
index 000000000..43ed5ec92
--- /dev/null
+++ b/src/lib/protocols/spotify.c
@@ -0,0 +1,128 @@
+/*
+ * spotify.c
+ *
+ * Copyright (C) 2011-13 by ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_SPOTIFY
+static void ndpi_int_spotify_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int8_t due_to_correlation)
+{
+ ndpi_int_add_connection(ndpi_struct, flow,
+ NDPI_PROTOCOL_SPOTIFY,
+ due_to_correlation ? NDPI_CORRELATED_PROTOCOL : NDPI_REAL_PROTOCOL);
+}
+
+
+static void ndpi_check_spotify(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // const u_int8_t *packet_payload = packet->payload;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ if(packet->udp != NULL) {
+ u_int16_t spotify_port = htons(57621);
+
+ if((packet->udp->source == spotify_port)
+ && (packet->udp->dest == spotify_port)) {
+ if(payload_len > 2) {
+ if(memcmp(packet->payload, "SpotUdp", 7) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SPOTIFY, ndpi_struct, NDPI_LOG_DEBUG, "Found spotify udp dissector.\n");
+ ndpi_int_spotify_add_connection(ndpi_struct, flow, 0);
+ return;
+ }
+ }
+ }
+ } else if(packet->tcp != NULL) {
+
+ if(packet->payload[0] == 0x00 && packet->payload[1] == 0x04 &&
+ packet->payload[2] == 0x00 && packet->payload[3] == 0x00&&
+ packet->payload[6] == 0x52 && packet->payload[7] == 0x0e &&
+ packet->payload[8] == 0x50 ) {
+ NDPI_LOG(NDPI_PROTOCOL_SPOTIFY, ndpi_struct, NDPI_LOG_DEBUG, "Found spotify tcp dissector.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SPOTIFY, NDPI_REAL_PROTOCOL);
+ }
+
+
+ if(packet->iph /* IPv4 Only: we need to support packet->iphv6 at some point */) {
+ /* if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) */ {
+ /*
+ Spotify
+
+ 78.31.8.0 - 78.31.15.255 (78.31.8.0/22)
+ AS29017
+
+ 193.235.232.0 - 193.235.235.255 (193.235.232.0/22)
+ AS29017
+
+ 194.132.196.0 - 194.132.199.255 (194.132.198.147/22)
+ AS43650
+
+ 194.132.176.0 - 194.132.179.255 (194.132.176.0/22)
+ AS43650
+
+ 194.132.162.0 - 194.132.163.255 (194.132.162.0/24)
+ AS43650
+ */
+
+ //printf("%08X - %08X\n", ntohl(packet->iph->saddr), ntohl(packet->iph->daddr));
+ if(((ntohl(packet->iph->saddr) & 0xFFFFFC00 /* 255.255.252.0 */) == 0x4E1F0800 /* 78.31.8.0 */)
+ || ((ntohl(packet->iph->daddr) & 0xFFFFFC00 /* 255.255.252.0 */) == 0x4E1F0800 /* 78.31.8.0 */)
+ /* **** */
+ || ((ntohl(packet->iph->saddr) & 0xFFFFFC00 /* 255.255.252.0 */) == 0xC1EBE800 /* 193.235.232.0 */)
+ || ((ntohl(packet->iph->daddr) & 0xFFFFFC00 /* 255.255.252.0 */) == 0xC1EBE800 /* 193.235.232.0 */)
+ /* **** */
+ || ((ntohl(packet->iph->saddr) & 0xFFFFFC00 /* 255.255.252.0 */) == 0xC284C400 /* 194.132.196.0 */)
+ || ((ntohl(packet->iph->daddr) & 0xFFFFFC00 /* 255.255.252.0 */) == 0xC284C400 /* 194.132.196.0 */)
+ /* **** */
+ || ((ntohl(packet->iph->saddr) & 0xFFFFFC00 /* 255.255.252.0 */) == 0xC284A200 /* 194.132.162.0 */)
+ || ((ntohl(packet->iph->daddr) & 0xFFFFFC00 /* 255.255.252.0 */) == 0xC284A200 /* 194.132.162.0 */)
+ ) {
+ NDPI_LOG(NDPI_PROTOCOL_SPOTIFY, ndpi_struct, NDPI_LOG_DEBUG, "Found spotify via ip range.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SPOTIFY, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_SPOTIFY, ndpi_struct, NDPI_LOG_DEBUG, "exclude spotify.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SPOTIFY);
+}
+
+void ndpi_search_spotify(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_SPOTIFY, ndpi_struct, NDPI_LOG_DEBUG, "spotify detection...\n");
+
+ /* skip marked packets */
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_SPOTIFY) {
+ if (packet->tcp_retransmission == 0) {
+ ndpi_check_spotify(ndpi_struct, flow);
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/ssdp.c b/src/lib/protocols/ssdp.c
new file mode 100644
index 000000000..83ce102d4
--- /dev/null
+++ b/src/lib/protocols/ssdp.c
@@ -0,0 +1,70 @@
+/*
+ * ssdp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_SSDP
+
+
+static void ndpi_int_ssdp_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSDP, NDPI_REAL_PROTOCOL);
+}
+
+/* this detection also works asymmetrically */
+void ndpi_search_ssdp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_SSDP, ndpi_struct, NDPI_LOG_DEBUG, "search ssdp.\n");
+ if (packet->udp != NULL) {
+
+ if (packet->payload_packet_len > 100) {
+ if ((memcmp(packet->payload, "M-SEARCH * HTTP/1.1", 19) == 0)
+ || memcmp(packet->payload, "NOTIFY * HTTP/1.1", 17) == 0) {
+
+
+ NDPI_LOG(NDPI_PROTOCOL_SSDP, ndpi_struct, NDPI_LOG_DEBUG, "found ssdp.\n");
+ ndpi_int_ssdp_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+#define SSDP_HTTP "HTTP/1.1 200 OK\r\n"
+ if(memcmp(packet->payload, SSDP_HTTP, strlen(SSDP_HTTP)) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SSDP, ndpi_struct, NDPI_LOG_DEBUG, "found ssdp.\n");
+ ndpi_int_ssdp_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_SSDP, ndpi_struct, NDPI_LOG_DEBUG, "ssdp excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SSDP);
+}
+
+#endif
diff --git a/src/lib/protocols/ssh.c b/src/lib/protocols/ssh.c
new file mode 100644
index 000000000..f659294a2
--- /dev/null
+++ b/src/lib/protocols/ssh.c
@@ -0,0 +1,68 @@
+/*
+ * ssh.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_SSH
+
+static void ndpi_int_ssh_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSH, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_ssh_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+
+ if (flow->l4.tcp.ssh_stage == 0) {
+ if (packet->payload_packet_len > 7 && packet->payload_packet_len < 100
+ && memcmp(packet->payload, "SSH-", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SSH, ndpi_struct, NDPI_LOG_DEBUG, "ssh stage 0 passed\n");
+ flow->l4.tcp.ssh_stage = 1 + packet->packet_direction;
+ return;
+ }
+ } else if (flow->l4.tcp.ssh_stage == (2 - packet->packet_direction)) {
+ if (packet->payload_packet_len > 7 && packet->payload_packet_len < 100
+ && memcmp(packet->payload, "SSH-", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SSH, ndpi_struct, NDPI_LOG_DEBUG, "found ssh\n");
+ ndpi_int_ssh_add_connection(ndpi_struct, flow);
+ return;
+
+ }
+
+
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_SSH, ndpi_struct, NDPI_LOG_DEBUG, "excluding ssh at stage %d\n", flow->l4.tcp.ssh_stage);
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SSH);
+}
+
+#endif
diff --git a/src/lib/protocols/ssl.c b/src/lib/protocols/ssl.c
new file mode 100644
index 000000000..c61c039c1
--- /dev/null
+++ b/src/lib/protocols/ssl.c
@@ -0,0 +1,637 @@
+/*
+ * ssl.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+// #define CERTIFICATE_DEBUG 1
+
+#ifdef NDPI_PROTOCOL_SSL
+
+#define NDPI_MAX_SSL_REQUEST_SIZE 10000
+
+/* Skype.c */
+extern u_int8_t is_skype_flow(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow);
+
+static void ndpi_int_ssl_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, u_int32_t protocol)
+{
+ if((protocol != NDPI_PROTOCOL_SSL)
+ && (protocol != NDPI_PROTOCOL_SSL_NO_CERT)) {
+ ndpi_int_add_connection(ndpi_struct, flow, protocol, NDPI_CORRELATED_PROTOCOL);
+ } else {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if((flow->protos.ssl.client_certificate[0] != '\0')
+ || (flow->protos.ssl.server_certificate[0] != '\0')
+ || (flow->host_server_name[0] != '\0'))
+ protocol = NDPI_PROTOCOL_SSL;
+ else
+ protocol = NDPI_PROTOCOL_SSL_NO_CERT;
+
+ if(packet->tcp != NULL) {
+ switch(protocol) {
+ case NDPI_PROTOCOL_SSL:
+ case NDPI_PROTOCOL_SSL_NO_CERT:
+ {
+ /*
+ In case of SSL there are probably sub-protocols
+ such as IMAPS that can be otherwise detected
+ */
+ u_int16_t sport = ntohs(packet->tcp->source);
+ u_int16_t dport = ntohs(packet->tcp->dest);
+
+ if((sport == 465) || (dport == 465)) protocol = NDPI_PROTOCOL_MAIL_SMTPS;
+ else if((sport == 993) || (dport == 993)) protocol = NDPI_PROTOCOL_MAIL_IMAPS;
+ else if((sport == 995) || (dport == 995)) protocol = NDPI_PROTOCOL_MAIL_POPS;
+ }
+ break;
+ }
+
+ if((protocol == NDPI_PROTOCOL_SSL_NO_CERT)
+ && is_skype_flow(ndpi_struct, flow)) {
+ protocol = NDPI_PROTOCOL_SKYPE;
+ }
+ }
+
+ ndpi_int_add_connection(ndpi_struct, flow, protocol, NDPI_REAL_PROTOCOL);
+ }
+}
+
+/* Can't call libc functions from kernel space, define some stub instead */
+
+#define ndpi_isalpha(ch) (((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z'))
+#define ndpi_isdigit(ch) ((ch) >= '0' && (ch) <= '9')
+#define ndpi_isspace(ch) (((ch) >= '\t' && (ch) <= '\r') || ((ch) == ' '))
+#define ndpi_isprint(ch) ((ch) >= 0x20 && (ch) <= 0x7e)
+#define ndpi_ispunct(ch) (((ch) >= '!' && (ch) <= '/') || \
+ ((ch) >= ':' && (ch) <= '@') || \
+ ((ch) >= '[' && (ch) <= '`') || \
+ ((ch) >= '{' && (ch) <= '~'))
+
+static void stripCertificateTrailer(char *buffer, int buffer_len) {
+ int i;
+
+ // printf("->%s<-\n", buffer);
+
+ for(i=0; i<buffer_len; i++) {
+ // printf("%c [%d]\n", buffer[i], buffer[i]);
+
+ if((buffer[i] != '.')
+ && (buffer[i] != '-')
+ && (buffer[i] != '*')
+ && (!ndpi_isalpha(buffer[i]))
+ && (!ndpi_isdigit(buffer[i]))) {
+ buffer[i] = '\0';
+ buffer_len = i;
+ break;
+ }
+ }
+
+ if(i > 0) i--;
+
+ while(i > 0) {
+ if(!ndpi_isalpha(buffer[i])) {
+ buffer[i] = '\0';
+ buffer_len = i;
+ i--;
+ } else
+ break;
+ }
+
+ for(i=buffer_len; i>0; i--) {
+ if(buffer[i] == '.') break;
+ else if(ndpi_isdigit(buffer[i]))
+ buffer[i] = '\0', buffer_len = i;
+ }
+}
+
+/* Code fixes courtesy of Alexsandro Brahm <alex@digistar.com.br> */
+int getSSLcertificate(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ char *buffer, int buffer_len) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ /*
+ Nothing matched so far: let's decode the certificate with some heuristics
+ Patches courtesy of Denys Fedoryshchenko <nuclearcat@nuclearcat.com>
+ */
+ if(packet->payload[0] == 0x16 /* Handshake */) {
+ u_int16_t total_len = (packet->payload[3] << 8) + packet->payload[4] + 5 /* SSL Header */;
+ u_int8_t handshake_protocol = packet->payload[5]; /* handshake protocol a bit misleading, it is message type according TLS specs */
+
+ memset(buffer, 0, buffer_len);
+
+ /* Truncate total len, search at least in incomplete packet */
+ if (total_len > packet->payload_packet_len)
+ total_len = packet->payload_packet_len;
+
+ /* At least "magic" 3 bytes, null for string end, otherwise no need to waste cpu cycles */
+ if(total_len > 4) {
+ int i;
+
+ if(handshake_protocol == 0x02 || handshake_protocol == 0xb /* Server Hello and Certificate message types are interesting for us */) {
+ u_int num_found = 0;
+
+ flow->l4.tcp.ssl_seen_server_cert = 1;
+
+ /* Check after handshake protocol header (5 bytes) and message header (4 bytes) */
+ for(i = 9; i < packet->payload_packet_len-3; i++) {
+ if(((packet->payload[i] == 0x04) && (packet->payload[i+1] == 0x03) && (packet->payload[i+2] == 0x0c))
+ || ((packet->payload[i] == 0x55) && (packet->payload[i+1] == 0x04) && (packet->payload[i+2] == 0x03))) {
+ u_int8_t server_len = packet->payload[i+3];
+
+ if(packet->payload[i] == 0x55) {
+ num_found++;
+
+ if(num_found != 2) continue;
+ }
+
+ if(server_len+i+3 < packet->payload_packet_len) {
+ char *server_name = (char*)&packet->payload[i+4];
+ u_int8_t begin = 0, len, j, num_dots;
+
+ while(begin < server_len) {
+ if(!ndpi_isprint(server_name[begin]))
+ begin++;
+ else
+ break;
+ }
+
+ // len = ndpi_min(server_len-begin, buffer_len-1);
+ len = buffer_len-1;
+ strncpy(buffer, &server_name[begin], len);
+ buffer[len] = '\0';
+
+ /* We now have to check if this looks like an IP address or host name */
+ for(j=0, num_dots = 0; j<len; j++) {
+ if(!ndpi_isprint((buffer[j]))) {
+ num_dots = 0; /* This is not what we look for */
+ break;
+ } else if(buffer[j] == '.') {
+ num_dots++;
+ if(num_dots >=2) break;
+ }
+ }
+
+ if(num_dots >= 2) {
+ stripCertificateTrailer(buffer, buffer_len);
+ snprintf(flow->protos.ssl.server_certificate,
+ sizeof(flow->protos.ssl.server_certificate), "%s", buffer);
+ return(1 /* Server Certificate */);
+ }
+ }
+ }
+ }
+ } else if(handshake_protocol == 0x01 /* Client Hello */) {
+ u_int offset, base_offset = 43;
+ u_int16_t session_id_len = packet->payload[base_offset];
+
+ if((session_id_len+base_offset+2) <= total_len) {
+ u_int16_t cypher_len = packet->payload[session_id_len+base_offset+2] + (packet->payload[session_id_len+base_offset+1] << 8);
+ offset = base_offset + session_id_len + cypher_len + 2;
+
+ flow->l4.tcp.ssl_seen_client_cert = 1;
+
+ if(offset < total_len) {
+ u_int16_t compression_len;
+ u_int16_t extensions_len;
+
+ compression_len = packet->payload[offset+1];
+ offset += compression_len + 3;
+
+ if(offset < total_len) {
+ extensions_len = packet->payload[offset];
+
+ if((extensions_len+offset) < total_len) {
+ u_int16_t extension_offset = 1; /* Move to the first extension */
+
+ while(extension_offset < extensions_len) {
+ u_int16_t extension_id, extension_len;
+
+ memcpy(&extension_id, &packet->payload[offset+extension_offset], 2);
+ extension_offset += 2;
+
+ memcpy(&extension_len, &packet->payload[offset+extension_offset], 2);
+ extension_offset += 2;
+
+ extension_id = ntohs(extension_id), extension_len = ntohs(extension_len);
+
+ if(extension_id == 0) {
+ u_int begin = 0,len;
+ char *server_name = (char*)&packet->payload[offset+extension_offset];
+
+ while(begin < extension_len) {
+ if((!ndpi_isprint(server_name[begin]))
+ || ndpi_ispunct(server_name[begin])
+ || ndpi_isspace(server_name[begin]))
+ begin++;
+ else
+ break;
+ }
+
+ len = (u_int)ndpi_min(extension_len-begin, buffer_len-1);
+ strncpy(buffer, &server_name[begin], len);
+ buffer[len] = '\0';
+ stripCertificateTrailer(buffer, buffer_len);
+
+ snprintf(flow->protos.ssl.client_certificate,
+ sizeof(flow->protos.ssl.client_certificate), "%s", buffer);
+
+ /* We're happy now */
+ return(2 /* Client Certificate */);
+ }
+
+ extension_offset += extension_len;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return(0); /* Not found */
+}
+
+int sslDetectProtocolFromCertificate(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(!packet->iph /* IPv4 */) return(-1);
+
+ if((packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN)
+ || (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL)) {
+ char certificate[64];
+ int rc;
+
+ certificate[0] = '\0';
+ rc = getSSLcertificate(ndpi_struct, flow, certificate, sizeof(certificate));
+ packet->ssl_certificate_num_checks++;
+
+ if(rc > 0) {
+ packet->ssl_certificate_detected++;
+#ifdef CERTIFICATE_DEBUG
+ printf("***** [SSL] %s\n", certificate);
+#endif
+
+ if(ndpi_match_string_subprotocol(ndpi_struct, flow, certificate, strlen(certificate)) != NDPI_PROTOCOL_UNKNOWN)
+ return(rc); /* Fix courtesy of Gianluca Costa <g.costa@xplico.org> */
+
+#ifdef NDPI_PROTOCOL_TOR
+ if(ndpi_is_ssl_tor(ndpi_struct, flow, certificate) != 0)
+ return(rc);
+#endif
+ }
+
+ if(((packet->ssl_certificate_num_checks >= 2)
+ && flow->l4.tcp.seen_syn
+ && flow->l4.tcp.seen_syn_ack
+ && flow->l4.tcp.seen_ack /* We have seen the 3-way handshake */)
+ || (flow->protos.ssl.server_certificate[0] != '\0')
+ || (flow->protos.ssl.client_certificate[0] != '\0')
+ )
+ ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL);
+ }
+
+ return(0);
+}
+
+static void ssl_mark_and_payload_search_for_other_protocols(struct
+ ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+#if defined(NDPI_PROTOCOL_MEEBO)|| defined(NDPI_PROTOCOL_TOR) || defined(NDPI_PROTOCOL_VPN_X) || defined(NDPI_PROTOCOL_UNENCRYPED_JABBER) || defined (NDPI_PROTOCOL_OSCAR) || defined (NDPI_PROTOCOL_ITUNES) || defined (NDPI_SERVICE_GMAIL)
+ struct ndpi_packet_struct *packet = &flow->packet;
+ // struct ndpi_id_struct *src=flow->src;
+ // struct ndpi_id_struct *dst=flow->dst;
+ u_int32_t a;
+ u_int32_t end;
+#if defined(NDPI_PROTOCOL_UNENCRYPED_JABBER)
+ if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_UNENCRYPED_JABBER) != 0)
+ goto check_for_ssl_payload;
+#endif
+#if defined(NDPI_PROTOCOL_OSCAR)
+ if (NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_struct->detection_bitmask, NDPI_PROTOCOL_OSCAR) != 0)
+ goto check_for_ssl_payload;
+#endif
+ goto no_check_for_ssl_payload;
+
+ check_for_ssl_payload:
+ end = packet->payload_packet_len - 20;
+ for (a = 5; a < end; a++) {
+#ifdef NDPI_PROTOCOL_UNENCRYPED_JABBER
+ if (packet->payload[a] == 't') {
+ if (memcmp(&packet->payload[a], "talk.google.com", 15) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_UNENCRYPED_JABBER, ndpi_struct, NDPI_LOG_DEBUG, "ssl jabber packet match\n");
+ if (NDPI_COMPARE_PROTOCOL_TO_BITMASK
+ (ndpi_struct->detection_bitmask, NDPI_PROTOCOL_UNENCRYPED_JABBER) != 0) {
+ ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_UNENCRYPED_JABBER);
+ return;
+ }
+ }
+ }
+#endif
+#ifdef NDPI_PROTOCOL_OSCAR
+ if (packet->payload[a] == 'A' || packet->payload[a] == 'k' || packet->payload[a] == 'c'
+ || packet->payload[a] == 'h') {
+ if (((a + 19) < packet->payload_packet_len && memcmp(&packet->payload[a], "America Online Inc.", 19) == 0)
+ // || (end - c > 3 memcmp (&packet->payload[c],"AOL", 3) == 0 )
+ // || (end - c > 7 && memcmp (&packet->payload[c], "AOL LLC", 7) == 0)
+ || ((a + 15) < packet->payload_packet_len && memcmp(&packet->payload[a], "kdc.uas.aol.com", 15) == 0)
+ || ((a + 14) < packet->payload_packet_len && memcmp(&packet->payload[a], "corehc@aol.net", 14) == 0)
+ || ((a + 41) < packet->payload_packet_len
+ && memcmp(&packet->payload[a], "http://crl.aol.com/AOLMSPKI/aolServerCert", 41) == 0)
+ || ((a + 28) < packet->payload_packet_len
+ && memcmp(&packet->payload[a], "http://ocsp.web.aol.com/ocsp", 28) == 0)
+ || ((a + 32) < packet->payload_packet_len
+ && memcmp(&packet->payload[a], "http://pki-info.aol.com/AOLMSPKI", 32) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR SERVER SSL DETECTED\n");
+
+ if (flow->dst != NULL && packet->payload_packet_len > 75) {
+ memcpy(flow->dst->oscar_ssl_session_id, &packet->payload[44], 32);
+ flow->dst->oscar_ssl_session_id[32] = '\0';
+ flow->dst->oscar_last_safe_access_time = packet->tick_timestamp;
+ }
+
+ ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OSCAR);
+ return;
+ }
+ }
+
+ if (packet->payload[a] == 'm' || packet->payload[a] == 's') {
+ if ((a + 21) < packet->payload_packet_len &&
+ (memcmp(&packet->payload[a], "my.screenname.aol.com", 21) == 0
+ || memcmp(&packet->payload[a], "sns-static.aolcdn.com", 21) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_OSCAR, ndpi_struct, NDPI_LOG_DEBUG, "OSCAR SERVER SSL DETECTED\n");
+ ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_OSCAR);
+ return;
+ }
+ }
+#endif
+ }
+
+ no_check_for_ssl_payload:
+#endif
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "found ssl connection.\n");
+ sslDetectProtocolFromCertificate(ndpi_struct, flow);
+
+ if(!packet->ssl_certificate_detected
+ && (!(flow->l4.tcp.ssl_seen_client_cert && flow->l4.tcp.ssl_seen_server_cert))) {
+ /* SSL without certificate (Skype, Ultrasurf?) */
+ ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL_NO_CERT);
+ } else
+ ndpi_int_ssl_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SSL);
+ }
+}
+
+
+static u_int8_t ndpi_search_sslv3_direction1(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+ //
+ // struct ndpi_id_struct *src=flow->src;
+ // struct ndpi_id_struct *dst=flow->dst;
+
+
+ if ((packet->payload_packet_len >= 5)
+ && (packet->payload[0] == 0x16)
+ && (packet->payload[1] == 0x03)
+ && ((packet->payload[2] == 0x00)
+ || (packet->payload[2] == 0x01)
+ || (packet->payload[2] == 0x02)
+ || (packet->payload[2] == 0x03)
+ )) {
+ u_int32_t temp;
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "search sslv3\n");
+ // SSLv3 Record
+ if (packet->payload_packet_len >= 1300) {
+ return 1;
+ }
+ temp = ntohs(get_u_int16_t(packet->payload, 3)) + 5;
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp);
+ if (packet->payload_packet_len == temp
+ || (temp < packet->payload_packet_len && packet->payload_packet_len > 500)) {
+ return 1;
+ }
+
+ if (packet->payload_packet_len < temp && temp < 5000 && packet->payload_packet_len > 9) {
+ /* the server hello may be split into small packets */
+ u_int32_t cert_start;
+
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG,
+ "maybe SSLv3 server hello split into smaller packets\n");
+
+ /* lets hope at least the server hello and the start of the certificate block are in the first packet */
+ cert_start = ntohs(get_u_int16_t(packet->payload, 7)) + 5 + 4;
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "suspected start of certificate: %u\n",
+ cert_start);
+
+ if (cert_start < packet->payload_packet_len && packet->payload[cert_start] == 0x0b) {
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG,
+ "found 0x0b at suspected start of certificate block\n");
+ return 2;
+ }
+ }
+
+ if ((packet->payload_packet_len > temp && packet->payload_packet_len > 100) && packet->payload_packet_len > 9) {
+ /* the server hello may be split into small packets and the certificate has its own SSL Record
+ * so temp contains only the length for the first ServerHello block */
+ u_int32_t cert_start;
+
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG,
+ "maybe SSLv3 server hello split into smaller packets but with seperate record for the certificate\n");
+
+ /* lets hope at least the server hello record and the start of the certificate record are in the first packet */
+ cert_start = ntohs(get_u_int16_t(packet->payload, 7)) + 5 + 5 + 4;
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "suspected start of certificate: %u\n",
+ cert_start);
+
+ if (cert_start < packet->payload_packet_len && packet->payload[cert_start] == 0x0b) {
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG,
+ "found 0x0b at suspected start of certificate block\n");
+ return 2;
+ }
+ }
+
+
+ if (packet->payload_packet_len >= temp + 5 && (packet->payload[temp] == 0x14 || packet->payload[temp] == 0x16)
+ && packet->payload[temp + 1] == 0x03) {
+ u_int32_t temp2 = ntohs(get_u_int16_t(packet->payload, temp + 3)) + 5;
+ if (temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) {
+ return 1;
+ }
+ temp += temp2;
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp);
+ if (packet->payload_packet_len == temp) {
+ return 1;
+ }
+ if (packet->payload_packet_len >= temp + 5 &&
+ packet->payload[temp] == 0x16 && packet->payload[temp + 1] == 0x03) {
+ temp2 = ntohs(get_u_int16_t(packet->payload, temp + 3)) + 5;
+ if (temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) {
+ return 1;
+ }
+ temp += temp2;
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp);
+ if (packet->payload_packet_len == temp) {
+ return 1;
+ }
+ if (packet->payload_packet_len >= temp + 5 &&
+ packet->payload[temp] == 0x16 && packet->payload[temp + 1] == 0x03) {
+ temp2 = ntohs(get_u_int16_t(packet->payload, temp + 3)) + 5;
+ if (temp + temp2 > NDPI_MAX_SSL_REQUEST_SIZE) {
+ return 1;
+ }
+ temp += temp2;
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "temp = %u.\n", temp);
+ if (temp == packet->payload_packet_len) {
+ return 1;
+ }
+ }
+
+ }
+
+
+ }
+
+ }
+ return 0;
+
+}
+
+void ndpi_search_ssl_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=flow->src;
+ // struct ndpi_id_struct *dst=flow->dst;
+
+ u_int8_t ret;
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) {
+ if (flow->l4.tcp.ssl_stage == 3 && packet->payload_packet_len > 20 && flow->packet_counter < 5) {
+ /* this should only happen, when we detected SSL with a packet that had parts of the certificate in subsequent packets
+ * so go on checking for certificate patterns for a couple more packets
+ */
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG,
+ "ssl flow but check another packet for patterns\n");
+ ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow);
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) {
+ /* still ssl so check another packet */
+ return;
+ } else {
+ /* protocol has changed so we are done */
+ return;
+ }
+ }
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "search ssl\n");
+
+ {
+ /* Check if this is whatsapp first (this proto runs over port 443) */
+ if((packet->payload_packet_len > 5)
+ && ((packet->payload[0] == 'W')
+ && (packet->payload[1] == 'A')
+ && (packet->payload[4] == 0)
+ && (packet->payload[2] <= 9)
+ && (packet->payload[3] <= 9))) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_SERVICE_WHATSAPP, NDPI_REAL_PROTOCOL);
+ return;
+ } else {
+ /* No whatsapp, let's try SSL */
+ if(sslDetectProtocolFromCertificate(ndpi_struct, flow) > 0)
+ return;
+ }
+ }
+
+ if (packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "first ssl packet\n");
+ // SSLv2 Record
+ if (packet->payload[2] == 0x01 && packet->payload[3] == 0x03
+ && (packet->payload[4] == 0x00 || packet->payload[4] == 0x01 || packet->payload[4] == 0x02)
+ && (packet->payload_packet_len - packet->payload[1] == 2)) {
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv2 len match\n");
+ flow->l4.tcp.ssl_stage = 1 + packet->packet_direction;
+ return;
+ }
+
+ if (packet->payload[0] == 0x16 && packet->payload[1] == 0x03
+ && (packet->payload[2] == 0x00 || packet->payload[2] == 0x01 || packet->payload[2] == 0x02)
+ && (packet->payload_packet_len - ntohs(get_u_int16_t(packet->payload, 3)) == 5)) {
+ // SSLv3 Record
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv3 len match\n");
+ flow->l4.tcp.ssl_stage = 1 + packet->packet_direction;
+ return;
+ }
+ }
+
+ if (packet->payload_packet_len > 40 &&
+ flow->l4.tcp.ssl_stage == 1 + packet->packet_direction
+ && flow->packet_direction_counter[packet->packet_direction] < 5) {
+ return;
+ }
+
+ if (packet->payload_packet_len > 40 && flow->l4.tcp.ssl_stage == 2 - packet->packet_direction) {
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "second ssl packet\n");
+ // SSLv2 Record
+ if (packet->payload[2] == 0x01 && packet->payload[3] == 0x03
+ && (packet->payload[4] == 0x00 || packet->payload[4] == 0x01 || packet->payload[4] == 0x02)
+ && (packet->payload_packet_len - 2) >= packet->payload[1]) {
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv2 server len match\n");
+ ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow);
+ return;
+ }
+
+ ret = ndpi_search_sslv3_direction1(ndpi_struct, flow);
+ if (ret == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "sslv3 server len match\n");
+ ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow);
+ return;
+ } else if (ret == 2) {
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG,
+ "sslv3 server len match with split packet -> check some more packets for SSL patterns\n");
+ ssl_mark_and_payload_search_for_other_protocols(ndpi_struct, flow);
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL) {
+ flow->l4.tcp.ssl_stage = 3;
+ }
+ return;
+ }
+
+ if (packet->payload_packet_len > 40 && flow->packet_direction_counter[packet->packet_direction] < 5) {
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "need next packet\n");
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_SSL, ndpi_struct, NDPI_LOG_DEBUG, "exclude ssl\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SSL);
+ return;
+}
+#endif
diff --git a/src/lib/protocols/stealthnet.c b/src/lib/protocols/stealthnet.c
new file mode 100644
index 000000000..e8f1778e6
--- /dev/null
+++ b/src/lib/protocols/stealthnet.c
@@ -0,0 +1,58 @@
+/*
+ * stealthnet.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_STEALTHNET
+
+
+static void ndpi_int_stealthnet_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_STEALTHNET, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_stealthnet(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+// struct ndpi_id_struct *src = flow->src;
+// struct ndpi_id_struct *dst = flow->dst;
+
+
+ if (packet->payload_packet_len > 40
+ && memcmp(packet->payload, "LARS REGENSBURGER'S FILE SHARING PROTOCOL", 41) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_STEALTHNET, ndpi_struct, NDPI_LOG_DEBUG, "found stealthnet\n");
+ ndpi_int_stealthnet_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_STEALTHNET, ndpi_struct, NDPI_LOG_DEBUG, "exclude stealthnet.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_STEALTHNET);
+
+}
+#endif
diff --git a/src/lib/protocols/steam.c b/src/lib/protocols/steam.c
new file mode 100644
index 000000000..7911df85a
--- /dev/null
+++ b/src/lib/protocols/steam.c
@@ -0,0 +1,286 @@
+/*
+ * steam.c
+ *
+ * Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk>
+ *
+ * The signature is mostly based on the Libprotoident library
+ * except the detection of HTTP Steam flows.
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_STEAM
+static void ndpi_int_steam_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_STEAM, NDPI_REAL_PROTOCOL);
+}
+
+static void ndpi_check_steam_http(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if (packet->user_agent_line.ptr != NULL
+ && packet->user_agent_line.len >= 23
+ && memcmp(packet->user_agent_line.ptr, "Valve/Steam HTTP Client", 23) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Found STEAM.\n");
+ ndpi_int_steam_add_connection(ndpi_struct, flow);
+ }
+}
+
+static void ndpi_check_steam_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ if (flow->steam_stage == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "STEAM stage 0: \n");
+
+ if (((payload_len == 1) || (payload_len == 4) || (payload_len == 5)) && match_first_bytes(packet->payload, "\x01\x00\x00\x00")) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Possible STEAM request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->steam_stage = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
+ return;
+ }
+
+ if (((payload_len == 1) || (payload_len == 4) || (payload_len == 5)) && (packet->payload[0] == 0x00) && (packet->payload[1] == 0x00) && (packet->payload[2] == 0x00)) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Possible STEAM request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->steam_stage = packet->packet_direction + 3; // packet_direction 0: stage 3, packet_direction 1: stage 4
+ return;
+ }
+ } else if ((flow->steam_stage == 1) || (flow->steam_stage == 2)) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "STEAM stage %u: \n", flow->steam_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->steam_stage - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if (((payload_len == 1) || (payload_len == 4) || (payload_len == 5)) && (packet->payload[0] == 0x00) && (packet->payload[1] == 0x00) && (packet->payload[2] == 0x00)) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Found STEAM.\n");
+ ndpi_int_steam_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to STEAM, resetting the stage to 0...\n");
+ flow->steam_stage = 0;
+ }
+ } else if ((flow->steam_stage == 3) || (flow->steam_stage == 4)) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "STEAM stage %u: \n", flow->steam_stage);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->steam_stage - packet->packet_direction) == 3) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if (((payload_len == 1) || (payload_len == 4) || (payload_len == 5)) && match_first_bytes(packet->payload, "\x01\x00\x00\x00")) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Found STEAM.\n");
+ ndpi_int_steam_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to STEAM, resetting the stage to 0...\n");
+ flow->steam_stage = 0;
+ }
+ }
+}
+
+static void ndpi_check_steam_udp1(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "VS01")) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Found STEAM.\n");
+ ndpi_int_steam_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->steam_stage1 == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "STEAM stage 0: \n");
+
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "\x31\xff\x30\x2e")) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Possible STEAM request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->steam_stage1 = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
+ return;
+ }
+
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "\xff\xff\xff\xff")) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Possible STEAM request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->steam_stage1 = packet->packet_direction + 3; // packet_direction 0: stage 3, packet_direction 1: stage 4
+ return;
+ }
+
+ } else if ((flow->steam_stage1 == 1) || (flow->steam_stage1 == 2)) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "STEAM stage %u: \n", flow->steam_stage1);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->steam_stage1 - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "\xff\xff\xff\xff")) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Found STEAM.\n");
+ ndpi_int_steam_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to STEAM, resetting the stage to 0...\n");
+ flow->steam_stage1 = 0;
+ }
+
+ } else if ((flow->steam_stage1 == 3) || (flow->steam_stage1 == 4)) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "STEAM stage %u: \n", flow->steam_stage1);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->steam_stage1 - packet->packet_direction) == 3) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len > 0) && match_first_bytes(packet->payload, "\x31\xff\x30\x2e")) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Found STEAM.\n");
+ ndpi_int_steam_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to STEAM, resetting the stage to 0...\n");
+ flow->steam_stage1 = 0;
+ }
+
+ }
+}
+
+static void ndpi_check_steam_udp2(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->steam_stage2 == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "STEAM stage 0: \n");
+
+ if ((payload_len == 25) && match_first_bytes(packet->payload, "\xff\xff\xff\xff")) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Possible STEAM request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->steam_stage2 = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
+ }
+
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "STEAM stage %u: \n", flow->steam_stage2);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->steam_stage2 - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len == 0) || match_first_bytes(packet->payload, "\xff\xff\xff\xff")) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Found STEAM.\n");
+ ndpi_int_steam_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to STEAM, resetting the stage to 0...\n");
+ flow->steam_stage2 = 0;
+ }
+
+ }
+}
+
+static void ndpi_check_steam_udp3(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+
+ /* Check if we so far detected the protocol in the request or not. */
+ if (flow->steam_stage3 == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "STEAM stage 0: \n");
+
+ if ((payload_len == 4) && (packet->payload[0] == 0x39) && (packet->payload[1] == 0x18) && (packet->payload[2] == 0x00) && (packet->payload[3] == 0x00)) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Possible STEAM request detected, we will look further for the response...\n");
+
+ /* Encode the direction of the packet in the stage, so we will know when we need to look for the response packet. */
+ flow->steam_stage3 = packet->packet_direction + 1; // packet_direction 0: stage 1, packet_direction 1: stage 2
+ }
+
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "STEAM stage %u: \n", flow->steam_stage3);
+
+ /* At first check, if this is for sure a response packet (in another direction. If not, do nothing now and return. */
+ if ((flow->steam_stage3 - packet->packet_direction) == 1) {
+ return;
+ }
+
+ /* This is a packet in another direction. Check if we find the proper response. */
+ if ((payload_len == 0) || ((payload_len == 8) && (packet->payload[0] == 0x3a) && (packet->payload[1] == 0x18) && (packet->payload[2] == 0x00) && (packet->payload[3] == 0x00))) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Found STEAM.\n");
+ ndpi_int_steam_add_connection(ndpi_struct, flow);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "The reply did not seem to belong to STEAM, resetting the stage to 0...\n");
+ flow->steam_stage3 = 0;
+ }
+
+ }
+}
+
+void ndpi_search_steam(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ /* Break after 20 packets. */
+ if (flow->packet_counter > 20) {
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "Exclude STEAM.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_STEAM);
+ return;
+ }
+
+ /* skip marked or retransmitted packets */
+ if (packet->tcp_retransmission != 0) {
+ return;
+ }
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM) {
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_STEAM, ndpi_struct, NDPI_LOG_DEBUG, "STEAM detection...\n");
+ ndpi_check_steam_http(ndpi_struct, flow);
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM) {
+ return;
+ }
+
+ ndpi_check_steam_tcp(ndpi_struct, flow);
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM) {
+ return;
+ }
+
+ ndpi_check_steam_udp1(ndpi_struct, flow);
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM) {
+ return;
+ }
+
+ ndpi_check_steam_udp2(ndpi_struct, flow);
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM) {
+ return;
+ }
+
+ ndpi_check_steam_udp3(ndpi_struct, flow);
+}
+
+#endif
diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c
new file mode 100644
index 000000000..09ec4a050
--- /dev/null
+++ b/src/lib/protocols/stun.c
@@ -0,0 +1,188 @@
+/*
+ * stun.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_STUN
+
+
+static void ndpi_int_stun_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_STUN, NDPI_REAL_PROTOCOL);
+}
+
+
+
+typedef enum {
+ NDPI_IS_STUN,
+ NDPI_IS_NOT_STUN
+} ndpi_int_stun_t;
+
+static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *ndpi_struct,
+ const u_int8_t * payload, const u_int16_t payload_length)
+{
+ u_int16_t a;
+
+
+ if((payload_length > 13)
+ && (strncmp((const char*)payload, (const char*)"RSP/", 4) == 0)
+ && (strncmp((const char*)&payload[7], (const char*)" STUN_", 6) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "Found stun.\n");
+ return NDPI_IS_STUN;
+ }
+
+ /*
+ * token list of message types and attribute types from
+ * http://wwwbs1.informatik.htw-dresden.de/svortrag/i02/Schoene/stun/stun.html
+ * the same list you can find in
+ * https://summersoft.fay.ar.us/repos/ethereal/branches/redhat-9/ethereal-0.10.3-1/ethereal-0.10.3/packet-stun.c
+ * token further message types and attributes from
+ * http://www.freeswitch.org/docs/group__stun1.html
+ * added further attributes observed
+ * message types: 0x0001, 0x0101, 0x0111, 0x0002, 0x0102, 0x0112, 0x0003, 0x0103, 0x0004, 0x0104, 0x0114, 0x0115
+ * attribute types: 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
+ * 0x000a, 0x000b, 0c000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0020,
+ * 0x0022, 0x0024, 0x8001, 0x8006, 0x8008, 0x8015, 0x8020, 0x8028, 0x802a, 0x8029, 0x8050, 0x8054, 0x8055
+ *
+ * 0x8003, 0x8004 used by facetime
+ */
+
+ if (payload_length >= 20 && ntohs(get_u_int16_t(payload, 2)) + 20 == payload_length &&
+ ((payload[0] == 0x00 && (payload[1] >= 0x01 && payload[1] <= 0x04)) ||
+ (payload[0] == 0x01 &&
+ ((payload[1] >= 0x01 && payload[1] <= 0x04) || (payload[1] >= 0x11 && payload[1] <= 0x15))))) {
+ u_int8_t mod;
+ u_int8_t old = 1;
+ u_int8_t padding = 0;
+ NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "len and type match.\n");
+
+ if (payload_length == 20) {
+ NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "found stun.\n");
+ return NDPI_IS_STUN;
+ }
+
+ a = 20;
+
+ while (a < payload_length) {
+
+ if (old && payload_length >= a + 4
+ &&
+ ((payload[a] == 0x00
+ && ((payload[a + 1] >= 0x01 && payload[a + 1] <= 0x16) || payload[a + 1] == 0x19
+ || payload[a + 1] == 0x20 || payload[a + 1] == 0x22 || payload[a + 1] == 0x24
+ || payload[a + 1] == 0x25))
+ || (payload[a] == 0x80
+ && (payload[a + 1] == 0x01 || payload[a + 1] == 0x03 || payload[a + 1] == 0x04
+ || payload[a + 1] == 0x06 || payload[a + 1] == 0x08 || payload[a + 1] == 0x15
+ || payload[a + 1] == 0x20 || payload[a + 1] == 0x22 || payload[a + 1] == 0x28
+ || payload[a + 1] == 0x2a || payload[a + 1] == 0x29 || payload[a + 1] == 0x50
+ || payload[a + 1] == 0x54 || payload[a + 1] == 0x55)))) {
+
+ NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "attribute match.\n");
+
+ a += ((payload[a + 2] << 8) + payload[a + 3] + 4);
+ mod = a % 4;
+ if (mod) {
+ padding = 4 - mod;
+ }
+ if (a == payload_length || (padding && (a + padding) == payload_length)) {
+ NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "found stun.\n");
+ return NDPI_IS_STUN;
+ }
+
+ } else if (payload_length >= a + padding + 4
+ &&
+ ((payload[a + padding] == 0x00
+ && ((payload[a + 1 + padding] >= 0x01 && payload[a + 1 + padding] <= 0x16)
+ || payload[a + 1 + padding] == 0x19 || payload[a + 1 + padding] == 0x20
+ || payload[a + 1 + padding] == 0x22 || payload[a + 1 + padding] == 0x24
+ || payload[a + 1 + padding] == 0x25))
+ || (payload[a + padding] == 0x80
+ && (payload[a + 1 + padding] == 0x01 || payload[a + 1 + padding] == 0x03
+ || payload[a + 1 + padding] == 0x04 || payload[a + 1 + padding] == 0x06
+ || payload[a + 1 + padding] == 0x08 || payload[a + 1 + padding] == 0x15
+ || payload[a + 1 + padding] == 0x20 || payload[a + 1 + padding] == 0x22
+ || payload[a + 1 + padding] == 0x28 || payload[a + 1 + padding] == 0x2a
+ || payload[a + 1 + padding] == 0x29 || payload[a + 1 + padding] == 0x50
+ || payload[a + 1 + padding] == 0x54 || payload[a + 1 + padding] == 0x55)))) {
+
+ NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "New STUN - attribute match.\n");
+
+ old = 0;
+ a += ((payload[a + 2 + padding] << 8) + payload[a + 3 + padding] + 4);
+ padding = 0;
+ mod = a % 4;
+ if (mod) {
+ a += 4 - mod;
+ }
+ if (a == payload_length) {
+ NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "found stun.\n");
+ return NDPI_IS_STUN;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ return NDPI_IS_NOT_STUN;
+}
+
+void ndpi_search_stun(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+ NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "search stun.\n");
+
+
+ if (packet->tcp) {
+
+ /* STUN may be encapsulated in TCP packets */
+
+ if (packet->payload_packet_len >= 2 + 20 &&
+ ntohs(get_u_int16_t(packet->payload, 0)) + 2 == packet->payload_packet_len) {
+
+ /* TODO there could be several STUN packets in a single TCP packet so maybe the detection could be
+ * improved by checking only the STUN packet of given length */
+
+ if (ndpi_int_check_stun(ndpi_struct, packet->payload + 2, packet->payload_packet_len - 2) ==
+ NDPI_IS_STUN) {
+ NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "found TCP stun.\n");
+ ndpi_int_stun_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+ if (ndpi_int_check_stun(ndpi_struct, packet->payload, packet->payload_packet_len) == NDPI_IS_STUN) {
+ NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "found UDP stun.\n");
+ ndpi_int_stun_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "exclude stun.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_STUN);
+}
+
+#endif
diff --git a/src/lib/protocols/syslog.c b/src/lib/protocols/syslog.c
new file mode 100644
index 000000000..b4732bfca
--- /dev/null
+++ b/src/lib/protocols/syslog.c
@@ -0,0 +1,130 @@
+/*
+ * syslog.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_SYSLOG
+
+static void ndpi_int_syslog_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_SYSLOG, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_syslog(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ u_int8_t i;
+
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG, "search syslog\n");
+
+ if (packet->payload_packet_len > 20 && packet->payload_packet_len <= 1024 && packet->payload[0] == '<') {
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG, "checked len>20 and <1024 and first symbol=<.\n");
+ i = 1;
+
+ for (;;) {
+ if (packet->payload[i] < '0' || packet->payload[i] > '9' || i++ > 3) {
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG,
+ "read symbols while the symbol is a number.\n");
+ break;
+ }
+ }
+
+ if (packet->payload[i++] != '>') {
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG, "there is no > following the number.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SYSLOG);
+ return;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG, "a > following the number.\n");
+ }
+
+ if (packet->payload[i] == 0x20) {
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG, "a blank following the >: increment i.\n");
+ i++;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG, "no blank following the >: do nothing.\n");
+ }
+
+ /* check for "last message repeated" */
+ if (i + sizeof("last message") - 1 <= packet->payload_packet_len &&
+ memcmp(packet->payload + i, "last message", sizeof("last message") - 1) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG, "found syslog by 'last message' string.\n");
+
+ ndpi_int_syslog_add_connection(ndpi_struct, flow);
+
+ return;
+ } else if (i + sizeof("snort: ") - 1 <= packet->payload_packet_len &&
+ memcmp(packet->payload + i, "snort: ", sizeof("snort: ") - 1) == 0) {
+
+ /* snort events */
+
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG, "found syslog by 'snort: ' string.\n");
+
+ ndpi_int_syslog_add_connection(ndpi_struct, flow);
+
+ return;
+ }
+
+ if (memcmp(&packet->payload[i], "Jan", 3) != 0
+ && memcmp(&packet->payload[i], "Feb", 3) != 0
+ && memcmp(&packet->payload[i], "Mar", 3) != 0
+ && memcmp(&packet->payload[i], "Apr", 3) != 0
+ && memcmp(&packet->payload[i], "May", 3) != 0
+ && memcmp(&packet->payload[i], "Jun", 3) != 0
+ && memcmp(&packet->payload[i], "Jul", 3) != 0
+ && memcmp(&packet->payload[i], "Aug", 3) != 0
+ && memcmp(&packet->payload[i], "Sep", 3) != 0
+ && memcmp(&packet->payload[i], "Oct", 3) != 0
+ && memcmp(&packet->payload[i], "Nov", 3) != 0 && memcmp(&packet->payload[i], "Dec", 3) != 0) {
+
+
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG,
+ "no month-shortname following: syslog excluded.\n");
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SYSLOG);
+
+ return;
+
+ } else {
+
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG,
+ "a month-shortname following: syslog detected.\n");
+
+ ndpi_int_syslog_add_connection(ndpi_struct, flow);
+
+ return;
+ }
+ }
+ NDPI_LOG(NDPI_PROTOCOL_SYSLOG, ndpi_struct, NDPI_LOG_DEBUG, "no syslog detected.\n");
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SYSLOG);
+}
+
+#endif
diff --git a/src/lib/protocols/tcp_udp.c b/src/lib/protocols/tcp_udp.c
new file mode 100644
index 000000000..da33e6e0e
--- /dev/null
+++ b/src/lib/protocols/tcp_udp.c
@@ -0,0 +1,78 @@
+/*
+ * tcp_or_udp.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+/* ndpi_main.c */
+extern u_int8_t ndpi_is_tor_flow(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
+
+u_int ndpi_search_tcp_or_udp_raw(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int8_t protocol,
+ u_int32_t saddr, u_int32_t daddr, /* host endianess */
+ u_int16_t sport, u_int16_t dport) /* host endianess */
+{
+ u_int16_t rc;
+
+ if(protocol == IPPROTO_UDP) {
+ if((sport == dport) && (sport == 17500)) {
+ return(NDPI_PROTOCOL_DROPBOX);
+ }
+ }
+
+ if((rc = ndpi_host_ptree_match(ndpi_struct, saddr)) != NDPI_PROTOCOL_UNKNOWN) return(rc);
+
+ return(ndpi_host_ptree_match(ndpi_struct, daddr));
+}
+
+void ndpi_search_tcp_or_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ u_int16_t sport, dport;
+ u_int proto;
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ if(ndpi_is_tor_flow(ndpi_struct, flow)) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TOR, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ if(packet->udp) sport = ntohs(packet->udp->source), dport = ntohs(packet->udp->dest);
+ else if(packet->tcp) sport = ntohs(packet->tcp->source), dport = ntohs(packet->tcp->dest);
+ else sport = dport = 0;
+
+ if(packet->iph /* IPv4 Only: we need to support packet->iphv6 at some point */) {
+ proto = ndpi_search_tcp_or_udp_raw(ndpi_struct,
+ flow->packet.iph ? flow->packet.iph->protocol :
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ flow->packet.iphv6->nexthdr,
+#else
+ 0,
+#endif
+ ntohl(packet->iph->saddr),
+ ntohl(packet->iph->daddr),
+ sport, dport);
+
+ if(proto != NDPI_PROTOCOL_UNKNOWN)
+ ndpi_int_add_connection(ndpi_struct, flow, proto, NDPI_REAL_PROTOCOL);
+ }
+}
+
+
+
diff --git a/src/lib/protocols/tds.c b/src/lib/protocols/tds.c
new file mode 100644
index 000000000..af97316cd
--- /dev/null
+++ b/src/lib/protocols/tds.c
@@ -0,0 +1,91 @@
+/*
+ * tds.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_TDS
+
+static void ndpi_int_tds_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TDS, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_tds_tcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len > 8
+ && packet->payload_packet_len < 512
+ && packet->payload[1] < 0x02
+ && ntohs(get_u_int16_t(packet->payload, 2)) == packet->payload_packet_len && get_u_int16_t(packet->payload, 4) == 0x0000) {
+
+ if (flow->l4.tcp.tds_stage == 0) {
+ if (packet->payload[0] != 0x02 && packet->payload[0] != 0x07 && packet->payload[0] != 0x12) {
+ goto exclude_tds;
+ } else {
+ flow->l4.tcp.tds_stage = 1 + packet->packet_direction;
+ flow->l4.tcp.tds_login_version = packet->payload[0];
+ return;
+ }
+ } else if (flow->l4.tcp.tds_stage == 2 - packet->packet_direction) {
+ switch (flow->l4.tcp.tds_login_version) {
+ case 0x12:
+ if (packet->payload[0] == 0x04) {
+ flow->l4.tcp.tds_stage = 3 + packet->packet_direction;
+ return;
+ } else {
+ goto exclude_tds;
+ }
+ //TODO: add more cases for other versions
+ default:
+ goto exclude_tds;
+ }
+ } else if (flow->l4.tcp.tds_stage == 4 - packet->packet_direction) {
+ switch (flow->l4.tcp.tds_login_version) {
+ case 0x12:
+ if (packet->payload[0] == 0x12) {
+ NDPI_LOG(NDPI_PROTOCOL_TDS, ndpi_struct, NDPI_LOG_DEBUG, "TDS detected\n");
+ ndpi_int_tds_add_connection(ndpi_struct, flow);
+ return;
+ } else {
+ goto exclude_tds;
+ }
+ //TODO: add more cases for other versions
+ default:
+ goto exclude_tds;
+ }
+ }
+ }
+
+ exclude_tds:
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TDS);
+}
+
+#endif
diff --git a/src/lib/protocols/teamspeak.c b/src/lib/protocols/teamspeak.c
new file mode 100644
index 000000000..89ec12040
--- /dev/null
+++ b/src/lib/protocols/teamspeak.c
@@ -0,0 +1,65 @@
+/*
+ * viber.c
+ *
+ * Copyright (C) 2013 Remy Mudingay <mudingay@ill.fr>
+ *
+ * This module is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This module 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License.
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ndpi_api.h"
+
+
+#ifdef NDPI_PROTOCOL_TEAMSPEAK
+
+static void ndpi_int_teamspeak_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TEAMSPEAK, NDPI_REAL_PROTOCOL);
+}
+ u_int16_t tdport = 0, tsport = 0;
+ u_int16_t udport = 0, usport = 0;
+
+
+void ndpi_search_teamspeak(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+if (packet->udp != NULL) {
+ usport = ntohs(packet->udp->source), udport = ntohs(packet->udp->dest);
+ /* http://www.imfirewall.com/en/protocols/teamSpeak.htm */
+ if (((usport == 9987 || udport == 9987) || (usport == 8767 || udport == 8767)) && packet->payload_packet_len >= 20) {
+ NDPI_LOG(NDPI_PROTOCOL_TEAMSPEAK, ndpi_struct, NDPI_LOG_DEBUG, "found TEAMSPEAK udp.\n");
+ ndpi_int_teamspeak_add_connection(ndpi_struct, flow);
+ }
+}
+else if (packet->tcp != NULL) {
+ tsport = ntohs(packet->tcp->source), tdport = ntohs(packet->tcp->dest);
+ /* https://github.com/Youx/soliloque-server/wiki/Connection-packet */
+ if(packet->payload_packet_len >= 20) {
+ if (((memcmp(packet->payload, "\xf4\xbe\x03\x00", 4) == 0)) ||
+ ((memcmp(packet->payload, "\xf4\xbe\x02\x00", 4) == 0)) ||
+ ((memcmp(packet->payload, "\xf4\xbe\x01\x00", 4) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_TEAMSPEAK, ndpi_struct, NDPI_LOG_DEBUG, "found TEAMSPEAK tcp.\n");
+ ndpi_int_teamspeak_add_connection(ndpi_struct, flow);
+ } /* http://www.imfirewall.com/en/protocols/teamSpeak.htm */
+ } else if ((tsport == 14534 || tdport == 14534) || (tsport == 51234 || tdport == 51234)) {
+ NDPI_LOG(NDPI_PROTOCOL_TEAMSPEAK, ndpi_struct, NDPI_LOG_DEBUG, "found TEAMSPEAK.\n");
+ ndpi_int_teamspeak_add_connection(ndpi_struct, flow);
+ }
+ }
+ NDPI_LOG(NDPI_PROTOCOL_TEAMSPEAK, ndpi_struct, NDPI_LOG_DEBUG, "TEAMSPEAK excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TEAMSPEAK);
+ return;
+}
+#endif
diff --git a/src/lib/protocols/teamviewer.c b/src/lib/protocols/teamviewer.c
new file mode 100644
index 000000000..0fe0810c9
--- /dev/null
+++ b/src/lib/protocols/teamviewer.c
@@ -0,0 +1,100 @@
+/*
+ * teamviewer.c
+ *
+ * Copyright (C) 2012 by Gianluca Costa xplico.org
+ * Copyright (C) 2012-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_TEAMVIEWER
+
+static void ndpi_int_teamview_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TEAMVIEWER, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_TEAMVIEWER, ndpi_struct, NDPI_LOG_TRACE, "TEAMWIEWER Found.\n");
+}
+
+
+void ndpi_search_teamview(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ NDPI_LOG(NDPI_PROTOCOL_TEAMVIEWER, ndpi_struct, NDPI_LOG_TRACE, "TEAMWIEWER detection...\n");
+ /*
+ TeamViewer
+ 178.77.120.0/25
+
+ http://myip.ms/view/ip_owners/144885/Teamviewer_Gmbh.html
+ */
+ if(flow->packet.iph) {
+ u_int32_t src = ntohl(flow->packet.iph->saddr);
+ u_int32_t dst = ntohl(flow->packet.iph->daddr);
+
+ /* 95.211.37.195 - 95.211.37.203 */
+ if(((src >= 1607673283) && (src <= 1607673291))
+ || ((dst >= 1607673283) && (dst <= 1607673291))
+ || ((src & 0xFFFFFF80 /* 255.255.255.128 */) == 0xB24D7800 /* 178.77.120.0 */)
+ || ((dst & 0xFFFFFF80 /* 255.255.255.128 */) == 0xB24D7800 /* 178.77.120.0 */)
+ ) {
+ ndpi_int_teamview_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+ if(packet->payload_packet_len == 0) return;
+
+ if (packet->udp != NULL) {
+ if (packet->payload_packet_len > 13) {
+ if (packet->payload[0] == 0x00 && packet->payload[11] == 0x17 && packet->payload[12] == 0x24) { /* byte 0 is a counter/seq number, and at the start is 0 */
+ flow->l4.udp.teamviewer_stage++;
+ if (flow->l4.udp.teamviewer_stage == 4 ||
+ packet->udp->dest == ntohs(5938) || packet->udp->source == ntohs(5938)) {
+ ndpi_int_teamview_add_connection(ndpi_struct, flow);
+ }
+ return;
+ }
+ }
+ }
+ else if(packet->tcp != NULL) {
+ if (packet->payload_packet_len > 2) {
+ if (packet->payload[0] == 0x17 && packet->payload[1] == 0x24) {
+ flow->l4.udp.teamviewer_stage++;
+ if (flow->l4.udp.teamviewer_stage == 4 ||
+ packet->tcp->dest == ntohs(5938) || packet->tcp->source == ntohs(5938)) {
+ ndpi_int_teamview_add_connection(ndpi_struct, flow);
+ }
+ return;
+ }
+ else if (flow->l4.udp.teamviewer_stage) {
+ if (packet->payload[0] == 0x11 && packet->payload[1] == 0x30) {
+ flow->l4.udp.teamviewer_stage++;
+ if (flow->l4.udp.teamviewer_stage == 4)
+ ndpi_int_teamview_add_connection(ndpi_struct, flow);
+ }
+ return;
+ }
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TEAMVIEWER);
+}
+#endif
diff --git a/src/lib/protocols/telegram.c b/src/lib/protocols/telegram.c
new file mode 100644
index 000000000..ba9397a92
--- /dev/null
+++ b/src/lib/protocols/telegram.c
@@ -0,0 +1,68 @@
+/*
+ * telegram.c
+ *
+ * Copyright (C) 2014 by Gianluca Costa xplico.org
+ * Copyright (C) 2012-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_TELEGRAM
+
+static void ndpi_int_telegram_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TELEGRAM, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_TELEGRAM, ndpi_struct, NDPI_LOG_TRACE, "TELEGRAM Found.\n");
+}
+
+
+void ndpi_search_telegram(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t dport /* , sport */;
+
+ NDPI_LOG(NDPI_PROTOCOL_TELEGRAM, ndpi_struct, NDPI_LOG_TRACE, "TELEGRAM detection...\n");
+
+ if (packet->payload_packet_len == 0)
+ return;
+ if (packet->tcp != NULL) {
+ if (packet->payload_packet_len > 56) {
+ dport = ntohs(packet->tcp->dest);
+ /* sport = ntohs(packet->tcp->source); */
+
+ if (packet->payload[0] == 0xef && (
+ dport == 443 || dport == 80 || dport == 25
+ )) {
+ if (packet->payload[1] == 0x7f) {
+ ndpi_int_telegram_add_connection(ndpi_struct, flow);
+ }
+ else if (packet->payload[1]*4 <= packet->payload_packet_len - 1) {
+ ndpi_int_telegram_add_connection(ndpi_struct, flow);
+ }
+ return;
+ }
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TELEGRAM);
+}
+#endif
diff --git a/src/lib/protocols/telnet.c b/src/lib/protocols/telnet.c
new file mode 100644
index 000000000..0954be111
--- /dev/null
+++ b/src/lib/protocols/telnet.c
@@ -0,0 +1,107 @@
+/*
+ * telnet.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_TELNET
+
+
+
+static void ndpi_int_telnet_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TELNET, NDPI_REAL_PROTOCOL);
+}
+
+
+#if !defined(WIN32)
+ static inline
+#else
+__forceinline static
+#endif
+ u_int8_t search_iac(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ u_int16_t a;
+
+ if (packet->payload_packet_len < 3) {
+ return 0;
+ }
+
+ if (!(packet->payload[0] == 0xff
+ && packet->payload[1] > 0xf9 && packet->payload[1] != 0xff && packet->payload[2] < 0x28)) {
+ return 0;
+ }
+
+ a = 3;
+
+ while (a < packet->payload_packet_len - 2) {
+ // commands start with a 0xff byte followed by a command byte >= 0xf0 and < 0xff
+ // command bytes 0xfb to 0xfe are followed by an option byte <= 0x28
+ if (!(packet->payload[a] != 0xff ||
+ (packet->payload[a] == 0xff && (packet->payload[a + 1] >= 0xf0) && (packet->payload[a + 1] <= 0xfa)) ||
+ (packet->payload[a] == 0xff && (packet->payload[a + 1] >= 0xfb) && (packet->payload[a + 1] != 0xff)
+ && (packet->payload[a + 2] <= 0x28)))) {
+ return 0;
+ }
+ a++;
+ }
+
+ return 1;
+}
+
+/* this detection also works asymmetrically */
+void ndpi_search_telnet_tcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+// struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_TELNET, ndpi_struct, NDPI_LOG_DEBUG, "search telnet.\n");
+
+ if (search_iac(ndpi_struct, flow) == 1) {
+
+ if (flow->l4.tcp.telnet_stage == 2) {
+ NDPI_LOG(NDPI_PROTOCOL_TELNET, ndpi_struct, NDPI_LOG_DEBUG, "telnet identified.\n");
+ ndpi_int_telnet_add_connection(ndpi_struct, flow);
+ return;
+ }
+ flow->l4.tcp.telnet_stage++;
+ NDPI_LOG(NDPI_PROTOCOL_TELNET, ndpi_struct, NDPI_LOG_DEBUG, "telnet stage %u.\n", flow->l4.tcp.telnet_stage);
+ return;
+ }
+
+ if ((flow->packet_counter < 12 && flow->l4.tcp.telnet_stage > 0) || flow->packet_counter < 6) {
+ return;
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_TELNET, ndpi_struct, NDPI_LOG_DEBUG, "telnet excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TELNET);
+ }
+ return;
+}
+
+#endif
diff --git a/src/lib/protocols/tftp.c b/src/lib/protocols/tftp.c
new file mode 100644
index 000000000..d5145445b
--- /dev/null
+++ b/src/lib/protocols/tftp.c
@@ -0,0 +1,70 @@
+/*
+ * tftp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_TFTP
+
+static void ndpi_int_tftp_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TFTP, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_tftp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+
+
+ NDPI_LOG(NDPI_PROTOCOL_TFTP, ndpi_struct, NDPI_LOG_DEBUG, "search TFTP.\n");
+
+
+
+ if (packet->payload_packet_len > 3 && flow->l4.udp.tftp_stage == 0
+ && ntohl(get_u_int32_t(packet->payload, 0)) == 0x00030001) {
+ NDPI_LOG(NDPI_PROTOCOL_TFTP, ndpi_struct, NDPI_LOG_DEBUG, "maybe tftp. need next packet.\n");
+ flow->l4.udp.tftp_stage = 1;
+ return;
+ }
+ if (packet->payload_packet_len > 3 && (flow->l4.udp.tftp_stage == 1)
+ && ntohl(get_u_int32_t(packet->payload, 0)) == 0x00040001) {
+
+ NDPI_LOG(NDPI_PROTOCOL_TFTP, ndpi_struct, NDPI_LOG_DEBUG, "found tftp.\n");
+ ndpi_int_tftp_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->payload_packet_len > 1
+ && ((packet->payload[0] == 0 && packet->payload[packet->payload_packet_len - 1] == 0)
+ || (packet->payload_packet_len == 4 && ntohl(get_u_int32_t(packet->payload, 0)) == 0x00040000))) {
+ NDPI_LOG(NDPI_PROTOCOL_TFTP, ndpi_struct, NDPI_LOG_DEBUG, "skip initial packet.\n");
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_TFTP, ndpi_struct, NDPI_LOG_DEBUG, "exclude TFTP.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TFTP);
+}
+#endif
diff --git a/src/lib/protocols/thunder.c b/src/lib/protocols/thunder.c
new file mode 100644
index 000000000..3784bb781
--- /dev/null
+++ b/src/lib/protocols/thunder.c
@@ -0,0 +1,211 @@
+/*
+ * thunder.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_THUNDER
+
+static void ndpi_int_thunder_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, ndpi_protocol_type_t protocol_type)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_THUNDER, protocol_type);
+
+ if (src != NULL) {
+ src->thunder_ts = packet->tick_timestamp;
+ }
+ if (dst != NULL) {
+ dst->thunder_ts = packet->tick_timestamp;
+ }
+}
+
+
+
+#if !defined(WIN32)
+ static inline
+#else
+__forceinline static
+#endif
+ void ndpi_int_search_thunder_udp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len > 8 && packet->payload[0] >= 0x30
+ && packet->payload[0] < 0x40 && packet->payload[1] == 0 && packet->payload[2] == 0 && packet->payload[3] == 0) {
+ if (flow->thunder_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG, "THUNDER udp detected\n");
+ ndpi_int_thunder_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ flow->thunder_stage++;
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG,
+ "maybe thunder udp packet detected, stage increased to %u\n", flow->thunder_stage);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG,
+ "excluding thunder udp at stage %u\n", flow->thunder_stage);
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_THUNDER);
+}
+
+
+#if !defined(WIN32)
+ static inline
+#else
+__forceinline static
+#endif
+ void ndpi_int_search_thunder_tcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->payload_packet_len > 8 && packet->payload[0] >= 0x30
+ && packet->payload[0] < 0x40 && packet->payload[1] == 0 && packet->payload[2] == 0 && packet->payload[3] == 0) {
+ if (flow->thunder_stage == 3) {
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG, "THUNDER tcp detected\n");
+ ndpi_int_thunder_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ flow->thunder_stage++;
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG,
+ "maybe thunder tcp packet detected, stage increased to %u\n", flow->thunder_stage);
+ return;
+ }
+
+ if (flow->thunder_stage == 0 && packet->payload_packet_len > 17
+ && memcmp(packet->payload, "POST / HTTP/1.1\r\n", 17) == 0) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG,
+ "maybe thunder http POST packet detected, parsed packet lines: %u, empty line set %u (at: %u)\n",
+ packet->parsed_lines, packet->empty_line_position_set, packet->empty_line_position);
+
+ if (packet->empty_line_position_set != 0 &&
+ packet->content_line.ptr != NULL &&
+ packet->content_line.len == 24 &&
+ memcmp(packet->content_line.ptr, "application/octet-stream",
+ 24) == 0 && packet->empty_line_position_set < (packet->payload_packet_len - 8)
+ && packet->payload[packet->empty_line_position + 2] >= 0x30
+ && packet->payload[packet->empty_line_position + 2] < 0x40
+ && packet->payload[packet->empty_line_position + 3] == 0x00
+ && packet->payload[packet->empty_line_position + 4] == 0x00
+ && packet->payload[packet->empty_line_position + 5] == 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG,
+ "maybe thunder http POST packet application does match\n");
+ ndpi_int_thunder_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG,
+ "excluding thunder tcp at stage %u\n", flow->thunder_stage);
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_THUNDER);
+}
+
+
+#if !defined(WIN32)
+ static inline
+#else
+__forceinline static
+#endif
+ void ndpi_int_search_thunder_http(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_THUNDER) {
+ if (src != NULL && ((u_int32_t)
+ (packet->tick_timestamp - src->thunder_ts) < ndpi_struct->thunder_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG,
+ "thunder : save src connection packet detected\n");
+ src->thunder_ts = packet->tick_timestamp;
+ } else if (dst != NULL && ((u_int32_t)
+ (packet->tick_timestamp - dst->thunder_ts) < ndpi_struct->thunder_timeout)) {
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG,
+ "thunder : save dst connection packet detected\n");
+ dst->thunder_ts = packet->tick_timestamp;
+ }
+ return;
+ }
+
+ if (packet->payload_packet_len > 5
+ && memcmp(packet->payload, "GET /", 5) == 0 && NDPI_SRC_OR_DST_HAS_PROTOCOL(src, dst, NDPI_PROTOCOL_THUNDER)) {
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG, "HTTP packet detected.\n");
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if (packet->parsed_lines > 7
+ && packet->parsed_lines < 11
+ && packet->line[1].len > 10
+ && memcmp(packet->line[1].ptr, "Accept: */*", 11) == 0
+ && packet->line[2].len > 22
+ && memcmp(packet->line[2].ptr, "Cache-Control: no-cache",
+ 23) == 0 && packet->line[3].len > 16
+ && memcmp(packet->line[3].ptr, "Connection: close", 17) == 0
+ && packet->line[4].len > 6
+ && memcmp(packet->line[4].ptr, "Host: ", 6) == 0
+ && packet->line[5].len > 15
+ && memcmp(packet->line[5].ptr, "Pragma: no-cache", 16) == 0
+ && packet->user_agent_line.ptr != NULL
+ && packet->user_agent_line.len > 49
+ && memcmp(packet->user_agent_line.ptr,
+ "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)", 50) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_THUNDER, ndpi_struct, NDPI_LOG_DEBUG,
+ "Thunder HTTP download detected, adding flow.\n");
+ ndpi_int_thunder_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ }
+ }
+}
+
+void ndpi_search_thunder(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ //
+ //struct ndpi_id_struct *src = flow->src;
+ //struct ndpi_id_struct *dst = flow->dst;
+
+ if (packet->tcp != NULL) {
+ ndpi_int_search_thunder_http(ndpi_struct, flow);
+ ndpi_int_search_thunder_tcp(ndpi_struct, flow);
+ } else if (packet->udp != NULL) {
+ ndpi_int_search_thunder_udp(ndpi_struct, flow);
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/tor.c b/src/lib/protocols/tor.c
new file mode 100644
index 000000000..ead857726
--- /dev/null
+++ b/src/lib/protocols/tor.c
@@ -0,0 +1,109 @@
+/*
+ * tor.c
+ *
+ * Copyright (C) 2015 ntop.org
+ * Copyright (C) 2013 Remy Mudingay <mudingay@ill.fr>
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+
+#ifdef NDPI_PROTOCOL_TOR
+
+static void ndpi_int_tor_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TOR, NDPI_CORRELATED_PROTOCOL);
+}
+
+
+int ndpi_is_ssl_tor(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, char *certificate) {
+ int prev_num = 0, numbers_found = 0, num_found = 0, i;
+ char dummy[48], *dot, *name;
+
+ if((certificate == NULL)
+ || (strlen(certificate) < 6)
+ || strncmp(certificate, "www.", 4))
+ return(0);
+
+ // printf("***** [SSL] %s(): %s\n", __FUNCTION__, certificate);
+
+ snprintf(dummy, sizeof(dummy), "%s", certificate);
+
+ if((dot = strrchr(dummy, '.')) == NULL) return(0);
+ dot[0] = '\0';
+
+ if((dot = strrchr(dummy, '.')) == NULL) return(0);
+ name = &dot[1];
+
+ for(i = 0; name[i+1] != '\0'; i++) {
+ if((name[i] >= '0') && (name[i] <= '9')) {
+
+ if(prev_num != 1) {
+ numbers_found++;
+
+ if(numbers_found == 2) {
+ ndpi_int_tor_add_connection(ndpi_struct, flow);
+ return(1);
+ }
+ prev_num = 1;
+ }
+ } else
+ prev_num = 0;
+
+ if(ndpi_match_bigram(ndpi_struct, &ndpi_struct->impossible_bigrams_automa, &name[i])) {
+ ndpi_int_tor_add_connection(ndpi_struct, flow);
+ return(1);
+ }
+
+ if(ndpi_match_bigram(ndpi_struct, &ndpi_struct->bigrams_automa, &name[i])) {
+ num_found++;
+ }
+ }
+
+ if(num_found == 0) {
+ ndpi_int_tor_add_connection(ndpi_struct, flow);
+ return(1);
+ } else {
+#ifndef __KERNEL__
+#ifdef PENDANTIC_TOR_CHECK
+ if(gethostbyname(certificate) == NULL) {
+ ndpi_int_tor_add_connection(ndpi_struct, flow);
+ return(1);
+ }
+#endif
+#endif
+ }
+
+ return(0);
+}
+
+/* ******************************************* */
+
+void ndpi_search_tor(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t dport = 0, sport = 0;
+
+ NDPI_LOG(NDPI_PROTOCOL_TOR, ndpi_struct, NDPI_LOG_DEBUG, "search for TOR.\n");
+
+ if(packet->tcp != NULL) {
+ sport = ntohs(packet->tcp->source), dport = ntohs(packet->tcp->dest);
+ NDPI_LOG(NDPI_PROTOCOL_TOR, ndpi_struct, NDPI_LOG_DEBUG, "calculating TOR over tcp.\n");
+
+ if ((((dport == 9001) || (sport == 9001)) || ((dport == 9030) || (sport == 9030)))
+ && ((packet->payload[0] == 0x17) || (packet->payload[0] == 0x16))
+ && (packet->payload[1] == 0x03)
+ && (packet->payload[2] == 0x01)
+ && (packet->payload[3] == 0x00)) {
+ NDPI_LOG(NDPI_PROTOCOL_TOR, ndpi_struct, NDPI_LOG_DEBUG, "found tor.\n");
+ ndpi_int_tor_add_connection(ndpi_struct, flow);
+ }
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_TOR, ndpi_struct, NDPI_LOG_DEBUG, "exclude TOR.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TOR);
+ }
+}
+#endif
diff --git a/src/lib/protocols/tvants.c b/src/lib/protocols/tvants.c
new file mode 100644
index 000000000..5021fadcd
--- /dev/null
+++ b/src/lib/protocols/tvants.c
@@ -0,0 +1,78 @@
+/*
+ * tvants.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_TVANTS
+
+static void ndpi_int_tvants_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TVANTS, NDPI_REAL_PROTOCOL);
+}
+
+
+
+
+void ndpi_search_tvants_udp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ NDPI_LOG(NDPI_PROTOCOL_TVANTS, ndpi_struct, NDPI_LOG_DEBUG, "search tvants. \n");
+
+ if (packet->udp != NULL && packet->payload_packet_len > 57
+ && packet->payload[0] == 0x04 && packet->payload[1] == 0x00
+ && (packet->payload[2] == 0x05 || packet->payload[2] == 0x06
+ || packet->payload[2] == 0x07) && packet->payload[3] == 0x00
+ && packet->payload_packet_len == (packet->payload[5] << 8) + packet->payload[4]
+ && packet->payload[6] == 0x00 && packet->payload[7] == 0x00
+ && (memcmp(&packet->payload[48], "TVANTS", 6) == 0
+ || memcmp(&packet->payload[49], "TVANTS", 6) == 0 || memcmp(&packet->payload[51], "TVANTS", 6) == 0)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_TVANTS, ndpi_struct, NDPI_LOG_DEBUG, "found tvants over udp. \n");
+ ndpi_int_tvants_add_connection(ndpi_struct, flow);
+
+ } else if (packet->tcp != NULL && packet->payload_packet_len > 15
+ && packet->payload[0] == 0x04 && packet->payload[1] == 0x00
+ && packet->payload[2] == 0x07 && packet->payload[3] == 0x00
+ && packet->payload_packet_len == (packet->payload[5] << 8) + packet->payload[4]
+ && packet->payload[6] == 0x00 && packet->payload[7] == 0x00
+ && memcmp(&packet->payload[8], "TVANTS", 6) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_TVANTS, ndpi_struct, NDPI_LOG_DEBUG, "found tvants over tcp. \n");
+ ndpi_int_tvants_add_connection(ndpi_struct, flow);
+
+ }
+ NDPI_LOG(NDPI_PROTOCOL_TVANTS, ndpi_struct, NDPI_LOG_DEBUG, "exclude tvants. \n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TVANTS);
+
+}
+#endif
diff --git a/src/lib/protocols/tvuplayer.c b/src/lib/protocols/tvuplayer.c
new file mode 100644
index 000000000..a81ea96b3
--- /dev/null
+++ b/src/lib/protocols/tvuplayer.c
@@ -0,0 +1,153 @@
+/*
+ * tvuplayer.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_TVUPLAYER
+
+
+static void ndpi_int_tvuplayer_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_TVUPLAYER, protocol_type);
+}
+
+void ndpi_search_tvuplayer(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_TVUPLAYER, ndpi_struct, NDPI_LOG_DEBUG, "search tvuplayer. \n");
+
+
+
+ if (packet->tcp != NULL) {
+ if ((packet->payload_packet_len == 36 || packet->payload_packet_len == 24)
+ && packet->payload[0] == 0x00
+ && ntohl(get_u_int32_t(packet->payload, 2)) == 0x31323334
+ && ntohl(get_u_int32_t(packet->payload, 6)) == 0x35363837 && packet->payload[10] == 0x01) {
+ NDPI_LOG(NDPI_PROTOCOL_TVUPLAYER, ndpi_struct, NDPI_LOG_DEBUG, "found tvuplayer over tcp. \n");
+ ndpi_int_tvuplayer_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+
+ if (packet->payload_packet_len >= 50) {
+
+ if (memcmp(packet->payload, "POST", 4) || memcmp(packet->payload, "GET", 3)) {
+ NDPI_PARSE_PACKET_LINE_INFO(ndpi_struct, flow, packet);
+ if (packet->user_agent_line.ptr != NULL &&
+ packet->user_agent_line.len >= 8 && (memcmp(packet->user_agent_line.ptr, "MacTVUP", 7) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_TVUPLAYER, ndpi_struct, NDPI_LOG_DEBUG, "Found user agent as MacTVUP.\n");
+ ndpi_int_tvuplayer_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+ }
+
+ if (packet->udp != NULL) {
+
+ if (packet->payload_packet_len == 56 &&
+ packet->payload[0] == 0xff
+ && packet->payload[1] == 0xff && packet->payload[2] == 0x00
+ && packet->payload[3] == 0x01
+ && packet->payload[12] == 0x02 && packet->payload[13] == 0xff
+ && packet->payload[19] == 0x2c && ((packet->payload[26] == 0x05 && packet->payload[27] == 0x14)
+ || (packet->payload[26] == 0x14 && packet->payload[27] == 0x05))) {
+ NDPI_LOG(NDPI_PROTOCOL_TVUPLAYER, ndpi_struct, NDPI_LOG_DEBUG, "found tvuplayer pattern type I. \n");
+ ndpi_int_tvuplayer_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 82
+ && packet->payload[0] == 0x00 && packet->payload[2] == 0x00
+ && packet->payload[10] == 0x00 && packet->payload[11] == 0x00
+ && packet->payload[12] == 0x01 && packet->payload[13] == 0xff
+ && packet->payload[19] == 0x14 && packet->payload[32] == 0x03
+ && packet->payload[33] == 0xff && packet->payload[34] == 0x01
+ && packet->payload[39] == 0x32 && ((packet->payload[46] == 0x05 && packet->payload[47] == 0x14)
+ || (packet->payload[46] == 0x14 && packet->payload[47] == 0x05))) {
+ NDPI_LOG(NDPI_PROTOCOL_TVUPLAYER, ndpi_struct, NDPI_LOG_DEBUG, "found tvuplayer pattern type II. \n");
+ ndpi_int_tvuplayer_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 32
+ && packet->payload[0] == 0x00 && packet->payload[2] == 0x00
+ && (packet->payload[10] == 0x00 || packet->payload[10] == 0x65
+ || packet->payload[10] == 0x7e || packet->payload[10] == 0x49)
+ && (packet->payload[11] == 0x00 || packet->payload[11] == 0x57
+ || packet->payload[11] == 0x06 || packet->payload[11] == 0x22)
+ && packet->payload[12] == 0x01 && (packet->payload[13] == 0xff || packet->payload[13] == 0x01)
+ && packet->payload[19] == 0x14) {
+ NDPI_LOG(NDPI_PROTOCOL_TVUPLAYER, ndpi_struct, NDPI_LOG_DEBUG, "found tvuplayer pattern type III. \n");
+ ndpi_int_tvuplayer_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 84
+ && packet->payload[0] == 0x00 && packet->payload[2] == 0x00
+ && packet->payload[10] == 0x00 && packet->payload[11] == 0x00
+ && packet->payload[12] == 0x01 && packet->payload[13] == 0xff
+ && packet->payload[19] == 0x14 && packet->payload[32] == 0x03
+ && packet->payload[33] == 0xff && packet->payload[34] == 0x01 && packet->payload[39] == 0x34) {
+ NDPI_LOG(NDPI_PROTOCOL_TVUPLAYER, ndpi_struct, NDPI_LOG_DEBUG, "found tvuplayer pattern type IV. \n");
+ ndpi_int_tvuplayer_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 102
+ && packet->payload[0] == 0x00 && packet->payload[2] == 0x00
+ && packet->payload[10] == 0x00 && packet->payload[11] == 0x00
+ && packet->payload[12] == 0x01 && packet->payload[13] == 0xff
+ && packet->payload[19] == 0x14 && packet->payload[33] == 0xff && packet->payload[39] == 0x14) {
+ NDPI_LOG(NDPI_PROTOCOL_TVUPLAYER, ndpi_struct, NDPI_LOG_DEBUG, "found tvuplayer pattern type V. \n");
+ ndpi_int_tvuplayer_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len == 62 && packet->payload[0] == 0x00 && packet->payload[2] == 0x00
+ //&& packet->payload[10] == 0x00 && packet->payload[11] == 0x00
+ && packet->payload[12] == 0x03 && packet->payload[13] == 0xff
+ && packet->payload[19] == 0x32 && ((packet->payload[26] == 0x05 && packet->payload[27] == 0x14)
+ || (packet->payload[26] == 0x14 && packet->payload[27] == 0x05))) {
+ NDPI_LOG(NDPI_PROTOCOL_TVUPLAYER, ndpi_struct, NDPI_LOG_DEBUG, "found tvuplayer pattern type VI. \n");
+ ndpi_int_tvuplayer_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ // to check, if byte 26, 27, 33,39 match
+ if (packet->payload_packet_len == 60
+ && packet->payload[0] == 0x00 && packet->payload[2] == 0x00
+ && packet->payload[10] == 0x00 && packet->payload[11] == 0x00
+ && packet->payload[12] == 0x06 && packet->payload[13] == 0x00 && packet->payload[19] == 0x30) {
+ NDPI_LOG(NDPI_PROTOCOL_TVUPLAYER, ndpi_struct, NDPI_LOG_DEBUG, "found tvuplayer pattern type VII. \n");
+ ndpi_int_tvuplayer_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_TVUPLAYER, ndpi_struct, NDPI_LOG_DEBUG, "exclude tvuplayer. \n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_TVUPLAYER);
+
+}
+#endif
diff --git a/src/lib/protocols/twitter.c b/src/lib/protocols/twitter.c
new file mode 100644
index 000000000..db2f77a5e
--- /dev/null
+++ b/src/lib/protocols/twitter.c
@@ -0,0 +1,63 @@
+/*
+ * twitter.c
+ *
+ * Copyright (C) 2014 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_SERVICE_TWITTER
+
+static void ndpi_int_twitter_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_SERVICE_TWITTER, NDPI_REAL_PROTOCOL);
+}
+
+
+void ndpi_search_twitter(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+ /*
+ Twitter AS34702
+
+ http://bgp.he.net/AS13414
+ */
+ if(flow->packet.iph) {
+ // IPv4
+ u_int32_t src = ntohl(flow->packet.iph->saddr);
+ u_int32_t dst = ntohl(flow->packet.iph->daddr);
+
+ if(ndpi_ips_match(src, dst, 0xC0854C00, 22) /* 192.133.76.0/22 */
+ || ndpi_ips_match(src, dst, 0xC7109C00, 22) /* 199.16.156.0/22 */
+ || ndpi_ips_match(src, dst, 0xC73B9400, 22) /* 199.59.148.0/22 */
+ || ndpi_ips_match(src, dst, 0xC7603A00, 23) /* 199.96.58.0/23 */
+ || ndpi_ips_match(src, dst, 0xC7603E00, 23) /* 199.96.62.0/23 */
+ ) {
+ ndpi_int_twitter_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_SERVICE_TWITTER);
+}
+#endif
diff --git a/src/lib/protocols/usenet.c b/src/lib/protocols/usenet.c
new file mode 100644
index 000000000..07ed91678
--- /dev/null
+++ b/src/lib/protocols/usenet.c
@@ -0,0 +1,105 @@
+/*
+ * usenet.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_USENET
+
+
+static void ndpi_int_usenet_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_USENET, NDPI_REAL_PROTOCOL);
+}
+
+
+
+void ndpi_search_usenet_tcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_USENET, ndpi_struct, NDPI_LOG_DEBUG, "USENET: search usenet.\n");
+
+
+
+
+
+ NDPI_LOG(NDPI_PROTOCOL_USENET, ndpi_struct, NDPI_LOG_DEBUG, "USENET: STAGE IS %u.\n", flow->l4.tcp.usenet_stage);
+
+
+ // check for the first server replay
+ /*
+ 200 Service available, posting allowed
+ 201 Service available, posting prohibited
+ */
+ if (flow->l4.tcp.usenet_stage == 0 && packet->payload_packet_len > 10
+ && ((memcmp(packet->payload, "200 ", 4) == 0)
+ || (memcmp(packet->payload, "201 ", 4) == 0))) {
+
+ NDPI_LOG(NDPI_PROTOCOL_USENET, ndpi_struct, NDPI_LOG_DEBUG, "USENET: found 200 or 201.\n");
+ flow->l4.tcp.usenet_stage = 1 + packet->packet_direction;
+
+ NDPI_LOG(NDPI_PROTOCOL_USENET, ndpi_struct, NDPI_LOG_DEBUG, "USENET: maybe hit.\n");
+ return;
+ }
+
+ /*
+ [C] AUTHINFO USER fred
+ [S] 381 Enter passphrase
+ [C] AUTHINFO PASS flintstone
+ [S] 281 Authentication accepted
+ */
+ // check for client username
+ if (flow->l4.tcp.usenet_stage == 2 - packet->packet_direction) {
+ if (packet->payload_packet_len > 20 && (memcmp(packet->payload, "AUTHINFO USER ", 14) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_USENET, ndpi_struct, NDPI_LOG_DEBUG, "USENET: username found\n");
+ flow->l4.tcp.usenet_stage = 3 + packet->packet_direction;
+
+ NDPI_LOG(NDPI_PROTOCOL_USENET, ndpi_struct, NDPI_LOG_DEBUG, "USENET: found usenet.\n");
+ ndpi_int_usenet_add_connection(ndpi_struct, flow);
+ return;
+ } else if (packet->payload_packet_len == 13 && (memcmp(packet->payload, "MODE READER\r\n", 13) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_USENET, ndpi_struct, NDPI_LOG_DEBUG,
+ "USENET: no login necessary but we are a client.\n");
+
+ NDPI_LOG(NDPI_PROTOCOL_USENET, ndpi_struct, NDPI_LOG_DEBUG, "USENET: found usenet.\n");
+ ndpi_int_usenet_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+
+
+
+ NDPI_LOG(NDPI_PROTOCOL_USENET, ndpi_struct, NDPI_LOG_DEBUG, "USENET: exclude usenet.\n");
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_USENET);
+
+}
+
+#endif
diff --git a/src/lib/protocols/veohtv.c b/src/lib/protocols/veohtv.c
new file mode 100644
index 000000000..10f84c3fd
--- /dev/null
+++ b/src/lib/protocols/veohtv.c
@@ -0,0 +1,116 @@
+/*
+ * veohtv.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+
+#ifdef NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV
+
+static void ndpi_int_veohtv_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, protocol_type);
+}
+
+void ndpi_search_veohtv_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV)
+ return;
+
+ if (flow->l4.tcp.veoh_tv_stage == 1 || flow->l4.tcp.veoh_tv_stage == 2) {
+ if (packet->packet_direction != flow->setup_packet_direction &&
+ packet->payload_packet_len > NDPI_STATICSTRING_LEN("HTTP/1.1 20")
+ && memcmp(packet->payload, "HTTP/1.1 ", NDPI_STATICSTRING_LEN("HTTP/1.1 ")) == 0 &&
+ (packet->payload[NDPI_STATICSTRING_LEN("HTTP/1.1 ")] == '2' ||
+ packet->payload[NDPI_STATICSTRING_LEN("HTTP/1.1 ")] == '3' ||
+ packet->payload[NDPI_STATICSTRING_LEN("HTTP/1.1 ")] == '4' ||
+ packet->payload[NDPI_STATICSTRING_LEN("HTTP/1.1 ")] == '5')) {
+#ifdef NDPI_CONTENT_FLASH
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->detected_protocol_stack[0] == NDPI_CONTENT_FLASH &&
+ packet->server_line.ptr != NULL &&
+ packet->server_line.len > NDPI_STATICSTRING_LEN("Veoh-") &&
+ memcmp(packet->server_line.ptr, "Veoh-", NDPI_STATICSTRING_LEN("Veoh-")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, ndpi_struct, NDPI_LOG_DEBUG, "VeohTV detected.\n");
+ ndpi_int_veohtv_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+#endif
+ if (flow->l4.tcp.veoh_tv_stage == 2) {
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask,
+ NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV);
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, ndpi_struct, NDPI_LOG_DEBUG, "VeohTV detected.\n");
+ ndpi_int_veohtv_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ } else if (flow->packet_direction_counter[(flow->setup_packet_direction == 1) ? 0 : 1] > 3) {
+ if (flow->l4.tcp.veoh_tv_stage == 2) {
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask,
+ NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV);
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, ndpi_struct, NDPI_LOG_DEBUG, "VeohTV detected.\n");
+ ndpi_int_veohtv_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ } else {
+ if (flow->packet_counter > 10) {
+ if (flow->l4.tcp.veoh_tv_stage == 2) {
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask,
+ NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV);
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, ndpi_struct, NDPI_LOG_DEBUG, "VeohTV detected.\n");
+ ndpi_int_veohtv_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ return;
+ }
+ } else if (packet->udp) {
+ /* UDP packets from Veoh Client Player
+ *
+ * packet starts with 16 byte random? value
+ * then a 4 byte mode value
+ * values between 21 and 26 has been seen
+ * then a 4 byte counter */
+
+ if (packet->payload_packet_len == 28 &&
+ get_u_int32_t(packet->payload, 16) == htonl(0x00000021) &&
+ get_u_int32_t(packet->payload, 20) == htonl(0x00000000) && get_u_int32_t(packet->payload, 24) == htonl(0x01040000)) {
+ NDPI_LOG(NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV, ndpi_struct, NDPI_LOG_DEBUG, "UDP VeohTV found.\n");
+ ndpi_int_veohtv_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_HTTP_APPLICATION_VEOHTV);
+}
+#endif
diff --git a/src/lib/protocols/vhua.c b/src/lib/protocols/vhua.c
new file mode 100644
index 000000000..027cc697c
--- /dev/null
+++ b/src/lib/protocols/vhua.c
@@ -0,0 +1,68 @@
+/*
+ * vhua.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * nDPI is free software: you can vhuatribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+/*
+ http://www.vhua.com
+
+ Skype-like Chinese phone protocol
+
+ */
+
+#ifdef NDPI_PROTOCOL_VHUA
+
+static void ndpi_int_vhua_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_VHUA, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_VHUA, ndpi_struct, NDPI_LOG_TRACE, "VHUA Found.\n");
+}
+
+
+static void ndpi_check_vhua(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+ u_char p0[] = { 0x05, 0x14, 0x3a, 0x05, 0x08, 0xf8, 0xa1, 0xb1, 0x03 };
+
+ if(payload_len == 0) return; /* Shouldn't happen */
+
+ /* Break after 3 packets. */
+ if((flow->packet_counter > 3)
+ || (packet->udp == NULL)
+ || (packet->payload_packet_len < sizeof(p0))) {
+ NDPI_LOG(NDPI_PROTOCOL_VHUA, ndpi_struct, NDPI_LOG_TRACE, "Exclude VHUA.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_VHUA);
+ } else if(memcmp(packet->payload, p0, sizeof(p0)) == 0) {
+ ndpi_int_vhua_add_connection(ndpi_struct, flow);
+ }
+}
+
+void ndpi_search_vhua(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_VHUA, ndpi_struct, NDPI_LOG_TRACE, "VHUA detection...\n");
+
+ /* skip marked packets */
+ if(packet->detected_protocol_stack[0] != NDPI_PROTOCOL_VHUA) {
+ ndpi_check_vhua(ndpi_struct, flow);
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/viber.c b/src/lib/protocols/viber.c
new file mode 100644
index 000000000..f53139e83
--- /dev/null
+++ b/src/lib/protocols/viber.c
@@ -0,0 +1,48 @@
+/*
+ * viber.c
+ *
+ * Copyright (C) 2013 Remy Mudingay <mudingay@ill.fr>
+ * Copyright (C) 2013 - 2014 ntop.org
+ *
+ * This module is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This module 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License.
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_VIBER
+
+void ndpi_search_viber(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_VIBER, ndpi_struct, NDPI_LOG_DEBUG, "search for VIBER.\n");
+
+ if(packet->udp != NULL) {
+ NDPI_LOG(NDPI_PROTOCOL_VIBER, ndpi_struct, NDPI_LOG_DEBUG, "calculating dport over udp.\n");
+
+ if((packet->payload_packet_len == 12 && packet->payload[2] == 0x03 && packet->payload[3] == 0x00)
+ || (packet->payload_packet_len == 20 && packet->payload[2] == 0x09 && packet->payload[3] == 0x00)
+ || ((packet->payload_packet_len < 135) && (packet->payload[0] == 0x11))) {
+ NDPI_LOG(NDPI_PROTOCOL_VIBER, ndpi_struct, NDPI_LOG_DEBUG, "found VIBER.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_VIBER, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_VIBER, ndpi_struct, NDPI_LOG_DEBUG, "exclude VIBER.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_VIBER);
+}
+
+#endif
diff --git a/src/lib/protocols/vmware.c b/src/lib/protocols/vmware.c
new file mode 100644
index 000000000..de21c521f
--- /dev/null
+++ b/src/lib/protocols/vmware.c
@@ -0,0 +1,45 @@
+/*
+ * vmware.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_VMWARE
+
+
+void ndpi_search_vmware(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ /* Check whether this is an VMWARE flow */
+ if((packet->payload_packet_len == 66)
+ && (ntohs(packet->udp->dest) == 902)
+ && ((packet->payload[0] & 0xFF) == 0xA4)) {
+ NDPI_LOG(NDPI_PROTOCOL_VMWARE, ndpi_struct, NDPI_LOG_DEBUG, "Found vmware.\n");
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_VMWARE, NDPI_REAL_PROTOCOL);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_VMWARE, ndpi_struct, NDPI_LOG_DEBUG, "exclude vmware.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_VMWARE);
+ }
+}
+
+
+#endif /* NDPI_PROTOCOL_VMWARE */
+
diff --git a/src/lib/protocols/vnc.c b/src/lib/protocols/vnc.c
new file mode 100644
index 000000000..afd467ea7
--- /dev/null
+++ b/src/lib/protocols/vnc.c
@@ -0,0 +1,67 @@
+/*
+ * vnc.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_VNC
+
+static void ndpi_int_vnc_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_VNC, NDPI_REAL_PROTOCOL);
+}
+
+/*
+ return 0 if nothing has been detected
+ return 1 if it is a http packet
+*/
+
+void ndpi_search_vnc_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ if (flow->l4.tcp.vnc_stage == 0) {
+ if (packet->payload_packet_len == 12
+ && memcmp(packet->payload, "RFB 003.00", 10) == 0 && packet->payload[11] == 0x0a) {
+ NDPI_LOG(NDPI_PROTOCOL_VNC, ndpi_struct, NDPI_LOG_DEBUG, "reached vnc stage one\n");
+ flow->l4.tcp.vnc_stage = 1 + packet->packet_direction;
+ return;
+ }
+ } else if (flow->l4.tcp.vnc_stage == 2 - packet->packet_direction) {
+ if (packet->payload_packet_len == 12
+ && memcmp(packet->payload, "RFB 003.00", 10) == 0 && packet->payload[11] == 0x0a) {
+ NDPI_LOG(NDPI_PROTOCOL_VNC, ndpi_struct, NDPI_LOG_DEBUG, "found vnc\n");
+ ndpi_int_vnc_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_VNC);
+
+}
+#endif
diff --git a/src/lib/protocols/warcraft3.c b/src/lib/protocols/warcraft3.c
new file mode 100644
index 000000000..7780dbf6e
--- /dev/null
+++ b/src/lib/protocols/warcraft3.c
@@ -0,0 +1,100 @@
+/*
+ * warcraft3.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+/* include files */
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_WARCRAFT3
+
+static void ndpi_int_warcraft3_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_WARCRAFT3, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_warcraft3(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ u_int32_t l; /*
+ Leave it as u_int32_t because otherwise 'u_int16_t temp'
+ might overflood it and thus generate an infinite loop
+ */
+
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "search WARCRAFT3\n");
+
+
+ if (flow->packet_counter == 1 && packet->payload_packet_len == 1 && packet->payload[0] == 0x01) {
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "maybe warcraft3: packet_len == 1\n");
+ return;
+ } else if (packet->payload_packet_len >= 4 && (packet->payload[0] == 0xf7 || packet->payload[0] == 0xff)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "packet_payload begins with 0xf7 or 0xff\n");
+
+ l = packet->payload[2] + (packet->payload[3] << 8); // similar to ntohs
+
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "l = %u \n", l);
+
+ while (l <= (packet->payload_packet_len - 4)) {
+ if (packet->payload[l] == 0xf7) {
+ u_int16_t temp = (packet->payload[l + 2 + 1] << 8) + packet->payload[l + 2];
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "another f7 visited.\n");
+
+ if((temp <= 2) || (temp > 1500)) {
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "break\n");
+ break;
+ } else {
+ l += temp;
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "l = %u \n", l);
+ }
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "break\n");
+ break;
+ }
+ }
+
+ if (l == packet->payload_packet_len) {
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "maybe WARCRAFT3\n");
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "flow->packet_counter = %u \n",
+ flow->packet_counter);
+ if (flow->packet_counter > 2) {
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "detected WARCRAFT3\n");
+ ndpi_int_warcraft3_add_connection(ndpi_struct, flow);
+ return;
+ }
+ return;
+ }
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_WARCRAFT3, ndpi_struct, NDPI_LOG_DEBUG, "no warcraft3 detected.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_WARCRAFT3);
+}
+
+#endif
diff --git a/src/lib/protocols/whoisdas.c b/src/lib/protocols/whoisdas.c
new file mode 100644
index 000000000..90fa387d7
--- /dev/null
+++ b/src/lib/protocols/whoisdas.c
@@ -0,0 +1,60 @@
+/*
+ * ssh.c
+ *
+ * Copyright (C) 2013 - ntop.org
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_WHOIS_DAS
+
+void ndpi_search_whois_das(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int16_t sport = ntohs(packet->tcp->source), dport = ntohs(packet->tcp->dest);
+
+ if ((packet->tcp != NULL)
+ && (
+ ((sport == 43) || (dport == 43))
+ ||
+ ((sport == 4343) || (dport == 4343))
+ )
+ ) {
+ if(packet->payload_packet_len > 0) {
+ u_int max_len = sizeof(flow->host_server_name)-1;
+ u_int i, j;
+
+ for(i=strlen((const char *)flow->host_server_name), j=0; (i<max_len) && (j<packet->payload_packet_len); i++, j++) {
+ if((packet->payload[j] == '\n') || (packet->payload[j] == '\r')) break;
+
+ flow->host_server_name[i] = packet->payload[j];
+ }
+
+ flow->host_server_name[i] = '\0';
+ flow->server_id = ((sport == 43) || (sport == 4343)) ? flow->src : flow->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_WHOIS_DAS, ndpi_struct, NDPI_LOG_DEBUG, "[WHOIS/DAS] %s\n", flow->host_server_name);
+ }
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_WHOIS_DAS, NDPI_REAL_PROTOCOL);
+ } else {
+ NDPI_LOG(NDPI_PROTOCOL_WHOIS_DAS, ndpi_struct, NDPI_LOG_TRACE, "WHOIS Excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_WHOIS_DAS);
+ }
+}
+
+#endif
diff --git a/src/lib/protocols/winmx.c b/src/lib/protocols/winmx.c
new file mode 100644
index 000000000..d032150b7
--- /dev/null
+++ b/src/lib/protocols/winmx.c
@@ -0,0 +1,104 @@
+/*
+ * winmx.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+
+#ifdef NDPI_PROTOCOL_WINMX
+
+
+static void ndpi_int_winmx_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow);
+
+static void ndpi_int_winmx_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_WINMX, NDPI_REAL_PROTOCOL);
+}
+
+
+void ndpi_search_winmx_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+
+ if (flow->l4.tcp.winmx_stage == 0) {
+ if (packet->payload_packet_len == 1 || (packet->payload_packet_len > 1 && packet->payload[0] == 0x31)) {
+ return;
+ }
+ /* did not see this pattern in any trace that we have */
+ if (((packet->payload_packet_len) == 4)
+ && (memcmp(packet->payload, "SEND", 4) == 0)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_WINMX, ndpi_struct, NDPI_LOG_DEBUG, "maybe WinMX Send\n");
+ flow->l4.tcp.winmx_stage = 1;
+ return;
+ }
+
+ if (((packet->payload_packet_len) == 3)
+ && (memcmp(packet->payload, "GET", 3) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_WINMX, ndpi_struct, NDPI_LOG_DEBUG, "found winmx by GET\n");
+ ndpi_int_winmx_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+
+ if (packet->payload_packet_len == 149 && packet->payload[0] == '8') {
+ NDPI_LOG(NDPI_PROTOCOL_WINMX, ndpi_struct, NDPI_LOG_DEBUG, "maybe WinMX\n");
+ if (get_u_int32_t(packet->payload, 17) == 0
+ && get_u_int32_t(packet->payload, 21) == 0
+ && get_u_int32_t(packet->payload, 25) == 0
+ && get_u_int16_t(packet->payload, 39) == 0 && get_u_int16_t(packet->payload, 135) == htons(0x7edf)
+ && get_u_int16_t(packet->payload, 147) == htons(0xf792)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_WINMX, ndpi_struct, NDPI_LOG_DEBUG,
+ "found winmx by pattern in first packet\n");
+ ndpi_int_winmx_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ /* did not see this pattern in any trace that we have */
+ } else if (flow->l4.tcp.winmx_stage == 1) {
+ if (packet->payload_packet_len > 10 && packet->payload_packet_len < 1000) {
+ u_int16_t left = packet->payload_packet_len - 1;
+ while (left > 0) {
+ if (packet->payload[left] == ' ') {
+ NDPI_LOG(NDPI_PROTOCOL_WINMX, ndpi_struct, NDPI_LOG_DEBUG, "found winmx in second packet\n");
+ ndpi_int_winmx_add_connection(ndpi_struct, flow);
+ return;
+ } else if (packet->payload[left] < '0' || packet->payload[left] > '9') {
+ break;
+ }
+ left--;
+ }
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_WINMX);
+}
+
+#endif
diff --git a/src/lib/protocols/world_of_kung_fu.c b/src/lib/protocols/world_of_kung_fu.c
new file mode 100644
index 000000000..da35c0aa0
--- /dev/null
+++ b/src/lib/protocols/world_of_kung_fu.c
@@ -0,0 +1,58 @@
+/*
+ * world_of_kung_fu.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+
+/* include files */
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_WORLD_OF_KUNG_FU
+
+static void ndpi_int_world_of_kung_fu_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_WORLD_OF_KUNG_FU, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_world_of_kung_fu(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src=ndpi_struct->src;
+ // struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_WORLD_OF_KUNG_FU, ndpi_struct, NDPI_LOG_DEBUG, "search world_of_kung_fu.\n");
+
+ if ((packet->payload_packet_len == 16)
+ && ntohl(get_u_int32_t(packet->payload, 0)) == 0x0c000000 && ntohl(get_u_int32_t(packet->payload, 4)) == 0xd2000c00
+ && (packet->payload[9]
+ == 0x16) && ntohs(get_u_int16_t(packet->payload, 10)) == 0x0000 && ntohs(get_u_int16_t(packet->payload, 14)) == 0x0000) {
+ NDPI_LOG(NDPI_PROTOCOL_WORLD_OF_KUNG_FU, ndpi_struct, NDPI_LOG_DEBUG, "detected world_of_kung_fu.\n");
+ ndpi_int_world_of_kung_fu_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_WORLD_OF_KUNG_FU, ndpi_struct, NDPI_LOG_DEBUG, "exclude world_of_kung_fu.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_WORLD_OF_KUNG_FU);
+}
+
+#endif
diff --git a/src/lib/protocols/world_of_warcraft.c b/src/lib/protocols/world_of_warcraft.c
new file mode 100644
index 000000000..02afc9d13
--- /dev/null
+++ b/src/lib/protocols/world_of_warcraft.c
@@ -0,0 +1,210 @@
+/*
+ * world_of_warcraft.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_WORLDOFWARCRAFT
+
+
+static void ndpi_int_worldofwarcraft_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_WORLDOFWARCRAFT, protocol_type);
+}
+
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+u_int8_t ndpi_int_is_wow_port(const u_int16_t port)
+{
+ if (port == htons(3724) || port == htons(6112) || port == htons(6113) ||
+ port == htons(6114) || port == htons(4000) || port == htons(1119)) {
+ return 1;
+ }
+ return 0;
+}
+
+void ndpi_search_worldofwarcraft(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct, NDPI_LOG_DEBUG, "Search World of Warcraft.\n");
+
+ if (packet->tcp != NULL) {
+ if ((packet->payload_packet_len > NDPI_STATICSTRING_LEN("POST /") &&
+ memcmp(packet->payload, "POST /", NDPI_STATICSTRING_LEN("POST /")) == 0) ||
+ (packet->payload_packet_len > NDPI_STATICSTRING_LEN("GET /") &&
+ memcmp(packet->payload, "GET /", NDPI_STATICSTRING_LEN("GET /")) == 0)) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->user_agent_line.ptr != NULL &&
+ packet->user_agent_line.len == NDPI_STATICSTRING_LEN("Blizzard Web Client") &&
+ memcmp(packet->user_agent_line.ptr, "Blizzard Web Client",
+ NDPI_STATICSTRING_LEN("Blizzard Web Client")) == 0) {
+ ndpi_int_worldofwarcraft_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct, NDPI_LOG_DEBUG,
+ "World of Warcraft: Web Client found\n");
+ return;
+ }
+ }
+ if (packet->payload_packet_len > NDPI_STATICSTRING_LEN("GET /")
+ && memcmp(packet->payload, "GET /", NDPI_STATICSTRING_LEN("GET /")) == 0) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->user_agent_line.ptr != NULL && packet->host_line.ptr != NULL
+ && packet->user_agent_line.len > NDPI_STATICSTRING_LEN("Blizzard Downloader")
+ && packet->host_line.len > NDPI_STATICSTRING_LEN("worldofwarcraft.com")
+ && memcmp(packet->user_agent_line.ptr, "Blizzard Downloader",
+ NDPI_STATICSTRING_LEN("Blizzard Downloader")) == 0
+ && memcmp(&packet->host_line.ptr[packet->host_line.len - NDPI_STATICSTRING_LEN("worldofwarcraft.com")],
+ "worldofwarcraft.com", NDPI_STATICSTRING_LEN("worldofwarcraft.com")) == 0) {
+ ndpi_int_worldofwarcraft_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct, NDPI_LOG_DEBUG,
+ "World of Warcraft: Web Client found\n");
+ return;
+ }
+ }
+ if (packet->payload_packet_len == 50 && memcmp(&packet->payload[2], "WORLD OF WARCRAFT CONNECTION",
+ NDPI_STATICSTRING_LEN("WORLD OF WARCRAFT CONNECTION")) == 0) {
+ ndpi_int_worldofwarcraft_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct, NDPI_LOG_DEBUG, "World of Warcraft: Login found\n");
+ return;
+ }
+ if (packet->tcp->dest == htons(3724) && packet->payload_packet_len < 70
+ && packet->payload_packet_len > 40 && (memcmp(&packet->payload[4], "WoW", 3) == 0
+ || memcmp(&packet->payload[5], "WoW", 3) == 0)) {
+ ndpi_int_worldofwarcraft_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct, NDPI_LOG_DEBUG, "World of Warcraft: Login found\n");
+ return;
+ }
+
+ if (NDPI_SRC_OR_DST_HAS_PROTOCOL(src, dst, NDPI_PROTOCOL_WORLDOFWARCRAFT) != 0) {
+ if (packet->tcp->source == htons(3724)
+ && packet->payload_packet_len == 8 && get_u_int32_t(packet->payload, 0) == htonl(0x0006ec01)) {
+ ndpi_int_worldofwarcraft_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct,
+ NDPI_LOG_DEBUG, "World of Warcraft: connection detected\n");
+ return;
+ }
+
+ }
+
+ /* for some well known WoW ports
+ check another pattern */
+ if (flow->l4.tcp.wow_stage == 0) {
+ if (ndpi_int_is_wow_port(packet->tcp->source) &&
+ packet->payload_packet_len >= 14 &&
+ ntohs(get_u_int16_t(packet->payload, 0)) == (packet->payload_packet_len - 2)) {
+ if (get_u_int32_t(packet->payload, 2) == htonl(0xec010100)) {
+
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct,
+ NDPI_LOG_DEBUG, "probably World of Warcraft, waiting for final packet\n");
+ flow->l4.tcp.wow_stage = 2;
+ return;
+ } else if (packet->payload_packet_len == 41 &&
+ (get_u_int16_t(packet->payload, 2) == htons(0x0085) ||
+ get_u_int16_t(packet->payload, 2) == htons(0x0034) ||
+ get_u_int16_t(packet->payload, 2) == htons(0x1960))) {
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct,
+ NDPI_LOG_DEBUG, "maybe World of Warcraft, need next\n");
+ flow->l4.tcp.wow_stage = 1;
+ return;
+ }
+ }
+ }
+
+ if (flow->l4.tcp.wow_stage == 1) {
+ if (packet->payload_packet_len == 325 &&
+ ntohs(get_u_int16_t(packet->payload, 0)) == (packet->payload_packet_len - 2) &&
+ get_u_int16_t(packet->payload, 4) == 0 &&
+ (get_u_int16_t(packet->payload, packet->payload_packet_len - 3) == htons(0x2331) ||
+ get_u_int16_t(packet->payload, 67) == htons(0x2331)) &&
+ (memcmp
+ (&packet->payload[packet->payload_packet_len - 18],
+ "\x94\xec\xff\xfd\x67\x62\xd4\x67\xfb\xf9\xdd\xbd\xfd\x01\xc0\x8f\xf9\x81", 18) == 0
+ || memcmp(&packet->payload[packet->payload_packet_len - 30],
+ "\x94\xec\xff\xfd\x67\x62\xd4\x67\xfb\xf9\xdd\xbd\xfd\x01\xc0\x8f\xf9\x81", 18) == 0)) {
+ ndpi_int_worldofwarcraft_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct,
+ NDPI_LOG_DEBUG, "World of Warcraft: connection detected\n");
+ return;
+ }
+ if (packet->payload_packet_len > 32 &&
+ ntohs(get_u_int16_t(packet->payload, 0)) == (packet->payload_packet_len - 2)) {
+ if (get_u_int16_t(packet->payload, 4) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct,
+ NDPI_LOG_DEBUG, "probably World of Warcraft, waiting for final packet\n");
+ flow->l4.tcp.wow_stage = 2;
+ return;
+ } else if (get_u_int32_t(packet->payload, 2) == htonl(0x12050000)) {
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct,
+ NDPI_LOG_DEBUG, "probably World of Warcraft, waiting for final packet\n");
+ flow->l4.tcp.wow_stage = 2;
+ return;
+ }
+ }
+ }
+
+ if (flow->l4.tcp.wow_stage == 2) {
+ if (packet->payload_packet_len == 4) {
+ ndpi_int_worldofwarcraft_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct,
+ NDPI_LOG_DEBUG, "World of Warcraft: connection detected\n");
+ return;
+ } else if (packet->payload_packet_len > 4 && packet->payload_packet_len <= 16 && packet->payload[4] == 0x0c) {
+ ndpi_int_worldofwarcraft_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct,
+ NDPI_LOG_DEBUG, "World of Warcraft: connection detected\n");
+ return;
+ } else if (flow->packet_counter < 3) {
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct, NDPI_LOG_DEBUG, "waiting for final packet\n");
+ return;
+ }
+ }
+ if (flow->l4.tcp.wow_stage == 0 && packet->tcp->dest == htons(1119)) {
+ /* special log in port for battle.net/world of warcraft */
+
+ if (packet->payload_packet_len >= 77 &&
+ get_u_int32_t(packet->payload, 0) == htonl(0x40000aed) && get_u_int32_t(packet->payload, 4) == htonl(0xea070aed)) {
+
+ ndpi_int_worldofwarcraft_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_WORLDOFWARCRAFT, ndpi_struct,
+ NDPI_LOG_DEBUG, "World of Warcraft: connection detected\n");
+ return;
+ }
+ }
+ }
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_WORLDOFWARCRAFT);
+}
+
+#endif
diff --git a/src/lib/protocols/xbox.c b/src/lib/protocols/xbox.c
new file mode 100644
index 000000000..6ee25f05f
--- /dev/null
+++ b/src/lib/protocols/xbox.c
@@ -0,0 +1,103 @@
+/*
+ * xbox.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_XBOX
+
+static void ndpi_int_xbox_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_XBOX, NDPI_REAL_PROTOCOL);
+}
+
+
+void ndpi_search_xbox(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ // struct ndpi_id_struct *src = flow->src;
+ // struct ndpi_id_struct *dst = flow->dst;
+
+ /*
+ * THIS IS TH XBOX UDP DETCTION ONLY !!!
+ * the xbox tcp detection is done by http code
+ */
+
+
+ /* this detection also works for asymmetric xbox udp traffic */
+ if (packet->udp != NULL) {
+
+ u_int16_t dport = ntohs(packet->udp->dest);
+ u_int16_t sport = ntohs(packet->udp->source);
+
+ NDPI_LOG(NDPI_PROTOCOL_XBOX, ndpi_struct, NDPI_LOG_DEBUG, "search xbox\n");
+
+ if (packet->payload_packet_len > 12 &&
+ get_u_int32_t(packet->payload, 0) == 0 && packet->payload[5] == 0x58 &&
+ memcmp(&packet->payload[7], "\x00\x00\x00", 3) == 0) {
+
+ if ((packet->payload[4] == 0x0c && packet->payload[6] == 0x76) ||
+ (packet->payload[4] == 0x02 && packet->payload[6] == 0x18) ||
+ (packet->payload[4] == 0x0b && packet->payload[6] == 0x80) ||
+ (packet->payload[4] == 0x03 && packet->payload[6] == 0x40) ||
+ (packet->payload[4] == 0x06 && packet->payload[6] == 0x4e)) {
+
+ ndpi_int_xbox_add_connection(ndpi_struct, flow);
+ NDPI_LOG(NDPI_PROTOCOL_XBOX, ndpi_struct, NDPI_LOG_DEBUG, "xbox udp connection detected\n");
+ return;
+ }
+ }
+ if ((dport == 3074 || sport == 3074)
+ && ((packet->payload_packet_len == 24 && packet->payload[0] == 0x00)
+ || (packet->payload_packet_len == 42 && packet->payload[0] == 0x4f && packet->payload[2] == 0x0a)
+ || (packet->payload_packet_len == 80 && ntohs(get_u_int16_t(packet->payload, 0)) == 0x50bc
+ && packet->payload[2] == 0x45)
+ || (packet->payload_packet_len == 40 && ntohl(get_u_int32_t(packet->payload, 0)) == 0xcf5f3202)
+ || (packet->payload_packet_len == 38 && ntohl(get_u_int32_t(packet->payload, 0)) == 0xc1457f03)
+ || (packet->payload_packet_len == 28 && ntohl(get_u_int32_t(packet->payload, 0)) == 0x015f2c00))) {
+ if (flow->l4.udp.xbox_stage == 1) {
+ ndpi_int_xbox_add_connection(ndpi_struct, flow);
+ NDPI_LOG(NDPI_PROTOCOL_XBOX, ndpi_struct, NDPI_LOG_DEBUG, "xbox udp connection detected\n");
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_XBOX, ndpi_struct, NDPI_LOG_DEBUG, "maybe xbox.\n");
+ flow->l4.udp.xbox_stage++;
+ return;
+ }
+
+ /* exclude here all non matched udp traffic, exclude here tcp only if http has been excluded, because xbox could use http */
+ if (packet->tcp == NULL
+#ifdef NDPI_PROTOCOL_HTTP
+ || NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_HTTP) != 0
+#endif
+ ) {
+ NDPI_LOG(NDPI_PROTOCOL_XBOX, ndpi_struct, NDPI_LOG_DEBUG, "xbox udp excluded.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_XBOX);
+ }
+ }
+ /* to not exclude tcp traffic here, done by http code... */
+}
+
+#endif
diff --git a/src/lib/protocols/xdmcp.c b/src/lib/protocols/xdmcp.c
new file mode 100644
index 000000000..dcbcfd231
--- /dev/null
+++ b/src/lib/protocols/xdmcp.c
@@ -0,0 +1,69 @@
+/*
+ * xdmcp.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_protocols.h"
+#ifdef NDPI_PROTOCOL_XDMCP
+
+
+static void ndpi_int_xdmcp_add_connection(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_XDMCP, NDPI_REAL_PROTOCOL);
+}
+
+void ndpi_search_xdmcp(struct ndpi_detection_module_struct
+ *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+// struct ndpi_id_struct *src=ndpi_struct->src;
+// struct ndpi_id_struct *dst=ndpi_struct->dst;
+
+ NDPI_LOG(NDPI_PROTOCOL_XDMCP, ndpi_struct, NDPI_LOG_DEBUG, "search xdmcp.\n");
+
+ if (packet->tcp != NULL && (ntohs(packet->tcp->dest) >= 6000 && ntohs(packet->tcp->dest) <= 6005)
+ && packet->payload_packet_len == 48
+ && packet->payload[0] == 0x6c && packet->payload[1] == 0x00
+ && ntohs(get_u_int16_t(packet->payload, 6)) == 0x1200 && ntohs(get_u_int16_t(packet->payload, 8)) == 0x1000) {
+
+ NDPI_LOG(NDPI_PROTOCOL_XDMCP, ndpi_struct, NDPI_LOG_DEBUG, "found xdmcp over tcp.\n");
+ ndpi_int_xdmcp_add_connection(ndpi_struct, flow);
+ return;
+ }
+ if (packet->udp != NULL && ntohs(packet->udp->dest) == 177
+ && packet->payload_packet_len >= 6 && packet->payload_packet_len == 6 + ntohs(get_u_int16_t(packet->payload, 4))
+ && ntohs(get_u_int16_t(packet->payload, 0)) == 0x0001 && ntohs(get_u_int16_t(packet->payload, 2)) == 0x0002) {
+
+ NDPI_LOG(NDPI_PROTOCOL_XDMCP, ndpi_struct, NDPI_LOG_DEBUG, "found xdmcp over udp.\n");
+ ndpi_int_xdmcp_add_connection(ndpi_struct, flow);
+ return;
+ }
+
+
+ NDPI_LOG(NDPI_PROTOCOL_XDMCP, ndpi_struct, NDPI_LOG_DEBUG, "exclude xdmcp.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_XDMCP);
+}
+
+#endif
diff --git a/src/lib/protocols/yahoo.c b/src/lib/protocols/yahoo.c
new file mode 100644
index 000000000..c5d340bc1
--- /dev/null
+++ b/src/lib/protocols/yahoo.c
@@ -0,0 +1,434 @@
+/*
+ * yahoo.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_YAHOO
+
+
+struct ndpi_yahoo_header {
+ u_int8_t YMSG_str[4];
+ u_int16_t version;
+ u_int16_t nothing0;
+ u_int16_t len;
+ u_int16_t service;
+ u_int32_t status;
+ u_int32_t session_id;
+};
+
+/* This function checks the pattern '<Ymsg Command=' in line 8 of parsed lines or
+ * in the payload*/
+static u_int8_t ndpi_check_for_YmsgCommand(u_int16_t len, const u_int8_t * ptr)
+{
+ u_int16_t i;
+
+ for (i = 0; i < len - 12; i++) {
+ if (ptr[i] == 'Y') {
+ if (memcmp(&ptr[i + 1], "msg Command=", 12) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static void ndpi_int_yahoo_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow, ndpi_protocol_type_t protocol_type)
+{
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_YAHOO, protocol_type);
+}
+
+
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+u_int8_t check_ymsg(const u_int8_t * payload, u_int16_t payload_packet_len)
+{
+
+ const struct ndpi_yahoo_header *yahoo = (struct ndpi_yahoo_header *) payload;
+
+ u_int16_t yahoo_len_parsed = 0;
+ do {
+ u_int16_t ylen = ntohs(yahoo->len);
+
+ yahoo_len_parsed += 20 + ylen; /* possible overflow here: 20 + ylen = 0x10000 --> 0 --> infinite loop */
+
+ if (ylen >= payload_packet_len || yahoo_len_parsed >= payload_packet_len)
+ break;
+
+ yahoo = (struct ndpi_yahoo_header *) (payload + yahoo_len_parsed);
+ }
+ while (memcmp(yahoo->YMSG_str, "YMSG", 4) == 0);
+
+ if (yahoo_len_parsed == payload_packet_len)
+ return 1;
+ return 0;
+}
+
+static void ndpi_search_yahoo_tcp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ const struct ndpi_yahoo_header *yahoo = (struct ndpi_yahoo_header *) packet->payload;
+ if (packet->payload_packet_len == 0) {
+ return;
+ }
+
+ /* packet must be at least 20 bytes long */
+ if (packet->payload_packet_len >= 20
+ && memcmp(yahoo->YMSG_str, "YMSG", 4) == 0 && ((packet->payload_packet_len - 20) == ntohs(yahoo->len)
+ || check_ymsg(packet->payload, packet->payload_packet_len))) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_TRACE, "YAHOO FOUND\n");
+ flow->yahoo_detection_finished = 2;
+ if (ntohs(yahoo->service) == 24 || ntohs(yahoo->service) == 152 || ntohs(yahoo->service) == 74) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_TRACE, "YAHOO conference or chat invite found");
+ if (src != NULL) {
+ src->yahoo_conf_logged_in = 1;
+ }
+ if (dst != NULL) {
+ dst->yahoo_conf_logged_in = 1;
+ }
+ }
+ if (ntohs(yahoo->service) == 27 || ntohs(yahoo->service) == 155 || ntohs(yahoo->service) == 160) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_TRACE, "YAHOO conference or chat logoff found");
+ if (src != NULL) {
+ src->yahoo_conf_logged_in = 0;
+ src->yahoo_voice_conf_logged_in = 0;
+ }
+ }
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ } else if (flow->yahoo_detection_finished == 2 && packet->detected_protocol_stack[0] == NDPI_PROTOCOL_YAHOO) {
+ return;
+ } else if (packet->payload_packet_len == 4 && memcmp(yahoo->YMSG_str, "YMSG", 4) == 0) {
+ flow->l4.tcp.yahoo_sip_comm = 1;
+ return;
+ } else if (flow->l4.tcp.yahoo_sip_comm && packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN
+ && flow->packet_counter < 3) {
+ return;
+ }
+
+ /* now test for http login, at least 100 a bytes packet */
+ if (ndpi_struct->yahoo_detect_http_connections != 0 && packet->payload_packet_len > 100) {
+ if (memcmp(packet->payload, "POST /relay?token=", 18) == 0
+ || memcmp(packet->payload, "GET /relay?token=", 17) == 0
+ || memcmp(packet->payload, "GET /?token=", 12) == 0
+ || memcmp(packet->payload, "HEAD /relay?token=", 18) == 0) {
+ if ((src != NULL
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, NDPI_PROTOCOL_YAHOO)
+ != 0) || (dst != NULL
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, NDPI_PROTOCOL_YAHOO)
+ != 0)) {
+ /* this is mostly a file transfer */
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ if (memcmp(packet->payload, "POST ", 5) == 0) {
+ u_int16_t a;
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+
+ if ((packet->user_agent_line.len >= 21)
+ && (memcmp(packet->user_agent_line.ptr, "YahooMobileMessenger/", 21) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO(Mobile)");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+
+ if (NDPI_SRC_OR_DST_HAS_PROTOCOL(src, dst, NDPI_PROTOCOL_YAHOO)
+ && packet->parsed_lines > 5
+ && memcmp(&packet->payload[5], "/Messenger.", 11) == 0
+ && packet->line[1].len >= 17
+ && memcmp(packet->line[1].ptr, "Connection: Close",
+ 17) == 0 && packet->line[2].len >= 6
+ && memcmp(packet->line[2].ptr, "Host: ", 6) == 0
+ && packet->line[3].len >= 16
+ && memcmp(packet->line[3].ptr, "Content-Length: ",
+ 16) == 0 && packet->line[4].len >= 23
+ && memcmp(packet->line[4].ptr, "User-Agent: Mozilla/5.0",
+ 23) == 0 && packet->line[5].len >= 23
+ && memcmp(packet->line[5].ptr, "Cache-Control: no-cache", 23) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_TRACE,
+ "YAHOO HTTP POST P2P FILETRANSFER FOUND\n");
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+
+ if (packet->host_line.ptr != NULL && packet->host_line.len >= 26 &&
+ memcmp(packet->host_line.ptr, "filetransfer.msg.yahoo.com", 26) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_TRACE, "YAHOO HTTP POST FILETRANSFER FOUND\n");
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ /* now check every line */
+ for (a = 0; a < packet->parsed_lines; a++) {
+ if (packet->line[a].len >= 4 && memcmp(packet->line[a].ptr, "YMSG", 4) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct,
+ NDPI_LOG_TRACE,
+ "YAHOO HTTP POST FOUND, line is: %.*s\n", packet->line[a].len, packet->line[a].ptr);
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ if (packet->parsed_lines > 8 && packet->line[8].len > 250 && packet->line[8].ptr != NULL) {
+ if (memcmp(packet->line[8].ptr, "<Session ", 9) == 0) {
+ if (ndpi_check_for_YmsgCommand(packet->line[8].len, packet->line[8].ptr)) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG,
+ "found HTTP Proxy Yahoo Chat <Ymsg Command= pattern \n");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+ }
+ if (memcmp(packet->payload, "GET /Messenger.", 15) == 0) {
+ if ((src != NULL
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, NDPI_PROTOCOL_YAHOO)
+ != 0) || (dst != NULL
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, NDPI_PROTOCOL_YAHOO)
+ != 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_TRACE, "YAHOO HTTP GET /Messenger. match\n");
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+
+ if ((memcmp(packet->payload, "GET /", 5) == 0)) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if ((packet->user_agent_line.ptr != NULL
+ && packet->user_agent_line.len >= NDPI_STATICSTRING_LEN("YahooMobileMessenger/")
+ && memcmp(packet->user_agent_line.ptr, "YahooMobileMessenger/",
+ NDPI_STATICSTRING_LEN("YahooMobileMessenger/")) == 0)
+ || (packet->user_agent_line.len >= 15
+ && (memcmp(packet->user_agent_line.ptr, "Y!%20Messenger/", 15) == 0))) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO(Mobile)");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ if (packet->host_line.ptr != NULL && packet->host_line.len >= NDPI_STATICSTRING_LEN("msg.yahoo.com") &&
+ memcmp(&packet->host_line.ptr[packet->host_line.len - NDPI_STATICSTRING_LEN("msg.yahoo.com")],
+ "msg.yahoo.com", NDPI_STATICSTRING_LEN("msg.yahoo.com")) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+
+ }
+
+ }
+ /* found another http login command for yahoo, it is like OSCAR */
+ /* detect http connections */
+
+ if (packet->payload_packet_len > 50 && (memcmp(packet->payload, "content-length: ", 16) == 0)) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (packet->parsed_lines > 2 && packet->line[1].len == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_TRACE, "first line is empty.\n");
+ if (packet->line[2].len > 13 && memcmp(packet->line[2].ptr, "<Ymsg Command=", 14) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_TRACE, "YAHOO web chat found\n");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ }
+ }
+
+ if (packet->payload_packet_len > 38 && memcmp(packet->payload, "CONNECT scs.msg.yahoo.com:5050 HTTP/1.", 38) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_TRACE, "YAHOO-HTTP FOUND\n");
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+
+ if ((src != NULL && NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, NDPI_PROTOCOL_YAHOO) != 0)
+ || (dst != NULL
+ && NDPI_COMPARE_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, NDPI_PROTOCOL_YAHOO) != 0)) {
+ if (packet->payload_packet_len == 6 && memcmp(packet->payload, "YAHOO!", 6) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ /* asymmetric detection for SNDIMG not done yet.
+ * See ./Yahoo8.1-VideoCall-LAN.pcap and ./Yahoo-VideoCall-inPublicIP.pcap */
+
+
+ if (packet->payload_packet_len == 8
+ && (memcmp(packet->payload, "<SNDIMG>", 8) == 0 || memcmp(packet->payload, "<REQIMG>", 8) == 0
+ || memcmp(packet->payload, "<RVWCFG>", 8) == 0 || memcmp(packet->payload, "<RUPCFG>", 8) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_TRACE,
+ "YAHOO SNDIMG or REQIMG or RVWCFG or RUPCFG FOUND\n");
+ if (src != NULL) {
+ if (memcmp(packet->payload, "<SNDIMG>", 8) == 0) {
+ src->yahoo_video_lan_dir = 0;
+ } else {
+ src->yahoo_video_lan_dir = 1;
+ }
+ src->yahoo_video_lan_timer = packet->tick_timestamp;
+ }
+ if (dst != NULL) {
+ if (memcmp(packet->payload, "<SNDIMG>", 8) == 0) {
+ dst->yahoo_video_lan_dir = 0;
+ } else {
+ dst->yahoo_video_lan_dir = 1;
+ }
+ dst->yahoo_video_lan_timer = packet->tick_timestamp;
+
+ }
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO subtype VIDEO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ if (src != NULL && packet->tcp->dest == htons(5100)
+ && ((u_int32_t)
+ (packet->tick_timestamp - src->yahoo_video_lan_timer) < ndpi_struct->yahoo_lan_video_timeout)) {
+ if (src->yahoo_video_lan_dir == 1) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "IMG MARKED");
+ return;
+ }
+
+ }
+ if (dst != NULL && packet->tcp->dest == htons(5100)
+ && ((u_int32_t)
+ (packet->tick_timestamp - dst->yahoo_video_lan_timer) < ndpi_struct->yahoo_lan_video_timeout)) {
+ if (dst->yahoo_video_lan_dir == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "IMG MARKED");
+ return;
+ }
+
+ }
+ }
+
+ /* detect YAHOO over HTTP proxy */
+#ifdef NDPI_PROTOCOL_HTTP
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP)
+#endif
+ {
+
+ if (flow->l4.tcp.yahoo_http_proxy_stage == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG,
+ "YAHOO maybe HTTP proxy packet 1 => need next packet\n");
+ flow->l4.tcp.yahoo_http_proxy_stage = 1 + packet->packet_direction;
+ return;
+ }
+ if (flow->l4.tcp.yahoo_http_proxy_stage == 1 + packet->packet_direction) {
+ if ((packet->payload_packet_len > 250) && (memcmp(packet->payload, "<Session ", 9) == 0)) {
+ if (ndpi_check_for_YmsgCommand(packet->payload_packet_len, packet->payload)) {
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG,
+ "found HTTP Proxy Yahoo Chat <Ymsg Command= pattern \n");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG,
+ "YAHOO maybe HTTP proxy still initial direction => need next packet\n");
+ return;
+ }
+ if (flow->l4.tcp.yahoo_http_proxy_stage == 2 - packet->packet_direction) {
+
+ ndpi_parse_packet_line_info_any(ndpi_struct, flow);
+
+ if (packet->parsed_lines >= 9) {
+
+ if (packet->line[4].ptr != NULL && packet->line[4].len >= 9 &&
+ packet->line[8].ptr != NULL && packet->line[8].len >= 6 &&
+ memcmp(packet->line[4].ptr, "<Session ", 9) == 0 &&
+ memcmp(packet->line[8].ptr, "<Ymsg ", 6) == 0) {
+
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "found YAHOO over HTTP proxy");
+ ndpi_int_yahoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ }
+ }
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_YAHOO);
+}
+
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+void ndpi_search_yahoo_udp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+
+
+
+ struct ndpi_id_struct *src = flow->src;
+ if (src == NULL || NDPI_COMPARE_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, NDPI_PROTOCOL_YAHOO) == 0) {
+ goto excl_yahoo_udp;
+ }
+ excl_yahoo_udp:
+
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_YAHOO);
+}
+
+void ndpi_search_yahoo(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+
+ NDPI_LOG(NDPI_PROTOCOL_YAHOO, ndpi_struct, NDPI_LOG_DEBUG, "search yahoo\n");
+
+ if (packet->payload_packet_len > 0 && flow->yahoo_detection_finished == 0) {
+ if (packet->tcp != NULL && packet->tcp_retransmission == 0) {
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN
+#ifdef NDPI_PROTOCOL_HTTP
+ || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_HTTP
+#endif
+#ifdef NDPI_PROTOCOL_SSL
+ || packet->detected_protocol_stack[0] == NDPI_PROTOCOL_SSL
+#endif
+ ) {
+ ndpi_search_yahoo_tcp(ndpi_struct, flow);
+ }
+ } else if (packet->udp != NULL) {
+ ndpi_search_yahoo_udp(ndpi_struct, flow);
+ }
+ }
+ if (packet->payload_packet_len > 0 && flow->yahoo_detection_finished == 2) {
+ if (packet->tcp != NULL && packet->tcp_retransmission == 0) {
+ ndpi_search_yahoo_tcp(ndpi_struct, flow);
+ }
+ }
+}
+#endif
diff --git a/src/lib/protocols/zattoo.c b/src/lib/protocols/zattoo.c
new file mode 100644
index 000000000..f7de4a8e7
--- /dev/null
+++ b/src/lib/protocols/zattoo.c
@@ -0,0 +1,235 @@
+/*
+ * zattoo.c
+ *
+ * Copyright (C) 2009-2011 by ipoque GmbH
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * This file is part of nDPI, an open source deep packet inspection
+ * library based on the OpenDPI and PACE technology by ipoque GmbH
+ *
+ * nDPI is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_ZATTOO
+
+static void ndpi_int_zattoo_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ ndpi_protocol_type_t protocol_type)
+{
+
+ struct ndpi_packet_struct *packet = &flow->packet;
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_ZATTOO, protocol_type);
+
+ if (src != NULL) {
+ src->zattoo_ts = packet->tick_timestamp;
+ }
+ if (dst != NULL) {
+ dst->zattoo_ts = packet->tick_timestamp;
+ }
+}
+
+
+
+#if !defined(WIN32)
+static inline
+#else
+__forceinline static
+#endif
+u_int8_t ndpi_int_zattoo_user_agent_set(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ if (flow->packet.user_agent_line.ptr != NULL && flow->packet.user_agent_line.len == 111) {
+ if (memcmp(flow->packet.user_agent_line.ptr +
+ flow->packet.user_agent_line.len - 25, "Zattoo/4", sizeof("Zattoo/4") - 1) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct, NDPI_LOG_DEBUG, "found zattoo useragent\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void ndpi_search_zattoo(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
+{
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+
+ struct ndpi_id_struct *src = flow->src;
+ struct ndpi_id_struct *dst = flow->dst;
+
+ u_int16_t i;
+
+ if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_ZATTOO) {
+ if (src != NULL && ((u_int32_t)
+ (packet->tick_timestamp - src->zattoo_ts) < ndpi_struct->zattoo_connection_timeout)) {
+ src->zattoo_ts = packet->tick_timestamp;
+ }
+ if (dst != NULL && ((u_int32_t)
+ (packet->tick_timestamp - dst->zattoo_ts) < ndpi_struct->zattoo_connection_timeout)) {
+ dst->zattoo_ts = packet->tick_timestamp;
+ }
+ return;
+ }
+
+ if (packet->tcp != NULL) {
+ if (packet->payload_packet_len > 50 && memcmp(packet->payload, "GET /frontdoor/fd?brand=Zattoo&v=", 33) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct,
+ NDPI_LOG_DEBUG, "add connection over tcp with pattern GET /frontdoor/fd?brand=Zattoo&v=\n");
+ ndpi_int_zattoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len > 50
+ && memcmp(packet->payload, "GET /ZattooAdRedirect/redirect.jsp?user=", 40) == 0) {
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct,
+ NDPI_LOG_DEBUG, "add connection over tcp with pattern GET /ZattooAdRedirect/redirect.jsp?user=\n");
+ ndpi_int_zattoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ if (packet->payload_packet_len > 50
+ && (memcmp(packet->payload, "POST /channelserver/player/channel/update HTTP/1.1", 50) == 0
+ || memcmp(packet->payload, "GET /epg/query", 14) == 0)) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ for (i = 0; i < packet->parsed_lines; i++) {
+ if (packet->line[i].len >= 18 && (memcmp(packet->line[i].ptr, "User-Agent: Zattoo", 18) == 0)) {
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct,
+ NDPI_LOG_DEBUG,
+ "add connection over tcp with pattern POST /channelserver/player/channel/update HTTP/1.1\n");
+ ndpi_int_zattoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ } else if (packet->payload_packet_len > 50
+ && (memcmp(packet->payload, "GET /", 5) == 0
+ || memcmp(packet->payload, "POST /", NDPI_STATICSTRING_LEN("POST /")) == 0)) {
+ /* TODO to avoid searching currently only a specific length and offset is used
+ * that might be changed later */
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ if (ndpi_int_zattoo_user_agent_set(ndpi_struct, flow)) {
+ ndpi_int_zattoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ } else if (packet->payload_packet_len > 50 && memcmp(packet->payload, "POST http://", 12) == 0) {
+ ndpi_parse_packet_line_info(ndpi_struct, flow);
+ // test for unique character of the zattoo header
+ if (packet->parsed_lines == 4 && packet->host_line.ptr != NULL) {
+ u_int32_t ip;
+ u_int16_t bytes_read = 0;
+
+ ip = ndpi_bytestream_to_ipv4(&packet->payload[12], packet->payload_packet_len, &bytes_read);
+
+ // and now test the firt 5 bytes of the payload for zattoo pattern
+ if (ip == packet->iph->daddr
+ && packet->empty_line_position_set != 0
+ && ((packet->payload_packet_len - packet->empty_line_position) > 10)
+ && packet->payload[packet->empty_line_position + 2] ==
+ 0x03
+ && packet->payload[packet->empty_line_position + 3] ==
+ 0x04
+ && packet->payload[packet->empty_line_position + 4] ==
+ 0x00
+ && packet->payload[packet->empty_line_position + 5] ==
+ 0x04
+ && packet->payload[packet->empty_line_position + 6] ==
+ 0x0a && packet->payload[packet->empty_line_position + 7] == 0x00) {
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct,
+ NDPI_LOG_DEBUG, "add connection over tcp with pattern POST http://\n");
+ ndpi_int_zattoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ }
+ } else if (flow->zattoo_stage == 0) {
+
+ if (packet->payload_packet_len > 50
+ && packet->payload[0] == 0x03
+ && packet->payload[1] == 0x04
+ && packet->payload[2] == 0x00
+ && packet->payload[3] == 0x04 && packet->payload[4] == 0x0a && packet->payload[5] == 0x00) {
+ flow->zattoo_stage = 1 + packet->packet_direction;
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct,
+ NDPI_LOG_DEBUG, "need next packet, seen pattern 0x030400040a00\n");
+ return;
+ }
+ /* the following is is searching for flash, not for zattoo. cust1 wants to do so. */
+ } else if (flow->zattoo_stage == 2 - packet->packet_direction
+ && packet->payload_packet_len > 50 && packet->payload[0] == 0x03 && packet->payload[1] == 0x04) {
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct, NDPI_LOG_DEBUG, "add connection over tcp with 0x0304.\n");
+ ndpi_int_zattoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ } else if (flow->zattoo_stage == 1 + packet->packet_direction) {
+ if (packet->payload_packet_len > 500 && packet->payload[0] == 0x00 && packet->payload[1] == 0x00) {
+ flow->zattoo_stage = 3 + packet->packet_direction;
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct,
+ NDPI_LOG_DEBUG, "need next packet, seen pattern 0x0000\n");
+ return;
+ }
+ if (packet->payload_packet_len > 50
+ && packet->payload[0] == 0x03
+ && packet->payload[1] == 0x04
+ && packet->payload[2] == 0x00
+ && packet->payload[3] == 0x04 && packet->payload[4] == 0x0a && packet->payload[5] == 0x00) {
+ }
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct, NDPI_LOG_DEBUG,
+ "need next packet, seen pattern 0x030400040a00\n");
+ return;
+ } else if (flow->zattoo_stage == 4 - packet->packet_direction
+ && packet->payload_packet_len > 50 && packet->payload[0] == 0x03 && packet->payload[1] == 0x04) {
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct, NDPI_LOG_DEBUG, "add connection over tcp with 0x0304.\n");
+ ndpi_int_zattoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ } else if (flow->zattoo_stage == 5 + packet->packet_direction && (packet->payload_packet_len == 125)) {
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct, NDPI_LOG_DEBUG, "detected zattoo.\n");
+ ndpi_int_zattoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ } else if (flow->zattoo_stage == 6 - packet->packet_direction && packet->payload_packet_len == 1412) {
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct, NDPI_LOG_DEBUG, "found zattoo.\n");
+ ndpi_int_zattoo_add_connection(ndpi_struct, flow, NDPI_CORRELATED_PROTOCOL);
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct, NDPI_LOG_DEBUG,
+ "ZATTOO: discarted the flow (TCP): packet_size: %u; Flowstage: %u\n",
+ packet->payload_packet_len, flow->zattoo_stage);
+
+ } else if (packet->udp != NULL) {
+
+ if (packet->payload_packet_len > 20 && (packet->udp->dest == htons(5003)
+ || packet->udp->source == htons(5003))
+ && (get_u_int16_t(packet->payload, 0) == htons(0x037a)
+ || get_u_int16_t(packet->payload, 0) == htons(0x0378)
+ || get_u_int16_t(packet->payload, 0) == htons(0x0305)
+ || get_u_int32_t(packet->payload, 0) == htonl(0x03040004)
+ || get_u_int32_t(packet->payload, 0) == htonl(0x03010005))) {
+ if (++flow->zattoo_stage == 2) {
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct, NDPI_LOG_DEBUG, "add connection over udp.\n");
+ ndpi_int_zattoo_add_connection(ndpi_struct, flow, NDPI_REAL_PROTOCOL);
+ return;
+ }
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct, NDPI_LOG_DEBUG, "need next packet udp.\n");
+ return;
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct, NDPI_LOG_DEBUG,
+ "ZATTOO: discarded the flow (UDP): packet_size: %u; Flowstage: %u\n",
+ packet->payload_packet_len, flow->zattoo_stage);
+
+ }
+
+ NDPI_LOG(NDPI_PROTOCOL_ZATTOO, ndpi_struct, NDPI_LOG_DEBUG, "exclude zattoo.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_ZATTOO);
+}
+#endif
diff --git a/src/lib/protocols/zmq.c b/src/lib/protocols/zmq.c
new file mode 100644
index 000000000..12548a2ed
--- /dev/null
+++ b/src/lib/protocols/zmq.c
@@ -0,0 +1,100 @@
+/*
+ * zmq.c
+ *
+ * Copyright (C) 2011-15 - ntop.org
+ *
+ * nDPI is free software: you can zmqtribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * nDPI 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include "ndpi_api.h"
+
+#ifdef NDPI_PROTOCOL_ZMQ
+
+static void ndpi_int_zmq_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_ZMQ, NDPI_REAL_PROTOCOL);
+ NDPI_LOG(NDPI_PROTOCOL_ZMQ, ndpi_struct, NDPI_LOG_TRACE, "ZMQ Found.\n");
+}
+
+
+static void ndpi_check_zmq(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+ u_int32_t payload_len = packet->payload_packet_len;
+ u_char p0[] = { 0x00, 0x00, 0x00, 0x05, 0x01, 0x66, 0x6c, 0x6f, 0x77 };
+ u_char p1[] = { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f };
+ u_char p2[] = { 0x28, 0x66, 0x6c, 0x6f, 0x77, 0x00 };
+
+ if(payload_len == 0) return; /* Shouldn't happen */
+
+ /* Break after 17 packets. */
+ if(flow->packet_counter > 17) {
+ NDPI_LOG(NDPI_PROTOCOL_ZMQ, ndpi_struct, NDPI_LOG_TRACE, "Exclude ZMQ.\n");
+ NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_ZMQ);
+ return;
+ }
+
+ if(flow->l4.tcp.prev_zmq_pkt_len == 0) {
+ flow->l4.tcp.prev_zmq_pkt_len = ndpi_min(packet->payload_packet_len, 10);
+ memcpy(flow->l4.tcp.prev_zmq_pkt, packet->payload, flow->l4.tcp.prev_zmq_pkt_len);
+ return; /* Too early */
+ }
+
+ if(payload_len == 2) {
+ if(flow->l4.tcp.prev_zmq_pkt_len == 2) {
+ if((memcmp(packet->payload, "\01\01", 2) == 0)
+ && (memcmp(flow->l4.tcp.prev_zmq_pkt, "\01\02", 2) == 0)) {
+ ndpi_int_zmq_add_connection(ndpi_struct, flow);
+ return;
+ }
+ } else if(flow->l4.tcp.prev_zmq_pkt_len == 9) {
+ if((memcmp(packet->payload, "\00\00", 2) == 0)
+ && (memcmp(flow->l4.tcp.prev_zmq_pkt, p0, 9) == 0)) {
+ ndpi_int_zmq_add_connection(ndpi_struct, flow);
+ return;
+ }
+ } else if(flow->l4.tcp.prev_zmq_pkt_len == 10) {
+ if((memcmp(packet->payload, "\01\02", 2) == 0)
+ && (memcmp(flow->l4.tcp.prev_zmq_pkt, p1, 10) == 0)) {
+ ndpi_int_zmq_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ } else if(payload_len >= 10) {
+ if(flow->l4.tcp.prev_zmq_pkt_len == 10) {
+ if(((memcmp(packet->payload, p1, 10) == 0)
+ && (memcmp(flow->l4.tcp.prev_zmq_pkt, p1, 10) == 0))
+ || ((memcmp(&packet->payload[1], p2, sizeof(p2)) == 0)
+ && (memcmp(&flow->l4.tcp.prev_zmq_pkt[1], p2, sizeof(p2)) == 0))) {
+ ndpi_int_zmq_add_connection(ndpi_struct, flow);
+ return;
+ }
+ }
+ }
+}
+
+void ndpi_search_zmq(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ NDPI_LOG(NDPI_PROTOCOL_ZMQ, ndpi_struct, NDPI_LOG_TRACE, "ZMQ detection...\n");
+
+ /* skip marked packets */
+ if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_ZMQ) {
+ if (packet->tcp_retransmission == 0) {
+ ndpi_check_zmq(ndpi_struct, flow);
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/third_party/include/actypes.h b/src/lib/third_party/include/actypes.h
new file mode 100644
index 000000000..1900ae9a0
--- /dev/null
+++ b/src/lib/third_party/include/actypes.h
@@ -0,0 +1,135 @@
+/*
+ * actypes.h: Includes basic data types of ahocorasick library
+ * This file is part of multifast.
+ *
+ Copyright 2010-2012 Kamiar Kanani <kamiar.kanani@gmail.com>
+
+ multifast is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ multifast 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with multifast. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _AC_TYPES_H_
+#define _AC_TYPES_H_
+
+/* AC_ALPHABET_t:
+ * defines the alphabet type.
+ * Actually defining AC_ALPHABET_t as a char will work, but sometimes we deal
+ * with streams of other (bigger) types e.g. integers, specific enum, objects.
+ * Although they consists of string of bytes (chars), but using their specific
+ * types for AC_ALPHABET_t will lead to a better performance. so instead of
+ * dealing with strings of chars, we assume dealing with strings of
+ * AC_ALPHABET_t and leave it optional for other developers to define their
+ * own alphabets.
+ **/
+typedef char AC_ALPHABET_t;
+
+/* AC_REP_t:
+ * Provides a more readable representative for a pattern.
+ * because patterns themselves are not always suitable for displaying
+ * (e.g. for hex patterns), we offer this type to improve intelligibility
+ * of output. furthermore, sometimes it is useful, for example while
+ * retrieving patterns from a database, to maintain their identifiers in the
+ * automata for further reference. we provisioned two possible types as a
+ * union for this purpose. you can add your desired type in it.
+ **/
+typedef union {
+ char * stringy; /* null-terminated string */
+ unsigned long number;
+} AC_REP_t;
+
+/* AC_PATTERN_t:
+ * This is the pattern type that must be fed into AC automata.
+ * the 'astring' field is not null-terminated, due to it can contain zero
+ * value bytes. the 'length' field determines the number of AC_ALPHABET_t it
+ * carries. the 'representative' field is described in AC_REP_t. despite
+ * 'astring', 'representative' can have duplicate values for different given
+ * AC_PATTERN_t. it is an optional field and you can just fill it with 0.
+ * CAUTION:
+ * Not always the 'astring' points to the correct position in memory.
+ * it is the responsibility of your program to maintain a permanent allocation
+ * for astring field of the added pattern to automata.
+ **/
+typedef struct
+{
+ AC_ALPHABET_t * astring; /* String of alphabets */
+ unsigned int length; /* Length of pattern */
+ AC_REP_t rep; /* Representative string (optional) */
+} AC_PATTERN_t;
+
+/* AC_TEXT_t:
+ * The input text type that is fed to ac_automata_search() to be searched.
+ * it is similar to AC_PATTERN_t. actually we could use AC_PATTERN_t as input
+ * text, but for the purpose of being more readable, we defined this new type.
+ **/
+typedef struct
+{
+ AC_ALPHABET_t * astring; /* String of alphabets */
+ unsigned int length; /* Length of string */
+} AC_TEXT_t;
+
+/* AC_MATCH_t:
+ * Provides the structure for reporting a match event.
+ * a match event occurs when the automata reaches a final node. any final
+ * node can match one or more pattern at a position in a text. the
+ * 'patterns' field holds these matched patterns. obviously these
+ * matched patterns have same end-position in the text. there is a relationship
+ * between matched patterns: the shorter one is a factor (tail) of the longer
+ * one. the 'position' maintains the end position of matched patterns. the
+ * start position of patterns could be found by knowing their 'length' in
+ * AC_PATTERN_t. e.g. suppose "recent" and "cent" are matched at
+ * position 40 in the text, then the start position of them are 34 and 36
+ * respectively. finally the field 'match_num' maintains the number of
+ * matched patterns.
+ **/
+typedef struct
+{
+ AC_PATTERN_t * patterns; /* Array of matched pattern */
+ long position; /* The end position of matching pattern(s) in the text */
+ unsigned int match_num; /* Number of matched patterns */
+} AC_MATCH_t;
+
+/* AC_ERROR_t:
+ * Error that may occur while adding a pattern to the automata.
+ * it is returned by ac_automata_add().
+ **/
+typedef enum
+ {
+ ACERR_SUCCESS = 0, /* No error occurred */
+ ACERR_DUPLICATE_PATTERN, /* Duplicate patterns */
+ ACERR_LONG_PATTERN, /* Pattern length is longer than AC_PATTRN_MAX_LENGTH */
+ ACERR_ZERO_PATTERN, /* Empty pattern (zero length) */
+ ACERR_AUTOMATA_CLOSED, /* Automata is closed. after calling
+ ac_automata_finalize() you can not add new patterns to the automata. */
+ } AC_ERROR_t;
+
+/* MATCH_CALBACK_t:
+ * This is the call-back function type that must be given to automata at
+ * initialization to report match occurrence to the caller.
+ * at a match event, the automata will reach you using this function and sends
+ * you a pointer to AC_MATCH_t. using that pointer you can handle
+ * matches. you can send parameters to the call-back function when you call
+ * ac_automata_search(). at call-back, the automata will sent you those
+ * parameters as the second parameter (void *) of MATCH_CALBACK_t. inside
+ * the call-back function you can cast it to whatever you want.
+ * If you return 0 from MATCH_CALBACK_t function to the automata, it will
+ * continue searching, otherwise it will return from ac_automata_search()
+ * to your calling function.
+ **/
+typedef int (*MATCH_CALBACK_f)(AC_MATCH_t *, void *);
+
+/* AC_PATTRN_MAX_LENGTH:
+ * Maximum acceptable pattern length in AC_PATTERN_t.length
+ **/
+#define AC_PATTRN_MAX_LENGTH 1024
+
+#endif
diff --git a/src/lib/third_party/include/ahocorasick.h b/src/lib/third_party/include/ahocorasick.h
new file mode 100644
index 000000000..ea92e4a1b
--- /dev/null
+++ b/src/lib/third_party/include/ahocorasick.h
@@ -0,0 +1,69 @@
+/*
+ * ahocorasick.h: the main ahocorasick header file.
+ * This file is part of multifast.
+ *
+ Copyright 2010-2012 Kamiar Kanani <kamiar.kanani@gmail.com>
+
+ multifast is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ multifast 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with multifast. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _AUTOMATA_H_
+#define _AUTOMATA_H_
+
+#include "node.h"
+
+typedef struct
+{
+ /* The root of the Aho-Corasick trie */
+ AC_NODE_t * root;
+
+ /* maintain all nodes pointers. it will be used to access or release
+ * all nodes. */
+ AC_NODE_t ** all_nodes;
+
+ unsigned int all_nodes_num; /* Number of all nodes in the automata */
+ unsigned int all_nodes_max; /* Current max allocated memory for *all_nodes */
+
+ AC_MATCH_t match; /* Any match is reported with this */
+ MATCH_CALBACK_f match_callback; /* Match call-back function */
+
+ /* this flag indicates that if automata is finalized by
+ * ac_automata_finalize() or not. 1 means finalized and 0
+ * means not finalized (is open). after finalizing automata you can not
+ * add pattern to automata anymore. */
+ unsigned short automata_open;
+
+ /* It is possible to feed a large input to the automata chunk by chunk to
+ * be searched using ac_automata_search(). in fact by default automata
+ * thinks that all chunks are related unless you do ac_automata_reset().
+ * followings are variables that keep track of searching state. */
+ AC_NODE_t * current_node; /* Pointer to current node while searching */
+ unsigned long base_position; /* Represents the position of current chunk
+ related to whole input text */
+
+ /* Statistic Variables */
+ unsigned long total_patterns; /* Total patterns in the automata */
+
+} AC_AUTOMATA_t;
+
+
+AC_AUTOMATA_t * ac_automata_init (MATCH_CALBACK_f mc);
+AC_ERROR_t ac_automata_add (AC_AUTOMATA_t * thiz, AC_PATTERN_t * str);
+void ac_automata_finalize (AC_AUTOMATA_t * thiz);
+int ac_automata_search (AC_AUTOMATA_t * thiz, AC_TEXT_t * str, void * param);
+void ac_automata_reset (AC_AUTOMATA_t * thiz);
+void ac_automata_release (AC_AUTOMATA_t * thiz);
+void ac_automata_display (AC_AUTOMATA_t * thiz, char repcast);
+
+#endif
diff --git a/src/lib/third_party/include/node.h b/src/lib/third_party/include/node.h
new file mode 100644
index 000000000..13cf2ff11
--- /dev/null
+++ b/src/lib/third_party/include/node.h
@@ -0,0 +1,66 @@
+/*
+ * node.h: automata node header file
+ * This file is part of multifast.
+ *
+ Copyright 2010-2012 Kamiar Kanani <kamiar.kanani@gmail.com>
+
+ multifast is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ multifast 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with multifast. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _NODE_H_
+#define _NODE_H_
+
+#include "actypes.h"
+
+/* Forward Declaration */
+struct edge;
+
+/* automata node */
+typedef struct ac_node
+{
+ int id; /* Node ID : for debugging purpose */
+ short int final; /* 0: no ; 1: yes, it is a final node */
+ struct ac_node * failure_node; /* The failure node of this node */
+ unsigned short depth; /* depth: distance between this node and the root */
+
+ /* Matched patterns */
+ AC_PATTERN_t * matched_patterns; /* Array of matched patterns */
+ unsigned short matched_patterns_num; /* Number of matched patterns at this node */
+ unsigned short matched_patterns_max; /* Max capacity of allocated memory for matched_patterns */
+
+ /* Outgoing Edges */
+ struct edge * outgoing; /* Array of outgoing edges */
+ unsigned short outgoing_degree; /* Number of outgoing edges */
+ unsigned short outgoing_max; /* Max capacity of allocated memory for outgoing */
+} AC_NODE_t;
+
+/* The Edge of the Node */
+struct edge
+{
+ AC_ALPHABET_t alpha; /* Edge alpha */
+ struct ac_node * next; /* Target of the edge */
+};
+
+
+AC_NODE_t * node_create (void);
+AC_NODE_t * node_create_next (AC_NODE_t * thiz, AC_ALPHABET_t alpha);
+void node_register_matchstr (AC_NODE_t * thiz, AC_PATTERN_t * str);
+void node_register_outgoing (AC_NODE_t * thiz, AC_NODE_t * next, AC_ALPHABET_t alpha);
+AC_NODE_t * node_find_next (AC_NODE_t * thiz, AC_ALPHABET_t alpha);
+AC_NODE_t * node_findbs_next (AC_NODE_t * thiz, AC_ALPHABET_t alpha);
+void node_release (AC_NODE_t * thiz);
+void node_assign_id (AC_NODE_t * thiz);
+void node_sort_edges (AC_NODE_t * thiz);
+
+#endif
diff --git a/src/lib/third_party/include/patricia.h b/src/lib/third_party/include/patricia.h
new file mode 100644
index 000000000..be8476e85
--- /dev/null
+++ b/src/lib/third_party/include/patricia.h
@@ -0,0 +1,302 @@
+/*
+ * $Id: patricia.h,v 1.6 2005/12/07 20:53:01 dplonka Exp $
+ * Dave Plonka <plonka@doit.wisc.edu>
+ *
+ * This product includes software developed by the University of Michigan,
+ * Merit Network, Inc., and their contributors.
+ *
+ * This file had been called "radix.h" in the MRT sources.
+ *
+ * I renamed it to "patricia.h" since it's not an implementation of a general
+ * radix trie. Also, pulled in various requirements from "mrt.h" and added
+ * some other things it could be used as a standalone API.
+
+ https://github.com/deepfield/MRT/blob/master/COPYRIGHT
+
+ Copyright (c) 1999-2013
+
+ The Regents of the University of Michigan ("The Regents") and Merit
+ Network, Inc.
+
+ 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.
+
+ 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
+ HOLDER 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.
+*/
+
+#ifndef _PATRICIA_H
+#define _PATRICIA_H
+
+#define HAVE_IPV6
+
+/* typedef unsigned int u_int; */
+/* { from defs.h */
+#define prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin)
+
+#ifdef __KERNEL__
+#define MAXLINE 512
+#else
+#define MAXLINE 1024
+#endif
+
+#define BIT_TEST(f, b) ((f) & (b))
+/* } */
+
+#define addroute make_and_lookup
+
+#ifndef __KERNEL__
+#include <sys/types.h> /* for u_* definitions (on FreeBSD 5) */
+#include <errno.h> /* for EAFNOSUPPORT */
+
+#ifndef EAFNOSUPPORT
+# defined EAFNOSUPPORT WSAEAFNOSUPPORT
+#else
+#ifndef WIN32
+# include <netinet/in.h> /* for struct in_addr */
+#endif
+#endif
+
+#ifndef WIN32
+#include <sys/socket.h> /* for AF_INET */
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h> /* IPv6 */
+#endif
+
+#endif /* __KERNEL__ */
+
+/* { from mrt.h */
+
+typedef struct the_prefix4_t {
+ unsigned short family; /* AF_INET | AF_INET6 */
+ unsigned short bitlen; /* same as mask? */
+ int ref_count; /* reference count */
+ struct in_addr sin;
+} prefix4_t;
+
+typedef struct the_prefix_t {
+ unsigned short family; /* AF_INET | AF_INET6 */
+ unsigned short bitlen; /* same as mask? */
+ int ref_count; /* reference count */
+ union {
+ struct in_addr sin;
+#ifdef HAVE_IPV6
+ struct in6_addr sin6;
+#endif /* IPV6 */
+ } add;
+} prefix_t;
+
+/* } */
+
+/* pointer to usr data (ex. route flap info) */
+union patricia_node_value_t {
+ void *user_data;
+ u_int32_t user_value;
+};
+
+typedef struct _patricia_node_t {
+ u_int bit; /* flag if this node used */
+ prefix_t *prefix; /* who we are in patricia tree */
+ struct _patricia_node_t *l, *r; /* left and right children */
+ struct _patricia_node_t *parent;/* may be used */
+ void *data; /* pointer to data */
+ union patricia_node_value_t value;
+} patricia_node_t;
+
+typedef struct _patricia_tree_t {
+ patricia_node_t *head;
+ u_int maxbits; /* for IP, 32 bit addresses */
+ int num_active_node; /* for debug purpose */
+} patricia_tree_t;
+
+typedef void (*void_fn_t)(void *data);
+typedef void (*void_fn2_t)(prefix_t *prefix, void *data);
+
+/* renamed to ndpi_Patricia to avoid name conflicts */
+patricia_node_t *ndpi_patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix);
+patricia_node_t *ndpi_patricia_search_best (patricia_tree_t *patricia, prefix_t *prefix);
+patricia_node_t * ndpi_patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix,
+ int inclusive);
+patricia_node_t *ndpi_patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix);
+void ndpi_patricia_remove (patricia_tree_t *patricia, patricia_node_t *node);
+patricia_tree_t *ndpi_New_Patricia (int maxbits);
+void ndpi_Clear_Patricia (patricia_tree_t *patricia, void_fn_t func);
+void ndpi_Destroy_Patricia (patricia_tree_t *patricia, void_fn_t func);
+void ndpi_patricia_process (patricia_tree_t *patricia, void_fn2_t func);
+
+#define PATRICIA_MAXBITS (sizeof(struct in6_addr) * 8)
+#define PATRICIA_NBIT(x) (0x80 >> ((x) & 0x7f))
+#define PATRICIA_NBYTE(x) ((x) >> 3)
+
+#define PATRICIA_DATA_GET(node, type) (type *)((node)->data)
+#define PATRICIA_DATA_SET(node, value) ((node)->data = (void *)(value))
+
+#define PATRICIA_WALK(Xhead, Xnode) \
+ do { \
+ patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \
+ patricia_node_t **Xsp = Xstack; \
+ patricia_node_t *Xrn = (Xhead); \
+ while ((Xnode = Xrn)) { \
+ if (Xnode->prefix)
+
+#define PATRICIA_WALK_ALL(Xhead, Xnode) \
+ do { \
+ patricia_node_t *Xstack[PATRICIA_MAXBITS+1]; \
+ patricia_node_t **Xsp = Xstack; \
+ patricia_node_t *Xrn = (Xhead); \
+ while ((Xnode = Xrn)) { \
+ if (1)
+
+#define PATRICIA_WALK_BREAK { \
+ if (Xsp != Xstack) { \
+ Xrn = *(--Xsp); \
+ } else { \
+ Xrn = (patricia_node_t *) 0; \
+ } \
+ continue; }
+
+#define PATRICIA_WALK_END \
+ if (Xrn->l) { \
+ if (Xrn->r) { \
+ *Xsp++ = Xrn->r; \
+ } \
+ Xrn = Xrn->l; \
+ } else if (Xrn->r) { \
+ Xrn = Xrn->r; \
+ } else if (Xsp != Xstack) { \
+ Xrn = *(--Xsp); \
+ } else { \
+ Xrn = (patricia_node_t *) 0; \
+ } \
+ } \
+ } while (0)
+
+#endif /* _PATRICIA_H */
+
+/*************************
+
+
+ [newtool.gif]
+
+MRT Credits
+
+ The Multi-Threaded Routing Toolkit
+ _________________________________________________________________
+
+ MRT was developed by [1]Merit Network, Inc., under National Science
+ Foundation grant NCR-9318902, "Experimentation with Routing Technology
+ to be Used for Inter-Domain Routing in the Internet."
+
+ Current MRT Staff
+
+ * [2]Craig Labovitz <labovit@merit.edu>
+ * [3]Makaki Hirabaru <masaki@merit.edu>
+ * [4]Farnam Jahanian <farnam@eecs.umich.edu>
+ * Susan Hares <skh@merit.edu>
+ * Susan R. Harris <srh@merit.edu>
+ * Nathan Binkert <binkertn@eecs.umich.edu>
+ * Gerald Winters <gerald@merit.edu>
+
+ Project Alumni
+
+ * [5]Marc Unangst <mju@merit.edu>
+ * John Scudder <jgs@ieng.com>
+
+ The BGP4+ extension was originally written by Francis Dupont
+ <Francis.Dupont@inria.fr>.
+
+ The public domain Struct C-library of linked list, hash table and
+ memory allocation routines was developed by Jonathan Dekock
+ <dekock@cadence.com>.
+
+ Susan Rebecca Harris <srh@merit.edu> provided help with the
+ documentation.
+ David Ward <dward@netstar.com> provided bug fixes and helpful
+ suggestions.
+ Some sections of code and architecture ideas were taken from the GateD
+ routing daemon.
+
+ The first port to Linux with IPv6 was done by Pedro Roque
+ <roque@di.fc.ul.pt>. Some interface routines to the Linux kernel were
+ originally written by him.
+
+ Alexey Kuznetsov made enhancements to 1.4.3a and fixed the Linux
+ kernel intarface. Linux's netlink interface was written, referring to
+ his code "iproute2".
+
+ We would also like to thank our other colleagues in Japan, Portugal,
+ the Netherlands, the UK, and the US for their many contributions to
+ the MRT development effort.
+ _________________________________________________________________
+
+ Cisco is a registered trademark of Cisco Systems Inc.
+ _________________________________________________________________
+
+ Merit Network 4251 Plymouth Road Suite C Ann Arbor, MI 48105-2785
+ 734-764-9430
+ info@merit.edu
+ _________________________________________________________________
+
+ © 1999 Merit Network, Inc.
+ [6]www@merit.edu
+
+References
+
+ 1. http://www.merit.edu/
+ 2. http://www.merit.edu/~labovit
+ 3. http://www.merit.edu/~masaki
+ 4. http://www.eecs.umich.edu/~farnam
+ 5. http://www.contrib.andrew.cmu.edu/~mju/
+ 6. mailto:www@merit.edu
+
+------------
+
+Copyright (c) 1997, 1998, 1999
+
+
+The Regents of the University of Michigan ("The Regents") and Merit Network,
+Inc. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+2. 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.
+3. All advertising materials mentioning features or use of
+ this software must display the following acknowledgement:
+This product includes software developed by the University of Michigan, Merit
+Network, Inc., and their contributors.
+4. Neither the name of the University, Merit Network, nor the
+ names of their contributors may be used to endorse or
+ promote products derived from this software without
+ specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+
+
+************************ */
diff --git a/src/lib/third_party/include/sort.h b/src/lib/third_party/include/sort.h
new file mode 100644
index 000000000..ee7df8a10
--- /dev/null
+++ b/src/lib/third_party/include/sort.h
@@ -0,0 +1,6 @@
+/* This is a function ported from the Linux kernel lib/sort.c */
+
+void sort(void *base, size_t num, size_t len,
+ int (*cmp_func)(const void *, const void *),
+ void (*swap_func)(void *, void *, int size));
+
diff --git a/src/lib/third_party/src/ahocorasick.c b/src/lib/third_party/src/ahocorasick.c
new file mode 100644
index 000000000..54a97e776
--- /dev/null
+++ b/src/lib/third_party/src/ahocorasick.c
@@ -0,0 +1,391 @@
+/*
+ * ahocorasick.c: implementation of ahocorasick library's functions
+ * This file is part of multifast.
+ *
+ Copyright 2010-2012 Kamiar Kanani <kamiar.kanani@gmail.com>
+
+ multifast is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ multifast 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with multifast. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __KERNEL__
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#endif
+
+#include "ndpi_api.h"
+#include "ahocorasick.h"
+
+/* Allocation step for automata.all_nodes */
+#define REALLOC_CHUNK_ALLNODES 200
+
+/* Private function prototype */
+static void ac_automata_register_nodeptr
+(AC_AUTOMATA_t * thiz, AC_NODE_t * node);
+static void ac_automata_union_matchstrs
+(AC_NODE_t * node);
+static void ac_automata_set_failure
+(AC_AUTOMATA_t * thiz, AC_NODE_t * node, AC_ALPHABET_t * alphas);
+static void ac_automata_traverse_setfailure
+(AC_AUTOMATA_t * thiz, AC_NODE_t * node, AC_ALPHABET_t * alphas);
+
+
+/******************************************************************************
+ * FUNCTION: ac_automata_init
+ * Initialize automata; allocate memories and set initial values
+ * PARAMS:
+ * MATCH_CALBACK mc: call-back function
+ * the call-back function will be used to reach the caller on match occurrence
+ ******************************************************************************/
+AC_AUTOMATA_t * ac_automata_init (MATCH_CALBACK_f mc)
+{
+ AC_AUTOMATA_t * thiz = (AC_AUTOMATA_t *)ndpi_malloc(sizeof(AC_AUTOMATA_t));
+ memset (thiz, 0, sizeof(AC_AUTOMATA_t));
+ thiz->root = node_create ();
+ thiz->all_nodes_max = REALLOC_CHUNK_ALLNODES;
+ thiz->all_nodes = (AC_NODE_t **) ndpi_malloc (thiz->all_nodes_max*sizeof(AC_NODE_t *));
+ thiz->match_callback = mc;
+ ac_automata_register_nodeptr (thiz, thiz->root);
+ ac_automata_reset (thiz);
+ thiz->total_patterns = 0;
+ thiz->automata_open = 1;
+ return thiz;
+}
+
+/******************************************************************************
+ * FUNCTION: ac_automata_add
+ * Adds pattern to the automata.
+ * PARAMS:
+ * AC_AUTOMATA_t * thiz: the pointer to the automata
+ * AC_PATTERN_t * patt: the pointer to added pattern
+ * RETUERN VALUE: AC_ERROR_t
+ * the return value indicates the success or failure of adding action
+ ******************************************************************************/
+AC_ERROR_t ac_automata_add (AC_AUTOMATA_t * thiz, AC_PATTERN_t * patt)
+{
+ unsigned int i;
+ AC_NODE_t * n = thiz->root;
+ AC_NODE_t * next;
+ AC_ALPHABET_t alpha;
+
+ if(!thiz->automata_open)
+ return ACERR_AUTOMATA_CLOSED;
+
+ if (!patt->length)
+ return ACERR_ZERO_PATTERN;
+
+ if (patt->length > AC_PATTRN_MAX_LENGTH)
+ return ACERR_LONG_PATTERN;
+
+ for (i=0; i<patt->length; i++)
+ {
+ alpha = patt->astring[i];
+ if ((next = node_find_next(n, alpha)))
+ {
+ n = next;
+ continue;
+ }
+ else
+ {
+ next = node_create_next(n, alpha);
+ next->depth = n->depth + 1;
+ n = next;
+ ac_automata_register_nodeptr(thiz, n);
+ }
+ }
+
+ if(n->final)
+ return ACERR_DUPLICATE_PATTERN;
+
+ n->final = 1;
+ node_register_matchstr(n, patt);
+ thiz->total_patterns++;
+
+ return ACERR_SUCCESS;
+}
+
+/******************************************************************************
+ * FUNCTION: ac_automata_finalize
+ * Locate the failure node for all nodes and collect all matched pattern for
+ * every node. it also sorts outgoing edges of node, so binary search could be
+ * performed on them. after calling this function the automate literally will
+ * be finalized and you can not add new patterns to the automate.
+ * PARAMS:
+ * AC_AUTOMATA_t * thiz: the pointer to the automata
+ ******************************************************************************/
+void ac_automata_finalize (AC_AUTOMATA_t * thiz)
+{
+ unsigned int i;
+ AC_ALPHABET_t *alphas;
+ AC_NODE_t * node;
+
+ if((alphas = ndpi_malloc(AC_PATTRN_MAX_LENGTH)) != NULL) {
+ ac_automata_traverse_setfailure (thiz, thiz->root, alphas);
+
+ for (i=0; i < thiz->all_nodes_num; i++)
+ {
+ node = thiz->all_nodes[i];
+ ac_automata_union_matchstrs (node);
+ node_sort_edges (node);
+ }
+ thiz->automata_open = 0; /* do not accept patterns any more */
+ ndpi_free(alphas);
+ }
+}
+
+/******************************************************************************
+ * FUNCTION: ac_automata_search
+ * Search in the input text using the given automata. on match event it will
+ * call the call-back function. and the call-back function in turn after doing
+ * its job, will return an integer value to ac_automata_search(). 0 value means
+ * continue search, and non-0 value means stop search and return to the caller.
+ * PARAMS:
+ * AC_AUTOMATA_t * thiz: the pointer to the automata
+ * AC_TEXT_t * txt: the input text that must be searched
+ * void * param: this parameter will be send to call-back function. it is
+ * useful for sending parameter to call-back function from caller function.
+ * RETURN VALUE:
+ * -1: failed call; automata is not finalized
+ * 0: success; continue searching; call-back sent me a 0 value
+ * 1: success; stop searching; call-back sent me a non-0 value
+ ******************************************************************************/
+int ac_automata_search (AC_AUTOMATA_t * thiz, AC_TEXT_t * txt, void * param)
+{
+ unsigned long position;
+ AC_NODE_t *curr;
+ AC_NODE_t *next;
+
+ if(thiz->automata_open)
+ /* you must call ac_automata_locate_failure() first */
+ return -1;
+
+ position = 0;
+ curr = thiz->current_node;
+
+ /* This is the main search loop.
+ * it must be keep as lightweight as possible. */
+ while (position < txt->length)
+ {
+ if(!(next = node_findbs_next(curr, txt->astring[position])))
+ {
+ if(curr->failure_node /* we are not in the root node */)
+ curr = curr->failure_node;
+ else
+ position++;
+ }
+ else
+ {
+ curr = next;
+ position++;
+ }
+
+ if(curr->final && next)
+ /* We check 'next' to find out if we came here after a alphabet
+ * transition or due to a fail. in second case we should not report
+ * matching because it was reported in previous node */
+ {
+ thiz->match.position = position + thiz->base_position;
+ thiz->match.match_num = curr->matched_patterns_num;
+ thiz->match.patterns = curr->matched_patterns;
+ /* we found a match! do call-back */
+ if (thiz->match_callback(&thiz->match, param))
+ return 1;
+ }
+ }
+
+ /* save status variables */
+ thiz->current_node = curr;
+ thiz->base_position += position;
+ return 0;
+}
+
+/******************************************************************************
+ * FUNCTION: ac_automata_reset
+ * reset the automata and make it ready for doing new search on a new text.
+ * when you finished with the input text, you must reset automata state for
+ * new input, otherwise it will not work.
+ * PARAMS:
+ * AC_AUTOMATA_t * thiz: the pointer to the automata
+ ******************************************************************************/
+void ac_automata_reset (AC_AUTOMATA_t * thiz)
+{
+ thiz->current_node = thiz->root;
+ thiz->base_position = 0;
+}
+
+/******************************************************************************
+ * FUNCTION: ac_automata_release
+ * Release all allocated memories to the automata
+ * PARAMS:
+ * AC_AUTOMATA_t * thiz: the pointer to the automata
+ ******************************************************************************/
+void ac_automata_release (AC_AUTOMATA_t * thiz)
+{
+ unsigned int i;
+ AC_NODE_t * n;
+
+ for (i=0; i < thiz->all_nodes_num; i++)
+ {
+ n = thiz->all_nodes[i];
+ node_release(n);
+ }
+ ndpi_free(thiz->all_nodes);
+ ndpi_free(thiz);
+}
+
+#ifndef __KERNEL__
+/******************************************************************************
+ * FUNCTION: ac_automata_display
+ * Prints the automata to output in human readable form. it is useful for
+ * debugging purpose.
+ * PARAMS:
+ * AC_AUTOMATA_t * thiz: the pointer to the automata
+ * char repcast: 'n': print AC_REP_t as number, 's': print AC_REP_t as string
+ ******************************************************************************/
+void ac_automata_display (AC_AUTOMATA_t * thiz, char repcast)
+{
+ unsigned int i, j;
+ AC_NODE_t * n;
+ struct edge * e;
+ AC_PATTERN_t sid;
+
+ printf("---------------------------------\n");
+
+ for (i=0; i<thiz->all_nodes_num; i++)
+ {
+ n = thiz->all_nodes[i];
+ printf("NODE(%3d)/----fail----> NODE(%3d)\n",
+ n->id, (n->failure_node)?n->failure_node->id:1);
+ for (j=0; j<n->outgoing_degree; j++)
+ {
+ e = &n->outgoing[j];
+ printf(" |----(");
+ if(isgraph(e->alpha))
+ printf("%c)---", e->alpha);
+ else
+ printf("0x%x)", e->alpha);
+ printf("--> NODE(%3d)\n", e->next->id);
+ }
+ if (n->matched_patterns_num) {
+ printf("Accepted patterns: {");
+ for (j=0; j<n->matched_patterns_num; j++)
+ {
+ sid = n->matched_patterns[j];
+ if(j) printf(", ");
+ switch (repcast)
+ {
+ case 'n':
+ printf("%ld", sid.rep.number);
+ break;
+ case 's':
+ printf("%s", sid.rep.stringy);
+ break;
+ }
+ }
+ printf("}\n");
+ }
+ printf("---------------------------------\n");
+ }
+}
+#endif /* __KERNEL__ */
+
+/******************************************************************************
+ * FUNCTION: ac_automata_register_nodeptr
+ * Adds the node pointer to all_nodes.
+ ******************************************************************************/
+static void ac_automata_register_nodeptr (AC_AUTOMATA_t * thiz, AC_NODE_t * node)
+{
+ if(thiz->all_nodes_num >= thiz->all_nodes_max)
+ {
+ thiz->all_nodes = ndpi_realloc(thiz->all_nodes,
+ thiz->all_nodes_max*sizeof(AC_NODE_t *),
+ (REALLOC_CHUNK_ALLNODES+thiz->all_nodes_max)*sizeof(AC_NODE_t *)
+ );
+ thiz->all_nodes_max += REALLOC_CHUNK_ALLNODES;
+ }
+ thiz->all_nodes[thiz->all_nodes_num++] = node;
+}
+
+/******************************************************************************
+ * FUNCTION: ac_automata_union_matchstrs
+ * Collect accepted patterns of the node. the accepted patterns consist of the
+ * node's own accepted pattern plus accepted patterns of its failure node.
+ ******************************************************************************/
+static void ac_automata_union_matchstrs (AC_NODE_t * node)
+{
+ unsigned int i;
+ AC_NODE_t * m = node;
+
+ while ((m = m->failure_node))
+ {
+ for (i=0; i < m->matched_patterns_num; i++)
+ node_register_matchstr(node, &(m->matched_patterns[i]));
+
+ if (m->final)
+ node->final = 1;
+ }
+ // TODO : sort matched_patterns? is that necessary? I don't think so.
+}
+
+/******************************************************************************
+ * FUNCTION: ac_automata_set_failure
+ * find failure node for the given node.
+ ******************************************************************************/
+static void ac_automata_set_failure
+(AC_AUTOMATA_t * thiz, AC_NODE_t * node, AC_ALPHABET_t * alphas)
+{
+ unsigned int i, j;
+ AC_NODE_t * m;
+
+ for (i=1; i < node->depth; i++)
+ {
+ m = thiz->root;
+ for (j=i; j < node->depth && m; j++)
+ m = node_find_next (m, alphas[j]);
+ if (m)
+ {
+ node->failure_node = m;
+ break;
+ }
+ }
+ if (!node->failure_node)
+ node->failure_node = thiz->root;
+}
+
+/******************************************************************************
+ * FUNCTION: ac_automata_traverse_setfailure
+ * Traverse all automata nodes using DFS (Depth First Search), meanwhile it set
+ * the failure node for every node it passes through. this function must be
+ * called after adding last pattern to automata. i.e. after calling this you
+ * can not add further pattern to automata.
+ ******************************************************************************/
+static void ac_automata_traverse_setfailure
+(AC_AUTOMATA_t * thiz, AC_NODE_t * node, AC_ALPHABET_t * alphas)
+{
+ unsigned int i;
+ AC_NODE_t * next;
+
+ for (i=0; i < node->outgoing_degree; i++)
+ {
+ alphas[node->depth] = node->outgoing[i].alpha;
+ next = node->outgoing[i].next;
+
+ /* At every node look for its failure node */
+ ac_automata_set_failure (thiz, next, alphas);
+
+ /* Recursively call itself to traverse all nodes */
+ ac_automata_traverse_setfailure (thiz, next, alphas);
+ }
+}
diff --git a/src/lib/third_party/src/node.c b/src/lib/third_party/src/node.c
new file mode 100644
index 000000000..404fb24d4
--- /dev/null
+++ b/src/lib/third_party/src/node.c
@@ -0,0 +1,260 @@
+/*
+ * node.c: implementation of automata node
+ * This file is part of multifast.
+ *
+ Copyright 2010-2012 Kamiar Kanani <kamiar.kanani@gmail.com>
+
+ multifast is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ multifast 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with multifast. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __KERNEL__
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#endif
+
+#include "ndpi_api.h"
+
+#include "../include/node.h"
+#include "sort.h"
+
+/* reallocation step for AC_NODE_t.matched_patterns */
+#define REALLOC_CHUNK_MATCHSTR 8
+
+/* reallocation step for AC_NODE_t.outgoing array */
+#define REALLOC_CHUNK_OUTGOING 8
+/* TODO: For different depth of node, number of outgoing edges differs
+ considerably, It is efficient to use different chunk size for
+ different depths */
+
+/* Private function prototype */
+void node_init (AC_NODE_t * thiz);
+int node_edge_compare (const void * l, const void * r);
+int node_has_matchstr (AC_NODE_t * thiz, AC_PATTERN_t * newstr);
+
+
+/******************************************************************************
+ * FUNCTION: node_create
+ * Create the node
+ ******************************************************************************/
+AC_NODE_t * node_create(void)
+{
+ AC_NODE_t * thiz = (AC_NODE_t *) ndpi_malloc (sizeof(AC_NODE_t));
+ node_init(thiz);
+ node_assign_id(thiz);
+ return thiz;
+}
+
+/******************************************************************************
+ * FUNCTION: node_init
+ * Initialize node
+ ******************************************************************************/
+void node_init(AC_NODE_t * thiz)
+{
+ memset(thiz, 0, sizeof(AC_NODE_t));
+
+ thiz->outgoing_max = REALLOC_CHUNK_OUTGOING;
+ thiz->outgoing = (struct edge *) ndpi_malloc
+ (thiz->outgoing_max*sizeof(struct edge));
+
+ thiz->matched_patterns_max = REALLOC_CHUNK_MATCHSTR;
+ thiz->matched_patterns = (AC_PATTERN_t *) ndpi_malloc
+ (thiz->matched_patterns_max*sizeof(AC_PATTERN_t));
+}
+
+/******************************************************************************
+ * FUNCTION: node_release
+ * Release node
+ ******************************************************************************/
+void node_release(AC_NODE_t * thiz)
+{
+ ndpi_free(thiz->matched_patterns);
+ ndpi_free(thiz->outgoing);
+ ndpi_free(thiz);
+}
+
+/******************************************************************************
+ * FUNCTION: node_find_next
+ * Find out the next node for a given Alpha to move. this function is used in
+ * the pre-processing stage in which edge array is not sorted. so it uses
+ * linear search.
+ ******************************************************************************/
+AC_NODE_t * node_find_next(AC_NODE_t * thiz, AC_ALPHABET_t alpha)
+{
+ int i;
+
+ for (i=0; i < thiz->outgoing_degree; i++)
+ {
+ if(thiz->outgoing[i].alpha == alpha)
+ return (thiz->outgoing[i].next);
+ }
+ return NULL;
+}
+
+/******************************************************************************
+ * FUNCTION: node_findbs_next
+ * Find out the next node for a given Alpha. this function is used after the
+ * pre-processing stage in which we sort edges. so it uses Binary Search.
+ ******************************************************************************/
+AC_NODE_t * node_findbs_next (AC_NODE_t * thiz, AC_ALPHABET_t alpha)
+{
+ int min, max, mid;
+ AC_ALPHABET_t amid;
+
+ min = 0;
+ max = thiz->outgoing_degree - 1;
+
+ while (min <= max)
+ {
+ mid = (min+max) >> 1;
+ amid = thiz->outgoing[mid].alpha;
+ if (alpha > amid)
+ min = mid + 1;
+ else if (alpha < amid)
+ max = mid - 1;
+ else
+ return (thiz->outgoing[mid].next);
+ }
+ return NULL;
+}
+
+/******************************************************************************
+ * FUNCTION: node_has_matchstr
+ * Determine if a final node contains a pattern in its accepted pattern list
+ * or not. return values: 1 = it has, 0 = it hasn't
+ ******************************************************************************/
+int node_has_matchstr (AC_NODE_t * thiz, AC_PATTERN_t * newstr)
+{
+ int i, j;
+ AC_PATTERN_t * str;
+
+ for (i=0; i < thiz->matched_patterns_num; i++)
+ {
+ str = &thiz->matched_patterns[i];
+
+ if (str->length != newstr->length)
+ continue;
+
+ for (j=0; j<(int)str->length; j++)
+ if(str->astring[j] != newstr->astring[j])
+ continue;
+
+ if (j == str->length)
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * FUNCTION: node_create_next
+ * Create the next node for the given alpha.
+ ******************************************************************************/
+AC_NODE_t * node_create_next (AC_NODE_t * thiz, AC_ALPHABET_t alpha)
+{
+ AC_NODE_t * next;
+ next = node_find_next (thiz, alpha);
+ if (next)
+ /* The edge already exists */
+ return NULL;
+ /* Otherwise register new edge */
+ next = node_create ();
+ node_register_outgoing(thiz, next, alpha);
+
+ return next;
+}
+
+/******************************************************************************
+ * FUNCTION: node_register_matchstr
+ * Adds the pattern to the list of accepted pattern.
+ ******************************************************************************/
+void node_register_matchstr (AC_NODE_t * thiz, AC_PATTERN_t * str)
+{
+ /* Check if the new pattern already exists in the node list */
+ if (node_has_matchstr(thiz, str))
+ return;
+
+ /* Manage memory */
+ if (thiz->matched_patterns_num >= thiz->matched_patterns_max)
+ {
+ thiz->matched_patterns = (AC_PATTERN_t *) ndpi_realloc
+ (thiz->matched_patterns, thiz->matched_patterns_max*sizeof(AC_PATTERN_t),
+ (REALLOC_CHUNK_MATCHSTR+thiz->matched_patterns_max)*sizeof(AC_PATTERN_t));
+
+ thiz->matched_patterns_max += REALLOC_CHUNK_MATCHSTR;
+ }
+
+ thiz->matched_patterns[thiz->matched_patterns_num].astring = str->astring;
+ thiz->matched_patterns[thiz->matched_patterns_num].length = str->length;
+ thiz->matched_patterns[thiz->matched_patterns_num].rep = str->rep;
+ thiz->matched_patterns_num++;
+}
+
+/******************************************************************************
+ * FUNCTION: node_register_outgoing
+ * Establish an edge between two nodes
+ ******************************************************************************/
+void node_register_outgoing
+(AC_NODE_t * thiz, AC_NODE_t * next, AC_ALPHABET_t alpha)
+{
+ if(thiz->outgoing_degree >= thiz->outgoing_max)
+ {
+ thiz->outgoing = (struct edge *) ndpi_realloc
+ (thiz->outgoing, thiz->outgoing_max*sizeof(struct edge),
+ (REALLOC_CHUNK_OUTGOING+thiz->outgoing_max)*sizeof(struct edge));
+ thiz->outgoing_max += REALLOC_CHUNK_OUTGOING;
+ }
+
+ thiz->outgoing[thiz->outgoing_degree].alpha = alpha;
+ thiz->outgoing[thiz->outgoing_degree++].next = next;
+}
+
+/******************************************************************************
+ * FUNCTION: node_assign_id
+ * assign a unique ID to the node (used for debugging purpose).
+ ******************************************************************************/
+void node_assign_id (AC_NODE_t * thiz)
+{
+ static int unique_id = 1;
+ thiz->id = unique_id ++;
+}
+
+/******************************************************************************
+ * FUNCTION: node_edge_compare
+ * Comparison function for qsort. see man qsort.
+ ******************************************************************************/
+int node_edge_compare (const void * l, const void * r)
+{
+ /* According to man page:
+ * The comparison function must return an integer less than, equal to, or
+ * greater than zero if the first argument is considered to be
+ * respectively less than, equal to, or greater than the second. if two
+ * members compare as equal, their order in the sorted array is undefined.
+ *
+ * NOTE: Because edge alphabets are unique in every node we ignore
+ * equivalence case.
+ **/
+ if ( ((struct edge *)l)->alpha >= ((struct edge *)r)->alpha )
+ return 1;
+ else
+ return -1;
+}
+
+/******************************************************************************
+ * FUNCTION: node_sort_edges
+ * sorts edges alphabets.
+ ******************************************************************************/
+void node_sort_edges (AC_NODE_t * thiz)
+{
+ sort ((void *)thiz->outgoing, thiz->outgoing_degree, sizeof(struct edge), node_edge_compare, NULL);
+}
diff --git a/src/lib/third_party/src/patricia.c b/src/lib/third_party/src/patricia.c
new file mode 100644
index 000000000..b7b4c2010
--- /dev/null
+++ b/src/lib/third_party/src/patricia.c
@@ -0,0 +1,1076 @@
+/*
+ * $Id: patricia.c,v 1.7 2005/12/07 20:46:41 dplonka Exp $
+ * Dave Plonka <plonka@doit.wisc.edu>
+ *
+ * This product includes software developed by the University of Michigan,
+ * Merit Network, Inc., and their contributors.
+ *
+ * This file had been called "radix.c" in the MRT sources.
+ *
+ * I renamed it to "patricia.c" since it's not an implementation of a general
+ * radix trie. Also I pulled in various requirements from "prefix.c" and
+ * "demo.c" so that it could be used as a standalone API.
+
+
+ https://github.com/deepfield/MRT/blob/master/COPYRIGHT
+
+ Copyright (c) 1999-2013
+
+ The Regents of the University of Michigan ("The Regents") and Merit
+ Network, Inc.
+
+ 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.
+
+ 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
+ HOLDER 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.
+*/
+
+#ifndef __KERNEL__
+#include <assert.h> /* assert */
+#include <ctype.h> /* isdigit */
+#include <errno.h> /* errno */
+#include <math.h> /* sin */
+#include <stddef.h> /* NULL */
+#include <stdio.h> /* sprintf, fprintf, stderr */
+#include <stdlib.h> /* free, atol, calloc */
+#include <string.h> /* memcpy, strchr, strlen */
+#include <sys/types.h> /* BSD: for inet_addr */
+#ifndef WIN32
+#include <sys/socket.h> /* BSD, Linux: for inet_addr */
+#include <netinet/in.h> /* BSD, Linux: for inet_addr */
+#include <arpa/inet.h> /* BSD, Linux, Solaris: for inet_addr */
+#endif
+#else
+#define assert(a) ;
+#endif /* __KERNEL__ */
+
+#include "patricia.h"
+
+#ifdef __KERNEL__
+
+long atol(const char *nptr) {
+ long l;
+ char *endp;
+
+ l = simple_strtol(nptr, &endp, 10);
+ return(l);
+}
+#endif
+
+// #define PATRICIA_DEBUG
+
+void ndpi_DeleteEntry(void *a) {
+ ndpi_free(a);
+}
+
+/* { from prefix.c */
+
+/* ndpi_prefix_tochar
+ * convert prefix information to bytes
+ */
+u_char *
+ndpi_prefix_tochar (prefix_t * prefix)
+{
+ if(prefix == NULL)
+ return (NULL);
+
+ return ((u_char *) & prefix->add.sin);
+}
+
+int ndpi_comp_with_mask (void *addr, void *dest, u_int mask) {
+ if( /* mask/8 == 0 || */ memcmp (addr, dest, mask / 8) == 0) {
+ int n = mask / 8;
+ int m = ((-1) << (8 - (mask % 8)));
+
+ if(mask % 8 == 0 || (((u_char *)addr)[n] & m) == (((u_char *)dest)[n] & m))
+ return (1);
+ }
+ return (0);
+}
+
+#if 0 /* this implementation does not support IPv6, using system inet_pton */
+#ifndef WIN32
+/* inet_pton substitute implementation
+ * Uses inet_addr to convert an IP address in dotted decimal notation into
+ * unsigned long and copies the result to dst.
+ * Only supports AF_INET. Follows standard error return conventions of
+ * inet_pton.
+ */
+int
+inet_pton (int af, const char *src, void *dst)
+{
+ u_long result;
+
+ if(af == AF_INET) {
+ result = inet_addr(src);
+ if(result == -1)
+ return 0;
+ else {
+ memcpy (dst, &result, sizeof(struct in_addr));
+ return 1;
+ }
+ }
+#ifdef NT
+#if defined(HAVE_IPV6) && (!defined(__KERNEL__))
+ else if(af == AF_INET6) {
+ struct in6_addr Address;
+ return (inet6_addr(src, &Address));
+ }
+#endif /* HAVE_IPV6 */
+#endif /* NT */
+#ifndef NT
+ else {
+ printf("NOT SUPP\n");
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+#endif /* NT */
+}
+#endif
+#endif
+
+/* this allows imcomplete prefix */
+int
+ndpi_my_inet_pton (int af, const char *src, void *dst)
+{
+ if(af == AF_INET) {
+ int i;
+ u_char xp[sizeof(struct in_addr)] = {0, 0, 0, 0};
+
+ for (i = 0; ; i++) {
+ int c, val;
+
+ c = *src++;
+ if(!isdigit (c))
+ return (-1);
+ val = 0;
+ do {
+ val = val * 10 + c - '0';
+ if(val > 255)
+ return (0);
+ c = *src++;
+ } while (c && isdigit (c));
+ xp[i] = val;
+ if(c == '\0')
+ break;
+ if(c != '.')
+ return (0);
+ if(i >= 3)
+ return (0);
+ }
+ memcpy (dst, xp, sizeof(struct in_addr));
+ return (1);
+#if defined(HAVE_IPV6) && (!defined(__KERNEL__))
+ } else if(af == AF_INET6) {
+ return (inet_pton (af, src, dst));
+#endif /* HAVE_IPV6 */
+ } else {
+#ifndef NT
+#ifndef __KERNEL__
+ errno = EAFNOSUPPORT;
+#endif
+#endif /* NT */
+ return -1;
+ }
+}
+
+#define PATRICIA_MAX_THREADS 16
+
+/*
+ * convert prefix information to ascii string with length
+ * thread safe and (almost) re-entrant implementation
+ */
+char *
+ndpi_ndpi_prefix_toa2x (prefix_t *prefix, char *buff, int with_len)
+{
+ if(prefix == NULL)
+ return ((char*)"(Null)");
+ assert (prefix->ref_count >= 0);
+ if(buff == NULL) {
+
+ struct buffer {
+ char buffs[PATRICIA_MAX_THREADS][48+5];
+ u_int i;
+ } *buffp;
+
+# if 0
+ THREAD_SPECIFIC_DATA (struct buffer, buffp, 1);
+# else
+ { /* for scope only */
+ static struct buffer local_buff;
+ buffp = &local_buff;
+ }
+# endif
+ if(buffp == NULL) {
+ /* XXX should we report an error? */
+ return (NULL);
+ }
+
+ buff = buffp->buffs[buffp->i++%PATRICIA_MAX_THREADS];
+ }
+ if(prefix->family == AF_INET) {
+ u_char *a;
+ assert (prefix->bitlen <= sizeof(struct in_addr) * 8);
+ a = prefix_touchar (prefix);
+ if(with_len) {
+ sprintf (buff, "%d.%d.%d.%d/%d", a[0], a[1], a[2], a[3],
+ prefix->bitlen);
+ }
+ else {
+ sprintf (buff, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
+ }
+ return (buff);
+ }
+#if defined(HAVE_IPV6) && (!defined(__KERNEL__))
+ else if(prefix->family == AF_INET6) {
+ char *r;
+ r = (char *) inet_ntop (AF_INET6, &prefix->add.sin6, buff, 48 /* a guess value */ );
+ if(r && with_len) {
+ assert (prefix->bitlen <= sizeof(struct in6_addr) * 8);
+ sprintf (buff + strlen (buff), "/%d", prefix->bitlen);
+ }
+ return (buff);
+ }
+#endif /* HAVE_IPV6 */
+ else
+ return (NULL);
+}
+
+/* ndpi_prefix_toa2
+ * convert prefix information to ascii string
+ */
+char *
+ndpi_prefix_toa2 (prefix_t *prefix, char *buff)
+{
+ return (ndpi_ndpi_prefix_toa2x (prefix, buff, 0));
+}
+
+/* ndpi_prefix_toa
+ */
+char *
+ndpi_prefix_toa (prefix_t * prefix)
+{
+ return (ndpi_prefix_toa2 (prefix, (char *) NULL));
+}
+
+prefix_t *
+ndpi_New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix)
+{
+ int dynamic_allocated = 0;
+ int default_bitlen = sizeof(struct in_addr) * 8;
+
+#if defined(HAVE_IPV6) && (!defined(__KERNEL__))
+ if(family == AF_INET6) {
+ default_bitlen = sizeof(struct in6_addr) * 8;
+ if(prefix == NULL) {
+ prefix = (prefix_t*)ndpi_calloc(1, sizeof (prefix_t));
+ dynamic_allocated++;
+ }
+ memcpy (&prefix->add.sin6, dest, sizeof(struct in6_addr));
+ }
+ else
+#endif /* HAVE_IPV6 */
+ if(family == AF_INET) {
+ if(prefix == NULL) {
+#ifndef NT
+ prefix = (prefix_t*)ndpi_calloc(1, sizeof (prefix4_t));
+#else
+ //for some reason, compiler is getting
+ //prefix4_t size incorrect on NT
+ prefix = ndpi_calloc(1, sizeof (prefix_t));
+#endif /* NT */
+
+ dynamic_allocated++;
+ }
+ memcpy (&prefix->add.sin, dest, sizeof(struct in_addr));
+ }
+ else {
+ return (NULL);
+ }
+
+ prefix->bitlen = (bitlen >= 0)? bitlen: default_bitlen;
+ prefix->family = family;
+ prefix->ref_count = 0;
+ if(dynamic_allocated) {
+ prefix->ref_count++;
+ }
+ /* fprintf(stderr, "[C %s, %d]\n", ndpi_prefix_toa (prefix), prefix->ref_count); */
+ return (prefix);
+}
+
+prefix_t *
+ndpi_New_Prefix (int family, void *dest, int bitlen)
+{
+ return (ndpi_New_Prefix2 (family, dest, bitlen, NULL));
+}
+
+/* ndpi_ascii2prefix
+ */
+prefix_t *
+ndpi_ascii2prefix (int family, char *string)
+{
+ long bitlen;
+ long maxbitlen = 0;
+ char *cp;
+ struct in_addr sin;
+#if defined(HAVE_IPV6) && (!defined(__KERNEL__))
+ struct in6_addr sin6;
+#endif /* HAVE_IPV6 */
+ char save[MAXLINE];
+
+ if(string == NULL)
+ return (NULL);
+
+ /* easy way to handle both families */
+ if(family == 0) {
+ family = AF_INET;
+#if defined(HAVE_IPV6) && (!defined(__KERNEL__))
+ if(strchr (string, ':')) family = AF_INET6;
+#endif /* HAVE_IPV6 */
+ }
+
+ if(family == AF_INET) {
+ maxbitlen = sizeof(struct in_addr) * 8;
+ }
+#if defined(HAVE_IPV6) && (!defined(__KERNEL__))
+ else if(family == AF_INET6) {
+ maxbitlen = sizeof(struct in6_addr) * 8;
+ }
+#endif /* HAVE_IPV6 */
+
+ if((cp = strchr (string, '/')) != NULL) {
+ bitlen = atol (cp + 1);
+ /* *cp = '\0'; */
+ /* copy the string to save. Avoid destroying the string */
+ assert (cp - string < MAXLINE);
+ memcpy (save, string, cp - string);
+ save[cp - string] = '\0';
+ string = save;
+ if((bitlen < 0) || (bitlen > maxbitlen))
+ bitlen = maxbitlen;
+ } else {
+ bitlen = maxbitlen;
+ }
+
+ if(family == AF_INET) {
+ if(ndpi_my_inet_pton (AF_INET, string, &sin) <= 0)
+ return (NULL);
+ return (ndpi_New_Prefix (AF_INET, &sin, bitlen));
+ }
+
+#if defined(HAVE_IPV6) && (!defined(__KERNEL__))
+ else if(family == AF_INET6) {
+ // Get rid of this with next IPv6 upgrade
+#if defined(NT) && !defined(HAVE_INET_NTOP)
+ inet6_addr(string, &sin6);
+ return (ndpi_New_Prefix (AF_INET6, &sin6, bitlen));
+#else
+ if(inet_pton (AF_INET6, string, &sin6) <= 0)
+ return (NULL);
+#endif /* NT */
+ return (ndpi_New_Prefix (AF_INET6, &sin6, bitlen));
+ }
+#endif /* HAVE_IPV6 */
+ else
+ return (NULL);
+}
+
+prefix_t *
+ndpi_Ref_Prefix (prefix_t * prefix)
+{
+ if(prefix == NULL)
+ return (NULL);
+ if(prefix->ref_count == 0) {
+ /* make a copy in case of a static prefix */
+ return (ndpi_New_Prefix2 (prefix->family, &prefix->add, prefix->bitlen, NULL));
+ }
+ prefix->ref_count++;
+ /* fprintf(stderr, "[A %s, %d]\n", ndpi_prefix_toa (prefix), prefix->ref_count); */
+ return (prefix);
+}
+
+void
+ndpi_Deref_Prefix (prefix_t * prefix)
+{
+ if(prefix == NULL)
+ return;
+ /* for secure programming, raise an assert. no static prefix can call this */
+ assert (prefix->ref_count > 0);
+
+ prefix->ref_count--;
+ assert (prefix->ref_count >= 0);
+ if(prefix->ref_count <= 0) {
+ ndpi_DeleteEntry (prefix);
+ return;
+ }
+}
+
+/* } */
+
+/* #define PATRICIA_DEBUG 1 */
+
+static int num_active_patricia = 0;
+
+/* these routines support continuous mask only */
+
+patricia_tree_t *
+ndpi_New_Patricia (int maxbits)
+{
+ patricia_tree_t *patricia = (patricia_tree_t*)ndpi_calloc(1, sizeof *patricia);
+
+ patricia->maxbits = maxbits;
+ patricia->head = NULL;
+ patricia->num_active_node = 0;
+ assert((u_int)maxbits <= PATRICIA_MAXBITS); /* XXX */
+ num_active_patricia++;
+ return (patricia);
+}
+
+
+/*
+ * if func is supplied, it will be called as func(node->data)
+ * before deleting the node
+ */
+
+void
+ndpi_Clear_Patricia (patricia_tree_t *patricia, void_fn_t func)
+{
+ assert (patricia);
+ if(patricia->head) {
+
+ patricia_node_t *Xstack[PATRICIA_MAXBITS+1];
+ patricia_node_t **Xsp = Xstack;
+ patricia_node_t *Xrn = patricia->head;
+
+ while (Xrn) {
+ patricia_node_t *l = Xrn->l;
+ patricia_node_t *r = Xrn->r;
+
+ if(Xrn->prefix) {
+ ndpi_Deref_Prefix (Xrn->prefix);
+ if(Xrn->data && func)
+ func (Xrn->data);
+ }
+ else {
+ assert (Xrn->data == NULL);
+ }
+ ndpi_DeleteEntry (Xrn);
+ patricia->num_active_node--;
+
+ if(l) {
+ if(r) {
+ *Xsp++ = r;
+ }
+ Xrn = l;
+ } else if(r) {
+ Xrn = r;
+ } else if(Xsp != Xstack) {
+ Xrn = *(--Xsp);
+ } else {
+ Xrn = NULL;
+ }
+ }
+ }
+ assert (patricia->num_active_node == 0);
+ /* ndpi_DeleteEntry (patricia); */
+}
+
+
+void
+ndpi_Destroy_Patricia (patricia_tree_t *patricia, void_fn_t func)
+{
+ ndpi_Clear_Patricia (patricia, func);
+ ndpi_DeleteEntry (patricia);
+ num_active_patricia--;
+}
+
+
+/*
+ * if func is supplied, it will be called as func(node->prefix, node->data)
+ */
+
+void
+ndpi_patricia_process (patricia_tree_t *patricia, void_fn2_t func)
+{
+ patricia_node_t *node;
+ assert (func);
+
+ PATRICIA_WALK (patricia->head, node) {
+ func (node->prefix, node->data);
+ } PATRICIA_WALK_END;
+}
+
+size_t
+ndpi_patricia_walk_inorder(patricia_node_t *node, void_fn2_t func)
+{
+ size_t n = 0;
+ assert(func);
+
+ if(node->l) {
+ n += ndpi_patricia_walk_inorder(node->l, func);
+ }
+
+ if(node->prefix) {
+ func(node->prefix, node->data);
+ n++;
+ }
+
+ if(node->r) {
+ n += ndpi_patricia_walk_inorder(node->r, func);
+ }
+
+ return n;
+}
+
+
+patricia_node_t *
+ndpi_patricia_search_exact (patricia_tree_t *patricia, prefix_t *prefix)
+{
+ patricia_node_t *node;
+ u_char *addr;
+ u_int bitlen;
+
+ assert (patricia);
+ assert (prefix);
+ assert (prefix->bitlen <= patricia->maxbits);
+
+ if(patricia->head == NULL)
+ return (NULL);
+
+ node = patricia->head;
+ addr = prefix_touchar (prefix);
+ bitlen = prefix->bitlen;
+
+ while (node->bit < bitlen) {
+
+ if(BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) {
+#ifdef PATRICIA_DEBUG
+ if(node->prefix)
+ fprintf (stderr, "patricia_search_exact: take right %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+ else
+ fprintf (stderr, "patricia_search_exact: take right at %u\n",
+ node->bit);
+#endif /* PATRICIA_DEBUG */
+ node = node->r;
+ }
+ else {
+#ifdef PATRICIA_DEBUG
+ if(node->prefix)
+ fprintf (stderr, "patricia_search_exact: take left %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+ else
+ fprintf (stderr, "patricia_search_exact: take left at %u\n",
+ node->bit);
+#endif /* PATRICIA_DEBUG */
+ node = node->l;
+ }
+
+ if(node == NULL)
+ return (NULL);
+ }
+
+#ifdef PATRICIA_DEBUG
+ if(node->prefix)
+ fprintf (stderr, "patricia_search_exact: stop at %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+ else
+ fprintf (stderr, "patricia_search_exact: stop at %u\n", node->bit);
+#endif /* PATRICIA_DEBUG */
+ if(node->bit > bitlen || node->prefix == NULL)
+ return (NULL);
+ assert (node->bit == bitlen);
+ assert (node->bit == node->prefix->bitlen);
+ if(ndpi_comp_with_mask (ndpi_prefix_tochar (node->prefix), ndpi_prefix_tochar (prefix),
+ bitlen)) {
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_search_exact: found %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ return (node);
+ }
+ return (NULL);
+}
+
+
+/* if inclusive != 0, "best" may be the given prefix itself */
+patricia_node_t *
+ndpi_patricia_search_best2 (patricia_tree_t *patricia, prefix_t *prefix, int inclusive)
+{
+ patricia_node_t *node;
+ patricia_node_t *stack[PATRICIA_MAXBITS + 1];
+ u_char *addr;
+ u_int bitlen;
+ int cnt = 0;
+
+ assert (patricia);
+ assert (prefix);
+ assert (prefix->bitlen <= patricia->maxbits);
+
+ if(patricia->head == NULL)
+ return (NULL);
+
+ node = patricia->head;
+ addr = prefix_touchar (prefix);
+ bitlen = prefix->bitlen;
+
+ while (node->bit < bitlen) {
+
+ if(node->prefix) {
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_search_best: push %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ stack[cnt++] = node;
+ }
+
+ if(BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) {
+#ifdef PATRICIA_DEBUG
+ if(node->prefix)
+ fprintf (stderr, "patricia_search_best: take right %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+ else
+ fprintf (stderr, "patricia_search_best: take right at %u\n",
+ node->bit);
+#endif /* PATRICIA_DEBUG */
+ node = node->r;
+ }
+ else {
+#ifdef PATRICIA_DEBUG
+ if(node->prefix)
+ fprintf (stderr, "patricia_search_best: take left %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+ else
+ fprintf (stderr, "patricia_search_best: take left at %u\n",
+ node->bit);
+#endif /* PATRICIA_DEBUG */
+ node = node->l;
+ }
+
+ if(node == NULL)
+ break;
+ }
+
+ if(inclusive && node && node->prefix)
+ stack[cnt++] = node;
+
+#ifdef PATRICIA_DEBUG
+ if(node == NULL)
+ fprintf (stderr, "patricia_search_best: stop at null\n");
+ else if(node->prefix)
+ fprintf (stderr, "patricia_search_best: stop at %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+ else
+ fprintf (stderr, "patricia_search_best: stop at %u\n", node->bit);
+#endif /* PATRICIA_DEBUG */
+
+ if(cnt <= 0)
+ return (NULL);
+
+ while (--cnt >= 0) {
+ node = stack[cnt];
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_search_best: pop %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ if(ndpi_comp_with_mask (ndpi_prefix_tochar (node->prefix),
+ ndpi_prefix_tochar (prefix),
+ node->prefix->bitlen) && node->prefix->bitlen <= bitlen) {
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_search_best: found %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ return (node);
+ }
+ }
+ return (NULL);
+}
+
+
+patricia_node_t *
+ndpi_patricia_search_best (patricia_tree_t *patricia, prefix_t *prefix)
+{
+ return (ndpi_patricia_search_best2 (patricia, prefix, 1));
+}
+
+
+patricia_node_t *
+ndpi_patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
+{
+ patricia_node_t *node, *new_node, *parent, *glue;
+ u_char *addr, *test_addr;
+ u_int bitlen, check_bit, differ_bit;
+ int i, j;
+
+ assert (patricia);
+ assert (prefix);
+ assert (prefix->bitlen <= patricia->maxbits);
+
+ if(patricia->head == NULL) {
+ node = (patricia_node_t*)ndpi_calloc(1, sizeof *node);
+ node->bit = prefix->bitlen;
+ node->prefix = ndpi_Ref_Prefix (prefix);
+ node->parent = NULL;
+ node->l = node->r = NULL;
+ node->data = NULL;
+ patricia->head = node;
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_lookup: new_node #0 %s/%d (head)\n",
+ ndpi_prefix_toa (prefix), prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ patricia->num_active_node++;
+ return (node);
+ }
+
+ addr = prefix_touchar (prefix);
+ bitlen = prefix->bitlen;
+ node = patricia->head;
+
+ while (node->bit < bitlen || node->prefix == NULL) {
+
+ if(node->bit < patricia->maxbits &&
+ BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) {
+ if(node->r == NULL)
+ break;
+#ifdef PATRICIA_DEBUG
+ if(node->prefix)
+ fprintf (stderr, "patricia_lookup: take right %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+ else
+ fprintf (stderr, "patricia_lookup: take right at %u\n", node->bit);
+#endif /* PATRICIA_DEBUG */
+ node = node->r;
+ }
+ else {
+ if(node->l == NULL)
+ break;
+#ifdef PATRICIA_DEBUG
+ if(node->prefix)
+ fprintf (stderr, "patricia_lookup: take left %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+ else
+ fprintf (stderr, "patricia_lookup: take left at %u\n", node->bit);
+#endif /* PATRICIA_DEBUG */
+ node = node->l;
+ }
+
+ assert (node);
+ }
+
+ assert (node->prefix);
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_lookup: stop at %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+
+ test_addr = prefix_touchar (node->prefix);
+ /* find the first bit different */
+ check_bit = (node->bit < bitlen)? node->bit: bitlen;
+ differ_bit = 0;
+ for (i = 0; (u_int)i*8 < check_bit; i++) {
+ int r;
+
+ if((r = (addr[i] ^ test_addr[i])) == 0) {
+ differ_bit = (i + 1) * 8;
+ continue;
+ }
+ /* I know the better way, but for now */
+ for (j = 0; j < 8; j++) {
+ if(BIT_TEST (r, (0x80 >> j)))
+ break;
+ }
+ /* must be found */
+ assert (j < 8);
+ differ_bit = i * 8 + j;
+ break;
+ }
+ if(differ_bit > check_bit)
+ differ_bit = check_bit;
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_lookup: differ_bit %d\n", differ_bit);
+#endif /* PATRICIA_DEBUG */
+
+ parent = node->parent;
+ while (parent && parent->bit >= differ_bit) {
+ node = parent;
+ parent = node->parent;
+#ifdef PATRICIA_DEBUG
+ if(node->prefix)
+ fprintf (stderr, "patricia_lookup: up to %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+ else
+ fprintf (stderr, "patricia_lookup: up to %u\n", node->bit);
+#endif /* PATRICIA_DEBUG */
+ }
+
+ if(differ_bit == bitlen && node->bit == bitlen) {
+ if(node->prefix) {
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_lookup: found %s/%d\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ return (node);
+ }
+ node->prefix = ndpi_Ref_Prefix (prefix);
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_lookup: new node #1 %s/%d (glue mod)\n",
+ ndpi_prefix_toa (prefix), prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ assert (node->data == NULL);
+ return (node);
+ }
+
+ new_node = (patricia_node_t*)ndpi_calloc(1, sizeof *new_node);
+ new_node->bit = prefix->bitlen;
+ new_node->prefix = ndpi_Ref_Prefix (prefix);
+ new_node->parent = NULL;
+ new_node->l = new_node->r = NULL;
+ new_node->data = NULL;
+ patricia->num_active_node++;
+
+ if(node->bit == differ_bit) {
+ new_node->parent = node;
+ if(node->bit < patricia->maxbits &&
+ BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) {
+ assert (node->r == NULL);
+ node->r = new_node;
+ }
+ else {
+ assert (node->l == NULL);
+ node->l = new_node;
+ }
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_lookup: new_node #2 %s/%d (child)\n",
+ ndpi_prefix_toa (prefix), prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ return (new_node);
+ }
+
+ if(bitlen == differ_bit) {
+ if(bitlen < patricia->maxbits &&
+ BIT_TEST (test_addr[bitlen >> 3], 0x80 >> (bitlen & 0x07))) {
+ new_node->r = node;
+ }
+ else {
+ new_node->l = node;
+ }
+ new_node->parent = node->parent;
+ if(node->parent == NULL) {
+ assert (patricia->head == node);
+ patricia->head = new_node;
+ }
+ else if(node->parent->r == node) {
+ node->parent->r = new_node;
+ }
+ else {
+ node->parent->l = new_node;
+ }
+ node->parent = new_node;
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_lookup: new_node #3 %s/%d (parent)\n",
+ ndpi_prefix_toa (prefix), prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ }
+ else {
+ glue = (patricia_node_t*)ndpi_calloc(1, sizeof *glue);
+ glue->bit = differ_bit;
+ glue->prefix = NULL;
+ glue->parent = node->parent;
+ glue->data = NULL;
+ patricia->num_active_node++;
+ if(differ_bit < patricia->maxbits &&
+ BIT_TEST (addr[differ_bit >> 3], 0x80 >> (differ_bit & 0x07))) {
+ glue->r = new_node;
+ glue->l = node;
+ }
+ else {
+ glue->r = node;
+ glue->l = new_node;
+ }
+ new_node->parent = glue;
+
+ if(node->parent == NULL) {
+ assert (patricia->head == node);
+ patricia->head = glue;
+ }
+ else if(node->parent->r == node) {
+ node->parent->r = glue;
+ }
+ else {
+ node->parent->l = glue;
+ }
+ node->parent = glue;
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_lookup: new_node #4 %s/%d (glue+node)\n",
+ ndpi_prefix_toa (prefix), prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ }
+ return (new_node);
+}
+
+
+void
+ndpi_patricia_remove (patricia_tree_t *patricia, patricia_node_t *node)
+{
+ patricia_node_t *parent, *child;
+
+ assert (patricia);
+ assert (node);
+
+ if(node->r && node->l) {
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_remove: #0 %s/%d (r & l)\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+
+ /* this might be a placeholder node -- have to check and make sure
+ * there is a prefix aossciated with it ! */
+ if(node->prefix != NULL)
+ ndpi_Deref_Prefix (node->prefix);
+ node->prefix = NULL;
+ /* Also I needed to clear data pointer -- masaki */
+ node->data = NULL;
+ return;
+ }
+
+ if(node->r == NULL && node->l == NULL) {
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_remove: #1 %s/%d (!r & !l)\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ parent = node->parent;
+ ndpi_Deref_Prefix (node->prefix);
+ ndpi_DeleteEntry (node);
+ patricia->num_active_node--;
+
+ if(parent == NULL) {
+ assert (patricia->head == node);
+ patricia->head = NULL;
+ return;
+ }
+
+ if(parent->r == node) {
+ parent->r = NULL;
+ child = parent->l;
+ }
+ else {
+ assert (parent->l == node);
+ parent->l = NULL;
+ child = parent->r;
+ }
+
+ if(parent->prefix)
+ return;
+
+ /* we need to remove parent too */
+
+ if(parent->parent == NULL) {
+ assert (patricia->head == parent);
+ patricia->head = child;
+ }
+ else if(parent->parent->r == parent) {
+ parent->parent->r = child;
+ }
+ else {
+ assert (parent->parent->l == parent);
+ parent->parent->l = child;
+ }
+ child->parent = parent->parent;
+ ndpi_DeleteEntry (parent);
+ patricia->num_active_node--;
+ return;
+ }
+
+#ifdef PATRICIA_DEBUG
+ fprintf (stderr, "patricia_remove: #2 %s/%d (r ^ l)\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+#endif /* PATRICIA_DEBUG */
+ if(node->r) {
+ child = node->r;
+ }
+ else {
+ assert (node->l);
+ child = node->l;
+ }
+ parent = node->parent;
+ child->parent = parent;
+
+ ndpi_Deref_Prefix (node->prefix);
+ ndpi_DeleteEntry (node);
+ patricia->num_active_node--;
+
+ if(parent == NULL) {
+ assert (patricia->head == node);
+ patricia->head = child;
+ return;
+ }
+
+ if(parent->r == node) {
+ parent->r = child;
+ }
+ else {
+ assert (parent->l == node);
+ parent->l = child;
+ }
+}
+
+/* { from demo.c */
+#if 0
+
+patricia_node_t *
+ndpi_make_and_lookup (patricia_tree_t *tree, char *string)
+{
+ prefix_t *prefix;
+ patricia_node_t *node;
+
+ prefix = ndpi_ascii2prefix (AF_INET, string);
+ printf ("make_and_lookup: %s/%d\n", ndpi_prefix_toa (prefix), prefix->bitlen);
+ node = ndpi_patricia_lookup (tree, prefix);
+ ndpi_Deref_Prefix (prefix);
+ return (node);
+}
+
+patricia_node_t *
+ndpi_try_search_exact (patricia_tree_t *tree, char *string)
+{
+ prefix_t *prefix;
+ patricia_node_t *node;
+
+ prefix = ndpi_ascii2prefix (AF_INET, string);
+ printf ("try_search_exact: %s/%d\n", ndpi_prefix_toa (prefix), prefix->bitlen);
+ if((node = patricia_search_exact (tree, prefix)) == NULL) {
+ printf ("try_search_exact: not found\n");
+ }
+ else {
+ printf ("try_search_exact: %s/%d found\n",
+ ndpi_prefix_toa (node->prefix), node->prefix->bitlen);
+ }
+ ndpi_Deref_Prefix (prefix);
+ return (node);
+}
+
+void
+ndpi_lookup_then_remove (patricia_tree_t *tree, char *string)
+{
+ patricia_node_t *node;
+
+ if((node = try_search_exact (tree, string)))
+ patricia_remove (tree, node);
+}
+#endif
+
+/* } */
diff --git a/src/lib/third_party/src/sort.c b/src/lib/third_party/src/sort.c
new file mode 100644
index 000000000..d6545e85a
--- /dev/null
+++ b/src/lib/third_party/src/sort.c
@@ -0,0 +1,130 @@
+/*
+ * A fast, small, non-recursive O(nlog n) sort for the Linux kernel
+ *
+ * Jan 23 2005 Matt Mackall <mpm@selenic.com>
+ */
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#ifdef WIN32
+#include <stdint.h>
+typedef uint32_t u_int32_t;
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#endif
+
+/* This is a function ported from the Linux kernel lib/sort.c */
+
+static void u_int32_t_swap(void *a, void *b, int size)
+{
+ u_int32_t t = *(u_int32_t *)a;
+ *(u_int32_t *)a = *(u_int32_t *)b;
+ *(u_int32_t *)b = t;
+}
+
+static void generic_swap(void *_a, void *_b, int size)
+{
+ char t;
+ char *a = (char*)_a;
+ char *b = (char*)_b;
+
+ do {
+ t = *a;
+ *a++ = *b;
+ *b++ = t;
+ } while (--size > 0);
+}
+
+/**
+ * sort - sort an array of elements
+ * @base: pointer to data to sort
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp_func: pointer to comparison function
+ * @swap_func: pointer to swap function or NULL
+ *
+ * This function does a heapsort on the given array. You may provide a
+ * swap_func function optimized to your element type.
+ *
+ * Sorting time is O(n log n) both on average and worst-case. While
+ * qsort is about 20% faster on average, it suffers from exploitable
+ * O(n*n) worst-case behavior and extra memory requirements that make
+ * it less suitable for kernel use.
+ */
+
+void sort(void *_base, size_t num, size_t size,
+ int (*cmp_func)(const void *, const void *),
+ void (*swap_func)(void *, void *, int size))
+{
+ /* pre-scale counters for performance */
+ int i = (num/2 - 1) * size, n = num * size, c, r;
+ char *base = (char*)_base;
+
+ if (!swap_func)
+ swap_func = (size == 4 ? u_int32_t_swap : generic_swap);
+
+ /* heapify */
+ for ( ; i >= 0; i -= size) {
+ for (r = i; r * 2 + size < n; r = c) {
+ c = r * 2 + size;
+ if (c < n - size &&
+ cmp_func(base + c, base + c + size) < 0)
+ c += size;
+ if (cmp_func(base + r, base + c) >= 0)
+ break;
+ swap_func(base + r, base + c, size);
+ }
+ }
+
+ /* sort */
+ for (i = n - size; i > 0; i -= size) {
+ swap_func(base, base + i, size);
+ for (r = 0; r * 2 + size < i; r = c) {
+ c = r * 2 + size;
+ if (c < i - size &&
+ cmp_func(base + c, base + c + size) < 0)
+ c += size;
+ if (cmp_func(base + r, base + c) >= 0)
+ break;
+ swap_func(base + r, base + c, size);
+ }
+ }
+}
+
+
+#if 0
+/* a simple boot-time regression test */
+
+int cmpint(const void *a, const void *b)
+{
+ return *(int *)a - *(int *)b;
+}
+
+int main(int argc, char *argv[]) {
+ int *a, i, r = 1;
+
+ a = ndpi_malloc(1000 * sizeof(int));
+
+ printf("testing sort()\n");
+
+ for (i = 0; i < 1000; i++) {
+ r = (r * 725861) % 6599;
+ a[i] = r;
+ }
+
+ sort(a, 1000, sizeof(int), cmpint, NULL);
+
+ for (i = 0; i < 999; i++)
+ if (a[i] > a[i+1]) {
+ printf("sort() failed!\n");
+ break;
+ }
+
+ return 0;
+}
+
+#endif