Exemplo n.º 1
0
/* Determines how much data is available for reading on the DAG card and
 * updates the various offsets accordingly */
static int dag_available(libtrace_t *libtrace) {

        if (FORMAT_DATA->diff > 0)
                return FORMAT_DATA->diff;

        FORMAT_DATA->bottom = FORMAT_DATA->top;
	FORMAT_DATA->top = dag_offset(
                        FORMAT_DATA->fd,
                        &(FORMAT_DATA->bottom),
                        DAGF_NONBLOCK);
	FORMAT_DATA->diff = FORMAT_DATA->top - FORMAT_DATA->bottom;
	FORMAT_DATA->offset = 0;
        return FORMAT_DATA->diff;
}
Exemplo n.º 2
0
Arquivo: dag.c Projeto: DPMI/mp
static int legacy_read_packet(struct dag_context* cap, unsigned char* dst, struct cap_header* head){
	const ssize_t diff = cap->top - cap->bottom;

	/* no packet in buffer */
	if ( diff < dag_record_size ){
		cap->top = dag_offset(cap->fd, &cap->bottom, 0);
		return 0; /* process eventual packages in the next batch */
	}

	dag_record_t* dr = (dag_record_t *)(cap->buffer + cap->bottom);
	const size_t rlen = ntohs(dr->rlen);

	/* not enough data in buffer */
	if ( diff < rlen ){
		cap->top = dag_offset(cap->fd, &cap->bottom, 0);
		return 0; /* process eventual packages in the next batch */
	}

	/* process packet */
	int ret = process_packet(cap, dr, dst, head);
	cap->bottom += rlen; /* advance read position */

	return ret;
}
Exemplo n.º 3
0
/*
 *  Read at most max_packets from the capture stream and call the callback
 *  for each of them. Returns the number of packets handled, -1 if an
 *  error occured, or -2 if we were told to break out of the loop.
 */
static int
dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
	unsigned int processed = 0;
	int flags = p->md.dag_offset_flags;
	unsigned int nonblocking = flags & DAGF_NONBLOCK;

	/* Get the next bufferful of packets (if necessary). */
	while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) {
 
		/*
		 * Has "pcap_breakloop()" been called?
		 */
		if (p->break_loop) {
			/*
			 * Yes - clear the flag that indicates that
			 * it has, and return -2 to indicate that
			 * we were told to break out of the loop.
			 */
			p->break_loop = 0;
			return -2;
		}

#ifdef HAVE_DAG_STREAMS_API
		/* dag_advance_stream() will block (unless nonblock is called)
		 * until 64kB of data has accumulated.
		 * If to_ms is set, it will timeout before 64kB has accumulated.
		 * We wait for 64kB because processing a few packets at a time
		 * can cause problems at high packet rates (>200kpps) due
		 * to inefficiencies.
		 * This does mean if to_ms is not specified the capture may 'hang'
		 * for long periods if the data rate is extremely slow (<64kB/sec)
		 * If non-block is specified it will return immediately. The user
		 * is then responsible for efficiency.
		 */
		p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom));
#else
		/* dag_offset does not support timeouts */
		p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags);
#endif /* HAVE_DAG_STREAMS_API */

		if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))
		{
			/* Pcap is configured to process only available packets, and there aren't any, return immediately. */
			return 0;
		}
		
		if(!nonblocking &&
		   p->md.dag_timeout &&
		   (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size))
		{
			/* Blocking mode, but timeout set and no data has arrived, return anyway.*/
			return 0;
		}

	}
	
	/* Process the packets. */
	while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) {

		unsigned short packet_len = 0;
		int caplen = 0;
		struct pcap_pkthdr	pcap_header;

#ifdef HAVE_DAG_STREAMS_API
		dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom);
#else
		dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);
