打印

stm32f107+lwip 可以ping通其他电脑无法ping通网关

[复制链接]
17033|30
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
610095871|  楼主 | 2012-12-26 14:15 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 610095871 于 2013-7-16 16:58 编辑

      最近开始在stm32f107上学习lwip,遇到好多问题,也发了几篇帖子,现在又遇到问题了,搞了两天没搞出来,进入正题, 我想在lwip上实现ping命令,开始我用etharp_output发送arp命令给局域网内的其他PC机,抓包软件能够看出PC机正确响应,之后我就开始修改udp发送函数,将udp的头换成icmp的头,之后给其他pc机发送ping命令,抓包软件能看到PC机正确响应,之后我就去ping外网,发现ping不同,看资料说如果是外网的话会通过网关往外网发送数据,抓包软件也可以看到开发板给网关发送了arp命令,但是网关没有响应,我又用PC机在cmd界面中发送arp -d 抓包软件抓到pc机给网关发送的arp数据包,并且网关正确响应,之后我对比了开发板给网关发的arp数据包,除了源地址源mac不一样外其他的都一样的,不知道有人遇到这样的问题没,我用的是官网提供的lwip例程,而且例程已经跑通,希望有遇到同样问题的朋友能给点提示,真诚表示感谢。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//主要代码
err_t
udp_sendicmp(struct udp_pcb *pcb, struct pbuf *p,
  struct ip_addr *dst_ip, u16_t dst_port)
{
  struct netif *netif;
  LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 3, ("udp_send\n"));
  /* find the outgoing network interface for this packet */
#if LWIP_IGMP
  netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip)):(dst_ip));
#else
  netif = ip_route(dst_ip);
#endif /* LWIP_IGMP */
  /* no outgoing network interface could be found? */
  if (netif == NULL) {
    LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%"X32_F"\n", dst_ip->addr));
    UDP_STATS_INC(udp.rterr);
    return ERR_RTE;
  }
  return udp_sendto_ping(pcb, p, dst_ip, dst_port, netif);
}
err_t
udp_sendto_ping(struct udp_pcb *pcb, struct pbuf *p,
  struct ip_addr *dst_ip, u16_t dst_port, struct netif *netif)
{
  struct udp_hdr *udphdr;
  struct ip_addr *src_ip;
  err_t err;
  struct pbuf *q; /* q will be sent down the stack */
  struct icmp_echo_hdr *icmphdr; //kaishui

  /* not enough space to add an UDP header to first pbuf in given p chain? */
  if (pbuf_header(p, sizeof(struct icmp_echo_hdr))) {
    /* allocate header in a separate new pbuf */
    q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr), PBUF_RAM);
    /* new header pbuf could not be allocated? */
    /* chain header q in front of given pbuf p */
    pbuf_chain(q, p);
    /* first pbuf q points to header pbuf */
  }
  
  /* q now represents the packet to be sent */
  icmphdr = q->payload;
  icmphdr->type = 8; //类型
  icmphdr->code = 0; //code
  icmphdr->id =htons(0x0200)  ;     //id
  icmphdr->seqno =htons(0x5800); //报文序列号
   icmphdr->chksum = 0;  //校验和清0
   icmphdr->chksum = inet_chksum(p->payload, 10);//从算校验和
  /* PCB local address is IP_ANY_ADDR? */
  if (ip_addr_isany(&pcb->local_ip)) {
    /* use outgoing network interface IP address as source address */
    src_ip = &(netif->ip_addr);
  } else {
    /* check if UDP PCB local IP address is correct
     * this could be an old address if netif->ip_addr has changed */
   
    /* use UDP PCB local IP address as source address */
    src_ip = &(pcb->local_ip);
  }

    err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_ICMP, netif);
  snmp_inc_udpoutdatagrams();
  /* did we chain a separate header pbuf earlier? */
  if (q != p) {
    /* free the header pbuf */
    pbuf_free(q);
    q = NULL;
    /* p is still referenced by the caller, and will live on */
  }
  UDP_STATS_INC(udp.xmit);
  return err;
}
这个是我参考lwip中的函数改过来的

下面这些是我试验的代码
struct udp_pcb *UDPpcb;
u8 UDPData[10]={0};
struct pbuf *p;
void PingInit(void)
{

struct ip_addr ipaddr;

unsigned int port = 2000; //69
p = pbuf_alloc(PBUF_RAW,10,PBUF_RAM);
   p->payload=(void *)UDPData;
IP4_ADDR(&ipaddr,0,0,0,0);  
UDPpcb = udp_new();
udp_bind(UDPpcb,&ipaddr, port);
}
void ICMP_Ping(void)
{
unsigned char  i=0;
   struct ip_addr dstipaddr;

   
IP4_ADDR(&dstipaddr,InternetCmd.icmp_ip[0],InternetCmd.icmp_ip[1],InternetCmd.icmp_ip[2],InternetCmd.icmp_ip[3]); //www.baidu.com
//  IP4_ADDR(&dstipaddr,192,168,1,109); //www.baidu.com
  for(i=0;i<12;i++)
  {
      
  udp_sendicmp(UDPpcb,p,&dstipaddr,2000);
  
  }
     
}

在发送代码中有个计算校验和的那里是有问题的,所以数据内容要全为0 这样校验和才能正确,利用抓包工具看下就可以了,另外访问外网的话,需要知道外网的IP,当然利用Lwip的dns也可以通过域名来测试。
希望能帮到大家,因为我对以太网太小白了,所以没有继续深入的研究。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、
另外对ucgui感兴趣的可以来
UCGUI源码学习中---Q群295214484



沙发
610095871|  楼主 | 2012-12-26 15:11 | 只看该作者
:Q

使用特权

