C套接字编程:设置ipheader的id为0?
C socket programming: Set ip header's id to 0?
我想发送原始 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
然后我创建一个 RAW_SOCKET 并设置 IP_HDRINCL 选项:
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
接口)。
在 packet(7)
和 rtnetlink(7)
上查看更多信息。如果您的项目是开源的,您可以使用 my old project 来做其中的一些事情(有关更多信息,请联系我)。
我想发送原始 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
然后我创建一个 RAW_SOCKET 并设置 IP_HDRINCL 选项:
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
接口)。
在 packet(7)
和 rtnetlink(7)
上查看更多信息。如果您的项目是开源的,您可以使用 my old project 来做其中的一些事情(有关更多信息,请联系我)。