#endif /* HAVE_DAG_STREAMS_API */

		u_char *dp = ((u_char *)header) + dag_record_size;
		unsigned short rlen;
 
		/*
		 * Has "pcap_breakloop()" been called?
		 */
		if (p->break_loop) {
			/*
			 * Yes - clear the flag that indicates that
			 * it has, and return -2 to indicate that
			 * we were told to break out of the loop.
			 */
			p->break_loop = 0;
			return -2;
		}
 
		rlen = ntohs(header->rlen);
		if (rlen < dag_record_size)
		{
			strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
			return -1;
		}
		p->md.dag_mem_bottom += rlen;

		switch(header->type) {
		case TYPE_ATM:
#ifdef TYPE_AAL5
		case TYPE_AAL5:
			if (header->type == TYPE_AAL5) {
				packet_len = ntohs(header->wlen);
				caplen = rlen - dag_record_size;
			}
#endif
#ifdef TYPE_MC_ATM
		case TYPE_MC_ATM:
			if (header->type == TYPE_MC_ATM) {
				caplen = packet_len = ATM_CELL_SIZE;
				dp+=4;
			}
#endif
#ifdef TYPE_MC_AAL5
		case TYPE_MC_AAL5:
			if (header->type == TYPE_MC_AAL5) {
				packet_len = ntohs(header->wlen);
				caplen = rlen - dag_record_size - 4;
				dp+=4;
			}
#endif
			if (header->type == TYPE_ATM) {
				caplen = packet_len = ATM_CELL_SIZE;
			}
			if (p->linktype == DLT_SUNATM) {
				struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
				unsigned long rawatm;
					
				rawatm = ntohl(*((unsigned long *)dp));
				sunatm->vci = htons((rawatm >>  4) & 0xffff);
				sunatm->vpi = (rawatm >> 20) & 0x00ff;
				sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) | 
					((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
					 ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 : 
					  ((dp[ATM_HDR_SIZE] == 0xaa &&
					    dp[ATM_HDR_SIZE+1] == 0xaa &&
					    dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));

			} else {
				packet_len -= ATM_HDR_SIZE;
				caplen -= ATM_HDR_SIZE;
				dp += ATM_HDR_SIZE;
			}
			break;

#ifdef TYPE_COLOR_ETH
		case TYPE_COLOR_ETH:
#endif
		case TYPE_ETH:
			packet_len = ntohs(header->wlen);
			packet_len -= (p->md.dag_fcs_bits >> 3);
			caplen = rlen - dag_record_size - 2;
			if (caplen > packet_len) {
				caplen = packet_len;
			}
			dp += 2;
			break;
#ifdef TYPE_COLOR_HDLC_POS
		case TYPE_COLOR_HDLC_POS:
#endif
		case TYPE_HDLC_POS:
			packet_len = ntohs(header->wlen);
			packet_len -= (p->md.dag_fcs_bits >> 3);
			caplen = rlen - dag_record_size;
			if (caplen > packet_len) {
				caplen = packet_len;
			}
			break;
#ifdef TYPE_MC_HDLC
		case TYPE_MC_HDLC:
			packet_len = ntohs(header->wlen);
			packet_len -= (p->md.dag_fcs_bits >> 3);
			caplen = rlen - dag_record_size - 4;
			if (caplen > packet_len) {
				caplen = packet_len;
			}
			dp += 4;
			break;
#endif
		}
 
		if (caplen > p->snapshot)
			caplen = p->snapshot;

		/* Count lost packets. */
		switch(header->type) {
#ifdef TYPE_COLOR_HDLC_POS
			/* in this type the color value overwrites the lctr */
		case TYPE_COLOR_HDLC_POS:
			break;
#endif
#ifdef TYPE_COLOR_ETH
			/* in this type the color value overwrites the lctr */
		case TYPE_COLOR_ETH:
			break;
#endif
		default:
			if (header->lctr) {
				if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
					p->md.stat.ps_drop = UINT_MAX;
				} else {
					p->md.stat.ps_drop += ntohs(header->lctr);
				}
			}
		}

		/* Run the packet filter if there is one. */
		if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {

			/* convert between timestamp formats */
			register unsigned long long ts;
				
			if (IS_BIGENDIAN()) {
				ts = SWAP_TS(header->ts);
			} else {
				ts = header->ts;
			}

			pcap_header.ts.tv_sec = ts >> 32;
			ts = (ts & 0xffffffffULL) * 1000000;
			ts += 0x80000000; /* rounding */
			pcap_header.ts.tv_usec = ts >> 32;		
			if (pcap_header.ts.tv_usec >= 1000000) {
				pcap_header.ts.tv_usec -= 1000000;
				pcap_header.ts.tv_sec++;
			}

			/* Fill in our own header data */
			pcap_header.caplen = caplen;
			pcap_header.len = packet_len;
	
			/* Count the packet. */
			p->md.stat.ps_recv++;
	
			/* Call the user supplied callback function */
			callback(user, &pcap_header, dp);
	
			/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
			processed++;
			if (processed == cnt)
			{
				/* Reached the user-specified limit. */
				return cnt;
			}
		}
	}
Exemplo n.º 4
0
/*
 *  Read at most max_packets from the capture stream and call the callback
 *  for each of them. Returns the number of packets handled, -1 if an
 *  error occured, or -2 if we were told to break out of the loop.
 */
