示例#1
0
static void callback(u_char *ignore, const struct pcap_pkthdr *h, const u_char *packet)
{
	struct linkedlist *node = &head;
	const uint8_t *flag, *fltr, *pkt = packet;
	int hdrlen = sizeof(struct ether_header) + sizeof(struct ip);
	int payloadlen = ntohs(*(uint16_t *)&IPLEN(packet)) - sizeof(struct ip);
	int fltrloadlen, i;
	uint8_t extract;

	if( PROTOCOL(pkt) == 6 ) {
		hdrlen += sizeof(struct tcphdr);
		payloadlen -= sizeof(struct tcphdr);

	}else if( PROTOCOL(pkt) == 17 ) {
		hdrlen += sizeof(struct udphdr);
		payloadlen -= sizeof(struct udphdr);
	}
	

	while( node->next != NULL ) {
		node = node->next;
		flag = ((uint8_t *)&node->flag) + 2;
		fltr = ((uint8_t *)&node->data) + 2;
		pkt = packet;

		/* Extract and compare fields byte by btye */
		for(i = 0; i < hdrlen; flag++, pkt++, fltr++, i++) {
			memset(&extract, *flag & *pkt, 1);
			
			if( memcmp(&extract, fltr, 1) != 0 )
				break;
		}

		// No match
		if( i < hdrlen )
			continue;

		/* HTTP Request */
		if( (i = strlen(node->http)) != 0 ) {
			// No match
			if( payloadlen == 0 )
				continue;

			// Find in a payload
			if( memcmp((char *)pkt, node->http, i) == 0 ) {
				while( i++ < payloadlen) {
					if( *(pkt + i) == ' ' ) {
						if( i + 8 < payloadlen && memcmp((char *)(pkt + i + 1), "HTTP/1.1", 8) == 0 )
							break;
						else
							continue;
					}
				}
			}else   continue;

			// Set custom protocol number
			if( strncmp(node->http, "GET", 3) == 0 )
				memset((uint8_t *)packet + 23, 3, 1);
			else if( strncmp(node->http, "PUT", 3) == 0 )
				memset((uint8_t *)packet + 23, 5, 1);
			else// POST
				memset((uint8_t *)packet + 23, 7, 1);
		}

		/* Write to file */
		fltrloadlen = strlen(node->payload);
		if( fltrloadlen == 0 )
			printfile((uint8_t *)&node->flag, packet, NULL, payloadlen);

		else if( payloadlen >= fltrloadlen ) {
			if( memcmp_cont(pkt, node->payload, fltrloadlen, payloadlen) != NULL )
				printfile((uint8_t *)&node->flag, packet, node->payload, payloadlen);
		}
	}
}
示例#2
0
/*
 * connection リスト各パケットを表示。
 * オプションフラグによっては通常出力に加えて、
 * sequence 番号チェックを表示
 */
