void send_DAO_ACK(ipv6_addr_t *destination) { ipv6_print_addr(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 = ICMP_RPL_CONTROL; icmp_send_buf->code = ICMP_CODE_DAO_ACK; icmp_send_buf->checksum = ~icmpv6_csum(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, PROTO_NUM_ICMPV6, NULL); mutex_unlock(&rpl_send_mutex, 0); }
void context(char *str){ uint8_t i; lowpan_context_t *context; for(i = 0; i < LOWPAN_CONTEXT_MAX; i++){ context = lowpan_context_num_lookup(i); if (context != NULL) { printf("%2d\tLifetime: %5u\tLength: %3d\t",context->num,context->lifetime,context->length); ipv6_print_addr(&(context->prefix)); } } }
void recv_rtr_sol(void) { opt_hdr_len = RTR_SOL_LEN; ipv6_buf = get_ipv6_buf(); /* check if source option is set*/ if (opt_stllao_buf->type == OPT_SLLAO_TYPE) { opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len); llao = (uint8_t *)opt_stllao_buf; opt_hdr_len += (opt_stllao_buf->length) << 3; } if (llao != NULL) { nbr_entry = nbr_cache_search(&ipv6_buf->srcaddr); if (nbr_entry != NULL) { /* found neighbor in cache, update values and check long addr */ if (memcmp(&llao[2], &nbr_entry->laddr, 8) == 0) { nbr_entry->isrouter = 0; } else { /* new long addr found, update */ memcpy(&nbr_entry->laddr, &llao[2], 8); nbr_entry->state = NBR_STATUS_STALE; nbr_entry->isrouter = 0; } } else { /* nothing found, add neigbor into cache*/ nbr_cache_add(&ipv6_buf->srcaddr, (ieee_802154_long_t *)&llao[2], 0, NBR_STATUS_STALE, NBR_CACHE_TYPE_TEN, NBR_CACHE_LTIME_TEN, NULL); } } /* send solicited router advertisment */ if (abr_count > 0) { init_rtr_adv(&ipv6_buf->srcaddr, 0, 0, OPT_PI, OPT_6CO, OPT_ABRO); } else { init_rtr_adv(&ipv6_buf->srcaddr, 0, 0, OPT_PI, 0, 0); } #if ENABLE_DEBUG printf("INFO: send router advertisment to: "); ipv6_print_addr(&ipv6_buf->destaddr); #endif lowpan_init((ieee_802154_long_t *)&(ipv6_buf->destaddr.uint16[4]), (uint8_t *)ipv6_buf); }
void send_udp(char *str) { timex_t start, end, total; long secs; int sock; sockaddr6_t sa; ipv6_addr_t ipaddr; int bytes_sent; int address, count; char text[] = "abcdefghijklmnopqrstuvwxyz0123456789!-=$%&/()"; sscanf(str, "send_udp %i %i %s", &count, &address, text); sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (-1 == sock) { printf("Error Creating Socket!"); exit(EXIT_FAILURE); } memset(&sa, 0, sizeof sa); ipv6_init_address(&ipaddr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, (uint16_t)address); ipv6_print_addr(&ipaddr); sa.sin6_family = AF_INET; memcpy(&sa.sin6_addr, &ipaddr, 16); sa.sin6_port = HTONS(7654); ltc4150_start(); printf("Start power: %f\n", ltc4150_get_total_Joule()); start = vtimer_now(); for (int i = 0; i < count; i++) { bytes_sent = sendto(sock, (char*)text, strlen((char*)text)+1, 0, &sa, sizeof sa); if (bytes_sent < 0) { printf("Error sending packet!\n"); } // hwtimer_wait(20*1000); } end = vtimer_now(); total = timex_sub(end, start); secs = total.microseconds / 1000000; printf("Used power: %f\n", ltc4150_get_total_Joule()); printf("Start: %lu, End: %lu, Total: %lu\n", start.microseconds, end.microseconds, total.microseconds); secs = total.microseconds / 1000000; printf("Time: %lu seconds, Bandwidth: %lu byte/second\n", secs, (count*48)/secs); close(sock); }
void send_packet(char *str){ uint8_t test[2]; test[0] = 30; test[1] = 98; ipv6_addr_t ipaddr; ipv6_init_address(&ipaddr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, 0x0005); ipv6_print_addr(&ipaddr); for(int j=0;j<100;j++){ test[0] = j; for(int i=0;i<1000;i++){ sixlowpan_send(&ipaddr, test, 2, 0); } //lib6lowpan_bootstrapping(&addr8); } }
/* send router solicitation message - RFC4861 section 4.1 */ void init_rtr_sol(uint8_t sllao) { ipv6_buf = get_ipv6_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); packet_length = 0; icmp_buf->type = ICMP_RTR_SOL; icmp_buf->code = 0; ipv6_buf->version_trafficclass = IPV6_VER; ipv6_buf->trafficclass_flowlabel = 0; ipv6_buf->flowlabel = 0; ipv6_buf->nextheader = PROTO_NUM_ICMPV6; ipv6_buf->hoplimit = ND_HOPLIMIT; ipv6_set_all_rtrs_mcast_addr(&ipv6_buf->destaddr); //iface_find_src_ipaddr(&ipv6_buf->srcaddr, ADDR_STATE_PREFERRED, /* ADDR_TYPE_MULTICAST); */ ipv6_get_saddr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); opt_hdr_len = RTR_SOL_LEN; ipv6_buf->length = ICMPV6_HDR_LEN + RTR_SOL_LEN + OPT_STLLAO_MAX_LEN; if (sllao == OPT_SLLAO) { opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len); set_llao(opt_stllao_buf, OPT_SLLAO_TYPE, 2); packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + RTR_SOL_LEN + OPT_STLLAO_MAX_LEN; } else { packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + RTR_SOL_LEN; } icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6); #if ENABLE_DEBUG printf("INFO: send router solicitation to: "); ipv6_print_addr(&ipv6_buf->destaddr); #endif lowpan_init((ieee_802154_long_t *)&(ipv6_buf->destaddr.uint16[4]), (uint8_t *)ipv6_buf); }
void tcp_ch(void) { msg_t recv_msg; int read_bytes = 0; char buff_msg[MAX_TCP_BUFFER]; sockaddr6_t stSockAddr; msg_receive(&recv_msg); int SocketFD = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); if (-1 == SocketFD) { printf("cannot create socket"); return; } memset(&stSockAddr, 0, sizeof(stSockAddr)); stSockAddr.sin6_family = AF_INET6; stSockAddr.sin6_port = HTONS(1100); ipv6_init_address(&stSockAddr.sin6_addr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, current_message.node_number); ipv6_print_addr(&stSockAddr.sin6_addr); if (-1 == connect(SocketFD, &stSockAddr, sizeof(stSockAddr))) { printf("Connect failed!\n"); close(SocketFD); return; } tcp_socket_id = SocketFD; while (read_bytes != -1) { read_bytes = recv(SocketFD, buff_msg, MAX_TCP_BUFFER, 0); if (read_bytes > 0) { printf("--- Message: %s ---\n", buff_msg); } } }
void init(char *str){ char command; uint16_t r_addr; ipv6_addr_t std_addr; int res = sscanf(str, "init %c %hu", &command, &r_addr); if(res < 1){ printf("Usage: init {h | r | a | e} radio_address\n"); printf("\th\tinitialize as host\n"); printf("\tr\tinitialize as router\n"); printf("\ta\tinitialize as ad-hoc router\n"); printf("\tb\tinitialize as border router\n\n"); printf("\tradio_address must be an 8 bit integer\n"); } ipv6_init_address(&std_addr,0xABCD,0,0,0,0x1034,0x00FF,0xFE00,r_addr); switch (command) { case 'h': printf("INFO: Initialize as host on radio address %hu\n", r_addr); if (r_addr > 255) { printf("ERROR: radio_address not an 8 bit integer\n"); return; } sixlowpan_init(TRANSCEIVER_CC1100,r_addr,0); break; case 'r': printf("INFO: Initialize as router on radio address %hu\n", r_addr); if (r_addr > 255) { printf("ERROR: radio_address not an 8 bit integer\n"); return; } sixlowpan_init(TRANSCEIVER_CC1100, r_addr,0); ipv6_init_iface_as_router(); break; case 'a': printf("INFO: Initialize as adhoc router on radio address %hu\n", r_addr); if (r_addr > 255) { printf("ERROR: radio_address not an 8 bit integer\n"); return; } sixlowpan_adhoc_init(TRANSCEIVER_CC1100, &std_addr, r_addr); break; case 'b': printf("INFO: Initialize as border router on radio address %hu\n", r_addr); if (r_addr > 255) { printf("ERROR: radio_address not an 8 bit integer\n"); return; } res = border_initialize(TRANSCEIVER_CC1100, &std_addr); switch (res) { case (SUCCESS): printf("INFO: Border router initialized.\n"); break; case (SIXLOWERROR_ADDRESS): printf("ERROR: Illegal IP address: "); ipv6_print_addr(&std_addr); break; default: printf("ERROR: Unknown error (%d).\n", res); break; } break; default: printf("ERROR: Unknown command '%c'\n", command); break; } tcp_send_pid = thread_create( tcp_send_stack_buffer, SEND_TCP_THREAD_SIZE, PRIORITY_MAIN, CREATE_STACKTEST, send_tcp_thread, "send_tcp_thread"); }
void init_tcp_server(void) { sockaddr6_t stSockAddr; int read_bytes; char buff_msg[MAX_TCP_BUFFER]; memset(buff_msg, 0, MAX_TCP_BUFFER); int SocketFD = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); if(-1 == SocketFD) { perror("can not create socket"); exit(EXIT_FAILURE); } memset(&stSockAddr, 0, sizeof(stSockAddr)); stSockAddr.sin6_family = AF_INET6; stSockAddr.sin6_port = HTONS(1100); ipv6_init_address(&stSockAddr.sin6_addr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, get_radio_address()); ipv6_print_addr(&stSockAddr.sin6_addr); if(-1 == bind(SocketFD, &stSockAddr, sizeof(stSockAddr))) { printf("error bind failed\n"); close(SocketFD); return; } print_internal_socket(getSocket(SocketFD)); if(-1 == listen(SocketFD, 10)) { printf("error listen failed\n"); close(SocketFD); return; } while (1) { read_bytes = 0; printf("INFO: WAITING FOR INC CONNECTIONS!\n"); int ConnectFD = accept(SocketFD, NULL, 0); if(0 > ConnectFD) { printf("error accept failed\n"); close(SocketFD); return; } else { printf("Connection established on socket %u.\n", ConnectFD); if (running_recv_threads == 0) { recv_socket_id1 = ConnectFD; thread_create(recv_from_tcp_thread_stack1, RECV_FROM_TCP_THREAD_STACK_SIZE1, PRIORITY_MAIN, CREATE_STACKTEST, recv_from_tcp_thread1, "recv_from_tcp_thread1"); } else if (running_recv_threads == 1) { recv_socket_id2 = ConnectFD; thread_create(recv_from_tcp_thread_stack2, RECV_FROM_TCP_THREAD_STACK_SIZE2, PRIORITY_MAIN, CREATE_STACKTEST, recv_from_tcp_thread2, "recv_from_tcp_thread2"); } running_recv_threads++; } } }
void recv_nbr_sol(void) { ipv6_buf = get_ipv6_buf(); llao = NULL; opt_hdr_len = NBR_SOL_LEN; uint8_t send_na = 0; uint8_t sllao_set = 0; uint8_t aro_state = OPT_ARO_STATE_SUCCESS; /* check whick options are set, we need that because an aro * option condition is that a sllao option is set. thus that we don't * know which option comes first we need to this here */ while (packet_length > IPV6HDR_ICMPV6HDR_LEN + opt_hdr_len) { opt_buf = get_opt_buf(ipv6_ext_hdr_len, opt_hdr_len); if (opt_buf->type == OPT_SLLAO_TYPE) { sllao_set = 1; } opt_hdr_len += (opt_buf->length * 8); } opt_hdr_len = NBR_SOL_LEN; while (packet_length > IPV6HDR_ICMPV6HDR_LEN + opt_hdr_len) { opt_buf = get_opt_buf(ipv6_ext_hdr_len, opt_hdr_len); switch(opt_buf->type) { case (OPT_SLLAO_TYPE): { opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len); llao = (uint8_t *)opt_stllao_buf; if (llao != NULL && !(ipv6_addr_unspec_match(&ipv6_buf->srcaddr))) { nbr_entry = nbr_cache_search(&(ipv6_buf->srcaddr)); if (nbr_entry != NULL) { switch(opt_stllao_buf->length) { case (1): { if (memcmp(&llao[2], &(nbr_entry->saddr), 2) == 0) { nbr_entry->isrouter = 0; } else { memcpy(&nbr_entry->saddr, &llao[2], 2); nbr_entry->state = NBR_STATUS_STALE; nbr_entry->isrouter = 0; } break; } case (2): { if (memcmp(&llao[2], &(nbr_entry->laddr), 8) == 0) { nbr_entry->isrouter = 0; } else { memcpy(&nbr_entry->laddr, &llao[2], 8); nbr_entry->state = NBR_STATUS_STALE; nbr_entry->isrouter = 0; } break; } default: break; } } else { switch(opt_stllao_buf->length) { case (1): { nbr_cache_add(&ipv6_buf->srcaddr, NULL , 0, NBR_STATUS_STALE, NBR_CACHE_TYPE_TEN, NBR_CACHE_LTIME_TEN, (ieee_802154_short_t *)&llao[2]); break; } case (2): { nbr_cache_add(&ipv6_buf->srcaddr, (ieee_802154_long_t *)&llao[2], 0, NBR_STATUS_STALE, NBR_CACHE_TYPE_TEN, NBR_CACHE_LTIME_TEN, NULL); break; } default: break; } } } break; } case (OPT_ARO_TYPE): { /* check if sllao option is set, and if address src address * isn't unspecified - draft-ietf-6lowpan-nd-15#section-6.5 */ if (!(ipv6_addr_unspec_match(&ipv6_buf->srcaddr)) && sllao_set == 1) { opt_aro_buf = get_opt_aro_buf(ipv6_ext_hdr_len, opt_hdr_len); if ((opt_aro_buf->length == 2) && (opt_aro_buf->status == 0)) { /* check neighbor cache for duplicates */ nbr_entry = nbr_cache_search(&(ipv6_buf->srcaddr)); if (nbr_entry == NULL) { /* create neighbor cache */ aro_state = nbr_cache_add(&ipv6_buf->srcaddr, &(opt_aro_buf->eui64), 0, NBR_STATUS_STALE, NBR_CACHE_TYPE_TEN, opt_aro_buf->reg_ltime, NULL); } else { if (memcmp(&(nbr_entry->addr.uint16[4]), &(opt_aro_buf->eui64.uint16[0]), 8) == 0) { /* update neighbor cache entry */ if (opt_aro_buf->reg_ltime == 0) { /* delete neighbor cache entry */ nbr_cache_rem(&nbr_entry->addr); } else { set_remaining_time(&(nbr_entry->ltime), (uint32_t)opt_aro_buf->reg_ltime); nbr_entry->state = NBR_STATUS_STALE; nbr_entry->isrouter = 0; memcpy(&(nbr_entry->addr.uint8[0]), &(ipv6_buf->srcaddr.uint8[0]), 16); } aro_state = OPT_ARO_STATE_SUCCESS; } else { /* duplicate found */ aro_state = OPT_ARO_STATE_DUP_ADDR; } } } } break; } default: break; } opt_hdr_len += (opt_buf->length * 8); } addr_list_t *alist_targ, *alist_dest; nbr_sol_buf = get_nbr_sol_buf(ipv6_ext_hdr_len); alist_targ = ipv6_iface_addr_match(&(nbr_sol_buf->tgtaddr)); if (alist_targ != NULL) { alist_dest = ipv6_iface_addr_match(&(ipv6_buf->destaddr)); if ((memcmp(&(alist_targ->addr), &(alist_dest->addr), 16) == 0) || ipv6_addr_sol_node_mcast_match(&ipv6_buf->destaddr)) { memcpy(&(ipv6_buf->destaddr.uint8[0]), &(ipv6_buf->srcaddr.uint8[0]), 16); memcpy(&(ipv6_buf->srcaddr.uint8[0]), &(nbr_sol_buf->tgtaddr.uint8[0]), 16); send_na = 1; } } if (send_na) { /* solicited na */ uint8_t flags = (NBR_ADV_FLAG_O | NBR_ADV_FLAG_S); init_nbr_adv(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr), &(alist_targ->addr), flags, 0, OPT_ARO, aro_state); #if ENABLE_DEBUG printf("INFO: send neighbor advertisment to: "); ipv6_print_addr(&ipv6_buf->destaddr); #endif lowpan_init((ieee_802154_long_t *) & (ipv6_buf->destaddr.uint16[4]), (uint8_t *)ipv6_buf); } }
void recv_rtr_adv(void) { int8_t trigger_ns = -1; int8_t abro_found = 0; int16_t abro_version = 0; /* later replaced, just to supress warnings */ ipv6_addr_t abro_addr; ipv6_buf = get_ipv6_buf(); opt_hdr_len = RTR_ADV_LEN; rtr_adv_buf = get_rtr_adv_buf(ipv6_ext_hdr_len); ipv6_addr_t newaddr; recvd_cids_len = 0; /* update interface reachable time and retrans timer */ if (rtr_adv_buf->reachable_time != 0) { iface.adv_reachable_time = HTONL(rtr_adv_buf->reachable_time); } if (rtr_adv_buf->retrans_timer != 0) { iface.adv_retrans_timer = HTONL(rtr_adv_buf->retrans_timer); } def_rtr_entry = def_rtr_lst_search(&ipv6_buf->srcaddr); if (rtr_adv_buf->router_lifetime != 0) { if (def_rtr_entry != NULL) { set_remaining_time(&(def_rtr_entry->inval_time), HTONL(rtr_adv_buf->router_lifetime)); } else { def_rtr_lst_add(&(ipv6_buf->srcaddr), HTONL(rtr_adv_buf->router_lifetime)); trigger_ns = 1; } } else { /* remove router from default router list */ if (def_rtr_entry != NULL) { def_rtr_lst_rem(def_rtr_entry); } } mutex_lock(&lowpan_context_mutex); /* read options */ while (packet_length > IPV6HDR_ICMPV6HDR_LEN + opt_hdr_len) { opt_buf = get_opt_buf(ipv6_ext_hdr_len, opt_hdr_len); switch(opt_buf->type) { case (OPT_SLLAO_TYPE): { break; } case (OPT_MTU_TYPE): { break; } /* rfc 4862 section 5.5.3 */ case (OPT_PI_TYPE): { opt_pi_buf = get_opt_pi_buf(ipv6_ext_hdr_len, opt_hdr_len); /* crazy condition, read 5.5.3a-b-c for further information */ if (ipv6_prefix_ll_match(&opt_pi_buf->addr) || (HTONL(opt_pi_buf->pref_ltime) > HTONL(opt_pi_buf->val_ltime))) { break; } else { /* check if on-link flag is set */ if (opt_pi_buf->l_a_reserved1 & OPT_PI_FLAG_L) { /* TODO: do on-link pi handling */ } if (opt_pi_buf->l_a_reserved1 & OPT_PI_FLAG_A) { addr_list_ptr = ipv6_iface_addr_prefix_eq(&opt_pi_buf->addr); if (addr_list_ptr == NULL) { /* 5.5.3d */ if (opt_pi_buf->val_ltime != 0) { /* iid will also be added here */ ipv6_init_addr_prefix(&newaddr, &opt_pi_buf->addr); /* add into address list * TODO: duplicate address detection is not * implementet yet, so all new addresse will * be added with state PREFFERED */ ipv6_iface_add_addr(&newaddr, ADDR_STATE_PREFERRED, opt_pi_buf->val_ltime, opt_pi_buf->pref_ltime, ADDR_CONFIGURED_AUTO); printf("INFO: added address to interface\n"); trigger_ns = 1; } } else { /* 5.5.3e */ set_remaining_time(&(addr_list_ptr->pref_ltime), opt_pi_buf->pref_ltime); /* 7200 = 2hours in seconds */ if (HTONL(opt_pi_buf->val_ltime) > 7200 || HTONL(opt_pi_buf->val_ltime) > get_remaining_time(&(addr_list_ptr->val_ltime))) { set_remaining_time(&(addr_list_ptr->val_ltime), HTONL(opt_pi_buf->val_ltime)); } else { /* reset valid lifetime to 2 hours */ set_remaining_time(&(addr_list_ptr->val_ltime), 7200); } } } } /* TODO: save found prefixes */ break; } case (OPT_6CO_TYPE): { uint8_t comp; uint8_t num; opt_6co_hdr_buf = get_opt_6co_hdr_buf(ipv6_ext_hdr_len, opt_hdr_len); get_opt_6co_flags(&comp, &num, opt_6co_hdr_buf->c_flags); ipv6_addr_t prefix; memset(&prefix, 0, 16); opt_6co_prefix_buf = get_opt_6co_prefix_buf(ipv6_ext_hdr_len, opt_hdr_len + OPT_6CO_HDR_LEN); memcpy(&prefix, opt_6co_prefix_buf, opt_6co_hdr_buf->c_length); lowpan_context_update( num, &prefix, opt_6co_hdr_buf->c_length, comp, HTONS(opt_6co_hdr_buf->val_ltime) ); recvd_cids[recvd_cids_len] = num; recvd_cids_len = (recvd_cids_len + 1) % LOWPAN_CONTEXT_MAX; break; } case (OPT_ABRO_TYPE): { opt_abro_buf = get_opt_abro_buf(ipv6_ext_hdr_len, opt_hdr_len); abro_found = 1; abro_version = HTONS(opt_abro_buf->version); memcpy(&(abro_addr), &(opt_abro_buf->addr), sizeof(ipv6_addr_t)); break; } default: break; } /* multiplied with 8 because options length is in units of 8 bytes */ opt_hdr_len += (opt_buf->length * 8); } if (abro_found) { int i; for (i = 0; i < recvd_cids_len; i++) { abr_add_context(abro_version, &abro_addr, recvd_cids[i]); } } mutex_unlock(&lowpan_context_mutex, 0); if (trigger_ns >= 0) { /* send ns - draft-ietf-6lowpan-nd-15#section-5.5.1 * * section-10.2.4 * "Next the 6LN registers that address with one or more of its * default routers by sending a unicast NS message with an ARO * containing its tentative global IPv6 address to register * * if new address was configured, set src to newaddr(gp16) */ init_nbr_sol(&newaddr, &(ipv6_buf->srcaddr), &(ipv6_buf->srcaddr), OPT_SLLAO, OPT_ARO); #if ENABLE_DEBUG printf("INFO: send neighbor solicitation to: "); ipv6_print_addr(&(ipv6_buf->destaddr)); #endif lowpan_init((ieee_802154_long_t *) & (ipv6_buf->destaddr.uint16[4]), (uint8_t *)ipv6_buf); } }
void recv_rpl_dio(void) { ipv6_buf = get_rpl_ipv6_buf(); rpl_dio_buf = get_rpl_dio_buf(); int len = DIO_BASE_LEN; rpl_instance_t *dio_inst = rpl_get_instance(rpl_dio_buf->rpl_instanceid); rpl_instance_t *my_inst = rpl_get_my_instance(); if(dio_inst == NULL) { if(my_inst != NULL) { /* Dieser Knoten ist schon Teil eines DODAGS -> kein beitritt zu anderer Instanz moeglich */ return; } dio_inst = rpl_new_instance(rpl_dio_buf->rpl_instanceid); if(dio_inst == NULL) { return; } } else if(my_inst->id != dio_inst->id) { printf("Andere Instanz, wir haben %d es kam aber %d\n", my_inst->id, dio_inst->id); /* DIO von fremder Instanz ignorieren, Knoten können Momentan nur * einer Instanz beitreten und das wird die Instanz sein, der sie als * erstes beitreten. Danach kann die Instanz nicht mehr gewechselt * werden Unterstützung für mehrere Instanzen könnte in Zukunft * implementiert werden */ return; } rpl_dodag_t dio_dodag; memset(&dio_dodag, 0, sizeof(dio_dodag)); memcpy(&dio_dodag.dodag_id, &rpl_dio_buf->dodagid, sizeof(dio_dodag.dodag_id)); dio_dodag.dtsn = rpl_dio_buf->dtsn; dio_dodag.mop = ((rpl_dio_buf->g_mop_prf >> RPL_MOP_SHIFT) & RPL_SHIFTED_MOP_MASK); dio_dodag.grounded = rpl_dio_buf->g_mop_prf >> RPL_GROUNDED_SHIFT; dio_dodag.prf = (rpl_dio_buf->g_mop_prf & RPL_PRF_MASK); dio_dodag.version = rpl_dio_buf->version_number; dio_dodag.instance = dio_inst; uint8_t has_dodag_conf_opt = 0; /* So lange das Paket größer ist, als die DIO Größe + Größe der bisher * verarbeiteten Optionen, sind noch weitere Optionen zu bearbeiten */ /* dabei müssen wir jedoch von der ipv6_buf->length die Größe des ICMP * Headers abziehen weil get_rpl_opt_buf die Paketlänge OHNE ipv6 und * icmpv6 header übergeben werden muss in ipv6_buf->length ist die * IPV6_HDR_LEN nicht enthalten, also muss nur noch die ICMPV6_HDR_LEN * abgezogen werden */ while(len < (ipv6_buf->length - ICMPV6_HDR_LEN)) { rpl_opt_buf = get_rpl_opt_buf(len); switch(rpl_opt_buf->type) { case(RPL_OPT_PAD1): { len += 1; break; } case(RPL_OPT_PADN): { len += rpl_opt_buf->length + 2; break; } case(RPL_OPT_DAG_METRIC_CONTAINER): { len += rpl_opt_buf->length + 2; break; } case(RPL_OPT_ROUTE_INFO): { len += rpl_opt_buf->length + 2; break; } case(RPL_OPT_DODAG_CONF): { has_dodag_conf_opt = 1; if(rpl_opt_buf->length != RPL_OPT_DODAG_CONF_LEN) { /* error malformed */ return; } rpl_opt_dodag_conf_buf = get_rpl_opt_dodag_conf_buf(len); dio_dodag.dio_interval_doubling = rpl_opt_dodag_conf_buf->DIOIntDoubl; dio_dodag.dio_min = rpl_opt_dodag_conf_buf->DIOIntMin; dio_dodag.dio_redundancy = rpl_opt_dodag_conf_buf->DIORedun; dio_dodag.maxrankincrease = rpl_opt_dodag_conf_buf->MaxRankIncrease; dio_dodag.minhoprankincrease = rpl_opt_dodag_conf_buf->MinHopRankIncrease; dio_dodag.default_lifetime = rpl_opt_dodag_conf_buf->default_lifetime; dio_dodag.lifetime_unit = rpl_opt_dodag_conf_buf->lifetime_unit; dio_dodag.of = rpl_get_of_for_ocp(rpl_opt_dodag_conf_buf->ocp); len += RPL_OPT_DODAG_CONF_LEN + 2; break; } case(RPL_OPT_PREFIX_INFO): { if(rpl_opt_buf->length != RPL_OPT_PREFIX_INFO_LEN) { /* error malformed */ return; } len += RPL_OPT_PREFIX_INFO_LEN + 2; break; } default: printf("[Error] Unsupported DIO option\n"); return; } } /* handle packet content... */ rpl_dodag_t *my_dodag = rpl_get_my_dodag(); if(my_dodag == NULL) { if(!has_dodag_conf_opt) { puts("send DIS"); send_DIS(&ipv6_buf->srcaddr); return; } if(rpl_dio_buf->rank < ROOT_RANK) { printf("DIO with Rank < ROOT_RANK\n"); return; } if(dio_dodag.mop != RPL_DEFAULT_MOP) { printf("Required MOP not supported\n"); return; } if(dio_dodag.of == NULL) { printf("Required objective function not supported\n"); return; } if(rpl_dio_buf->rank != INFINITE_RANK) { puts("Will join DODAG\n"); ipv6_print_addr(&dio_dodag.dodag_id); rpl_join_dodag(&dio_dodag, &ipv6_buf->srcaddr, rpl_dio_buf->rank); } else { printf("Cannot access DODAG because of DIO with infinite rank\n"); return; } } if(rpl_equal_id(&my_dodag->dodag_id, &dio_dodag.dodag_id)) { /* Mein DODAG */ if(RPL_COUNTER_GREATER_THAN(dio_dodag.version, my_dodag->version)) { if(my_dodag->my_rank == ROOT_RANK) { /* Jemand hat ein DIO mit einer höheren Version als der richtigen gesendet */ /* Wir erhöhen diese Version noch einmal, und machen sie zur neuen */ printf("[Warning] Inconsistent Dodag Version\n"); my_dodag->version = RPL_COUNTER_INCREMENT(dio_dodag.version); reset_trickletimer(); } else { printf("[Info] New Version of dodag %d\n", dio_dodag.version); rpl_global_repair(&dio_dodag, &ipv6_buf->srcaddr, rpl_dio_buf->rank); } return; } else if(RPL_COUNTER_GREATER_THAN(my_dodag->version, dio_dodag.version)) { /* ein Knoten hat noch eine kleinere Versionsnummer -> mehr DIOs senden */ reset_trickletimer(); return; } } /* Version stimmt, DODAG stimmt */ if(rpl_dio_buf->rank == INFINITE_RANK) { reset_trickletimer(); } /* Wenn wir root sind, ist nichts weiter zu tun */ if(my_dodag->my_rank == ROOT_RANK) { if(rpl_dio_buf->rank != INFINITE_RANK) { trickle_increment_counter(); } return; } /* */ /* Parent Handling */ /* */ /* Ist Knoten bereits Parent? */ rpl_parent_t *parent; parent = rpl_find_parent(&ipv6_buf->srcaddr); if(parent == NULL) { /* neuen möglichen Elternknoten hinzufuegen */ parent = rpl_new_parent(my_dodag, &ipv6_buf->srcaddr, rpl_dio_buf->rank); if(parent == NULL) { return; } } else { /* DIO ok */ trickle_increment_counter(); } /* update parent rank */ parent->rank = rpl_dio_buf->rank; rpl_parent_update(parent); if(rpl_equal_id(&parent->addr, &my_dodag->my_preferred_parent->addr) && (parent->dtsn != rpl_dio_buf->dtsn)) { delay_dao(); } parent->dtsn = rpl_dio_buf->dtsn; }