现在的位置: 首页 > 综合 > 正文

Linux Trace实现

2018年07月16日 ⁄ 综合 ⁄ 共 9485字 ⁄ 字号 评论关闭

  1. #include <signal.h>  
      
  2. #include <netinet/in.h>    
  3. #include <netdb.h>    
  4. #include <sys/socket.h>    
  5. #include  <sys/types.h>     
  6. #include  <sys/times.h>     
  7. #include <sys/time.h>    
  8. #include  <sys/select.h>     
  9. #include <unistd.h>    
  10. #include <stdio.h>    
  11. #include <stdlib.h>     
  12. #include <fcntl.h>    
  13. #include <errno.h>    
  14.     
  15. struct ip    
  16. {    
  17. #if __BYTE_ORDER == __LITTLE_ENDIAN    
  18.     unsigned int ip_hl:4;                /* little-endian IP头长度(单位为32位)4位 */    
  19.     unsigned int ip_v:4;                 /* 版本号4 IP4用4 */    
  20. #endif    
  21. #if __BYTE_ORDER == __BIG_ENDIAN    
  22.     unsigned int ip_v:4;                /*  version */    
  23.     unsigned int ip_hl:4;               /*  header length */    
  24. #endif    
  25.     u_int8_t ip_tos;                    /* 服务类型  一般为0 */    
  26.     u_short ip_len;                     /* 数据总长度 (单位为32位) */    
  27.     u_short ip_id;                      /* 标识16 */    
  28.     u_short ip_off;                     /* 分段偏移*/    
  29. #define IP_RF 0x8000                    /*  reserved fragment标志 */    
  30. #define IP_DF 0x4000                    /*  dont fragment flag */    
  31. #define IP_MF 0x2000                    /*  more fragments flag */    
  32. #define IP_OFFMASK 0x1fff               /*  mask for fragmenting bits */    
  33.     u_int8_t ip_ttl;                     /* 生存时间 */    
  34.     u_int8_t ip_p;                      /* 传输协议 tcp是6 */    
  35.     u_short ip_sum;                     /* 头校验和 */    
  36.     struct in_addr ip_src, ip_dst;      /*  源地址 目标地址 */    
  37. };    
  38.     
  39. struct icmp                 
  40. {    
  41. u_int8_t  type;     /* 消息类型 */    
  42.     u_int8_t  code;     /* 代码类型 */    
  43.     u_int16_t checksum; /* 校验位 */    
  44.     union    
  45.     {    
  46.             u_char ih_pptr;         /* ICMP_PARAMPROB */    
  47.             struct in_addr ih_gwaddr;   /* 网关地址 */    
  48.             struct                  /* echo 数据包 */    
  49. {    
  50.             u_int16_t id;    
  51.             u_int16_t sequence;    
  52.             } echo;    
  53.     
  54.     u_int32_t ih_void;    
  55.     
  56.     struct ih_pmtu    
  57.     {    
  58.         u_int16_t ipm_void;    
  59.         u_int16_t ipm_nextmtu;    
  60. } ih_pmtu;    
  61.     
  62.     struct ih_rtradv    
  63.     {    
  64. u_int8_t irt_num_addrs;    
  65. u_int8_t irt_wpa;    
  66. u_int16_t irt_lifetime;    
  67.     } ih_rtradv;    
  68.   } un;    
  69. #define icmp_pptr   un.ih_pptr    
  70. #define icmp_gwaddr un.ih_gwaddr    
  71. #define icmp_id     un.echo.id    
  72. #define icmp_seq    un.echo.sequence    
  73. #define icmp_void   un.ih_void    
  74. #define icmp_pmvoid un.ih_pmtu.ipm_void    
  75. #define icmp_nextmtu    un.ih_pmtu.ipm_nextmtu    
  76. #define icmp_num_addrs  un.ih_rtradv.irt_num_addrs    
  77. #define icmp_wpa    un.ih_rtradv.irt_wpa    
  78. #define icmp_lifetime   un.ih_rtradv.irt_lifetime    
  79.       
  80. union    
  81. {    
  82.     struct    
  83.     {    
  84.             u_int32_t its_otime;    
  85. u_int32_t its_rtime;    
  86.         u_int32_t its_ttime;    
  87.     } id_ts;    
  88.     struct    
  89.     {    
  90.             struct ip idi_ip;    
  91.       /* 属性阿和紧跟它的64位数据 */    
  92.     } id_ip;    
  93.     
  94.   } icmp_dun;    
  95. #define icmp_otime  icmp_dun.id_ts.its_otime    
  96. #define icmp_rtime  icmp_dun.id_ts.its_rtime    
  97. #define icmp_ttime  icmp_dun.id_ts.its_ttime    
  98. #define icmp_ip     icmp_dun.id_ip.idi_ip    
  99. #define icmp_radv   icmp_dun.id_radv    
  100. #define icmp_mask   icmp_dun.id_mask    
  101. #define icmp_data   icmp_dun.id_data    
  102. };    
  103.     
  104.     
  105. struct ip_and_icmp    
  106. {    
  107. struct  ip iph;    
  108. struct  icmp icmph;    
  109. };    
  110.     
  111. /* 公共信息 */     
  112. char dstip[]="202.115.57.24";   /* 目标IP */    
  113. int errno;    
  114. int sends,waits;                /* 发送的socket 接收用的socket */    
  115. char info[500];                 /* 收到的icmp信息 */    
  116. struct icmp *eicmp;             /* TTL超时的icmp信息 */    
  117. struct ip_and_icmp *ip_icmp;        /* 收到的icmp原始信息 */    
  118. struct sockaddr_in toaddr,from;     /* 目标地址  来信息地址 */    
  119.     
  120. unsigned short csum (unsigned short *packet, int packlen)  /* 校验和计算 */    
  121. {    
  122.     register unsigned long sum = 0;    
  123.     
  124.     while (packlen > 1) {    
  125.         sum+= *(packet++);    
  126.         packlen-=2;    
  127.     }    
  128.     
  129.     if (packlen > 0)    
  130.         sum += *(unsigned char *)packet;    
  131.     
  132.     /* 这些将取决于位顺序 */    
  133.     while (sum >> 16)    
  134.         sum = (sum & 0xffff) + (sum >> 16);    
  135.     
  136.     return (unsigned short) ~sum;    
  137. }    
  138.     
  139. long int send_echo(struct sockaddr_in toaddr,int id,int sq,int size,int ttlset)    
  140. /* 发送icmp ECHO信息可定目标IP,ID号,SQ号和 IP的TTL大小, */    
  141. /* 出现返回-1,否则返回发送时的时间 */    
  142. void sendicmp()    
  143. {    
  144.  int lenth;    
  145.  long int nowtime;    
  146.  char icmpbuffer[200];    
  147.  struct  icmp  *icmph;    
  148.  memset(icmpbuffer,'a', 200);    
  149.  icmph=(struct  icmp *)icmpbuffer;    
  150.  sen=socket(AF_INET,SOCK_RAW,1);    
  151.  inet_aton(toip,&toaddr.sin_addr);   /* 字符串转入地址 */    
  152.  toaddr.sin_family = AF_INET;     
  153.  icmph->type=8;    
  154.  icmph->code=0;    
  155.  icmph->un.echo.id=htons(id);    
  156.  icmph->un.echo.sequence=htons(sq);    
  157.  icmph->checksum=htons(0);    
  158.  icmph->checksum=csum((unsigned short *)icmpbuffer,8+size);    
  159.  /* 发送的没有IP头信息 */    
  160.  setsockopt(sends, IPPROTO_IP, IP_TTL, &ttlset, sizeof(ttlset));  /* 设定TTL的大小 */    
  161.  lenth=sendto(sends,icmpbuffer,8+size,0,(struct sockaddr *)&toaddr,sizeof(toaddr));    
  162.  if (lenth>0)    
  163.  {    
  164.     nowtime=clock();    
  165. printf("send ICMO size %d at clock %d to %s  id=%d sq=%d  \n",    
  166. size,nowtime,inet_ntoa(toaddr.sin_addr),id,sq);    
  167.   }    
  168.   else    
  169.   {    
  170.     return -1;    
  171.   }    
  172.  return nowtime;    
  173. }    
  174.     
  175. /* 等对应的ICMP REPLY信息 指定IP,ID,SQ和等待时间。*/    
  176. /* 出现ttl超时或收到返回接收到时的时间,否则为-1 */    
  177. int wait_icmp(struct sockaddr_in toaddr,int id,int sq,clock_t timesize)    
  178. {    
  179. int length,fromlength;    
  180. clock_t endclock,recvclock;    
  181. inet_aton(toip,&toaddr.sin_addr);    
  182. memset(info,'A',500);    
  183. endclock=clock()+timesize;    
  184. while(clock()<endclock)    
  185.      {    
  186. fromlength=sizeof(from);    
  187.         length=recvfrom(waits,info,sizeof(info),0,    
  188. (struct sockaddr *)&from,&fromlength);    
  189.            
  190.        if ( length>0 && (from.sin_addr.s_addr==toaddr.sin_addr.s_addr)     
  191. && (ip_icmp->icmph.type==0) )    
  192.        {     
  193. recvclock=clock();    
  194. if ((ntohs(ip_icmp->icmph.un.echo.id)==id)     
  195. && (ntohs(ip_icmp->icmph.un.echo.sequence)==sq) )    
  196.             {    
  197. viewinfo(info,length);    
  198.             return recvclock;    
  199.             }    
  200.         } /* end length>0   
  201.         if (length>0 && (ip_icmp->icmph.type==11)&&(ntohs(eicmp->icmp_id)==id)    
  202. && (ntohs(eicmp->icmp_seq)==sq) )   /* 11为ttl超时 */    
  203.         {    
  204. recvclock=clock();    
  205.             return recvclock;    
  206.         }    
  207.     } /* end while */    
  208.     
  209. return -1;  /* 超时 */    
  210. }    
  211.     
  212. int main(int argc, char *argv[])    
  213. {    
  214. int rec,fromlen,n,sq,id,mstime,on=1,route=1,timeout=0,ttl;    
  215. long int iplong;    
  216. struct protoent *proto;    
  217. struct hostent *hp,*fromname;     
  218. clock_t start,sendtime,waittime;    
  219. start = clock();    
  220. ip_icmp=(struct ip_and_icmp *)info;    
  221. eicmp=(struct icmp *)(&ip_icmp->icmph.icmp_ip+1);    
  222. id=999;    
  223. mstime=2000;    
  224. if (argc<2)    
  225. {    
  226. printf("usage: %s ip_addrs time-out(millisecond)  \n",argv[0]);    
  227. printf("       %s testping 192.168.11.38 1000  \n",argv[0]);    
  228. printf("or     %s testping 192.168.11.38   \n",argv[0]);    
  229. return 0;    
  230. }    
  231. if (argc>2)    
  232. {    
  233. mstime=atoi(argv[2]);    
  234. if (mstime<1)    
  235.             {    
  236. printf("time-out(millisecond) is error \n");    
  237. exit (0);    
  238. }    
  239. printf("timo-out %d ms \n",mstime);    
  240. }    
  241. if ((hp = gethostbyname(argv[1])) == NULL)    /* 进入名字的分析 */    
  242. {    
  243. if ( (toaddr.sin_addr.s_addr=inet_addr(argv[1])) == -1)     
  244. {     
  245.                 fprintf(stderr, "%s: unknown host\n", argv[1]);    
  246. exit (0);    
  247.         }    
  248.         if (htonl(toaddr.sin_addr.s_addr)<0x1000001)    
  249.             {    
  250.                 printf("error ip %s \n",inet_ntoa(toaddr.sin_addr));    
  251.                 exit (0);    
  252.             }    
  253.      }     
  254. else     
  255. {    
  256. bcopy(hp->h_addr_list[0], &toaddr.sin_addr.s_addr, hp->h_length);    
  257. }     
  258. icmph=(struct  icmphdr *)icmpbuffer;    
  259. /* 初化接收和发送用的sends */    
  260. sends=socket(AF_INET,SOCK_RAW,1);    
  261. if(setsockopt(sends, IPPROTO_IP, IP_TTL, &on, sizeof(on)) < 0)    
  262. {    
  263. perror("This is sytem can't set TTL \n");     
  264. exit(1);     
  265.      }    
  266. waits=socket(AF_INET,SOCK_RAW,1);    
  267. fcntl(waits,F_SETFL,O_NDELAY);     
  268. proto = getprotobyname("icmp");      
  269. rec=socket(AF_INET,SOCK_RAW, proto->p_proto);    
  270. fcntl(rec,F_SETFL,O_NDELAY);     
  271. printf("%s \n",sys_errlist[errno]);    
  272. if (rec<0)    
  273. {    
  274. exit(0);    
  275. }    
  276. printf("now to wait... at %d \n",start);    
  277. /* waiting for packets */    
  278. inet_aton(dstip,&toaddr.sin_addr);    
  279. printf("send ICMO  to %s  \n",inet_ntoa(toaddr.sin_addr));    
  280.     id=999;         /* 初始化ID */    
  281. sq=0;           /* 初始化sq */    
  282. timeout=0;      /* time out次数 */    
  283. ttl=1;    /* ttl 值 */    
  284. while (1)    
  285. {    
  286. sq++;    
  287. sendtime=send_echo(toaddr,id,sq*100,20,ttl);    /* 发送ICMP ECHO */    
  288. /* 目标IP  编号  长度 ttl */    
  289. if (sendtime==-1)    
  290. {    
  291. printf("end error \n");    
  292. exit (0);    
  293. }    
  294. waittime=wait_icmp(toaddr,id,sq*100,mstime*1000); /* 接收ICMP ECHO */    
  295.     
  296. if (waittime==-1)    
  297. {    
  298. if (timeout==4)  /* 连续4次time out退出 */    
  299. {    
  300. printf("time out >3 end \n");    
  301. exit (1);    
  302. }    
  303. printf("time out \n");    
  304. timeout++;    
  305. }    
  306.      else     
  307. {    
  308. if (ip_icmp->icmph.type==0)    
  309. {    
  310. printf("%02d ",route);    
  311. printf(" %04d ms ",(waittime-sendtime)/1000);    
  312. printf("  %s ",inet_ntoa(ip_icmp->iph.ip_src));    
  313. printf("\n");    
  314. printf("\n");    
  315. printf("Trace complete \n");    
  316. break;    
  317. }    
  318. if (ip_icmp->icmph.type==11)    
  319. {    
  320. timeout=0;    
  321. ttl++;              /* 接收到一个ttl超时信息TTL值加1 */    
  322. printf("%02d ",route);    
  323. printf(" %04d ms ",(waittime-sendtime)/1000);    
  324. printf("  %s ",inet_ntoa(ip_icmp->iph.ip_src));    
  325. printf("\n");    
  326. route++;    
  327. }    
  328. /* end else waittime==-1 */    
  329. /* end for */    
  330. }    

转自:http://read.pudn.com/downloads135/doc/574330/3786/CODES/example08/traceroute.c__.htm

抱歉!评论已关闭.