void send_DAO_ACK(ipv6_addr_t *destination) { DEBUG("%s, %d: Send DAO ACK\n", __FILE__, __LINE__); rpl_dodag_t *my_dodag; my_dodag = rpl_get_my_dodag(); if (my_dodag == NULL) { return; } mutex_lock(&rpl_send_mutex); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DAO_ACK; rpl_send_dao_ack_buf = get_rpl_send_dao_ack_buf(); rpl_send_dao_ack_buf->rpl_instanceid = my_dodag->instance->id; rpl_send_dao_ack_buf->d_reserved = 0; rpl_send_dao_ack_buf->dao_sequence = my_dodag->dao_seq; rpl_send_dao_ack_buf->status = 0; uint16_t plen = ICMPV6_HDR_LEN + DAO_ACK_LEN; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); mutex_unlock(&rpl_send_mutex); }
void rpl_send_DAO_ACK(rpl_dodag_t *my_dodag, ipv6_addr_t *destination) { #if ENABLE_DEBUG if (destination) { DEBUGF("Send DAO ACK to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, destination)); } #endif if (my_dodag == NULL) { return; } icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DAO_ACK; rpl_send_dao_ack_buf = get_rpl_send_dao_ack_buf(); rpl_send_dao_ack_buf->rpl_instanceid = my_dodag->instance->id; rpl_send_dao_ack_buf->d_reserved = 0; rpl_send_dao_ack_buf->dao_sequence = my_dodag->dao_seq; rpl_send_dao_ack_buf->status = 0; uint16_t plen = ICMPV6_HDR_LEN + DAO_ACK_LEN; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); }
void send_DAO_ACK(ipv6_addr_t *destination) { char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("%s\n", ipv6_addr_to_str(addr_str, destination)); rpl_dodag_t *my_dodag; my_dodag = rpl_get_my_dodag(); if (my_dodag == NULL) { return; } mutex_lock(&rpl_send_mutex); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DAO_ACK; icmp_send_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); rpl_send_dao_ack_buf = get_rpl_send_dao_ack_buf(); rpl_send_dao_ack_buf->rpl_instanceid = my_dodag->instance->id; rpl_send_dao_ack_buf->d_reserved = 0; rpl_send_dao_ack_buf->dao_sequence = my_dodag->dao_seq; rpl_send_dao_ack_buf->status = 0; uint16_t plen = ICMPV6_HDR_LEN + DIS_BASE_LEN; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6, NULL); mutex_unlock(&rpl_send_mutex); }
/* obligatory for each mode. normally not modified */ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_t next_header) { uint8_t *p_ptr; ipv6_send_buf = get_rpl_send_ipv6_buf(); p_ptr = get_rpl_send_payload_buf(ipv6_ext_hdr_len); ipv6_send_buf->version_trafficclass = IPV6_VER; ipv6_send_buf->trafficclass_flowlabel = 0; ipv6_send_buf->flowlabel = 0; ipv6_send_buf->nextheader = next_header; ipv6_send_buf->hoplimit = MULTIHOP_HOPLIMIT; ipv6_send_buf->length = HTONS(p_len); memcpy(&(ipv6_send_buf->destaddr), destination, 16); ipv6_net_if_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->checksum = icmpv6_csum(ipv6_send_buf, icmp_send_buf); /* The packet was "assembled" in rpl_%mode%.c. Therefore rpl_send_buf was used. * Therefore memcpy is not needed because the payload is at the * right memory location already. */ if (p_ptr != payload) { memcpy(p_ptr, payload, p_len); } ipv6_send_packet(ipv6_send_buf, NULL); }
/* obligatory for each mode. normally not modified */ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_t next_header) { uint8_t *p_ptr; ipv6_send_buf = get_rpl_send_ipv6_buf(); p_ptr = get_rpl_send_payload_buf(ipv6_ext_hdr_len); DEBUGF("Trying to send to destination: %s\n", ipv6_addr_to_str(addr_str_mode, IPV6_MAX_ADDR_STR_LEN, destination)); ipv6_send_buf->version_trafficclass = IPV6_VER; ipv6_send_buf->trafficclass_flowlabel = 0; ipv6_send_buf->flowlabel = 0; ipv6_send_buf->nextheader = next_header; ipv6_send_buf->hoplimit = MULTIHOP_HOPLIMIT; ipv6_send_buf->length = HTONS(p_len); memcpy(&(ipv6_send_buf->destaddr), destination, 16); ipv6_net_if_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->checksum = icmpv6_csum(ipv6_send_buf, icmp_send_buf); /* The packet was "assembled" in rpl_%mode%.c. Therefore rpl_send_buf was used. * Therefore memcpy is not needed because the payload is at the * right memory location already. */ if (p_ptr != payload) { memcpy(p_ptr, payload, p_len); } if (ipv6_addr_is_multicast(&ipv6_send_buf->destaddr)) { ipv6_send_packet(ipv6_send_buf, NULL); } else { /* find appropriate next hop before sending */ ipv6_addr_t *next_hop = rpl_get_next_hop(&ipv6_send_buf->destaddr); DEBUGF("Trying to send to destination: %s\n", ipv6_addr_to_str(addr_str_mode, IPV6_MAX_ADDR_STR_LEN, next_hop)); if (next_hop == NULL) { if (i_am_root) { DEBUGF("[Error] destination unknown: %s\n", ipv6_addr_to_str(addr_str_mode, IPV6_MAX_ADDR_STR_LEN, &ipv6_send_buf->destaddr)); return; } else { next_hop = rpl_get_my_preferred_parent(); if (next_hop == NULL) { DEBUGF("[Error] no preferred parent, dropping package\n"); return; } } } DEBUGF("Sending done (for RPL)\n"); ipv6_send_packet(ipv6_send_buf, NULL); } }
void rpl_send_DIO_mode(ipv6_addr_t *destination) { if (i_am_leaf) { return; } rpl_dodag_t *mydodag; icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); mydodag = rpl_get_my_dodag(); if (mydodag == NULL) { DEBUGF("Error - trying to send DIO without being part of a dodag.\n"); return; } icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DIO; rpl_send_dio_buf = get_rpl_send_dio_buf(); memset(rpl_send_dio_buf, 0, sizeof(*rpl_send_dio_buf)); DEBUGF("Sending DIO with "); rpl_send_dio_buf->rpl_instanceid = mydodag->instance->id; DEBUG("instance %02X ", rpl_send_dio_buf->rpl_instanceid); rpl_send_dio_buf->version_number = mydodag->version; rpl_send_dio_buf->rank = mydodag->my_rank; DEBUG("rank %04X\n", rpl_send_dio_buf->rank); rpl_send_dio_buf->g_mop_prf = (mydodag->grounded << RPL_GROUNDED_SHIFT) | (mydodag->mop << RPL_MOP_SHIFT) | mydodag->prf; rpl_send_dio_buf->dtsn = mydodag->dtsn; rpl_send_dio_buf->flags = 0; rpl_send_dio_buf->reserved = 0; rpl_send_dio_buf->dodagid = mydodag->dodag_id; int opt_hdr_len = 0; /* DODAG configuration option */ rpl_send_opt_dodag_conf_buf = get_rpl_send_opt_dodag_conf_buf(DIO_BASE_LEN); rpl_send_opt_dodag_conf_buf->type = RPL_OPT_DODAG_CONF; rpl_send_opt_dodag_conf_buf->length = RPL_OPT_DODAG_CONF_LEN; rpl_send_opt_dodag_conf_buf->flags_a_pcs = 0; rpl_send_opt_dodag_conf_buf->DIOIntDoubl = mydodag->dio_interval_doubling; rpl_send_opt_dodag_conf_buf->DIOIntMin = mydodag->dio_min; rpl_send_opt_dodag_conf_buf->DIORedun = mydodag->dio_redundancy; rpl_send_opt_dodag_conf_buf->MaxRankIncrease = mydodag->maxrankincrease; rpl_send_opt_dodag_conf_buf->MinHopRankIncrease = mydodag->minhoprankincrease; rpl_send_opt_dodag_conf_buf->ocp = mydodag->of->ocp; DEBUGF("Building done.\n"); rpl_send_opt_dodag_conf_buf->reserved = 0; rpl_send_opt_dodag_conf_buf->default_lifetime = mydodag->default_lifetime; rpl_send_opt_dodag_conf_buf->lifetime_unit = mydodag->lifetime_unit; opt_hdr_len += RPL_OPT_DODAG_CONF_LEN; uint16_t plen = ICMPV6_HDR_LEN + DIO_BASE_LEN + opt_hdr_len; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); }
void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_t next_header) { uint8_t *p_ptr; ipv6_send_buf = get_rpl_send_ipv6_buf(); p_ptr = get_rpl_send_payload_buf(ipv6_ext_hdr_len); uint16_t packet_length = 0; ipv6_send_buf->version_trafficclass = IPV6_VER; ipv6_send_buf->trafficclass_flowlabel = 0; ipv6_send_buf->flowlabel = 0; ipv6_send_buf->nextheader = next_header; ipv6_send_buf->hoplimit = MULTIHOP_HOPLIMIT; ipv6_send_buf->length = HTONS(p_len); memcpy(&(ipv6_send_buf->destaddr), destination, 16); ipv6_net_if_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->checksum = icmpv6_csum(ipv6_send_buf, icmp_send_buf); /* The packet was "assembled" in rpl.c. Therefore rpl_send_buf was used. * Therefore memcpy is not needed because the payload is at the * right memory location already. */ if (p_ptr != payload) { memcpy(p_ptr, payload, p_len); } packet_length = IPV6_HDR_LEN + p_len; if (ipv6_addr_is_multicast(&ipv6_send_buf->destaddr)) { ipv6_send_packet(ipv6_send_buf); } else { /* find appropriate next hop before sending */ ipv6_addr_t *next_hop = rpl_get_next_hop(&ipv6_send_buf->destaddr); if (next_hop == NULL) { if (i_am_root) { DEBUG("%s, %d: [Error] destination unknown\n", __FILE__, __LINE__); return; } else { next_hop = rpl_get_my_preferred_parent(); if (next_hop == NULL) { DEBUG("%s, %d: [Error] no preferred parent, dropping package\n", __FILE__, __LINE__); return; } } } ipv6_send_packet(ipv6_send_buf); } }
void rpl_send_DIS_mode(ipv6_addr_t *destination) { icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DIS; rpl_send_dis_buf = get_rpl_send_dis_buf(); uint16_t plen = ICMPV6_HDR_LEN + DIS_BASE_LEN; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); }
void send_DIO(ipv6_addr_t *destination) { mutex_lock(&rpl_send_mutex); rpl_dodag_t *mydodag; icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); mydodag = rpl_get_my_dodag(); if(mydodag == NULL) { printf("Error, trying to send DIO without being part of a dodag. This should not happen\n"); mutex_unlock(&rpl_send_mutex, 0); return; } icmp_send_buf->type = ICMP_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DIO; icmp_send_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6); rpl_send_dio_buf = get_rpl_send_dio_buf(); memset(rpl_send_dio_buf, 0, sizeof(*rpl_send_dio_buf)); rpl_send_dio_buf->rpl_instanceid = mydodag->instance->id; rpl_send_dio_buf->version_number = mydodag->version; rpl_send_dio_buf->rank = mydodag->my_rank; rpl_send_dio_buf->g_mop_prf = (mydodag->grounded << RPL_GROUNDED_SHIFT) | (mydodag->mop << RPL_MOP_SHIFT) | mydodag->prf; rpl_send_dio_buf->dtsn = mydodag->dtsn; rpl_send_dio_buf->flags = 0; rpl_send_dio_buf->reserved = 0; rpl_send_dio_buf->dodagid = mydodag->dodag_id; int opt_hdr_len = 0; /* DODAG Configuration Option! */ rpl_send_opt_dodag_conf_buf = get_rpl_send_opt_dodag_conf_buf(DIO_BASE_LEN); rpl_send_opt_dodag_conf_buf->type = RPL_OPT_DODAG_CONF; rpl_send_opt_dodag_conf_buf->length = RPL_OPT_DODAG_CONF_LEN; rpl_send_opt_dodag_conf_buf->flags_a_pcs = 0; rpl_send_opt_dodag_conf_buf->DIOIntDoubl = mydodag->dio_interval_doubling; rpl_send_opt_dodag_conf_buf->DIOIntMin = mydodag->dio_min; rpl_send_opt_dodag_conf_buf->DIORedun = mydodag->dio_redundancy; rpl_send_opt_dodag_conf_buf->MaxRankIncrease = mydodag->maxrankincrease; rpl_send_opt_dodag_conf_buf->MinHopRankIncrease = mydodag->minhoprankincrease; rpl_send_opt_dodag_conf_buf->ocp = mydodag->of->ocp; rpl_send_opt_dodag_conf_buf->reserved = 0; rpl_send_opt_dodag_conf_buf->default_lifetime = mydodag->default_lifetime; rpl_send_opt_dodag_conf_buf->lifetime_unit = mydodag->lifetime_unit; opt_hdr_len += RPL_OPT_LEN + RPL_OPT_DODAG_CONF_LEN; uint16_t plen = ICMPV6_HDR_LEN + DIO_BASE_LEN + opt_hdr_len; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, PROTO_NUM_ICMPV6, NULL); mutex_unlock(&rpl_send_mutex, 0); }
void send_DIS(ipv6_addr_t *destination) { DEBUG("%s, %d: Send DIS\n", __FILE__, __LINE__); mutex_lock(&rpl_send_mutex); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DIS; rpl_send_dis_buf = get_rpl_send_dis_buf(); uint16_t plen = ICMPV6_HDR_LEN + DIS_BASE_LEN; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); mutex_unlock(&rpl_send_mutex); }
void send_DIS(ipv6_addr_t *destination) { mutex_lock(&rpl_send_mutex); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DIS; icmp_send_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); rpl_send_dis_buf = get_rpl_send_dis_buf(); uint16_t plen = ICMPV6_HDR_LEN + DIS_BASE_LEN; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6, NULL); mutex_unlock(&rpl_send_mutex); }
void rpl_send_DIS(ipv6_addr_t *destination) { #if ENABLE_DEBUG if (destination) { DEBUGF("Send DIS to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, destination)); } #endif icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DIS; rpl_send_dis_buf = get_rpl_send_dis_buf(); uint16_t plen = ICMPV6_HDR_LEN + DIS_BASE_LEN; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); }
void rpl_send_DAO_ACK_mode(ipv6_addr_t *destination) { rpl_dodag_t *my_dodag; my_dodag = rpl_get_my_dodag(); if (my_dodag == NULL) { return; } icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DAO_ACK; rpl_send_dao_ack_buf = get_rpl_send_dao_ack_buf(); rpl_send_dao_ack_buf->rpl_instanceid = my_dodag->instance->id; rpl_send_dao_ack_buf->d_reserved = 0; rpl_send_dao_ack_buf->dao_sequence = my_dodag->dao_seq; rpl_send_dao_ack_buf->status = 0; uint16_t plen = ICMPV6_HDR_LEN + DAO_ACK_LEN; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); }
void rpl_send_DAO(rpl_dodag_t *my_dodag, ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime, uint8_t start_index) { #if RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE (void) start_index; #endif #if ENABLE_DEBUG if (destination) { DEBUGF("Send DAO to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, destination)); } #endif if (i_am_root) { return; } if (my_dodag == NULL) { DEBUGF("send_DAO: I have no my_dodag\n"); return; } if (destination == NULL) { #if RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE destination = &my_dodag->dodag_id; #else if (my_dodag->my_preferred_parent == NULL) { DEBUGF("send_DAO: my_dodag has no my_preferred_parent\n"); return; } destination = &my_dodag->my_preferred_parent->addr; #endif } if (default_lifetime) { lifetime = my_dodag->default_lifetime; } icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DAO; rpl_send_dao_buf = get_rpl_send_dao_buf(); memset(rpl_send_dao_buf, 0, sizeof(*rpl_send_dao_buf)); rpl_send_dao_buf->rpl_instanceid = my_dodag->instance->id; rpl_send_dao_buf->k_d_flags = 0x00; rpl_send_dao_buf->dao_sequence = my_dodag->dao_seq; uint16_t opt_len = 0; rpl_send_opt_target_buf = get_rpl_send_opt_target_buf(DAO_BASE_LEN); #if RPL_DEFAULT_MOP != RPL_MOP_NON_STORING_MODE /* add all targets from routing table as targets */ uint8_t entries = 0; uint8_t continue_index = 0; for (uint8_t i = start_index; i < rpl_max_routing_entries; i++) { if (rpl_get_routing_table()[i].used) { rpl_send_opt_target_buf->type = RPL_OPT_TARGET; rpl_send_opt_target_buf->length = RPL_OPT_TARGET_LEN; rpl_send_opt_target_buf->flags = 0x00; rpl_send_opt_target_buf->prefix_length = RPL_DODAG_ID_LEN; memcpy(&rpl_send_opt_target_buf->target, &rpl_get_routing_table()[i].address, sizeof(ipv6_addr_t)); opt_len += RPL_OPT_TARGET_LEN_WITH_OPT_LEN; rpl_send_opt_transit_buf = get_rpl_send_opt_transit_buf(DAO_BASE_LEN + opt_len); rpl_send_opt_transit_buf->type = RPL_OPT_TRANSIT; rpl_send_opt_transit_buf->length = (RPL_OPT_TRANSIT_LEN - sizeof(ipv6_addr_t)); rpl_send_opt_transit_buf->e_flags = 0x00; rpl_send_opt_transit_buf->path_control = 0x00; /* not used */ rpl_send_opt_transit_buf->path_sequence = 0x00; /* not used */ rpl_send_opt_transit_buf->path_lifetime = lifetime; opt_len += (RPL_OPT_TRANSIT_LEN_WITH_OPT_LEN - sizeof(ipv6_addr_t)); rpl_send_opt_target_buf = get_rpl_send_opt_target_buf(DAO_BASE_LEN + opt_len); entries++; } /* Split DAO, so packages don't get too big. * The value 5 is based on experience. */ if (entries >= 5) { continue_index = i + 1; break; } } #endif /* add own address */ rpl_send_opt_target_buf->type = RPL_OPT_TARGET; rpl_send_opt_target_buf->length = RPL_OPT_TARGET_LEN; rpl_send_opt_target_buf->flags = 0x00; rpl_send_opt_target_buf->prefix_length = RPL_DODAG_ID_LEN; if (!ipv6_addr_is_unspecified(&my_dodag->prefix)) { ipv6_addr_t tmp; ipv6_addr_set_by_eui64(&tmp, rpl_if_id, &my_dodag->prefix); memcpy(&rpl_send_opt_target_buf->target, &tmp, sizeof(ipv6_addr_t)); } else { memcpy(&rpl_send_opt_target_buf->target, &my_address, sizeof(ipv6_addr_t)); } opt_len += RPL_OPT_TARGET_LEN_WITH_OPT_LEN; rpl_send_opt_transit_buf = get_rpl_send_opt_transit_buf(DAO_BASE_LEN + opt_len); rpl_send_opt_transit_buf->type = RPL_OPT_TRANSIT; rpl_send_opt_transit_buf->e_flags = 0x00; rpl_send_opt_transit_buf->path_control = 0x00; rpl_send_opt_transit_buf->path_sequence = 0x00; rpl_send_opt_transit_buf->path_lifetime = lifetime; #if RPL_DEFAULT_MOP == RPL_MOP_NON_STORING_MODE rpl_send_opt_transit_buf->length = RPL_OPT_TRANSIT_LEN; memcpy(&rpl_send_opt_transit_buf->parent, &my_dodag->my_preferred_parent->addr, sizeof(ipv6_addr_t)); opt_len += RPL_OPT_TRANSIT_LEN_WITH_OPT_LEN; #else rpl_send_opt_transit_buf->length = (RPL_OPT_TRANSIT_LEN - sizeof(ipv6_addr_t)); opt_len += (RPL_OPT_TRANSIT_LEN_WITH_OPT_LEN - sizeof(ipv6_addr_t)); #endif uint16_t plen = ICMPV6_HDR_LEN + DAO_BASE_LEN + opt_len; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); #if RPL_DEFAULT_MOP != RPL_MOP_NON_STORING_MODE if (continue_index > 1) { rpl_send_DAO(my_dodag, destination, lifetime, default_lifetime, continue_index); } #endif }
void rpl_send_DIO(rpl_dodag_t *mydodag, ipv6_addr_t *destination) { #if ENABLE_DEBUG if (destination) { DEBUGF("Send DIO to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, destination)); } #endif icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); if (mydodag == NULL) { DEBUGF("Error - trying to send DIO without being part of a dodag.\n"); return; } icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DIO; rpl_send_dio_buf = get_rpl_send_dio_buf(); memset(rpl_send_dio_buf, 0, sizeof(*rpl_send_dio_buf)); DEBUGF("Sending DIO with "); rpl_send_dio_buf->rpl_instanceid = mydodag->instance->id; DEBUG("instance %02X ", rpl_send_dio_buf->rpl_instanceid); rpl_send_dio_buf->version_number = mydodag->version; rpl_send_dio_buf->rank = byteorder_htons(mydodag->my_rank); DEBUG("rank %04X\n", byteorder_ntohs(rpl_send_dio_buf->rank)); rpl_send_dio_buf->g_mop_prf = (mydodag->grounded << RPL_GROUNDED_SHIFT) | (mydodag->mop << RPL_MOP_SHIFT) | mydodag->prf; rpl_send_dio_buf->dtsn = mydodag->dtsn; rpl_send_dio_buf->flags = 0; rpl_send_dio_buf->reserved = 0; rpl_send_dio_buf->dodagid = mydodag->dodag_id; int opt_hdr_len = 0; /* DODAG configuration option */ rpl_send_opt_dodag_conf_buf = get_rpl_send_opt_dodag_conf_buf(DIO_BASE_LEN); rpl_send_opt_dodag_conf_buf->type = RPL_OPT_DODAG_CONF; rpl_send_opt_dodag_conf_buf->length = RPL_OPT_DODAG_CONF_LEN; rpl_send_opt_dodag_conf_buf->flags_a_pcs = 0; rpl_send_opt_dodag_conf_buf->DIOIntDoubl = mydodag->dio_interval_doubling; rpl_send_opt_dodag_conf_buf->DIOIntMin = mydodag->dio_min; rpl_send_opt_dodag_conf_buf->DIORedun = mydodag->dio_redundancy; rpl_send_opt_dodag_conf_buf->MaxRankIncrease = byteorder_htons(mydodag->maxrankincrease); rpl_send_opt_dodag_conf_buf->MinHopRankIncrease = byteorder_htons(mydodag->minhoprankincrease); rpl_send_opt_dodag_conf_buf->ocp = byteorder_htons(mydodag->of->ocp); rpl_send_opt_dodag_conf_buf->reserved = 0; rpl_send_opt_dodag_conf_buf->default_lifetime = mydodag->default_lifetime; rpl_send_opt_dodag_conf_buf->lifetime_unit = byteorder_htons(mydodag->lifetime_unit); opt_hdr_len += RPL_OPT_DODAG_CONF_LEN_WITH_OPT_LEN; if (!ipv6_addr_is_unspecified(&mydodag->prefix)) { rpl_send_opt_prefix_information_buf = get_rpl_send_opt_prefix_information_buf(DIO_BASE_LEN + opt_hdr_len); rpl_send_opt_prefix_information_buf->type = RPL_OPT_PREFIX_INFO; rpl_send_opt_prefix_information_buf->length = RPL_OPT_PREFIX_INFO_LEN; rpl_send_opt_prefix_information_buf->flags = mydodag->prefix_flags; rpl_send_opt_prefix_information_buf->prefix = mydodag->prefix; rpl_send_opt_prefix_information_buf->prefix_length = mydodag->prefix_length; rpl_send_opt_prefix_information_buf->preferred_lifetime = byteorder_htonl(mydodag->prefix_preferred_lifetime); rpl_send_opt_prefix_information_buf->valid_lifetime = byteorder_htonl(mydodag->prefix_valid_lifetime); opt_hdr_len += RPL_OPT_PREFIX_INFO_LEN_WITH_OPT_LEN; } uint16_t plen = ICMPV6_HDR_LEN + DIO_BASE_LEN + opt_hdr_len; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); }
void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime, uint8_t start_index) { if (i_am_root) { return; } mutex_lock(&rpl_send_mutex); rpl_dodag_t *my_dodag; my_dodag = rpl_get_my_dodag(); if (destination == NULL) { destination = &my_dodag->my_preferred_parent->addr; } if (default_lifetime) { lifetime = my_dodag->default_lifetime; } icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DAO; icmp_send_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); if (my_dodag == NULL) { mutex_unlock(&rpl_send_mutex); return; } rpl_send_dao_buf = get_rpl_send_dao_buf(); memset(rpl_send_dao_buf, 0, sizeof(*rpl_send_dao_buf)); rpl_send_dao_buf->rpl_instanceid = my_dodag->instance->id; rpl_send_dao_buf->k_d_flags = 0x00; rpl_send_dao_buf->dao_sequence = my_dodag->dao_seq; uint16_t opt_len = 0; rpl_send_opt_target_buf = get_rpl_send_opt_target_buf(DAO_BASE_LEN); /* add all targets from routing table as targets */ uint8_t entries = 0; uint8_t continue_index = 0; for (uint8_t i = start_index; i < RPL_MAX_ROUTING_ENTRIES; i++) { if (routing_table[i].used) { rpl_send_opt_target_buf->type = RPL_OPT_TARGET; rpl_send_opt_target_buf->length = RPL_OPT_TARGET_LEN; rpl_send_opt_target_buf->flags = 0x00; rpl_send_opt_target_buf->prefix_length = RPL_DODAG_ID_LEN; memcpy(&rpl_send_opt_target_buf->target, &routing_table[i].address, sizeof(ipv6_addr_t)); opt_len += RPL_OPT_TARGET_LEN + 2; rpl_send_opt_transit_buf = get_rpl_send_opt_transit_buf(DAO_BASE_LEN + opt_len); rpl_send_opt_transit_buf->type = RPL_OPT_TRANSIT; rpl_send_opt_transit_buf->length = RPL_OPT_TRANSIT_LEN; rpl_send_opt_transit_buf->e_flags = 0x00; rpl_send_opt_transit_buf->path_control = 0x00; /* not used */ rpl_send_opt_transit_buf->path_sequence = 0x00; /* not used */ rpl_send_opt_transit_buf->path_lifetime = lifetime; opt_len += RPL_OPT_TRANSIT_LEN + 2; rpl_send_opt_target_buf = get_rpl_send_opt_target_buf(DAO_BASE_LEN + opt_len); entries++; } /* Split DAO, so packages don't get too big. * The value 5 is based on experience. */ if (entries >= 5) { continue_index = i + 1; break; } } /* add own address */ rpl_send_opt_target_buf->type = RPL_OPT_TARGET; rpl_send_opt_target_buf->length = RPL_OPT_TARGET_LEN; rpl_send_opt_target_buf->flags = 0x00; rpl_send_opt_target_buf->prefix_length = RPL_DODAG_ID_LEN; memcpy(&rpl_send_opt_target_buf->target, &my_address, sizeof(ipv6_addr_t)); opt_len += RPL_OPT_TARGET_LEN + 2; rpl_send_opt_transit_buf = get_rpl_send_opt_transit_buf(DAO_BASE_LEN + opt_len); rpl_send_opt_transit_buf->type = RPL_OPT_TRANSIT; rpl_send_opt_transit_buf->length = RPL_OPT_TRANSIT_LEN; rpl_send_opt_transit_buf->e_flags = 0x00; rpl_send_opt_transit_buf->path_control = 0x00; rpl_send_opt_transit_buf->path_sequence = 0x00; rpl_send_opt_transit_buf->path_lifetime = lifetime; opt_len += RPL_OPT_TRANSIT_LEN + 2; uint16_t plen = ICMPV6_HDR_LEN + DAO_BASE_LEN + opt_len; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6, NULL); mutex_unlock(&rpl_send_mutex); if (continue_index > 1) { send_DAO(destination, lifetime, default_lifetime, continue_index); } }
void rpl_send_DAO_mode(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime, uint8_t start_index) { (void) start_index; if (i_am_root) { return; } /* TODO: take advantage of start_index, by now not used in non-storing mode start_index++; */ rpl_dodag_t *my_dodag; if ((my_dodag = rpl_get_my_dodag()) == NULL) { DEBUGF("send_DAO: Not part of a DODAG\n"); return; } if (destination == NULL) { destination = &my_dodag->dodag_id; } if (default_lifetime) { lifetime = my_dodag->default_lifetime; } icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->type = ICMPV6_TYPE_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DAO; rpl_send_dao_buf = get_rpl_send_dao_buf(); memset(rpl_send_dao_buf, 0, sizeof(*rpl_send_dao_buf)); rpl_send_dao_buf->rpl_instanceid = my_dodag->instance->id; rpl_send_dao_buf->k_d_flags = 0x00; rpl_send_dao_buf->dao_sequence = my_dodag->dao_seq; uint16_t opt_len = 0; rpl_send_opt_target_buf = get_rpl_send_opt_target_buf(DAO_BASE_LEN); /* add own address */ rpl_send_opt_target_buf->type = RPL_OPT_TARGET; rpl_send_opt_target_buf->length = RPL_OPT_TARGET_LEN; rpl_send_opt_target_buf->flags = 0x00; rpl_send_opt_target_buf->prefix_length = RPL_DODAG_ID_LEN; memcpy(&rpl_send_opt_target_buf->target, &my_address, sizeof(ipv6_addr_t)); /* 18+2=20 bytes for one target-option */ opt_len += RPL_OPT_TARGET_LEN; /* add parent */ rpl_send_opt_transit_buf = get_rpl_send_opt_transit_buf(DAO_BASE_LEN + opt_len); rpl_send_opt_transit_buf->type = RPL_OPT_TRANSIT; rpl_send_opt_transit_buf->length = RPL_OPT_TRANSIT_LEN; rpl_send_opt_transit_buf->e_flags = 0x00; rpl_send_opt_transit_buf->path_control = 0x00; rpl_send_opt_transit_buf->path_sequence = 0x00; rpl_send_opt_transit_buf->path_lifetime = lifetime; memcpy(&rpl_send_opt_transit_buf->parent, rpl_get_my_preferred_parent(), sizeof(ipv6_addr_t)); DEBUGF("My pref parent is:%s\n", ipv6_addr_to_str(addr_str_mode, IPV6_MAX_ADDR_STR_LEN, rpl_get_my_preferred_parent())); DEBUGF("Send DAO with instance %04X and sequence %04X to %s\n", rpl_send_dao_buf->rpl_instanceid, rpl_send_dao_buf->dao_sequence, ipv6_addr_to_str(addr_str_mode, IPV6_MAX_ADDR_STR_LEN, destination)); /* 4+2=6 byte for one transit-option */ opt_len += RPL_OPT_TRANSIT_LEN; uint16_t plen = ICMPV6_HDR_LEN + DAO_BASE_LEN + opt_len; rpl_send(destination, (uint8_t *)icmp_send_buf, plen, IPV6_PROTO_NUM_ICMPV6); }