Merge pull request #3667 from cgundogan/pr/rpl/control_message_validity_checks
rpl: control message validity checks
This commit is contained in:
commit
2c73d2ad15
@ -419,8 +419,9 @@ void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, ipv6_addr_t *src, uint16_t len);
|
|||||||
* @brief Parse a DAO-ACK.
|
* @brief Parse a DAO-ACK.
|
||||||
*
|
*
|
||||||
* @param[in] dao_ack Pointer to the DAO-ACK message.
|
* @param[in] dao_ack Pointer to the DAO-ACK message.
|
||||||
|
* @param[in] len Length of the IPv6 packet.
|
||||||
*/
|
*/
|
||||||
void gnrc_rpl_recv_DAO_ACK(gnrc_rpl_dao_ack_t *dao_ack);
|
void gnrc_rpl_recv_DAO_ACK(gnrc_rpl_dao_ack_t *dao_ack, uint16_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Delay the DAO sending interval
|
* @brief Delay the DAO sending interval
|
||||||
|
|||||||
@ -133,7 +133,8 @@ static void _receive(gnrc_pktsnip_t *icmpv6)
|
|||||||
break;
|
break;
|
||||||
case GNRC_RPL_ICMPV6_CODE_DAO_ACK:
|
case GNRC_RPL_ICMPV6_CODE_DAO_ACK:
|
||||||
DEBUG("RPL: DAO-ACK received\n");
|
DEBUG("RPL: DAO-ACK received\n");
|
||||||
gnrc_rpl_recv_DAO_ACK((gnrc_rpl_dao_ack_t *)(icmpv6_hdr + 1));
|
gnrc_rpl_recv_DAO_ACK((gnrc_rpl_dao_ack_t *)(icmpv6_hdr + 1),
|
||||||
|
byteorder_ntohs(ipv6_hdr->len));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG("RPL: Unknown ICMPV6 code received\n");
|
DEBUG("RPL: Unknown ICMPV6 code received\n");
|
||||||
|
|||||||
@ -36,6 +36,8 @@ static char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
|||||||
#define GNRC_RPL_MOP_SHIFT (3)
|
#define GNRC_RPL_MOP_SHIFT (3)
|
||||||
#define GNRC_RPL_OPT_DODAG_CONF_LEN (14)
|
#define GNRC_RPL_OPT_DODAG_CONF_LEN (14)
|
||||||
#define GNRC_RPL_OPT_PREFIX_INFO_LEN (30)
|
#define GNRC_RPL_OPT_PREFIX_INFO_LEN (30)
|
||||||
|
#define GNRC_RPL_OPT_TARGET_LEN (18)
|
||||||
|
#define GNRC_RPL_OPT_TRANSIT_INFO_LEN (4)
|
||||||
#define GNRC_RPL_SHIFTED_MOP_MASK (0x7)
|
#define GNRC_RPL_SHIFTED_MOP_MASK (0x7)
|
||||||
#define GNRC_RPL_PRF_MASK (0x7)
|
#define GNRC_RPL_PRF_MASK (0x7)
|
||||||
#define GNRC_RPL_PREFIX_AUTO_ADDRESS_BIT (1 << 6)
|
#define GNRC_RPL_PREFIX_AUTO_ADDRESS_BIT (1 << 6)
|
||||||
@ -194,12 +196,29 @@ void gnrc_rpl_send_DIS(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination)
|
|||||||
gnrc_rpl_send(pkt, NULL, destination, (dodag ? &dodag->dodag_id : NULL));
|
gnrc_rpl_send(pkt, NULL, destination, (dodag ? &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, ipv6_addr_t *src, ipv6_addr_t *dst, uint16_t len)
|
void gnrc_rpl_recv_DIS(gnrc_rpl_dis_t *dis, ipv6_addr_t *src, ipv6_addr_t *dst, uint16_t len)
|
||||||
{
|
{
|
||||||
/* TODO handle Solicited Information Option */
|
/* TODO handle Solicited Information Option */
|
||||||
(void) dis;
|
(void) dis;
|
||||||
(void) len;
|
(void) len;
|
||||||
|
|
||||||
|
if (!_gnrc_rpl_check_DIS_validity(dis, len)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ipv6_addr_is_multicast(dst)) {
|
if (ipv6_addr_is_multicast(dst)) {
|
||||||
for (uint8_t i = 0; i < GNRC_RPL_DODAGS_NUMOF; ++i) {
|
for (uint8_t i = 0; i < GNRC_RPL_DODAGS_NUMOF; ++i) {
|
||||||
if (gnrc_rpl_dodags[i].state != 0) {
|
if (gnrc_rpl_dodags[i].state != 0) {
|
||||||
@ -217,6 +236,92 @@ void gnrc_rpl_recv_DIS(gnrc_rpl_dis_t *dis, ipv6_addr_t *src, ipv6_addr_t *dst,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _gnrc_rpl_check_options_validity(int msg_type, gnrc_rpl_dodag_t *dodag,
|
||||||
|
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 (dodag->instance->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 */
|
/** @todo allow target prefixes in target options to be of variable length */
|
||||||
bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt, uint16_t len,
|
bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt, uint16_t len,
|
||||||
ipv6_addr_t *src)
|
ipv6_addr_t *src)
|
||||||
@ -224,30 +329,25 @@ bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt,
|
|||||||
uint16_t l = 0;
|
uint16_t l = 0;
|
||||||
gnrc_rpl_opt_target_t *first_target = NULL;
|
gnrc_rpl_opt_target_t *first_target = NULL;
|
||||||
eui64_t iid;
|
eui64_t iid;
|
||||||
while(l < len) {
|
kernel_pid_t if_id = KERNEL_PID_UNDEF;
|
||||||
if ((opt->type != GNRC_RPL_OPT_PAD1) && (len < opt->length + sizeof(gnrc_rpl_opt_t) + l)) {
|
|
||||||
/* return false to delete the dodag,
|
|
||||||
* because former options may also contain errors */
|
|
||||||
DEBUG("RPL: Wrong option length encountered\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!_gnrc_rpl_check_options_validity(msg_type, dodag, opt, len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(l < len) {
|
||||||
switch(opt->type) {
|
switch(opt->type) {
|
||||||
case (GNRC_RPL_OPT_PAD1): {
|
case (GNRC_RPL_OPT_PAD1):
|
||||||
DEBUG("RPL: PAD1 option parsed\n");
|
DEBUG("RPL: PAD1 option parsed\n");
|
||||||
l += 1;
|
l += 1;
|
||||||
opt = (gnrc_rpl_opt_t *) (((uint8_t *) opt) + 1);
|
opt = (gnrc_rpl_opt_t *) (((uint8_t *) opt) + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
case (GNRC_RPL_OPT_PADN): {
|
case (GNRC_RPL_OPT_PADN):
|
||||||
DEBUG("RPL: PADN option parsed\n");
|
DEBUG("RPL: PADN option parsed\n");
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case (GNRC_RPL_OPT_DODAG_CONF): {
|
case (GNRC_RPL_OPT_DODAG_CONF):
|
||||||
if (msg_type != GNRC_RPL_ICMPV6_CODE_DIO) {
|
|
||||||
DEBUG("RPL: Ignore DODAG CONF DIO option\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
DEBUG("RPL: DODAG CONF DIO option parsed\n");
|
DEBUG("RPL: DODAG CONF DIO option parsed\n");
|
||||||
gnrc_rpl_opt_dodag_conf_t *dc = (gnrc_rpl_opt_dodag_conf_t *) opt;
|
gnrc_rpl_opt_dodag_conf_t *dc = (gnrc_rpl_opt_dodag_conf_t *) opt;
|
||||||
gnrc_rpl_of_t *of = gnrc_rpl_get_of_for_ocp(byteorder_ntohs(dc->ocp));
|
gnrc_rpl_of_t *of = gnrc_rpl_get_of_for_ocp(byteorder_ntohs(dc->ocp));
|
||||||
@ -269,16 +369,12 @@ bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt,
|
|||||||
dodag->trickle.Imax = dodag->dio_interval_doubl;
|
dodag->trickle.Imax = dodag->dio_interval_doubl;
|
||||||
dodag->trickle.k = dodag->dio_redun;
|
dodag->trickle.k = dodag->dio_redun;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case (GNRC_RPL_OPT_PREFIX_INFO): {
|
case (GNRC_RPL_OPT_PREFIX_INFO):
|
||||||
if (msg_type != GNRC_RPL_ICMPV6_CODE_DIO) {
|
|
||||||
DEBUG("RPL: Ignore Prefix Information DIO option\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
DEBUG("RPL: Prefix Information DIO option parsed\n");
|
DEBUG("RPL: Prefix Information DIO option parsed\n");
|
||||||
gnrc_rpl_opt_prefix_info_t *pi = (gnrc_rpl_opt_prefix_info_t *) opt;
|
gnrc_rpl_opt_prefix_info_t *pi = (gnrc_rpl_opt_prefix_info_t *) opt;
|
||||||
ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR;
|
ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR;
|
||||||
kernel_pid_t if_id = gnrc_ipv6_netif_find_by_addr(NULL, &all_RPL_nodes);
|
if_id = gnrc_ipv6_netif_find_by_addr(NULL, &all_RPL_nodes);
|
||||||
/* check for the auto address-configuration flag */
|
/* check for the auto address-configuration flag */
|
||||||
if ((gnrc_netapi_get(if_id, NETOPT_IPV6_IID, 0, &iid, sizeof(eui64_t)) < 0) &&
|
if ((gnrc_netapi_get(if_id, NETOPT_IPV6_IID, 0, &iid, sizeof(eui64_t)) < 0) &&
|
||||||
!(pi->LAR_flags & GNRC_RPL_PREFIX_AUTO_ADDRESS_BIT)) {
|
!(pi->LAR_flags & GNRC_RPL_PREFIX_AUTO_ADDRESS_BIT)) {
|
||||||
@ -288,14 +384,10 @@ bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt,
|
|||||||
gnrc_ipv6_netif_add_addr(if_id, &pi->prefix, pi->prefix_len, 0);
|
gnrc_ipv6_netif_add_addr(if_id, &pi->prefix, pi->prefix_len, 0);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case (GNRC_RPL_OPT_TARGET): {
|
case (GNRC_RPL_OPT_TARGET):
|
||||||
if (msg_type != GNRC_RPL_ICMPV6_CODE_DAO) {
|
|
||||||
DEBUG("RPL: Ignore RPL TARGET DAO option\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
DEBUG("RPL: RPL TARGET DAO option parsed\n");
|
DEBUG("RPL: RPL TARGET DAO option parsed\n");
|
||||||
kernel_pid_t if_id = gnrc_ipv6_netif_find_by_prefix(NULL, &dodag->dodag_id);
|
if_id = gnrc_ipv6_netif_find_by_prefix(NULL, &dodag->dodag_id);
|
||||||
if (if_id == KERNEL_PID_UNDEF) {
|
if (if_id == KERNEL_PID_UNDEF) {
|
||||||
DEBUG("RPL: no interface found for the configured DODAG id\n");
|
DEBUG("RPL: no interface found for the configured DODAG id\n");
|
||||||
return false;
|
return false;
|
||||||
@ -312,12 +404,8 @@ bool _parse_options(int msg_type, gnrc_rpl_dodag_t *dodag, gnrc_rpl_opt_t *opt,
|
|||||||
(dodag->default_lifetime * dodag->lifetime_unit) *
|
(dodag->default_lifetime * dodag->lifetime_unit) *
|
||||||
SEC_IN_MS);
|
SEC_IN_MS);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case (GNRC_RPL_OPT_TRANSIT): {
|
case (GNRC_RPL_OPT_TRANSIT):
|
||||||
if (msg_type != GNRC_RPL_ICMPV6_CODE_DAO) {
|
|
||||||
DEBUG("RPL: Ignore RPL TRANSIT INFO DAO option\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
DEBUG("RPL: RPL TRANSIT INFO DAO option parsed\n");
|
DEBUG("RPL: RPL TRANSIT INFO DAO option parsed\n");
|
||||||
gnrc_rpl_opt_transit_t *transit = (gnrc_rpl_opt_transit_t *) opt;
|
gnrc_rpl_opt_transit_t *transit = (gnrc_rpl_opt_transit_t *) opt;
|
||||||
if (first_target == NULL) {
|
if (first_target == NULL) {
|
||||||
@ -338,7 +426,7 @@ a preceding RPL TARGET DAO option\n");
|
|||||||
|
|
||||||
first_target = NULL;
|
first_target = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
l += opt->length + sizeof(gnrc_rpl_opt_t);
|
l += opt->length + sizeof(gnrc_rpl_opt_t);
|
||||||
opt = (gnrc_rpl_opt_t *) (((uint8_t *) (opt + 1)) + opt->length);
|
opt = (gnrc_rpl_opt_t *) (((uint8_t *) (opt + 1)) + opt->length);
|
||||||
@ -346,11 +434,28 @@ a preceding RPL TARGET DAO option\n");
|
|||||||
return true;
|
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, ipv6_addr_t *src, uint16_t len)
|
void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, ipv6_addr_t *src, uint16_t len)
|
||||||
{
|
{
|
||||||
gnrc_rpl_instance_t *inst = NULL;
|
gnrc_rpl_instance_t *inst = NULL;
|
||||||
gnrc_rpl_dodag_t *dodag = NULL;
|
gnrc_rpl_dodag_t *dodag = NULL;
|
||||||
|
|
||||||
|
if (!_gnrc_rpl_check_DIO_validity(dio, len)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
len -= (sizeof(gnrc_rpl_dio_t) + sizeof(icmpv6_hdr_t));
|
len -= (sizeof(gnrc_rpl_dio_t) + sizeof(icmpv6_hdr_t));
|
||||||
|
|
||||||
if (gnrc_rpl_instance_add(dio->instance_id, &inst)) {
|
if (gnrc_rpl_instance_add(dio->instance_id, &inst)) {
|
||||||
@ -641,10 +746,32 @@ void gnrc_rpl_send_DAO_ACK(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *destination, ui
|
|||||||
gnrc_rpl_send(pkt, NULL, destination, &dodag->dodag_id);
|
gnrc_rpl_send(pkt, 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, ipv6_addr_t *src, uint16_t len)
|
void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, ipv6_addr_t *src, uint16_t len)
|
||||||
{
|
{
|
||||||
gnrc_rpl_instance_t *inst = NULL;
|
gnrc_rpl_instance_t *inst = NULL;
|
||||||
gnrc_rpl_dodag_t *dodag = NULL;
|
gnrc_rpl_dodag_t *dodag = NULL;
|
||||||
|
|
||||||
|
if (!_gnrc_rpl_check_DAO_validity(dao, len)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gnrc_rpl_opt_t *opts = (gnrc_rpl_opt_t *) (dao + 1);
|
gnrc_rpl_opt_t *opts = (gnrc_rpl_opt_t *) (dao + 1);
|
||||||
|
|
||||||
if ((inst = gnrc_rpl_instance_get(dao->instance_id)) == NULL) {
|
if ((inst = gnrc_rpl_instance_get(dao->instance_id)) == NULL) {
|
||||||
@ -672,8 +799,7 @@ void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, ipv6_addr_t *src, uint16_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DAO, dodag, opts, len, src)) {
|
if(!_parse_options(GNRC_RPL_ICMPV6_CODE_DAO, dodag, opts, len, src)) {
|
||||||
DEBUG("RPL: Error encountered during DAO option parsing - remove DODAG\n");
|
DEBUG("RPL: Error encountered during DAO option parsing - ignore DAO\n");
|
||||||
gnrc_rpl_dodag_remove(dodag);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,10 +811,32 @@ void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, ipv6_addr_t *src, uint16_t len)
|
|||||||
gnrc_rpl_delay_dao(dodag);
|
gnrc_rpl_delay_dao(dodag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gnrc_rpl_recv_DAO_ACK(gnrc_rpl_dao_ack_t *dao_ack)
|
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, uint16_t len)
|
||||||
{
|
{
|
||||||
gnrc_rpl_instance_t *inst = NULL;
|
gnrc_rpl_instance_t *inst = NULL;
|
||||||
gnrc_rpl_dodag_t *dodag = NULL;
|
gnrc_rpl_dodag_t *dodag = NULL;
|
||||||
|
|
||||||
|
if (!_gnrc_rpl_check_DAO_ACK_validity(dao_ack, len)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((inst = gnrc_rpl_instance_get(dao_ack->instance_id)) == NULL) {
|
if ((inst = gnrc_rpl_instance_get(dao_ack->instance_id)) == NULL) {
|
||||||
DEBUG("RPL: DAO-ACK with unknown instance id (%d) received\n", dao_ack->instance_id);
|
DEBUG("RPL: DAO-ACK with unknown instance id (%d) received\n", dao_ack->instance_id);
|
||||||
return;
|
return;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user