基于原始套接字实现ICMP回显报文时sendto无效参数问题排查
手动实现Ping时sendto返回"invalid argument"及报文格式异常问题
正在手动实现Ping命令以学习其工作原理,当前在发送包含IP头、ICMP头和负载(限制为16字节+struct timeval大小)的原始数据报时遇到问题。调用sendto函数后,perror输出“invalid argument”,且生成的报文存在格式异常。
手动构造的报文详情
IP version: 4 IP header length: 5 IP TOS: 0 IP total length: 40 IP ID: 4242 IP flags: 2 IP fragment offset: 0 IP time to live: ff IP protocol: 1 IP header checksum: 517 IP source address: ac8acd1 IP destination address: d83acc4e // Google IP ICMP type: 8 ICMP code: 0 ICMP checksum: 3e33 ICMP identifier: 806f ICMP sequence: 0 ICMP payload seconds: 1693445511 ICMP payload microseconds: 867091 ICMP payload: 5400 4000 4242 0200 ff01 1705 d1ac c80a 4ecc 3ad8 0800 333e 6f80 0000 87ed ef64 0000 0000 133b 0d00 98b6 336b 0100 0000 ad00 9f0e 9419 00b8 e0b6 336b 0100 0000 cc74 ac04 0100 0000 0000 0000 0000 0000 ad00 9f0e 9419 00b8
相关结构体定义
typedef struct s_ip_header { unsigned char version : 4; unsigned char ihl : 4; unsigned char type_of_service : 8; unsigned short total_length : 16; unsigned short identification : 16; unsigned char flags : 3; unsigned short fragment_offset : 13; unsigned char time_to_live : 8; unsigned char protocol : 8; unsigned short header_checksum : 16; unsigned int source_address : 32; unsigned int destination_address : 32; } __attribute__((__packed__)) t_ip_header; typedef struct s_ip_header { unsigned char version : 4; unsigned char ihl : 4; unsigned char type_of_service : 8; unsigned short total_length : 16; unsigned short identification : 16; unsigned char flags : 3; unsigned short fragment_offset : 13; unsigned char time_to_live : 8; unsigned char protocol : 8; unsigned short header_checksum : 16; unsigned int source_address : 32; unsigned int destination_address : 32; } __attribute__((__packed__)) t_ip_header;
测试代码
#include "../incs/icmp.h" #include "../incs/utils.h" #include <netdb.h> #include <stdio.h> #include <stdlib.h> void my_ping(t_args *args) { t_icmp_packet packet = build_echo_message_packet( 180923601, 3627732046, (unsigned char *)"payload42 42 42\0"); unsigned short *bytes_packet = (unsigned short *)&packet; int manual_ip_header = 1; struct sockaddr_in servaddr; socklen_t servlen; for (size_t i = 0; i < sizeof(t_icmp_packet); i++) *(bytes_packet + i) = htons(*(bytes_packet + i)); int fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (fd < 0) exit(1); if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &manual_ip_header, sizeof(manual_ip_header)) == -1) exit(1); servaddr.sin_family = AF_INET; servaddr.sin_port = 0; servaddr.sin_addr.s_addr = 3627732046; servlen = sizeof(struct sockaddr_in); if (sendto(fd, bytes_packet, sizeof(t_icmp_packet), 0, (struct sockaddr *)&servaddr, servlen) <= 0) { perror("Error: "); exit(1); } }
已尝试调整位序但未解决问题。观察报文发现,首个16位字为5400,正确应为4500;下一个4000需改为0040。
内容的提问来源于stack exchange,提问作者Mario
相关产品推荐
相关产品推荐

