从pcap文件中读数据并组播

本文介绍如何从pcap文件中提取数据,并详细阐述了如何利用这些数据进行UDP组播操作,参考了https://www.tenouk.com/Module41c.html的相关教程。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#define UDP_DEST_PORT 30000
#define UDP_LOCAL_PORT 30000
#define MAX_LINE 1024
//#define SEND_NUM            10
unsigned match_udp(FILE*, int, unsigned char*, long*);
int      dataSend(unsigned char*, long, const char*, int);

const char* ipDst = "239.100.0.100";
typedef struct pcap_pkt_header_t
{
    // struct   time_val   ts;           /* time stamp */
    int          wSecond;       /* seconds ????? time_t ?????? */
    int          wMicroseconds; /* and microseconds */
    unsigned int uwcaplen;      /* length of portion present */
    unsigned int uwlen;         /* length this packet (off wire) */
} __attribute__((packed)) pcap_pkt_header_t;
// MAC_HEAD_STRUCT
typedef struct mac_header_t
{
    unsigned char  ucaDstMAC[6]; //
    unsigned char  ucaSrcMAC[6]; //
    unsigned short usFrameType;  //
} __attribute__((packed)) mac_header_t;

// IP_PACKET_HEAD
typedef struct ip_header_t
{
    unsigned char  ucVer_HLen;     //
    unsigned char  ucTOS;          //
    unsigned short usTotalLen;     //
    unsigned short usID;           //
    unsigned short usFlag_Segment; //
    unsigned char  ucTTL;          //
    unsigned char  ucProtocol;     //
    unsigned short usChecksum;     //
    unsigned int   uwSrcIP;        //
    unsigned int   uwDstIP;        //
} __attribute__((packed)) ip_header_t;

// UDP HEADER
typedef struct udp_header_t
{                              // UDP
    unsigned short usSrcPort;  //
    unsigned short usDstPort;  //
    unsigned short usDataLen;  //
    unsigned short usChecksum; //
} __attribute__((packed)) udp_header_t;

