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\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;
}
诸神对凡人心生艳羡,厌倦天堂。