gpt4 book ai didi

c - C 中简单的 icmp traceroute 实现

转载 作者:太空宇宙 更新时间:2023-11-04 00:04:38 30 4
gpt4 key购买 nike

好的,所以我尝试使用讲师提供的 Material 编写一个简单的 ICMP traceroute,这些 Material 是 echo_request 和 icmp_receive 程序,我想将它们合并以实现我的目标,但它有点行不通。

您可以看到这些程序的代码以及我包含在我的代码中的其他程序 >here<

请记住,我是套接字编程的初学者。今天刚开始,有些东西还是不明白。

所以我的代码看起来像这样(这不是 traceroute 的最终版本!这只是我认为应该给出一些结果的片段):

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <netinet/ip_icmp.h>
#include "sockwrap.h"
#include "icmp.h"
#include <time.h>

unsigned char buffer[IP_MAXPACKET+1];
unsigned char* buffer_ptr;
int re;

int main(int argc, char **argv){
if(argc != 2){
printf("Usage: ./traceroute <ip>\n");
return 1;
}

int sockfd = Socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

struct sockaddr_in remote_address;
bzero (&remote_address, sizeof(remote_address));
remote_address.sin_family = AF_INET;
inet_pton(AF_INET, argv[1], &remote_address.sin_addr);

int ttl = 1;

while(1){
struct icmp icmp_packet;
icmp_packet.icmp_type = ICMP_ECHO;
icmp_packet.icmp_code = 0;
icmp_packet.icmp_id = 123;
icmp_packet.icmp_seq = ttl;
icmp_packet.icmp_cksum = 0;
icmp_packet.icmp_cksum = in_cksum((u_short*)&icmp_packet, 8, 0);

Setsockopt (sockfd, IPPROTO_IP, IP_TTL, &ttl, sizeof(int));

Sendto(sockfd, &icmp_packet, ICMP_HEADER_LEN, 0, &remote_address, sizeof(remote_address));
Sendto(sockfd, &icmp_packet, ICMP_HEADER_LEN, 0, &remote_address, sizeof(remote_address));
Sendto(sockfd, &icmp_packet, ICMP_HEADER_LEN, 0, &remote_address, sizeof(remote_address));

clock_t start = clock();
float seconds = 0;
while(seconds < 1){
clock_t c = clock();
seconds = (float)(c - start)/CLOCKS_PER_SEC;
}

struct sockaddr_in sender;
socklen_t sender_len = sizeof(sender);
buffer_ptr = buffer;
re = Recvfrom (sockfd, buffer_ptr, IP_MAXPACKET,
0, &sender, &sender_len);

char str[20];
inet_ntop(AF_INET, &(sender.sin_addr), str, sizeof(str));
// this printf shows me ip adresses of routers on route to
// destination(probably?), but anything below it doesn't seem to work
// properly :(
//printf ("%s\n", str);

struct icmp* icmp_packet_recv = (struct icmp*) buffer_ptr;

printf("%d %d\n", icmp_packet_recv->icmp_id, icmp_packet_recv->icmp_seq);

if (icmp_packet_recv->icmp_type == ICMP_TIME_EXCEEDED &&
icmp_packet_recv->icmp_code == ICMP_EXC_TTL) {

struct ip* packet_orig = (struct ip*) buffer_ptr;

if (packet_orig->ip_p == IPPROTO_ICMP) {
if(icmp_packet_recv->icmp_seq == ttl && icmp_packet_recv->icmp_id == 123)
printf ("%s\n", str);
}
}
if (icmp_packet_recv->icmp_type == ICMP_ECHOREPLY) {
printf ("%s\n", str);
return 0;
}

ttl++;
}

return 0;
}

它有点工作,因为当我 printf("%s\n", str); 其中 str 是发件人的 ip,它看起来像是跟踪路由,但是当我想检查一个包时我收到的它包含与我发送的内容不同的 icmp_idicmp_seq。这对我来说似乎很奇怪,因为当我运行 echo_requesticmp_receive 并发送一个带有 id 123 和 seq 的包时> 1,我收到完全相同的 idseq,但在我的程序中它是不同的(我通过这个 printf("%d %d\n", icmp_packet_recv->icmp_id, icmp_packet_recv->icmp_seq);).

如果您能指出我在代码中的哪些地方做了愚蠢的事情并加以解释,我将不胜感激。这项任务比我预期的要难。

最佳答案

您需要在调用Recvfrom 后检查re。可能存在错误或与您预期的长度不同。

另外,我记得,使用这个 RAW 套接字,您将所有 ICMP 数据包发送到您的网络接口(interface);所以你需要接收所有数据包并且只处理包含相同序列号的数据包。

而且我看不到 bind()。没有必要吗?

关于c - C 中简单的 icmp traceroute 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29344543/

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