我正在尝试伪造一个 IGMPv2 Membership Request 数据包并将其发送到 RAW 套接字上。
RFC 3376 规定:
IGMP 消息封装在 IPv4 数据报中,IP 协议号为 2。本文档中描述的每个 IGMP 消息都以 1 的 IP 生存时间发送,IP 网络控制优先级(例如,服务类型 0xc0),并在其 IP 标头中携带 IP 路由器警报选项 [RFC-2113]
所以必须设置 IP_ROUTER_ALERT 标志。
我试图伪造数据包的严格必要条件(例如,只有 IGMP 标头和有效负载),所以我使用 setsockopt 来编辑 IP 选项。
一些有用的变量:
#define C_IP_MULTICAST_TTL 1
#define C_IP_ROUTER_ALERT 1
int sockfd = 0;
int ecsockopt = 0;
int bytes_num = 0;
int ip_multicast_ttl = C_IP_MULTICAST_TTL;
int ip_router_alert = C_IP_ROUTER_ALERT;
以下是我打开 RAW 套接字的方法:
sock_domain = AF_INET;
sock_type = SOCK_RAW;
sock_proto = IPPROTO_IGMP;
if ((ecsockopt = socket(sock_domain,sock_type,sock_proto)) < 0) {
printf("Error %d: Can't open socket.\n", errno);
return 1;
} else {
printf("** Socket opened.\n");
}
sockfd = ecsockopt;
然后我设置 TTL 和 Router Alert 选项:
// Set the sent packets TTL
if((ecsockopt = setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ip_multicast_ttl, sizeof(ip_multicast_ttl))) < 0) {
printf("Error %d: Can't set TTL.\n", ecsockopt);
return 1;
} else {
printf("** TTL set.\n");
}
// Set the Router Alert
if((ecsockopt = setsockopt(sockfd, IPPROTO_IP, IP_ROUTER_ALERT, &ip_router_alert, sizeof(ip_router_alert))) < 0) {
printf("Error %d: Can't set Router Alert.\n", ecsockopt);
return 1;
} else {
printf("** Router Alert set.\n");
}
IP_ROUTER_ALERT的setsockopt返回0。伪造数据包后,我用sendto这样发送:
// Send the packet
if((bytes_num = sendto(sockfd, packet, packet_size, 0, (struct sockaddr*) &mgroup1_addr, sizeof(mgroup1_addr))) < 0) {
printf("Error %d: Can't send Membership report message.\n", bytes_num);
return 1;
} else {
printf("** Membership report message sent. (bytes=%d)\n",bytes_num);
}
数据包已发送,但缺少 IP_ROUTER_ALERT 选项(使用 wireshark 检查)。难道我做错了什么?还有其他方法可以设置 IP_ROUTER_ALERT 选项吗?
提前致谢。