diff --git a/Makefile.dep b/Makefile.dep index 85facbec086ed29ef269891945974f0739580736..57b2e52e1bac956ebdbbc25429582b3320f331ba 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -112,6 +112,18 @@ ifneq (,$(filter ng_ipv6_hdr,$(USEMODULE))) USEMODULE += ng_pktbuf endif +ifneq (,$(filter ng_rpl_srh,$(USEMODULE))) + USEMODULE += ng_ipv6_ext_rh +endif + +ifneq (,$(filter ng_ipv6_ext_rh,$(USEMODULE))) + USEMODULE += ng_ipv6_ext +endif + +ifneq (,$(filter ng_ipv6_ext,$(USEMODULE))) + USEMODULE += ng_ipv6 +endif + ifneq (,$(filter ng_ipv6_router,$(USEMODULE))) USEMODULE += ng_ipv6 endif diff --git a/sys/Makefile b/sys/Makefile index b5ce3cd2bc0395cd1c71963e786aae1ea5a9244d..d48d954c22257c6ddd89cf7d77e537b797375c48 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -74,6 +74,9 @@ endif ifneq (,$(filter ng_ipv6_addr,$(USEMODULE))) DIRS += net/network_layer/ng_ipv6/addr endif +ifneq (,$(filter ng_ipv6_ext,$(USEMODULE))) + DIRS += net/network_layer/ng_ipv6/ext +endif ifneq (,$(filter ng_ipv6_hdr,$(USEMODULE))) DIRS += net/network_layer/ng_ipv6/hdr endif diff --git a/sys/include/net/ng_ipv6.h b/sys/include/net/ng_ipv6.h index b7415de35c3b44529c81f79a6f4fee4973c110e5..b76107d5bc4e137c8b386737b541a9a05140b8a9 100644 --- a/sys/include/net/ng_ipv6.h +++ b/sys/include/net/ng_ipv6.h @@ -33,6 +33,7 @@ #include "thread.h" #include "net/ng_ipv6/addr.h" +#include "net/ng_ipv6/ext.h" #include "net/ng_ipv6/hdr.h" #include "net/ng_ipv6/nc.h" #include "net/ng_ipv6/netif.h" diff --git a/sys/include/net/ng_ipv6/ext.h b/sys/include/net/ng_ipv6/ext.h new file mode 100644 index 0000000000000000000000000000000000000000..f86c9f0d75b462cb466d273531887246352c002d --- /dev/null +++ b/sys/include/net/ng_ipv6/ext.h @@ -0,0 +1,105 @@ +/* + * 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_ipv6_ext IPv6 extension headers. + * @ingroup net_ng_ipv6 + * @brief Implementation of IPv6 extension headers + * @see <a href="https://tools.ietf.org/html/rfc2460#section-4"> + * RFC 2460, section 4 + * </a> + * @{ + * + * @file + * @brief Definititions for IPv6 extension headers + * + * @author Martine Lenders <mlenders@inf.fu-berlin.de> + */ + + +#ifndef NG_IPV6_EXT_H_ +#define NG_IPV6_EXT_H_ + +#include <inttypes.h> +#include <stdbool.h> + +#include "byteorder.h" +#include "kernel_types.h" +#include "net/ng_pkt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NG_IPV6_EXT_LEN_UNIT (8U) /**< Unit in byte for the extension header's + * length field */ + +/** + * @brief IPv6 extension headers. + * + * @see <a href="https://tools.ietf.org/html/rfc2460#section-4"> + * RFC 2460, section 4.1 + * </a> + */ +typedef struct __attribute__((packed)) { + uint8_t nh; /**< next header */ + uint8_t len; /**< length in 8 octets without first octet */ +} ng_ipv6_ext_t; + +/** + * @brief Demultiplex extension headers according to @p nh. + * + * @internal + * + * @param[in] iface The receiving interface. + * @param[in] pkt A packet. + * @param[in] nh A protocol number (see @ref net_ng_protnum). + * + * @return true, on success. + * @return false, on failure. + */ +bool ng_ipv6_ext_demux(kernel_pid_t iface, ng_pktsnip_t *pkt, + uint8_t nh); + +/** + * @brief Gets the next extension header in a packet. + * + * @param[in] ext The current extension header. + * + * @return The next extension header. + */ +static inline ng_ipv6_ext_t *ng_ipv6_ext_get_next(ng_ipv6_ext_t *ext) +{ + return (ng_ipv6_ext_t *)((uint8_t *)(ext) + + (ext->len * NG_IPV6_EXT_LEN_UNIT) + + NG_IPV6_EXT_LEN_UNIT); +} + +/** + * @brief Builds an extension header for sending. + * + * @param[in] ipv6 The IPv6 header. Can be NULL. + * @param[in] next The next header. Must be a successor to @p ipv6 if it is + * not NULL. + * @param[in] nh @ref net_ng_protnum of the next header. + * @param[in] size Size of the extension header. + * + * @return The extension header on success. + * @return NULL, on error. + */ +ng_pktsnip_t *ng_ipv6_ext_build(ng_pktsnip_t *ipv6, ng_pktsnip_t *next, + uint8_t nh, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* NG_IPV6_EXT_H_ */ +/** + * @} + */ diff --git a/sys/include/net/ng_protnum.h b/sys/include/net/ng_protnum.h index f1d476079c41754b3916651b00a18658375f0fa3..3f82d8b6250f7a541dfc72ab255f65ebc3c32289 100644 --- a/sys/include/net/ng_protnum.h +++ b/sys/include/net/ng_protnum.h @@ -75,7 +75,7 @@ extern "C" { #define NG_PROTNUM_IL (40) /**< IL Transport Protocol */ #define NG_PROTNUM_IPV6 (41) /**< IPv6 encapsulation */ #define NG_PROTNUM_SDRP (42) /**< Source Demand Routing Protocol */ -#define NG_PROTNUM_IPV6_EXT_ROUTE (43) /**< Routing Header for IPv6 */ +#define NG_PROTNUM_IPV6_EXT_RH (43) /**< Routing Header for IPv6 */ #define NG_PROTNUM_IPV6_EXT_FRAG (44) /**< Fragment Header for IPv6 */ #define NG_PROTNUM_IDRP (45) /**< Inter-Domain Routing Protocol */ #define NG_PROTNUM_RSVP (46) /**< Reservation Protocol */ @@ -95,7 +95,7 @@ extern "C" { #define NG_PROTNUM_SKIP (57) /**< SKIP */ #define NG_PROTNUM_ICMPV6 (58) /**< ICMP for IPv6 */ #define NG_PROTNUM_IPV6_NONXT (59) /**< No Next Header for IPv6 */ -#define NG_PROTNUM_IPV6_EXT_DEST_OPTS (60) /**< IPv6 Extension Header: +#define NG_PROTNUM_IPV6_EXT_DST (60) /**< IPv6 Extension Header: * Destination Options */ #define NG_PROTNUM_CFTP (62) /**< CFTP */ #define NG_PROTNUM_SAT_EXPAK (64) /**< SATNET and Backroom EXPAK */ @@ -168,7 +168,7 @@ extern "C" { #define NG_PROTNUM_SCTP (132) /**< Stream Control Transmission Protocol */ #define NG_PROTNUM_FC (133) /**< Fibre Channel */ #define NG_PROTNUM_RSVP_E2E_IGNORE (134) /**< RSVP-E2E-IGNORE */ -#define NG_PROTNUM_IPV6_EXT_MOB_HDR (135) /**< IPv6 Mobility Extension Header */ +#define NG_PROTNUM_IPV6_EXT_MOB (135) /**< IPv6 Mobility Extension Header */ #define NG_PROTNUM_UDPLITE (136) /**< UDPLite */ #define NG_PROTNUM_MPLS_IN_IP (137) /**< MPLS-in-IP */ #define NG_PROTNUM_MANET (138) /**< MANET Protocols */ diff --git a/sys/net/network_layer/ng_ipv6/ext/Makefile b/sys/net/network_layer/ng_ipv6/ext/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e8b451976986f5efcb643f84e338fb5a4894e8d7 --- /dev/null +++ b/sys/net/network_layer/ng_ipv6/ext/Makefile @@ -0,0 +1,3 @@ +MODULE = ng_ipv6_ext + +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/network_layer/ng_ipv6/ext/ng_ipv6_ext.c b/sys/net/network_layer/ng_ipv6/ext/ng_ipv6_ext.c new file mode 100644 index 0000000000000000000000000000000000000000..8919291e0f7c5452c5ce50db467472f97d9781e5 --- /dev/null +++ b/sys/net/network_layer/ng_ipv6/ext/ng_ipv6_ext.c @@ -0,0 +1,111 @@ +/* + * 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 <errno.h> + +#include "utlist.h" +#include "net/ng_pktbuf.h" +#include "net/ng_ipv6.h" + +#include "net/ng_ipv6/ext.h" + +bool ng_ipv6_ext_demux(kernel_pid_t iface, ng_pktsnip_t *pkt, + uint8_t nh) +{ + ng_pktsnip_t *ext_snip; + ng_ipv6_ext_t *ext; + unsigned int offset = 0; + + ext = ((ng_ipv6_ext_t *)(((uint8_t *)pkt->data) + sizeof(ng_ipv6_hdr_t))); + + bool c = true; + + while (c) { + switch (nh) { + case NG_PROTNUM_IPV6_EXT_HOPOPT: + case NG_PROTNUM_IPV6_EXT_DST: + case NG_PROTNUM_IPV6_EXT_RH: + case NG_PROTNUM_IPV6_EXT_FRAG: + case NG_PROTNUM_IPV6_EXT_AH: + case NG_PROTNUM_IPV6_EXT_ESP: + case NG_PROTNUM_IPV6_EXT_MOB: + /* TODO: add handling of types */ + nh = ext->nh; + offset += ((ext->len * NG_IPV6_EXT_LEN_UNIT) + NG_IPV6_EXT_LEN_UNIT); + ext = ng_ipv6_ext_get_next((ng_ipv6_ext_t *)ext); + break; + + default: + c = false; + offset += ((ext->len * NG_IPV6_EXT_LEN_UNIT) + NG_IPV6_EXT_LEN_UNIT); + ext = ng_ipv6_ext_get_next((ng_ipv6_ext_t *)ext); + break; + } + } + + ext_snip = ng_pktbuf_add(pkt, pkt->data, offset, NG_NETTYPE_IPV6); + + if (ext_snip == NULL) { + return false; + } + + ng_ipv6_demux(iface, pkt, nh); /* demultiplex next header */ + + return true; +} + +ng_pktsnip_t *ng_ipv6_ext_build(ng_pktsnip_t *ipv6, ng_pktsnip_t *next, + uint8_t nh, size_t size) +{ + ng_pktsnip_t *prev = NULL, *snip; + ng_ipv6_ext_t *ext; + + if (ipv6 != NULL) { + LL_SEARCH_SCALAR(ipv6, prev, next, next); + + if (prev == NULL) { + return NULL; + } + } + + if (size < NG_IPV6_EXT_LEN_UNIT) { + return NULL; + } + + snip = ng_pktbuf_add(next, NULL, size, NG_NETTYPE_IPV6); + + if (snip == NULL) { + return NULL; + } + + ext = snip->data; + + ext->nh = nh; + + if (size & 0x7) { /* not divisible by eight */ + ext->len = (size / NG_IPV6_EXT_LEN_UNIT); + } + else { + ext->len = (size / NG_IPV6_EXT_LEN_UNIT) - 1; + } + + if (prev != NULL) { + prev->next = snip; + } + + return snip; +} + + +/** @} */ diff --git a/sys/net/network_layer/ng_ipv6/ng_ipv6.c b/sys/net/network_layer/ng_ipv6/ng_ipv6.c index 9389b60ceb6aaf56c302551d46e8d4d928776180..2b49496cc80be1d0dbd125aade790afe5d23ecf2 100644 --- a/sys/net/network_layer/ng_ipv6/ng_ipv6.c +++ b/sys/net/network_layer/ng_ipv6/ng_ipv6.c @@ -78,7 +78,18 @@ void ng_ipv6_demux(kernel_pid_t iface, ng_pktsnip_t *pkt, uint8_t nh) case NG_PROTNUM_ICMPV6: ng_icmpv6_demux(iface, pkt); break; - /* TODO: add extension header handling */ + case NG_PROTNUM_IPV6_EXT_HOPOPT: + case NG_PROTNUM_IPV6_EXT_DST: + case NG_PROTNUM_IPV6_EXT_RH: + case NG_PROTNUM_IPV6_EXT_FRAG: + case NG_PROTNUM_IPV6_EXT_AH: + case NG_PROTNUM_IPV6_EXT_ESP: + case NG_PROTNUM_IPV6_EXT_MOB: + if (!ng_ipv6_ext_demux(iface, pkt, nh)) { + DEBUG("ipv6: unable to parse extension headers.\n"); + ng_pktbuf_release(pkt); + return; + } case NG_PROTNUM_IPV6: _decapsulate(pkt); break;