评论回复
板凳
videre| | 2012-12-26 15:22 | 只看该作者
ping外网的话,要首先arp获取网关的mac,发送icmp包时,目的IP是外网IP,但目的mac地址应该是网关的mac

如果上述没有问题,再看下下路由器的配置吧,有可能路由器启用了防火墙,设置了禁止icmp

使用特权

评论回复
地板
610095871|  楼主 | 2012-12-26 15:30 | 只看该作者
videre 发表于 2012-12-26 15:22
ping外网的话,要首先arp获取网关的mac,发送icmp包时,目的IP是外网IP,但目的mac地址应该是网关的mac

如 ...


是的  现在的问题就是无法获取网关的mac地址,但是抓包感觉是正常的

使用特权

评论回复
5
610095871|  楼主 | 2012-12-26 15:37 | 只看该作者
103是PC机  108是开发板 1是网关

pc和开发板分别发arp给网关,网关相应了103即PC机的arp命令
下面是两次arp的抓包数据截图



使用特权

评论回复
6
videre| | 2012-12-26 15:50 | 只看该作者
本帖最后由 videre 于 2012-12-26 15:52 编辑

帧头看起来没什么问题

第二个图,arp报文一共多少个字节?也是60byte吗

使用特权

评论回复
7
610095871|  楼主 | 2012-12-26 16:01 | 只看该作者
videre 发表于 2012-12-26 15:50
帧头看起来没什么问题

第二个图,arp报文一共多少个字节?也是60byte吗

我刚看了 PC给网关发的是42Byte   我看看是不是这里的问题 表示感谢

使用特权

评论回复
8
videre| | 2012-12-26 16:03 | 只看该作者
缺少18byte的Trailer

使用特权

评论回复
9
610095871|  楼主 | 2012-12-26 16:06 | 只看该作者
videre 发表于 2012-12-26 16:03
缺少18byte的Trailer

不过我用开发板去给pc机(IP最后为103)发arp命令 也是60字节 多18字节,PC给网管发的话 没有那18字节。难道给网关发arp不能有那18字节的trailer???

使用特权

评论回复
10
videre| | 2012-12-26 16:14 | 只看该作者
填上试试看吧,我有印象我碰到过这样的问题,但想不起细节来了,按道理42个byte的请求报文是没问题的,也可能pc和路由器对协议的处理方式不同

使用特权

评论回复
11
610095871|  楼主 | 2012-12-26 16:19 | 只看该作者
videre 发表于 2012-12-26 16:14
填上试试看吧,我有印象我碰到过这样的问题,但想不起细节来了,按道理42个byte的请求报文是没问题的,也可 ...

PC给网关发arp的是42Byte
开发板给网关发arp是60Byte  
我刚查了下资料,说帧最小为64Byte  其中42Byte + 4Byte(校验)+18Byte trailer
不过貌似校验的4字节被省略了, 如果你想起当时你是怎么解决的请留言,表示感谢。

使用特权

评论回复
12
610095871|  楼主 | 2012-12-26 17:03 | 只看该作者
又一天过去了,依然找不到原因

使用特权

评论回复
13
eydj2008| | 2012-12-26 20:14 | 只看该作者
不要急 要一个问题一个问题的排 除

使用特权

评论回复
14
610095871|  楼主 | 2012-12-27 16:05 | 只看该作者
今天又测试了下  我用上位机把处理接收arp数据包的函数进行了全面的监控,并把每次收到的arp响应包,中的各个参数打印出来,发现了一个很奇怪的现象,就是 我给网关发的arp命令,网关每次都有回应,而且包中包含了网关的mac地址,奇怪的是我我打印出来的只是网关的前4个字节的mac地址,也就是说少了两个字节的mac地址,还有抓包软件居然没找到网关的arp响应,同时我检测到opcode=2应该就是arp响应了。不知道为什么抓包软件没抓到回应开发板的包。。。。。继续

使用特权

评论回复
15
610095871|  楼主 | 2012-12-28 11:42 | 只看该作者
哈哈 问题解决了 貌似一开始就没什么问题,出错的原因在于我对抓包软件的理解,一开始我本想用串口来监控的,后来网上找到了一个抓包软件,就用抓包软件来监控,不过貌似抓包软件只能抓取局域网内的数据 对于外网如果数据不是给PC机的貌似抓不了,应该是软件的适用范围问题,今天我全部用串口来打印,并且吧icmp的响应功能完善了,收到响应分析包获取TTL 打印出来结果,发现ping外网一点问题没有,感谢各位的指导,这次的学习对我来说是一次很好的挑战和启发,对于没有接触过以太网或者刚接触以太网的新手来说,尝试是最直接的方法。

使用特权

评论回复
16
382430325| | 2013-3-27 13:02 | 只看该作者
楼主 你好 我也在弄一个用LWIP实现ping功能,不知道是否可以赐教

使用特权

评论回复
17
wanwank| | 2013-4-1 16:13 | 只看该作者
382430325 发表于 2013-3-27 13:02
楼主 你好 我也在弄一个用LWIP实现ping功能,不知道是否可以赐教

最近也在做这个 socket 连公网连不上  局域网可以 现在  想ping公网的一个IP 你是怎么实现的啊

使用特权

评论回复
18
wfmartin28| | 2013-4-7 09:38 | 只看该作者
楼主你好!能不能将你的程序分享一下!

使用特权

评论回复
19
弯弯的月神| | 2013-6-12 23:52 | 只看该作者
我最近在学,感觉一头雾水

使用特权

评论回复
20
610095871|  楼主 | 2013-7-16 16:58 | 只看该作者
主要的那部分代码已经共享了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:UCGUI源码学习中---Q群295214484 http://ucgui.taobao.com

27

主题

323

帖子

10

粉丝