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;
}

诸神对凡人心生艳羡,厌倦天堂。
原文地址:https://www.cnblogs.com/dirge/p/14799705.html