免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2802 | 回复: 5
打印 上一主题 下一主题

关于icmp报文的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-27 16:58 |只看该作者 |倒序浏览
我编写了如下一段ping代码,但是总是出错,检验函数都按照标准规范来写的,采用sendto与recvfrom来发送与接收,但是在测试的时候就是出现如下错误:
1)ping内部循环 (127.0.0.1)有时能够通,有时却显示因为icmp_type或是icmp_id不一致而ping不通;
2)外网无法ping通。
请各位大虾指点,搞了很久都没解决这些问题。郁闷ing。。。。。。

论坛徽章:
0
2 [报告]
发表于 2008-11-27 17:24 |只看该作者
你的代码呢?

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
3 [报告]
发表于 2008-11-27 17:51 |只看该作者

回复 #1 letueo 的帖子

直接发上代码说明问题

论坛徽章:
0
4 [报告]
发表于 2008-11-28 18:58 |只看该作者

代码现在帖出

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <setjmp.h>


#define datalen 56

#define MAX(a,b)  ((a)>(b))?(a)b)
#define MIN(a,b)  ((a)>(b))?(b)a)


/*=====================================================
======================================================*/
u_short ChkSum(u_short *pIcmpData,int iDataLen)
{
  u_short iSum;
  u_short iOldByte=0;
  unsigned short *w=pIcmpData;
  int len=iDataLen;
  iSum=0;
  
  while(len>1)
    {
      iSum +=*w++;
      len-=2;
    }
  
  if(len==1)
    {
      *(u_char*)(&iOldByte)=*(u_char*)w;
      iSum+=iOldByte;
    }
  iSum=(iSum>>16)+(iSum&0xffff);
  iSum+=(iSum>>16);
  iOldByte=~iSum;
  printf("chsum is %d\n",iOldByte);
  return(iOldByte);
}

