?? traceroute.c
字號:
#include <signal.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/times.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
struct ip
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ip_hl:4; /* little-endian IP頭長度(單位為32位)4位 */
unsigned int ip_v:4; /* 版本號4 IP4用4 */
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned int ip_v:4; /* version */
unsigned int ip_hl:4; /* header length */
#endif
u_int8_t ip_tos; /* 服務類型 一般為0 */
u_short ip_len; /* 數據總長度 (單位為32位) */
u_short ip_id; /* 標識16 */
u_short ip_off; /* 分段偏移*/
#define IP_RF 0x8000 /* reserved fragment標志 */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_int8_t ip_ttl; /* 生存時間 */
u_int8_t ip_p; /* 傳輸協議 tcp是6 */
u_short ip_sum; /* 頭校驗和 */
struct in_addr ip_src, ip_dst; /* 源地址 目標地址 */
};
struct icmp
{
u_int8_t type; /* 消息類型 */
u_int8_t code; /* 代碼類型 */
u_int16_t checksum; /* 校驗位 */
union
{
u_char ih_pptr; /* ICMP_PARAMPROB */
struct in_addr ih_gwaddr; /* 網關地址 */
struct /* echo 數據包 */
{
u_int16_t id;
u_int16_t sequence;
} echo;
u_int32_t ih_void;
struct ih_pmtu
{
u_int16_t ipm_void;
u_int16_t ipm_nextmtu;
} ih_pmtu;
struct ih_rtradv
{
u_int8_t irt_num_addrs;
u_int8_t irt_wpa;
u_int16_t irt_lifetime;
} ih_rtradv;
} un;
#define icmp_pptr un.ih_pptr
#define icmp_gwaddr un.ih_gwaddr
#define icmp_id un.echo.id
#define icmp_seq un.echo.sequence
#define icmp_void un.ih_void
#define icmp_pmvoid un.ih_pmtu.ipm_void
#define icmp_nextmtu un.ih_pmtu.ipm_nextmtu
#define icmp_num_addrs un.ih_rtradv.irt_num_addrs
#define icmp_wpa un.ih_rtradv.irt_wpa
#define icmp_lifetime un.ih_rtradv.irt_lifetime
union
{
struct
{
u_int32_t its_otime;
u_int32_t its_rtime;
u_int32_t its_ttime;
} id_ts;
struct
{
struct ip idi_ip;
/* 屬性阿和緊跟它的64位數據 */
} id_ip;
} icmp_dun;
#define icmp_otime icmp_dun.id_ts.its_otime
#define icmp_rtime icmp_dun.id_ts.its_rtime
#define icmp_ttime icmp_dun.id_ts.its_ttime
#define icmp_ip icmp_dun.id_ip.idi_ip
#define icmp_radv icmp_dun.id_radv
#define icmp_mask icmp_dun.id_mask
#define icmp_data icmp_dun.id_data
};
struct ip_and_icmp
{
struct ip iph;
struct icmp icmph;
};
/* 公共信息 */
char dstip[]="202.115.57.24"; /* 目標IP */
int errno;
int sends,waits; /* 發送的socket 接收用的socket */
char info[500]; /* 收到的icmp信息 */
struct icmp *eicmp; /* TTL超時的icmp信息 */
struct ip_and_icmp *ip_icmp; /* 收到的icmp原始信息 */
struct sockaddr_in toaddr,from; /* 目標地址 來信息地址 */
unsigned short csum (unsigned short *packet, int packlen) /* 校驗和計算 */
{
register unsigned long sum = 0;
while (packlen > 1) {
sum+= *(packet++);
packlen-=2;
}
if (packlen > 0)
sum += *(unsigned char *)packet;
/* 這些將取決于位順序 */
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
return (unsigned short) ~sum;
}
long int send_echo(struct sockaddr_in toaddr,int id,int sq,int size,int ttlset)
/* 發送icmp ECHO信息可定目標IP,ID號,SQ號和 IP的TTL大小, */
/* 出現返回-1,否則返回發送時的時間 */
void sendicmp()
{
int lenth;
long int nowtime;
char icmpbuffer[200];
struct icmp *icmph;
memset(icmpbuffer,'a', 200);
icmph=(struct icmp *)icmpbuffer;
sen=socket(AF_INET,SOCK_RAW,1);
inet_aton(toip,&toaddr.sin_addr); /* 字符串轉入地址 */
toaddr.sin_family = AF_INET;
icmph->type=8;
icmph->code=0;
icmph->un.echo.id=htons(id);
icmph->un.echo.sequence=htons(sq);
icmph->checksum=htons(0);
icmph->checksum=csum((unsigned short *)icmpbuffer,8+size);
/* 發送的沒有IP頭信息 */
setsockopt(sends, IPPROTO_IP, IP_TTL, &ttlset, sizeof(ttlset)); /* 設定TTL的大小 */
lenth=sendto(sends,icmpbuffer,8+size,0,(struct sockaddr *)&toaddr,sizeof(toaddr));
if (lenth>0)
{
nowtime=clock();
printf("send ICMO size %d at clock %d to %s id=%d sq=%d \n",
size,nowtime,inet_ntoa(toaddr.sin_addr),id,sq);
}
else
{
return -1;
}
return nowtime;
}
/* 等對應的ICMP REPLY信息 指定IP,ID,SQ和等待時間。*/
/* 出現ttl超時或收到返回接收到時的時間,否則為-1 */
int wait_icmp(struct sockaddr_in toaddr,int id,int sq,clock_t timesize)
{
int length,fromlength;
clock_t endclock,recvclock;
inet_aton(toip,&toaddr.sin_addr);
memset(info,'A',500);
endclock=clock()+timesize;
while(clock()<endclock)
{
fromlength=sizeof(from);
length=recvfrom(waits,info,sizeof(info),0,
(struct sockaddr *)&from,&fromlength);
if ( length>0 && (from.sin_addr.s_addr==toaddr.sin_addr.s_addr)
&& (ip_icmp->icmph.type==0) )
{
recvclock=clock();
if ((ntohs(ip_icmp->icmph.un.echo.id)==id)
&& (ntohs(ip_icmp->icmph.un.echo.sequence)==sq) )
{
viewinfo(info,length);
return recvclock;
}
} /* end length>0
if (length>0 && (ip_icmp->icmph.type==11)&&(ntohs(eicmp->icmp_id)==id)
&& (ntohs(eicmp->icmp_seq)==sq) ) /* 11為ttl超時 */
{
recvclock=clock();
return recvclock;
}
} /* end while */
return -1; /* 超時 */
}
int main(int argc, char *argv[])
{
int rec,fromlen,n,sq,id,mstime,on=1,route=1,timeout=0,ttl;
long int iplong;
struct protoent *proto;
struct hostent *hp,*fromname;
clock_t start,sendtime,waittime;
start = clock();
ip_icmp=(struct ip_and_icmp *)info;
eicmp=(struct icmp *)(&ip_icmp->icmph.icmp_ip+1);
id=999;
mstime=2000;
if (argc<2)
{
printf("usage: %s ip_addrs time-out(millisecond) \n",argv[0]);
printf(" %s testping 192.168.11.38 1000 \n",argv[0]);
printf("or %s testping 192.168.11.38 \n",argv[0]);
return 0;
}
if (argc>2)
{
mstime=atoi(argv[2]);
if (mstime<1)
{
printf("time-out(millisecond) is error \n");
exit (0);
}
printf("timo-out %d ms \n",mstime);
}
if ((hp = gethostbyname(argv[1])) == NULL) /* 進入名字的分析 */
{
if ( (toaddr.sin_addr.s_addr=inet_addr(argv[1])) == -1)
{
fprintf(stderr, "%s: unknown host\n", argv[1]);
exit (0);
}
if (htonl(toaddr.sin_addr.s_addr)<0x1000001)
{
printf("error ip %s \n",inet_ntoa(toaddr.sin_addr));
exit (0);
}
}
else
{
bcopy(hp->h_addr_list[0], &toaddr.sin_addr.s_addr, hp->h_length);
}
icmph=(struct icmphdr *)icmpbuffer;
/* 初化接收和發送用的sends */
sends=socket(AF_INET,SOCK_RAW,1);
if(setsockopt(sends, IPPROTO_IP, IP_TTL, &on, sizeof(on)) < 0)
{
perror("This is sytem can't set TTL \n");
exit(1);
}
waits=socket(AF_INET,SOCK_RAW,1);
fcntl(waits,F_SETFL,O_NDELAY);
proto = getprotobyname("icmp");
rec=socket(AF_INET,SOCK_RAW, proto->p_proto);
fcntl(rec,F_SETFL,O_NDELAY);
printf("%s \n",sys_errlist[errno]);
if (rec<0)
{
exit(0);
}
printf("now to wait... at %d \n",start);
/* waiting for packets */
inet_aton(dstip,&toaddr.sin_addr);
printf("send ICMO to %s \n",inet_ntoa(toaddr.sin_addr));
id=999; /* 初始化ID */
sq=0; /* 初始化sq */
timeout=0; /* time out次數 */
ttl=1; /* ttl 值 */
while (1)
{
sq++;
sendtime=send_echo(toaddr,id,sq*100,20,ttl); /* 發送ICMP ECHO */
/* 目標IP 編號 長度 ttl */
if (sendtime==-1)
{
printf("end error \n");
exit (0);
}
waittime=wait_icmp(toaddr,id,sq*100,mstime*1000); /* 接收ICMP ECHO */
if (waittime==-1)
{
if (timeout==4) /* 連續4次time out退出 */
{
printf("time out >3 end \n");
exit (1);
}
printf("time out \n");
timeout++;
}
else
{
if (ip_icmp->icmph.type==0)
{
printf("%02d ",route);
printf(" %04d ms ",(waittime-sendtime)/1000);
printf(" %s ",inet_ntoa(ip_icmp->iph.ip_src));
printf("\n");
printf("\n");
printf("Trace complete \n");
break;
}
if (ip_icmp->icmph.type==11)
{
timeout=0;
ttl++; /* 接收到一個ttl超時信息TTL值加1 */
printf("%02d ",route);
printf(" %04d ms ",(waittime-sendtime)/1000);
printf(" %s ",inet_ntoa(ip_icmp->iph.ip_src));
printf("\n");
route++;
}
} /* end else waittime==-1 */
} /* end for */
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -