其他分享
首页 > 其他分享> > dpdk发送RST报文(一)—— 构建RST包

dpdk发送RST报文(一)—— 构建RST包

作者:互联网

suricata中阻断报文函数“RejectSendLibnet11IPv4TCP”使用libnet11构造阻断报文。今天试一下自己手动构建RST报文,然后通过dpdk发送出去。

dpdk-response-reject.h

#ifndef __DPDK_RESPONSE_REJECT_H__
#define __DPDK_RESPONSE_REJECT_H__

#include "rte_mbuf.h"

enum RejectDirection {
    REJECT_DIR_SRC = 0,
    REJECT_DIR_DST = 1,
};

rte_mbuf * DpdkRejectBuildIpv4TCP(rte_mbuf *originalMbuf, enum RejectDirection dir);

#endif

dpdk-response-reject.c

#include "dpdk-response-reject.h"

// 构造tcp头
static int BuildTCP(struct rte_ipv4_hdr *ip, struct rte_tcp_hdr *tcp, uint16_t payloadLen enum RejectDirection dir)
{
    uint16_t tmpPort;
    uint32_t uTmpSeq;
    // 更改tcp头
    switch (dir)
    {
        case REJECT_DIR_SRC:
            tmpPort = tcp->src_port;
            tcp->src_port = tcp->dst_port;
            tcp->dst_port = tmpPort;
            uTmpSeq = ntohl(tcp->sent_seq);
            if(0 == (tcp->tcp_flags & TH_ACK))
            {
                tcp->sent_seq = 0;  // 没有ack标致,seq应该为0
                tcp->recv_ack = htonl(uTmpSeq + payloadLen + 1);
            }
            else
            {
                tcp->sent_seq = tcp->recv_ack;
                tcp->recv_ack = htonl(uTmpSeq + payloadLen + 1);
            }
            break;
        case REJECT_DIR_DST:
        default:
            break;
    }
    tcp->tcp_flags = 0x014;  // 置位rst, TH_ACK | TH_RST
    tcp->cksum = 0;
    tcp->cksum = rte_ipv4_udptcp_cksum(ip, (const void *)tcp);
    return 0;
}

// 构造ip头
static int BuildIpv4(struct rte_ipv4_hdr *ip, enum RejectDirection dir)
{
    uint16_t ident;
    uint32_t tmpAddr;
    // 更改ip头
    switch (dir)
    {
        case REJECT_DIR_SRC:
            ident = ntohs(ip->packet_id) + 27; /* 改写ident */
            ip->packet_id       = htons(ident);
            ip->fragment_offset = 0;
            tmpAddr             = ip->src_addr;
            ip->src_addr        = ip->dst_addr;
            ip->dst_addr        = tmpAddr;
            break;
        case REJECT_DIR_DST:
        default:
            break;
    }
    ip->hdr_checksum    = 0;
    ip->hdr_checksum    = rte_ipv4_cksum((const struct rte_ipv4_hdr *)ip);
    return 0;
}

// 构造以太头
static int BuildEther(struct rte_ether_hdr *eth_hdr, enum RejectDirection dir)
{
    struct rte_ether_addr stTmpMac;
    // 更改以太头
    switch (dir)
    {
        case REJECT_DIR_SRC:
            memcpy( &stTmpMac, &ethhdr->s_addr, sizeof(struct rte_ether_addr));
            memcpy( &ethhdr->s_addr, &ethhdr->d_addr, sizeof(struct rte_ether_addr));
            memcpy( &ethhdr->d_addr, &stTmpMac, sizeof(struct rte_ether_addr));
            break;
        case REJECT_DIR_DST:
        default:
            break;
    }
    return 0;
}

// 构造tcp阻断报文
rte_mbuf * DpdkRejectBuildIpv4TCP(rte_mbuf *originalMbuf, enum RejectDirection dir)
{
    // 申请新mbuf用于存储Rst报文内容
    struct rte_mbuf *mbuf = rte_pktmbuf_alloc(originalMbuf->pool);
	/* 从原mbuf拷贝内容到新mbuf */
    memcpy(rte_pktmbuf_mtod(mbuf, void *), rte_pktmbuf_mtod(originalMbuf, void *), originalMbuf->data_len);
    mbuf->packet_type = originalMbuf->packet_type;
    mbuf->pkt_len     = originalMbuf->pkt_len;
    mbuf->data_len    = originalMbuf->data_len;
    mbuf->hash.rss   = originalMbuf->hash.rss;
    
	struct rte_ether_hdr *eth_hdr  = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *); //获取以太头地址
	struct rte_ipv4_hdr  *ipv4_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);           //获取ip头地址
	struct rte_tcp_hdr   *tcp_hdr  = (struct rte_tcp_hdr *)(ipv4_hdr + 1);           //获取tcp头地址
	uint16_t usTcpPayloadLen       = rte_pktmbuf_data_len(mbuf) - sizeof(struct rte_ether_hdr) - sizeof(struct rte_ipv4_hdr) - sizeof(struct rte_tcp_hdr); //计算tcp payload长度,填ack number时用到
	/* 在原始包上更改,组Rst报文 */
    BuildTCP( ipv4_hdr, tcp_hdr, usTcpPayloadLen, dir );
    BuildIpv4( ipv4_hdr, dir );
    BuildEther( eth_hdr, dir );

    return mbuf;
}

标签:rte,hdr,ip,报文,mbuf,struct,tcp,RST,dpdk
来源: https://blog.csdn.net/superbfly/article/details/123125611