diff options
author | Campus <campus@ntop.org> | 2015-12-29 18:17:52 +0100 |
---|---|---|
committer | Campus <campus@ntop.org> | 2015-12-29 18:17:52 +0100 |
commit | 60e7e19dab72a37d57bc7854e702264e7d25886d (patch) | |
tree | cbbc7b598035070f47d0a781c01fac28b03f20b3 | |
parent | 6d37ee2970c5866260a3fd66920a6bf6e740b702 (diff) |
wrote new dns dissector - deleted useless part of dns to slim data structures used in nDPI and ntopng
-rw-r--r-- | src/include/ndpi_typedefs.h | 48 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 4 | ||||
-rw-r--r-- | src/lib/protocols/dns.c | 341 |
3 files changed, 110 insertions, 283 deletions
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index d73768f52..c4f4fdf73 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -270,7 +270,12 @@ struct ndpi_udphdr PACK_ON struct ndpi_dns_packet_header { - u_int16_t transaction_id, flags, num_queries, answer_rrs, authority_rrs, additional_rrs; + u_int16_t tr_id; + u_int16_t flags; + u_int16_t num_queries; + u_int16_t num_answers; + u_int16_t authority_rrs; + u_int16_t additional_rrs; } PACK_OFF; typedef union @@ -340,7 +345,7 @@ typedef enum { HTTP_METHOD_CONNECT } ndpi_http_method; -typedef struct ndpi_id_struct { +struct ndpi_id_struct { /** detected_protocol_bitmask: access this bitmask to find out whether an id has used skype or not @@ -436,7 +441,7 @@ typedef struct ndpi_id_struct { #ifdef NDPI_PROTOCOL_RTSP u_int32_t rtsp_ts_set:1; #endif -} ndpi_id_struct; +}; /* ************************************************** */ @@ -628,12 +633,12 @@ struct ndpi_flow_udp_struct { /* ************************************************** */ -typedef struct ndpi_int_one_line_struct { +struct ndpi_int_one_line_struct { const u_int8_t *ptr; u_int16_t len; -} ndpi_int_one_line_struct_t; +}; -typedef struct ndpi_packet_struct { +struct ndpi_packet_struct { const struct ndpi_iphdr *iph; #ifdef NDPI_DETECTION_SUPPORT_IPV6 const struct ndpi_ipv6hdr *iphv6; @@ -688,22 +693,22 @@ typedef struct ndpi_packet_struct { u_int8_t packet_lines_parsed_complete:1, packet_direction:1, empty_line_position_set:1; -} ndpi_packet_struct_t; +}; struct ndpi_detection_module_struct; struct ndpi_flow_struct; -typedef struct ndpi_call_function_struct { +struct ndpi_call_function_struct { NDPI_PROTOCOL_BITMASK detection_bitmask; NDPI_PROTOCOL_BITMASK excluded_protocol_bitmask; NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_bitmask; void (*func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow); u_int8_t detection_feature; -} ndpi_call_function_struct_t; +}; -typedef struct ndpi_subprotocol_conf_struct { +struct ndpi_subprotocol_conf_struct { void (*func) (struct ndpi_detection_module_struct *, char *attr, char *value, int protocol_id); -} ndpi_subprotocol_conf_struct_t; +}; typedef struct { @@ -746,7 +751,8 @@ typedef struct ndpi_proto { #define NDPI_PROTOCOL_NULL { NDPI_PROTOCOL_UNKNOWN , NDPI_PROTOCOL_UNKNOWN } -typedef struct ndpi_detection_module_struct { +struct ndpi_detection_module_struct { + NDPI_PROTOCOL_BITMASK detection_bitmask; NDPI_PROTOCOL_BITMASK generic_http_packet_bitmask; @@ -799,6 +805,7 @@ typedef struct ndpi_detection_module_struct { content_automa, /* Used for HTTP subprotocol_detection */ subprotocol_automa, /* Used for HTTP subprotocol_detection */ bigrams_automa, impossible_bigrams_automa; /* TOR */ + /* IP-based protocol detection */ void *protocols_ptree; @@ -842,11 +849,11 @@ typedef struct ndpi_detection_module_struct { ndpi_proto_defaults_t proto_defaults[NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS]; - u_int8_t match_dns_host_names:1, http_dont_dissect_response:1; + u_int8_t http_dont_dissect_response:1; u_int8_t direction_detect_disable:1; /* disable internal detection of packet direction */ -} ndpi_detection_module_struct_t; +}; -typedef struct ndpi_flow_struct { +struct ndpi_flow_struct { u_int16_t detected_protocol_stack[NDPI_PROTOCOL_HISTORY_SIZE]; #ifndef WIN32 __attribute__ ((__packed__)) @@ -899,12 +906,13 @@ typedef struct ndpi_flow_struct { } http; union { + + /* the only fields useful for nDPI and ntopng */ struct { - u_int8_t num_queries, num_answers, ret_code; - u_int8_t bad_packet /* the received packet looks bad */; - u_int16_t query_type, query_class, rsp_type; + u_int8_t num_answers, ret_code; + u_int16_t query_type; } dns; - + struct { u_int8_t request_code; u_int8_t version; @@ -1003,6 +1011,6 @@ typedef struct ndpi_flow_struct { struct ndpi_flow_struct *flow; struct ndpi_id_struct *src; struct ndpi_id_struct *dst; -} ndpi_flow_struct_t; +}; #endif/* __NDPI_TYPEDEFS_H__ */ diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index dd5022b03..afff64e98 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -1664,10 +1664,6 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(u_int32_t ticks_ ndpi_str->user_data = NULL; #endif - ndpi_str->match_dns_host_names = 1; /* - Set it to 0 to increase library speed avoid - matching host names - */ ndpi_str->ticks_per_second = ticks_per_second; ndpi_str->tcp_max_retransmission_window_size = NDPI_DEFAULT_MAX_TCP_RETRANSMISSION_WINDOW_SIZE; ndpi_str->directconnect_connection_ip_tick_timeout = diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c index 3b4322823..ea136f453 100644 --- a/src/lib/protocols/dns.c +++ b/src/lib/protocols/dns.c @@ -1,7 +1,9 @@ /* * dns.c * - * Copyright (C) 2012-15 - ntop.org + * Copyright (C) 2012-16 - ntop.org + * + * Michele Campus - <campus@ntop.org> * * This file is part of nDPI, an open source deep packet inspection * library based on the OpenDPI and PACE technology by ipoque GmbH @@ -21,282 +23,103 @@ * */ - #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)); -} - -/* *********************************************** */ +#define FLAGS_MASK 0x8000 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"); + int x; + u_int8_t is_query, ret_code; + u_int16_t s_port = 0; + u_int16_t d_port = 0; - 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 ndpi_dns_packet_header))) { - int i = packet->tcp ? 2 : 0; - struct ndpi_dns_packet_header header, *dns = (struct ndpi_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 ndpi_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; - 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); - - // Skip past the CLASS (2 octets) and TTL (4 octets) fields. - i += 6; - 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; - } + NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "search DNS.\n"); - i += data_len; - } /* for */ - } - } + if(flow->packet.udp != NULL) + { + s_port = ntohs(flow->packet.udp->source); + d_port = ntohs(flow->packet.udp->dest); + x = 0; + } + else if(flow->packet.tcp != NULL) /* pkt size > 512 bytes */ + { + s_port = ntohs(flow->packet.tcp->source); + d_port = ntohs(flow->packet.tcp->dest); + x = 2; + } + else + { + 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); + } - 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((s_port == 53 || d_port == 53 || d_port == 5355) + && (flow->packet.payload_packet_len > sizeof(struct ndpi_dns_packet_header))) + { + struct ndpi_dns_packet_header * dns_header = (struct ndpi_dns_packet_header*) &flow->packet.payload[x]; + dns_header->tr_id = ntohs(dns_header->tr_id); + dns_header->flags = ntohs(dns_header->flags); + dns_header->num_queries = ntohs(dns_header->num_queries); + dns_header->num_answers = ntohs(dns_header->num_answers); + dns_header->authority_rrs = ntohs(dns_header->authority_rrs); + dns_header->additional_rrs = ntohs(dns_header->additional_rrs); + + /* 0x0000 QUERY */ + if(dns_header->flags & FLAGS_MASK == 0x0000) + is_query = 0; + /* 0x8000 RESPONSE */ + else if(dns_header->flags & FLAGS_MASK != 0x8000) + is_query = 1; + else + { + 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); } - - if(is_dns) { - int j = 0; - int size_host_server_name = sizeof(flow->host_server_name); - - 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 < (size_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] != 0) { - char a_buf[32]; - int i; - - for(i=0; i<num_a_records && j < size_host_server_name; i++) { - j += snprintf((char*)&flow->host_server_name[j], size_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_host_subprotocol(ndpi_struct, flow, - (char *)flow->host_server_name, - strlen((const char*)flow->host_server_name), - NDPI_PROTOCOL_DNS); - } - - 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_host_subprotocol() has - matched a subprotocol - */ - NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "found DNS.\n"); - ndpi_set_detected_protocol(ndpi_struct, flow, (dport == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN); - } - } else { - flow->protos.dns.bad_packet = 1; + + /* extract host name server */ + ret_code = (is_query == 0) ? 0 : (dns_header->flags & 0x0F); + int j = 0; + int off = sizeof(struct ndpi_dns_packet_header) + 1; + while((flow->packet.payload[off] != '\0')) + { + flow->host_server_name[j] = flow->packet.payload[off]; + if(flow->host_server_name[j] < ' ') + flow->host_server_name[j] = '.'; + off++; + j++; + } + flow->host_server_name[j] = '\0'; + + flow->protos.dns.num_answers = (u_int8_t) (dns_header->num_answers + dns_header->authority_rrs + dns_header->additional_rrs); + flow->protos.dns.ret_code = ret_code; + + if(j > 0) + ndpi_match_host_subprotocol(ndpi_struct, flow, + (char *)flow->host_server_name, + strlen((const char*)flow->host_server_name), + NDPI_PROTOCOL_DNS); + + if(flow->packet.detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) + { + /** + Do not set the protocol with DNS if ndpi_match_host_subprotocol() has + matched a subprotocol + **/ + NDPI_LOG(NDPI_PROTOCOL_DNS, ndpi_struct, NDPI_LOG_DEBUG, "found DNS.\n"); + ndpi_set_detected_protocol(ndpi_struct, flow, (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN); + } + else + { 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); } } } - void init_dns_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) { ndpi_set_bitmask_protocol_detection("DNS", ndpi_struct, detection_bitmask, *id, |