Exemple #1
0
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);
    }

}
Exemple #2
0
void border_send_ipv6_over_lowpan(struct ipv6_hdr_t *packet, uint8_t aro_flag, uint8_t sixco_flag) {
    uint16_t offset = IPV6_HDR_LEN+HTONS(packet->length);
    
    packet->flowlabel = HTONS(packet->flowlabel);
    packet->length = HTONS(packet->length);
    
    memset(buffer, 0, BUFFER_SIZE);
    memcpy(buffer+LL_HDR_LEN, packet, offset);
    
    lowpan_init((ieee_802154_long_t*)&(packet->destaddr.uint16[4]), (uint8_t*)packet);
}
Exemple #3
0
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);

}
Exemple #4
0
/* 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);
}
Exemple #5
0
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);
    }
}
Exemple #6
0
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);
    }
}