예제 #1
0
파일: sixlownd.c 프로젝트: maxmue/RIOT
void init_para_prob(ipv6_addr_t *src, ipv6_addr_t *dest, uint8_t code, uint32_t pointer, uint8_t *packet, uint8_t packet_len)
{
    struct para_prob_t *para_prob_buf;


    packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + PARA_PROB_LEN;

    memcpy(&(ipv6_buf[packet_length]), packet, min(MTU - packet_length, packet_len));

    ipv6_buf = get_ipv6_buf();
    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_ext_hdr_len = 0;
    icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);
    icmp_buf->type = ICMP_PARA_PROB;
    icmp_buf->code = code;

    memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dest->uint8[0]), 16);
    memcpy(&(ipv6_buf->srcaddr.uint8[0]), &(src->uint8[0]), 16);

    para_prob_buf = get_para_prob_buf(ipv6_ext_hdr_len);

    para_prob_buf->pointer = pointer;

    packet_length += min(MTU - packet_length, packet_len);

    ipv6_buf->length = packet_length - IPV6_HDR_LEN;

    icmp_buf->checksum = 0;
    icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
}
예제 #2
0
파일: sixlownd.c 프로젝트: maxmue/RIOT
void init_nbr_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *tgt,
                  uint8_t rso, uint8_t sllao, uint8_t aro, uint8_t aro_state)
{
    ipv6_buf = get_ipv6_buf();
    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_ext_hdr_len = 0;
    icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);
    icmp_buf->type = ICMP_NBR_ADV;
    icmp_buf->code = 0;

    memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dst->uint8[0]), 16);
    memcpy(&(ipv6_buf->srcaddr.uint8[0]), &(src->uint8[0]), 16);

    nbr_adv_buf = get_nbr_adv_buf(ipv6_ext_hdr_len);
    nbr_adv_buf->rso = rso;

    memset(&(nbr_adv_buf->reserved[0]), 0, 3);
    memcpy(&(nbr_adv_buf->tgtaddr.uint8[0]), &(tgt->uint8[0]), 16);

    packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + NBR_ADV_LEN;

    if (sllao == OPT_SLLAO) {
        /* set sllao option */
        opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len);
        set_llao(opt_stllao_buf, OPT_SLLAO_TYPE, 1);
        opt_hdr_len += OPT_STLLAO_MIN_LEN;

        packet_length += OPT_STLLAO_MIN_LEN;
    }

    if (aro == OPT_ARO) {
        /* set aro option */
        opt_aro_buf = get_opt_aro_buf(ipv6_ext_hdr_len, opt_hdr_len);
        opt_aro_buf->type = OPT_ARO_TYPE;
        opt_aro_buf->length = OPT_ARO_LEN;
        opt_aro_buf->status = 0;    /* TODO */
        opt_aro_buf->reserved1 = 0;
        opt_aro_buf->reserved2 = 0;
        memcpy(&(opt_aro_buf->eui64), mac_get_eui(dst), 8);
        opt_hdr_len += OPT_ARO_HDR_LEN;

        packet_length += OPT_ARO_HDR_LEN;
    }

    ipv6_buf->length = packet_length - IPV6_HDR_LEN;

    icmp_buf->checksum = 0;
    icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
}
예제 #3
0
파일: sixlownd.c 프로젝트: maxmue/RIOT
uint16_t icmpv6_csum(uint8_t proto)
{
    ipv6_buf = get_ipv6_buf();
    uint16_t sum;
    uint16_t len = ipv6_buf->length;
    sum = len + proto;

    sum = csum(sum, (uint8_t *)&ipv6_buf->srcaddr, 2 * sizeof(ipv6_addr_t));
    sum = csum(sum, (uint8_t *)get_icmpv6_buf(0), len);

    return (sum == 0) ? 0xffff : HTONS(sum);
}
예제 #4
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);

}
예제 #5
0
파일: rpl.c 프로젝트: swp2013riot/RIOT
void rpl_process(void)
{

    msg_t m_recv;
    msg_init_queue(msg_queue, RPL_PKT_RECV_BUF_SIZE);

    while(1) {
        msg_receive(&m_recv);
        uint8_t *code;
        code = ((uint8_t *)m_recv.content.ptr);
        /* pakettypen unterscheiden */
        ipv6_buf = get_ipv6_buf();
        memcpy(&rpl_buffer, ipv6_buf, ipv6_buf->length + IPV6_HDR_LEN);

        switch(*code) {
            case(ICMP_CODE_DIS): {
                recv_rpl_dis();
                mutex_unlock(&rpl_recv_mutex, 0);
                break;
            }

            case(ICMP_CODE_DIO): {
                recv_rpl_dio();
                mutex_unlock(&rpl_recv_mutex, 0);
                break;
            }

            case(ICMP_CODE_DAO): {
                recv_rpl_dao();
                mutex_unlock(&rpl_recv_mutex, 0);
                break;
            }

            case(ICMP_CODE_DAO_ACK): {
                recv_rpl_dao_ack();
                mutex_unlock(&rpl_recv_mutex, 0);
                break;
            }

            default:
                mutex_unlock(&rpl_recv_mutex, 0);
                puts("default unlock");
                break;
        }
    }
}
예제 #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
파일: 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);
    }
}
예제 #8
0
파일: sixlownd.c 프로젝트: maxmue/RIOT
void init_nbr_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t *targ,
                  uint8_t sllao, uint8_t aro)
{
    ipv6_buf = get_ipv6_buf();
    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;

    if (dest == NULL) {
        ipv6_set_sol_node_mcast_addr(targ, &(ipv6_buf->destaddr));
    }
    else {
        memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dest->uint8[0]), 16);
    }

    ipv6_ext_hdr_len = 0;
    icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);
    icmp_buf->type = ICMP_NBR_SOL;
    icmp_buf->code = 0;

    nbr_sol_buf = get_nbr_sol_buf(ipv6_ext_hdr_len);
    nbr_sol_buf->reserved = 0;
    memcpy(&(nbr_sol_buf->tgtaddr), targ, 16);
    opt_hdr_len = NBR_SOL_LEN;

    packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + NBR_SOL_LEN;

    if (ipv6_iface_addr_match(targ) == NULL) {
        if (src == NULL) {
            ipv6_get_saddr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr));
        }
        else {
            memcpy(&(ipv6_buf->srcaddr), src, 16);
        }

        if (sllao == OPT_SLLAO) {
            /* set sllao option */
            opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len);
            set_llao(opt_stllao_buf, OPT_SLLAO_TYPE, 1);
            opt_hdr_len += OPT_STLLAO_MIN_LEN;

            packet_length += OPT_STLLAO_MIN_LEN;
        }
    }

    if (aro == OPT_ARO) {
        /* set aro option */
        opt_aro_buf = get_opt_aro_buf(ipv6_ext_hdr_len, opt_hdr_len);
        opt_aro_buf->type = OPT_ARO_TYPE;
        opt_aro_buf->length = OPT_ARO_LEN;
        opt_aro_buf->status = 0;
        opt_aro_buf->reserved1 = 0;
        opt_aro_buf->reserved2 = 0;
        memcpy(&(opt_aro_buf->eui64), mac_get_eui(src), 8);
        opt_hdr_len += OPT_ARO_HDR_LEN;

        packet_length += OPT_ARO_HDR_LEN;
    }

    ipv6_buf->length = packet_length - IPV6_HDR_LEN;

    icmp_buf->checksum = 0;
    icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
}
예제 #9
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);
    }
}
예제 #10
0
파일: sixlownd.c 프로젝트: maxmue/RIOT
void init_rtr_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8_t pi, 
                  uint8_t sixco, uint8_t abro)
{
    lowpan_context_t *contexts = NULL;

    abr_cache_t *msg_abr = NULL;
    ipv6_buf = get_ipv6_buf();
    icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);

    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;

    if (addr == NULL) {
        /* not solicited */
        ipv6_set_all_nds_mcast_addr(&ipv6_buf->destaddr);
    }
    else {
        memcpy(&ipv6_buf->destaddr, addr, 16);
    }

    ipv6_get_saddr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr));

    icmp_buf->type = ICMP_RTR_ADV;
    icmp_buf->code = 0;

    //TODO: gethoplimit func, set current ttl

    rtr_adv_buf = get_rtr_adv_buf(ipv6_ext_hdr_len);
    rtr_adv_buf->hoplimit = MULTIHOP_HOPLIMIT;
    /* set M and O flag, last 6 bits are zero */
    rtr_adv_buf->autoconfig_flags = (RTR_ADV_M_FLAG << 7) | (RTR_ADV_O_FLAG << 6);
    rtr_adv_buf->router_lifetime = HTONS(RTR_ADV_MAX_INTERVAL * RTR_ADV_MAX);
    rtr_adv_buf->reachable_time = 0;
    rtr_adv_buf->retrans_timer = 0;
    opt_hdr_len = RTR_ADV_LEN;

    packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + RTR_ADV_LEN;

    if (sllao == OPT_SLLAO) {
        /* set link layer address option */
        opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len);
        set_llao(opt_stllao_buf, OPT_SLLAO_TYPE, 2);
        opt_hdr_len += OPT_STLLAO_MAX_LEN;
        packet_length += OPT_STLLAO_MAX_LEN;
    }

    if (mtu == OPT_MTU) {
        /* set MTU options */
        opt_mtu_buf = get_opt_mtu_buf(ipv6_ext_hdr_len, opt_hdr_len);
        opt_mtu_buf->type = OPT_MTU_TYPE;
        opt_mtu_buf->length = OPT_MTU_LEN;
        opt_mtu_buf->reserved = 0;
        opt_mtu_buf->mtu = HTONL(1500);
        opt_hdr_len += OPT_MTU_HDR_LEN;
        packet_length += OPT_MTU_HDR_LEN;
    }

    /* set payload length field */

    if (abro == OPT_ABRO) {
        /* set authoritive border router option */
        if (abr_count > 0) {
            msg_abr = abr_get_most_current();
            opt_abro_buf = get_opt_abro_buf(ipv6_ext_hdr_len, opt_hdr_len);
            opt_abro_buf->type = OPT_ABRO_TYPE;
            opt_abro_buf->length = OPT_ABRO_LEN;
            opt_abro_buf->version = HTONS(msg_abr->version);
            opt_abro_buf->reserved = 0;
            memcpy(&(opt_abro_buf->addr), &(msg_abr->abr_addr), sizeof(ipv6_addr_t));
        }
    }

    if (sixco == OPT_6CO) {
        /* set 6lowpan context option */
        int contexts_len = 0;
        mutex_lock(&lowpan_context_mutex);

        if (msg_abr == NULL) {
            contexts = lowpan_context_get();
            contexts_len = lowpan_context_len();
        }
        else {
            lowpan_context_t c_tmp[LOWPAN_CONTEXT_MAX];

            contexts_len = 0;

            for (int i = 0; i < LOWPAN_CONTEXT_MAX; i++) {
                lowpan_context_t *ctx = abr_get_context(msg_abr, i);

                if (ctx != NULL) {
                    memcpy(&(c_tmp[contexts_len++]), ctx, sizeof(lowpan_context_t));
                }
            }

            contexts = (lowpan_context_t *)calloc(contexts_len, sizeof(lowpan_context_t));
            memcpy(contexts, c_tmp, contexts_len);
        }

        for (int i = 0; i < contexts_len; i++) {
            opt_6co_hdr_buf = get_opt_6co_hdr_buf(ipv6_ext_hdr_len, opt_hdr_len);
            opt_6co_hdr_buf->type = OPT_6CO_TYPE;

            if (contexts[i].length > 64) {
                opt_6co_hdr_buf->length = OPT_6CO_MAX_LEN;
            }
            else {
                opt_6co_hdr_buf->length = OPT_6CO_MIN_LEN;
            }

            opt_6co_hdr_buf->c_length = contexts[i].length;
            opt_6co_hdr_buf->c_flags = set_opt_6co_flags(contexts[i].comp, contexts[i].num);
            opt_6co_hdr_buf->reserved = 0;
            opt_6co_hdr_buf->val_ltime = HTONS(contexts[i].lifetime);

            opt_hdr_len += OPT_6CO_HDR_LEN;
            packet_length += OPT_6CO_HDR_LEN;
            /* attach prefixes */
            opt_6co_prefix_buf = get_opt_6co_prefix_buf(ipv6_ext_hdr_len, opt_hdr_len);

            if (opt_6co_hdr_buf->c_length > 64) {
                memset((void *)opt_6co_prefix_buf, 0, 16);
                memcpy((void *)opt_6co_prefix_buf, (void *) & (contexts[i].prefix.uint8[0]), opt_6co_hdr_buf->c_length / 8);
                opt_hdr_len += 16;
                packet_length += 16;
            }
            else {
                memset((void *)opt_6co_prefix_buf, 0, 8);
                memcpy((void *)opt_6co_prefix_buf, (void *) & (contexts[i].prefix.uint8[0]), opt_6co_hdr_buf->c_length / 8);
                opt_hdr_len += 8;
                packet_length += 8;
            }

        }

        if (msg_abr != NULL && contexts != NULL) {
            free(contexts);
        }

        mutex_unlock(&lowpan_context_mutex, 0);
    }

    if (pi == OPT_PI) {
        /* set prefix option */
        for (int i = 0; i < OPT_PI_LIST_LEN; i++) {
            if (plist[i].inuse && plist[i].adv) {
                opt_pi_buf = get_opt_pi_buf(ipv6_ext_hdr_len, opt_hdr_len);
                memcpy(&(opt_pi_buf->addr.uint8[0]), &(plist[i].addr.uint8[0]), 16);
                opt_pi_buf->type = OPT_PI_TYPE;
                opt_pi_buf->length = OPT_PI_LEN;
                opt_pi_buf->prefix_length = plist[i].length;
                opt_pi_buf->l_a_reserved1 = plist[i].l_a_reserved1;
                opt_pi_buf->val_ltime = HTONL(plist[i].val_ltime);
                opt_pi_buf->pref_ltime = HTONL(plist[i].pref_ltime);
                opt_pi_buf->reserved2 = 0;
                packet_length += OPT_PI_HDR_LEN;
                opt_hdr_len += OPT_PI_HDR_LEN;
            }
        }
    }

    ipv6_buf->length = packet_length - IPV6_HDR_LEN;

    /* calculate checksum */
    icmp_buf->checksum = 0;
    icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
}