本帖最后由 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
|
|