struct flow_record * process_ip(const struct pcap_pkthdr *h, const void *ip_start, int ip_len, struct flow_key *key) { const unsigned char *payload; int size_payload; // const struct udp_hdr *udp = (const struct udp_hdr *)udp_start; struct flow_record *record = NULL; if (output_level > none) { fprintf(output, " protocol: IP\n"); } payload = (unsigned char *)(ip_start); size_payload = ip_len; /* * Print payload data; it might be binary, so don't just * treat it as a string. */ if (size_payload > 0) { if (output_level > packet_summary) { fprintf(output, " payload (%d bytes):\n", size_payload); print_payload(payload, size_payload); } } /* signify IP by using zero (reserved) port values */ key->sp = key->dp = 0; record = flow_key_get_record(key, CREATE_RECORDS); if (record == NULL) { return NULL; } if (record->op < num_pkt_len) { if (include_zeroes || (size_payload != 0)) { record->pkt_len[record->op] = size_payload; record->pkt_time[record->op] = h->ts; record->op++; } } record->ob += size_payload; flow_record_update_byte_count(record, payload, size_payload); flow_record_update_compact_byte_count(record, payload, size_payload); flow_record_update_byte_dist_mean_var(record, payload, size_payload); wht_update(&record->wht, payload, size_payload, report_wht); return record; }
void wht_unit_test() { struct wht wht, wht2; uint8_t buffer1[8] = { 1, 1, 1, 1, 1, 1, 1, 1 }; uint8_t buffer2[8] = { 1, 0, 1, 0, 1, 0, 1, 0 }; uint8_t buffer3[8] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, // 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf }; uint8_t buffer4[4] = { 255, 254, 253, 252 }; zfile output; output = zattach(stdout, "w"); if (output == NULL) { fprintf(stderr, "error: could not initialize (possibly compressed) stdout for writing\n"); } wht_init(&wht); wht_update(&wht, buffer1, sizeof(buffer1), 1); wht_printf_scaled(&wht, output, sizeof(buffer1)); wht_init(&wht); wht_update(&wht, buffer2, sizeof(buffer2), 1); wht_printf_scaled(&wht, output, sizeof(buffer2)); wht_init(&wht); wht_update(&wht, buffer3, sizeof(buffer3), 1); wht_printf_scaled(&wht, output, sizeof(buffer3)); wht_init(&wht); wht_init(&wht2); wht_update(&wht, buffer4, 1, 1); /* note: only reading first byte */ wht_update(&wht, buffer4, 1, 1); /* note: only reading first byte */ wht_update(&wht, buffer4, 1, 1); /* note: only reading first byte */ wht_printf_scaled_bidir(&wht, 3, &wht2, 0, output); }
void wht_unit_test() { struct wht wht, wht2; uint8_t buffer1[8] = { 1, 1, 1, 1, 1, 1, 1, 1 }; uint8_t buffer2[8] = { 1, 0, 1, 0, 1, 0, 1, 0 }; uint8_t buffer3[8] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, // 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf }; uint8_t buffer4[4] = { 255, 254, 253, 252 }; wht_init(&wht); wht_update(&wht, buffer1, sizeof(buffer1), 1); wht_printf_scaled(&wht, stdout, sizeof(buffer1)); wht_init(&wht); wht_update(&wht, buffer2, sizeof(buffer2), 1); wht_printf_scaled(&wht, stdout, sizeof(buffer2)); wht_init(&wht); wht_update(&wht, buffer3, sizeof(buffer3), 1); wht_printf_scaled(&wht, stdout, sizeof(buffer3)); wht_init(&wht); wht_init(&wht2); wht_update(&wht, buffer4, 1, 1); /* note: only reading first byte */ wht_update(&wht, buffer4, 1, 1); /* note: only reading first byte */ wht_update(&wht, buffer4, 1, 1); /* note: only reading first byte */ wht_printf_scaled_bidir(&wht, 3, &wht2, 0, stdout); }
struct flow_record * process_icmp(const struct pcap_pkthdr *h, const void *start, int len, struct flow_key *key) { int size_icmp_hdr; const unsigned char *payload; int size_payload; const struct icmp_hdr *icmp = (const struct icmp_hdr *)start; struct flow_record *record = NULL; if (output_level > none) { fprintf(output, " protocol: ICMP\n"); } size_icmp_hdr = 8; if (len < size_icmp_hdr) { // fprintf(output, " * Invalid ICMP packet length: %u bytes\n", len); return NULL; } if (output_level > none) { fprintf(output, " type: %d\n", icmp->type); fprintf(output, " code: %d\n", icmp->code); } payload = (unsigned char *)(start + size_icmp_hdr); size_payload = len - size_icmp_hdr; /* * Print payload data; it might be binary, so don't just * treat it as a string. */ if (size_payload > 0) { if (output_level > packet_summary) { fprintf(output, " payload (%d bytes):\n", size_payload); print_payload(payload, size_payload); } } /* * signify ICMP by using sp = dp = 0 (which is an IANA-reserved * value); this key will be distinguished from the keys of TCP and * UDP flows by the key->prot value */ key->sp = 0; key->dp = 0; record = flow_key_get_record(key, CREATE_RECORDS); if (record == NULL) { return NULL; } if (record->op < num_pkt_len) { if (include_zeroes || (size_payload != 0)) { record->pkt_len[record->op] = size_payload; record->pkt_time[record->op] = h->ts; record->op++; } } record->ob += size_payload; flow_record_update_byte_count(record, payload, size_payload); flow_record_update_compact_byte_count(record, payload, size_payload); flow_record_update_byte_dist_mean_var(record, payload, size_payload); wht_update(&record->wht, payload, size_payload, report_wht); return record; }
struct flow_record * process_udp(const struct pcap_pkthdr *h, const void *udp_start, int udp_len, struct flow_key *key) { unsigned int udp_hdr_len; const unsigned char *payload; unsigned int size_payload; const struct udp_hdr *udp = (const struct udp_hdr *)udp_start; struct flow_record *record = NULL; if (output_level > none) { fprintf(output, " protocol: UDP\n"); } udp_hdr_len = 8; if (udp_len < 8) { // fprintf(output, " * Invalid UDP packet length: %u bytes\n", udp_len); return NULL; } payload = (unsigned char *)(udp_start + udp_hdr_len); size_payload = udp_len - udp_hdr_len; if (output_level > none) { fprintf(output, " src port: %d\n", ntohs(udp->src_port)); fprintf(output, " dst port: %d\n", ntohs(udp->dst_port)); fprintf(output, "payload len: %d\n", size_payload); } /* * Print payload data; it might be binary, so don't just * treat it as a string. */ if (size_payload > 0) { if (output_level > packet_summary) { fprintf(output, " payload (%d bytes):\n", size_payload); print_payload(payload, size_payload); } } key->sp = ntohs(udp->src_port); key->dp = ntohs(udp->dst_port); record = flow_key_get_record(key, CREATE_RECORDS); if (record == NULL) { return NULL; } if (record->op < num_pkt_len) { if (report_dns && (key->dp == 53 || key->sp == 53)) { process_dns(h, payload, size_payload, record); } if (include_zeroes || (size_payload != 0)) { record->pkt_len[record->op] = size_payload; record->pkt_time[record->op] = h->ts; record->op++; } } record->ob += size_payload; flow_record_update_byte_count(record, payload, size_payload); flow_record_update_compact_byte_count(record, payload, size_payload); flow_record_update_byte_dist_mean_var(record, payload, size_payload); wht_update(&record->wht, payload, size_payload, report_wht); if (nfv9_capture_port && (key->dp == nfv9_capture_port)) { process_nfv9(h, payload, size_payload, record); } return record; }
struct flow_record * process_tcp(const struct pcap_pkthdr *h, const void *tcp_start, int tcp_len, struct flow_key *key) { unsigned int tcp_hdr_len; const unsigned char *payload; unsigned int payload_len; const struct tcp_hdr *tcp = (const struct tcp_hdr *)tcp_start; struct flow_record *record = NULL; unsigned int cur_itr = 0; if (output_level > none) { fprintf(output, " protocol: TCP\n"); } // tcp_hdr_len = TCP_OFF(tcp)*4; tcp_hdr_len = tcp_hdr_length(tcp); if (tcp_hdr_len < 20 || tcp_hdr_len > tcp_len) { // fprintf(output, " * Invalid TCP header length: %u bytes\n", tcp_hdr_len); return NULL; } /* define/compute tcp payload (segment) offset */ payload = (unsigned char *)(tcp_start + tcp_hdr_len); /* compute tcp payload (segment) size */ payload_len = tcp_len - tcp_hdr_len; if (output_level > none) { fprintf(output, " src port: %d\n", ntohs(tcp->src_port)); fprintf(output, " dst port: %d\n", ntohs(tcp->dst_port)); fprintf(output, "payload len: %u\n", payload_len); fprintf(output, " tcp len: %u\n", tcp_len); fprintf(output, "tcp hdr len: %u\n", tcp_hdr_len); fprintf(output, " flags:"); if (tcp->tcp_flags & TCP_FIN) { fprintf(output, "FIN "); } if (tcp->tcp_flags & TCP_SYN) { fprintf(output, "SYN "); } if (tcp->tcp_flags & TCP_RST) { fprintf(output, "RST "); } if (tcp->tcp_flags & TCP_PSH) { fprintf(output, "PSH "); } if (tcp->tcp_flags & TCP_ACK) { fprintf(output, "ACK "); } if (tcp->tcp_flags & TCP_URG) { fprintf(output, "URG "); } if (tcp->tcp_flags & TCP_ECE) { fprintf(output, "ECE "); } if (tcp->tcp_flags & TCP_CWR) { fprintf(output, "CWR "); } fprintf(output, "\n"); if (output_level > packet_summary) { if (payload_len > 0) { fprintf(output, " payload:\n"); print_payload(payload, payload_len); } } } key->sp = ntohs(tcp->src_port); key->dp = ntohs(tcp->dst_port); record = flow_key_get_record(key, CREATE_RECORDS); if (record == NULL) { return NULL; } if (output_level > none) { fprintf(output, " SEQ: %d\trelative SEQ: %d\n", ntohl(tcp->tcp_seq), ntohl(tcp->tcp_seq) - record->seq); fprintf(output, " ACK: %d\trelative ACK: %d\n", ntohl(tcp->tcp_ack), ntohl(tcp->tcp_ack) - record->ack); // fprintf(output, " SEQ: %d\n", ntohl(tcp->tcp_seq) - record->seq); // fprintf(output, " ACK: %d\n", ntohl(tcp->tcp_ack) - record->ack); } if (payload_len > 0) { if (ntohl(tcp->tcp_seq) < record->seq) { // fprintf(info, "retransmission detected\n"); record->retrans++; } } if (include_zeroes || payload_len > 0) { flow_record_process_packet_length_and_time_ack(record, payload_len, &h->ts, tcp); } // if initial SYN/ACK packet, parse TCP options unsigned int offset = 20; if (tcp->tcp_flags == 2 || tcp->tcp_flags == 18) { // SYN==2, SYN/ACK==18 // get initial window size if (!record->tcp_initial_window_size) { record->tcp_initial_window_size = ntohs(tcp->tcp_win); } // get SYN packet size if (tcp->tcp_flags == 2) { record->tcp_syn_size = tcp_len; } // parse TCP options cur_itr = 0; while (offset < tcp_hdr_len) { // while there are TCP options present cur_itr += 1; if (cur_itr > 20) { break; } if ((unsigned int)*(const unsigned char *)(tcp_start+offset) <= 0) { // EOL break ; } if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 1) { // NOP record->tcp_option_nop += 1; offset += 1; } else if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 2) { // MSS if ((unsigned int)*(const unsigned char *)(tcp_start+offset+1) == 4) { record->tcp_option_mss = htons(*(const unsigned short *)(tcp_start+offset+2)); } offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } else if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 3) { // WSCALE record->tcp_option_wscale = (unsigned int)*(const unsigned char *)(tcp_start+offset+2); offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } else if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 4) { // SACK record->tcp_option_sack = 1; offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } else if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 8) { // TSTAMP record->tcp_option_tstamp = 1; offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } else if ((unsigned int)*(const unsigned char *)(tcp_start+offset) == 34) { // TCP FAST OPEN record->tcp_option_fastopen = 1; offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } else { // if all TCP options are being correctly parsed, this else should not be called offset += (unsigned int)*(const unsigned char *)(tcp_start+offset+1); } } } record->ob += payload_len; flow_record_update_byte_count(record, payload, payload_len); flow_record_update_compact_byte_count(record, payload, payload_len); flow_record_update_byte_dist_mean_var(record, payload, payload_len); wht_update(&record->wht, payload, payload_len, report_wht); /* if packet has port 443 and nonzero data length, process it as TLS */ if (include_tls && payload_len && (key->sp == 443 || key->dp == 443)) { process_tls(h, payload, payload_len, &record->tls_info); } /* if packet has port 80 and nonzero data length, process it as HTTP */ if (config.http && payload_len && (key->sp == 80 || key->dp == 80)) { http_update(&record->http_data, payload, payload_len, config.http); } /* * update header description */ if (payload_len >= report_hd) { header_description_update(&record->hd, payload, report_hd); } return record; }