Ejemplo n.º 1
0
inline 
#endif
int pcapProcess(pcap_pkthdr** header, u_char** packet, bool *destroy,
		bool enableDefrag, bool enableCalcMD5, bool enableDedup, bool enableDump,
		pcapProcessData *ppd, int pcapLinklayerHeaderType, pcap_dumper_t *pcapDumpHandle, const char *interfaceName) {
	if(destroy) {
		*destroy = false;
	}
	
	if(!parseEtherHeader(pcapLinklayerHeaderType, *packet,
			     ppd->header_sll, ppd->header_eth, ppd->header_ip_offset, ppd->protocol)) {
		syslog(LOG_ERR, "BAD DATALINK %s: datalink number [%d] is not supported", interfaceName ? interfaceName : "---", pcapLinklayerHeaderType);
		return(0);
	}
	
	if(ppd->protocol != ETHERTYPE_IP) {
		#if TCPREPLAY_WORKARROUND
		if(ppd->protocol == 0) {
			ppd->header_ip_offset += 2;
			ppd->protocol = ETHERTYPE_IP;
		} else 
		#endif
		{
			if(interfaceName && !strcmp(interfaceName, "lo")) {
				syslog(LOG_ERR, "BAD PROTOCOL (not ipv4) IN %s (dlt %d) - TRY TCPREPLAY_WORKARROUND", interfaceName, pcapLinklayerHeaderType);
			}
			return(0);
		}
	}
	
	ppd->header_ip = (iphdr2*)(*packet + ppd->header_ip_offset);

	extern BogusDumper *bogusDumper;
	static u_long lastTimeLogErrBadIpHeader = 0;
	if(ppd->header_ip->version != 4) {
		if(interfaceName) {
			if(bogusDumper) {
				bogusDumper->dump(*header, *packet, pcapLinklayerHeaderType, interfaceName);
			}
			u_long actTime = getTimeMS(*header);
			if(actTime - 1000 > lastTimeLogErrBadIpHeader) {
				syslog(LOG_ERR, "BAD HEADER_IP: %s: bogus ip header version %i", interfaceName, ppd->header_ip->version);
				lastTimeLogErrBadIpHeader = actTime;
			}
		}
		return(0);
	}
	if(htons(ppd->header_ip->tot_len) + ppd->header_ip_offset > (*header)->len) {
		if(interfaceName) {
			if(bogusDumper) {
				bogusDumper->dump(*header, *packet, pcapLinklayerHeaderType, interfaceName);
			}
			u_long actTime = getTimeMS(*header);
			if(actTime - 1000 > lastTimeLogErrBadIpHeader) {
				syslog(LOG_ERR, "BAD HEADER_IP: %s: bogus ip header length %i, len %i", interfaceName, htons(ppd->header_ip->tot_len), (*header)->len);
				lastTimeLogErrBadIpHeader = actTime;
			}
		}
		return(0);
	}
	
	if(enableDefrag) {
		//if UDP defrag is enabled process only UDP packets and only SIP packets
		if(opt_udpfrag && (ppd->header_ip->protocol == IPPROTO_UDP || ppd->header_ip->protocol == 4)) {
			int foffset = ntohs(ppd->header_ip->frag_off);
			if ((foffset & IP_MF) || ((foffset & IP_OFFSET) > 0)) {
				if(htons(ppd->header_ip->tot_len) + ppd->header_ip_offset > (*header)->caplen) {
					if(interfaceName) {
						if(bogusDumper) {
							bogusDumper->dump(*header, *packet, pcapLinklayerHeaderType, interfaceName);
						}
						u_long actTime = getTimeMS(*header);
						if(actTime - 1000 > lastTimeLogErrBadIpHeader) {
							syslog(LOG_ERR, "BAD FRAGMENTED HEADER_IP: %s: bogus ip header length %i, caplen %i", interfaceName, htons(ppd->header_ip->tot_len), (*header)->caplen);
							lastTimeLogErrBadIpHeader = actTime;
						}
					}
					//cout << "pcapProcess exit 001" << endl;
					return(0);
				}
				// packet is fragmented
				if(handle_defrag(ppd->header_ip, header, packet, 0, &ppd->ipfrag_data)) {
					// packets are reassembled
					//cout << "*** packets are reassembled in pcapProcess" << endl;
					ppd->header_ip = (iphdr2*)(*packet + ppd->header_ip_offset);
					*destroy = true;
				} else {
					//cout << "pcapProcess exit 002" << endl;
					return(0);
				}
			}
		}
	}
	
	bool nextPass;
	do {
		nextPass = false;
		if(ppd->header_ip->protocol == IPPROTO_IPIP) {
			// ip in ip protocol
			ppd->header_ip = (iphdr2*)((char*)ppd->header_ip + sizeof(iphdr2));
			
			if(enableDefrag) {
				//if UDP defrag is enabled process only UDP packets and only SIP packets
				if(opt_udpfrag && ppd->header_ip->protocol == IPPROTO_UDP) {
					int foffset = ntohs(ppd->header_ip->frag_off);
					if ((foffset & IP_MF) || ((foffset & IP_OFFSET) > 0)) {
						// packet is fragmented
						pcap_pkthdr* header_old = *header;
						u_char* packet_old = *packet;
						if(handle_defrag(ppd->header_ip, header, packet, 0, &ppd->ipfrag_data)) {
							// packet was returned
							iphdr2 *header_ip_1 = (iphdr2*)(*packet + ppd->header_ip_offset);

							// turn off frag flag in the first IP header
							header_ip_1->frag_off = 0;

							// turn off frag flag in the second IP header
							ppd->header_ip = (iphdr2*)((char*)header_ip_1 + sizeof(iphdr2));
							ppd->header_ip->frag_off = 0;

							// update lenght of the first ip header to the len of the second IP header since it can be changed due to reassemble
							header_ip_1->tot_len = htons((ntohs(ppd->header_ip->tot_len)) + sizeof(iphdr2));

							if(*destroy) {
								delete header_old;
								delete [] packet_old;
							}
							*destroy = true;
						} else {
							//cout << "pcapProcess exit 003" << endl;
							return(0);
						}
					}
				}
			}
			
		} else if(ppd->header_ip->protocol == IPPROTO_GRE) {
			// gre protocol
			iphdr2 *header_ip = convertHeaderIP_GRE(ppd->header_ip);
			if(header_ip) {
				ppd->header_ip = header_ip;
				ppd->header_ip_offset = (u_char*)header_ip - *packet;
				nextPass = true;
			} else {
				if(opt_ipaccount == 0) {
					//cout << "pcapProcess exit 004" << endl;
					return(0);
				}
			}
		}
	} while(nextPass);
	
	if(enableDefrag) {
		// if IP defrag is enabled, run each 10 seconds cleaning 
		if(opt_udpfrag && (ppd->ipfrag_lastprune + 10) < (*header)->ts.tv_sec) {
			ipfrag_prune((*header)->ts.tv_sec, 0, &ppd->ipfrag_data);
			ppd->ipfrag_lastprune = (*header)->ts.tv_sec;
			//TODO it would be good to still pass fragmented packets even it does not contain the last semant, the ipgrad_prune just wipes all unfinished frags
		}
	}
	
	bool enableReturnZeroInCheckData = !opt_udpfrag || enableDefrag || enableCalcMD5 || enableDedup || enableDump;

	ppd->header_udp = &ppd->header_udp_tmp;
	if (ppd->header_ip->protocol == IPPROTO_UDP) {
		// prepare packet pointers 
		ppd->header_udp = (udphdr2*) ((char*) ppd->header_ip + sizeof(*ppd->header_ip));
		ppd->data = (char*) ppd->header_udp + sizeof(*ppd->header_udp);
		ppd->datalen = (int)((*header)->caplen - ((unsigned long) ppd->data - (unsigned long) *packet)); 
		ppd->traillen = (int)((*header)->caplen - ((unsigned long) ppd->header_ip - (unsigned long) *packet)) - ntohs(ppd->header_ip->tot_len);
		ppd->istcp = 0;
	} else if (ppd->header_ip->protocol == IPPROTO_TCP) {
		ppd->istcp = 1;
		// prepare packet pointers 
		ppd->header_tcp = (tcphdr2*) ((char*) ppd->header_ip + sizeof(*ppd->header_ip));
		ppd->data = (char*) ppd->header_tcp + (ppd->header_tcp->doff * 4);
		ppd->datalen = (int)((*header)->caplen - ((unsigned long) ppd->data - (unsigned long) *packet)); 
		if (!(sipportmatrix[htons(ppd->header_tcp->source)] || sipportmatrix[htons(ppd->header_tcp->dest)]) &&
		    !(opt_enable_http && (httpportmatrix[htons(ppd->header_tcp->source)] || httpportmatrix[htons(ppd->header_tcp->dest)]) &&
		      (tcpReassemblyHttp->check_ip(htonl(ppd->header_ip->saddr)) || tcpReassemblyHttp->check_ip(htonl(ppd->header_ip->daddr)))) &&
		    !(opt_enable_webrtc && (webrtcportmatrix[htons(ppd->header_tcp->source)] || webrtcportmatrix[htons(ppd->header_tcp->dest)]) &&
		      (tcpReassemblyWebrtc->check_ip(htonl(ppd->header_ip->saddr)) || tcpReassemblyWebrtc->check_ip(htonl(ppd->header_ip->daddr)))) &&
		    !(opt_enable_ssl && 
		      (isSslIpPort(htonl(ppd->header_ip->saddr), htons(ppd->header_tcp->source)) ||
		       isSslIpPort(htonl(ppd->header_ip->daddr), htons(ppd->header_tcp->dest)))) &&
		    !(opt_skinny && (htons(ppd->header_tcp->source) == 2000 || htons(ppd->header_tcp->dest) == 2000))) {
			// not interested in TCP packet other than SIP port
			if(opt_ipaccount == 0 && !DEBUG_ALL_PACKETS && enableReturnZeroInCheckData) {
				//cout << "pcapProcess exit 005" << endl;
				return(0);
			}
		}

		ppd->header_udp->source = ppd->header_tcp->source;
		ppd->header_udp->dest = ppd->header_tcp->dest;
	} else {
		//packet is not UDP and is not TCP, we are not interested, go to the next packet (but if ipaccount is enabled, do not skip IP
		ppd->datalen = 0;
		if(opt_ipaccount == 0 && !DEBUG_ALL_PACKETS && enableReturnZeroInCheckData) {
			//cout << "pcapProcess exit 006 / protocol: " << (int)ppd->header_ip->protocol << endl;
			return(0);
		}
	}

	if(ppd->datalen < 0 && enableReturnZeroInCheckData) {
		//cout << "pcapProcess exit 007" << endl;
		return(0);
	}

	if(enableCalcMD5 || enableDedup) {
		/* check for duplicate packets (md5 is expensive operation - enable only if you really need it */
		if(ppd->datalen > 0 && opt_dup_check && ppd->prevmd5s != NULL && (ppd->traillen < ppd->datalen) &&
		   !(ppd->istcp && opt_enable_http && (httpportmatrix[htons(ppd->header_tcp->source)] || httpportmatrix[htons(ppd->header_tcp->dest)])) &&
		   !(ppd->istcp && opt_enable_webrtc && (webrtcportmatrix[htons(ppd->header_tcp->source)] || webrtcportmatrix[htons(ppd->header_tcp->dest)])) &&
		   !(ppd->istcp && opt_enable_ssl && (isSslIpPort(htonl(ppd->header_ip->saddr), htons(ppd->header_tcp->source)) || isSslIpPort(htonl(ppd->header_ip->daddr), htons(ppd->header_tcp->dest))))) {
			if(enableCalcMD5) {
				MD5_Init(&ppd->ctx);
				if(opt_dup_check_ipheader) {
					// check duplicates based on full ip header and data 
					MD5_Update(&ppd->ctx, ppd->header_ip, MIN(ppd->datalen - ((char*)ppd->header_ip - ppd->data), ntohs(ppd->header_ip->tot_len)));
				} else {
					// check duplicates based only on data (without ip header and without UDP/TCP header). Duplicate packets 
					// will be matched regardless on IP 
					MD5_Update(&ppd->ctx, ppd->data, MAX(0, (unsigned long)ppd->datalen - ppd->traillen));
				}
				MD5_Final((unsigned char*)ppd->md5, &ppd->ctx);
			}
			if(enableDedup && ppd->md5[0]) {
				if(memcmp(ppd->md5, ppd->prevmd5s + (*ppd->md5 * MD5_DIGEST_LENGTH), MD5_DIGEST_LENGTH) == 0) {
					//printf("dropping duplicate md5[%s]\n", md5);
					duplicate_counter++;
					return(0);
				}
				memcpy(ppd->prevmd5s+(*ppd->md5 * MD5_DIGEST_LENGTH), ppd->md5, MD5_DIGEST_LENGTH);
			}
		}
	}
	
	if(enableDump) {
		if(pcapDumpHandle) {
			pcap_dump((u_char*)pcapDumpHandle, *header, *packet);
		}
	}
	
	return(1);
}
Ejemplo n.º 2
0
inline 
#endif
int pcapProcess(sHeaderPacket **header_packet, int pushToStack_queue_index,
		pcap_block_store *block_store, int block_store_index,
		int ppf,
		pcapProcessData *ppd, int pcapLinklayerHeaderType, pcap_dumper_t *pcapDumpHandle, const char *interfaceName) {
 
	pcap_pkthdr_plus2 *pcap_header_plus2 = NULL;
	u_char *packet = NULL;
	if(header_packet) {
		if((*header_packet)->detect_headers & 0x01) {
			ppd->header_ip_offset = (*header_packet)->header_ip_first_offset;
			ppd->protocol = (*header_packet)->eth_protocol;
			ppd->header_ip = (iphdr2*)(HPP(*header_packet) + ppd->header_ip_offset);
		} else if(parseEtherHeader(pcapLinklayerHeaderType, HPP(*header_packet),
					   ppd->header_sll, ppd->header_eth, ppd->header_ip_offset, ppd->protocol)) {
			(*header_packet)->detect_headers |= 0x01;
			(*header_packet)->header_ip_first_offset = ppd->header_ip_offset;
			(*header_packet)->eth_protocol = ppd->protocol;
			if(ppd->protocol != ETHERTYPE_IP) {
				if(sverb.tcpreplay) {
					if(ppd->protocol == 0) {
						ppd->header_ip_offset += 2;
						ppd->protocol = ETHERTYPE_IP;
					} else {
						return(0);
					}
				} else {
					pcapProcessEvalError(bad_eth_protocol, *HPH(*header_packet), HPP(*header_packet),
							     ppd, pcapLinklayerHeaderType, pcapDumpHandle, interfaceName);
					return(0);
				}
			}
			ppd->header_ip = (iphdr2*)(HPP(*header_packet) + ppd->header_ip_offset);
			if(ppd->header_ip->version != 4) {
				pcapProcessEvalError(bad_ip_version, *HPH(*header_packet), HPP(*header_packet),
						     ppd, pcapLinklayerHeaderType, pcapDumpHandle, interfaceName);
				return(0);
			}
			if(htons(ppd->header_ip->tot_len) + ppd->header_ip_offset > HPH(*header_packet)->len) {
				pcapProcessEvalError(bad_ip_length, *HPH(*header_packet), HPP(*header_packet),
						     ppd, pcapLinklayerHeaderType, pcapDumpHandle, interfaceName);
				return(0);
			}
		} else {
			pcapProcessEvalError(bad_datalink, *HPH(*header_packet), HPP(*header_packet),
					     ppd, pcapLinklayerHeaderType, pcapDumpHandle, interfaceName);
			return(0);
		}
	} else {
		pcap_header_plus2 = (pcap_pkthdr_plus2*)block_store->get_header(block_store_index);
		packet = block_store->get_packet(block_store_index);
		if(pcap_header_plus2->detect_headers & 0x01) {
			ppd->header_ip_offset = pcap_header_plus2->header_ip_first_offset;
			ppd->protocol = pcap_header_plus2->eth_protocol;
			ppd->header_ip = (iphdr2*)(packet + ppd->header_ip_offset);
		} else if(parseEtherHeader(pcapLinklayerHeaderType, packet,
					   ppd->header_sll, ppd->header_eth, ppd->header_ip_offset, ppd->protocol)) {
			pcap_header_plus2->detect_headers |= 0x01;
			pcap_header_plus2->header_ip_first_offset = ppd->header_ip_offset;
			pcap_header_plus2->eth_protocol = ppd->protocol;
			if(ppd->protocol != ETHERTYPE_IP) {
				if(sverb.tcpreplay) {
					if(ppd->protocol == 0) {
						ppd->header_ip_offset += 2;
						ppd->protocol = ETHERTYPE_IP;
					} else {
						pcap_header_plus2->ignore = true;
						return(0);
					}
				} else {
					pcapProcessEvalError(bad_eth_protocol, pcap_header_plus2, packet,
							     ppd, pcapLinklayerHeaderType, pcapDumpHandle, interfaceName);
					pcap_header_plus2->ignore = true;
					return(0);
				}
			}
			ppd->header_ip = (iphdr2*)(packet + ppd->header_ip_offset);
			if(ppd->header_ip->version != 4) {
				pcapProcessEvalError(bad_ip_version, pcap_header_plus2, packet,
						     ppd, pcapLinklayerHeaderType, pcapDumpHandle, interfaceName);
				pcap_header_plus2->ignore = true;
				return(0);
			}
			if(htons(ppd->header_ip->tot_len) + ppd->header_ip_offset > pcap_header_plus2->get_len()) {
				pcapProcessEvalError(bad_ip_length, pcap_header_plus2, packet,
						     ppd, pcapLinklayerHeaderType, pcapDumpHandle, interfaceName);
				pcap_header_plus2->ignore = true;
				return(0);
			}
		} else {
			pcapProcessEvalError(bad_datalink, pcap_header_plus2, packet,
					     ppd, pcapLinklayerHeaderType, pcapDumpHandle, interfaceName);
			pcap_header_plus2->ignore = true;
			return(0);
		}
	}
	
	if(ppf & ppf_defrag) {
		//if UDP defrag is enabled process only UDP packets and only SIP packets
		if(opt_udpfrag) {
			int foffset = ntohs(ppd->header_ip->frag_off);
			if ((foffset & IP_MF) || ((foffset & IP_OFFSET) > 0)) {
				if(htons(ppd->header_ip->tot_len) + ppd->header_ip_offset > HPH(*header_packet)->caplen) {
					if(interfaceName) {
						extern BogusDumper *bogusDumper;
						static u_long lastTimeLogErrBadIpHeader = 0;
						if(bogusDumper) {
							bogusDumper->dump(HPH(*header_packet), HPP(*header_packet), pcapLinklayerHeaderType, interfaceName);
						}
						u_long actTime = getTimeMS(HPH(*header_packet));
						if(actTime - 1000 > lastTimeLogErrBadIpHeader) {
							syslog(LOG_ERR, "BAD FRAGMENTED HEADER_IP: %s: bogus ip header length %i, caplen %i", interfaceName, htons(ppd->header_ip->tot_len), HPH(*header_packet)->caplen);
							lastTimeLogErrBadIpHeader = actTime;
						}
					}
					//cout << "pcapProcess exit 001" << endl;
					return(0);
				}
				// packet is fragmented
				if(handle_defrag(ppd->header_ip, header_packet, &ppd->ipfrag_data, pushToStack_queue_index) > 0) {
					// packets are reassembled
					ppd->header_ip = (iphdr2*)(HPP(*header_packet) + ppd->header_ip_offset);
					if(sverb.defrag) {
						defrag_counter++;
						cout << "*** DEFRAG 1 " << defrag_counter << endl;
					}
				} else {
					//cout << "pcapProcess exit 002" << endl;
					return(0);
				}
			}
		}
	}
	
	bool nextPass;
	do {
		nextPass = false;
		u_int first_header_ip_offset = ppd->header_ip_offset;
		if(ppd->header_ip->protocol == IPPROTO_IPIP) {
			// ip in ip protocol
			ppd->header_ip = (iphdr2*)((char*)ppd->header_ip + sizeof(iphdr2));
			ppd->header_ip_offset += sizeof(iphdr2);
		} else if(ppd->header_ip->protocol == IPPROTO_GRE) {
			// gre protocol
			iphdr2 *header_ip = convertHeaderIP_GRE(ppd->header_ip);
			if(header_ip) {
				ppd->header_ip = header_ip;
				ppd->header_ip_offset = (u_char*)header_ip - (header_packet ? HPP(*header_packet) : packet);
				nextPass = true;
			} else {
				if(ppf & ppf_returnZeroInCheckData) {
					//cout << "pcapProcess exit 004" << endl;
					if(pcap_header_plus2) {
						pcap_header_plus2->ignore = true;
					}
					return(0);
				}
			}
		} else {
			break;
		}
		if(ppf & ppf_defrag) {
			//if UDP defrag is enabled process only UDP packets and only SIP packets
			if(opt_udpfrag && ppd->header_ip->protocol == IPPROTO_UDP) {
				int foffset = ntohs(ppd->header_ip->frag_off);
				if ((foffset & IP_MF) || ((foffset & IP_OFFSET) > 0)) {
					// packet is fragmented
					if(handle_defrag(ppd->header_ip, header_packet, &ppd->ipfrag_data, pushToStack_queue_index) > 0) {
						// packets are reassembled
						iphdr2 *first_header_ip = (iphdr2*)(HPP(*header_packet) + first_header_ip_offset);

						// turn off frag flag in the first IP header
						first_header_ip->frag_off = 0;

						// turn off frag flag in the second IP header
						ppd->header_ip = (iphdr2*)(HPP(*header_packet) + ppd->header_ip_offset);
						ppd->header_ip->frag_off = 0;

						// update lenght of the first ip header to the len of the second IP header since it can be changed due to reassemble
						first_header_ip->tot_len = htons(ntohs(ppd->header_ip->tot_len) + (ppd->header_ip_offset - first_header_ip_offset));

						if(sverb.defrag) {
							defrag_counter++;
							cout << "*** DEFRAG 2 " << defrag_counter << endl;
						}
					} else {
						//cout << "pcapProcess exit 003" << endl;
						return(0);
					}
				}
			}
		}
	} while(nextPass);
	
	if(header_packet) {
		(*header_packet)->header_ip_offset = ppd->header_ip_offset;
	} else {
		pcap_header_plus2->header_ip_offset = ppd->header_ip_offset;
	}
	
	if(ppf & ppf_defrag) {
		// if IP defrag is enabled, run each 10 seconds cleaning 
		if(opt_udpfrag && (ppd->ipfrag_lastprune + 10) < HPH(*header_packet)->ts.tv_sec) {
			ipfrag_prune(HPH(*header_packet)->ts.tv_sec, false, &ppd->ipfrag_data, pushToStack_queue_index, -1);
			ppd->ipfrag_lastprune = HPH(*header_packet)->ts.tv_sec;
			//TODO it would be good to still pass fragmented packets even it does not contain the last semant, the ipgrad_prune just wipes all unfinished frags
		}
	}
	
	if(!(ppf & ppf_defragInPQout)) {
		u_int32_t caplen;
		if(header_packet) {
			caplen = HPH(*header_packet)->caplen;
			packet = HPP(*header_packet);
		} else {
			caplen = pcap_header_plus2->get_caplen();
		}
		ppd->header_udp = &ppd->header_udp_tmp;
		if (ppd->header_ip->protocol == IPPROTO_UDP) {
			// prepare packet pointers 
			ppd->header_udp = (udphdr2*) ((char*) ppd->header_ip + sizeof(*ppd->header_ip));
			ppd->data = (char*) ppd->header_udp + sizeof(*ppd->header_udp);
			ppd->datalen = (int)(caplen - ((u_char*)ppd->data - packet)); 
			ppd->traillen = (int)(caplen - ((u_char*)ppd->header_ip - packet)) - ntohs(ppd->header_ip->tot_len);
			ppd->istcp = 0;
		} else if (ppd->header_ip->protocol == IPPROTO_TCP) {
			ppd->istcp = 1;
			// prepare packet pointers 
			ppd->header_tcp = (tcphdr2*) ((char*) ppd->header_ip + sizeof(*ppd->header_ip));
			ppd->data = (char*) ppd->header_tcp + (ppd->header_tcp->doff * 4);
			ppd->datalen = (int)(caplen - ((u_char*)ppd->data - packet)); 
			if (!(sipportmatrix[htons(ppd->header_tcp->source)] || sipportmatrix[htons(ppd->header_tcp->dest)]) &&
			    !(opt_enable_http && (httpportmatrix[htons(ppd->header_tcp->source)] || httpportmatrix[htons(ppd->header_tcp->dest)]) &&
			      (tcpReassemblyHttp->check_ip(htonl(ppd->header_ip->saddr)) || tcpReassemblyHttp->check_ip(htonl(ppd->header_ip->daddr)))) &&
			    !(opt_enable_webrtc && (webrtcportmatrix[htons(ppd->header_tcp->source)] || webrtcportmatrix[htons(ppd->header_tcp->dest)]) &&
			      (tcpReassemblyWebrtc->check_ip(htonl(ppd->header_ip->saddr)) || tcpReassemblyWebrtc->check_ip(htonl(ppd->header_ip->daddr)))) &&
			    !(opt_enable_ssl && 
			      (isSslIpPort(htonl(ppd->header_ip->saddr), htons(ppd->header_tcp->source)) ||
			       isSslIpPort(htonl(ppd->header_ip->daddr), htons(ppd->header_tcp->dest)))) &&
			    !(opt_skinny && (htons(ppd->header_tcp->source) == 2000 || htons(ppd->header_tcp->dest) == 2000))) {
				// not interested in TCP packet other than SIP port
				if(!opt_ipaccount && !DEBUG_ALL_PACKETS && (ppf & ppf_returnZeroInCheckData)) {
					//cout << "pcapProcess exit 005" << endl;
					if(pcap_header_plus2) {
						pcap_header_plus2->ignore = true;
					}
					return(0);
				}
			}

			ppd->header_udp->source = ppd->header_tcp->source;
			ppd->header_udp->dest = ppd->header_tcp->dest;
		} else {
			//packet is not UDP and is not TCP, we are not interested, go to the next packet (but if ipaccount is enabled, do not skip IP
			ppd->datalen = 0;
			if(!opt_ipaccount && !DEBUG_ALL_PACKETS && (ppf & ppf_returnZeroInCheckData)) {
				//cout << "pcapProcess exit 006 / protocol: " << (int)ppd->header_ip->protocol << endl;
				if(pcap_header_plus2) {
					pcap_header_plus2->ignore = true;
				}
				return(0);
			}
		}

		if(ppd->datalen < 0 && (ppf & ppf_returnZeroInCheckData)) {
			//cout << "pcapProcess exit 007" << endl;
			if(pcap_header_plus2) {
				pcap_header_plus2->ignore = true;
			}
			return(0);
		}
	} else {
		ppd->data = NULL;
		ppd->datalen = 0;
	}

	if((ppf & ppf_calcMD5) || (ppf & ppf_dedup)) {
		// check for duplicate packets (md5 is expensive operation - enable only if you really need it
		if(opt_dup_check && 
		   ppd->prevmd5s != NULL && 
		   ((ppf & ppf_defragInPQout) ||
		    (ppd->datalen > 0 && (opt_dup_check_ipheader || ppd->traillen < ppd->datalen))) &&
		   !(ppd->istcp && opt_enable_http && (httpportmatrix[htons(ppd->header_tcp->source)] || httpportmatrix[htons(ppd->header_tcp->dest)])) &&
		   !(ppd->istcp && opt_enable_webrtc && (webrtcportmatrix[htons(ppd->header_tcp->source)] || webrtcportmatrix[htons(ppd->header_tcp->dest)])) &&
		   !(ppd->istcp && opt_enable_ssl && (isSslIpPort(htonl(ppd->header_ip->saddr), htons(ppd->header_tcp->source)) || isSslIpPort(htonl(ppd->header_ip->daddr), htons(ppd->header_tcp->dest))))) {
			uint16_t *_md5 = header_packet ? (*header_packet)->md5 : pcap_header_plus2->md5;
			if(ppf & ppf_calcMD5) {
				MD5_Init(&ppd->ctx);
				if(ppf & ppf_defragInPQout) {
					u_int32_t caplen = header_packet ? HPH(*header_packet)->caplen : pcap_header_plus2->get_caplen();
					MD5_Update(&ppd->ctx, ppd->header_ip, MIN(caplen - ppd->header_ip_offset, ntohs(ppd->header_ip->tot_len)));
				} else if(opt_dup_check_ipheader) {
					MD5_Update(&ppd->ctx, ppd->header_ip, MIN(ppd->datalen + (ppd->data - (char*)ppd->header_ip), ntohs(ppd->header_ip->tot_len)));
				} else {
					// check duplicates based only on data (without ip header and without UDP/TCP header). Duplicate packets 
					// will be matched regardless on IP 
					MD5_Update(&ppd->ctx, ppd->data, MAX(0, (unsigned long)ppd->datalen - ppd->traillen));
				}
				MD5_Final((unsigned char*)_md5, &ppd->ctx);
			}
			if((ppf & ppf_dedup) && _md5[0]) {
				if(memcmp(_md5, ppd->prevmd5s + (_md5[0] * MD5_DIGEST_LENGTH), MD5_DIGEST_LENGTH) == 0) {
					//printf("dropping duplicate md5[%s]\n", md5);
					duplicate_counter++;
					if(sverb.dedup) {
						cout << "*** DEDUP " << duplicate_counter << endl;
					}
					if(pcap_header_plus2) {
						pcap_header_plus2->ignore = true;
					}
					return(0);
				}
				memcpy(ppd->prevmd5s + (_md5[0] * MD5_DIGEST_LENGTH), _md5, MD5_DIGEST_LENGTH);
			}
		}
	}
	
	if(ppf & ppf_dump) {
		if(pcapDumpHandle) {
			if(header_packet) {
				pcap_dump((u_char*)pcapDumpHandle, HPH(*header_packet), HPP(*header_packet));
			} else {
				pcap_pkthdr header = pcap_header_plus2->getStdHeader();
				pcap_dump((u_char*)pcapDumpHandle, &header, packet);
			}
		}
	}
	
	return(1);
}