我正在尝试通过构造适当的 ip 标头和 icmp 标头来使用 icmp 原始套接字实现 traceroute。我使用的端口号是 7,我已经计算了校验和。每次都会增加跃点限制,并发送一个数据包直到回复消息包含类型 0 的回显回复。
#include "libsock"
#include<netinet/ip.h>
#include<netinet/ip_icmp.h>
unsigned short
csum (unsigned short *buf, int nwords)
{
unsigned long sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
int
main (int argc, char *argv[])
{
if (argc != 2)
{
printf ("need destination for tracert\n");
exit (0);
}
int sfd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
char buf[4096] = { 0 };
struct ip *ip_hdr = (struct ip *) buf;
int hop = 0;
int one = 1;
const int *val = &one;
if (setsockopt (sfd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
printf ("Cannot set HDRINCL!\n");
struct sockaddr_in addr;
addr.sin_port = htons (7);
addr.sin_family = AF_INET;
inet_pton (AF_INET, argv[1], &(addr.sin_addr));
while (1)
{
ip_hdr->ip_hl = 5;
ip_hdr->ip_v = 4;
ip_hdr->ip_tos = 0;
ip_hdr->ip_len = 20 + 8;
ip_hdr->ip_id = 10000;
ip_hdr->ip_off = 0;
ip_hdr->ip_ttl = hop;
ip_hdr->ip_p = IPPROTO_ICMP;
inet_pton (AF_INET, "172.30.104.59", &(ip_hdr->ip_src));
inet_pton (AF_INET, argv[1], &(ip_hdr->ip_dst));
ip_hdr->ip_sum = csum ((unsigned short *) buf, 9);
struct icmphdr *icmphd = (struct icmphdr *) (buf + 20);
icmphd->type = ICMP_ECHO;
icmphd->code = 0;
icmphd->checksum = 0;
icmphd->un.echo.id = 0;
icmphd->un.echo.sequence = hop + 1;
icmphd->checksum = csum ((unsigned short *) (buf + 20), 4);
sendto (sfd, buf, 28, 0, SA & addr, sizeof addr);
char buff[4096] = { 0 };
struct sockaddr_in addr2;
socklen_t len = sizeof (struct sockaddr_in);
recvfrom (sfd, buff, 28, 0, SA & addr2, &len);
struct icmphdr *icmphd2 = (struct icmphdr *) (buff + 20);
if (icmphd2->type != 0)
printf ("hop limit:%d Address:%s\n", hop, inet_ntoa (addr2.sin_addr));
else
{
printf ("Reached destination:%s with hop limit:%d\n",
inet_ntoa (addr2.sin_addr), hop);
exit (0);
}
hop++;
}
return 0;
}
当输入 ieargv[1]
是"127.0.0.1"
o/p 是
hop limit:0 Address:127.0.0.1
Reached destination:127.0.0.1 with hop limit:1
但是对于我的局域网中存在的其他地址,tracepath 为这些地址工作,我的程序块位于recvfrom
.
你能指出原因吗?
谢谢你。
这是libsock: -
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<unistd.h>
#include<pthread.h>
#include<poll.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<signal.h>
#include<sys/sem.h>
#include<poll.h>
#include<pthread.h>
#include<sys/select.h>
#include<sys/un.h>
#define SA (struct sockaddr*)