Skip to content

Commit

Permalink
Merge pull request #11745 from miri64/gnrc_ipv6/fix/rm-dangerous-dup
Browse files Browse the repository at this point in the history
 gnrc_ipv6: remove obsolete and harmful reception code
  • Loading branch information
miri64 committed Jul 3, 2019
2 parents 0cc4c50 + ea449f3 commit 16f0751
Show file tree
Hide file tree
Showing 7 changed files with 412 additions and 13 deletions.
14 changes: 1 addition & 13 deletions sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c
Expand Up @@ -724,10 +724,7 @@ static void _receive(gnrc_pktsnip_t *pkt)
ipv6_addr_to_str(addr_str, &(hdr->dst), sizeof(addr_str)),
first_nh, byteorder_ntohs(hdr->len));

if ((pkt = gnrc_ipv6_ext_process_hopopt(pkt, &first_nh)) != NULL) {
ipv6 = pkt->next->next;
}
else {
if ((pkt = gnrc_ipv6_ext_process_hopopt(pkt, &first_nh)) == NULL) {
DEBUG("ipv6: packet's extension header was errorneous or packet was "
"consumed due to it\n");
return;
Expand Down Expand Up @@ -762,16 +759,7 @@ static void _receive(gnrc_pktsnip_t *pkt)
else if (--(hdr->hl) > 0) { /* drop packets that *reach* Hop Limit 0 */
DEBUG("ipv6: forward packet to next hop\n");

/* pkt might not be writable yet, if header was given above */
ipv6 = gnrc_pktbuf_start_write(ipv6);
if (ipv6 == NULL) {
DEBUG("ipv6: unable to get write access to packet: dropping it\n");
gnrc_pktbuf_release(pkt);
return;
}

/* remove L2 headers around IPV6 */
netif_hdr = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF);
if (netif_hdr != NULL) {
gnrc_pktbuf_remove_snip(pkt, netif_hdr);
}
Expand Down
27 changes: 27 additions & 0 deletions tests/gnrc_ipv6_fwd_w_sub/Makefile
@@ -0,0 +1,27 @@
DEVELHELP := 1
include ../Makefile.tests_common

BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-leonardo \
arduino-mega2560 arduino-nano arduino-uno chronos \
i-nucleo-lrwan1 msb-430 msb-430h nucleo-f030r8 \
nucleo-f031k6 nucleo-f042k6 nucleo-l031k6 \
nucleo-l053r8 stm32f0discovery telosb \
waspmote-pro wsn430-v1_3b wsn430-v1_4 z1

USEMODULE += gnrc_ipv6_router_default
USEMODULE += gnrc_netif
USEMODULE += gnrc_pktbuf_cmd
USEMODULE += netdev_eth
USEMODULE += netdev_test
USEMODULE += od
USEMODULE += ps
USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += xtimer

CFLAGS += -DGNRC_PKTBUF_SIZE=512
CFLAGS += -DTEST_SUITES

TEST_ON_CI_WHITELIST += all

include $(RIOTBASE)/Makefile.include
10 changes: 10 additions & 0 deletions tests/gnrc_ipv6_fwd_w_sub/README.md
@@ -0,0 +1,10 @@
# Regression test for forwarding IPv6 packets with a sniffing subscriber

This only tests if a router can sniff its own forwarded IPv6 traffic. It is
**not** a full IPv6 test suite.

## Usage

```
BOARD='<your choice>' make flash test
```
48 changes: 48 additions & 0 deletions tests/gnrc_ipv6_fwd_w_sub/common.h
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2017 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
* directory for more details.
*/

/**
* @defgroup tests_gnrc_ipv6_nib Common header for GNRC's NIB tests
* @ingroup tests
* @brief Common definitions for GNRC's NIB tests
* @{
*
* @file
*
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#ifndef COMMON_H
#define COMMON_H

#include <stdio.h>

#include "net/gnrc.h"
#include "net/gnrc/netif.h"

#ifdef __cplusplus
extern "C" {
#endif

#define _LL0 (0xce)
#define _LL1 (0xab)
#define _LL2 (0xfe)
#define _LL3 (0xad)
#define _LL4 (0xf7)
#define _LL5 (0x26)

extern gnrc_netif_t *_mock_netif;

void _tests_init(void);


#ifdef __cplusplus
}
#endif

#endif /* COMMON_H */
/** @} */
202 changes: 202 additions & 0 deletions tests/gnrc_ipv6_fwd_w_sub/main.c
@@ -0,0 +1,202 @@
/*
* Copyright (C) 2019 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
* directory for more details.
*/

/**
* @ingroup tests
* @{
*
* @file
* @brief Regression test to test subscribing to IPv6 packets while
* forwarding
*
* @author Martine S. Lenders <m.lenders@fu-berlin.de>
*
* @}
*/

#include <assert.h>
#include <errno.h>
#include <stdio.h>

#include "kernel_types.h"
#include "msg.h"
#include "net/ethernet/hdr.h"
#include "net/ipv6/addr.h"
#include "net/udp.h"
#include "net/gnrc.h"
#include "net/gnrc.h"
#include "net/gnrc/ipv6/nib.h"
#include "net/netdev_test.h"
#include "od.h"
#include "sched.h"
#include "shell.h"
#include "thread.h"
#include "xtimer.h"

#include "common.h"

#define DUMPER_QUEUE_SIZE (16)
#define NBR_MAC { 0x57, 0x44, 0x33, 0x22, 0x11, 0x00, }
#define NBR_LINK_LOCAL { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x55, 0x44, 0x33, 0xff, 0xfe, 0x22, 0x11, 0x00, }
#define DST { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0xab, 0xcd, \
0x55, 0x44, 0x33, 0xff, 0xfe, 0x22, 0x11, 0x00, }
#define DST_PFX_LEN (64U)
/* IPv6 header + payload: version+TC FL: 0 plen: 16 NH:17 HL:64 */
#define L2_PAYLOAD { 0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x40, \
/* source: random address */ \
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0xef, 0x01, \
0x02, 0xca, 0x4b, 0xef, 0xf4, 0xc2, 0xde, 0x01, \
/* destination: DST */ \
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0xab, 0xcd, \
0x55, 0x44, 0x33, 0xff, 0xfe, 0x22, 0x11, 0x00, \
/* random payload of length 16 */ \
0x54, 0xb8, 0x59, 0xaf, 0x3a, 0xb4, 0x5c, 0x85, \
0x1e, 0xce, 0xe2, 0xeb, 0x05, 0x4e, 0xa3, 0x85, }

