

8 changed files with 362 additions and 2 deletions
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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 Internet Control Message Protocol for IPv6 |
||||
* @ingroup net_ng_ipv6 |
||||
* @brief Basic implementation of ICMPv6 |
||||
* |
||||
* @see <a href="https://tools.ietf.org/html/rfc4443"> |
||||
* RFC 4443 |
||||
* </a> |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Definitions for ICMPv6 |
||||
* |
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de> |
||||
*/ |
||||
|
||||
#ifndef NG_ICMPV6_H_ |
||||
#define NG_ICMPV6_H_ |
||||
|
||||
#include <inttypes.h> |
||||
|
||||
#include "byteorder.h" |
||||
#include "kernel_types.h" |
||||
#include "net/ng_ipv6/hdr.h" |
||||
#include "net/ng_nettype.h" |
||||
#include "net/ng_nettype.h" |
||||
#include "net/ng_pkt.h" |
||||
|
||||
#include "net/ng_icmpv6/types.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief General ICMPv6 message format. |
||||
* |
||||
* @see <a href="https://tools.ietf.org/html/rfc4443#section-2.1"> |
||||
* RFC 4443, section 2.1 |
||||
* </a> |
||||
*/ |
||||
typedef struct __attribute__((packed)) { |
||||
uint8_t type; /**< message type */ |
||||
uint8_t code; /**< message code */ |
||||
network_uint16_t csum; /**< checksum */ |
||||
} ng_icmpv6_hdr_t; |
||||
|
||||
/**
|
||||
* @brief Demultiplexes a received ICMPv6 packet according to its type field. |
||||
* |
||||
* @param[in] iface The receiving interface |
||||
* @param[in] pkt The packet to demultiplex. |
||||
*/ |
||||
void ng_icmpv6_demux(kernel_pid_t iface, ng_pktsnip_t *pkt); |
||||
|
||||
/**
|
||||
* @brief Builds an ICMPv6 message for sending. |
||||
* |
||||
* @param[in] type Type for the ICMPv6 message. |
||||
* @param[in] code Code for the ICMPv6 message. |
||||
* @param[in] size Size of the ICMPv6 message (needs do be > |
||||
* `sizeof(ng_icmpv6_hdr_t)`). |
||||
* |
||||
* @return The ICMPv6 message on success |
||||
* @return NULL, on failure |
||||
*/ |
||||
ng_pktsnip_t *ng_icmpv6_build(uint8_t type, uint8_t code, size_t size); |
||||
|
||||
/* TODO: build error messages */ |
||||
|
||||
/**
|
||||
* @brief Calculates the checksum for an ICMPv6 packet. |
||||
* |
||||
* @param[in] hdr The header the checksum should be calculated |
||||
* for. |
||||
* @param[in] pseudo_hdr The header the pseudo header shall be generated |
||||
* from. NULL if none is needed. |
||||
* |
||||
* @return 0, on success. |
||||
* @return -EINVAL, if ng_pktsnip_t::type of @p pkt was not NG_NETTYPE_ICMPV6 |
||||
* @return -ENOENT, if ng_pktsnip_t::type of @p pseudo_hdr was not |
||||
* NG_NETTYPE_IPV6 |
||||
*/ |
||||
int ng_icmpv6_calc_csum(ng_pktsnip_t *hdr, ng_pktsnip_t *pseudo_hdr); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* NG_ICMPV6_H_ */ |
||||
/**
|
||||
* @} |
||||
*/ |
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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_types ICMPv6 message type definitions |
||||
* @ingroup net_ng_icmpv6 |
||||
* @brief Type numbers for the corresponding field in ICMPv6 messages. |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Macro definitions for ICMPv6 type fields |
||||
* |
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de> |
||||
*/ |
||||
#ifndef NG_ICMPV6_TYPES_H_ |
||||
#define NG_ICMPV6_TYPES_H_ |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @{ |
||||
* @name Error message types |
||||
* @see <a href="http://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-2"> |
||||
* IANA, ICMPv6 "type" Numbers |
||||
* </a> |
||||
*/ |
||||
#define NG_ICMPV6_DEST_UNR (1) /**< Destination unreachable message */ |
||||
#define NG_ICMPV6_PKT_TOO_BIG (2) /**< Packet Too Big message */ |
||||
#define NG_ICMPV6_TIME_EXC (3) /**< Time Exceeded message */ |
||||
#define NG_ICMPV6_PARAM_PROB (4) /**< Parameter Problem message */ |
||||
#define NG_ICMPV6_ERR_EXP1 (100) /**< message type for private experimentation */ |
||||
#define NG_ICMPV6_ERR_EXP2 (101) /**< message type for private experimentation */ |
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/**
|
||||
* @{ |
||||
* @name Informational message types |
||||
* @see <a href="http://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-2"> |
||||
* IANA, ICMPv6 "type" Numbers |
||||
* </a> |
||||
*/ |
||||
#define NG_ICMPV6_ECHO_REQ (128) /**< Echo request message (ping) */ |
||||
#define NG_ICMPV6_ECHO_REP (129) /**< Echo reply message (pong) */ |
||||
#define NG_ICMPV6_RTR_SOL (133) /**< NDP router solicitation message */ |
||||
#define NG_ICMPV6_RTR_ADV (134) /**< NDP router advertisement message */ |
||||
#define NG_ICMPV6_NBR_SOL (135) /**< NDP neighbor solicitation message */ |
||||
#define NG_ICMPV6_NBR_ADV (136) /**< NDP neighbor advertisement message */ |
||||
#define NG_ICMPV6_REDIRECT (137) /**< NDP redirect message */ |
||||
#define NG_ICMPV6_RPL_CTRL (155) /**< RPL control message */ |
||||
#define NG_ICMPV6_INF_EXP1 (200) /**< message type for private experimentation */ |
||||
#define NG_ICMPV6_INF_EXP2 (201) /**< message type for private experimentation */ |
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* NG_ICMPV6_TYPES_H_ */ |
||||
/** @} */ |
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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. |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup net_ng_icmpv6 |
||||
* @{ |
||||
* |
||||
* @file |
||||
* |
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de> |
||||
*/ |
||||
|
||||
#include <errno.h> |
||||
#include <inttypes.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "byteorder.h" |
||||
#include "kernel_types.h" |
||||
#include "net/ng_netbase.h" |
||||
#include "net/ng_protnum.h" |
||||
#include "net/ng_ipv6/hdr.h" |
||||
#include "od.h" |
||||
#include "utlist.h" |
||||
|
||||
#include "net/ng_icmpv6.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
static inline uint16_t _calc_csum(ng_pktsnip_t *hdr, |
||||
ng_pktsnip_t *pseudo_hdr, |
||||
ng_pktsnip_t *payload) |
||||
{ |
||||
uint16_t csum = 0; |
||||
uint16_t len = (uint16_t)hdr->size; |
||||
|
||||
while (payload && (payload != hdr)) { |
||||
csum = ng_inet_csum(csum, payload->data, payload->size); |
||||
len += (uint16_t)payload->size; |
||||
payload = payload->next; |
||||
} |
||||
|
||||
csum = ng_inet_csum(csum, hdr->data, hdr->size); |
||||
csum = ng_ipv6_hdr_inet_csum(csum, pseudo_hdr->data, NG_PROTNUM_ICMPV6, |
||||
len); |
||||
|
||||
return ~csum; |
||||
} |
||||
|
||||
void ng_icmpv6_demux(kernel_pid_t iface, ng_pktsnip_t *pkt) |
||||
{ |
||||
ng_pktsnip_t *icmpv6, *ipv6; |
||||
ng_icmpv6_hdr_t *hdr; |
||||
ng_netreg_entry_t *sendto; |
||||
|
||||
LL_SEARCH_SCALAR(pkt, icmpv6, type, NG_NETTYPE_ICMPV6); |
||||
|
||||
/* there can be extension headers between IPv6 and ICMPv6 header so we have
|
||||
* to search it */ |
||||
LL_SEARCH_SCALAR(icmpv6, ipv6, type, NG_NETTYPE_IPV6); |
||||
|
||||
hdr = (ng_icmpv6_hdr_t *)icmpv6->data; |
||||
|
||||
if (_calc_csum(icmpv6, ipv6, pkt)) { |
||||
DEBUG("icmpv6: wrong checksum.\n"); |
||||
/* don't release: IPv6 does this */ |
||||
return; |
||||
} |
||||
|
||||
switch (hdr->type) { |
||||
/* TODO: handle ICMPv6 errors */ |
||||
#ifdef MODULE_NG_ICMPV6_ECHO |
||||
case NG_ICMPV6_ECHO_REQ: |
||||
DEBUG("icmpv6: handle echo request.\n"); |
||||
/* TODO */ |
||||
break; |
||||
#endif |
||||
|
||||
#ifdef MODULE_NG_NDP |
||||
case NG_ICMPV6_RTR_SOL: |
||||
case NG_ICMPV6_RTR_ADV: |
||||
case NG_ICMPV6_NBR_SOL: |
||||
case NG_ICMPV6_NBR_ADV: |
||||
case NG_ICMPV6_REDIRECT: |
||||
DEBUG("icmpv6: neighbor discovery message received\n"); |
||||
/* TODO */ |
||||
break; |
||||
#endif |
||||
|
||||
#ifdef MODULE_NG_RPL |
||||
case NG_ICMPV6_RPL_CTRL: |
||||
DEBUG("icmpv6: RPL control message received\n"); |
||||
/* TODO */ |
||||
break; |
||||
#endif |
||||
|
||||
default: |
||||
DEBUG("icmpv6: unknown type field %" PRIu8 "\n", hdr->type); |
||||
break; |
||||
} |
||||
|
||||
/* ICMPv6-all will be send in ng_ipv6.c so only dispatch of subtypes is
|
||||
* needed */ |
||||
|
||||
sendto = ng_netreg_lookup(NG_NETTYPE_ICMPV6, hdr->type); |
||||
|
||||
if (sendto == NULL) { |
||||
DEBUG("icmpv6: no receivers for ICMPv6 type %" PRIu8 "\n", hdr->type); |
||||
/* don't release: IPv6 does this */ |
||||
return; |
||||
} |
||||
|
||||
/* ICMPv6 is not interested anymore so `- 1` */ |
||||
ng_pktbuf_hold(pkt, ng_netreg_num(NG_NETTYPE_ICMPV6, hdr->type) - 1); |
||||
|
||||
while (sendto != NULL) { |
||||
ng_netapi_receive(sendto->pid, pkt); |
||||
sendto = ng_netreg_getnext(sendto); |
||||
} |
||||
} |
||||
|
||||
ng_pktsnip_t *ng_icmpv6_build(uint8_t type, uint8_t code, size_t size) |
||||
{ |
||||
ng_pktsnip_t *pkt; |
||||
ng_icmpv6_hdr_t *icmpv6; |
||||
|
||||
pkt = ng_pktbuf_add(NULL, NULL, size, NG_NETTYPE_ICMPV6); |
||||
|
||||
if (pkt == NULL) { |
||||
DEBUG("icmpv6_echo: no space left in packet buffer\n"); |
||||
return NULL; |
||||
} |
||||
|
||||
DEBUG("icmpv6: Building ICMPv6 message with type=%" PRIu8 ", code=%" PRIu8 "\n", |
||||
type, code); |
||||
icmpv6 = (ng_icmpv6_hdr_t *)pkt->data; |
||||
icmpv6->type = type; |
||||
icmpv6->code = code; |
||||
|
||||
return pkt; |
||||
} |
||||
|
||||
int ng_icmpv6_calc_csum(ng_pktsnip_t *hdr, ng_pktsnip_t *pseudo_hdr) |
||||
{ |
||||
uint32_t csum = 0; |
||||
|
||||
if (hdr == NULL) { |
||||
return -EFAULT; |
||||
} |
||||
if (hdr->type != NG_NETTYPE_ICMPV6) { |
||||
return -EBADMSG; |
||||
} |
||||
|
||||
csum = _calc_csum(hdr, pseudo_hdr, hdr->next); |
||||
|
||||
if (csum == 0) { |
||||
return -ENOENT; |
||||
} |
||||
|
||||
((ng_icmpv6_hdr_t *)hdr->data)->csum = byteorder_htons(csum); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
Loading…
Reference in new issue