尝试使用原始套接字编写traceroute获得无限循环 [英] Trying to write traceroute using raw socket getting endless loop
问题描述
我正在尝试使用原始套接字和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 bygetifaddrs()
. You should check if that is an existing INET IPv4 interface and not something else or the loopback interface.
You are also passingifa->ifa_name
toinet_pton()
. But that is the name of the interface (e.g. localhost, eth0) whileinet_pton()
expects an IP address as string (e.g. "127.0.0.1"). You probably want to useifa->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 forinet_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屋!