net: Add ICMPv6 handler
The host will be able to respond to ICMPv6 messages. An echo-request handler is implemented and it will send echo-reply when needed. Change-Id: I08f4703bab5cf3e95d3ae722ebc7a386d22fe17e Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
4445e53f1e
commit
7c78925050
6 changed files with 207 additions and 2 deletions
|
@ -129,7 +129,14 @@ config NETWORK_IP_STACK_DEBUG_IPV6_DS
|
||||||
|
|
||||||
config NETWORK_IP_STACK_DEBUG_IPV6_ICMPV6
|
config NETWORK_IP_STACK_DEBUG_IPV6_ICMPV6
|
||||||
bool "Debug ICMPv6"
|
bool "Debug ICMPv6"
|
||||||
depends on NETWORKING_WITH_IPV6 || NET_IPV6
|
depends on NETWORKING_WITH_IPV6
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enables ICMPv6 code part to output debug messages
|
||||||
|
|
||||||
|
config NETWORK_IP_STACK_DEBUG_ICMPV6
|
||||||
|
bool "Debug ICMPv6"
|
||||||
|
depends on NET_IPV6
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
Enables ICMPv6 code part to output debug messages
|
Enables ICMPv6 code part to output debug messages
|
||||||
|
|
|
@ -4,3 +4,5 @@ obj-y = net_core.o \
|
||||||
net_context.o \
|
net_context.o \
|
||||||
nbuf.o \
|
nbuf.o \
|
||||||
utils.o
|
utils.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_NET_IPV6) += icmpv6.o
|
||||||
|
|
136
net/yaip/icmpv6.c
Normal file
136
net/yaip/icmpv6.c
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/** @file
|
||||||
|
* @brief ICMPv6 related functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NETWORK_IP_STACK_DEBUG_ICMPV6
|
||||||
|
#define SYS_LOG_DOMAIN "net/icmpv6"
|
||||||
|
#define NET_DEBUG 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <misc/slist.h>
|
||||||
|
#include <net/net_core.h>
|
||||||
|
#include <net/nbuf.h>
|
||||||
|
#include <net/net_if.h>
|
||||||
|
#include <net/net_stats.h>
|
||||||
|
#include "net_private.h"
|
||||||
|
#include "icmpv6.h"
|
||||||
|
|
||||||
|
static sys_slist_t handlers;
|
||||||
|
|
||||||
|
void net_icmpv6_register_handler(struct net_icmpv6_handler *handler)
|
||||||
|
{
|
||||||
|
sys_slist_prepend(&handlers, &handler->node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum net_verdict handle_echo_request(struct net_buf *buf)
|
||||||
|
{
|
||||||
|
/* Note that we send the same data buffers back and just swap
|
||||||
|
* the addresses etc.
|
||||||
|
*/
|
||||||
|
#if NET_DEBUG > 0
|
||||||
|
char out[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
|
||||||
|
|
||||||
|
snprintf(out, sizeof(out),
|
||||||
|
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->dst));
|
||||||
|
NET_DBG("Received Echo Request from %s to %s",
|
||||||
|
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->src), out);
|
||||||
|
#endif /* NET_DEBUG > 0 */
|
||||||
|
|
||||||
|
if (net_is_ipv6_addr_mcast(&NET_IPV6_BUF(buf)->dst)) {
|
||||||
|
net_ipaddr_copy(&NET_IPV6_BUF(buf)->dst,
|
||||||
|
&NET_IPV6_BUF(buf)->src);
|
||||||
|
|
||||||
|
net_ipaddr_copy(&NET_IPV6_BUF(buf)->src,
|
||||||
|
net_if_ipv6_select_src_addr(net_nbuf_iface(buf),
|
||||||
|
&NET_IPV6_BUF(buf)->dst));
|
||||||
|
} else {
|
||||||
|
struct in6_addr addr;
|
||||||
|
|
||||||
|
net_ipaddr_copy(&addr, &NET_IPV6_BUF(buf)->src);
|
||||||
|
net_ipaddr_copy(&NET_IPV6_BUF(buf)->src,
|
||||||
|
&NET_IPV6_BUF(buf)->dst);
|
||||||
|
net_ipaddr_copy(&NET_IPV6_BUF(buf)->dst, &addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
NET_IPV6_BUF(buf)->hop_limit =
|
||||||
|
net_if_ipv6_get_hop_limit(net_nbuf_iface(buf));
|
||||||
|
|
||||||
|
NET_ICMP_BUF(buf)->type = NET_ICMPV6_ECHO_REPLY;
|
||||||
|
NET_ICMP_BUF(buf)->code = 0;
|
||||||
|
NET_ICMP_BUF(buf)->chksum = 0;
|
||||||
|
NET_ICMP_BUF(buf)->chksum = ~net_calc_chksum_icmpv6(buf);
|
||||||
|
|
||||||
|
#if NET_DEBUG > 0
|
||||||
|
snprintf(out, sizeof(out),
|
||||||
|
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->dst));
|
||||||
|
NET_DBG("Sending Echo Reply from %s to %s",
|
||||||
|
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->src), out);
|
||||||
|
#endif /* NET_DEBUG > 0 */
|
||||||
|
|
||||||
|
if (net_send_data(buf) < 0) {
|
||||||
|
NET_STATS(++net_stats.icmp.drop);
|
||||||
|
return NET_DROP;
|
||||||
|
}
|
||||||
|
|
||||||
|
NET_STATS(++net_stats.icmp.sent);
|
||||||
|
|
||||||
|
return NET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum net_verdict net_icmpv6_input(struct net_buf *buf, uint16_t len,
|
||||||
|
uint8_t type, uint8_t code)
|
||||||
|
{
|
||||||
|
sys_snode_t *node;
|
||||||
|
struct net_icmpv6_handler *cb;
|
||||||
|
|
||||||
|
SYS_SLIST_FOR_EACH_NODE(&handlers, node) {
|
||||||
|
cb = (struct net_icmpv6_handler *)node;
|
||||||
|
|
||||||
|
if (!cb) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cb->type == type && (cb->code == code || cb->code == 0)) {
|
||||||
|
NET_STATS(++net_stats.icmp.recv);
|
||||||
|
return cb->handler(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NET_DROP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct net_icmpv6_handler echo_request_handler = {
|
||||||
|
.type = NET_ICMPV6_ECHO_REQUEST,
|
||||||
|
.code = 0,
|
||||||
|
.handler = handle_echo_request,
|
||||||
|
};
|
||||||
|
|
||||||
|
void net_icmpv6_init(void)
|
||||||
|
{
|
||||||
|
static bool is_initialized;
|
||||||
|
|
||||||
|
if (is_initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_icmpv6_register_handler(&echo_request_handler);
|
||||||
|
|
||||||
|
is_initialized = true;
|
||||||
|
}
|
49
net/yaip/icmpv6.h
Normal file
49
net/yaip/icmpv6.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/** @file
|
||||||
|
@brief ICMPv6 handler
|
||||||
|
|
||||||
|
This is not to be included by the application.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ICMPV6_H
|
||||||
|
#define __ICMPV6_H
|
||||||
|
|
||||||
|
#include <misc/slist.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <net/net_ip.h>
|
||||||
|
#include <net/nbuf.h>
|
||||||
|
|
||||||
|
#define NET_ICMPV6_ECHO_REQUEST 128
|
||||||
|
#define NET_ICMPV6_ECHO_REPLY 129
|
||||||
|
|
||||||
|
typedef enum net_verdict (*icmpv6_callback_handler_t)(struct net_buf *buf);
|
||||||
|
|
||||||
|
struct net_icmpv6_handler {
|
||||||
|
sys_snode_t node;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t code;
|
||||||
|
icmpv6_callback_handler_t handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
void net_icmpv6_register_handler(struct net_icmpv6_handler *handler);
|
||||||
|
enum net_verdict net_icmpv6_input(struct net_buf *buf, uint16_t len,
|
||||||
|
uint8_t type, uint8_t code);
|
||||||
|
void net_icmpv6_init(void);
|
||||||
|
|
||||||
|
#endif /* __ICMPV6_H */
|
|
@ -41,6 +41,10 @@
|
||||||
|
|
||||||
#include "net_private.h"
|
#include "net_private.h"
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_IPV6)
|
||||||
|
#include "icmpv6.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Stack for the rx fiber.
|
/* Stack for the rx fiber.
|
||||||
*/
|
*/
|
||||||
#if !defined(CONFIG_NET_RX_STACK_SIZE)
|
#if !defined(CONFIG_NET_RX_STACK_SIZE)
|
||||||
|
@ -323,7 +327,9 @@ int net_recv_data(struct net_if *iface, struct net_buf *buf)
|
||||||
|
|
||||||
static int network_initialization(void)
|
static int network_initialization(void)
|
||||||
{
|
{
|
||||||
|
#if defined(CONFIG_NET_IPV6)
|
||||||
|
net_icmpv6_init();
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,11 @@ extern char *net_sprint_ip_addr_buf(uint8_t *ip, int ip_len,
|
||||||
char *buf, int buflen);
|
char *buf, int buflen);
|
||||||
extern uint16_t net_calc_chksum(struct net_buf *buf, uint8_t proto);
|
extern uint16_t net_calc_chksum(struct net_buf *buf, uint8_t proto);
|
||||||
|
|
||||||
|
static inline uint16_t net_calc_chksum_icmpv6(struct net_buf *buf)
|
||||||
|
{
|
||||||
|
return net_calc_chksum(buf, IPPROTO_ICMPV6);
|
||||||
|
}
|
||||||
|
|
||||||
#if NET_DEBUG > 0
|
#if NET_DEBUG > 0
|
||||||
static inline char *net_sprint_ll_addr(uint8_t *ll, uint8_t ll_len)
|
static inline char *net_sprint_ll_addr(uint8_t *ll, uint8_t ll_len)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue