net/icpmv4: Add dynamically registered ICMPv4 handlers

As it is done for ICMPv6. This will prove to be useful for implementing
an echo reply handler in a ping for instance.

Change-Id: I969a1da60f2a4ea59eee5c9983eb6e340923e2ef
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2017-03-24 09:14:10 +01:00 committed by Jukka Rissanen
commit 19af4eee4f
3 changed files with 63 additions and 20 deletions

View file

@ -24,6 +24,8 @@
#define BUF_WAIT_TIME K_SECONDS(1)
static sys_slist_t handlers;
static inline enum net_verdict handle_echo_request(struct net_buf *buf)
{
/* Note that we send the same data buffers back and just swap
@ -161,24 +163,6 @@ int net_icmpv4_send_echo_request(struct net_if *iface,
return -EIO;
}
enum net_verdict net_icmpv4_input(struct net_buf *buf, uint16_t len,
uint8_t type, uint8_t code)
{
ARG_UNUSED(code);
ARG_UNUSED(len);
net_stats_update_icmp_recv();
switch (type) {
case NET_ICMPV4_ECHO_REQUEST:
return handle_echo_request(buf);
}
net_stats_update_icmp_drop();
return NET_DROP;
}
int net_icmpv4_send_error(struct net_buf *orig, uint8_t type, uint8_t code)
{
struct net_buf *buf, *frag;
@ -283,3 +267,44 @@ drop_no_buf:
return err;
}
void net_icmpv4_register_handler(struct net_icmpv4_handler *handler)
{
sys_slist_prepend(&handlers, &handler->node);
}
void net_icmpv4_unregister_handler(struct net_icmpv4_handler *handler)
{
sys_slist_find_and_remove(&handlers, &handler->node);
}
enum net_verdict net_icmpv4_input(struct net_buf *buf, uint16_t len,
uint8_t type, uint8_t code)
{
struct net_icmpv4_handler *cb;
ARG_UNUSED(len);
net_stats_update_icmp_recv();
SYS_SLIST_FOR_EACH_CONTAINER(&handlers, cb, node) {
if (cb->type == type && (cb->code == code || cb->code == 0)) {
return cb->handler(buf);
}
}
net_stats_update_icmp_drop();
return NET_DROP;
}
static struct net_icmpv4_handler echo_request_handler = {
.type = NET_ICMPV4_ECHO_REQUEST,
.code = 0,
.handler = handle_echo_request,
};
void net_icmpv4_init(void)
{
net_icmpv4_register_handler(&echo_request_handler);
}

View file

@ -34,6 +34,15 @@ struct net_icmpv4_echo_req {
((struct net_icmpv4_echo_req *)(net_nbuf_icmp_data(buf) + \
sizeof(struct net_icmp_hdr)))
typedef enum net_verdict (*icmpv4_callback_handler_t)(struct net_buf *buf);
struct net_icmpv4_handler {
sys_snode_t node;
uint8_t type;
uint8_t code;
icmpv4_callback_handler_t handler;
};
/**
* @brief Send ICMPv4 error message.
* @param buf Network buffer that this error is related to.
@ -60,7 +69,17 @@ int net_icmpv4_send_echo_request(struct net_if *iface,
uint16_t identifier,
uint16_t sequence);
void net_icmpv4_register_handler(struct net_icmpv4_handler *handler);
void net_icmpv4_unregister_handler(struct net_icmpv4_handler *handler);
enum net_verdict net_icmpv4_input(struct net_buf *buf, uint16_t len,
uint8_t type, uint8_t code);
#if defined(CONFIG_NET_IPV4)
void net_icmpv4_init(void);
#else
#define net_icmpv4_init(...)
#endif
#endif /* __ICMPV4_H */

View file

@ -35,9 +35,7 @@
#include "icmpv6.h"
#include "ipv6.h"
#if defined(CONFIG_NET_IPV4)
#include "icmpv4.h"
#endif
#if defined(CONFIG_NET_DHCPV4)
#include "dhcpv4.h"
@ -757,6 +755,7 @@ int net_recv_data(struct net_if *iface, struct net_buf *buf)
static inline void l3_init(void)
{
net_icmpv4_init();
net_icmpv6_init();
net_ipv6_init();