Я пытаюсь создать простой эхо-запрос icmp, но не могу получить хороший ответ.
Я пытался отправить запрос с сокетом RAW и с протоколом IPPROTO_ICMP или IPPROTO_RAW, и я получаю разные результаты, от отсутствия ответа на все это до ответа с помощью icmp типа 69 или типа 8.
ctx.socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); // OR IPPROTO_ICMP
if (ctx.socket_fd == -1)
{
perror("socket:");
exit(EXIT_FAILURE);
}
int on = 1;
setsockopt(ctx.socket_fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)); // IF IPPROTO_ICMP and struct ip not sent
Первая инициализация:
struct s_ping packet = {
.ip = { // == struct ip if IPPROTO_RAW or if setsockoptionned IP_HDRINCL
.ip_hl = BYTE_TO_WORD(sizeof(struct iphdr)),
.ip_v = 4,
/* tos */
.ip_len = htons(sizeof(packet)),
.ip_id = (u_short)getpid(),
.ip_off = htons(IP_DF),
.ip_ttl = TTL,
.ip_p = IPPROTO_ICMP,
},
.icmp = { // == struct icmp
.icmp_type = ICMP_ECHO,
.icmp_code = 0,
.icmp_id = (u_int16_t)getpid(),
},
};
memset(&packet.icmp.icmp_data, 0, DATA_LEN);
inet_pton(AF_INET, "0.0.0.0", &packet.ip.ip_src.s_addr);
inet_pton(AF_INET, ctx->addr /* == "127.0.0.1", &packet.ip.ip_dst.s_addr);
А затем последние данные ICMP:
packet.icmp.icmp_seq = htons(sequence);
packet.icmp.icmp_cksum = 0;
packet.icmp.icmp_cksum = htons(checksum(&packet, sizeof(packet)));
Для IPPROTO_RAW данные отправляются, но ответа на них нет.
Для IPPROTO_ICMP с HDRINCL у меня есть ответ с ECHO icmp (тип 8), а не echo_reply (тип 1)
Для IPPROTO_ICMP без HDRINCL (и везде с комментариями struct ip) в качестве ответа используется icmp 69.
Когда я впервые попробовал эти «конфигурации», я подумал, что они не вызовут никакой разницы, но это так. Почему?
Кто-нибудь видит, что не так и как я могу исправить свои проблемы? Если да, то как?
Большое спасибо