1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

gnrc_rpl: separate validation from msg handling

This commit is contained in:
Cenk Gündoğan 2016-04-12 11:29:02 +02:00
parent 2f9a37a624
commit 25baea1e50
3 changed files with 265 additions and 146 deletions

View File

@ -246,19 +246,6 @@ void gnrc_rpl_send_DIS(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination)
gnrc_rpl_send(pkt, KERNEL_PID_UNDEF, NULL, destination, (inst? &(inst->dodag.dodag_id) : NULL));
}
static bool _gnrc_rpl_check_DIS_validity(gnrc_rpl_dis_t *dis, uint16_t len)
{
uint16_t expected_len = sizeof(*dis) + sizeof(icmpv6_hdr_t);
if (expected_len <= len) {
return true;
}
DEBUG("RPL: wrong DIS len: %d, expected: %d\n", len, expected_len);
return false;
}
void gnrc_rpl_recv_DIS(gnrc_rpl_dis_t *dis, kernel_pid_t iface, ipv6_addr_t *src,
ipv6_addr_t *dst, uint16_t len)
{
@ -294,92 +281,6 @@ void gnrc_rpl_recv_DIS(gnrc_rpl_dis_t *dis, kernel_pid_t iface, ipv6_addr_t *src
}
}
static bool _gnrc_rpl_check_options_validity(int msg_type, gnrc_rpl_instance_t *inst,
gnrc_rpl_opt_t *opt, uint16_t len)
{
uint16_t expected_len = 0;
while(expected_len < len) {
switch(opt->type) {
case (GNRC_RPL_OPT_PAD1):
expected_len += 1;
opt = (gnrc_rpl_opt_t *) (((uint8_t *) opt) + 1);
continue;
case (GNRC_RPL_OPT_DODAG_CONF):
if (msg_type != GNRC_RPL_ICMPV6_CODE_DIO) {
DEBUG("RPL: DODAG CONF DIO option not expected\n");
return false;
}
if (opt->length != GNRC_RPL_OPT_DODAG_CONF_LEN) {
DEBUG("RPL: wrong DIO option (DODAG CONF) len: %d, expected: %d\n",
opt->length, GNRC_RPL_OPT_DODAG_CONF_LEN);
return false;
}
break;
case (GNRC_RPL_OPT_PREFIX_INFO):
if (msg_type != GNRC_RPL_ICMPV6_CODE_DIO) {
DEBUG("RPL: PREFIX INFO DIO option not expected\n");
return false;
}
if (opt->length != GNRC_RPL_OPT_PREFIX_INFO_LEN) {
DEBUG("RPL: wrong DIO option (PREFIX INFO) len: %d, expected: %d\n",
opt->length, GNRC_RPL_OPT_PREFIX_INFO_LEN);
return false;
}
break;
case (GNRC_RPL_OPT_TARGET):
if (msg_type != GNRC_RPL_ICMPV6_CODE_DAO) {
DEBUG("RPL: RPL TARGET DAO option not expected\n");
return false;
}
if (opt->length > GNRC_RPL_OPT_TARGET_LEN) {
DEBUG("RPL: wrong DAO option (RPL TARGET) len: %d, expected (max): %d\n",
opt->length, GNRC_RPL_OPT_TARGET_LEN);
return false;
}
break;
case (GNRC_RPL_OPT_TRANSIT):
if (msg_type != GNRC_RPL_ICMPV6_CODE_DAO) {
DEBUG("RPL: RPL TRANSIT INFO DAO option not expected\n");
return false;
}
uint8_t parent_addr = 0;
if (inst->mop == GNRC_RPL_MOP_NON_STORING_MODE) {
parent_addr = sizeof(ipv6_addr_t);
}
if (opt->length != (GNRC_RPL_OPT_TRANSIT_INFO_LEN + parent_addr)) {
DEBUG("RPL: wrong DAO option (TRANSIT INFO) len: %d, expected: %d\n",
opt->length, (GNRC_RPL_OPT_TRANSIT_INFO_LEN + parent_addr));
return false;
}
break;
default:
break;
}
expected_len += opt->length + sizeof(gnrc_rpl_opt_t);
opt = (gnrc_rpl_opt_t *) (((uint8_t *) (opt + 1)) + opt->length);
}
if (expected_len == len) {
return true;
}
DEBUG("RPL: wrong options len: %d, expected: %d\n", len, expected_len);
return false;
}
/** @todo allow target prefixes in target options to be of variable length */
bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt_t *opt, uint16_t len,
ipv6_addr_t *src, uint32_t *included_opts)
@ -524,19 +425,6 @@ bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt_t *opt
return true;
}
static bool _gnrc_rpl_check_DIO_validity(gnrc_rpl_dio_t *dio, uint16_t len)
{
uint16_t expected_len = sizeof(*dio) + sizeof(icmpv6_hdr_t);
if (expected_len <= len) {
return true;
}
DEBUG("RPL: wrong DIO len: %d, expected: %d\n", len, expected_len);
return false;
}
void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, kernel_pid_t iface, ipv6_addr_t *src, uint16_t len)
{
gnrc_rpl_instance_t *inst = NULL;
@ -970,23 +858,6 @@ void gnrc_rpl_send_DAO_ACK(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination,
gnrc_rpl_send(pkt, dodag->iface, NULL, destination, &dodag->dodag_id);
}
static bool _gnrc_rpl_check_DAO_validity(gnrc_rpl_dao_t *dao, uint16_t len)
{
uint16_t expected_len = sizeof(*dao) + sizeof(icmpv6_hdr_t);
if ((dao->k_d_flags & GNRC_RPL_DAO_D_BIT)) {
expected_len += sizeof(ipv6_addr_t);
}
if (expected_len <= len) {
return true;
}
DEBUG("RPL: wrong DAO len: %d, expected: %d\n", len, expected_len);
return false;
}
void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, kernel_pid_t iface, ipv6_addr_t *src, uint16_t len)
{
(void)iface;
@ -1045,23 +916,6 @@ void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, kernel_pid_t iface, ipv6_addr_t *src
gnrc_rpl_delay_dao(dodag);
}
static bool _gnrc_rpl_check_DAO_ACK_validity(gnrc_rpl_dao_ack_t *dao_ack, uint16_t len)
{
uint16_t expected_len = sizeof(*dao_ack) + sizeof(icmpv6_hdr_t);
if ((dao_ack->d_reserved & GNRC_RPL_DAO_ACK_D_BIT)) {
expected_len += sizeof(ipv6_addr_t);
}
if (expected_len == len) {
return true;
}
DEBUG("RPL: wrong DAO-ACK len: %d, expected: %d\n", len, expected_len);
return false;
}
void gnrc_rpl_recv_DAO_ACK(gnrc_rpl_dao_ack_t *dao_ack, kernel_pid_t iface, uint16_t len)
{
(void)iface;

View File

@ -0,0 +1,147 @@
/*
* Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.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_gnrc_rpl
* @{
*
* @file
* @brief RPL control message validation functions
*
* @author Cenk Gündoğan <mail@cgundogan.de>
*/
#ifndef GNRC_RPL_VALIDATION_H_
#define GNRC_RPL_VALIDATION_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "net/gnrc/rpl/structs.h"
#include "net/gnrc/icmpv6.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/**
* @brief Checks validity of DIS control messages
*
* @param[in] dis The DIS control message
* @param[in] len Length of the DIS control message
*
* @return true, if @p dis is valid
* @return false, otherwise
*/
static inline bool gnrc_rpl_validation_DIS(gnrc_rpl_dis_t *dis, uint16_t len)
{
uint16_t expected_len = sizeof(*dis) + sizeof(icmpv6_hdr_t);
if (expected_len <= len) {
return true;
}
DEBUG("RPL: wrong DIS len: %d, expected: %d\n", len, expected_len);
return false;
}
/**
* @brief Checks validity of control message options
*
* @param[in] msg_type Type of the control message
* @param[in] inst The RPL instance
* @param[in] opt Options of the control message
* @param[in] len Length of the options
*
* @return true, if @p opt is valid
* @return false, otherwise
*/
bool gnrc_rpl_validation_options(int msg_type, gnrc_rpl_instance_t *inst,
gnrc_rpl_opt_t *opt, uint16_t len);
/**
* @brief Checks validity of DIO control messages
*
* @param[in] dio The DIO control message
* @param[in] len Length of the DIO control message
*
* @return true, if @p dio is valid
* @return false, otherwise
*/
static inline bool gnrc_rpl_validation_DIO(gnrc_rpl_dio_t *dio, uint16_t len)
{
uint16_t expected_len = sizeof(*dio) + sizeof(icmpv6_hdr_t);
if (expected_len <= len) {
return true;
}
DEBUG("RPL: wrong DIO len: %d, expected: %d\n", len, expected_len);
return false;
}
/**
* @brief Checks validity of DAO control messages
*
* @param[in] dao The DAO control message
* @param[in] len Length of the DAO control message
*
* @return true, if @p dao is valid
* @return false, otherwise
*/
static inline bool gnrc_rpl_validation_DAO(gnrc_rpl_dao_t *dao, uint16_t len)
{
uint16_t expected_len = sizeof(*dao) + sizeof(icmpv6_hdr_t);
if ((dao->k_d_flags & GNRC_RPL_DAO_D_BIT)) {
expected_len += sizeof(ipv6_addr_t);
}
if (expected_len <= len) {
return true;
}
DEBUG("RPL: wrong DAO len: %d, expected: %d\n", len, expected_len);
return false;
}
/**
* @brief Checks validity of DAO-ACK control messages
*
* @param[in] dao_ack The DAO-ACK control message
* @param[in] len Length of the DAO-ACK control message
*
* @return true, if @p dao_ack is valid
* @return false, otherwise
*/
static inline bool gnrc_rpl_validation_DAO_ACK(gnrc_rpl_dao_ack_t *dao_ack, uint16_t len)
{
uint16_t expected_len = sizeof(*dao_ack) + sizeof(icmpv6_hdr_t);
if ((dao_ack->d_reserved & GNRC_RPL_DAO_ACK_D_BIT)) {
expected_len += sizeof(ipv6_addr_t);
}
if (expected_len == len) {
return true;
}
DEBUG("RPL: wrong DAO-ACK len: %d, expected: %d\n", len, expected_len);
return false;
}
#ifdef __cplusplus
}
#endif
#endif /* GNRC_RPL_VALIDATION_H_ */
/** @} */

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2016 Cenk Gündoğan <mail@cgundogan.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
*
* @author Cenk Gündoğan <mail@cgundogan.de>
*/
#include "net/gnrc/icmpv6.h"
#include "net/gnrc/ipv6.h"
#include "net/gnrc/rpl.h"
#include "gnrc_rpl_internal/validation.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#if ENABLE_DEBUG
static char addr_str[IPV6_ADDR_MAX_STR_LEN];
#endif
bool gnrc_rpl_validation_options(int msg_type, gnrc_rpl_instance_t *inst,
gnrc_rpl_opt_t *opt, uint16_t len)
{
uint16_t expected_len = 0;
while(expected_len < len) {
switch(opt->type) {
case (GNRC_RPL_OPT_PAD1):
expected_len += 1;
opt = (gnrc_rpl_opt_t *) (((uint8_t *) opt) + 1);
continue;
case (GNRC_RPL_OPT_DODAG_CONF):
if (msg_type != GNRC_RPL_ICMPV6_CODE_DIO) {
DEBUG("RPL: DODAG CONF DIO option not expected\n");
return false;
}
if (opt->length != GNRC_RPL_OPT_DODAG_CONF_LEN) {
DEBUG("RPL: wrong DIO option (DODAG CONF) len: %d, expected: %d\n",
opt->length, GNRC_RPL_OPT_DODAG_CONF_LEN);
return false;
}
break;
case (GNRC_RPL_OPT_PREFIX_INFO):
if (msg_type != GNRC_RPL_ICMPV6_CODE_DIO) {
DEBUG("RPL: PREFIX INFO DIO option not expected\n");
return false;
}
if (opt->length != GNRC_RPL_OPT_PREFIX_INFO_LEN) {
DEBUG("RPL: wrong DIO option (PREFIX INFO) len: %d, expected: %d\n",
opt->length, GNRC_RPL_OPT_PREFIX_INFO_LEN);
return false;
}
break;
case (GNRC_RPL_OPT_TARGET):
if (msg_type != GNRC_RPL_ICMPV6_CODE_DAO) {
DEBUG("RPL: RPL TARGET DAO option not expected\n");
return false;
}
if (opt->length > GNRC_RPL_OPT_TARGET_LEN) {
DEBUG("RPL: wrong DAO option (RPL TARGET) len: %d, expected (max): %d\n",
opt->length, GNRC_RPL_OPT_TARGET_LEN);
return false;
}
break;
case (GNRC_RPL_OPT_TRANSIT):
if (msg_type != GNRC_RPL_ICMPV6_CODE_DAO) {
DEBUG("RPL: RPL TRANSIT INFO DAO option not expected\n");
return false;
}
uint8_t parent_addr = 0;
if (inst->mop == GNRC_RPL_MOP_NON_STORING_MODE) {
parent_addr = sizeof(ipv6_addr_t);
}
if (opt->length != (GNRC_RPL_OPT_TRANSIT_INFO_LEN + parent_addr)) {
DEBUG("RPL: wrong DAO option (TRANSIT INFO) len: %d, expected: %d\n",
opt->length, (GNRC_RPL_OPT_TRANSIT_INFO_LEN + parent_addr));
return false;
}
break;
default:
break;
}
expected_len += opt->length + sizeof(gnrc_rpl_opt_t);
opt = (gnrc_rpl_opt_t *) (((uint8_t *) (opt + 1)) + opt->length);
}
if (expected_len == len) {
return true;
}
DEBUG("RPL: wrong options len: %d, expected: %d\n", len, expected_len);
return false;
}
/**
* @}
*/