diff --git a/sys/include/net/gnrc/ipv6/ext/rh.h b/sys/include/net/gnrc/ipv6/ext/rh.h index 7a31355583617cadd3f22d28faa2077fea3c7322..89d9a25fd3da39664c903ac12df87235e06c3880 100644 --- a/sys/include/net/gnrc/ipv6/ext/rh.h +++ b/sys/include/net/gnrc/ipv6/ext/rh.h @@ -20,9 +20,7 @@ #ifndef NET_GNRC_IPV6_EXT_RH_H #define NET_GNRC_IPV6_EXT_RH_H -#include "net/ipv6/hdr.h" - -#include "net/ipv6/ext/rh.h" +#include "net/gnrc/pkt.h" #ifdef __cplusplus extern "C" { @@ -56,14 +54,14 @@ enum { /** * @brief Process the routing header of an IPv6 packet. * - * @param[in, out] ipv6 An IPv6 packet. - * @param[in] ext A routing header of @p ipv6. + * @param[in] pkt An IPv6 packet containing the routing header in the first + * snip * * @return @ref GNRC_IPV6_EXT_RH_AT_DST, on success * @return @ref GNRC_IPV6_EXT_RH_FORWARDED, when @p pkt was forwarded * @return @ref GNRC_IPV6_EXT_RH_ERROR, on error */ -int gnrc_ipv6_ext_rh_process(ipv6_hdr_t *ipv6, ipv6_ext_rh_t *ext); +int gnrc_ipv6_ext_rh_process(gnrc_pktsnip_t *pkt); #ifdef __cplusplus } diff --git a/sys/net/gnrc/network_layer/ipv6/ext/gnrc_ipv6_ext.c b/sys/net/gnrc/network_layer/ipv6/ext/gnrc_ipv6_ext.c index 4209e18fcaae04e8167cfec5e2dbd7034995bae7..e7c60634fbf85048534f3fce2e566cc0d434ca46 100644 --- a/sys/net/gnrc/network_layer/ipv6/ext/gnrc_ipv6_ext.c +++ b/sys/net/gnrc/network_layer/ipv6/ext/gnrc_ipv6_ext.c @@ -148,75 +148,6 @@ static bool _duplicate_hopopt(gnrc_pktsnip_t *pkt, unsigned protnum) return false; } -#ifdef MODULE_GNRC_IPV6_EXT_RH -/* unchecked precondition: hdr is gnrc_pktsnip_t::data of the - * GNRC_NETTYPE_IPV6 snip within pkt */ -static void _forward_pkt(gnrc_pktsnip_t *pkt, ipv6_hdr_t *hdr) -{ - gnrc_pktsnip_t *netif_snip; - - if (--(hdr->hl) == 0) { - DEBUG("ipv6_ext_rh: hop limit reached 0: drop packet\n"); - gnrc_pktbuf_release(pkt); - return; - } - /* remove L2 headers around IPV6 */ - netif_snip = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); - if (netif_snip != NULL) { - pkt = gnrc_pktbuf_remove_snip(pkt, netif_snip); - } - /* reverse packet into send order */ - pkt = gnrc_pktbuf_reverse_snips(pkt); - if (pkt == NULL) { - DEBUG("ipv6_ext_rh: can't reverse snip order in packet"); - /* gnrc_pktbuf_reverse_snips() releases pkt on error */ - return; - } - /* forward packet */ - if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_IPV6, - GNRC_NETREG_DEMUX_CTX_ALL, - pkt)) { - DEBUG("ipv6_ext_rh: could not dispatch packet to the IPv6 " - "thread\n"); - gnrc_pktbuf_release(pkt); - } -} - -/* handle routing header at pkt->data */ -static int _handle_rh(gnrc_pktsnip_t *pkt) -{ - gnrc_pktsnip_t *ipv6; - ipv6_ext_t *ext = (ipv6_ext_t *)pkt->data; - ipv6_hdr_t *hdr; - int res; - - /* check seg_left early to to exit quickly */ - if (((ipv6_ext_rh_t *)ext)->seg_left == 0) { - return GNRC_IPV6_EXT_RH_AT_DST; - } - ipv6 = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_IPV6); - assert(ipv6 != NULL); - hdr = ipv6->data; - switch ((res = gnrc_ipv6_ext_rh_process(hdr, (ipv6_ext_rh_t *)ext))) { - case GNRC_IPV6_EXT_RH_ERROR: - /* TODO: send ICMPv6 error codes */ - gnrc_pktbuf_release(pkt); - break; - - case GNRC_IPV6_EXT_RH_FORWARDED: - _forward_pkt(pkt, hdr); - break; - - case GNRC_IPV6_EXT_RH_AT_DST: - /* this should not happen since we checked seg_left early */ - gnrc_pktbuf_release(pkt); - break; - } - - return res; -} -#endif /* MODULE_GNRC_IPV6_EXT_RH */ - /** * @brief Marks an IPv6 extension header according to the length field * provided by the extension header itself. @@ -297,8 +228,8 @@ static gnrc_pktsnip_t *_demux(gnrc_pktsnip_t *pkt, unsigned protnum) } switch (protnum) { case PROTNUM_IPV6_EXT_RH: -#ifdef MODULE_GNRC_RPL_SRH - switch (_handle_rh(pkt)) { +#ifdef MODULE_GNRC_IPV6_EXT_RH + switch (gnrc_ipv6_ext_rh_process(pkt)) { case GNRC_IPV6_EXT_RH_AT_DST: /* We are the final destination of the route laid out in * the routing header. So proceeds like normal packet. */ @@ -314,14 +245,15 @@ static gnrc_pktsnip_t *_demux(gnrc_pktsnip_t *pkt, unsigned protnum) gnrc_pktbuf_release(pkt); /* Intentionally falls through */ case GNRC_IPV6_EXT_RH_ERROR: - /* already released by _handle_rh, so no release here */ + /* already released by gnrc_ipv6_ext_rh_process, so no + * release here */ case GNRC_IPV6_EXT_RH_FORWARDED: /* the packet is forwarded and released. finish processing */ return NULL; } break; -#endif +#endif /* MODULE_GNRC_IPV6_EXT_RH */ case PROTNUM_IPV6_EXT_HOPOPT: case PROTNUM_IPV6_EXT_DST: @@ -385,5 +317,4 @@ gnrc_pktsnip_t *gnrc_ipv6_ext_build(gnrc_pktsnip_t *ipv6, gnrc_pktsnip_t *next, return snip; } - /** @} */ diff --git a/sys/net/gnrc/network_layer/ipv6/ext/rh/gnrc_ipv6_ext_rh.c b/sys/net/gnrc/network_layer/ipv6/ext/rh/gnrc_ipv6_ext_rh.c index 776d7d40352c7ec1a5c5fdb8e30a3f7bf0480cf6..68d0c2b7e583bcf780bb19f37f93d6cdf37dadb3 100644 --- a/sys/net/gnrc/network_layer/ipv6/ext/rh/gnrc_ipv6_ext_rh.c +++ b/sys/net/gnrc/network_layer/ipv6/ext/rh/gnrc_ipv6_ext_rh.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de> + * Copyright (C) 2015 Cenk Gündoğan <cenk.guendogan@fu-berlin.de> + * Copyright (C) 2018 Freie Universität Berlin * * 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 @@ -10,29 +11,90 @@ * @{ * * @file + * @author Cenk Gündoğan <cenk.guendogan@fu-berlin.de> + * @author Martine Lenders <m.lenders@fu-berlin.de> */ -#include <stdbool.h> +#include "net/ipv6/ext/rh.h" +#include "net/gnrc.h" -#include "net/protnum.h" -#include "net/ipv6/ext.h" -#include "net/gnrc/ipv6/ext/rh.h" +#ifdef MODULE_GNRC_RPL_SRH #include "net/gnrc/rpl/srh.h" +#endif + +#include "net/gnrc/ipv6/ext/rh.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/* unchecked precondition: hdr is gnrc_pktsnip_t::data of the + * GNRC_NETTYPE_IPV6 snip within pkt */ +static void _forward_pkt(gnrc_pktsnip_t *pkt, ipv6_hdr_t *hdr) +{ + gnrc_pktsnip_t *netif_snip; + + if (--(hdr->hl) == 0) { + DEBUG("ipv6_ext_rh: hop limit reached 0: drop packet\n"); + gnrc_pktbuf_release(pkt); + return; + } + /* remove L2 headers around IPV6 */ + netif_snip = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); + if (netif_snip != NULL) { + pkt = gnrc_pktbuf_remove_snip(pkt, netif_snip); + } + /* reverse packet into send order */ + pkt = gnrc_pktbuf_reverse_snips(pkt); + if (pkt == NULL) { + DEBUG("ipv6_ext_rh: can't reverse snip order in packet"); + /* gnrc_pktbuf_reverse_snips() releases pkt on error */ + return; + } + /* forward packet */ + if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_IPV6, + GNRC_NETREG_DEMUX_CTX_ALL, + pkt)) { + DEBUG("ipv6_ext_rh: could not dispatch packet to the IPv6 " + "thread\n"); + gnrc_pktbuf_release(pkt); + } +} -int gnrc_ipv6_ext_rh_process(ipv6_hdr_t *hdr, ipv6_ext_rh_t *ext) +int gnrc_ipv6_ext_rh_process(gnrc_pktsnip_t *pkt) { - (void) hdr; + gnrc_pktsnip_t *ipv6; + ipv6_ext_rh_t *ext = pkt->data; + ipv6_hdr_t *hdr; + int res = GNRC_IPV6_EXT_RH_AT_DST; + /* check seg_left early to avoid duplicating the packet */ + if (ext->seg_left == 0) { + return res; + } + ipv6 = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_IPV6); + assert(ipv6 != NULL); + hdr = ipv6->data; switch (ext->type) { #ifdef MODULE_GNRC_RPL_SRH case IPV6_EXT_RH_TYPE_RPL_SRH: - return gnrc_rpl_srh_process(hdr, (gnrc_rpl_srh_t *)ext); + res = gnrc_rpl_srh_process(hdr, (gnrc_rpl_srh_t *)ext); + break; #endif - default: + res = GNRC_IPV6_EXT_RH_ERROR; + break; + } + switch (res) { + case GNRC_IPV6_EXT_RH_FORWARDED: + _forward_pkt(pkt, hdr); + break; + case GNRC_IPV6_EXT_RH_AT_DST: + break; + default: + gnrc_pktbuf_release(pkt); break; } - return GNRC_IPV6_EXT_RH_ERROR; + return res; } /** @} */