示例#1
0
void
traffic_read(
    struct ip *pip,		/* the packet */
    tcp_pair *ptp,		/* info I have about this connection */
    void *plast,		/* past byte in the packet */
    void *mod_data)		/* connection info for this one */
{
    struct tcphdr *ptcp = (struct tcphdr *) ((char *)pip + 4*IP_HL(pip));
    struct traffic_info *pti1 = FindPort(ntohs(ptcp->th_sport));
    struct traffic_info *pti2 = FindPort(ntohs(ptcp->th_dport));
    u_long bytes = ntohs(pip->ip_len);
    static timeval last_time = {0,0};
    struct conn_info *pci = mod_data;
    int was_rexmit = 0;

    /* in case files aren't set up yet */
    traffic_init_files();

    /* if neither port is interesting, then ignore this one */
    if (!pti1 && !pti2) {
	return;
    }

    /* OK, this connection is now active */
    pci->wasactive = 1;

    /* check to see if it's really "open" (traffic in both directions) */
    if (!pci->wasopen) {
	if ((ptp->a2b.packets > 0) && (ptp->b2a.packets > 0)) {
	    /* bidirectional: OK, we'll call it open */
	    pci->wasopen = 1;
	    pci->isopen = 1;
	    ++num_opens;
	    ++ttl_num_opens;
	    ++open_conns;

	    /* instantaneous opens and closes */
	    if (doplot_i_open) {
		DoplotIOpen(ntohs(ptcp->th_dport), TRUE);
		DoplotIOpen(ntohs(ptcp->th_sport), TRUE);
		DoplotIOpen(0, TRUE);
	    }
	}
    }

    /* add to port-specific counters */
    if (pti1) {
	pti1->nbytes += bytes;
	pti1->npackets += 1;
    }
    if (pti2) {
	pti2->nbytes += bytes;
	pti2->npackets += 1;
    }

    /* add to GLOBAL counters */
    ports[0]->nbytes += bytes;
    ports[0]->npackets += 1;
    ports[0]->npureacks += 1;

    /* see if we're closing it */
    if (RESET_SET(ptcp) ||
	(FIN_SET(ptcp) &&	/* find in BOTH directions */
	 ((ptp->a2b.fin_count>0) && (ptp->b2a.fin_count>0)))) {
	if (pci->isopen) {
	    pci->isopen = 0;
	    ++num_closes;
	    --open_conns;

	    /* instantaneous opens and closes */
	    if (doplot_i_open) {
		DoplotIOpen(ntohs(ptcp->th_dport), FALSE);
		DoplotIOpen(ntohs(ptcp->th_sport), FALSE);
		DoplotIOpen(0, FALSE);
	    }
	}
    }

    /* half open conns */
    if (FIN_SET(ptcp)) {
	if ((ptp->a2b.fin_count>0) && (ptp->b2a.fin_count>0)) {
	    if (pci->halfopen) {
		/* fully closed now */
		--num_halfopens;
		pci->halfopen = 0;
	    }
	} else if (!pci->halfopen) {
		/* half open now */
		++num_halfopens;
		pci->halfopen = 1;
	}
    }

    /* check losses */
    if (pci->last_dupacks != ptp->a2b.rtt_triple_dupack+
	ptp->b2a.rtt_triple_dupack) {
	pci->last_dupacks = ptp->a2b.rtt_triple_dupack+
	    ptp->b2a.rtt_triple_dupack;
	++dupacks;
	++ttl_dupacks;
    }
    if (pci->last_rexmits != ptp->a2b.rexmit_pkts+ptp->b2a.rexmit_pkts) {
	pci->last_rexmits = ptp->a2b.rexmit_pkts+ptp->b2a.rexmit_pkts;
	was_rexmit = 1;
	++rexmits;
	++ttl_rexmits;
    }


    /* add to total data counters */
    data_nbytes_all += bytes;
    if (!was_rexmit)
	data_nbytes_nonrexmit += bytes;
    

    /* RTT stats */
    if (ACK_SET(ptcp)) {
	tcb *ptcb;
	int rtt;

	/* see which of the 2 TCB's this goes with */
	if (ptp->addr_pair.a_port == ntohs(ptcp->th_dport))
	    ptcb = &ptp->a2b;
	else
	    ptcb = &ptp->b2a;

	/* check the rtt counter of the last sample */
	rtt = ptcb->rtt_last / 1000.0;
 
	if ((pci->last_rtts != ptcb->rtt_count + ptcb->rtt_amback) &&
	    (ptcb->rtt_last != 0.0) &&
	    (rtt > rtt_minvalid) && (rtt <= rtt_maxvalid)) {

	    /* sample is only valid when one of these counters is higher */
	    pci->last_rtts = ptcb->rtt_count + ptcb->rtt_amback;

	    /* keep stats */
	    rtt_ttl += rtt;
	    ttl_rtt_ttl += rtt;
	    ++rtt_samples;
	    ++ttl_rtt_samples;

	    /* also, remember min and max */
	    if ((rtt_max == -1) || (rtt_max < rtt))
		rtt_max = rtt;
	    if ((rtt_min == -1) || (rtt_min > rtt))
		rtt_min = rtt;

	    if (ldebug > 9)
		printf("Rtt: %d,  min:%d,  max:%d\n",
		       rtt, rtt_min, rtt_max);
	}
    }


    /* see if this is now "long duration" */
    if (!pci->islong) {
	int etime_msecs = elapsed(ptp->first_time,current_time);
	if (etime_msecs/1000000 > longconn_duration) {
	    pci->islong = 1;
	}
    }

    /* count "pure acks" (no data) */
    if (ACK_SET(ptcp)) {
	int tcp_length, tcp_data_length;
	tcp_length = getpayloadlength(pip, plast);
	tcp_data_length = tcp_length - (4 * TH_OFF(ptcp));
	if (tcp_data_length == 0) {
	    if (pti1) {
		++pti1->npureacks;
	    }
	    if (pti2) {
		++pti2->npureacks;
	    }
	}
    }


    /* determine elapsed time and age the samples */
    if (elapsed(last_time,current_time)/1000000.0 > age_interval) {
	AgeTraffic();
	last_time = current_time;
    }
}
示例#2
0
void dump_flow_stat (struct ip *pip, 
                     void *pproto, 
                     int tproto, 
                     void *pdir,
	                 int dir, 
                     void *hdr, 
                     void *plast) 
{
    int ucb_type;

    if (!dump_engine)
        return;

    if (threaded)
        pthread_mutex_lock(&dump_mutex);

    /***** TCP packets *****/
    if (tproto == PROTOCOL_TCP)
    /* It's TCP, there is still a flow associated to this, and we are not already discarding it */
     {
       struct stcp_pair *p = ((tcb *)pdir)->ptp;

       if (proto2dump[DUMP_TCP_COMPLETE].enabled && (p != NULL) && !(p->stop_dumping_tcp) ) 
         {
            /* are we still interested in this flow packets? */
            if ( ( p->con_type != UNKNOWN_PROTOCOL )  /* we always log unknowns */
                  &&
                 ( (p->con_type & stop_dumping_mask) != 0 ) /* after masking, we are not interested into it */
               )
             {
               p->stop_dumping_tcp = TRUE;
               if (debug>0)
                {
                  fprintf(fp_stderr, "Stopping dumping this flow - con_type = %d\n",p->con_type);
                }
             }
                
            if (!(p->stop_dumping_tcp))
             { 
               /* do we have to dump all the packets of all the flows */
               if (tcp_maxbytes == 0 && tcp_maxpackets == 0)
                {
                  dump_to_file(&proto2dump[DUMP_TCP_COMPLETE], pip, plast);
	            }
	            /* or we have to stop dumping acks and data packets up to reach 
                 * - tcp_maxbytes 
                 * - tcp_maxpackets 
                 */
               else
                {
                  struct tcphdr *ptcp = pproto;
                  /* check if the underlying flow struct tcb has not yet been released */
                  if ( p != NULL)
                   {
                     int tcp_data_length = getpayloadlength (pip, plast) - (4 * ptcp->th_off);

                     tcb *thisdir = (tcb*)pdir;
                     tcb *otherdir = (dir == C2S) ? &(thisdir->ptp->s2c) : &(thisdir->ptp->c2s);

                     if ((
                        /* packets with payload */
                        tcp_data_length > 0 && 
                            /* check the thresholds */
                            ((tcp_maxbytes > 0   && thisdir->seq - thisdir->syn - tcp_data_length <= tcp_maxbytes) || 
                             (tcp_maxpackets > 0 && thisdir->data_pkts <= tcp_maxpackets))
                        ) || (
                        /* this is a pure ack */
                        tcp_data_length == 0 && 
                            (otherdir->seq <= thisdir->ack && /* which is a valid ack */
                              ( /* and we are still interested in otherdir packets */
                                (tcp_maxbytes > 0 && otherdir->seq - otherdir->syn <= tcp_maxbytes) ||
                                (tcp_maxpackets > 0 && otherdir->data_pkts <= tcp_maxpackets) ||
                                (otherdir->fin_count >= 1 && thisdir->ack >= (otherdir->fin_seqno+1))
                            ))
                        ) ||
                        SYN_SET (ptcp) || 
                        FIN_SET(ptcp)
                       ) 
                        {
                            dump_to_file(&proto2dump[DUMP_TCP_COMPLETE], pip, plast);
                        }
                       
                    }
                   else
                    {
                      if (RESET_SET(ptcp))
                       {
                         dump_to_file(&proto2dump[DUMP_TCP_COMPLETE], pip, plast);
                       }
                    }
                 }
            } /* end !stop_dumping_tcp */
        } /* end DUMP_TCP_COMPLETE */

#ifdef STREAMING_CLASSIFIER
        if (proto2dump[DUMP_TCP_VIDEOSTREAMING].enabled && ((tcb*)pdir)->ptp != NULL)
         {
            struct stcp_pair *p = ((tcb *)pdir)->ptp;
            if (p->streaming.video_content_type || p->streaming.video_payload_type)
             {
               dump_to_file(&proto2dump[DUMP_TCP_VIDEOSTREAMING], pip, plast);
             }
         }
#endif
     }
    
    /***** UDP packets *****/
    else 
     {
        ucb *mydir = (ucb*)pdir;

        //specific controls to find kad obfuscated...
        ucb_type = UDP_p2p_to_logtype(mydir);

        /* dump to a specific DPI file */
        if (proto2dump[P2P_UTP].enabled)
         {
            /* 
               Since uTP classification is behavioral, we dump both already classified datagrams,
               and datagrams which are not classified, but that are already in a valid state of 
               the identification state machine.
            */
            if ( ucb_type == P2P_UTP || 
                 ucb_type == P2P_UTPBT ||
                 ( (ucb_type==UDP_UNKNOWN || ucb_type==FIRST_RTP || ucb_type==FIRST_RTCP || ucb_type==P2P_BT) &&
                   (mydir->uTP_state > UTP_UNKNOWN )
                 )
               )
             dump_to_file(&proto2dump[P2P_UTP], pip, plast);
         }
    	else if (proto2dump[ucb_type].enabled) 
    	 {
            dump_to_file(&proto2dump[ucb_type], pip, plast);
         }
        // dump to unknown
        // else if (proto2dump[UDP_UNKNOWN].enabled) {
        //    dump_to_file(&proto2dump[UDP_UNKNOWN], pip, plast);
        // }

        if (proto2dump[DUMP_UDP_COMPLETE].enabled) {
            /* dump all the packets of all the flows */
            if (udp_maxpackets == 0 && udp_maxbytes == 0) {
	            dump_to_file(&proto2dump[DUMP_UDP_COMPLETE], pip, plast);
            }
            else {
                /* check if the underlying flow struct ucb has not yet been released */
                if (((ucb*)pdir)->pup != NULL)
                {
                   ucb *thisdir = (ucb*)pdir;
                   /* dump acks and data packets up to reach 
                    * - udp_maxbytes 
                    * - udp_maxpackets 
                    */
                   if ( (thisdir->data_bytes <= udp_maxbytes) || 
                        (thisdir->packets <= udp_maxpackets)) 
                    {
                        dump_to_file(&proto2dump[DUMP_UDP_COMPLETE], pip, plast);
                    }
                }
                else /* it shouldn't happen, but in case dump the packet in any case */
                    dump_to_file(&proto2dump[DUMP_UDP_COMPLETE], pip, plast);
          }
        }
    }

    if (threaded)
        pthread_mutex_unlock(&dump_mutex);
}