mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 05:12:57 +01:00
gnrc_icmpv6_error: initial import
This commit is contained in:
parent
54e6163ab3
commit
70c3d29036
@ -197,6 +197,10 @@ ifneq (,$(filter gnrc_icmpv6_echo,$(USEMODULE)))
|
||||
USEMODULE += gnrc_icmpv6
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_icmpv6_error,$(USEMODULE)))
|
||||
USEMODULE += gnrc_icmpv6
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_icmpv6,$(USEMODULE)))
|
||||
USEMODULE += inet_csum
|
||||
USEMODULE += gnrc_ipv6
|
||||
|
@ -16,16 +16,66 @@
|
||||
* @brief ICMPv6 error message definitions
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*
|
||||
* @todo implement build and handle functions
|
||||
*/
|
||||
#ifndef GNRC_ICMPV6_ERROR_H_
|
||||
#define GNRC_ICMPV6_ERROR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "net/icmpv6.h"
|
||||
#include "net/ipv6/hdr.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Builds an ICMPv6 destination unreachable message for sending.
|
||||
*
|
||||
* @param[in] code The code for the message @see net/icmpv6.h.
|
||||
* @param[in] orig_pkt The invoking packet.
|
||||
*
|
||||
* @return The destination unreachable message on success.
|
||||
* @return NULL, on failure.
|
||||
*/
|
||||
gnrc_pktsnip_t *gnrc_icmpv6_error_dst_unr_build(uint8_t code, gnrc_pktsnip_t *orig_pkt);
|
||||
|
||||
/**
|
||||
* @brief Builds an ICMPv6 packet too big message for sending.
|
||||
*
|
||||
* @param[in] mtu The maximum transission unit of the next-hop link.
|
||||
* @param[in] orig_pkt The invoking packet.
|
||||
*
|
||||
* @return The packet too big message on success.
|
||||
* @return NULL, on failure.
|
||||
*/
|
||||
gnrc_pktsnip_t *gnrc_icmpv6_error_pkt_too_big_build(uint32_t mtu, gnrc_pktsnip_t *orig_pkt);
|
||||
|
||||
/**
|
||||
* @brief Builds an ICMPv6 time exceeded message for sending.
|
||||
*
|
||||
* @param[in] code The code for the message @see net/icmpv6.h.
|
||||
* @param[in] orig_pkt The invoking packet.
|
||||
*
|
||||
* @return The time exceeded message on success.
|
||||
* @return NULL, on failure.
|
||||
*/
|
||||
gnrc_pktsnip_t *gnrc_icmpv6_error_time_exc_build(uint8_t code, gnrc_pktsnip_t *orig_pkt);
|
||||
|
||||
/**
|
||||
* @brief Builds an ICMPv6 parameter problem message for sending.
|
||||
*
|
||||
* @param[in] code The code for the message @see net/icmpv6.h.
|
||||
* @param[in] ptr Pointer to the errorneous octet in @p orig_pkt.
|
||||
* @param[in] orig_pkt The invoking packet.
|
||||
*
|
||||
* @return The parameter problem message on success.
|
||||
* @return NULL, on failure.
|
||||
*/
|
||||
gnrc_pktsnip_t *gnrc_icmpv6_error_param_prob_build(uint8_t code, void *ptr,
|
||||
gnrc_pktsnip_t *orig_pkt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -38,7 +38,7 @@ extern "C" {
|
||||
* IANA, ICMPv6 "type" Numbers
|
||||
* </a>
|
||||
*/
|
||||
#define ICMPV6_DEST_UNR (1) /**< Destination unreachable message */
|
||||
#define ICMPV6_DST_UNR (1) /**< Destination unreachable message */
|
||||
#define ICMPV6_PKT_TOO_BIG (2) /**< Packet Too Big message */
|
||||
#define ICMPV6_TIME_EXC (3) /**< Time Exceeded message */
|
||||
#define ICMPV6_PARAM_PROB (4) /**< Parameter Problem message */
|
||||
|
@ -13,6 +13,9 @@ endif
|
||||
ifneq (,$(filter gnrc_icmpv6_echo,$(USEMODULE)))
|
||||
DIRS += network_layer/icmpv6/echo
|
||||
endif
|
||||
ifneq (,$(filter gnrc_icmpv6_error,$(USEMODULE)))
|
||||
DIRS += network_layer/icmpv6/error
|
||||
endif
|
||||
ifneq (,$(filter gnrc_ipv6,$(USEMODULE)))
|
||||
DIRS += network_layer/ipv6
|
||||
endif
|
||||
|
3
sys/net/gnrc/network_layer/icmpv6/error/Makefile
Normal file
3
sys/net/gnrc/network_layer/icmpv6/error/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = gnrc_icmpv6_error
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
122
sys/net/gnrc/network_layer/icmpv6/error/gnrc_icmpv6_error.c
Normal file
122
sys/net/gnrc/network_layer/icmpv6/error/gnrc_icmpv6_error.c
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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/gnrc/pktbuf.h"
|
||||
|
||||
#include "net/ipv6.h"
|
||||
#include "net/gnrc/ipv6/netif.h"
|
||||
#include "net/gnrc/icmpv6/error.h"
|
||||
#include "net/gnrc/icmpv6.h"
|
||||
|
||||
/* all error messages are basically the same size and format */
|
||||
#define ICMPV6_ERROR_SZ (sizeof(icmpv6_error_dst_unr_t))
|
||||
#define ICMPV6_ERROR_SET_VALUE(data, value) \
|
||||
((icmpv6_error_pkt_too_big_t *)(data))->mtu = byteorder_htonl(value)
|
||||
|
||||
/* TODO: generalize and centralize (see https://github.com/RIOT-OS/RIOT/pull/3184) */
|
||||
#define MIN(a, b) ((a) < (b)) ? (a) : (b)
|
||||
|
||||
static inline size_t _fit(gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
/* TODO: replace IPV6_MIN_MTU with known path MTU? */
|
||||
return MIN((gnrc_pkt_len(pkt) + ICMPV6_ERROR_SZ), IPV6_MIN_MTU);
|
||||
}
|
||||
|
||||
/* Build a generic error message */
|
||||
static gnrc_pktsnip_t *_icmpv6_error_build(uint8_t type, uint8_t code,
|
||||
gnrc_pktsnip_t *orig_pkt, uint32_t value)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = gnrc_icmpv6_build(NULL, type, code, _fit(orig_pkt));
|
||||
|
||||
/* copy as much of the originating packet into error message as fits the message's size */
|
||||
if (pkt != NULL) {
|
||||
size_t offset = ICMPV6_ERROR_SZ;
|
||||
uint8_t *data = pkt->data;
|
||||
ICMPV6_ERROR_SET_VALUE(data, value);
|
||||
while ((orig_pkt != NULL) && (offset < pkt->size)) {
|
||||
memcpy(data + offset, orig_pkt->data,
|
||||
MIN(pkt->size - offset, orig_pkt->size));
|
||||
offset += MIN(pkt->size - offset, orig_pkt->size);
|
||||
orig_pkt = orig_pkt->next;
|
||||
}
|
||||
}
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
gnrc_pktsnip_t *gnrc_icmpv6_error_dst_unr_build(uint8_t code, gnrc_pktsnip_t *orig_pkt)
|
||||
{
|
||||
return _icmpv6_error_build(ICMPV6_DST_UNR, code, orig_pkt, 0);
|
||||
}
|
||||
|
||||
gnrc_pktsnip_t *gnrc_icmpv6_error_pkt_too_big_build(uint32_t mtu, gnrc_pktsnip_t *orig_pkt)
|
||||
{
|
||||
return _icmpv6_error_build(ICMPV6_PKT_TOO_BIG, 0, orig_pkt, mtu);
|
||||
}
|
||||
|
||||
gnrc_pktsnip_t *gnrc_icmpv6_error_time_exc_build(uint8_t code, gnrc_pktsnip_t *orig_pkt)
|
||||
{
|
||||
return _icmpv6_error_build(ICMPV6_TIME_EXC, code, orig_pkt, 0);
|
||||
}
|
||||
|
||||
static inline bool _in_range(uint8_t *ptr, uint8_t *start, size_t sz)
|
||||
{
|
||||
return (ptr >= start) && (ptr < (start + sz));
|
||||
}
|
||||
|
||||
gnrc_pktsnip_t *gnrc_icmpv6_error_param_prob_build(uint8_t code, void *ptr,
|
||||
gnrc_pktsnip_t *orig_pkt)
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = gnrc_icmpv6_build(NULL, ICMPV6_PARAM_PROB, code,
|
||||
_fit(orig_pkt));
|
||||
|
||||
/* copy as much of the originating packet into error message and
|
||||
* determine relative *ptr* offset */
|
||||
if (pkt != NULL) {
|
||||
size_t offset = sizeof(icmpv6_error_param_prob_t);
|
||||
uint8_t *data = pkt->data;
|
||||
uint32_t ptr_offset = 0U;
|
||||
bool found_offset = false;
|
||||
|
||||
while (orig_pkt != NULL) {
|
||||
/* copy as long as it fits into packet */
|
||||
if (offset < pkt->size) {
|
||||
memcpy(data + offset, orig_pkt->data,
|
||||
MIN(pkt->size - offset, orig_pkt->size));
|
||||
offset += MIN(pkt->size - offset, orig_pkt->size);
|
||||
}
|
||||
|
||||
if (_in_range(ptr, orig_pkt->data, orig_pkt->size)) {
|
||||
ptr_offset += (uint32_t)(((uint8_t *)ptr) - ((uint8_t *)orig_pkt->data));
|
||||
found_offset = true;
|
||||
}
|
||||
else if (!found_offset) {
|
||||
ptr_offset += (uint32_t)orig_pkt->size;
|
||||
}
|
||||
|
||||
orig_pkt = orig_pkt->next;
|
||||
|
||||
if ((offset < pkt->size) && found_offset) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* set "pointer" field to relative pointer offset */
|
||||
((icmpv6_error_param_prob_t *)data)->ptr = byteorder_htonl(ptr_offset);
|
||||
}
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user