aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuca Deri <deri@ntop.org>2019-10-15 23:06:30 +0200
committerLuca Deri <deri@ntop.org>2019-10-15 23:06:30 +0200
commitd5c918d2586d7985b9f326d776171f8ad99003aa (patch)
tree8039a8d589ff0503fb7b1ee9e23f8d85df27bb4a /src
parentcbe20d3740c19dd59150c9764a549857902d16b8 (diff)
Initial implementation of ndpi_flow2json APi call
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_api.h9
-rw-r--r--src/lib/ndpi_main.c2
-rw-r--r--src/lib/ndpi_utils.c188
3 files changed, 197 insertions, 2 deletions
diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h
index 3c30f1f69..a1613458f 100644
--- a/src/include/ndpi_api.h
+++ b/src/include/ndpi_api.h
@@ -836,6 +836,15 @@ extern "C" {
u_int8_t min_string_match_len, /* Will return 0 if no string > min_string_match_len have been found */
char *outbuf, u_int outbuf_len);
char* ndpi_ssl_version2str(u_int16_t version, u_int8_t *unknown_tls_version);
+ void ndpi_patchIPv6Address(char *str);
+ int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int8_t ip_version,
+ u_int8_t l4_protocol, u_int16_t vlan_id,
+ u_int32_t src_v4, u_int32_t dst_v4,
+ struct ndpi_in6_addr *src_v6, struct ndpi_in6_addr *dst_v6,
+ u_int16_t src_port, u_int16_t dst_port,
+ ndpi_serializer *serializer);
/* Serializer */
int ndpi_init_serializer_ll(ndpi_serializer *serializer, ndpi_serialization_format fmt,
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index a72917b7f..7c6e2bc56 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -583,6 +583,8 @@ static char* string2hex(const char *pat) {
return(hexbuf);
}
+/* ******************************************************************** */
+
static int init_hyperscan(struct ndpi_detection_module_struct *ndpi_str) {
u_int num_patterns = 0, i, j;
char **expressions;
diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c
index de268c191..979596d5d 100644
--- a/src/lib/ndpi_utils.c
+++ b/src/lib/ndpi_utils.c
@@ -714,7 +714,7 @@ char* ndpi_ssl_version2str(u_int16_t version, u_int8_t *unknown_tls_version) {
static char v[12];
*unknown_tls_version = 0;
-
+
switch(version) {
case 0x0300: return("SSLv3");
case 0x0301: return("TLSv1");
@@ -731,8 +731,192 @@ char* ndpi_ssl_version2str(u_int16_t version, u_int8_t *unknown_tls_version) {
*unknown_tls_version = 1;
snprintf(v, sizeof(v), "TLS (%04X)", version);
-
+
return(v);
}
+/* ***************************************************** */
+
+void ndpi_patchIPv6Address(char *str) {
+ int i = 0, j = 0;
+
+ while(str[i] != '\0') {
+ if((str[i] == ':')
+ && (str[i+1] == '0')
+ && (str[i+2] == ':')) {
+ str[j++] = ':';
+ str[j++] = ':';
+ i += 3;
+ } else
+ str[j++] = str[i++];
+ }
+
+ if(str[j] != '\0') str[j] = '\0';
+}
+
+/* ********************************** */
+
+int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int8_t ip_version,
+ u_int8_t l4_protocol, u_int16_t vlan_id,
+ u_int32_t src_v4, u_int32_t dst_v4,
+ struct ndpi_in6_addr *src_v6, struct ndpi_in6_addr *dst_v6,
+ u_int16_t src_port, u_int16_t dst_port,
+ ndpi_serializer *serializer) {
+ u_int16_t proto = flow->detected_protocol_stack[0] ? flow->detected_protocol_stack[0] : flow->detected_protocol_stack[1];
+ char buf[48], src_name[32], dst_name[32];
+
+ if(ndpi_init_serializer(serializer, ndpi_serialization_format_json) == -1)
+ return(-1);
+
+ if(ip_version == 4) {
+ inet_ntop(AF_INET, &src_v4, src_name, sizeof(src_name));
+ inet_ntop(AF_INET, &dst_v4, dst_name, sizeof(dst_name));
+ } else {
+ inet_ntop(AF_INET6, src_v6, src_name, sizeof(src_name));
+ inet_ntop(AF_INET6, dst_v6, dst_name, sizeof(dst_name));
+ /* For consistency across platforms replace :0: with :: */
+ ndpi_patchIPv6Address(src_name), ndpi_patchIPv6Address(dst_name);
+ }
+
+ ndpi_serialize_string_string(serializer, "src_ip", src_name);
+ ndpi_serialize_string_string(serializer, "dest_ip", dst_name);
+ ndpi_serialize_string_uint32(serializer, "src_port", src_port);
+ ndpi_serialize_string_uint32(serializer, "dst_port", dst_port);
+
+ switch(l4_protocol) {
+ case IPPROTO_TCP:
+ ndpi_serialize_string_string(serializer, "proto", "TCP");
+ break;
+
+ case IPPROTO_UDP:
+ ndpi_serialize_string_string(serializer, "proto", "UDP");
+ break;
+
+ case IPPROTO_ICMP:
+ ndpi_serialize_string_string(serializer, "proto", "ICMP");
+ break;
+
+ default:
+ ndpi_serialize_string_uint32(serializer, "proto", l4_protocol);
+ break;
+ }
+
+ ndpi_serialize_string_string(serializer, "app_proto", ndpi_get_proto_name(ndpi_struct, proto));
+
+ switch(proto) {
+ case NDPI_PROTOCOL_DHCP:
+ ndpi_serialize_start_of_block(serializer, "dhcp");
+ ndpi_serialize_string_string(serializer, "fingerprint", flow->protos.dhcp.fingerprint);
+ ndpi_serialize_end_of_block(serializer);
+ break;
+
+ case NDPI_PROTOCOL_BITTORRENT:
+ {
+ u_int i, j, n = 0;
+ char bittorent_hash[32];
+
+ for(i=0, j = 0; j < sizeof(bittorent_hash)-1; i++) {
+ sprintf(&bittorent_hash[j], "%02x",
+ flow->protos.bittorrent.hash[i]);
+
+ j += 2, n += flow->protos.bittorrent.hash[i];
+ }
+
+ if(n == 0) bittorent_hash[0] = '\0';
+
+ ndpi_serialize_start_of_block(serializer, "bittorrent");
+ ndpi_serialize_string_string(serializer, "hash", bittorent_hash);
+ ndpi_serialize_end_of_block(serializer);
+ }
+ break;
+
+ case NDPI_PROTOCOL_DNS:
+ ndpi_serialize_start_of_block(serializer, "dns");
+ ndpi_serialize_string_uint32(serializer, "num_queries", flow->protos.dns.num_queries);
+ ndpi_serialize_string_uint32(serializer, "num_answers", flow->protos.dns.num_answers);
+ ndpi_serialize_string_uint32(serializer, "reply_code", flow->protos.dns.reply_code);
+ ndpi_serialize_string_uint32(serializer, "query_type", flow->protos.dns.query_type);
+ ndpi_serialize_string_uint32(serializer, "rsp_type", flow->protos.dns.rsp_type);
+
+ inet_ntop(AF_INET, &flow->protos.dns.rsp_addr, buf, sizeof(buf));
+ ndpi_serialize_string_string(serializer, "rsp_addr", buf);
+ ndpi_serialize_end_of_block(serializer);
+ break;
+
+ case NDPI_PROTOCOL_MDNS:
+ ndpi_serialize_start_of_block(serializer, "mdns");
+ ndpi_serialize_string_string(serializer, "answer", flow->protos.mdns.answer);
+ ndpi_serialize_end_of_block(serializer);
+ break;
+
+ case NDPI_PROTOCOL_UBNTAC2:
+ ndpi_serialize_start_of_block(serializer, "ubntac2");
+ ndpi_serialize_string_string(serializer, "version", flow->protos.ubntac2.version);
+ ndpi_serialize_end_of_block(serializer);
+ break;
+
+ case NDPI_PROTOCOL_KERBEROS:
+ ndpi_serialize_start_of_block(serializer, "kerberos");
+ ndpi_serialize_string_string(serializer, "cname", flow->protos.kerberos.cname);
+ ndpi_serialize_string_string(serializer, "realm", flow->protos.kerberos.realm);
+ ndpi_serialize_end_of_block(serializer);
+ break;
+
+ case NDPI_PROTOCOL_HTTP:
+ ndpi_serialize_start_of_block(serializer, "http");
+ if(flow->host_server_name[0] != '\0')
+ ndpi_serialize_string_string(serializer, "hostname", (const char*)flow->host_server_name);
+ ndpi_serialize_string_string(serializer, "url", flow->http.url);
+ ndpi_serialize_string_uint32(serializer, "code", flow->http.response_status_code);
+ ndpi_serialize_end_of_block(serializer);
+ break;
+
+ case NDPI_PROTOCOL_SSH:
+ ndpi_serialize_start_of_block(serializer, "ssh");
+ ndpi_serialize_string_string(serializer, "client_signature", flow->protos.ssh.client_signature);
+ ndpi_serialize_string_string(serializer, "server_signature", flow->protos.ssh.server_signature);
+ ndpi_serialize_string_string(serializer, "hassh_client", flow->protos.ssh.hassh_client);
+ ndpi_serialize_string_string(serializer, "hassh_server", flow->protos.ssh.hassh_server);
+ ndpi_serialize_end_of_block(serializer);
+ break;
+
+ case NDPI_PROTOCOL_TLS:
+ {
+ char notBefore[32], notAfter[32];
+ struct tm a, b;
+ struct tm *before = gmtime_r((const time_t *)&flow->protos.stun_ssl.ssl.notBefore, &a);
+ struct tm *after = gmtime_r((const time_t *)&flow->protos.stun_ssl.ssl.notAfter, &b);
+ u_int i, off;
+
+ strftime(notBefore, sizeof(notBefore), "%F %T", before);
+ strftime(notAfter, sizeof(notAfter), "%F %T", after);
+
+ ndpi_serialize_start_of_block(serializer, "tls");
+ ndpi_serialize_string_uint32(serializer, "version", flow->protos.stun_ssl.ssl.ssl_version);
+ ndpi_serialize_string_string(serializer, "client_cert", flow->protos.stun_ssl.ssl.client_certificate);
+ ndpi_serialize_string_string(serializer, "server_cert", flow->protos.stun_ssl.ssl.server_certificate);
+ ndpi_serialize_string_string(serializer, "issuer", flow->protos.stun_ssl.ssl.server_organization);
+ ndpi_serialize_string_string(serializer, "notbefore", notBefore);
+ ndpi_serialize_string_string(serializer, "notafter", notAfter);
+ ndpi_serialize_string_string(serializer, "ja3", flow->protos.stun_ssl.ssl.ja3_client);
+ ndpi_serialize_string_string(serializer, "ja3s", flow->protos.stun_ssl.ssl.ja3_server);
+ ndpi_serialize_string_uint32(serializer, "unsafe_cipher", flow->protos.stun_ssl.ssl.server_unsafe_cipher);
+ ndpi_serialize_string_string(serializer, "cipher", ndpi_cipher2str(flow->protos.stun_ssl.ssl.server_cipher));
+
+ for(i=0, off=0; i<20; i++)
+ off += snprintf(&buf[off], sizeof(buf)-off,"%s%02X", (i > 0) ? ":" : "",
+ flow->l4.tcp.tls_sha1_certificate_fingerprint[i] & 0xFF);
+
+ ndpi_serialize_string_string(serializer, "fingerprint", buf);
+
+ ndpi_serialize_end_of_block(serializer);
+ }
+ break;
+ } /* switch */
+
+ return(0);
+}
+
/* ********************************** */