📄 traceroute.h
字号:
//***************************************************************************************
// 作 成: 周赫 2004204276 pro1
//
// 作成时间: 2005/03/16
//
// traceroute.h - 定义数据结构及实现具体的函数
//
// 修改时间:
//
// 编译方法:gcc -o mytraceroute traceroute.c errexit.c
//
//***************************************************************************************
#include <sys/param.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <memory.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* rfc1716 */
#ifndef ICMP_UNREACH_FILTER_PROHIB
#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
#endif
#ifndef ICMP_UNREACH_HOST_PRECEDENCE
#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */
#endif
#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
#endif
/* Maximum number of gateways (include room for one noop) */
#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
/* Host name and address list */
struct hostinfo {
char *name;
int n;
u_int32_t *addrs;
};
/* UDP包的数据部分,即payload */
struct outdata {
u_char seq; /* sequence number of this packet */
u_char ttl; /* ttl packet left with */
struct timeval tv; /* time packet left */
};
u_char packet[512]; /* 接收返回的icmp包的缓冲区 */
struct ip *outip; /* 最新发送的udp包的ip头 */
struct udphdr *outudp; /* 最新发送的udp包的udp头 */
struct outdata *outdata; /* 最新发送的udp包的数据部分 */
/* 松散源路由中间路由节点地址表,包括目的节点地址 */
u_int32_t gwlist[NGATEWAYS + 1];
int s; /* 接收icmp包的socket描述符 */
int sndsock; /* 发送udp包的socket描述符 */
struct sockaddr whereto; /* Who to try to reach */
struct sockaddr wherefrom; /* Who we are */
int packlen; /* total length of packet */
int minpacket; /* min ip packet size */
int maxpacket = 32 * 1024; /* max ip packet size */
char *prog;
char *source;
char *hostname;
int nprobes = 3; /* 发送udp探测包的次数 */
int max_ttl = 30;
int first_ttl = 1;
u_short ident;
u_short port = 32768 + 666; /* start udp dest port # for probe packets */
int options; /* socket options */
int waittime = 3; /* time to wait for response (in seconds) */
int nflag; /* print addresses numerically */
int optlen; /* length of ip options */
extern int optind;
extern int opterr;
extern char *optarg;
double deltaT(struct timeval *, struct timeval *);
void freehostinfo(struct hostinfo *);
void getaddr(u_int32_t *, char *);
struct hostinfo *gethostinfo(char *);
u_short in_cksum(u_short *, int);
char *inetname(struct in_addr);
int packet_ok(u_char *, int, struct sockaddr_in *, int);
char *pr_type(u_char);
void print(u_char *, int, struct sockaddr_in *);
void send_probe(int, int, struct timeval *);
int str2val(const char *, const char *, int, int);
void tvsub(struct timeval *, struct timeval *);
int wait_for_reply(int, struct sockaddr_in *, const struct timeval *);
void setsin(register struct sockaddr_in *sin, register u_int32_t addr);
/*------------------------------------------------------------------------
* wait_for_reply - 在指定时间waittime内等待传回的icmp数据包,如未获得,则返回0
*------------------------------------------------------------------------
*/
int wait_for_reply(register int sock, register struct sockaddr_in *fromp,
register const struct timeval *tp)
{
fd_set fds;
struct timeval now, wait;
struct timezone tz;
register int cc = 0;
int fromlen = sizeof(*fromp);
FD_ZERO(&fds);
FD_SET(sock, &fds);
wait.tv_sec = tp->tv_sec + waittime;
wait.tv_usec = tp->tv_usec;
(void)gettimeofday(&now, &tz);
tvsub(&wait, &now);
if (select(sock + 1, &fds, NULL, NULL, &wait) > 0)
cc = recvfrom(sock, (char *)packet, sizeof(packet), 0, (struct sockaddr *)fromp, &fromlen);
return(cc);
}
/*------------------------------------------------------------------------
* send_probe - 发送udp数据包,生存期为ttl,序号为seq
*------------------------------------------------------------------------
*/
void send_probe(register int seq, int ttl, register struct timeval *tp)
{
register int cc;
register struct udpiphdr *ui, *oui;//udp overlaid ip structure
struct ip tip;
outip->ip_off = 0;
outip->ip_p = IPPROTO_UDP;
outip->ip_len = packlen;
outip->ip_ttl = ttl;
outip->ip_sum = 0;
in_cksum((u_short *)outip, sizeof(*outip) + optlen);
if (outip->ip_sum == 0)
outip->ip_sum = 0xffff;
outudp->source = htons(ident);
outudp->dest = htons(port+seq);
outudp->check = 0;
//outudp->check = in_cksum((u_short *), packlen);
//if (outudp->check == 0)
// outudp->check = 0xffff;
outdata->seq = seq;
outdata->ttl = ttl;
outdata->tv = *tp;
//printf("\n outip->ip_hl=%d, outip->ip_v=%d, outip->ip_tos=%d, outip->ip_len=%d,",outip->ip_hl,outip->ip_v,outip->ip_tos,outip->ip_len);
//printf("\n outip->ip_id=%d, outip->ip_off=%d, outip->ip_ttl=%d, outip->ip_p=%d,",outip->ip_id, outip->ip_off,outip->ip_ttl, outip->ip_p);
//printf("\n outip->ip_sum=%d, outip->ip_src=%s, outip->ip_dst=%s,",outip->ip_sum, inet_ntoa(outip->ip_src), inet_ntoa(outip->ip_dst));
cc = sendto(sndsock, (char *)outip,
packlen, 0, &whereto, sizeof(whereto));
if (cc < 0 || cc != packlen) {
if (cc < 0)
errexit( "%s: sendto: %s\n",
prog, strerror(errno));
printf("%s: wrote %s %d chars, ret=%d\n",
prog, hostname, packlen, cc);
(void)fflush(stdout);
}
}
/*------------------------------------------------------------------------
* deltaT - 计算两个时间差值,得一double型的微秒值(ms)
*------------------------------------------------------------------------
*/
double deltaT(struct timeval *t1p, struct timeval *t2p)
{
register double dt;
dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
(double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
return (dt);
}
/*------------------------------------------------------------------------
* packet_ok - 获得接收的icmp包,根据icmp的type等返回不同的值
*------------------------------------------------------------------------
*/
int packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
register int seq)
{
register struct icmp *icp;
register u_char type, code;
register int hlen;
#ifndef ARCHAIC
register struct ip *ip;
ip = (struct ip *) buf;
hlen = ip->ip_hl << 2; /*计算ip包头长*/
if (cc < hlen + ICMP_MINLEN)
{
printf("packet too short (%d bytes) from %s\n", cc, inet_ntoa(from->sin_addr));
return (0);
}
//获得icmp头结构
cc -= hlen;
icp = (struct icmp *)(buf + hlen);
#else
icp = (struct icmp *)buf;
#endif
type = icp->icmp_type;
code = icp->icmp_code;
if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
type == ICMP_UNREACH || type == ICMP_ECHOREPLY)
{
register struct ip *hip;
register struct udphdr *up;
register struct icmp *hicmp;
hip = &icp->icmp_ip;
hlen = hip->ip_hl << 2;
up = (struct udphdr *)((u_char *)hip + hlen);
/* XXX 8 is a magic number */
if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
up->source == htons(ident) && up->dest == htons(port + seq))
return (type == ICMP_TIMXCEED ? -1 : code + 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -