好的,所以我尝试使用讲师的材料编写一个简单的ICMP traceroute,这些材料是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时,它看起来像是它的tracerouting,但是当我想检查一个我收到它的包时会有不同的{ {1}}和icmp_id
来自我发送的内容。这对我来说似乎很奇怪,因为当我运行icmp_seq
和echo_request
并发送包含icmp_receive
123和id
1的包时,我会收到完全相同的{{1} }和seq
,但在我的程序中它有所不同(我在id
检查的内容)。
如果你能指出我在我的代码中做蠢事的地方并解释一下,我将不胜感激。这项任务变得比我预期的更难。
答案 0 :(得分:0)
您需要在致电re
后查看Recvfrom
。可能存在错误或不同的长度。
此外,我记得,使用此RAW套接字,您将获得发送到网络接口的所有 ICMP数据包;所以你需要接收所有数据包,只能使用包含相同序列号的数据包。
我看不到bind()
。这不是必要的吗?