static const uint8_t _nbr_mac[] = NBR_MAC;
static const ipv6_addr_t _nbr_link_local = { .u8 = NBR_LINK_LOCAL };
static const ipv6_addr_t _dst = { .u8 = DST };
static const uint8_t _l2_payload[] = L2_PAYLOAD;
static gnrc_netreg_entry_t _dumper;
static msg_t _dumper_queue[DUMPER_QUEUE_SIZE];
static char _dumper_stack[THREAD_STACKSIZE_MAIN];

static int _run_test(int argc, char **argv);

static const shell_command_t shell_commands[] = {
{ "run_test", "runs the regression test", _run_test },
{ NULL, NULL, NULL }
};

static void *_dumper_thread(void *arg)
{
(void)arg;
msg_init_queue(_dumper_queue, DUMPER_QUEUE_SIZE);

while (1) {
msg_t msg;

msg_receive(&msg);
if (msg.type == GNRC_NETAPI_MSG_TYPE_RCV) {
gnrc_pktsnip_t *pkt = msg.content.ptr;

/* wait a bit to give IPv6 time to handle the packet */
xtimer_usleep(500);
/* dump pkt. Should be equal to _l2_payloa*/
puts("I got a subscription!");
od_hex_dump(pkt->data, pkt->size, OD_WIDTH_DEFAULT);
gnrc_pktbuf_release(pkt);
}
else if (msg.type == GNRC_NETAPI_MSG_TYPE_SND) {
/* we are not interested in sent packets from the node itself;
* just release it */
gnrc_pktbuf_release(msg.content.ptr);
}
}

return NULL;
}