int main(int argc, char* argv[])
{
    struct in_addr     localInterface;
    struct sockaddr_in groupSock;
    int                sd;

    /* Create a datagram socket on which to send. */
    sd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sd < 0)
    {
        perror("Opening datagram socket error");
        exit(1);
    }
    else
        printf("Opening the datagram socket...OK.\n");

    /* Initialize the group sockaddr structure with a */
    /* group address of 225.1.1.1 and port 5555. */
    memset((char*)&groupSock, 0, sizeof(groupSock));
    groupSock.sin_family = AF_INET;
    groupSock.sin_addr.s_addr = inet_addr(ipDst );
    groupSock.sin_port = htons(UDP_DEST_PORT );

    /* Set local interface for outbound multicast datagrams. */
    /* The IP address specified must be associated with a local, */
    /* multicast capable interface. */

    localInterface.s_addr = inet_addr("168.192.0.100");
    if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, (char*)&localInterface,
                   sizeof(localInterface)) < 0)
    {
        perror("Setting local interface error");
        exit(1);
    }
    else
        printf("Setting the local interface...OK\n");

    FILE*          fpInput;
    long           dwPcapFileOffset = 0;
    long           dwPcapFileNextOffset = 0;
    long           dwPcapFileLength = 0;
    unsigned short usUDPDataLen = 0;
    int            rnd = 0;
    unsigned char  ucaUdpStream[2048];
    // int             ret = 0;
    // initialization
    memset(ucaUdpStream, 0, sizeof(ucaUdpStream));
    if ((fpInput = fopen(argv[1], "rb")) == NULL)
    {
        printf("error: can not open input pcap file\n");
        exit(0);
    }
    printf("open input pcap file:%s\n", argv[1]);

    // begin to read the pcap
    fseek(fpInput, 0, SEEK_END); // get the pcap file total length
    dwPcapFileLength = ftell(fpInput);
    if (dwPcapFileLength <= 24)
    {
        printf("\n pcap file's length abnormal\n");
        exit(0);
    };

    fseek(fpInput, 0, SEEK_SET);
    dwPcapFileOffset = 24;
    while (dwPcapFileOffset < dwPcapFileLength) // seek through the whole pcap file
    {
        fseek(fpInput, dwPcapFileOffset, SEEK_SET);
        rnd++;
        usUDPDataLen = match_udp(fpInput, rnd, ucaUdpStream, &dwPcapFileNextOffset);
        dwPcapFileOffset = dwPcapFileNextOffset;
        if (usUDPDataLen == 1)
        {
            // rnd++;
            continue;
        }
        else if (usUDPDataLen == 0)
        {
            printf("%d,an empty UDP packet\n", rnd);
            break;
        }
        else if (usUDPDataLen < 20)
        {
            printf("%d,UDP payload length is less than minimum packet's desire\n", rnd);
            break;
        }
        else
        {
            // match_level_two(ucaUdpStream,usUDPDataLen,rnd);
            printf("%d,get an UDP packet\n", rnd);
            // ret = dataSend(ucaUdpStream,usUDPDataLen,ipDst, UDP_DEST_PORT);
            printf("begin to send data,data length is %d\n", usUDPDataLen);
            /* send the string to server*/
            if (sendto(sd, ucaUdpStream, usUDPDataLen, 0, (struct sockaddr*)&groupSock,
                       sizeof(groupSock)) < 0)
            {
                printf("sendto error\n");
            }
            printf("send data succeed!!\n");
            rnd++;
        }
        // sleep(1);
        usleep(500 * 1000);

        // if( rnd >= SEND_NUM ) break;

    } // end while
    printf("%d,all UDP packet are sent successfully!!\n", rnd);
    close(sd);
    fclose(fpInput);
    // fclose(fpOutput);
    return 0;
}

