将char*转换为struct

Dee*_*ary 3 c c++ sockets

这里的代码中,有一行:

struct iphdr * iph = (struct iphdr *)buffer;
Run Code Online (Sandbox Code Playgroud)

ProcessPacket函数where buffer类型char*.buffer已经recvfrom在主函数中给出了值.如何将简单的string(buffer)转换为结构以及如何安全地提取数据?

iphdr:

struct iphdr {
    #if defined(__LITTLE_ENDIAN_BITFIELD)
        __u8    ihl:4,
                version:4;
    #elif defined (__BIG_ENDIAN_BITFIELD)
        __u8    version:4,
                ihl:4;
    #else
        #error  "Please fix <asm/byteorder.h>"
    #endif
         __u8   tos;
         __u16  tot_len;
         __u16  id;
         __u16  frag_off;
         __u8   ttl;
         __u8   protocol;
         __u16  check;
         __u32  saddr;
         __u32  daddr;
         /*The options start here. */
};
Run Code Online (Sandbox Code Playgroud)

Jon*_*nas 5

buffer不是一个string.它是指向原始二进制数据的指针.使用原始IP/TCP帧(也称为数据包)recvfrom填充(在此示例中,见下文buffer).因此,第一个sizeof(iphdr)字节bufferIP头结构:iphdr.这正是博客作者使用您提供的代码段的原因:

struct iphdr * iph = (struct iphdr *)buffer;
Run Code Online (Sandbox Code Playgroud)

如果包含IP标头选项,则标头的实际大小为iph->ihl*4.

然后在(在博客中)检查报头的协议字段(iph->protocol)ProcessPacket,以确定该分组包含哪个传输协议.

如果使用的传输协议是TCP,则可以使用(来自博客的片段)提取TCP标头(以及稍后的数据):

unsigned short iphdrlen = iph->ihl*4;
struct tcphdr *tcph = (struct tcphdr*)(buffer + iphdrlen);
Run Code Online (Sandbox Code Playgroud)

原始帧

该博客的作者使用以下方法创建了套接字:

sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
Run Code Online (Sandbox Code Playgroud)
  • 第一个参数AF_INET是指你想的IPv4数据包(如反对AF_INET6IPv6的).
  • 第二个参数告诉socket您需要原始帧
  • 第三个参数(IPPROTO_TCP)确保您获得TCP帧

或者,如果您想要UDP帧,您可以使用:

 sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_UDP);
Run Code Online (Sandbox Code Playgroud)

如果您贪婪并希望每个数据包都使用(请在使用之前阅读框架格式!):

socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
Run Code Online (Sandbox Code Playgroud)