Merge pull request #504 from adamdunkels/push/ping-reply-api

A ping reply API
This commit is contained in:
Adam Dunkels 2014-01-26 14:03:21 -08:00
commit 17d48c6d7a
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" #include "rpl/rpl.h"
#endif /* UIP_CONF_IPV6_RPL */ #endif /* UIP_CONF_IPV6_RPL */
LIST(echo_reply_callback_list);
#if UIP_CONF_IPV6 #if UIP_CONF_IPV6
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
@ -238,7 +240,7 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
UIP_STAT(++uip_stat.icmp.sent); 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); PRINT6ADDR(&UIP_IP_BUF->destipaddr);
PRINTF("from"); PRINTF("from");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
@ -248,7 +250,7 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void 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; 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(); 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 */ #endif /* UIP_CONF_IPV6 */

View file

@ -113,6 +113,15 @@ typedef struct uip_icmp6_error{
void void
uip_icmp6_echo_request_input(void); uip_icmp6_echo_request_input(void);
/** \
* brief Process an echo reply
*
* Perform a few checks, then call applications to inform that an echo
* reply has been received.
*/
void
uip_icmp6_echo_reply_input(void);
/** /**
* \brief Send an icmpv6 error message * \brief Send an icmpv6 error message
* \param type type of the error message * \param type type of the error message
@ -130,7 +139,55 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param);
* \param payload_len length of the payload * \param payload_len length of the payload
*/ */
void 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);
typedef void (* uip_icmp6_echo_reply_callback_t)(uip_ipaddr_t *source,
uint8_t ttl,
uint8_t *data,
uint16_t datalen);
struct uip_icmp6_echo_reply_notification {
struct uip_icmp6_echo_reply_notification *next;
uip_icmp6_echo_reply_callback_t callback;
};
/**
* \brief Add a callback function for ping replies
* \param n A struct uip_icmp6_echo_reply_notification that must have been allocated by the caller
* \param c A pointer to the callback function to be called
*
* This function adds a callback function to the list of
* callback functions that are called when an ICMP echo
* reply (ping reply) is received. This is used when
* implementing a ping protocol: attach a callback
* function to the ping reply, then send out a ping packet
* with uip_icmp6_send().
*
* The caller must have statically allocated a struct
* uip_icmp6_echo_reply_notification to hold the internal
* state of the callback function.
*
* When a ping reply packet is received, all registered
* callback functions are called. The callback functions
* must not modify the contents of the uIP buffer.
*/
void
uip_icmp6_echo_reply_callback_add(struct uip_icmp6_echo_reply_notification *n,
uip_icmp6_echo_reply_callback_t c);
/**
* \brief Remove a callback function for ping replies
* \param n A struct uip_icmp6_echo_reply_notification that must have been previously added with uip_icmp6_echo_reply_callback_add()
*
* This function removes a callback function from the list of
* callback functions that are called when an ICMP echo
* reply (ping reply) is received.
*/
void
uip_icmp6_echo_reply_callback_rm(struct uip_icmp6_echo_reply_notification *n);
/** @} */ /** @} */

View file

@ -1431,7 +1431,8 @@ uip_process(uint8_t flag)
uip_icmp6_echo_request_input(); uip_icmp6_echo_request_input();
break; break;
case ICMP6_ECHO_REPLY: case ICMP6_ECHO_REPLY:
/** \note We don't implement any application callback for now */ /** Call echo reply input function. */
uip_icmp6_echo_reply_input();
PRINTF("Received an icmp6 echo reply\n"); PRINTF("Received an icmp6 echo reply\n");
UIP_STAT(++uip_stat.icmp.recv); UIP_STAT(++uip_stat.icmp.recv);
uip_len = 0; uip_len = 0;