gpt4 book ai didi

c++ - 使用 TPACKET_V2 时,Vlan id 设置为 0

转载 作者:太空狗 更新时间:2023-10-29 12:34:54 25 4
gpt4 key购买 nike

我对这个 TPACKET_V2 的使用有疑问。

我的问题是,在套接字上设置了这种类型的数据包后,当我尝试接收一些数据包时,我无法从数据包中读取 vlan id(当然是从数据包的 header 中读取),vlan_tci 永远为 0 .

现在我正在使用 open suse sp1,当我在 sless sp2 上运行我的程序时,我能够使用在 sless sp1 上不起作用的相同程序获得 vlan id,但是奇怪的是 tcpdump 能够获取 vlan id(在这个 sless 上)并且 tcpdump 设置了 TPACKET_V2(所以这意味着支持 TPACKET_2)

我的简单项目基于这些函数,全部由函数 createSocket 调用,然后有一个简单的方法读取套接字上的数据包,我尝试获取有关 vlan id 的信息(还有之前使用TPACKET_V1的相关部分)

#include <linux/if_packet.h>
#include <linux/if_ether.h>

#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/ether.h>

#include <linux/filter.h>
#include <net/if.h>
#include <arpa/inet.h>

enum INTERFACE_T
{
RX_INTERFACE,
TX_INTERFACE
};

static const char* PKT_TYPE[];

// BLOCK_NUM*BLOCK_SIZE = FRAME_NUM*FRAME_SIZE
enum { RX_BLOCK_SIZE = 8192,
RX_BLOCK_NUM = 256,
RX_FRAME_SIZE = 2048,
RX_FRAME_NUM = 1024
};

enum { TX_BLOCK_SIZE = 8192,
TX_BLOCK_NUM = 256,
TX_FRAME_SIZE = 2048,
TX_FRAME_NUM = 1024
};

struct RxFrame {
struct tpacket2_hdr tp_h; // Packet header
uint8_t tp_pad[TPACKET_ALIGN(sizeof(tpacket2_hdr))-sizeof(tpacket2_hdr)];
struct sockaddr_ll sa_ll; // Link level address information
uint8_t sa_ll_pad[14]; //Alignment padding
struct ethhdr eth_h;
} __attribute__((packed));

struct TxFrame
{
struct tpacket_hdr tp_h; // Packet header
uint8_t tp_pad[TPACKET_ALIGN(sizeof(tpacket_hdr))-sizeof(tpacket_hdr)];
// struct vlan_ethhdr vlan_eth_h;
// struct arp arp;
} __attribute__((packed));


struct ring_buff {
struct tpacket_req req;
size_t size; // mmap size
size_t cur_frame;
struct iovec *ring_buffer_;
void *buffer; // mmap
};



int setIfFlags(short int flags)
{
struct ifreq ifr;

memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, if_name_.c_str(), sizeof(ifr.ifr_name));

ifr.ifr_hwaddr.sa_family=getIfArptype();

ifr.ifr_flags |= flags;
if ( ioctl(socket_, SIOCSIFFLAGS, &ifr) == -1)
{
std::cout << "Error: ioctl(SIOSIFFLAGS) failed!" << std::endl;
return 1;
}
return 0;
}


