IGMPv2メンバーシップリクエストパケットを偽造して、RAWソケットで送信しようとしています。
RFC3376は次のように述べています。
IGMPメッセージは、IPプロトコル番号2のIPv4データグラムにカプセル化されます。このドキュメントで説明されているすべてのIGMPメッセージは、IP Time-to-Live 1、IP Precedence of Internetwork Control(Type of Service 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とルーターアラートオプションを設定します。
// 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オプションを設定する他の方法はありますか?
前もって感謝します。