예제 #1
0
파일: rpl.c 프로젝트: swp2013riot/RIOT
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);


}
예제 #2
0
파일: main.c 프로젝트: benpicco/RIOT-old
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));
        }
    }
}
예제 #3
0
파일: sixlownd.c 프로젝트: maxmue/RIOT
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);

}
예제 #4
0
파일: main.c 프로젝트: benpicco/RIOT-old
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);
	}
예제 #5
0
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);
    }
}
예제 #6
0
파일: sixlownd.c 프로젝트: maxmue/RIOT
/* 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);
}
예제 #7
0
파일: main.c 프로젝트: benpicco/RIOT-old
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);
			}

		}
	}
예제 #8
0
파일: main.c 프로젝트: benpicco/RIOT-old
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");
}
예제 #9
0
파일: main.c 프로젝트: benpicco/RIOT-old
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++;
			}
		}
	}
예제 #10
0
파일: sixlownd.c 프로젝트: maxmue/RIOT
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);
    }
}
예제 #11
0
파일: sixlownd.c 프로젝트: maxmue/RIOT
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);
    }
}
예제 #12
0
파일: rpl.c 프로젝트: swp2013riot/RIOT
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;

}