static int
dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
    struct pcap_dag *pd = p->priv;
    unsigned int processed = 0;
    int flags = pd->dag_offset_flags;
    unsigned int nonblocking = flags & DAGF_NONBLOCK;
    unsigned int num_ext_hdr = 0;
    unsigned int ticks_per_second;

    /* Get the next bufferful of packets (if necessary). */
    while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) {

        /*
         * Has "pcap_breakloop()" been called?
         */
        if (p->break_loop) {
            /*
             * Yes - clear the flag that indicates that
             * it has, and return -2 to indicate that
             * we were told to break out of the loop.
             */
            p->break_loop = 0;
            return -2;
        }

#ifdef HAVE_DAG_STREAMS_API
        /* dag_advance_stream() will block (unless nonblock is called)
         * until 64kB of data has accumulated.
         * If to_ms is set, it will timeout before 64kB has accumulated.
         * We wait for 64kB because processing a few packets at a time
         * can cause problems at high packet rates (>200kpps) due
         * to inefficiencies.
         * This does mean if to_ms is not specified the capture may 'hang'
         * for long periods if the data rate is extremely slow (<64kB/sec)
         * If non-block is specified it will return immediately. The user
         * is then responsible for efficiency.
         */
        if ( NULL == (pd->dag_mem_top = dag_advance_stream(p->fd, pd->dag_stream, &(pd->dag_mem_bottom))) ) {
            return -1;
        }
#else
        /* dag_offset does not support timeouts */
        pd->dag_mem_top = dag_offset(p->fd, &(pd->dag_mem_bottom), flags);
#endif /* HAVE_DAG_STREAMS_API */

        if (nonblocking && (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
        {
            /* Pcap is configured to process only available packets, and there aren't any, return immediately. */
            return 0;
        }

        if(!nonblocking &&
                pd->dag_timeout &&
                (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
        {
            /* Blocking mode, but timeout set and no data has arrived, return anyway.*/
            return 0;
        }

    }

    /* Process the packets. */
    while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) {

        unsigned short packet_len = 0;
        int caplen = 0;
        struct pcap_pkthdr	pcap_header;

#ifdef HAVE_DAG_STREAMS_API
        dag_record_t *header = (dag_record_t *)(pd->dag_mem_bottom);
#else
        dag_record_t *header = (dag_record_t *)(pd->dag_mem_base + pd->dag_mem_bottom);
#endif /* HAVE_DAG_STREAMS_API */

        u_char *dp = ((u_char *)header); /* + dag_record_size; */
        unsigned short rlen;

        /*
         * Has "pcap_breakloop()" been called?
         */
        if (p->break_loop) {
            /*
             * Yes - clear the flag that indicates that
             * it has, and return -2 to indicate that
             * we were told to break out of the loop.
             */
            p->break_loop = 0;
            return -2;
        }

        rlen = ntohs(header->rlen);
        if (rlen < dag_record_size)
        {
            strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
            return -1;
        }
        pd->dag_mem_bottom += rlen;

        /* Count lost packets. */
        switch((header->type & 0x7f)) {
        /* in these types the color value overwrites the lctr */
        case TYPE_COLOR_HDLC_POS:
        case TYPE_COLOR_ETH:
        case TYPE_DSM_COLOR_HDLC_POS:
        case TYPE_DSM_COLOR_ETH:
        case TYPE_COLOR_MC_HDLC_POS:
        case TYPE_COLOR_HASH_ETH:
        case TYPE_COLOR_HASH_POS:
            break;

        default:
            if (header->lctr) {
                if (pd->stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) {
                    pd->stat.ps_drop = UINT_MAX;
                } else {
                    pd->stat.ps_drop += ntohs(header->lctr);
                }
            }
        }

        if ((header->type & 0x7f) == TYPE_PAD) {
            continue;
        }

        num_ext_hdr = dag_erf_ext_header_count(dp, rlen);

        /* ERF encapsulation */
        /* The Extensible Record Format is not dropped for this kind of encapsulation,
         * and will be handled as a pseudo header by the decoding application.
         * The information carried in the ERF header and in the optional subheader (if present)
         * could be merged with the libpcap information, to offer a better decoding.
         * The packet length is
         * o the length of the packet on the link (header->wlen),
         * o plus the length of the ERF header (dag_record_size), as the length of the
         *   pseudo header will be adjusted during the decoding,
         * o plus the length of the optional subheader (if present).
         *
         * The capture length is header.rlen and the byte stuffing for alignment will be dropped
         * if the capture length is greater than the packet length.
         */
        if (p->linktype == DLT_ERF) {
            packet_len = ntohs(header->wlen) + dag_record_size;
            caplen = rlen;
            switch ((header->type & 0x7f)) {
            case TYPE_MC_AAL5:
            case TYPE_MC_ATM:
            case TYPE_MC_HDLC:
            case TYPE_MC_RAW_CHANNEL:
            case TYPE_MC_RAW:
            case TYPE_MC_AAL2:
            case TYPE_COLOR_MC_HDLC_POS:
                packet_len += 4; /* MC header */
                break;

            case TYPE_COLOR_HASH_ETH:
            case TYPE_DSM_COLOR_ETH:
            case TYPE_COLOR_ETH:
            case TYPE_ETH:
                packet_len += 2; /* ETH header */
                break;
            } /* switch type */

            /* Include ERF extension headers */
            packet_len += (8 * num_ext_hdr);

            if (caplen > packet_len) {
                caplen = packet_len;
            }
        } else {
            /* Other kind of encapsulation according to the header Type */

            /* Skip over generic ERF header */
            dp += dag_record_size;
            /* Skip over extension headers */
            dp += 8 * num_ext_hdr;

            switch((header->type & 0x7f)) {
            case TYPE_ATM:
            case TYPE_AAL5:
                if (header->type == TYPE_AAL5) {
                    packet_len = ntohs(header->wlen);
                    caplen = rlen - dag_record_size;
                }
            case TYPE_MC_ATM:
                if (header->type == TYPE_MC_ATM) {
                    caplen = packet_len = ATM_CELL_SIZE;
                    dp+=4;
                }
            case TYPE_MC_AAL5:
                if (header->type == TYPE_MC_AAL5) {
                    packet_len = ntohs(header->wlen);
                    caplen = rlen - dag_record_size - 4;
                    dp+=4;
                }
                /* Skip over extension headers */
                caplen -= (8 * num_ext_hdr);

                if (header->type == TYPE_ATM) {
                    caplen = packet_len = ATM_CELL_SIZE;
                }
                if (p->linktype == DLT_SUNATM) {
                    struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
                    unsigned long rawatm;

                    rawatm = ntohl(*((unsigned long *)dp));
                    sunatm->vci = htons((rawatm >>  4) & 0xffff);
                    sunatm->vpi = (rawatm >> 20) & 0x00ff;
                    sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) |
                                    ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
                                     ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
                                      ((dp[ATM_HDR_SIZE] == 0xaa &&
                                        dp[ATM_HDR_SIZE+1] == 0xaa &&
                                        dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));

                } else {
                    packet_len -= ATM_HDR_SIZE;
                    caplen -= ATM_HDR_SIZE;
                    dp += ATM_HDR_SIZE;
                }
                break;

            case TYPE_COLOR_HASH_ETH:
            case TYPE_DSM_COLOR_ETH:
            case TYPE_COLOR_ETH:
            case TYPE_ETH:
                packet_len = ntohs(header->wlen);
                packet_len -= (pd->dag_fcs_bits >> 3);
                caplen = rlen - dag_record_size - 2;
                /* Skip over extension headers */
                caplen -= (8 * num_ext_hdr);
                if (caplen > packet_len) {
                    caplen = packet_len;
                }
                dp += 2;
                break;

            case TYPE_COLOR_HASH_POS:
            case TYPE_DSM_COLOR_HDLC_POS:
            case TYPE_COLOR_HDLC_POS:
            case TYPE_HDLC_POS:
                packet_len = ntohs(header->wlen);
                packet_len -= (pd->dag_fcs_bits >> 3);
                caplen = rlen - dag_record_size;
                /* Skip over extension headers */
                caplen -= (8 * num_ext_hdr);
                if (caplen > packet_len) {
                    caplen = packet_len;
                }
                break;

            case TYPE_COLOR_MC_HDLC_POS:
            case TYPE_MC_HDLC:
                packet_len = ntohs(header->wlen);
                packet_len -= (pd->dag_fcs_bits >> 3);
                caplen = rlen - dag_record_size - 4;
                /* Skip over extension headers */
                caplen -= (8 * num_ext_hdr);
                if (caplen > packet_len) {
                    caplen = packet_len;
                }
                /* jump the MC_HDLC_HEADER */
                dp += 4;
#ifdef DLT_MTP2_WITH_PHDR
                if (p->linktype == DLT_MTP2_WITH_PHDR) {
                    /* Add the MTP2 Pseudo Header */
                    caplen += MTP2_HDR_LEN;
                    packet_len += MTP2_HDR_LEN;

                    TempPkt[MTP2_SENT_OFFSET] = 0;
                    TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN;
                    *(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01);
                    *(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff);
                    memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen);
                    dp = TempPkt;
                }
#endif
                break;

            case TYPE_IPV4:
            case TYPE_IPV6:
                packet_len = ntohs(header->wlen);
                caplen = rlen - dag_record_size;
                /* Skip over extension headers */
                caplen -= (8 * num_ext_hdr);
                if (caplen > packet_len) {
                    caplen = packet_len;
                }
                break;

            /* These types have no matching 'native' DLT, but can be used with DLT_ERF above */
            case TYPE_MC_RAW:
            case TYPE_MC_RAW_CHANNEL:
            case TYPE_IP_COUNTER:
            case TYPE_TCP_FLOW_COUNTER:
            case TYPE_INFINIBAND:
            case TYPE_RAW_LINK:
            case TYPE_INFINIBAND_LINK:
            default:
                /* Unhandled ERF type.
                 * Ignore rather than generating error
                 */
                continue;
            } /* switch type */

        } /* ERF encapsulation */