Browse Source

ng_icmpv6: Initial import

dev/timer
Martine Lenders 8 years ago committed by Martine Lenders
parent
commit
591ef1826f
  1. 5
      Makefile.dep
  2. 3
      sys/Makefile
  3. 101
      sys/include/net/ng_icmpv6.h
  4. 70
      sys/include/net/ng_icmpv6/types.h
  5. 1
      sys/net/crosslayer/ng_netreg/ng_netreg.c
  6. 1
      sys/net/network_layer/ng_icmpv6/Makefile
  7. 172
      sys/net/network_layer/ng_icmpv6/ng_icmpv6.c
  8. 11
      sys/net/network_layer/ng_ipv6/ng_ipv6.c

5
Makefile.dep

@ -53,6 +53,10 @@ ifneq (,$(filter ng_sixlowpan_ctx,$(USEMODULE)))
USEMODULE += vtimer
endif
ifneq (,$(filter ng_icmpv6,$(USEMODULE)))
USEMODULE += ng_ipv6
endif
ifneq (,$(filter ng_ipv6_hdr,$(USEMODULE)))
USEMODULE += ng_inet_csum
USEMODULE += ng_pktbuf
@ -63,6 +67,7 @@ ifneq (,$(filter ng_ipv6_router,$(USEMODULE)))
endif
ifneq (,$(filter ng_ipv6,$(USEMODULE)))
USEMODULE += ng_icmpv6
USEMODULE += ng_inet_csum
USEMODULE += ng_ipv6_addr
USEMODULE += ng_ipv6_hdr

3
sys/Makefile

@ -62,6 +62,9 @@ endif
ifneq (,$(filter oneway_malloc,$(USEMODULE)))
DIRS += oneway-malloc
endif
ifneq (,$(filter ng_icmpv6,$(USEMODULE)))
DIRS += net/network_layer/ng_icmpv6
endif
ifneq (,$(filter ng_ipv6,$(USEMODULE)))
DIRS += net/network_layer/ng_ipv6
endif

101
sys/include/net/ng_icmpv6.h

@ -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_ */
/**
* @}
*/

70
sys/include/net/ng_icmpv6/types.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_ */
/** @} */

1
sys/net/crosslayer/ng_netreg/ng_netreg.c

@ -20,6 +20,7 @@
#include "net/ng_netreg.h"
#include "net/ng_nettype.h"
#include "net/ng_pkt.h"
#include "net/ng_icmpv6.h"
#include "net/ng_ipv6.h"
#define _INVALID_TYPE(type) (((type) < NG_NETTYPE_UNDEF) || ((type) >= NG_NETTYPE_NUMOF))

1
sys/net/network_layer/ng_icmpv6/Makefile

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

172
sys/net/network_layer/ng_icmpv6/ng_icmpv6.c

@ -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;
}
/**
* @}
*/

11
sys/net/network_layer/ng_ipv6/ng_ipv6.c

@ -18,6 +18,7 @@
#include "byteorder.h"
#include "cpu-conf.h"
#include "kernel_types.h"
#include "net/ng_icmpv6.h"
#include "net/ng_netbase.h"
#include "net/ng_protnum.h"
#include "thread.h"
@ -68,8 +69,14 @@ void ng_ipv6_demux(kernel_pid_t iface, ng_pktsnip_t *pkt, uint8_t nh)
pkt->type = ng_nettype_from_protnum(nh);
/* TODO: add ICMPv6 and extension header handling */
(void)iface; /* will be used by that */
switch (nh) {
case NG_PROTNUM_ICMPV6:
ng_icmpv6_demux(iface, pkt);
break;
/* TODO: add extension header handling */
default:
break;
}
receiver_num = ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) +
ng_netreg_num(NG_NETTYPE_IPV6, nh);

Loading…
Cancel
Save