Попытка написать traceroute с помощью raw сокета получает бесконечный цикл
Я пытаюсь написать очень простую версию программы traceroute, используя необработанные сокеты и ICMP. Но когда я запускаю его, я просто всегда получаю бесконечный цикл Эхо-запросов сам по себе.
#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
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 следующим образом
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;
затем следует send и 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
printf("ttl: %d Address:%s\n", ttl, inet_ntoa(serverAddr.sin_addr));
Но, как я уже сказал, я просто распечатываю исходный адрес, который помещаю в ip-головку в бесконечном цикле. В основном это выглядит так: (я просто ставлю заполнители для ip-адресов и так далее)
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
и так далее в качестве примера что я получаю
Я был бы очень признателен за любые советы, как я мог бы решить эту проблему.
Что я уже пробовал:
Благодаря Йохену Арндту я смог решить эту проблему и теперь ставлю правильные адреса. Но теперь у меня появилась новая проблема. Программа каким-то образом просто получает первый rcv, так что я думаю, что забыл что-то сделать, прежде чем снова получить его, потому что он говорит, что ресурс временно недоступен как ошибка для получения(когда я ставлю его, чтобы не ждать ответа). Есть идеи, что я забыл?