diff options
author | Luca Deri <deri@Lucas-MacBookPro.local> | 2015-04-19 07:25:59 +0200 |
---|---|---|
committer | Luca Deri <deri@Lucas-MacBookPro.local> | 2015-04-19 07:25:59 +0200 |
commit | 2e5ceac844c32fb52f4f3042be5b872f8b0b4ff0 (patch) | |
tree | 01af171f4af2b86efa64d0166dc540ee5c027c95 /src/lib/protocols | |
parent | 7fa4694dadf869d1de2baa99383308a163902f8f (diff) |
Initial import from SVN
Diffstat (limited to 'src/lib/protocols')
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 |