int bindSocket()
{
struct sockaddr_ll sll;

memset(&sll, 0, sizeof(sll));

sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(ETH_P_ALL);
sll.sll_ifindex = ifIndex_;
sll.sll_hatype = 0;
sll.sll_pkttype = 0;
sll.sll_halen = 0;

if (bind(socket_, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
std::cout << "Error: bind() failed!" << std::endl;
return 1;
}
return 0;
}


int packetMmap(ring_buff * rb)
{
assert(rb);

rb->buffer = mmap(0, rb->size, PROT_READ | PROT_WRITE, MAP_SHARED, socket_, 0);
if (rb->buffer == MAP_FAILED) {
std::cout << "Error: mmap() failed!" << std::endl;
return 1;
}
return 0;
}



void packetMunmap(ring_buff * rb)
{
assert(rb);

if (rb->buffer)
{
munmap(rb->buffer, rb->size);
rb->buffer = NULL;
rb->size = 0;
}
}



int frameBufferCreate(ring_buff * rb)
{
assert(rb);

rb->ring_buffer_ = (struct iovec*) malloc(rb->req.tp_frame_nr * sizeof(*rb->ring_buffer_));
if (!rb->ring_buffer_) {
std::cout << "No memory available !!!" << std::endl;
return 1;
}

memset(rb->ring_buffer_, 0, rb->req.tp_frame_nr * sizeof(*rb->ring_buffer_));

for (unsigned int i = 0; i < rb->req.tp_frame_nr; i++) {
rb->ring_buffer_[i].iov_base = static_cast<void *>(static_cast<char *>(rb->buffer)+(i*rb->req.tp_frame_size));
rb->ring_buffer_[i].iov_len = rb->req.tp_frame_size;
}

return 0;
}


void setRingBuffer(struct ring_buff *ringbuf) { rb_ = ringbuf; }


int setVlanTaggingStripping()
{
socklen_t len;
int val;
unsigned int sk_type, tp_reserve, maclen, tp_hdrlen, netoff, macoff;
unsigned int tp_hdr_len;
unsigned int frame_size = RX_FRAME_SIZE;


val = TPACKET_V2;
len = sizeof(val);
if (getsockopt(socket_, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
std::cout << "Error: getsockopt(SOL_PACKET, PACKET_HDRLEN) failed (can't get TPACKET_V2 header len on packet)" << std::endl;
return 1;

}
tp_hdr_len = val;
std::cout << "TPACKET_V2 header is supported (hdr len is " << val << ")"<< std::endl;
std::cout << "tpacket2_hdrs header is supported (hdr len is " << sizeof(tpacket2_hdr) << ")"<< std::endl;

val = TPACKET_V2;
if (setsockopt(socket_, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)) < 0) {
std::cout << "Error: setsockopt(SOL_PACKET, PACKET_VERSION) failed (can't activate TPACKET_V2 on packet)" << std::endl;
return 1;
}
std::cout << "TPACKET_V2 version is configured !!! " << std::endl;

/* Reserve space for VLAN tag reconstruction */
val = VLAN_TAG_LEN;
if (setsockopt(socket_, SOL_PACKET, PACKET_RESERVE, &val, sizeof(val)) < 0) {
std::cout << "Error: setsockopt(SOL_PACKET, PACKET_RESERVE) failed (can't set up reserve on packet)" << std::endl;
return 1;
}
std::cout<< "Reserve space for VLAN tag reconstruction is configured !!! " << std::endl;

return 0;
}


int setSoBufforce(int optname, int buffSize)
{
if (setsockopt(socket_, SOL_SOCKET, SO_SNDBUFFORCE, &buffSize, sizeof(buffSize)) == -1)
{
std::cout << "Error: setsocketopt("<< (optname == SO_SNDBUFFORCE ? "SO_SNDBUFFORCE" : "SO_RCVBUFFORCE") << ") failed!" << std::endl;
return 1;
}
return 0;
}

createSocket(std::string ifName, INTERFACE_T ifType)
{
if (ifName.empty())
{
std::cout << "Error: interface is empty!" << std::endl;;
return NULL;
}

//Create the socket
if ( (socket_ = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1 )
{
std::cout << "Error: calling socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) failed!" << std::endl;
}

std::cout << "Creating Socket on interface= " << ifName << " to listen to ETH_P_ALL"<<std::endl;;


s->setIfFlags(IFF_PROMISC|IFF_BROADCAST);

//allocate space for ring buffer
ring_buff *rb = (ring_buff *) malloc(sizeof(ring_buff));

// use the same size for RX/TX ring

//set the version , here I insert the use of TPACKET_V2!
setVlanTaggingStripping();

rb->req.tp_block_size = RX_BLOCK_SIZE;
rb->req.tp_block_nr = RX_BLOCK_NUM;
rb->req.tp_frame_size = RX_FRAME_SIZE;
rb->req.tp_frame_nr = RX_FRAME_NUM;

setPacketRing(PACKET_RX_RING,&rb->req);

rb->size = (rb->req.tp_block_size)*(rb->req.tp_block_nr);
rb->cur_frame = 0;

// Tweak send/rcv buffer size
int sndBufSz = 4194304; // Send buffer in bytes
int rcvBufSz = 4194304; // Receive buffer in bytes

if (setSoBufforce(SO_SNDBUFFORCE, sndBufSz))
{
//close socket
}

if (setSoBufforce(SO_RCVBUFFORCE, rcvBufSz))
{
//close socket
}

// Add ARP filter so we will only receive ARP packet on this socket
struct sock_filter BPF_code[6];
struct sock_fprog filter;

bindSocket();

if (packetMmap(rb))
{
std::cout << "Error: mmap() failed!" << std::endl;
//close socket
}

frameBufferCreate(rb);
setRingBuffer(rb);
}

在我接收数据包的函数中,我尝试从中读取信息,尤其是 h_vlan_TCI,但我收到过 0x00!有什么建议吗?

struct vlan_ethhdr* vlan_eth_h = (struct vlan_ethhdr*)&frame->eth_h


void readRawSocket(socket_)
{

while (*(unsigned long*)rb->ring_buffer_[rb->cur_frame].iov_base)
{
RxFrame* frame = (RxFrame *)rb->ring_buffer_[rb->cur_frame].iov_base;
#if 0
tpacket_hdr* h = &frame->tp_h;
char buffer[256];
sprintf (buffer, " -tpacket(v1): status=%ld,len=%d,snaplen=%d,mac=%d,net=%d,sec=%d,usec=%d",
h->tp_status, h->tp_len, h->tp_snaplen, h->tp_mac,h->tp_net, h->tp_sec, h->tp_usec);
std::cout << std::string(buffer) << std::endl;
#else
tpacket2_hdr* h = &frame->tp_h;
char buffer[512];
sprintf (buffer, " -tpacket(v2): status=%d,len=%d,snaplen=%d,mac=%d,net=%d,sec=%d,nsec=%d,vlan_tci=%d (vlan_tci=0x%04x)",
h->tp_status, h->tp_len, h->tp_snaplen, h->tp_mac, h->tp_net, h->tp_sec, h->tp_nsec, h->tp_vlan_tci, ntohs(h->tp_vlan_tci));
std::cout << std::string(buffer) << std::endl;
#endif

if ( ETH_P_8021Q == ntohs(frame->eth_h.h_proto) )
{
struct vlan_ethhdr* vlan_eth_h = (struct vlan_ethhdr*)&frame->eth_h;
int vlan_tag = VLAN_TAG(ntohs(vlan_eth_h->h_vlan_TCI));
std::cout << " -Vlan " << vlan_tag << " packet to this host received";

}

rb->cur_frame = ( rb->cur_frame+1) % rx_socket_->getFrameNum();
} // while()

}

最佳答案

当内核删除 vlan 时,它还会将 eth_h.h_proto 更改为 de vlan 标记后的协议(protocol),因此 ETH_P_8021Q == ntohs(frame->eth_h.h_proto) 将很可能是假的。

此外,如果您在标记接口(interface)(即 eth0.100)而不是物理接口(interface) (eth0) 中收听,您将看不到标签。

关于c++ - 使用 TPACKET_V2 时,Vlan id 设置为 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14288582/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com