ipv6_addr_t *rpl_get_next_hop(ipv6_addr_t *addr) { DEBUGF("Looking up the next hop to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, addr)); for (uint8_t i = 0; i < rpl_max_routing_entries; i++) { if (rpl_routing_table[i].used) { DEBUGF("checking %d: %s\n", i, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &rpl_routing_table[i].address)); } if ((RPL_DEFAULT_MOP == RPL_NON_STORING_MODE) && rpl_is_root()) { if (rpl_routing_table[i].used && rpl_equal_id(&rpl_routing_table[i].address, addr)) { DEBUGF("found %d: %s\n", i, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &rpl_routing_table[i].address)); return &rpl_routing_table[i].address; } } else { if (rpl_routing_table[i].used && rpl_equal_id(&rpl_routing_table[i].address, addr)) { DEBUGF("found %d: %s\n", i, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &rpl_routing_table[i].next_hop)); return &rpl_routing_table[i].next_hop; } } } return (rpl_get_my_preferred_parent()); }
/* 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); } }
/* TODO: tcp_socket unused? */ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_t next_header, void *tcp_socket) { 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 = p_len; memcpy(&(ipv6_send_buf->destaddr), destination, 16); ipv6_iface_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); /* 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)) { sixlowpan_lowpan_sendto((ieee_802154_long_t *) &(ipv6_send_buf->destaddr.uint16[4]), (uint8_t *)ipv6_send_buf, packet_length); } 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("[Error] destination unknown\n"); return; } else { next_hop = rpl_get_my_preferred_parent(); if (next_hop == NULL) { DEBUG("[Error] no preferred parent, dropping package\n"); return; } } } sixlowpan_lowpan_sendto((ieee_802154_long_t *) &(next_hop->uint16[4]), (uint8_t *)ipv6_send_buf, packet_length); } }
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); } }
ipv6_addr_t *rpl_get_next_hop(ipv6_addr_t *addr) { for (uint8_t i = 0; i < RPL_MAX_ROUTING_ENTRIES; i++) { if (routing_table[i].used && rpl_equal_id(&routing_table[i].address, addr)) { return &routing_table[i].next_hop; } } return (rpl_get_my_preferred_parent()); }
void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_t next_header, void *tcp_socket) { uint8_t *p_ptr; ipv6_send_buf = get_rpl_send_ipv6_buf(); p_ptr = get_rpl_send_payload_buf(ipv6_ext_hdr_len); 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 = p_len; memcpy(&(ipv6_send_buf->destaddr), destination, 16); ipv6_get_saddr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); /* Wenn das Paket in der rpl.c "zusammegebaut" wurde, wurde dafür ohnehin * der rpl_send_buf verwendet. In diesem Fall muss also keine memcopy * Aktion durchgeführt werden, da sich der payload bereits im richtigen * Speicherbereich befindet. */ if(p_ptr != payload) { memcpy(p_ptr, payload, p_len); } packet_length = IPV6_HDR_LEN + p_len; if(ipv6_prefix_mcast_match(&ipv6_send_buf->destaddr)) { lowpan_init((ieee_802154_long_t *)&(ipv6_send_buf->destaddr.uint16[4]), (uint8_t *)ipv6_send_buf); } else { /* find right 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) { /* oops... ich bin root und weiß nicht wohin mit dem paketn */ printf("[Error] destination unknown\n"); return; } else { next_hop = rpl_get_my_preferred_parent(); if(next_hop == NULL) { /* kein preferred parent eingetragen */ puts("[Error] no preferred parent, dropping package"); return; } } } lowpan_init((ieee_802154_long_t *)&(next_hop->uint16[4]), (uint8_t *)ipv6_send_buf); } }
ipv6_addr_t *rpl_get_next_hop(ipv6_addr_t *addr) { DEBUGF("looking up the next hop to %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, addr)); for (uint8_t i = 0; i < RPL_MAX_ROUTING_ENTRIES; i++) { if (rpl_routing_table[i].used) { DEBUGF("checking %d: %s\n", i, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &rpl_routing_table[i].address)); } if (rpl_routing_table[i].used && rpl_equal_id(&rpl_routing_table[i].address, addr)) { DEBUGF("found %d: %s\n", i, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &rpl_routing_table[i].next_hop)); return &rpl_routing_table[i].next_hop; } } return (rpl_get_my_preferred_parent()); }
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); }