如何在icmp header中复制消息

时间:2014-02-28 08:55:18

标签: linux-kernel network-programming

这是我不太了解的代码。

struct icmphdr *icmp;
icmp = (struct icmphdr *)(sb->data + sb->nh.iph->ihl * 4);

....

char *cp_data = (char *)((char *)icmp + sizeof(struct icmphdr));
memcpy(cp_data, buffer, 4);
dev_queue_xmit(sb);

基本上它的作用是将缓冲区复制到cp_data,它指向icmphdr结构中的某个位置,但cp_data指向哪里?什么是(char *)((char *)icmp + sizeof(struct icmphdr))

2 个答案:

答案 0 :(得分:2)

  

cp_data,指向icmphdr结构中的某个地方

不,它没有,它指向之后的内存

这就是ICMP有效负载所在的位置。看看this image

ICMP structure

ICMP有效负载(消息)在大小为sizeof(struct icmphdr)的标头之后开始,因此它位于icmp + sizeof(struct icmphdr)

因此,

memcpy(cp_data, buffer, 4);buffer中的四个字节复制到ICMP数据包消息。

sb->data + sb->nh.iph->ihl * 4实际上会跳过IP数据包标头并指向ICMP标头(再次查看上面的图像)。 IP标头位于sb->data,ICMP标头位于sb->data + sb->nh.iph->ihl * 4,ICMP消息位于sb->data + sb->nh.iph->ihl * 4 + sizeof(struct icmphdr)

例如,ping(echo request / reply)使用ICMP消息字段向前和向后发送数据。它也可以用于ICMP tunneling

<强>更新

  

如果我想获得数据部分的大小,只需要“size = 1500(MTU) - (sizeof(iphdr)+ sizeof(icmphdr)+ sizeof(ethhdr))。这是正确的吗?

不,完全没有,原因如下:

  1. MTU只是在没有碎片的情况下可以传输的最大数据包大小。 ICMP数据包实际上应该更小。
  2. MTU不包含以太网头,它定义了第3层中的最大数据包长度(IP,而不是以太网!)。
  3. sizeof(iphdr)不正确,因为标头大小可能因IP选项而异。使用iphdr.ihl以32位字获取IP标头的大小。
  4. 正确的方法是确定总IP数据包长度并减去IP报头长度和ICMP报头长度:

    tot_len     = sb->nh.iph->tot_len
    iphdr_len   = sb->nh.iph->ihl * 4
    icmphdr_len = sizeof(icmphdr)
    size        = tot_len - iphdr_len - icmphdr_len
    

    注意:您应始终使用ntohs网络字节顺序转换为主机字节顺序

答案 1 :(得分:0)

  1. 在您粘贴的代码中

    struct icmphdr *icmp; //is a pointer to the beginning of icmp header in a packet.

  2. &安培;通过这条线 -     char *cp_data = (char *)((char *)icmp + sizeof(struct icmphdr));

    你使cp_data指向icmp数据包的有效负载的开头。

    2. ((char *)icmp + sizeof(struct icmphdr)); - icmp被类型化为(char *),因此添加(char *)icmp + sizeof(struct icmphdr)将返回地址(icmpheader起始地址)+ headersize字节。

    这是一个例子 - 假设您有一个整数指针并将其递增1,它指向下一个整数(即它自动前进4个字节),而字符指针前进一个字节,因为char是1个字节。

    因此,由于memcpy用于将字节从缓冲区复制到cp_data现在指向的位置(icmp数据包的有效负载),(char*)icmp + sizeof(struct icmphdr)再次被类型化为(char *)。

    希望这有帮助!