aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols
diff options
context:
space:
mode:
authorLuca Deri <deri@Lucas-MacBookPro.local>2015-04-19 07:25:59 +0200
committerLuca Deri <deri@Lucas-MacBookPro.local>2015-04-19 07:25:59 +0200
commit2e5ceac844c32fb52f4f3042be5b872f8b0b4ff0 (patch)
tree01af171f4af2b86efa64d0166dc540ee5c027c95 /src/lib/protocols
parent7fa4694dadf869d1de2baa99383308a163902f8f (diff)
Initial import from SVN
Diffstat (limited to 'src/lib/protocols')
-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
138 files changed, 22488 insertions, 0 deletions
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