我想发送原始 IP 数据包,它工作得很好,除了 IP header 中的一个字段。
我需要将IP id设置为0。我尝试了以下方式:
struct iphdr ip;
ip.version = 4; // Ipv4
ip.frag_off = 0; // IP Fragmentation
ip.tos = 0; // Type of Service - We don't need this
ip.ttl = 64; // Maxmimum value
ip.protocol = IPPROTO_UDP; // DHCP uses UDP
ip.check = 0; // The checksum needs to be 0 before being calculated
// We don't yet have an IP Address
if((ip.saddr = inet_addr("0.0.0.0")) == -1) {
perror("Failed to convert IP address");
exit(1);
}
ip.daddr = inet_addr("255.255.255.255"); // we have to do a broadcast
ip.id = 0; //
ip.ihl = 5; // Header length - 5 means no additional options are being sent in the IP header
ip.tot_len = sizeof(struct packet); // The total length of the Packet
然后我创建一个设置了 IP_HDRINCL 选项的 RAW_SOCKET:
if ((sockd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) {
perror("Failed to create socket");
exit(1);
}
int hdrincl = 1;
if (setsockopt(sockd, IPPROTO_IP, IP_HDRINCL, &hdrincl, sizeof(hdrincl)) == -1) {
perror("Failed to set IP_HDRINCL");
exit(1);
}
然后我创建一个缓冲区,其中包含我的 IP header 、UDP header 和有效负载并将其发送出去。
但是,网络堆栈一直在更改 IP header 中的我的 ID。我需要包含 IP header ,但我还需要禁用分段和/或将 IP id 设置为 0。我该如何实现?
编辑:我在 Linux 上
最佳答案
在 Linux 上,您可以使用 AF_PACKET
和 SOCK_DGRAM
套接字,而不是 AF_INET
和 SOCK_RAW
并填充一个 sockaddr_ll
。
类似的东西:
socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))
但是,为了使您的程序也能在 Windows 上工作,您应该使用 libpcap .
请记住,您应该自己解析目的地的物理地址(在 linux 上,您可以尝试使用 rtnetlink
接口(interface))。
查看更多关于 packet(7)
和 rtnetlink(7)
的信息。如果您的项目是开源的,您可以使用 my old project做其中一些事情(有关更多信息,请与我联系)。
关于C套接字编程: Set ip header's id to 0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39476808/