gpt4 book ai didi

c - 需要帮助修复此 C Socket ICMP 程序

转载 作者:行者123 更新时间:2023-11-30 18:58:54 26 4
gpt4 key购买 nike

我有一个 C 程序,它能够接收 ICMP 请求并显示它们,但根据我使用 Wireshark 所看到的情况,它本身不会发送任何 ICMP 请求。

我已经包含了所需的库,并且正在使用省略的 IP 头文件和 ICMP 头文件。

如有任何帮助,我们将不胜感激。请忽略随机的 Printf 语句,它们只是为了帮助我。

谢谢

**

***IP.h*****

#ifndef __IP_H__
#define __IP_H__

struct iphdr {

uint8_t hdrlen:4;
uint8_t version:4;
uint8_t ecn:2;
uint8_t dscp:6;
uint16_t length;
uint16_t ident;
uint16_t fragoff:13;
uint16_t flags:3;
uint8_t ttl;
uint8_t protocol;
uint16_t checksum;
uint32_t srcip;
uint32_t dstip;
uint32_t options[ ];
} __attribute__((__packed__));

#endif // __IP_H__

****ICMP.H****

#ifndef __ICMP_H__
#define __ICMP_H__

struct icmphdr {
uint8_t type;
uint8_t code;
uint16_t checksum;
uint16_t id;
uint16_t seqNum;
uint32_t data[ ];
} __attribute__((__packed__));


char * messages[ ] = {
"Echo reply",
"Type 1",
"Type 2",
"Destination unreachable",
"Source quench",
"Redirect",
"Type 6",
"Type 7",
"Echo request",
"Router advertisement",
"Router discovery",
"Time exceeded",
"Parameter problem",
"Timestamp request",
"Timestamp reply",
"Information request (obsol.)",
"Information reply (obsol.)",
"Address mask request",
"Address mask reply"
};

#endif // __ICMP_H__


****Main C File ****

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "ip.h"
#include "icmp.h"

struct timeval timeout;
struct timeval end;


#define BUF_SIZE 1024
#define ICMP 1
#define ECHO_REQ 8
#define ECHO_REPL 0
#define HOSTADDR "8.8.8.8"

char *
iptos (uint32_t ipaddr) {
static char ips[16];

sprintf(ips, "%d.%d.%d.%d",
(ipaddr >> 24),
(ipaddr >> 16) & 0xff,
(ipaddr >> 8) & 0xff,
(ipaddr ) & 0xff );
return ips;
}

uint16_t
sum (uint16_t initial, void * buffer, int bytes) {
uint32_t total;
uint16_t * ptr;
int words;

total = initial;
ptr = (uint16_t *) buffer;
words = (bytes + 1) / 2; // +1 & truncation on / handles any odd byte at end

while (words--) total += *ptr++;
while (total & 0xffff0000) total = (total >> 16) + (total & 0xffff);

return (uint16_t) total;
}




void
some_function ( ) {

struct sockaddr_storage peer_addr;
socklen_t peer_addrlen;

struct sockaddr_in addr;
struct sockaddr_in dstaddr;
struct iphdr * ip;
struct icmphdr * icmp;
struct timeval * sent;
int skt;
int sequence;
long int length;
fd_set rdfds;
int ready;
int rtt;

char buff [BUF_SIZE];



skt = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (skt < 0) {
perror ("socket()");
exit (1);
}

addr.sin_family = AF_INET;
addr.sin_port = 0;
addr.sin_addr.s_addr = INADDR_ANY;

if (bind (skt, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) {
perror ("Can't bind socket");
exit (1);
}
printf("aaa");
ip = (struct iphdr *)buff;
peer_addrlen = (socklen_t) sizeof (struct sockaddr_storage);

memset (&dstaddr, 0, sizeof(struct sockaddr_in));
dstaddr.sin_addr.s_addr = inet_addr(HOSTADDR);
dstaddr.sin_family = AF_INET;

memset (buff, 0, sizeof(buff));
icmp = (struct icmphdr *) buff;
icmp->type = ECHO_REQ;
icmp->id = htons(getpid( ) & 0xffff);
icmp->seqNum = htons(sequence++);

printf("aabba");


if (gettimeofday ((struct timeval *)icmp->data, NULL)) {
perror ("Can't establish send time");
exit (1);
}

length = sizeof(struct icmphdr) + sizeof(struct timeval);
icmp->checksum = ~htons(sum (0, buff, length));


printf("aaa");

if (sendto (skt, buff, length, 0,
(struct sockaddr *) &dstaddr, sizeof(struct sockaddr_in)) <= 0) {
perror ("sendto()");
exit (1);


}
printf("aaa");
timeout.tv_sec = 1;
timeout.tv_usec = 0;
FD_ZERO(&rdfds);
FD_SET (skt, &rdfds);

ready = select (skt + 1, &rdfds, NULL, NULL, &timeout);
if (ready < 0) {
perror ("Select()");
exit (1);
}

memset (buff, 0, sizeof(buff));
if (recvfrom (skt, buff, sizeof(buff), 0,
(struct sockaddr *) &peer_addr, &peer_addrlen) <= 0) exit (1);

if (gettimeofday (&end, NULL)) { // Timestamp reception
perror ("Can't establish time of receipt");
exit (1);
}

if (ip->version != 4 ||
sum (0, buff, sizeof(struct iphdr)) != 0xffff ||
ip->protocol != ICMP)
exit(1);

length = ntohs(ip->length) - ip->hdrlen * 4; // Length of IP payload
icmp = (struct icmphdr *)((uint32_t *)ip + ip->hdrlen); // Find ICMP hdr

if (icmp->type != ECHO_REPL || sum (0, icmp, length) != 0xffff) {
fprintf (stderr, "Received %s\n", messages[icmp->type]);
exit (1);
}


sent = (struct timeval *)icmp->data;
if ((rtt = (end.tv_usec - sent->tv_usec) / 100) < 0)
rtt += 10000; // We've cycled to a new second
rtt += (end.tv_sec - sent->tv_sec) * 10000; // Add any seconds

printf ("%ld bytes from %s: icmp_req=%d ttl=%d time=%0.1f ms\n",
length,
iptos(ntohl(ip->srcip)),
ntohs(icmp->seqNum),
ip->ttl,
((float)rtt) / 10);

}
int main(){
printf("aaa");
some_function();
return(0);

}

最佳答案

问题是校验和错误。

更改此行

icmp->checksum = htons(sum (0, buff, length));

icmp->checksum = ~(sum (0, buff, length));

sum 函数已经关心字节顺序,无需使用 htons 再次翻译

关于c - 需要帮助修复此 C Socket ICMP 程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14634387/

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