尝试使用原始套接字编写traceroute获得无限循环 [英] Trying to write traceroute using raw socket getting endless loop

查看:200
本文介绍了尝试使用原始套接字编写traceroute获得无限循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用原始套接字和ICMP编写一个非常简单的traceroute程序版本。但是当我运行它时,我总是得到一个无限循环的回声请求。



I'm trying to write a very simple version of the traceroute program using raw sockets and ICMP. But when I run it i just always get an endless loop of echo requests by myself back.

#include <netinet/ip.h>         
#include <netinet/ip_icmp.h>        
#include <sys/socket.h>         
#include <stdlib.h>             
#include <stdio.h>              
#include <sys/types.h>
#include <errno.h>
#include <netdb.h> 
#include <arpa/inet.h>
#include <ifaddrs.h>

int mysock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 
int ttl = 0;                    
char buffr[4069] = { 0 };
struct ip *myIpHeader = (struct ip*)buffr;      
struct ifaddrs *ifa;
getifaddrs(&ifa);   





然后我只做一些输入检查并将setsocketopt设置为HDRINCL





then i just do some input checks and set setsocketopt to HDRINCL

struct sockaddr_in cliAddr; 
cliAddr.sin_port = htons(7);   
cliAddr.sin_family = AF_INET;   
inet_pton(AF_INET, argv[1], &(cliAddr.sin_addr));





然后是无尽的while循环,我设置了这样的ip和icmp标题





then the endless while loop where i set up the ip and icmp header like this

myIpHeader->ip_v = 4;                           
myIpHeader->ip_hl = 5;                      
myIpHeader->ip_tos = 0;                                             
myIpHeader->ip_len = 20+8;
myIpHeader->ip_off = 0;                     
myIpHeader->ip_p = IPPROTO_ICMP;                
inet_pton(AF_INET, argv[1], &(myIpHeader->ip_dst));
inet_pton(AF_INET, ifa->ifa_name, &(myIpHeader->ip_src));
myIpHeader->ip_sum = 0;
myIpHeader->ip_id = htonl(12345);                               
myIpHeader->ip_ttl = ttl;

struct icmphdr *myicmphead = (struct icmphdr *) (buffr + 20);        
myicmphead->type = 8; 
myicmphead->code = 0;               
myicmphead->checksum = 0;





then跟随发送和接收





then follows send and recv

sendto(mysock, buffr , sizeof (struct ip) + sizeof (struct icmphdr), 0, (struct sockaddr*)&cliAddr, sizeof cliAddr);
char buff[4096] = { 0 };            
struct sockaddr_in serverAddr;      
socklen_t inlen = sizeof(struct sockaddr_in);

recvfrom(mysock, buff, sizeof(buff), 0, (struct sockaddr*) & serverAddr, &inlen);
struct icmphdr *icmphd2 = (struct icmphdr *) (buff + 20);





然后我只检查我收到的类型是否等于0,如果是这样的话到达目的地,我退出,如果不是我要打印ttl和地址并增加ttl





and then i just check if the type i receive equals 0 if so the destination is reached and i exit if not im gonna print the ttl and address and increase the ttl

printf("ttl: %d Address:%s\n", ttl, inet_ntoa(serverAddr.sin_addr));





但就像我说的那样我只打印出我在无限循环中放入ip头的源地址。基本上看起来像这样:(我只是为IP地址添加占位符等等)





But like i said i just print out the source address i put in the ip head in an endless loop. Basically looking like that:(I just put placeholders for ip addresses and so on)

trace route to '...' (IP: 160.....) 
ICMP msgtype=8, code=0 
ttl limit: 0 Address 127.0.0.1 
ICMP msgtype=8, code=0 
ttl limit: 1 Address 127.0.0.1 
ICMP msgtype=8, code=0 
ttl limit: 2 Address 127.0.0.1
ICMP msgtype=8, code=0 
ttl limit: 3 Address 127.0.0.1 
ICMP msgtype=8, code=0 
ttl limit: 4 Address 127.0.0.1





等等我得到的例子

我真的很感激我能解决这个问题的任何提示。



什么我试过了:



感谢Jochen Arndt,我可以解决这个问题,现在把正确的地址。但现在我遇到了一个新问题。该程序以某种方式获得第一个rcv,所以我想在我再次收到之前忘记做某事,因为它说资源暂时不可用作接收错误(当我把它放在等待回复时)。知道我忘记了什么吗?



and so on as example what i get
I would really appreciate any tips how i could solve this.

What I have tried:

Thanks to Jochen Arndt, I could solve this problem and now put the right addresses. But now I got a new problem. The program somehow just gets the first rcv, so I guess I forgot to do something before I receive again because it says the resource is temporarily unavailable as error for receive(when I put it to not wait for an reply). Any idea what I forgot?

推荐答案

您没有枚举现有的网络接口,只使用 getifaddrs()返回的第一个接口。您应该检查它是否是现有的INET IPv4接口而不是其他东西或者是环回接口。



您还传递 ifa-> ifa_name inet_pton()。但这是接口的名称(例如 localhost eth0 ),而 inet_pton()期望IP地址为字符串(例如127.0.0.1)。您可能想要使用 ifa-> ifa_addr 而不是二进制格式。



可能有还有其他错误,但在检查您的发送数据是否正确之前必须修复上述内容。



我建议阅读使用过的功能的文档:

getifaddrs(3) - Linux手册页 [ ^ ]

inet_pton(3) - Linux手册页 [ ^ ]



您还应始终检查返回状态的函数的返回值。如果您已经为 inet_pton()执行了此操作,您可能已经识别出调用失败。
You are not enumerating the existing network interfaces but use only the first returned by getifaddrs(). You should check if that is an existing INET IPv4 interface and not something else or the loopback interface.

You are also passing ifa->ifa_name to inet_pton(). But that is the name of the interface (e.g. localhost, eth0) while inet_pton() expects an IP address as string (e.g. "127.0.0.1"). You probably want to use ifa->ifa_addr instead which is already in binary format.

There may be also other errors but the above have to be fixed before checking if your send data are correct.

I suggest to read the documentation of the used functions:
getifaddrs(3) - Linux manual page[^]
inet_pton(3) - Linux manual page[^]

You should also always check the return value of functions that return a state. If you would have done that for inet_pton(), you would have recognised that the call failed.


由于某种原因
inet_ntoa(serverAddr.sin_addr)

我在打印时使用了重写的地址到我从icmp获得的地址。现在它起作用了。

i used in printing rewrote the dest address to the one i got as source from icmp. Now it works tho.


这篇关于尝试使用原始套接字编写traceroute获得无限循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