From 86133b8404c8d599ebf9bd5f8276f6bd0f5aa6bf Mon Sep 17 00:00:00 2001 From: Martine Lenders <mlenders@inf.fu-berlin.de> Date: Wed, 1 Apr 2015 17:35:23 +0200 Subject: [PATCH] ng_icmpv6_echo: initial import --- Makefile.dep | 5 + sys/Makefile | 3 + sys/include/net/ng_icmpv6.h | 1 + sys/include/net/ng_icmpv6/echo.h | 129 ++++++++++++++++++ sys/net/network_layer/ng_icmpv6/echo/Makefile | 3 + .../ng_icmpv6/echo/ng_icmpv6_echo.c | 119 ++++++++++++++++ sys/net/network_layer/ng_icmpv6/ng_icmpv6.c | 4 +- 7 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 sys/include/net/ng_icmpv6/echo.h create mode 100644 sys/net/network_layer/ng_icmpv6/echo/Makefile create mode 100644 sys/net/network_layer/ng_icmpv6/echo/ng_icmpv6_echo.c diff --git a/Makefile.dep b/Makefile.dep index 3fe29f8597..1ba0400568 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -53,6 +53,11 @@ ifneq (,$(filter ng_sixlowpan_ctx,$(USEMODULE))) USEMODULE += vtimer endif +ifneq (,$(filter ng_icmpv6_echo,$(USEMODULE))) + USEMODULE += ng_icmpv6 + USEMODULE += ng_netbase +endif + ifneq (,$(filter ng_icmpv6,$(USEMODULE))) USEMODULE += ng_ipv6 endif diff --git a/sys/Makefile b/sys/Makefile index 3ec57b53d6..33569987c6 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -65,6 +65,9 @@ endif ifneq (,$(filter ng_icmpv6,$(USEMODULE))) DIRS += net/network_layer/ng_icmpv6 endif +ifneq (,$(filter ng_icmpv6_echo,$(USEMODULE))) + DIRS += net/network_layer/ng_icmpv6/echo +endif ifneq (,$(filter ng_ipv6,$(USEMODULE))) DIRS += net/network_layer/ng_ipv6 endif diff --git a/sys/include/net/ng_icmpv6.h b/sys/include/net/ng_icmpv6.h index daec59a27d..ba590b20de 100644 --- a/sys/include/net/ng_icmpv6.h +++ b/sys/include/net/ng_icmpv6.h @@ -34,6 +34,7 @@ #include "net/ng_nettype.h" #include "net/ng_pkt.h" +#include "net/ng_icmpv6/echo.h" #include "net/ng_icmpv6/error.h" #include "net/ng_icmpv6/types.h" diff --git a/sys/include/net/ng_icmpv6/echo.h b/sys/include/net/ng_icmpv6/echo.h new file mode 100644 index 0000000000..e7470746a3 --- /dev/null +++ b/sys/include/net/ng_icmpv6/echo.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de> + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup net_ng_icmpv6_echo ICMPv6 echo messages + * @ingroup net_ng_icmpv6 + * @brief ICMPv6 echo request and reply + * @{ + * + * @file + * @brief ICMPv6 echo message definitions + * + * @author Martine Lenders <mlenders@inf.fu-berlin.de> + */ +#ifndef NG_ICMPV6_ECHO_H_ +#define NG_ICMPV6_ECHO_H_ + +#include <inttypes.h> + +#include "byteorder.h" +#include "kernel_types.h" +#include "net/ng_icmpv6/types.h" +#include "net/ng_ipv6/hdr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Echo request and response message format. + * @extends ng_icmpv6_hdr_t + * + * @see <a href="https://tools.ietf.org/html/rfc4443#section-4.1"> + * RFC 4443, section 4.1 + * </a> + * @see <a href="https://tools.ietf.org/html/rfc4443#section-4.2"> + * RFC 4443, section 4.2 + * </a> + */ +typedef struct __attribute__((packed)) { + uint8_t type; /**< message type */ + uint8_t code; /**< message code */ + network_uint16_t csum; /**< checksum */ + network_uint16_t id; /**< identifier */ + network_uint16_t seq; /**< Sequence number */ +} ng_icmpv6_echo_t; + +/** + * @brief Builds an ICMPv6 echo message of type @p type for sending. + * + * @param[in] type Type of the echo message. Expected to be either + * NG_ICMPV6_ECHO_REQ or NG_ICMPV6_ECHO_REP. + * @param[in] id ID for the echo message in host byte-order + * @param[in] seq Sequence number for the echo message in host byte-order + * @param[in] data Payload for the echo message + * @param[in] data_len Length of @p data + * + * @return The echo message on success + * @return NULL, on failure + */ +ng_pktsnip_t *ng_icmpv6_echo_build(uint8_t type, uint16_t id, uint16_t seq, + uint8_t *data, size_t data_len); + +/** + * @brief Builds an ICMPv6 echo request for sending. + * + * @see <a href="https://tools.ietf.org/html/rfc4443#section-4.1"> + * RFC 4443, section 4.1 + * </a> + * + * @param[in] id ID for the echo request in host byte-order + * @param[in] seq Sequence number for the echo request in host byte-order + * @param[in] data Payload for the echo request + * @param[in] data_len Length of @p data + * + * @return The echo request message on success + * @return NULL, on failure + */ +static inline ng_pktsnip_t *ng_icmpv6_echo_req_build(uint16_t id, uint16_t seq, + uint8_t *data, size_t data_len) +{ + return ng_icmpv6_echo_build(NG_ICMPV6_ECHO_REQ, id, seq, data, data_len); +} + +/** + * @brief Builds an ICMPv6 echo reply for sending. + * + * @see <a href="https://tools.ietf.org/html/rfc4443#section-4.2"> + * RFC 4443, section 4.2 + * </a> + * + * @param[in] id ID for the echo reply in host byte-order + * @param[in] seq Sequence number for the echo reply in host byte-order + * @param[in] data Payload for the echo reply + * @param[in] data_len Length of @p data + * + * @return The echo reply message on success + * @return NULL, on failure + */ +static inline ng_pktsnip_t *ng_icmpv6_echo_rep_build(uint16_t id, uint16_t seq, + uint8_t *data, size_t data_len) +{ + return ng_icmpv6_echo_build(NG_ICMPV6_ECHO_REP, id, seq, data, data_len); +} + + +/** + * @brief ICMPv6 echo request handler + * + * @param[in] iface The interface the echo requuest was received on. + * @param[in] ipv6_hdr The IPv6 header of the echo request. + * @param[in] echo The Echo Request message. + * @param[in] len Length of the echo request message (ng_ipv6_hdr_t::len + * of @p ipv6_hdr minus length of extension headers). + */ +void ng_icmpv6_echo_req_handle(kernel_pid_t iface, ng_ipv6_hdr_t *ipv6_hdr, + ng_icmpv6_echo_t *echo, uint16_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* NG_ICMPV6_ECHO_H_ */ +/** @} */ diff --git a/sys/net/network_layer/ng_icmpv6/echo/Makefile b/sys/net/network_layer/ng_icmpv6/echo/Makefile new file mode 100644 index 0000000000..f30fd54da6 --- /dev/null +++ b/sys/net/network_layer/ng_icmpv6/echo/Makefile @@ -0,0 +1,3 @@ +MODULE = ng_icmpv6_echo + +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/network_layer/ng_icmpv6/echo/ng_icmpv6_echo.c b/sys/net/network_layer/ng_icmpv6/echo/ng_icmpv6_echo.c new file mode 100644 index 0000000000..24f4701acb --- /dev/null +++ b/sys/net/network_layer/ng_icmpv6/echo/ng_icmpv6_echo.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de> + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file + */ + +#include "net/ng_netbase.h" + +#include "net/ng_icmpv6.h" +#include "net/ng_icmpv6/echo.h" +#include "utlist.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +ng_pktsnip_t *ng_icmpv6_echo_build(uint8_t type, uint16_t id, uint16_t seq, + uint8_t *data, size_t data_len) +{ + ng_pktsnip_t *pkt; + ng_icmpv6_echo_t *echo; + + if ((pkt = ng_icmpv6_build(type, 0, data_len + sizeof(ng_icmpv6_echo_t))) == NULL) { + return NULL; + } + + DEBUG("icmpv6_echo: Building echo message with type=%" PRIu8 "id=%" PRIu16 + ", seq=%" PRIu16, type, id, seq); + echo = (ng_icmpv6_echo_t *)pkt->data; + echo->id = byteorder_htons(id >> 16); + echo->seq = byteorder_htons(seq); + + if (data != NULL) { + memcpy(echo + 1, data, data_len); +#if defined(MODULE_OD) && ENABLE_DEBUG + DEBUG(", payload:\n"); + od_hex_dump(data, data_len, OD_WIDTH_DEFAULT); +#endif + DEBUG("\n"); + } +#if ENABLE_DEBUG + else { + DEBUG("\n"); + } +#endif + + return pkt; +} + +void ng_icmpv6_echo_req_handle(kernel_pid_t iface, ng_ipv6_hdr_t *ipv6_hdr, + ng_icmpv6_echo_t *echo, uint16_t len) +{ + uint8_t *payload = ((uint8_t *)echo) + sizeof(ng_icmpv6_echo_t); + ng_pktsnip_t *hdr, *pkt; + ng_netreg_entry_t *sendto = NULL; + + if ((echo == NULL) || (len < sizeof(ng_icmpv6_echo_t))) { + DEBUG("icmpv6_echo: echo was NULL or len (%" PRIu16 + ") was < sizeof(ng_icmpv6_echo_t)\n", len); + return; + } + + pkt = _echo_build(NG_ICMPV6_ECHO_REP, byteorder_ntohs(echo->id), + byteorder_ntohs(echo->seq), payload, + len - sizeof(ng_icmpv6_echo_t)); + + if (pkt == NULL) { + DEBUG("icmpv6_echo: no space left in packet buffer\n"); + return; + } + + if (ng_ipv6_addr_is_multicast(&ipv6_hdr->dst)) { + hdr = ng_ipv6_hdr_build(pkt, NULL, 0, (uint8_t *)&ipv6_hdr->src, + sizeof(ng_ipv6_addr_t)); + } + else { + hdr = ng_ipv6_hdr_build(pkt, (uint8_t *)&ipv6_hdr->dst, + sizeof(ng_ipv6_addr_t), (uint8_t *)&ipv6_hdr->src, + sizeof(ng_ipv6_addr_t)); + } + + if (hdr == NULL) { + DEBUG("icmpv6_echo: no space left in packet buffer\n"); + ng_pktbuf_release(pkt); + return; + } + + pkt = hdr; + hdr = ng_netif_hdr_build(NULL, 0, NULL, 0); + + ((ng_netif_hdr_t *)hdr->data)->if_pid = iface; + + LL_PREPEND(pkt, hdr); + + sendto = ng_netreg_lookup(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL); + + if (sendto == NULL) { + DEBUG("icmpv6_echo: no receivers for IPv6 packets\n"); + ng_pktbuf_release(pkt); + return; + } + + /* ICMPv6 is not interested anymore so `- 1` */ + ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL) - 1); + + while (sendto != NULL) { + ng_netapi_send(sendto->pid, pkt); + sendto = ng_netreg_getnext(sendto); + } +} + +/** @} */ diff --git a/sys/net/network_layer/ng_icmpv6/ng_icmpv6.c b/sys/net/network_layer/ng_icmpv6/ng_icmpv6.c index f75e57b5aa..fb93c5a44d 100644 --- a/sys/net/network_layer/ng_icmpv6/ng_icmpv6.c +++ b/sys/net/network_layer/ng_icmpv6/ng_icmpv6.c @@ -28,6 +28,7 @@ #include "utlist.h" #include "net/ng_icmpv6.h" +#include "net/ng_icmpv6/echo.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -77,7 +78,8 @@ void ng_icmpv6_demux(kernel_pid_t iface, ng_pktsnip_t *pkt) #ifdef MODULE_NG_ICMPV6_ECHO case NG_ICMPV6_ECHO_REQ: DEBUG("icmpv6: handle echo request.\n"); - /* TODO */ + ng_icmpv6_echo_req_handle(iface, (ng_ipv6_hdr_t *)ipv6->data, + (ng_icmpv6_echo_t *)hdr, icmpv6->size); break; #endif -- GitLab