-
#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 */
- }
Linux Trace实现
最新推荐文章于 2024-05-10 14:23:21 发布