diff options
author | Campus <campus@ntop.org> | 2016-12-15 12:00:08 +0100 |
---|---|---|
committer | Campus <campus@ntop.org> | 2016-12-15 12:00:08 +0100 |
commit | 39e475b4eaa0be3cd3a3605e43858b8e54b6603b (patch) | |
tree | 8f07fb6aba8256419ea83cd837631fc28f8110f4 /src | |
parent | 03e8111e1b8c78832a344d523945c89431433621 (diff) | |
parent | f5b8855fedb982703b5dc5471c9a788d22639c7b (diff) |
Merge branch 'dev' of https://github.com/dfranusic/nDPI into dfranusic-dev
Diffstat (limited to 'src')
-rw-r--r-- | src/include/ndpi_protocol_ids.h | 3 | ||||
-rw-r--r-- | src/include/ndpi_protocols.h | 2 | ||||
-rw-r--r-- | src/lib/Makefile.am | 1 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 8 | ||||
-rw-r--r-- | src/lib/protocols/smpp.c | 325 |
5 files changed, 338 insertions, 1 deletions
diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h index 7c1ed4a99..0bc70ff5d 100644 --- a/src/include/ndpi_protocol_ids.h +++ b/src/include/ndpi_protocol_ids.h @@ -267,9 +267,10 @@ #define NDPI_PROTOCOL_BJNP 217 #define NDPI_SERVICE_1KXUN 218 #define NDPI_SERVICE_IQIYI 219 +#define NDPI_PROTOCOL_SMPP 220 /* Damir Franusic <df@release14.org> */ /* UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE UPDATE */ -#define NDPI_LAST_IMPLEMENTED_PROTOCOL NDPI_SERVICE_IQIYI +#define NDPI_LAST_IMPLEMENTED_PROTOCOL NDPI_PROTOCOL_SMPP #define NDPI_MAX_SUPPORTED_PROTOCOLS (NDPI_LAST_IMPLEMENTED_PROTOCOL + 1) #define NDPI_MAX_NUM_CUSTOM_PROTOCOLS (NDPI_NUM_BITS-NDPI_LAST_IMPLEMENTED_PROTOCOL) diff --git a/src/include/ndpi_protocols.h b/src/include/ndpi_protocols.h index 16ffb930b..f34a12f13 100644 --- a/src/include/ndpi_protocols.h +++ b/src/include/ndpi_protocols.h @@ -194,6 +194,7 @@ void ndpi_search_git(struct ndpi_detection_module_struct *ndpi_struct, struct nd void ndpi_search_drda(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); void ndpi_search_bjnp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); void ndpi_search_kxun(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); +void ndpi_search_smpp(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); /* --- INIT FUNCTIONS --- */ void init_afp_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); void init_aimini_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); @@ -335,4 +336,5 @@ void init_hangout_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_ void init_drda_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); void init_bjnp_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); void init_kxun_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); +void init_smpp_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask); #endif /* __NDPI_PROTOCOLS_H__ */ diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index aefde3a49..987975c47 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -156,6 +156,7 @@ libndpi_la_SOURCES = ndpi_content_match.c.inc \ protocols/yahoo.c \ protocols/zattoo.c \ protocols/zeromq.c \ + protocols/smpp.c \ third_party/include/actypes.h \ third_party/include/ahocorasick.h \ third_party/include/ndpi_patricia.h \ diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index f457bedd1..59253bf18 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -1573,6 +1573,11 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp no_master, "1kxun", NDPI_PROTOCOL_CATEGORY_MEDIA, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */ ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */ + ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_SMPP, + no_master, + no_master, "SMPP", NDPI_PROTOCOL_CATEGORY_P2P, + ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0), /* TCP */ + ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0)); /* UDP */ /* calling function for host and content matched protocols */ @@ -2629,6 +2634,9 @@ void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *n /* 1KXUN */ init_kxun_dissector(ndpi_struct, &a, detection_bitmask); + /* SMPP */ + init_smpp_dissector(ndpi_struct, &a, detection_bitmask); + /*** Put false-positive sensitive protocols at the end ***/ /* SKYPE */ diff --git a/src/lib/protocols/smpp.c b/src/lib/protocols/smpp.c new file mode 100644 index 000000000..de50f9427 --- /dev/null +++ b/src/lib/protocols/smpp.c @@ -0,0 +1,325 @@ +/* +* smpp.c +* +* Copyright (C) 2016 - Damir Franusic <df@release14.org> +* Copyright (C) 2016 - 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_SMPP + + +static void ndpi_int_smpp_add_connection(struct ndpi_detection_module_struct* ndpi_struct, + struct ndpi_flow_struct* flow) +{ + ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SMPP, NDPI_PROTOCOL_UNKNOWN); +} + +void ndpi_search_smpp_tcp(struct ndpi_detection_module_struct* ndpi_struct, + struct ndpi_flow_struct* flow) +{ + NDPI_LOG(NDPI_PROTOCOL_SMPP, ndpi_struct, NDPI_LOG_DEBUG, "SMPP protocol detection...\n"); + if (flow->packet.detected_protocol_stack[0] != NDPI_PROTOCOL_SMPP){ + struct ndpi_packet_struct* packet = &flow->packet; + // min SMPP packet length = 16 bytes + if (packet->payload_packet_len < 16) { + NDPI_LOG(NDPI_PROTOCOL_SMPP, ndpi_struct, NDPI_LOG_DEBUG, "SMPP excluded\n"); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SMPP); + return; + } + // get PDU length + uint32_t pdu_l = ntohl(get_u_int32_t(packet->payload, 0)); + + NDPI_LOG(NDPI_PROTOCOL_SMPP, + ndpi_struct, + NDPI_LOG_DEBUG, + "calculated PDU Length: %d, received PDU Length: %d\n", + pdu_l, packet->payload_packet_len); + + // if PDU size was invalid, try the following TCP segments, 3 attempts max + if(flow->packet_counter > 3) { + NDPI_LOG(NDPI_PROTOCOL_SMPP, ndpi_struct, NDPI_LOG_DEBUG, "SMPP excluded\n"); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SMPP); + return; + } + // verify PDU length + if(pdu_l != packet->payload_packet_len) { + // check if multiple PDUs included + uint32_t total_pdu_l = pdu_l; + uint32_t tmp_pdu_l = 0; + uint16_t pdu_c = 1; + // loop PDUs (check if lengths are valid) + while(total_pdu_l < packet->payload_packet_len) { + // get next PDU length + tmp_pdu_l = ntohl(get_u_int32_t(packet->payload, total_pdu_l)); + // if zero, return, will try the next TCP segment + if(tmp_pdu_l == 0) return; + // inc total PDU length + total_pdu_l += ntohl(get_u_int32_t(packet->payload, total_pdu_l)); + // inc total PDU count + ++pdu_c; + } + + NDPI_LOG(NDPI_PROTOCOL_SMPP, + ndpi_struct, + NDPI_LOG_DEBUG, + "multiple PDUs included, calculated total PDU Length: %d, PDU count: %d, TCP payload length: %d\n", + total_pdu_l, pdu_c, packet->payload_packet_len); + + // verify multi PDU total length + if(total_pdu_l != packet->payload_packet_len){ + // return, will try the next TCP segment + return; + } + } + + // *** check PDU type *** + uint32_t pdu_type = ntohl(get_u_int32_t(packet->payload, 4)); + // first byte of PDU type is either 0x00 of 0x80 + if(!(packet->payload[4] == 0x00 || packet->payload[4] == 0x80)) { + NDPI_LOG(NDPI_PROTOCOL_SMPP, ndpi_struct, NDPI_LOG_DEBUG, "SMPP excluded\n"); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SMPP); + return; + } + // remove 0x80, get request type pdu + uint32_t pdu_req = pdu_type & 0x00FFFFFF; + // list of known PDU types + if((pdu_req >= 0x00000000 && pdu_req <= 0x00000009) || + (pdu_req == 0x0000000B || pdu_req == 0x00000015 || + pdu_req == 0x00000021 || pdu_req == 0x00000102 || + pdu_req == 0x00000103)){ + + NDPI_LOG(NDPI_PROTOCOL_SMPP, + ndpi_struct, + NDPI_LOG_DEBUG, + "PDU type: %x, Request PDU type = %x\n", + pdu_type, pdu_req); + + // fresult flag + char extra_passed = 1; + // check PDU type specifics + switch(pdu_type){ + // GENERIC_NACK + case 0x80000000: + // body lengh must be zero + if(pdu_l > 16) extra_passed = 0; + break; + + // BIND_RECEIVER + // BIND_TRANSMITTER + // BIND_TRANSCEIVER + case 0x00000001: + case 0x00000002: + case 0x00000009: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // min body lengh = 10 bytes (+16 in header) + if(pdu_l < 26) extra_passed = 0; + break; + + // BIND_RECEIVER_RESP + // BIND_TRANSMITTER_RESP + // BIND_TRANSCEIVER_RESP + case 0x80000001: + case 0x80000002: + case 0x80000009: + // min body length = 2 bytes (+16 in header) + if(pdu_l < 18) extra_passed = 0; + break; + + // OUTBIND + case 0x0000000B: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // min body length = 4 bytes (+16 in header) + if(pdu_l < 20) extra_passed = 0; + break; + + // UNBIND + case 0x00000006: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // body lengh must be zero + if(pdu_l > 16) extra_passed = 0; + break; + + // UNBIND_RESP + case 0x80000006: + // body lengh must be zero + if(pdu_l > 16) extra_passed = 0; + break; + + + // SUBMIT_SM + case 0x00000004: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // min body length = 17 bytes (+16 in header) + if(pdu_l < 33) extra_passed = 0; + break; + + // SUBMIT_SM_RESP + case 0x80000004: + // - if status != 0, body length is 2 bytes min + // - if status > 0, body lenth must be zero + if(get_u_int32_t(packet->payload, 8) != 0){ + if(pdu_l > 16) extra_passed = 0; + + }else if(pdu_l < 18) extra_passed = 0; + break; + + // SUBMIT_MULTI + case 0x00000021: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // min body length = 17 bytes (+16 in header) + if(pdu_l < 33) extra_passed = 0; + break; + + // SUBMIT_MULTI_RESP + case 0x80000021: + // min body length = 10 bytes (+16 in header) + if(pdu_l < 26) extra_passed = 0; + break; + + // DELIVER_SM + case 0x00000005: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // min body length = 17 bytes (+16 in header) + if(pdu_l < 33) extra_passed = 0; + break; + + // DELIVER_SM_RESP + case 0x80000005: + // min body length = 1 byte (+16 in header) + if(pdu_l < 17) extra_passed = 0; + break; + + // DATA_SM + case 0x00000103: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // min body length = 10 bytes (+16 in header) + if(pdu_l < 26) extra_passed = 0; + break; + + // DATA_SM_RESP + case 0x80000103: + // min body length = 2 bytes (+16 in header) + if(pdu_l < 18) extra_passed = 0; + break; + + // QUERY_SM + case 0x00000003: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // min body length = 4 bytes (+16 in header) + if(pdu_l < 20) extra_passed = 0; + break; + + // QUERY_SM_RESP + case 0x80000003: + // min body length = 5 bytes (+16 in header) + if(pdu_l < 21) extra_passed = 0; + break; + + // CANCEL_SM + case 0x00000008: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // min body length = 8 bytes (+16 in header) + if(pdu_l < 24) extra_passed = 0; + break; + + // CANCEL_SM_RESP + case 0x80000008: + // body lenth must be zero + if(pdu_l > 16) extra_passed = 0; + break; + + // REPLACE_SM + case 0x00000007: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // min body length = 9 bytes (+16 in header) + if(pdu_l < 25) extra_passed = 0; + break; + + // REPLACE_SM_RESP + case 0x80000007: + // body lenth must be zero + if(pdu_l > 16) extra_passed = 0; + break; + + // ENQUIRE_LINK + case 0x00000015: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // body lengh must be zero + if(pdu_l > 16) extra_passed = 0; + break; + + // ENQUIRE_LINK_RESP + case 0x80000015: + // body lengh must be zero + if(pdu_l > 16) extra_passed = 0; + break; + + // ALERT_NOTIFICATION + case 0x00000102: + // status field must be NULL + if(get_u_int32_t(packet->payload, 8) != 0) extra_passed = 0; + // min body length = 6 bytes (+16 in header) + if(pdu_l < 22) extra_passed = 0; + break; + + default: break; + } + + // if extra checks passed, set as identified + if(extra_passed) { + NDPI_LOG(NDPI_PROTOCOL_SMPP, ndpi_struct, NDPI_LOG_DEBUG, "SMPP identified...\n"); + ndpi_int_smpp_add_connection(ndpi_struct, flow); + return; + } + } + + // exclude + NDPI_LOG(NDPI_PROTOCOL_SMPP, ndpi_struct, NDPI_LOG_DEBUG, "SMPP excluded\n"); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SMPP); + } +} + + +void init_smpp_dissector(struct ndpi_detection_module_struct* ndpi_struct, + u_int32_t* id, + NDPI_PROTOCOL_BITMASK* detection_bitmask) +{ + ndpi_set_bitmask_protocol_detection("SMPP", ndpi_struct, detection_bitmask, *id, + NDPI_PROTOCOL_SMPP, + ndpi_search_smpp_tcp, + NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION, + SAVE_DETECTION_BITMASK_AS_UNKNOWN, + ADD_TO_DETECTION_BITMASK); + + *id += 1; +} + +#endif // NDPI_PROTOCOL_SMPP |