/*=====================================================
=====================================================*/
long time_now()
{
  struct timeval now;
  long lPassed;
  gettimeofday(&now,0);
  lPassed=now.tv_sec*1000000 + now.tv_usec;//化为微妙计算
  return lPassed;
}
int time=1;
char * host;
char * prog;
extern errno;
long lSendTime;
u_short seq;
//int iTimeOut;
int sock,sent=0,recvd;
float max,min,total;
u_long lHostIp;
struct sockaddr_in it;
struct sockaddr_in from;
pid_t pid;
int fromlen=sizeof(from);
int ping();
void stat();
main(int argc,char ** argv)
{
  struct hostent*h;
  char buf1[200];
  char dst_host[32];
  int i,namelen;
  int flag;
  struct ip* pIpHead;
  struct icmp* pIcmpHead;
  struct protoent *protocol;
  int size1=50*1024;
  pid=getpid();

  if(argc<2)
    {
      printf("usage:%s[-timeout]host}IP\n",argv[0]);
      exit(0);
    }
  prog=argv[0];
  host=argc==2?argv[1]:argv[2];
  //iTimeOut=argc==2?1:atoi(argv[1]);
  if((protocol=getprotobyname("icmp")==NULL)
    {
      perror("getprotobyname";
      exit(1);
    }
  if((sock=socket(AF_INET,SOCK_RAW,protocol->p_proto))<0)
    {
      perror("socket";
      exit(2);
    }
   setsockopt(sock,SOL_SOCKET,SO_RCVBUF,&size1,sizeof(size1));
   setuid(getuid);
  bzero(&it,sizeof(it));
  it.sin_family==AF_INET;
  
  if((lHostIp=inet_addr(host))!=INADDR_NONE)
    {
      it.sin_addr.s_addr=lHostIp;
      strcpy(dst_host,host);
    }
  else if(h=gethostbyname(host))
    {
      bcopy(h->h_addr,&it.sin_addr,h->h_length);
      sprintf(dst_host,"%s(%s)",host,inet_ntoa(it.sin_addr));
    }
  else
    {
      fprintf(stderr,"bad IP or host\n";
      exit(3);
    }
  namelen=sizeof(it);
  printf("\nDigger pinging %s,send %d bytes\n",dst_host,datalen);
  seq=0;
  sigset(SIGINT,&stat);
  for(;
    {
      register size;
      register u_char ttl;
      register float delta;
      register iIpHeadLen;
      int len1;
      
     ping();
     size=recvfrom(sock,buf1,sizeof(buf1),0,(struct sockaddr *)&from,&fromlen);
     if(size==-1 && errno==EINTR)
        {
          continue;
        }
      delta=(float)((time_now()-lSendTime)/1000.0);
   
      pIpHead=(struct ip*)buf1;
      iIpHeadLen=(int)((pIpHead->ip_hl & 0x0f)<<2);//ip_hl中存放的是IP头部的长度,以4字节为单位。所以需要右移2位。
      len1=size-iIpHeadLen;
   
      if(len1<
        {
          printf("ICMP packets length is less than 8\n";
          return (-1);
        }
   
      ttl=pIpHead->ip_ttl;
      pIcmpHead=(struct icmp*)(buf1+iIpHeadLen);//越过IP报头,直接访问ICMP报头
   
      if(pIcmpHead->icmp_type!=ICMP_ECHOREPLY)
        {
          fprintf(stderr,"i will continue for ICMPHEAD->type\n";
          continue;
        }
     
      if(pIcmpHead->icmp_id!=pid || pIcmpHead->icmp_seq!=seq)
        {
          fprintf(stderr,"i will continue for ICMPHEAD->id/seq\n";
          continue;
        }
      sprintf(buf1,"icmp_seq=%u bytes=%d ttl=%d",pIcmpHead->icmp_seq,len1,ttl);
      fprintf(stderr,"reply from %s:%s time=%f ms\n",host,buf1,delta);
      max=MAX(delta,max);
      min=min?MIN(delta,min):delta;
      total+=delta;
      ++recvd;
      ++seq;
      printf("and now seq is %d\n",seq);
    }
}

/*======================================================================
  ======================================================================*/
ping()
{
  char buf[200];
  int iPacketSize;
  struct timeval *tval;
  long data=20;
  
  struct icmp*pIcmpHead1=(struct icmp*)buf;
  pIcmpHead1->icmp_type=ICMP_ECHO;
  pIcmpHead1->icmp_code=0;
  pIcmpHead1->icmp_id=pid;
  pIcmpHead1->icmp_seq=seq;
  pIcmpHead1->icmp_cksum=0;
  fprintf(stderr,"but icmp_seq is %d\n",seq);
  //data=(long *)pIcmpHead1->icmp_data;
  tval=(struct timeval *)pIcmpHead1->icmp_data;
  gettimeofday(tval,NULL);
  iPacketSize=datalen+8;
  pIcmpHead1->icmp_cksum=ChkSum((u_short*)pIcmpHead1,iPacketSize);
  lSendTime=time_now();
  if(sendto(sock,buf,iPacketSize,0,(struct sockaddr*)&it,sizeof(it))<0)
    {
      perror("send failed";
      exit(6);
    }
  printf("this time is No.%d\n",time++);
  //sleep(1);
  ++sent;

}

/*================================================================
  =================================================================*/
void stat()
{
  if(sent)
    {
      printf("\n----%s ping statistics summerized by Digger----\n",host);
      printf("%d packets sent,%d packets received,%.2f%%lost\n",sent,recvd,(float)(sent-recvd)/(float)sent*100);
    }
  if(recvd)
    {
      printf("round_trip min/avg/max:%f/%f/%f ms\n\n",min,total/recvd,max);
    }
  exit(0);
}

论坛徽章:
3
戌狗
日期:2014-09-10 17:07:162015年辞旧岁徽章
日期:2015-03-03 16:54:15wusuopu
日期:2016-06-17 17:43:45
5 [报告]
发表于 2008-11-28 20:04 |只看该作者
警告很多
it.sin_family==AF_INET;
...

论坛徽章:
0
6 [报告]
发表于 2008-11-30 19:54 |只看该作者
原帖由 letueo 于 2008-11-27 16:58 发表
我编写了如下一段ping代码,但是总是出错,检验函数都按照标准规范来写的,采用sendto与recvfrom来发送与接收,但是在测试的时候就是出现如下错误:
1)ping内部循环 (127.0.0.1)有时能够通,有时却显示因为ic ...

参考下我的这篇帖子
http://linux.chinaunix.net/bbs/viewthread.php?tid=876233
附件中的fakeping.c就是一个自己做的ping程序,发ICMP包并接受echo reply消息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP