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

#define MAX_PACKET_SIZE 65536

void packet_handler(u_char *user_data, const struct pcap_pkthdr *pkthdr, const u_char *packet) {
    struct ip *iph;
    struct udphdr *udph;

    // 解析IP头部
    iph = (struct ip *)(packet + 14); // 偏移以跳过以太网头部

    // 确保是UDP数据包
    if (iph->ip_p == IPPROTO_UDP) {
        // 解析UDP头部
        udph = (struct udphdr *)(packet + 14 + iph->ip_hl * 4); // 偏移以跳过以太网和IP头部

        // 获取UDP数据部分
        char *data = (char *)(packet + 14 + iph->ip_hl * 4 + sizeof(struct udphdr));
        // 获取UDP数据部分的长度，用作sendto的终止
        int data_len = ntohs(udph->len) - sizeof(struct udphdr);

        // 转发UDP数据包
        // 创建发送套接字
        int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd < 0) {
            perror("socket creation failed");
            exit(EXIT_FAILURE);
        }

        // 设置目标地址
        struct sockaddr_in dest_addr;
        memset(&dest_addr, 0, sizeof(dest_addr));
        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = udph->dest;
        dest_addr.sin_addr.s_addr = iph->ip_dst.s_addr;

        // 发送数据
        if (sendto(sockfd, data, data_len, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0) {
            perror("sendto failed");
            exit(EXIT_FAILURE);
        }

        close(sockfd); 
    }
}

int main(int argc, char** argv) {
    pcap_t *handle;
    char errbuf[PCAP_ERRBUF_SIZE];
    struct pcap_pkthdr header;
    const u_char *packet;

    if (argc != 3) {
      printf("you should input args as <pcap file> <num of sleep second>");
      return EXIT_FAILURE;
    }

    // 打开PCAP文件
    // handle = pcap_open_offline(trim(argv[2]), errbuf);
    handle = pcap_open_offline(argv[1], errbuf);
    if (handle == NULL) {
        fprintf(stderr, "Couldn't open pcap file: %s\n", errbuf);
        return EXIT_FAILURE;
    }

    // 读取和处理每个数据包
    while ((packet = pcap_next(handle, &header)) != NULL) {
        packet_handler(NULL, &header, packet);
        sleep(atoi(argv[2])); // 睡眠秒数
    }

    // 关闭PCAP句柄
    pcap_close(handle);

    return EXIT_SUCCESS;
}
