libpcap使用

reference:
https://blog.csdn.net/htttw/article/details/7521053
https://github.com/mozhuli/SDN-Learning-notes/blob/master/SUMMARY.md

#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\n", 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\n", gTotalFecPacket, gDecodeError);
	for ( auto it:gErrorCodeMap )
	{
		printf("errcode: %d, number: %d\n", it.first, it.second);
	}
	pcap_close(pFd);

	return 0;
}

上一篇:使用apt install openvswitch-switch之后的ovsdb数据库连接


下一篇:基于Liunx与C语言的网络抓包学习(简单抓包之数据包的长度)