gpt4 book ai didi

c - 发送 ICMP 消息但没有收到任何消息?

转载 作者:行者123 更新时间:2023-11-30 14:50:11 28 4
gpt4 key购买 nike

我想发送 ICMP 消息并接收回显。我花了一周的时间研究原始套接字并搜索引用资料。然后我编写下面的代码来保证发送ICMP消息成功,因为'socket'和'send'的返回是可以的(不是负1)。不幸的是,“recvfrom”什么也没收到,下面是我在 Windows 上的简洁代码:

#define _WIN32_WINNT 0x501

#include <stdio.h>
#include <ws2tcpip.h>
#include <winsock2.h>

#include <fcntl.h>
#include <unistd.h>

#include <string.h>
#include <sys/stat.h>

#pragma comment(lib,"Ws2_32.lib")

WSADATA wsaData;
int main(int args, char *argv[]){
WSAStartup(MAKEWORD(2,2),&wsaData);

//**************icmp book******************/
typedef struct icmp_hdr {
unsigned char icmp_type;
unsigned char icmp_code;
unsigned short icmp_checksum;
unsigned short icmp_id;
unsigned short icmp_sequence;
unsigned long icmp_timestamp;
} ICMP_HDR;

ICMP_HDR *icmp = NULL;
char buffer[sizeof(ICMP_HDR) + 32];

icmp = (ICMP_HDR *)buffer; //

icmp->icmp_type = 8;
icmp->icmp_code = 0;
icmp->icmp_id = 1314;
icmp->icmp_checksum = sizeof(ICMP_HDR) + 32;
icmp->icmp_sequence = 0;
icmp->icmp_timestamp = GetTickCount();

memset(&buffer[sizeof(ICMP_HDR)],'@',32);

int my_socket = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);

struct in_addr my_addr;
my_addr.s_addr = inet_addr("127.0.0.1");
// inet_aton(argv[1],&my_addr);

struct sockaddr_in sa_t;

sa_t.sin_family = AF_INET;
sa_t.sin_port = htons(0);
sa_t.sin_addr = my_addr;


int p = sendto(my_socket,buffer,sizeof(ICMP_HDR)+32,0,(struct sockaddr *)&sa_t, sizeof(sa_t));

printf("return : %d\n ------s: %d\n",p,my_socket);

int tmp_add = sizeof(sa_t);

char buf[1024];

recvfrom(my_socket,buf,1024,0,(struct sockaddr *)&sa_t,&tmp_add);

printf("receive is: %s\n",buf);

return 1;

}

当我编译并运行此代码时,我的期望是“recvfrom”函数将收到任何内容。

但是“recvfrom”没有任何结果,我花了两天时间,在这里谢谢。

最佳答案

首先,您需要确保编译器不会尝试在 4、8 或 16 字节地址边界上对齐所有内容(#pragma pack)来填充您的结构,然后您必须正确对齐构造并正确计算校验和。在响应端,您不能将缓冲区视为字符串,它可能包含非 ASCII 数据。此外,网络字节顺序并不总是与任一主机体系结构上的字节顺序相同,因此您应该始终在发送/接收之前进行转换。

这有效。我将让您弄清楚响应中额外的 20 个左右字节的含义。

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <ws2tcpip.h>
#include <winsock2.h>

#include <fcntl.h>

#include <string.h>
#include <sys/stat.h>

#pragma comment(lib,"Ws2_32.lib")

#define STRING_LENGTH 32

//**************icmp book******************/
#pragma pack(push, 1)
typedef struct icmp_msg {
uint8_t type;
uint8_t code;
uint16_t checksum;
uint16_t id;
uint16_t sequence;
uint32_t timestamp;
uint8_t tail[STRING_LENGTH + 2];
} ICMP_MSG;
#pragma pack(pop)

// malloc() is gauranteed to provide suitable alignement.
ICMP_MSG *ping = NULL;

void PrintMsg(ICMP_MSG *msg)
{
printf("Ping:\n\tId: %u16\n\tSequence: %u16\n\tTimestamp: %lu\n\tString: ", ntohs(msg->id), ntohs(msg->sequence), ntohl(msg->timestamp));

char *it = (char*)&(msg->tail[0]);
char *it_end = (char*)msg + sizeof(ICMP_MSG);
while (it < it_end)
{
char *hexString[65] = { 0 };
_itoa_s(*it, (char*)hexString, 32, 16);
printf("0x%s,", (char*)hexString);
it++;
}

printf("\n\n");
}

// Ripped from https://github.com/pocoproject/poco/blob/develop/Net/src/ICMPPacketImpl.cpp#L98 and cleaned-up.
uint16_t Checksum(uint16_t *addr, size_t len)
{
size_t nleft = len;
uint16_t* w = addr;
uint16_t answer;
int32_t sum = 0;

while (nleft > 1)
{
sum += *w++;
nleft -= sizeof(uint16_t);
}

if (nleft == 1)
{
uint16_t u = 0;
*(uint8_t*)(&u) = *(uint8_t*)w;
sum += u;
}

sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum & 0xffff;

return answer;
}

int main(void) {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

ping = malloc(sizeof(ICMP_MSG));

ping->type = 8;
ping->code = 0;
ping->id = htons(1314);
ping->checksum = 0; // Must be zero prior to checksum calculation.
ping->sequence = 0;
ping->timestamp = htonl(GetTickCount());

// 0x40 == '@' in ASCII
memset(ping->tail, 0x40, STRING_LENGTH);
// NUL pad the last two bytes fo the string.
ping->tail[STRING_LENGTH] = '\0';
ping->tail[STRING_LENGTH + 1] = '\0';

ping->checksum = Checksum((uint16_t*)ping, sizeof(ICMP_MSG));

int res;
int my_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);


struct in_addr my_addr;
my_addr.s_addr = inet_addr("127.0.0.1");
//res = inet_pton(AF_INET, "127.0.0.1", &my_addr.s_addr);

struct sockaddr_in sa_t;

sa_t.sin_family = AF_INET;
sa_t.sin_port = htons(0);
sa_t.sin_addr = my_addr;

PrintMsg(ping);

res = sendto(my_socket, (const char*)ping, sizeof(ICMP_MSG), 0, (struct sockaddr *)&sa_t, sizeof(sa_t));

printf("Socket: %d\nsendto returned: %d\n", my_socket, res);

int tmp_add = sizeof(sa_t);

ICMP_MSG *resp = calloc(1, 2048 /*sizeof(ICMP_MSG)*/);

res = recvfrom(my_socket, (char*)resp, 2048, 0, (struct sockaddr *)&sa_t, &tmp_add);

printf("recvfrom returned: %d\n", res);
if (SOCKET_ERROR == res)
{
res = WSAGetLastError();
printf("WSAGetLastError() returned: %d (", res);
switch (res)
{
case WSAEMSGSIZE:
printf("WSAMSGSIZE)\n");
break;
default:
printf("Unexpected)\n");
break;
}
}

PrintMsg(resp);

system("pause");

free(ping);
free(resp);

return 1;

}

关于c - 发送 ICMP 消息但没有收到任何消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49102067/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com