Skip to content

Commit

Permalink
Implements support for symbolic host names (#2123)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucaderi committed Oct 29, 2023
1 parent b8e0602 commit 76829b4
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 37 deletions.
7 changes: 6 additions & 1 deletion example/protos.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ host:"api-global.netflix.com"@Netflix
# detected as <L7 proto>.Google but only
# as <L7 proto>
#

ip:213.75.170.11/32:443@CustomProtocol
ip:8.248.73.247:443@AmazonPrime
ip:54.80.47.130@AmazonPrime
Expand All @@ -61,6 +60,12 @@ ipv6:[247f:855b:5e16:3caf::]/64@CustomProtocolF
ipv6:[fe80::76ac:b9ff:fe6c:c124]:12717@CustomProtocolG
ipv6:[fe80::76ac:b9ff:fe6c:c124]:12718@CustomProtocolH

#
# You can use symbolic IP addreses if you want
#
ip:www.ntop.org@ntop
ipv6:www.ntop.org@ntop

#
# Risk Exceptions
#
Expand Down
79 changes: 56 additions & 23 deletions src/lib/ndpi_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ static ndpi_risk_info ndpi_known_risks[] = {
{ NDPI_TCP_ISSUES, NDPI_RISK_MEDIUM, CLIENT_FAIR_RISK_PERCENTAGE, NDPI_CLIENT_ACCOUNTABLE },
{ NDPI_FULLY_ENCRYPTED, NDPI_RISK_MEDIUM, CLIENT_FAIR_RISK_PERCENTAGE, NDPI_CLIENT_ACCOUNTABLE },
{ NDPI_TLS_ALPN_SNI_MISMATCH, NDPI_RISK_MEDIUM, CLIENT_FAIR_RISK_PERCENTAGE, NDPI_CLIENT_ACCOUNTABLE },
{ NDPI_MALWARE_HOST_CONTACTED, NDPI_RISK_SEVERE, CLIENT_HIGH_RISK_PERCENTAGE, NDPI_CLIENT_ACCOUNTABLE },
{ NDPI_MALWARE_HOST_CONTACTED, NDPI_RISK_SEVERE, CLIENT_HIGH_RISK_PERCENTAGE, NDPI_CLIENT_ACCOUNTABLE },

/* Leave this as last member */
{ NDPI_MAX_RISK, NDPI_RISK_LOW, CLIENT_FAIR_RISK_PERCENTAGE, NDPI_NO_ACCOUNTABILITY }
Expand Down Expand Up @@ -2698,17 +2698,19 @@ static void ndpi_init_ptree_ipv6(struct ndpi_detection_module_struct *ndpi_str,
/* ******************************************* */

static int ndpi_add_host_ip_subprotocol(struct ndpi_detection_module_struct *ndpi_str,
char *value, u_int16_t protocol_id) {
char *value, u_int16_t protocol_id,
u_int8_t is_ipv6) {
ndpi_patricia_node_t *node;
struct in_addr pin;
struct in6_addr pin6;
int bits = 32;
int is_ipv6 = 0;
char *ptr = strrchr(value, '/');
u_int16_t port = 0; /* Format ip:8.248.73.247 */
/* Format ipv6:[fe80::76ac:b9ff:fe6c:c124]/64 */
char *double_column = NULL;

struct hostent *h;
bool value_ready = false;

if(!ndpi_str->protocols_ptree)
return(-1);

Expand Down Expand Up @@ -2741,6 +2743,7 @@ static int ndpi_add_host_ip_subprotocol(struct ndpi_detection_module_struct *ndp
} else {
/*
Let's check if there is the port defined
Example: ip:8.248.73.247:443@AmazonPrime
Example: ipv6:[fe80::76ac:b9ff:fe6c:c124]:36818@CustomProtocolF
*/
Expand All @@ -2761,12 +2764,41 @@ static int ndpi_add_host_ip_subprotocol(struct ndpi_detection_module_struct *ndp
}

if(!is_ipv6) {
if(inet_pton(AF_INET, value, &pin) != 1)
return(-1);
/* Check if the IP address is symbolic or numeric */
unsigned int d[4];
char tail[16] = { '\0' };
int c = sscanf(value, "%3u.%3u.%3u.%3u%s", &d[0], &d[1], &d[2], &d[3], tail);

if ((c != 4) || tail[0]) {
/* This might be a symbolic IPv4 address */

if((h = gethostbyname2(value, AF_INET)) != NULL) {
memcpy(&pin, h->h_addr_list[0], sizeof(pin));
value_ready = true;
}
}

if(!value_ready) {
if(inet_pton(AF_INET, value, &pin) != 1)
return(-1);
}

node = add_to_ptree(ndpi_str->protocols_ptree, AF_INET, &pin, bits);
} else {
if(inet_pton(AF_INET6, value, &pin6) != 1)
return(-1);
if(strchr(value, ':') == NULL) {
/* This might be a symbolic IPv6 address */

if((h = gethostbyname2(value, AF_INET6)) != NULL) {
memcpy(&pin6, h->h_addr_list[0], sizeof(pin6));
value_ready = true;
}
}

if(!value_ready) {
if(inet_pton(AF_INET6, value, &pin6) != 1)
return(-1);
}

node = add_to_ptree(ndpi_str->protocols_ptree6, AF_INET6, &pin6, bits);
}

Expand Down Expand Up @@ -3668,16 +3700,16 @@ int ndpi_match_custom_category(struct ndpi_detection_module_struct *ndpi_str,
char buf[128];
u_int8_t class_id;
u_int max_len = sizeof(buf)-1;

if(name_len > max_len) name_len = max_len;
memcpy(buf, name, name_len);
buf[name_len] = '\0';

if(ndpi_domain_classify_contains(ndpi_str->custom_categories.sc_hostnames,
&class_id, buf)) {
*category = (ndpi_protocol_category_t)class_id;
return(0);
} else
} else
return(-1); /* Not found */
#endif
}
Expand Down Expand Up @@ -4300,13 +4332,14 @@ int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,
char *attr = elem, *value = NULL;
ndpi_port_range range;
int is_tcp = 0, is_udp = 0, is_ip = 0;
u_int8_t is_ipv6_ip = 0;

if(strncmp(attr, "tcp:", 4) == 0)
is_tcp = 1, value = &attr[4];
else if(strncmp(attr, "udp:", 4) == 0)
is_udp = 1, value = &attr[4];
else if(strncmp(attr, "ipv6:", 5) == 0)
is_ip = 1, value = &attr[5];
is_ip = 1, is_ipv6_ip = 1, value = &attr[5];
else if(strncmp(attr, "ip:", 3) == 0)
is_ip = 1, value = &attr[3];
else if(strncmp(attr, "host:", 5) == 0) {
Expand Down Expand Up @@ -4374,7 +4407,7 @@ int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str,

if(rc != 0) ret = rc;
} else if(is_ip) {
int rc = ndpi_add_host_ip_subprotocol(ndpi_str, value, subprotocol_id);
int rc = ndpi_add_host_ip_subprotocol(ndpi_str, value, subprotocol_id, is_ipv6_ip);

if(rc != 0)
return(rc);
Expand Down Expand Up @@ -4510,10 +4543,10 @@ int ndpi_load_category_file(struct ndpi_detection_module_struct *ndpi_str,

while((line[len] == '\n') || (line[len] == '\r'))
line[len--] = '\0';

while((line[0] == '-') || (line[0] == '.'))
line++;

if(ndpi_load_category(ndpi_str, line, category_id, NULL) > 0)
num_loaded++;
}
Expand Down Expand Up @@ -7372,7 +7405,7 @@ int ndpi_fill_ip_protocol_category(struct ndpi_detection_module_struct *ndpi_str
u_int32_t saddr, u_int32_t daddr,
ndpi_protocol *ret) {
bool match_client = true;

ret->custom_category_userdata = NULL;

if(ndpi_str->custom_categories.categories_loaded &&
Expand Down Expand Up @@ -7408,7 +7441,7 @@ int ndpi_fill_ip_protocol_category(struct ndpi_detection_module_struct *ndpi_str
if((ret->category == CUSTOM_CATEGORY_MALWARE) && (match_client == false)) {
ndpi_set_risk(ndpi_str, flow, NDPI_MALWARE_HOST_CONTACTED, "Client contacted malware host");
}

return(1);
}
}
Expand Down Expand Up @@ -7674,7 +7707,7 @@ static ndpi_protocol ndpi_internal_detection_process_packet(struct ndpi_detectio

if(flow->num_processed_pkts == 1) {
/* first packet of this flow to be analyzed */

#ifdef HAVE_NBPF
if(ndpi_str->nbpf_custom_proto[0].tree != NULL) {
u_int8_t i;
Expand Down Expand Up @@ -7715,7 +7748,7 @@ static ndpi_protocol ndpi_internal_detection_process_packet(struct ndpi_detectio
}
#endif
}

ndpi_connection_tracking(ndpi_str, flow);

/* build ndpi_selection packet bitmask */
Expand Down Expand Up @@ -7763,7 +7796,7 @@ static ndpi_protocol ndpi_internal_detection_process_packet(struct ndpi_detectio
ndpi_fill_protocol_category(ndpi_str, flow, &ret);
else
ret.category = flow->category;

if((!flow->risk_checked)
&& ((ret.master_protocol != NDPI_PROTOCOL_UNKNOWN) || (ret.app_protocol != NDPI_PROTOCOL_UNKNOWN))
) {
Expand Down Expand Up @@ -10188,7 +10221,7 @@ int ndpi_check_dga_name(struct ndpi_detection_module_struct *ndpi_str,
u_int i, j, max_tmp_len = sizeof(tmp)-1;

len = ndpi_snprintf(tmp, max_tmp_len, "%s", name);

if(len < 0) {
NDPI_LOG_DBG2(ndpi_str, "[DGA] too short");
return(0);
Expand Down Expand Up @@ -10298,7 +10331,7 @@ int ndpi_check_dga_name(struct ndpi_detection_module_struct *ndpi_str,

for(word = strtok_r(tmp, ".", &tok_tmp); ; word = strtok_r(NULL, ".", &tok_tmp)) {
u_int num_consecutive_digits = 0, word_len;

if(!word) break; else num_word++;

num_words++;
Expand All @@ -10310,7 +10343,7 @@ int ndpi_check_dga_name(struct ndpi_detection_module_struct *ndpi_str,

if((word_len < 10) && (ndpi_ends_with(ndpi_str, word, "cdn") /* Content Delivery Network ? */))
continue; /* Ignore names (not too long) that end with cdn [ ssl.p.jwpcdn.com or www.awxcdn.com ] */

NDPI_LOG_DBG2(ndpi_str, "[DGA] word(%s) [%s][len: %u]\n", word, name, (unsigned int)strlen(word));

trigram_char_skip = 0;
Expand Down
4 changes: 2 additions & 2 deletions tests/cfgs/default/result/443-chrome.pcap.out
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ Patricia risk mask: 2/0 (search/found)
Patricia risk mask IPv6: 0/0 (search/found)
Patricia risk: 0/0 (search/found)
Patricia risk IPv6: 0/0 (search/found)
Patricia protocols: 2/0 (search/found)
Patricia protocols: 1/1 (search/found)
Patricia protocols IPv6: 0/0 (search/found)

TLS 1 1506 1

1 TCP 178.62.197.130:443 -> 192.168.1.13:53059 [proto: 91/TLS][IP: 0/Unknown][Encrypted][Confidence: Match by port][DPI packets: 1][cat: Web/5][1 pkts/1506 bytes -> 0 pkts/0 bytes][Goodput ratio: 96/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No client to server traffic][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0]
1 TCP 178.62.197.130:443 -> 192.168.1.13:53059 [proto: 91/TLS][IP: 26/ntop][Encrypted][Confidence: Match by port][DPI packets: 1][cat: Web/5][1 pkts/1506 bytes -> 0 pkts/0 bytes][Goodput ratio: 96/0][< 1 sec][Risk: ** Unidirectional Traffic **][Risk Score: 10][Risk Info: No client to server traffic][Plen Bins: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0]
4 changes: 2 additions & 2 deletions tests/cfgs/default/result/443-curl.pcap.out
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Patricia risk mask: 0/0 (search/found)
Patricia risk mask IPv6: 0/0 (search/found)
Patricia risk: 0/0 (search/found)
Patricia risk IPv6: 0/0 (search/found)
Patricia protocols: 2/0 (search/found)
Patricia protocols: 1/1 (search/found)
Patricia protocols IPv6: 0/0 (search/found)

ntop 109 73982 1
Expand All @@ -30,4 +30,4 @@ JA3 Host Stats:
1 192.168.1.13 1


1 TCP 192.168.1.13:55523 <-> 178.62.197.130:443 [proto: 91.26/TLS.ntop][IP: 0/Unknown][Encrypted][Confidence: DPI][DPI packets: 7][cat: Network/14][51 pkts/4260 bytes <-> 58 pkts/69722 bytes][Goodput ratio: 22/94][1.10 sec][Hostname/SNI: www.ntop.org][(Advertised) ALPNs: h2;http/1.1][(Negotiated) ALPN: h2][bytes ratio: -0.885 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 25/19 784/784 122/114][Pkt Len c2s/s2c min/avg/max/stddev: 54/66 84/1202 583/1506 74/562][TLSv1.2][JA3C: 2a26b1a62e40d25d4de3babc9d532f30][ServerNames: www.ntop.org][JA3S: ae53107a2e47ea20c72ac44821a728bf][Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3][Subject: CN=www.ntop.org][Certificate SHA-1: DB:A7:E4:3E:6D:BB:21:AB:68:47:35:E8:0B:8F:15:DF:DB:C7:C9:6F][Firefox][Validity: 2019-12-17 01:17:28 - 2020-03-16 01:17:28][Cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256][Plen Bins: 3,13,1,1,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,0,73,0,0]
1 TCP 192.168.1.13:55523 <-> 178.62.197.130:443 [proto: 91.26/TLS.ntop][IP: 26/ntop][Encrypted][Confidence: DPI][DPI packets: 7][cat: Network/14][51 pkts/4260 bytes <-> 58 pkts/69722 bytes][Goodput ratio: 22/94][1.10 sec][Hostname/SNI: www.ntop.org][(Advertised) ALPNs: h2;http/1.1][(Negotiated) ALPN: h2][bytes ratio: -0.885 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 25/19 784/784 122/114][Pkt Len c2s/s2c min/avg/max/stddev: 54/66 84/1202 583/1506 74/562][TLSv1.2][JA3C: 2a26b1a62e40d25d4de3babc9d532f30][ServerNames: www.ntop.org][JA3S: ae53107a2e47ea20c72ac44821a728bf][Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3][Subject: CN=www.ntop.org][Certificate SHA-1: DB:A7:E4:3E:6D:BB:21:AB:68:47:35:E8:0B:8F:15:DF:DB:C7:C9:6F][Firefox][Validity: 2019-12-17 01:17:28 - 2020-03-16 01:17:28][Cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256][Plen Bins: 3,13,1,1,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,0,73,0,0]
4 changes: 2 additions & 2 deletions tests/cfgs/default/result/443-firefox.pcap.out
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Patricia risk mask: 0/0 (search/found)
Patricia risk mask IPv6: 0/0 (search/found)
Patricia risk: 0/0 (search/found)
Patricia risk IPv6: 0/0 (search/found)
Patricia protocols: 2/0 (search/found)
Patricia protocols: 1/1 (search/found)
Patricia protocols IPv6: 0/0 (search/found)

ntop 667 458067 1
Expand All @@ -30,4 +30,4 @@ JA3 Host Stats:
1 192.168.1.13 1


1 TCP 192.168.1.13:53096 <-> 178.62.197.130:443 [proto: 91.26/TLS.ntop][IP: 0/Unknown][Encrypted][Confidence: DPI][DPI packets: 7][cat: Network/14][316 pkts/28495 bytes <-> 351 pkts/429572 bytes][Goodput ratio: 27/95][8.44 sec][Hostname/SNI: www.ntop.org][(Advertised) ALPNs: h2;http/1.1][(Negotiated) ALPN: h2][TLS Supported Versions: TLSv1.3;TLSv1.2;TLSv1.1;TLSv1][bytes ratio: -0.876 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 32/20 4007/4045 285/250][Pkt Len c2s/s2c min/avg/max/stddev: 54/66 90/1224 583/1506 58/472][TLSv1.2][JA3C: b20b44b18b853ef29ab773e921b03422][ServerNames: www.ntop.org][JA3S: 3653a20186a5b490426131a611e01992][Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3][Subject: CN=www.ntop.org][Certificate SHA-1: DB:A7:E4:3E:6D:BB:21:AB:68:47:35:E8:0B:8F:15:DF:DB:C7:C9:6F][Firefox][Validity: 2019-12-17 01:17:28 - 2020-03-16 01:17:28][Cipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256][Plen Bins: 1,0,1,6,7,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,1,0,0,0,0,1,70,0,0]
1 TCP 192.168.1.13:53096 <-> 178.62.197.130:443 [proto: 91.26/TLS.ntop][IP: 26/ntop][Encrypted][Confidence: DPI][DPI packets: 7][cat: Network/14][316 pkts/28495 bytes <-> 351 pkts/429572 bytes][Goodput ratio: 27/95][8.44 sec][Hostname/SNI: www.ntop.org][(Advertised) ALPNs: h2;http/1.1][(Negotiated) ALPN: h2][TLS Supported Versions: TLSv1.3;TLSv1.2;TLSv1.1;TLSv1][bytes ratio: -0.876 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 32/20 4007/4045 285/250][Pkt Len c2s/s2c min/avg/max/stddev: 54/66 90/1224 583/1506 58/472][TLSv1.2][JA3C: b20b44b18b853ef29ab773e921b03422][ServerNames: www.ntop.org][JA3S: 3653a20186a5b490426131a611e01992][Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3][Subject: CN=www.ntop.org][Certificate SHA-1: DB:A7:E4:3E:6D:BB:21:AB:68:47:35:E8:0B:8F:15:DF:DB:C7:C9:6F][Firefox][Validity: 2019-12-17 01:17:28 - 2020-03-16 01:17:28][Cipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256][Plen Bins: 1,0,1,6,7,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,1,0,0,0,0,1,70,0,0]
4 changes: 2 additions & 2 deletions tests/cfgs/default/result/443-safari.pcap.out
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Patricia risk mask: 0/0 (search/found)
Patricia risk mask IPv6: 0/0 (search/found)
Patricia risk: 0/0 (search/found)
Patricia risk IPv6: 0/0 (search/found)
Patricia protocols: 2/0 (search/found)
Patricia protocols: 1/1 (search/found)
Patricia protocols IPv6: 0/0 (search/found)

ntop 41 19929 1
Expand All @@ -30,4 +30,4 @@ JA3 Host Stats:
1 192.168.1.13 1


1 TCP 192.168.1.13:53031 <-> 178.62.197.130:443 [proto: 91.26/TLS.ntop][IP: 0/Unknown][Encrypted][Confidence: DPI][DPI packets: 7][cat: Network/14][21 pkts/2195 bytes <-> 20 pkts/17734 bytes][Goodput ratio: 36/93][1.10 sec][Hostname/SNI: www.ntop.org][(Advertised) ALPNs: h2;h2-16;h2-15;h2-14;spdy/3.1;spdy/3;http/1.1][(Negotiated) ALPN: h2][bytes ratio: -0.780 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 51/47 695/695 167/168][Pkt Len c2s/s2c min/avg/max/stddev: 66/66 105/887 394/1506 83/661][TLSv1.2][JA3C: a69708a64f853c3bcc214c2c5faf84f3][ServerNames: www.ntop.org][JA3S: f9fcb52580329fb6a9b61d7542087b90][Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3][Subject: CN=www.ntop.org][Certificate SHA-1: DB:A7:E4:3E:6D:BB:21:AB:68:47:35:E8:0B:8F:15:DF:DB:C7:C9:6F][Safari][Validity: 2019-12-17 01:17:28 - 2020-03-16 01:17:28][Cipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256][Plen Bins: 8,21,4,4,0,0,0,4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,4,0,0,0,0,40,0,0]
1 TCP 192.168.1.13:53031 <-> 178.62.197.130:443 [proto: 91.26/TLS.ntop][IP: 26/ntop][Encrypted][Confidence: DPI][DPI packets: 7][cat: Network/14][21 pkts/2195 bytes <-> 20 pkts/17734 bytes][Goodput ratio: 36/93][1.10 sec][Hostname/SNI: www.ntop.org][(Advertised) ALPNs: h2;h2-16;h2-15;h2-14;spdy/3.1;spdy/3;http/1.1][(Negotiated) ALPN: h2][bytes ratio: -0.780 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 51/47 695/695 167/168][Pkt Len c2s/s2c min/avg/max/stddev: 66/66 105/887 394/1506 83/661][TLSv1.2][JA3C: a69708a64f853c3bcc214c2c5faf84f3][ServerNames: www.ntop.org][JA3S: f9fcb52580329fb6a9b61d7542087b90][Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3][Subject: CN=www.ntop.org][Certificate SHA-1: DB:A7:E4:3E:6D:BB:21:AB:68:47:35:E8:0B:8F:15:DF:DB:C7:C9:6F][Safari][Validity: 2019-12-17 01:17:28 - 2020-03-16 01:17:28][Cipher: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256][Plen Bins: 8,21,4,4,0,0,0,4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,4,0,0,0,0,40,0,0]
Loading

0 comments on commit 76829b4

Please sign in to comment.