I ran into a number of issues using the PING app from the contrib section.
I am using RAW mode. The PING app just did requests, so I wrote some
additional code for it to handle replies now as well. That seems to work
fine, but working on this I then noticed some other issues. The previous
first routine ping_prepare_echo() was doing the checksum at the wrong place.
It needs to be last, after the sample data is built, since the checksum
covers that area as well. Also, there was a pbuf leak in the ping_recv()
routine. It needs to free the main pbuf, or after enough pings, the pool is
consumed. The significant portions of my code changes are given below.
Regards, Chris.
// Prepare a ECHO ICMP REQUEST
static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) {
int i;
ICMPH_TYPE_SET(iecho,ICMP_ECHO);
ICMPH_CODE_SET(iecho, 0);
iecho->chksum = 0;
iecho->id = PING_ID;
iecho->seqno = htons(++ping_seq_num);
// fill the additional data buffer with some data
for(i = 0; i < PING_DATA_SIZE; i++) {
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = i+48; // easier to
look at ASCII
}
iecho->chksum = inet_chksum(iecho, len); // CNS, checksum needs to be done
after data
}
// CNS, Prepare a ECHO REPLY
static void ping_prepare_reply( struct icmp_echo_hdr *ireply, u16_t len,
struct icmp_echo_hdr *iecho) {
int i,m;
ICMPH_TYPE_SET(ireply,ICMP_ER); // echo reply
ICMPH_CODE_SET(ireply, 0);
ireply->id = iecho->id; // copy ID from request
ireply->seqno = iecho->seqno; // copy seqno from request
ireply->chksum = 0;
// copy data from echo request
// Ping Size may not be standard, so calc from actual msg size and sub
header
m = len-sizeof(struct icmp_echo_hdr);
for(i = 0; i < m; i++) {
((char*)ireply)[sizeof(struct icmp_echo_hdr) + i] =
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i];
}
ireply->chksum = inet_chksum(ireply, len);
}
// Ping Rcve using the raw ip
static u8_t ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, struct
ip_addr *addr) {
LWIP_UNUSED_ARG(arg);
struct icmp_echo_hdr *iecho;
struct icmp_echo_hdr *ireply;
struct pbuf *r;
int hlen;
struct in_addr val;
if (pbuf_header( p, -PBUF_IP_HLEN)==0) {
iecho = p->payload;
// CNS this section generates REPLY to any ECHO REQUEST
if (iecho->_type_code == ICMP_ECHO) { // rcvd echo, generate echo reply
hlen = p->tot_len; // length of ping request, typ 40 bytes
r = pbuf_alloc(PBUF_IP, hlen, PBUF_RAM); // new pbuf
if (r!=NULL) {
ireply=r->payload;
ping_prepare_reply(ireply, hlen,iecho);
raw_sendto(pcb, r, addr);
pbuf_free(r); // dump new pbuf
r = NULL;
}
}
// this section handles replies to our ECHO REQUEST
if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
val.s_addr = addr->addr;
printf("Ping Reply %s\n", inet_ntoa(val));
LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
ip_addr_debug_print(PING_DEBUG, addr);
LWIP_DEBUGF( PING_DEBUG, (" %lu ms\n", (sys_now()-ping_time)));
// do some ping result processing
PING_RESULT(1);
}
}
pbuf_free(p); // CNS, free the org pbuf, otherwise leak!
p=NULL;
return 1; // eat the event
}
_______________________________________________
lwip-users mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/lwip-users