RAW icmp socket:如何获得正确的回复

时间:2019-01-08 19:42:09

标签: c sockets

我正在尝试建立一个简单的icmp echo请求,但是我无法得到很好的答复。

我尝试使用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,数据已发送,但没有回复全部 对于具有HDRINCL的IPPROTO_ICMP,我使用icmp ECHO(类型8)而不是echo_reply(类型1)进行答复 对于没有HDRINCL的IPPROTO_ICMP(并且struct ip到处都有注释),有icmp 69作为答复。

我认为,当我第一次尝试这些“配置”时,它们不会造成任何差异,但确实会造成差异。为什么?

有人看到什么问题了,我该如何解决我的问题?如果是,怎么办?

非常感谢

0 个答案:

没有答案