int
view_conn()
{ 
    connection_t *conn;
    stream_t *streams;
    stream_t *streams_check;
    uint32_t exp_ack; /* packet が期待する ACK 値 */
    uint32_t self_seq; /* Sefl packet SEQ 値 */
    uint32_t len; /* TCP の data の長さ*/
    double stream_init_time; /* connection 毎の開始時間*/
    double receive_time; /* 個々の packet の到着時間 */
    double previous_time = 0; /* 一つ前の packet の到着時間 */
    double acked_elapse ; /* ack を受けるまでの時間 */
    uint32_t next_seq[2];   /* Diag 用の 一つ前のパケットまでの SEQ の進行状況 */
    
    /* conn_head は空なので、次から・・*/
    conn = conn_head->conn_next ;
    if(conn == NULL )
        return(0);

    printf("\n====================================\n");
    printf("        Check each connection                \n");
    printf("====================================\n");
    for( ; conn != NULL ; conn = conn->conn_next) {
        printf("\n====================================\n");
        printf("Number of packets  : %d\n\n", conn->conn_count);
        printf("Addr 0: %s : Port: %d",inet_ntoa(conn->addr0),conn->port0);	
        printf("\t\t\t\t\t");
        printf("Addr 1: %s : Port: %d\n",inet_ntoa(conn->addr1),conn->port1);	        
        printf("---------------------------------------------------------------");
        printf("----------------------------------------------------------------\n");
        stream_init_time = TIMEVAL_TO_SEC(conn->stream->plist->php->pktime);
        previous_time = stream_init_time;

        /*
         * 以下 個々の packet の処理
         */
        for(streams = conn->stream ; streams != NULL ; streams = streams->stream_next ){
            receive_time = TIMEVAL_TO_SEC(streams->plist->php->pktime);
            INDENT(streams);
            /*
             * 以下 summary 表示部
             */
            printf("%d: ",streams->plist->packet_number);
            printf("%5.3f ",receive_time - previous_time);
            if (ntohs(streams->ip->ip_off) & (8191)){
                /*
                 * fragment offset が 0 以外(fragmentしていて、TCP header が無い) IP data gram を判定
                 */
                printf(" IP fragment");
                printf(" IPID: %u",ntohs(streams->ip->ip_id));
                printf(" Len:%4d", IPLEN(streams));                
                printf(" Flag: 0x%x",ntohs(streams->ip->ip_off));
                printf(" Offset: %u",((ntohs(streams->ip->ip_off)) & (8191))<<3);
                if (ntohs(streams->ip->ip_off) & IP_MF)
                    printf(" MF");
                if (ntohs(streams->ip->ip_off) & IP_DF)
                    printf(" DF");
                printf("\n");
            } else {
                /*
                 * IP fragment していない、もしくは最初の fragment の tcp packet
                 */
                printf("%u",  SEQ(streams));            
                printf("(%u)", ACK(streams));            
                printf(" Win:%d", ntohs(streams->tcphdr->th_win));
                printf(" Len:%u", TCPLEN(streams));
                if (ntohs(streams->ip->ip_off) & IP_MF)
                    printf(" MF");
                if (ntohs(streams->ip->ip_off) & IP_DF)
                    printf(" DF");                                            
                printf(" ");
                if(streams->tcphdr->th_flags & TH_FIN)
                    printf("FIN ");
                if(streams->tcphdr->th_flags & TH_SYN)
                    printf("SYN ");
                if(streams->tcphdr->th_flags & TH_RST)
                    printf("RST ");
                if(streams->tcphdr->th_flags & TH_PUSH)
                    printf("PSH ");
                if(streams->tcphdr->th_flags & TH_ACK)
                    printf("ACK ");
                if(streams->tcphdr->th_flags & TH_URG)
                    printf("URG ");
                printf("\n");
            }
            previous_time = receive_time ;            
                //printf("\t\t%s\n",streams->direction ? "<------------------\n" : "------------------>\n");

            
            if(!(optflag & DIAG))
                continue;
            
            /************** ここからは DIAG フラグがついていた場合だけ ******************/

            /*
             * more fragmen が立っている packet は ack の調査をしない                            
             * なぜなら、fragment の途中では TCP segment としての total length がわからないので
             */
            if (ntohs(streams->ip->ip_off) & IP_MF){
                //INDENT(streams);
                //printf("\t> IP fragment packet.(can't check ack packet)\n");
                continue;
            }
            
            self_seq = SEQ(streams);
            /*
             * len は fragmen/non-fragment パケット双方の データ長が入る
             */
            len = TCPLEN(streams);

            /*
             * SACK(Selective Ack) Option の確認
             * TCP ヘッダー長が 5(=20bytes) より大きければ、なんらかの
             * TCP Option が設定されている
             */
            if(streams->tcphdr->th_off > 5 ){
                    uint16_t tcphdrlen;
                    char *tcpopt, *tcpopt_head;
                    uint8_t optlen;
                    struct sackval 
                    {
                        uint32_t leftedge;
                        uint32_t rightedge;
                    } *sackval;

                    tcphdrlen = streams->tcphdr->th_off <<2;
                    
                    tcpopt_head = tcpopt = (char *)streams->tcphdr + 20 ; 
                    while(*tcpopt != 0 && (tcpopt - tcpopt_head) < tcphdrlen - 20){
                        switch(*tcpopt){
                            case 1: /* NOP。次のoption へ*/
                                tcpopt++; 
                                if(optflag & VERBOSE) { INDENT(streams); printf("\t> NOP option found\n");}
                                break;
                            case 4: /* SACK Permitted option */
                                tcpopt = tcpopt + 2; /* SACK OK option 次の option へ */
                                INDENT(streams);                                                                
                                printf("\t> sack-permitted option found\n");
                                break;                                
                            case 5: /* SACK OPTION */{
                                int i;
                                char *pointer; /* 処理用のポインタ */

                                pointer = tcpopt + 1 + 1; /* type と lenght の分を進める*/
                                optlen = *(uint8_t *)(tcpopt + 1);
                                sackval = malloc(sizeof(struct sackval));

                                /*
                                 * Left edge と Right edige のペア(8bytes)が繋がっている。
                                 * optlen -2 / 8 回分だけループ
                                 */
                                for ( i = optlen - 2 ; i > 0 ; i = i - 8){
                                    memcpy(sackval, pointer, 8);
                                    INDENT(streams);                                
                                    printf("\t> sack = %u - %u\n", sackval->leftedge, sackval->rightedge);
                                    pointer = pointer + 8;
                                }
                                tcpopt = tcpopt + optlen;
                                free(sackval); /* もう使わないので free */
                                break;
                            }
                            default : /* 他の Option */
                                if(optflag & VERBOSE){ INDENT(streams); printf("\t> TCP option found\n");}
                                optlen = *(uint8_t *)(tcpopt + 1); 
                                tcpopt = tcpopt + optlen; 
                                break;
                        } /* switch end */
                    } /* while end */
                } /* if tcphdr > 20 end */
            
            /*
             * 次にくると期待されていた SEQ と、このパケットの SEQ を比較
             * もし、期待値よりも大きければ、順番が入れ替わったか、または
             * パケットのドロップの可能性がある
             */
            if(conn->snd_nxt[streams->direction] == 0){
                    /* 期待する SEQ(SND_NXT)が 0 つまりここは snoop でのこの TCP */
                    /* connction の最初の packet だけが該当する                  */
                conn->snd_nxt[streams->direction] = SEQ(streams) + len + SYNFIN(streams->tcphdr);
            } else {
                next_seq[streams->direction] = conn->snd_nxt[streams->direction];
                if( next_seq[streams->direction] < SEQ(streams))
                {
                    /* 期待しているより、大きい SEQ 番号がきた */
                    INDENT(streams);
                    printf("\t> out of order data packet. expected SEQ = %u\n",next_seq[streams->direction]);
                    
                }
                else if (next_seq[streams->direction] == SEQ(streams)){
                    /* 期待通りのパケットが来た。snd_nxt を更新                       */
                    conn->snd_nxt[streams->direction] = SEQ(streams) + len + SYNFIN(streams->tcphdr);
                }
                else{
                        /* 期待値よりも小さい SEQ。再送?*/

                    INDENT(streams);
                    printf("\t> retransmission packet?\n");
                }

                /*
                 * これより前の packet に SND_NXT の SEQ が含まれているか調べる & 再送のチェック
                 * TODO:ここはデータがある全 packet が通るため、大変負荷が高い。要改善
                 */
                if( len > 0){
                    for(streams_check =  conn->stream ; streams_check != streams ; streams_check = streams_check->stream_next){
                         /* Self packet のみをチェック*/
                        if (streams_check->direction != streams->direction) 
                            continue;
                        /* last fragment(IP_MF の立ってない)パケットのみをチェック */
                        if (ntohs(streams_check->ip->ip_off) & IP_MF) 
                            continue;

                        /* データがあって、SEQ と SND_NXT が同じ packet を調べる*/	
                        if ( TCPLEN(streams_check) > 0 && SEQ(streams_check) == conn->snd_nxt[streams->direction]){
                            conn->snd_nxt[streams->direction] =
                                SEQ(streams_check) + TCPLEN(streams_check)  + SYNFIN(streams_check->tcphdr);
                            INDENT(streams);
                            printf("\t> SEQ = %u was already sent by pakcet %d\n",
                                   SEQ(streams_check), streams_check->plist->packet_number);
                                /* まだ、他にもあるかもしれないので、最初から調べ直す。*/
                            streams_check = conn->stream;
                            continue;
                        }
                        /* SEQ が同じで、データを持っている packet を調べる*/	
                        if( (SEQ(streams_check) == self_seq) && (TCPLEN(streams_check) != 0)){
                            INDENT(streams);
                            printf("\t> may retransmission packet of packet%d\n",streams_check->plist->packet_number);
                        }
                    } /* 以前の packet のチェックのループ終わり*/
                } /* もしデータがあったら・・*/
                
            }/* if SND_NXT == 0 else .. end */

            
            if(streams->stream_next == NULL){ /* つぎの packet が無い*/
                INDENT(streams);
                printf("\t> ...won't check ack packet. No more packets\n");
                continue;
            }            

            /*
             * まず、ACK が必要かどうか(データ有り、または FIN or SYN)を確認 
             * 必要無ければ、他の packet を調べない。必要なら次の for() ループへ
             */
            if(len != 0){
                /*
                 * データがある場合
                 */
                exp_ack = SEQ(streams) + len ;
                if(SYNFIN(streams->tcphdr)){
                    /*
                     * FIN or SYN の場合
                     */
                    exp_ack++;
                }
                INDENT(streams);                
                printf("\t> expecting ACk = %u\n",exp_ack);
            } else {
                /*
                 * データがない場合
                 */                
                if(SYNFIN(streams->tcphdr)){
                    /*
                     * FIN or SYN の場合
                     */
                    exp_ack = SEQ(streams) + 1;
                    INDENT(streams);
                    printf("\t> expecting ACK = %u\n",exp_ack);
                } else {
                    /*
                     * ただの ACK パケット。
                     * なので、以下のACK のチェックも、再送のチェックも行わない
                     */
                    INDENT(streams);
                    printf("\t> doesn't expect to be acked\n");
                    continue;
                }
            }

            /*
             * これより後の packet から期待する ACK があるかどうかをチェック
             */
            for(streams_check = streams->stream_next ; streams_check != NULL ; streams_check = streams_check->stream_next){
                if (streams_check->direction == streams->direction){ /* 相手からの packet のみをチェック*/
                    if(streams_check->stream_next == NULL){ /* もしこれが最後の packet なら ACK されていないと言うこと*/
                        INDENT(streams);                        
                        printf("\t> not acked!!!\n");
                    }
                    continue;
                }

                /* 相手からの packet の fragment の有無をチェックする必要は無い。*/
                /* 期待する ack をもつ packet を調べる*/	
                if( ACK(streams_check) == exp_ack ){
                    acked_elapse = TIMEVAL_TO_SEC(streams_check->plist->php->pktime);
                    INDENT(streams);
                    printf("\t> exactly acked by %d(%f Sec)\n",
                           streams_check->plist->packet_number, acked_elapse - receive_time);
                    break;
                } else if (ACK(streams_check) > exp_ack ){
                    acked_elapse = TIMEVAL_TO_SEC(streams_check->plist->php->pktime);
                    INDENT(streams);
                    printf("\t> acked by %d(%f Sec)\n",
                           streams_check->plist->packet_number,acked_elapse - receive_time);
                    break;
                }

                if(streams_check->stream_next == NULL){ /* 最後まで来たら ACK されていないと言うこと*/
                    INDENT(streams);
                    printf("\t> not acked!!!\n");
                }
            } /* loop for searching ack end */
        } /* loop for stream end */
    } /* loop for connection list end */
}
示例#3
0
/*
 *	Write captured packet to file
 *
 *	uint8_t *flag : filter is set or not
 *	const uint8_t *packet : captured packet
 *	char *fltrload : filter for payload
 *	cosnt int payloadlen : length of captured payload
 */
