zoukankan      html  css  js  c++  java
  • libpcap使用

    reference: https://blog.csdn.net/htttw/article/details/7521053 https://github.com/mozhuli/SDN-Learning-notes/blob/master/SUMMARY.md http://homes.di.unimi.it/~gfp/SiRe/2002-03/progetti/libpcap-tutorial.html

    相关结构体

    struct pcap_pkthdr {
        struct timeval ts;  /* time stamp */
        bpf_u_int32 caplen; /* length of portion present */
        bpf_u_int32 len;    /* length this packet (off wire) */
    };
    
    /* Ethernet header, 14 bytes */
    struct sniff_ethernet {
        u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
        u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
        u_short ether_type; /* IP? ARP? RARP? etc */
    };
    
    /* IP header, 20 bytes*/
    struct sniff_ip {
        #if BYTE_ORDER == LITTLE_ENDIAN
        u_int ip_hl:4, /* header length */
        ip_v:4; /* version */
        #if BYTE_ORDER == BIG_ENDIAN
        u_int ip_v:4, /* version */
        ip_hl:4; /* header length */
        #endif
        #endif /* not _IP_VHL */
        u_char ip_tos; /* type of service */
        u_short ip_len; /* total length */
        u_short ip_id; /* identification */
        u_short ip_off; /* fragment offset field */
        #define IP_RF 0x8000 /* reserved fragment flag */
        #define IP_DF 0x4000 /* dont fragment flag */
        #define IP_MF 0x2000 /* more fragments flag */
        #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
        u_char ip_ttl; /* time to live */
        u_char ip_p; /* protocol */
        u_short ip_sum; /* checksum */
        struct in_addr ip_src,ip_dst; /* source and dest address */
    };
    
    /* TCP header, 20 bytes */
    struct sniff_tcp {
        u_short th_sport; /* source port */
        u_short th_dport; /* destination port */
        tcp_seq th_seq; /* sequence number */
        tcp_seq th_ack; /* acknowledgement number */
        #if BYTE_ORDER == LITTLE_ENDIAN
        u_int th_x2:4, /* (unused) */
        th_off:4; /* data offset */
        #endif
        #if BYTE_ORDER == BIG_ENDIAN
        u_int th_off:4, /* data offset */
        th_x2:4; /* (unused) */
        #endif
        u_char th_flags;
        #define TH_FIN 0x01
        #define TH_SYN 0x02
        #define TH_RST 0x04
        #define TH_PUSH 0x08
        #define TH_ACK 0x10
        #define TH_URG 0x20
        #define TH_ECE 0x40
        #define TH_CWR 0x80
        #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
        u_short th_win; /* window */
        u_short th_sum; /* checksum */
        u_short th_urp; /* urgent pointer */
    };
    
    /* UDP header, 8 bytes */
    struct udphdr
    {
      u_int16_t source;
      u_int16_t dest;
      u_int16_t len;
      u_int16_t check;
    };
    

    code

    #include <iostream>
    #include <string>
    #include <sstream>
    #include <iomanip>
    #include <map>
    
    #include <stdio.h>
    #include <signal.h>
    #include <netinet/ip.h>
    #include <netinet/if_ether.h>
    #include <arpa/inet.h>
    #include <netinet/udp.h>
    #include <string.h>
    
    #include "pcap.h"
    #include "sll.h"
    #include "trtc_aes.h"
    #include "dataHead.h"
    #include "format.h"
    
    using namespace std;
    
    bool gStopFlag = false;
    char gErrBuf[PCAP_ERRBUF_SIZE];
    
    TrtcAES *gTrtcAES;
    string gAESKey = "A1DAE58E5859DE68ADB82B03BDD4168B";
    unsigned gTagLen = 8;
    
    unsigned gTotalFecPacket = 0;
    map<int, int> gErrorCodeMap;
    unsigned gDecodeError = 0;
    
    void SignalHandler(int sigValue)
    {
    	gStopFlag = true;
    
    	cout<<"recieve end flag, exit now!!!"<<endl;
    }
    
    string NetToIpString(unsigned ipNet)
    {
    	stringstream strStream;
    
    	strStream<<int(((unsigned char *)&ipNet)[0])<<".";
    	strStream<<int(((unsigned char *)&ipNet)[1])<<".";
    	strStream<<int(((unsigned char *)&ipNet)[2])<<".";
    	strStream<<int(((unsigned char *)&ipNet)[3]);
    
    	return strStream.str();
    }
    
    /*
     * struct udphdr
    {
      u_int16_t source;
      u_int16_t dest;
      u_int16_t len;
      u_int16_t check;
    };
     */
    
    void HandlePacket(const struct pcap_pkthdr *pktHdr,const unsigned char* pktContent, int linkType)
    {
    	if ( linkType!=DLT_LINUX_SLL && linkType!=DLT_EN10MB ) // 1. Linux抓包封装; 2. 以太网(10Mb, 100Mb, 1000Mb, 或者更高)
    	{
    		cout<<"packet type is not Ethernet, type: "<<linkType<<", Skip now!!!"<<endl;
    		return ;
    	}
    
    	struct ethhdr *ethHdr;
    	struct iphdr *ipHdr;
    	if ( linkType==DLT_EN10MB )
    	{
    		ethHdr = (struct ethhdr*)pktContent;
    		if ( ethHdr->h_proto!=ntohs(ETH_P_IP) )
    		{
    			cout<<"packet is not IP protocol, skip"<<endl;
    			return ;
    		}
    		ipHdr = (struct iphdr *)(pktContent+sizeof(struct ethhdr));
    	}
    	else
    	{
    		struct sll_header *sllHdr = (struct sll_header *)pktContent;
    		if ( sllHdr->sll_protocol!=ntohs(ETH_P_IP) )
    		{
    			cout<<"packet is not IP protocol, skip: "<<setiosflags(ios::hex)<<sllHdr->sll_protocol<<setiosflags(ios::dec)<<endl;
    			return ;
    		}
    		ipHdr = (struct iphdr *)(pktContent+sizeof(struct sll_header));
    	}
    
    	if ( ipHdr->protocol!=0x11 )
    	{
    		cout<<"packet is not UDP protocol, skip"<<endl;
    		return ;
    	}
    	unsigned short ipHdrLen = (ipHdr->ihl)<<2;
    	struct udphdr *udpHdr = (struct udphdr *)((char *)ipHdr+ipHdrLen);
    	unsigned dataLen = ntohs(udpHdr->len)-sizeof(struct udphdr);
    
    	cout<<NetToIpString(ipHdr->saddr)<<":"<<ntohs(udpHdr->source)<<"=>";
    	cout<<NetToIpString(ipHdr->daddr)<<":"<<ntohs(udpHdr->dest);
    	cout<<"  len:"<<dataLen<<endl;
    
    	static char pPackage[4096];
    	static char afterEncrypt[4096];
    	memcpy(pPackage, (char *)udpHdr+sizeof(struct udphdr), dataLen);
    
    	if ( pPackage[0]!=7 && pPackage[dataLen-1]!=8 )
    	{
    		cout<<"packet is not UDTV3, skip" << endl;
    		return;
    	}
    
    	LongConnUdtDataHeadV3 *udtReqV3 = (LongConnUdtDataHeadV3*) (pPackage + 1);
    	unsigned tlvLen = ntohs(udtReqV3->wTLVBufLen);
    	DataContrlPkgHead *dataCtr = (DataContrlPkgHead*) (pPackage + 1 + sizeof (LongConnUdtDataHeadV3) + tlvLen);
    	unsigned short SubCmd = ntohs(udtReqV3->wSubCmd);
    	unsigned SenderSeq = ntohl(udtReqV3->dwSenderSeq);
    
    	unsigned noEncryptLen = 1 + sizeof (LongConnUdtDataHeadV3) + tlvLen + sizeof (DataContrlPkgHead);
    	unsigned toEncryptLen = dataLen - noEncryptLen -1;
    	char *encryptBegin = pPackage + noEncryptLen;
    	memcpy(afterEncrypt, pPackage, noEncryptLen);
    
    	unsigned char iv[32];
    	unsigned int ivLen;
    	int ctLen;
    
    	gTrtcAES->MakeUDTIV(pPackage,dataLen,iv,ivLen);
    	int iRet = gTrtcAES->encrypt((const unsigned char*)gAESKey.c_str(),(const unsigned char*)iv,ivLen,
    	        (const unsigned char*)encryptBegin,(int)toEncryptLen,(unsigned char*)(afterEncrypt + noEncryptLen),ctLen,(unsigned int)gTagLen);
    	if ( iRet!=0 )
    	{
    		cout<<"decode error, ret: "<<iRet<<endl;
    		return ;
    	}
    	unsigned int afterChiperLen = noEncryptLen + ctLen + 1;
    	afterEncrypt[afterChiperLen - 1] = 8;
    
    	if ( SubCmd!=0x3f3 && SubCmd!=0x3f1 )
    	{
    		cout<<"skip not fec packet"<<endl;
    		return ;
    	}
    
    	LongConnUdtDataHeadV3* pUdtHeadV3 = (LongConnUdtDataHeadV3 *)(afterEncrypt + 1);
    	int udtHeadLen = sizeof(LongConnUdtDataHeadV3) + ntohs(pUdtHeadV3->wTLVBufLen);
    	DataContrlPkgHead* pCtrlHead = (DataContrlPkgHead*)(afterEncrypt + 1 + udtHeadLen);
    	int ctrlHeadLen = sizeof(DataContrlPkgHead);
    	int headLen = udtHeadLen + ctrlHeadLen;
    	if(pCtrlHead->cSubType != 1)
    	{
    		cout<<"skip not audio packet"<<endl;
    		return ;
    	}
    
    	gTotalFecPacket++;
    
    	frame_t frm;
    	unsigned char * pucOut = NULL;
    	int payloadLen;
    	int fmtRet = fmt_decode((unsigned char *)(afterEncrypt + 1 + headLen), afterChiperLen - headLen - 2, &frm);  //trae head
    	if ( fmtRet!=0 )
    	{
    		cout<<"fmt_decode error, ret: "<<fmtRet<<endl;
    		gDecodeError++;
    		gErrorCodeMap[fmtRet]++;
    		return ;
    	}
    	gErrorCodeMap[fmtRet]++;
    	printf("seq: %u, sendSeq: %u, ssn: %u
    ", ntohl(pUdtHeadV3->dwSeq), ntohl(pUdtHeadV3->dwSenderSeq), frm.sSN);
    
    	return ;
    }
    
    void PrintHelp(const char *exeName)
    {
    
    	cout<<"Usage: "<<exeName<<" option infile(devname) filter_discribe"<<endl;
    	cout<<"option: r or i"<<endl;
    	cout<<"r: read from pcap file"<<endl;
    	cout<<"i: cap packet from dev"<<endl;
    }
    
    int main(int argc, char *argv[])
    {
    	if ( argc<3 )
    	{
    		PrintHelp(argv[0]);
    		return -1;
    	}
    
    	string optStr = argv[1];
    	if ( optStr!="r" && optStr!="i" )
    	{
    
    		PrintHelp(argv[0]);
    		return -1;
    	}
    
    	string strFilter;
    	for ( int i=3; i<argc; i++ )
    	{
    		strFilter += argv[i];
    		strFilter += " ";
    	}
    
    	signal(SIGINT, SignalHandler);
    	string inFile = argv[2];
    	pcap_t *pFd;
    	if ( optStr=="r" )
    	{
    		pFd = pcap_open_offline(inFile.c_str(), gErrBuf);
    	}
    	else
    	{
    		pFd = pcap_open_live(inFile.c_str(), 80, 0, 1, gErrBuf);
    	}
    
    	if ( pFd==NULL )
    	{
    		cout<<"pcap read "<<inFile<<" error: "<<gErrBuf<<endl;
    		return -1;
    	}
    
    	if ( strFilter.size()!=0 )
    	{
    		struct bpf_program bpfFilter;
    		int retValue = pcap_compile(pFd, &bpfFilter, strFilter.c_str(), 1, 0);
    		if ( retValue!=0 )
    		{
    			cout<<"pcap compile error"<<endl;
    			return -1;
    		}
    
    		retValue = pcap_setfilter(pFd, &bpfFilter);
    		if ( retValue!=0 )
    		{
    			cout<<"pcap setfilter error"<<endl;
    			return -1;
    		}
    	}
    
    	gTrtcAES = new TrtcAES();
    	while ( !gStopFlag )
    	{
    		struct pcap_pkthdr *pktHdr;
    		const unsigned char *pktContent;
    
    		int linkType = pcap_datalink(pFd);
    		int retValue = pcap_next_ex(pFd, &pktHdr, &pktContent);
    		if ( retValue==0 )
    		{
    			continue;
    		}
    
    		if ( retValue<0 )
    		{
    			cout<<"pcap next error, ret="<<retValue<<", error: "<<pcap_geterr(pFd)<<endl;
    			break;
    		}
    
    		HandlePacket(pktHdr, pktContent, linkType);
    	}
    
    	printf("gTotalFecPacket: %u, gDecodeError: %u
    ", gTotalFecPacket, gDecodeError);
    	for ( auto it:gErrorCodeMap )
    	{
    		printf("errcode: %d, number: %d
    ", it.first, it.second);
    	}
    	pcap_close(pFd);
    
    	return 0;
    }
    
    
    诸神对凡人心生艳羡,厌倦天堂。
  • 相关阅读:
    deepinmind(转)
    不知道数据库中表的列类型的前提下,使用JDBC正确的取出数据(转)
    shell 监控局域网的主机是否up(转)
    IntelliJ Idea中一个编译报错引发的
    Unity插件之NGUI学习(8)—— Table和NGUI尺寸转换为世界坐标系尺寸
    使用php-fpm状态页观察当前的php-fpm状态
    PHP连接Access数据库代码
    HDU 4107 线段树
    Effective C++之‘宁以pass-by-reference-to-const替换pass-by-value’
    xdebug的安装和配置方法
  • 原文地址:https://www.cnblogs.com/dirge/p/14799705.html
Copyright © 2011-2022 走看看