⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nettaperf.cc

📁 网络流量采集及分析软件
💻 CC
字号:
/*!\file   NetTapERF.cc    Copyright 2004 Sebastian Zander (szander@swin.edu.au)    This file is part of Network Measurement and Accounting System (NETMATE).    NETMATE is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    NETMATE is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this software; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    Description:    nettap based on libpcap library    $Id: NetTapERF.cc,v 1.6 2006/02/03 08:04:56 s_zander Exp $*/#include "NetTapERF.h"#include "metadata.h"#include "Timeval.h"// fixed header lengthsconst int ETHER_HLEN = 14;const int UDP_HLEN = 8;const int ICMP_HLEN = 4;const int ICMP6_HLEN = 4;const int IP6_HLEN = 40;/* IPv6 extension header types */const uint8_t IP6HDR_HOP   =  0;const uint8_t IP6HDR_ROUTE = 43;const uint8_t IP6HDR_FRAG  = 44;const uint8_t IP6HDR_DEST  = 60;const uint8_t IP6HDR_AH    = 51;const uint8_t IP6HDR_ESP   = 50;/* dag stuff taken from dagbpf.c */# define MIN(A,B) (((A)<(B)) ? (A) : (B))const int edag = 4; /* EtherDAG compatibility       */typedef struct cell {        long long       ts;        unsigned        crc;        unsigned        header;        unsigned char   pload[48];} cell_t;typedef struct ether {        long long       ts;        u_short         len;        u_char          dst[6];        u_char          src[6];        u_short         etype;        unsigned        pload[40/sizeof(unsigned)];} ether_t;typedef struct pos {                    /* PoS comes with the new DAG record format */        long long       ts;        unsigned        slen;           /* snap len in this record, must be 64 for now */        unsigned        wlen;           /* length of the packet on the wire, seems to include FCS */        unsigned char   chdlc;          /* Cisco HDLC header */        unsigned char   unused;         /* padding */        unsigned short  etype;          /* EtherType */        unsigned        pload[11];      /* one more word than ATM and Ether */} pos_t;char usgtxt[256] = "that sux";// DAG is more accurate than our current internal timestamp format based on pcapstruct timeval NetTapERF::ERF2PcapTime(long long ts){  struct timeval tv;# if (BYTE_ORDER ==  BIG_ENDIAN)  ts = ((0xff00000000000000ULL & ts) >> 56) |       ((0x00ff000000000000ULL & ts) >> 40) |       ((0x0000ff0000000000ULL & ts) >> 24) |       ((0x000000ff00000000ULL & ts) >>  8) |       ((0x00000000ff000000ULL & ts) <<  8) |       ((0x0000000000ff0000ULL & ts) << 24) |       ((0x000000000000ff00ULL & ts) << 40) |       ((0x00000000000000ffULL & ts) << 56) ;# endif  tv.tv_sec = (long)(ts >> 32);  tv.tv_usec = ((ts & 0xffffffffLL) * 1000 * 1000) >> 32;  return tv;}/*!\short   construct and initialize a NetTap object */NetTapERF::NetTapERF(string df, int onl, int pro, unsigned int sl, int noblock, int bsize, 		     int legacy)  :  devfile(df), online(onl),  promisc(pro), snap_len(sl), erf_flags(0){    if (devfile.empty()) {      throw Error("empty file name");    }    if (legacy) {      erf_flags |= ERF_FLAG_LEGACY;    }    // no support for online cpaturing yet    if (online) {      throw Error("NetTapERF does not support online capturing yet");      //econtext = erf_create_dag_context(devfile.c_str(), erf_flags);    } else {      econtext = erf_create_file_context((char *)devfile.c_str(), erf_flags);      if (econtext == NULL) {	throw Error("erf_create_context failed: %s", strerror(errno));      }            // get the initial time stamp (the timestamp of the first packet)      char buf[64];      cell_t *cell = (cell_t *)buf;            int rtype = erf_read_record(econtext, buf, sizeof(buf), 1);      struct timeval start = ERF2PcapTime(cell->ts);      Timeval::settimeofday(&start);      // get the link type      switch (rtype) {      case TYPE_ATM:	s_linkType = DLT_ATM_RFC1483;	break;      case TYPE_ETH:	s_linkType = DLT_EN10MB;	break;      case TYPE_HDLC_POS:# ifdef DLT_CHDLC	s_linkType = DLT_CHDLC;# else	throw Error("for PoS support need a more recent libpcap from www.tcpdump.org");# endif	break;      default:	 throw Error("unknown erf capture type");      }      // reopen the dump file      erf_destroy_context(econtext);      econtext = erf_create_file_context((char *)devfile.c_str(), erf_flags);    }    // this function does not work properly    //s_linkType = erf_get_linktype(econtext);    // 2 lines -> support old g++    auto_ptr<NetTapStats> _stats(new NetTapERFStats());    stats = _stats;    cout << "Listening on: " << devfile << endl;}/*!\short   destroy a NetTap object */NetTapERF::~NetTapERF(){    erf_destroy_context(econtext);}// FIXME make this code extensible to different mac, network and transport layersvoid NetTapERF::procPacket(char *buf, unsigned long len, const struct pcap_pkthdr *pkthdr,                             const u_char *pktdata){    unsigned short offs = 0;    int net_type = 0;    int proto = 0;    int ret = 0;    // the current packet    metaData_t *pkt = (metaData_t *) buf;    // update the global last packet timestamp    if (!online) {      ret = Timeval::settimeofday(&pkthdr->ts);#ifdef NO_REORDERING      if (ret < 0) {        pkt->len = 0;        return;      }#endif    }        pkt->tv_sec = pkthdr->ts.tv_sec;    pkt->tv_usec = pkthdr->ts.tv_usec;    pkt->len = pkthdr->len;    pkt->cap_len = pkthdr->caplen;    pkt->reverse = 0;    if (len < (sizeof(metaData_t) + pkt->cap_len)) {        throw Error("buffer too small for captured packet");    }    memcpy(pkt->payload, pktdata, pkt->cap_len);    pkt->offs[L_LINK] = 0;    pkt->offs[L_NET] = -1;    pkt->offs[L_TRANS] = -1;    pkt->offs[L_DATA] = -1;        // only support Ethernet and raw IP for now    switch (s_linkType) {    case DLT_EN10MB:        offs += ETHER_HLEN;        pkt->layers[L_LINK] = L_ETHERNET;        // get the type of the next layer        net_type = ntohs(*((unsigned short *) &pkt->payload[pkt->offs[L_LINK] + 12]));	// use second type/length value in case of VLAN	if (net_type == 0x8100) {	    unsigned short tci = ntohs(*((unsigned short *) &pkt->payload[pkt->offs[L_LINK] + 14]));	    if ((tci & 0x1000) != 0) {		cerr << "found unsupported ethertype: VLAN with options (CFI=1)" << endl; 	    }	    // for VLAN with no options link level header is four bytes longer 	    net_type = ntohs(*((unsigned short *) &pkt->payload[pkt->offs[L_LINK] + (12+4)]));	    offs += 4;	}        break;    case DLT_RAW: // in case we have do not have link level header	pkt->layers[L_LINK] = L_UNKNOWN;        // get the type of this layer from the IP version	if ((pkt->payload[0] & 0xf0) == (6<<4)) {	    net_type = 0x86DD; // IPv6	} else if ((pkt->payload[0] & 0xf0) == (4<<4)) {	    net_type = 0x0800; // IPv4	} else {	    net_type = 0; // neither v4 nor v6, should not happen for raw IP link type 	}        break;    case DLT_ATM_RFC1483:        pkt->layers[L_LINK] = L_ATM_RFC1483;	net_type = ntohs(*((unsigned short *) &pkt->payload[pkt->offs[L_LINK] + 6]));	offs += 8;        break;    default:        offs = 0;        pkt->layers[L_LINK] = L_UNKNOWN;        return;     }    if (offs<pkt->cap_len) {        pkt->offs[L_NET] = offs;    } else {        return;    }        // only support IP for now    switch (net_type) {    case 0x0800:        // IPv4        offs += ((pkt->payload[pkt->offs[L_NET]] & 0x0F) << 2);        proto = pkt->payload[pkt->offs[L_NET] + 9];        pkt->layers[L_NET] = N_IP;        break;    case 0x86DD:        // IPv6        offs += IP6_HLEN;        proto = pkt->payload[pkt->offs[L_NET] + 6];        // IPv6 skip options        // FIXME currenty ESP is not supported        while ((proto == IP6HDR_HOP) || (proto == IP6HDR_ROUTE) || (proto == IP6HDR_FRAG) ||              (proto == IP6HDR_AH) || (proto == IP6HDR_DEST)) {            if (proto != IP6HDR_AH) {                offs += pkt->payload[pkt->offs[L_NET] + offs + 1] * 8 + 8;            } else {                offs += pkt->payload[pkt->offs[L_NET] + offs + 1] * 4 + 8;            }            proto = pkt->payload[pkt->offs[1] + offs];        }        pkt->layers[L_NET] = N_IP6;        break;    default:        offs = 0;        pkt->layers[L_NET] = N_UNKNOWN;        return;    }              if (offs < pkt->cap_len) {        pkt->offs[L_TRANS] = offs;    } else {        return;    }    // only support ICMP, UDP and TCP for now    switch (proto) {    case IPPROTO_ICMP:        offs += ICMP_HLEN;        pkt->layers[L_TRANS] = T_ICMP;        break;    case IPPROTO_ICMPV6:        offs += ICMP6_HLEN;        pkt->layers[L_TRANS] = T_ICMP6;        break;    case IPPROTO_UDP:        offs += UDP_HLEN;        pkt->layers[L_TRANS] = T_UDP;        break;    case IPPROTO_TCP:        offs += (pkt->payload[pkt->offs[L_TRANS]+12] & 0xF0) >> 2;        pkt->layers[L_TRANS] = T_TCP;        break;    default:        offs = 0;        pkt->layers[L_TRANS] = T_UNKNOWN;        return;    }    if (offs<pkt->cap_len) {        pkt->offs[L_DATA] = offs;    }}metaData_t *NetTapERF::getPacket(char *buf, unsigned long len){    char    cbuf[64];    cell_t  *cell = (cell_t *)cbuf;    ether_t *ep = (ether_t *)cbuf;    unsigned char   *lp = (unsigned char *)&ep->len;    pos_t   *pp = (pos_t *)cbuf;    int     rtype = 0;    struct pcap_pkthdr pkthdr;    unsigned char *data;           if ((rtype = erf_read_record(econtext, cbuf, sizeof(cbuf), 1)) < 0) {      return NULL;    } else {      // is a bit ugly but we first convert it to pcap and then      // feed it into the same functions as in NetTapPcap      // advantage: can use the same function for the real parsing      // get timestamp      pkthdr.ts = ERF2PcapTime(cell->ts);      switch(rtype) {      case TYPE_ATM:	pkthdr.caplen = 48;	pkthdr.len = ntohs(*(unsigned short *)&cell->pload[8+2])+8;	//pkthdr.len=48;	data = cell->pload;	break;      case TYPE_ETH:        int _len;	/* length field is little endian */	_len = ((unsigned)lp[1] << 8) + lp[0] - edag;	/* EtherDAGs count FCS as well */	pkthdr.caplen = MIN(_len,54);	pkthdr.len = _len;	data = ep->dst;	break;      case TYPE_HDLC_POS:# ifdef DLT_CHDLC	pkthdr.caplen = ntohl(pp->slen) - 16;   /* subtract dag header */	pkthdr.len = ntohl(pp->wlen) - edag;    /* PoS DAGs have the same problem */	data = &pp->chdlc;# else	throw Error("for PoS support need a more recent libpcap from www.tcpdump.org");# endif	break;      default:	throw Error("unknown erf capture type");      }            procPacket(buf, len, &pkthdr, data);      metaData_t *pkt = (metaData_t *) buf;      if (pkt->len == 0) {        return NULL;      }            stats->packets++;      stats->bytes += pkt->cap_len;            return pkt;    }}void NetTapERF::dump( ostream &os ){      os << "NetTapERF dump: " << endl;  os << *stats;}//!overload for <<, so that a network tap object can be thrown into an ostreamostream& operator<< ( ostream &os, NetTapERF &nt ){    nt.dump(os);    return os;}        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -