Added an API for getting a callback when a ping reply is received.

This commit is contained in:
Adam Dunkels 2013-11-16 16:23:43 +01:00
parent 75cbf4f48a
commit 9114cd3215
3 changed files with 150 additions and 4 deletions

View file

@ -71,6 +71,8 @@ static uip_ipaddr_t tmp_ipaddr;
#include "rpl/rpl.h"
#endif /* UIP_CONF_IPV6_RPL */
LIST(echo_reply_callback_list);
#if UIP_CONF_IPV6
/*---------------------------------------------------------------------------*/
void
@ -238,7 +240,7 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
UIP_STAT(++uip_stat.icmp.sent);
PRINTF("Sending ICMPv6 ERROR message to");
PRINTF("Sending ICMPv6 ERROR message type %d code %d to", type, code);
PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
@ -248,7 +250,7 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
/*---------------------------------------------------------------------------*/
void
uip_icmp6_send(uip_ipaddr_t *dest, int type, int code, int payload_len)
uip_icmp6_send(const uip_ipaddr_t *dest, int type, int code, int payload_len)
{
UIP_IP_BUF->vtc = 0x60;
@ -272,6 +274,92 @@ uip_icmp6_send(uip_ipaddr_t *dest, int type, int code, int payload_len)
tcpip_ipv6_output();
}
/*---------------------------------------------------------------------------*/
void
uip_icmp6_echo_reply_input(void)
{
int ttl;
uip_ipaddr_t sender;
#if UIP_CONF_IPV6_RPL
uint8_t temp_ext_len;
#endif /* UIP_CONF_IPV6_RPL */
uip_ipaddr_copy(&sender, &UIP_IP_BUF->srcipaddr);
ttl = UIP_IP_BUF->ttl;
if(uip_ext_len > 0) {
#if UIP_CONF_IPV6_RPL
if((temp_ext_len = rpl_invert_header())) {
/* If there were other extension headers*/
UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6;
if (uip_ext_len != temp_ext_len) {
uip_len -= (uip_ext_len - temp_ext_len);
UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
/* move the echo reply payload (starting after the icmp
* header) to the new location in the reply. The shift is
* equal to the length of the remaining extension headers
* present Note: UIP_ICMP_BUF still points to the echo reply
* at this stage
*/
memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - (uip_ext_len - temp_ext_len),
(uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN,
(uip_len - UIP_IPH_LEN - temp_ext_len - UIP_ICMPH_LEN));
}
uip_ext_len = temp_ext_len;
uip_len -= uip_ext_len;
} else {
#endif /* UIP_CONF_IPV6_RPL */
/* If there were extension headers*/
UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
uip_len -= uip_ext_len;
UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
/* move the echo reply payload (starting after the icmp header)
* to the new location in the reply. The shift is equal to the
* length of the extension headers present Note: UIP_ICMP_BUF
* still points to the echo request at this stage
*/
memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len,
(uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN,
(uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN));
uip_ext_len = 0;
#if UIP_CONF_IPV6_RPL
}
#endif /* UIP_CONF_IPV6_RPL */
}
/* Call all registered applications to let them know an echo reply
has been received. */
{
struct uip_icmp6_echo_reply_notification *n;
for(n = list_head(echo_reply_callback_list);
n != NULL;
n = list_item_next(n)) {
if(n->callback != NULL) {
n->callback(&sender, ttl,
(uint8_t *)&UIP_ICMP_BUF[sizeof(struct uip_icmp_hdr)],
uip_len - sizeof(struct uip_icmp_hdr) - UIP_IPH_LEN);
}
}
}
return;
}
/*---------------------------------------------------------------------------*/
void
uip_icmp6_echo_reply_callback_add(struct uip_icmp6_echo_reply_notification *n,
uip_icmp6_echo_reply_callback_t c)
{
if(n != NULL && c != NULL) {
n->callback = c;
list_add(echo_reply_callback_list, n);
}
}
/*---------------------------------------------------------------------------*/
void
uip_icmp6_echo_reply_callback_rm(struct uip_icmp6_echo_reply_notification *n)
{
list_remove(echo_reply_callback_list, n);
}
/*---------------------------------------------------------------------------*/
/** @} */
#endif /* UIP_CONF_IPV6 */