// SEEK UDP
/***********************************************************************************\
    Function Description:return a complete UDP packet's payload
    Input Parameter Description:
        fpInput:the input pcap file
        rnd:the index of a pcap packet
        ucaUdpStream:the output of the current UDP's payload
        dwPcapFileNextOffset:the offset of the next pcap packet in the whole pcap file

\***********************************************************************************/
unsigned match_udp(FILE* fpInput, int rnd, unsigned char* ucaUdpStream, long* dwPcapFileNextOffset)
{
    long           dwPcapFileOffset = 0;
    unsigned char  ucIPVersion;
    unsigned char  ucIPHeadLen;
    char           src_ip[20];
    char           dst_ip[20];
    unsigned char  ip_protocal;
    unsigned char  ucIPHeadSkipLen;
    unsigned short src_port = 0;
    unsigned short dst_port = 0;
    unsigned short usUDPDataLen = 0;

    pcap_pkt_header_t* strupPcapPktHeader;
    mac_header_t*      strupMacHeader;
    ip_header_t*       strupIPHeader;
    udp_header_t*      strupUDPHeader;

    strupPcapPktHeader = (pcap_pkt_header_t*)malloc(sizeof(pcap_pkt_header_t));
    strupMacHeader = (mac_header_t*)malloc(sizeof(mac_header_t));
    strupIPHeader = (ip_header_t*)malloc(sizeof(ip_header_t));
    strupUDPHeader = (udp_header_t*)malloc(sizeof(udp_header_t));
    memset(src_ip, 0, sizeof(src_ip)); // init
    memset(dst_ip, 0, sizeof(dst_ip)); // init

    dwPcapFileOffset = ftell(fpInput);
    if (fread(strupPcapPktHeader, 16, 1, fpInput) != 1)
    {
        printf("\n pcap file head get to an end\n");
        exit(0);
    }

    *dwPcapFileNextOffset =
        dwPcapFileOffset +
        (sizeof(pcap_pkt_header_t) + strupPcapPktHeader->uwcaplen); // The next one's offset

    // MAC HEAD
    if (fread(strupMacHeader, sizeof(mac_header_t), 1, fpInput) != 1)
    {
        printf("%d: can not read mac_header\n", rnd);
        exit(0);
    }

    if (strupMacHeader->usFrameType != 0x0008) // MAC IPV4 0800
    {
        printf("%d: this is not a IPV4 packet!\n", rnd);
        printf("%d: the current IPV4 ID is %04x!\n", rnd, ntohs(strupMacHeader->usFrameType));
        return 1;
    }
    // IP_PACKET_HEAD basic 20 bytes
    if (fread(strupIPHeader, sizeof(ip_header_t), 1, fpInput) != 1)
    {
        printf("%d: can not read ip_header\n", rnd);
        exit(0);
    }
    // printf("%d: IPV4 packet head size is %d\n", sizeof(ip_header_t));
    ucIPVersion = (strupIPHeader->ucVer_HLen) >> 4;
    ucIPHeadLen = (strupIPHeader->ucVer_HLen) & 0x0F;

    if (ucIPVersion != 0x04) // check IPV4
    {
        printf("%d: This is not a IPV4 packet\n", rnd);
        printf("%d: version and len is %x\n", rnd, strupIPHeader->ucVer_HLen);
        return 1;
    }

    inet_ntop(AF_INET, (void*)&(strupIPHeader->uwSrcIP), src_ip, 16);
    inet_ntop(AF_INET, (void*)&(strupIPHeader->uwDstIP), dst_ip, 16);
    //
    // if((strcmp(src_ip,src_ip_dsr0)!=0)&&
    //   (strcmp(src_ip,src_ip_dsr1)!=0)&&
    //   (strcmp(src_ip,src_ip_dsr2)!=0)&&
    //   (strcmp(src_ip,src_ip_dsr3)!=0)) //source IP address check
    //{
    //    printf("%d,source IP address is not match\n",rnd);
    //    return 1;
    //}

    if (strupIPHeader->ucProtocol != 0x11) // UDP or not
    {
        printf("%d,This is not a UDP packet\n", rnd);
        return 1;
    }
    // skip the remaining IPv4 head
    ucIPHeadSkipLen = (ucIPHeadLen - 0x5) << 2;
    if (ucIPHeadSkipLen != 0)
    {
        fseek(fpInput, ucIPHeadSkipLen, SEEK_CUR); // skip the MAC FRAME HEAD;
    }
    // UDP PKT HEAD == 8 BYTES
    if (fread(strupUDPHeader, sizeof(udp_header_t), 1, fpInput) != 1)
    {
        printf("%d: can not read udp_header\n", rnd);
        exit(0);
    }
    // printf("%d: current position is %d\n", rnd,ftell(fpInput));
    src_port = ntohs(strupUDPHeader->usSrcPort);
    dst_port = ntohs(strupUDPHeader->usDstPort);
    usUDPDataLen = ntohs(strupUDPHeader->usDataLen) - 8;
    // if(((src_port != 23111)||(dst_port != 23110))&&
    //   ((src_port != 22111)||(dst_port != 22110))&&
    //   ((src_port != 21111)||(dst_port != 21110))&&
    //   ((src_port != 20111)||(dst_port != 20110)))
    //{
    //    printf("%d: source or destination port is not match\n", rnd);
    //    return 1;
    //}

    if (fread(ucaUdpStream, usUDPDataLen, 1, fpInput) != 1)
    {
        printf("%d: can not read udp_payload\n", rnd);
        exit(0);
    }
    else
    {
        printf("%d: read udp_payload succeed\n", rnd);
    }

    fseek(fpInput, dwPcapFileOffset, SEEK_SET); // recover the file pointer to the initial place
    return usUDPDataLen;
}

Ref:
https://www.tenouk.com/Module41c.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值