Ejemplo n.º 1
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);
    }
}
Ejemplo n.º 2
0
void demultiplex(border_packet_t *packet)
{
    switch (packet->type) {
        case (BORDER_PACKET_RAW_TYPE): {
            fputs(((char *)packet) + sizeof(border_packet_t), stdin);
            break;
        }

        case (BORDER_PACKET_L3_TYPE): {
            border_l3_header_t *l3_header_buf = (border_l3_header_t *)packet;

            switch (l3_header_buf->ethertype) {
                case (BORDER_ETHERTYPE_IPV6): {
                    ipv6_hdr_t *ipv6_buf = (ipv6_hdr_t *)(((unsigned char *)packet) + sizeof(border_l3_header_t));
                    ipv6_send_packet(ipv6_buf);
                    break;
                }

                default:
                    printf("ERROR: Unknown ethertype 0x%04x\n", l3_header_buf->ethertype);
                    break;
            }

            break;
        }

        case (BORDER_PACKET_CONF_TYPE): {
            border_conf_header_t *conf_header_buf = (border_conf_header_t *)packet;

            switch (conf_header_buf->conftype) {
                case (BORDER_CONF_CONTEXT): {
                    border_context_packet_t *context = (border_context_packet_t *)packet;
                    ipv6_addr_t target_addr;
                    ipv6_addr_set_all_nodes_addr(&target_addr);
                    mutex_lock(&lowpan_context_mutex);
                    lowpan_context_update(
                        context->context.cid,
                        &context->context.prefix,
                        context->context.length,
                        context->context.comp,
                        context->context.lifetime
                    );
                    mutex_unlock(&lowpan_context_mutex);
                    abr_add_context(context->context.version, abr_addr, context->context.cid);
                    /* Send router advertisement */
                    break;
                }

                case (BORDER_CONF_IPADDR): {
                    //border_addr_packet_t *addr_packet = (border_addr_packet_t *)packet;
                    /* add address */
                    break;
                }

                default:
                    printf("ERROR: Unknown conftype %02x\n", conf_header_buf->conftype);
                    break;
            }

            break;
        }

        default:
            printf("ERROR: Unknown border packet type %02x\n", packet->type);
            break;
    }
}