static void printfile(uint8_t *flag, const uint8_t *packet, char *fltrload, const int payloadlen)
{
	FILE *fp = fopen(LOGFILE, "a");
	const uint8_t *http = NULL;
	char *timestamp;
	struct ether_header *eth;
	struct ip *iphdr;
	struct tcphdr *tcphdr;
	struct udphdr *udphdr;
	uint8_t prot;
	int hdrlen, i;

	flag += 2;  // remove unused member

	eth = (struct ether_header *)packet;
	hdrlen = sizeof(struct ether_header);

	iphdr = (struct ip *)(packet + hdrlen);
	hdrlen += sizeof(struct ip);

	prot = iphdr->ip_p;
	if( prot == 17 ) {
		udphdr = (struct udphdr *)(packet + hdrlen);
		hdrlen += sizeof(struct udphdr);
	}else {
		tcphdr = (struct tcphdr *)(packet + hdrlen);
		hdrlen += sizeof(struct tcphdr);

		// HTTP request check 
		if( PROTOCOL(flag) ) {
			if( prot == 3 ) {
				if( HTTPTEST("GET",3) == false )
					return;

			}else if( prot == 5 ) {
				if( HTTPTEST("PUT",3) == false )
					return;

			}else if(prot == 7) {
				if( HTTPTEST("POST",4) == false )
					return;
			}
		}
	}

	
	

	// Timestamp
	timestamp = (char *)gettime();
	fprintf(fp, "%s ------\n", timestamp);
	free(timestamp);

	/* Ethernet Header */
	i = 0;
	if( DSTMAC(flag) ) {
		fprintf(fp, "\x1b[45mDestination MAC\x1b[0m\t: \x1b[45m");
		while( i < 5 )
			fprintf(fp, "%02X:", eth->ether_dhost[i++]);
		fprintf(fp, "%02X\x1b[0m\n", eth->ether_dhost[i]);
	}else {
		fprintf(fp, "Destination MAC\t: ");
		while( i < 5 )
			fprintf(fp, "%02X:", eth->ether_dhost[i++]);
		fprintf(fp, "%02X\n", eth->ether_dhost[i]);
	}

	i = 0;
	if( SRCMAC(flag) ) {
		fprintf(fp, "\x1b[45mSource MAC\x1b[0m\t: \x1b[45m");
		while( i < 5 )
			fprintf(fp, "%02X:", eth->ether_shost[i++]);
		fprintf(fp, "%02X\x1b[0m\n", eth->ether_shost[i]);
	}else {
		fprintf(fp, "Source MAC\t: ");
		while( i < 5 )
			fprintf(fp, "%02X:", eth->ether_shost[i++]);
		fprintf(fp, "%02X\n", eth->ether_shost[i]);
	}

	if( ETHERTYPE(flag) )
		fprintf(fp, "\x1b[45mEthernet Type\x1b[0m\t: \x1b[45m%s\x1b[0m\n", gettype(eth->ether_type));
	else
		fprintf(fp, "Ethernet Type\t: %s\n", gettype(eth->ether_type));

	/* IP Header */
	if( VERSION(flag) & 0xf0 )
		fprintf(fp, "\x1b[44mVersion\x1b[0m\t\t: \x1b[44m%d\x1b[0m\n", iphdr->ip_v);
	else
		fprintf(fp, "Version\t\t: %d\n", iphdr->ip_v);

	if( IPHLEN(flag) & 0x0f )
		fprintf(fp, "\x1b[44mIP Header length\x1b[0m: \x1b[44m%d\x1b[0m\n", iphdr->ip_hl);
	else
		fprintf(fp, "IP Header length: %d\n", iphdr->ip_hl);

	if( TOS(flag) )
		fprintf(fp, "\x1b[44mType of Service\x1b[0m\t: \x1b[44m%s\x1b[0m\n", gettos(iphdr->ip_tos));
	else
		fprintf(fp, "Type of Service\t: %s\n", gettos(iphdr->ip_tos));

	if( IPLEN(flag) )
		fprintf(fp, "\x1b[44mTotal length\x1b[0m\t: \x1b[44m%d\x1b[0m\n", ntohs(iphdr->ip_len));
	else
		fprintf(fp, "Total length\t: %d\n", ntohs(iphdr->ip_len));

	if( IPID(flag) )
		fprintf(fp, "\x1b[44mIdentification\x1b[0m\t: \x1b[44m%d\x1b[0m\n", ntohs(iphdr->ip_id));
	else
		fprintf(fp, "Identification\t: %d\n", ntohs(iphdr->ip_id));

	if( FRAGMENT(flag) )
		fprintf(fp, "\x1b[44mFragment\x1b[0m\t: \x1b[44m%d\x1b[0m\n", iphdr->ip_off);
	else
		fprintf(fp, "Fragment\t: %d\n", iphdr->ip_off);

	if( TTL(flag) )
		fprintf(fp, "\x1b[44mTime to live\x1b[0m\t: \x1b[44m%d\x1b[0m\n", iphdr->ip_ttl);
	else
		fprintf(fp, "Time to live\t: %d\n", iphdr->ip_ttl);

	if( PROTOCOL(flag) )
		fprintf(fp, "\x1b[44mProtocol\x1b[0m\t: \x1b[44m%s\x1b[0m\n", getprot(iphdr->ip_p));
	else
		fprintf(fp, "Protocol\t: %s\n", getprot(iphdr->ip_p));

	if( IPCKSUM(flag) )
		fprintf(fp, "\x1b[44mChecksum\x1b[0m\t: \x1b[44m%d\x1b[0m\n", ntohs(iphdr->ip_sum));
	else
		fprintf(fp, "Checksum\t: %d\n", ntohs(iphdr->ip_sum));

	if( SRCIP(flag) )
		fprintf(fp, "\x1b[44mSource IP\x1b[0m\t: \x1b[44m%s\x1b[0m\n", inet_ntoa(iphdr->ip_src));
	else
		fprintf(fp, "Source IP\t: %s\n", inet_ntoa(iphdr->ip_src));

	if( DSTIP(flag) )
		fprintf(fp, "\x1b[44mDestination IP\x1b[0m\t: \x1b[44m%s\x1b[0m\n", inet_ntoa(iphdr->ip_dst));
	else
		fprintf(fp, "Destination IP\t: %s\n", inet_ntoa(iphdr->ip_dst));

	if( iphdr->ip_p == 17 ) {
	/* UDP Header */
		if( SRCPORT(flag) )
			fprintf(fp, "\x1b[42mSource Port\x1b[0m\t: \x1b[42m%d\x1b[0m\n", ntohs(udphdr->source));
		else
			fprintf(fp, "Source Port\t: %d\n", ntohs(udphdr->source));

		if( DSTPORT(flag) )
			fprintf(fp, "\x1b[42mDestination Port\x1b[0m: \x1b[42m%d\x1b[0m\n", ntohs(udphdr->dest));
		else
			fprintf(fp, "Destination Port: %d\n", ntohs(udphdr->dest));

		if( UDPLEN(flag) )
			fprintf(fp, "\x1b[42mTotal length\x1b[0m\t: \x1b[42m%d\x1b[0m\n", ntohs(udphdr->len));
		else
			fprintf(fp, "Total length\t: %d\n", ntohs(udphdr->len));

		if( UDPCKSUM(flag) )
			fprintf(fp, "\x1b[42mCheckSum\x1b[0m\t: \x1b[42m%d\x1b[0m\n", ntohs(udphdr->check));
		else
			fprintf(fp, "Checksum\t: %d\n", ntohs(udphdr->check));
	}else {
	/* TCP Header */
		if( SRCPORT(flag) )
			fprintf(fp, "\x1b[31;43mSource Port\x1b[0m\t: \x1b[31;43m%d\x1b[0m\n", ntohs(tcphdr->source));
		else
			fprintf(fp, "Source Port\t: %d\n", ntohs(tcphdr->source));

		if( DSTPORT(flag) )
			fprintf(fp, "\x1b[31;43mDestination Port\x1b[0m: \x1b[31;43m%d\x1b[0m\n", ntohs(tcphdr->dest));
		else
			fprintf(fp, "Destination Port: %d\n", ntohs(tcphdr->dest));

		if( SEQ(flag) )
			fprintf(fp, "\x1b[31;43mSequence Number\x1b[0m\t: \x1b[31;43m%u\x1b[0m\n", ntohl(tcphdr->seq));
		else
			fprintf(fp, "Sequence Number\t: %u\n", ntohl(tcphdr->seq));

		if( ACK(flag) )
			fprintf(fp, "\x1b[31;43mAcknowledgement\x1b[0m\t: \x1b[31;43m%u\x1b[0m\n", ntohl(tcphdr->ack));
		else
			fprintf(fp, "Acknowledgement\t: %u\n", ntohl(tcphdr->ack));

		if( TCPOFF(flag) & 0x0f )
			fprintf(fp, "\x1b[31;43mOffset\x1b[0m\t\t: \x1b[31;43m%d\x1b[0m\n", tcphdr->doff);
		else
			fprintf(fp, "Offset\t\t: %d\n", tcphdr->doff);

		if( TCPRES(flag) & 0xf0 )
			fprintf(fp, "\x1b[31;43mReserved\x1b[0m\t: \x1b[31;43m%d\x1b[0m\n", tcphdr->res1);
		else
			fprintf(fp, "Reserved\t: %d\n", tcphdr->res1);

		char *tmp = getflag(*(packet + 47), tcphdr->res1, tcphdr->res2);
		if( TCPFLAG(flag) )
			fprintf(fp, "\x1b[31;43mFlags\x1b[0m\t\t: \x1b[31;43m%s\x1b[0m\n", tmp);
		else
			fprintf(fp, "Flags\t\t: %s\n", tmp);
		free(tmp);

		if( WINDOW(flag) )
			fprintf(fp, "\x1b[31;43mWindow size\x1b[0m\t: \x1b[31;43m%d\x1b[0m\n", ntohs(tcphdr->window));
		else
			fprintf(fp, "Window size\t: %d\n", ntohs(tcphdr->window));

		if( TCPCKSUM(flag) )
			fprintf(fp, "\x1b[31;43mChecksum\x1b[0m\t: \x1b[31;43m%d\x1b[0m\n", ntohs(tcphdr->check));
		else
			fprintf(fp, "Checksum\t: %d\n", ntohs(tcphdr->check));

		if( URGPTR(flag) )
			fprintf(fp, "\x1b[31;43mUrgent Pointer\x1b[0m\t: \x1b[31;43m%d\x1b[0m\n", ntohs(tcphdr->urg_ptr));
		else
			fprintf(fp, "Urgent Pointer\t: %d\n", ntohs(tcphdr->urg_ptr));
	}

	/* Payload */
	if( fltrload != NULL ) {
		const uint8_t *match = NULL;
		uint8_t highlight[MAXPAYLOAD];
		int fltrloadlen, unmatchlen = 0;
		int colorhex = 0, colorstr = 0;
		int i = 0, str = 0, colorlen = 0, highlen = 0;
		char ch;

		memset(highlight, 0, MAXPAYLOAD);

		packet += hdrlen;
		fltrloadlen = strlen(fltrload);

		fprintf(fp, "*** Payload ***\n");

		if( http != NULL ) {
			if( prot == 3 ) {
				memcpy(highlight, HTTPCOLOR, 5);
				memcpy(highlight + 5, "GET\x1b[0m", 7);
				highlen += 12;
				i += 3;

			}else if( prot == 5 ) {
				memcpy(highlight, HTTPCOLOR, 5);
				memcpy(highlight + 5, "PUT\x1b[0m", 7);
				highlen += 12;
				i += 3;

			}else if( prot == 7 ) {
				memcpy(highlight, HTTPCOLOR, 5);
				memcpy(highlight + 5, "POST\x1b[0m", 8);
				highlen += 13;
				i += 4;
			}
		}

		while( i < payloadlen ) {
			// move to next matching string
			match = memcmp_cont(packet + i, fltrload, fltrloadlen, payloadlen - i);
			if( match == NULL ) {
				unmatchlen = payloadlen - i;

				memcpy(highlight + highlen, packet + i, unmatchlen);
				highlen += unmatchlen;

				break;
			}else {

				if( http != NULL && match - packet > http - packet ) {
				// HTTP/1.1
					unmatchlen = http - (packet + i);

					memcpy(highlight + highlen, packet + i, unmatchlen);
					highlen += unmatchlen;
					i += unmatchlen;

					memcpy(highlight + highlen, "\x1b[46mHTTP/1.1\x1b[0m", 17);
					highlen += 17;
					i += 8;
					http = NULL;
				}else {
					unmatchlen = match - (packet + i);

					memcpy(highlight + highlen, packet + i, unmatchlen);
					highlen += unmatchlen;
					i += unmatchlen;

					memcpy(highlight + highlen, PAYLOADCOLOR, 5);
					highlen += 5;

					memcpy(highlight + highlen, packet + i, fltrloadlen);
					highlen += fltrloadlen;
					i += fltrloadlen;

					memcpy(highlight + highlen, NORMALCOLOR, 4);
					highlen += 4;
				}
			}
		}

		i = 0;
		while( i < highlen ) {
			ch = *(highlight + i);

			if( ch == '\x1b' ) {
				if( COLORTEST(i, PAYLOADCOLOR) == true ) {
					fprintf(fp, PAYLOADCOLOR);
					colorhex = 41;
					i += 5;
					colorlen += 5;
					continue;

				}else if( COLORTEST(i, HTTPCOLOR) == true ) {
					fprintf(fp, HTTPCOLOR);
					colorhex = 46;
					i += 5;
					colorlen += 5;
					continue;

				}else if( COLORTEST(i, NORMALCOLOR) == true ) {
					fprintf(fp, NORMALCOLOR);
					colorhex = 0;
					i += 4;
					colorlen += 4;
					continue;
				}
			}

			fprintf(fp, "%02X ", ch);
			i++;

			if( ++str == 16 ) {
				if( colorhex != 0 )
					fprintf(fp, NORMALCOLOR);

				fprintf(fp, "   ");

				if( colorstr == 41 ) {
					fprintf(fp, PAYLOADCOLOR);
					colorstr = 0;

				}else if( colorstr == 46 ) {
					fprintf(fp, HTTPCOLOR);
					colorstr = 0;
				}

				while( colorlen > 0 ) {
					ch = *(highlight + i - colorlen - str);
					if( ch > 126 || ch < 32 ) {
						if( ch == 27 ) {
							if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true )
								colorstr = 41;

							else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true )
								colorstr = 46;

							else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true )
								colorstr = 0;

							else
								ch = '.';
						}else
							ch = '.';
					}
					fprintf(fp, "%c", ch);
					colorlen--;
				}

				while( str > 0 ) {
					ch = *(highlight + i - str);
					if( ch > 126 || ch < 32 ) {
						if( ch == 27 ) {
							if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true )
								colorstr = 41;
							else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true )
								colorstr = 46;
							else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true )
								colorstr = 0;
							else
								ch = '.';
						}else
							ch = '.';
					}
					fprintf(fp, "%c", ch);
					str--;
				}

				if( colorstr != 0 )
					fprintf(fp, NORMALCOLOR);

				fprintf(fp, "\n");

				if( colorhex == 41 ) {
					fprintf(fp, PAYLOADCOLOR);
					colorhex = 0;

				}else if( colorhex == 46 ) {
					fprintf(fp, HTTPCOLOR);
					colorhex = 0;
				}
			}
		}

		if( str != 0 ) {
			int padd = 17;
			if( colorhex != 0 )
				fprintf(fp, NORMALCOLOR);

			while( str < padd-- )
				fprintf(fp, "   ");

			if( colorstr == 41 ) {
				fprintf(fp, PAYLOADCOLOR);
				colorstr = 0;

			}else if( colorstr == 46 ) {
				fprintf(fp, HTTPCOLOR);
				colorstr = 0;
			}

			while( colorlen > 0 ) {
				ch = *(highlight + i - colorlen - str);
				if( ch > 126 || ch < 32 ) {
					if( ch == 27 ) {
						if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true )
							colorstr = 41;
						else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true )
							colorstr = 46;
						else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true )
							colorstr = 0;
						else
							ch = '.';
					}else
						ch = '.';
				}
				fprintf(fp, "%c", ch);
				colorlen--;
			}

			while( str > 0 ) {
				ch = *(highlight + i - str);
				if( ch > 126 || ch < 32 ) {
					if( ch == 27 ) {
						if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true )
							colorstr = 41;
						else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true )
							colorstr = 46;
						else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true )
							colorstr = 0;
						else
							ch = '.';
					}else
						ch = '.';
				}
				fprintf(fp, "%c", ch);
				str--;
			}
			fprintf(fp, "\x1b[0m\n");
		}
	}else { // fltrload == NULL
		uint8_t highlight[MAXPAYLOAD];
		int unmatchlen = 0;
		int colorhex = 0, colorstr = 0;
		int i = 0, str = 0, colorlen = 0, highlen = 0;
		char ch;

		memset(highlight, 0, MAXPAYLOAD);

		packet += hdrlen;

		fprintf(fp, "*** Payload ***\n");

		if( http != NULL ) {
			if( prot == 3 ) {
				memcpy(highlight, HTTPCOLOR, 5);
				memcpy(highlight + 5, "GET\x1b[0m", 7);
				highlen += 12;
				i += 3;

			}else if( prot == 5 ) {
				memcpy(highlight, HTTPCOLOR, 5);
				memcpy(highlight + 5, "PUT\x1b[0m", 7);
				highlen += 12;
				i += 3;

			}else if( prot == 7 ) {
				memcpy(highlight, HTTPCOLOR, 5);
				memcpy(highlight + 5, "POST\x1b[0m", 8);
				highlen += 13;
				i += 4;
			}
		}

		while( i < payloadlen ) {
		// move to next matching string
			if( http != NULL ) {
			// HTTP/1.1
				unmatchlen = http - (packet + i);

				memcpy(highlight + highlen, packet + i, unmatchlen);
				highlen += unmatchlen;
				i += unmatchlen;

				memcpy(highlight + highlen, "\x1b[46mHTTP/1.1\x1b[0m", 17);
				highlen += 17;
				i += 8;
				http = NULL;
			}else {
				memcpy(highlight + highlen, packet + i, payloadlen - i);
				highlen += unmatchlen;
				i += unmatchlen;
			}
		}

		i = 0;
		while( i < highlen ) {
			ch = *(highlight + i);

			if( ch == '\x1b' ) {
				if( COLORTEST(i, PAYLOADCOLOR) == true ) {
					fprintf(fp, PAYLOADCOLOR);
					colorhex = 41;
					i += 5;
					colorlen += 5;
					continue;

				}else if( COLORTEST(i, HTTPCOLOR) == true ) {
					fprintf(fp, HTTPCOLOR);
					colorhex = 46;
					i += 5;
					colorlen += 5;
					continue;

				}else if( COLORTEST(i, NORMALCOLOR) == true ) {
					fprintf(fp, NORMALCOLOR);
					colorhex = 0;
					i += 4;
					colorlen += 4;
					continue;
				}
			}

			fprintf(fp, "%02X ", ch);
			i++;

			if( ++str == 16 ) {
				if( colorhex != 0 )
					fprintf(fp, NORMALCOLOR);

				fprintf(fp, "   ");

				if( colorstr == 41 ) {
					fprintf(fp, PAYLOADCOLOR);
					colorstr = 0;

				}else if( colorstr == 46 ) {
					fprintf(fp, HTTPCOLOR);
					colorstr = 0;
				}

				while( colorlen > 0 ) {
					ch = *(highlight + i - colorlen - str);
					if( ch > 126 || ch < 32 ) {
						if( ch == 27 ) {
							if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true )
								colorstr = 41;
							else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true )
								colorstr = 46;
							else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true )
								colorstr = 0;
							else
								ch = '.';
						}else
							ch = '.';
					}
					fprintf(fp, "%c", ch);
					colorlen--;
				}

				while( str > 0 ) {
					ch = *(highlight + i - str);
					if( ch > 126 || ch < 32 ) {
						if( ch == 27 ) {
							if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true )
								colorstr = 41;
							else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true )
								colorstr = 46;
							else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true )
								colorstr = 0;
							else
								ch = '.';
						}else
							ch = '.';
					}
					fprintf(fp, "%c", ch);
					str--;
				}

				if( colorstr != 0 )
					fprintf(fp, NORMALCOLOR);

				fprintf(fp, "\n");

				if( colorhex == 41 ) {
					fprintf(fp, PAYLOADCOLOR);
					colorhex = 0;

				}else if( colorhex == 46 ) {
					fprintf(fp, HTTPCOLOR);
					colorhex = 0;
				}
			}
		}

		if( str != 0 ) {
			int padd = 17;
			if( colorhex != 0 )
				fprintf(fp, NORMALCOLOR);

			while( str < padd-- )
				fprintf(fp, "   ");

			if( colorstr == 41 ) {
				fprintf(fp, PAYLOADCOLOR);
				colorstr = 0;

			}else if( colorstr == 46 ) {
				fprintf(fp, HTTPCOLOR);
				colorstr = 0;
			}

			while( colorlen > 0 ) {
				ch = *(highlight + i - colorlen - str);
				if( ch > 126 || ch < 32 ) {
					if( ch == 27 ) {
						if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true )
							colorstr = 41;
						else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true )
							colorstr = 46;
						else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true )
							colorstr = 0;
						else
							ch = '.';
					}else
						ch = '.';
				}
				fprintf(fp, "%c", ch);
				colorlen--;
			}

			while( str > 0 ) {
				ch = *(highlight + i - str);
				if( ch > 126 || ch < 32 ) {
					if( ch == 27 ) {
						if( COLORTEST(i - colorlen - str, PAYLOADCOLOR) == true )
							colorstr = 41;
						else if( COLORTEST(i - colorlen - str, HTTPCOLOR) == true )
							colorstr = 46;
						else if( COLORTEST(i - colorlen - str, NORMALCOLOR) == true )
							colorstr = 0;
						else
							ch = '.';
					}else
						ch = '.';
				}
				fprintf(fp, "%c", ch);
				str--;
			}
			fprintf(fp, "\x1b[0m\n");
		}
	}
	fprintf(fp, "----------------------------\n");
	fclose(fp);
}