static int _dump_etherframe(netdev_t *dev, const iolist_t *iolist)
{
static uint8_t outbuf[sizeof(ethernet_hdr_t) + sizeof(_l2_payload)];
size_t outbuf_len = 0U;

(void)dev;
while (iolist) {
if ((outbuf_len + iolist->iol_len) > sizeof(outbuf)) {
printf("Ignoring packet: %u > %u\n",
(unsigned)(outbuf_len + iolist->iol_len),
(unsigned)sizeof(outbuf));
/* ignore larger packets */
return outbuf_len;
}
memcpy(&outbuf[outbuf_len], iolist->iol_base, iolist->iol_len);
outbuf_len += iolist->iol_len;
iolist = iolist->iol_next;
}

puts("Forwarded Ethernet frame:");
od_hex_dump(outbuf, outbuf_len, OD_WIDTH_DEFAULT);
return outbuf_len;
}

static gnrc_pktsnip_t *_build_recvd_pkt(void)
{
gnrc_pktsnip_t *netif;
gnrc_pktsnip_t *pkt;
gnrc_netif_hdr_t *netif_hdr;

netif = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
assert(netif);
netif_hdr = netif->data;
netif_hdr->if_pid = _mock_netif->pid;
pkt = gnrc_pktbuf_add(netif, _l2_payload, sizeof(_l2_payload),
GNRC_NETTYPE_IPV6);
assert(pkt);
return pkt;
}

static int _run_test(int argc, char **argv)
{
int subscribers;
(void)argc;
(void)argv;
if (_dumper.target.pid <= KERNEL_PID_UNDEF) {
gnrc_netreg_entry_init_pid(&_dumper, GNRC_NETREG_DEMUX_CTX_ALL,
thread_create(_dumper_stack,
sizeof(_dumper_stack),
THREAD_PRIORITY_MAIN - 1, 0,
_dumper_thread, NULL,
"dumper"));
assert(_dumper.target.pid > KERNEL_PID_UNDEF);
/* give dumper thread time to run */
xtimer_usleep(200);
}
/* activate dumping of sent ethernet frames */
netdev_test_set_send_cb((netdev_test_t *)_mock_netif->dev,
_dump_etherframe);
/* first, test forwarding without subscription */
subscribers = gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6,
GNRC_NETREG_DEMUX_CTX_ALL,
_build_recvd_pkt());
/* only IPv6 should be subscribed at the moment */
assert(subscribers == 1);
/* subscribe dumper thread for any IPv6 packets */
gnrc_netreg_register(GNRC_NETTYPE_IPV6, &_dumper);
/* now test forwarding with subscription */
subscribers = gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6,
GNRC_NETREG_DEMUX_CTX_ALL,
_build_recvd_pkt());
/* assert 2 subscribers: IPv6 and gnrc_pktdump as registered above */
assert(subscribers == 2);
return 0;
}

int main(void)
{
int res;

/* initialize mock interface */
_tests_init();
/* define neighbor to forward to */
res = gnrc_ipv6_nib_nc_set(&_nbr_link_local, _mock_netif->pid,
_nbr_mac, sizeof(_nbr_mac));
assert(res == 0);
/* set route to neighbor */
res = gnrc_ipv6_nib_ft_add(&_dst, DST_PFX_LEN, &_nbr_link_local,
_mock_netif->pid, 0);
assert(res == 0);
/* start shell */
char line_buf[SHELL_DEFAULT_BUFSIZE];
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);

/* should be never reached */
return 0;
}

0 comments on commit 16f0751

Please sign in to comment.