Beispiel #1
0
int nhdp_add_address(kernel_pid_t if_pid, uint8_t *addr, size_t addr_size, uint8_t addr_type)
{
    int result;

    /* Get NHDP address entry for the given address */
    nhdp_addr_t *nhdp_addr = nhdp_addr_db_get_address(addr, addr_size, addr_type);

    if (!nhdp_addr) {
        /* Insufficient memory */
        return -1;
    }

    result = lib_add_if_addr(if_pid, nhdp_addr);
    nhdp_decrement_addr_usage(nhdp_addr);

    return result;
}
Beispiel #2
0
int nhdp_register_if(kernel_pid_t if_pid, uint8_t *addr, size_t addr_size, uint8_t addr_type,
                     uint16_t max_pl_size, uint16_t hello_int_ms, uint16_t val_time_ms)
{
    nhdp_if_entry_t *if_entry = NULL;
    nhdp_addr_t *nhdp_addr;
    msg_t signal_msg;

    if (nhdp_rcv_pid != KERNEL_PID_UNDEF) {
        return -2;
    }

    for (int i = 0; i < GNRC_NETIF_NUMOF; i++) {
        if (nhdp_if_table[i].if_pid == KERNEL_PID_UNDEF) {
            if_entry = &nhdp_if_table[i];
            break;
        }
    }

    if (!if_entry) {
        /* Maximum number of registerable interfaces reached */
        return -2;
    }

    uint16_t payload_size = max_pl_size > NHDP_MAX_RFC5444_PACKET_SZ
                            ? NHDP_MAX_RFC5444_PACKET_SZ : max_pl_size;
    if_entry->wr_target.packet_buffer = (uint8_t *) calloc(payload_size, sizeof(uint8_t));

    if (!if_entry->wr_target.packet_buffer) {
        /* Insufficient memory */
        return -1;
    }

    if_entry->wr_target.packet_size = payload_size;
    if_entry->wr_target.sendPacket = write_packet;

    /* Get NHDP address entry for the given address */
    nhdp_addr = nhdp_addr_db_get_address(addr, addr_size, addr_type);

    if (!nhdp_addr) {
        /* Insufficient memory */
        free(if_entry->wr_target.packet_buffer);
        return -1;
    }

    /* Add the interface to the LIB */
    if (lib_add_if_addr(if_pid, nhdp_addr) != 0) {
        free(if_entry->wr_target.packet_buffer);
        nhdp_decrement_addr_usage(nhdp_addr);
        return -1;
    }

    /* Create new IIB for the interface */
    if (iib_register_if(if_pid) != 0) {
        /* TODO: Cleanup lib entry */
        free(if_entry->wr_target.packet_buffer);
        nhdp_decrement_addr_usage(nhdp_addr);
        return -1;
    }

    /* Set Interface's PID */
    if_entry->if_pid = if_pid;
    /* Set HELLO_INTERVAL and H_HOLD_TIME (validity time) */
    if_entry->hello_interval.seconds = 0;
    if_entry->hello_interval.microseconds = MS_IN_USEC * hello_int_ms;
    if_entry->validity_time.seconds = 0;
    if_entry->validity_time.microseconds = MS_IN_USEC * val_time_ms;
    timex_normalize(&if_entry->hello_interval);
    timex_normalize(&if_entry->validity_time);
    /* Reset sequence number */
    if_entry->seq_no = 0;

    /* Everything went well */
    nhdp_decrement_addr_usage(nhdp_addr);
    nhdp_writer_register_if(&if_entry->wr_target);
    helper_pid = if_pid;

    /* Start the receiving thread */
    nhdp_rcv_pid = thread_create(nhdp_rcv_stack, sizeof(nhdp_rcv_stack), THREAD_PRIORITY_MAIN - 1,
                                 THREAD_CREATE_STACKTEST, _nhdp_receiver, NULL, "nhdp_rcv_thread");

    /* Start sending periodic HELLO */
    signal_msg.type = HELLO_TIMER;
    signal_msg.content.ptr = if_entry;
    /* TODO: msg_send or msg_try_send? */
    msg_try_send(&signal_msg, nhdp_pid);

    return 0;
}
Beispiel #3
0
/**
 * Handle one address and its corresponding TLVs
 * Called by oonf_api for every included address to allow parsing
 */
static enum rfc5444_result
_nhdp_blocktlv_address_cb(struct rfc5444_reader_tlvblock_context *cont)
{
    uint8_t tmp_result;

    /* Get NHDP address for the current netaddr */
    nhdp_addr_t *current_addr = get_nhdp_db_addr(&cont->addr._addr[0], cont->addr._prefix_len);

    if (!current_addr) {
        /* Insufficient memory */
        return RFC5444_DROP_MESSAGE;
    }

    /* Check validity of address tlvs */
    if (check_addr_validity(current_addr) != RFC5444_OKAY) {
        nhdp_decrement_addr_usage(current_addr);
        return RFC5444_DROP_MESSAGE;
    }

    /* Handle address and add it to proper temporary list */
    if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_LOCAL_IF].tlv) {
        switch (*_nhdp_addr_tlvs[RFC5444_ADDRTLV_LOCAL_IF].tlv->single_value) {
            case RFC5444_LOCALIF_THIS_IF:
                current_addr->in_tmp_table = NHDP_ADDR_TMP_SEND_LIST;
                break;

            case RFC5444_LOCALIF_OTHER_IF:
                current_addr->in_tmp_table = NHDP_ADDR_TMP_NB_LIST;
                break;

            default:
                /* Wrong value, drop message */
                nhdp_decrement_addr_usage(current_addr);
                return RFC5444_DROP_MESSAGE;
        }
    }
    else if ((tmp_result = lib_is_reg_addr(if_pid, current_addr))) {
        /* The address is one of our local addresses (do not add it for processing) */
        if ((!sym) && (tmp_result == 1) && _nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_STATUS].tlv) {
            /* If address is a local address of the receiving interface, check */
            /* whether we can derive a status for this link (symmetry or lost) */
            switch (*_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_STATUS].tlv->single_value) {
                case RFC5444_LINKSTATUS_SYMMETRIC:
                    /* Fall - through */

                case RFC5444_LINKSTATUS_HEARD:
                    sym = 1;
                    break;

                case RFC5444_LINKSTATUS_LOST:
                    lost = 1;
                    break;

                default:
                    /* Wrong value, drop message */
                    nhdp_decrement_addr_usage(current_addr);
                    return RFC5444_DROP_MESSAGE;
            }
        }

        if (lt_metric_val == NHDP_METRIC_UNKNOWN
            && _nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_METRIC].tlv != NULL) {
            /* Determine our outgoing link metric value to the originator interface */
            uint16_t metric_enc = *((uint16_t*)_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_METRIC]
                                                      .tlv->single_value);
            if (metric_enc & NHDP_KD_LM_INC) {
                /* Incoming metric value at the neighbor if is outgoing value for our if */
                lt_metric_val = rfc5444_metric_decode(metric_enc);
            }
        }

        /* Address is one of our own addresses, ignore it */
        nhdp_decrement_addr_usage(current_addr);
    }
    else if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_STATUS].tlv) {
        switch (*_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_STATUS].tlv->single_value) {
            case RFC5444_LINKSTATUS_SYMMETRIC:
                add_temp_metric_value(current_addr);
                current_addr->in_tmp_table = NHDP_ADDR_TMP_TH_SYM_LIST;
                break;

            case RFC5444_LINKSTATUS_HEARD:
                /* Fall-through */

            case RFC5444_LINKSTATUS_LOST:
                if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_OTHER_NEIGHB].tlv
                    && *_nhdp_addr_tlvs[RFC5444_ADDRTLV_OTHER_NEIGHB].tlv->single_value
                    == RFC5444_OTHERNEIGHB_SYMMETRIC) {
                    /* Symmetric has higher priority */
                    add_temp_metric_value(current_addr);
                    current_addr->in_tmp_table = NHDP_ADDR_TMP_TH_SYM_LIST;
                }
                else {
                    current_addr->in_tmp_table = NHDP_ADDR_TMP_TH_REM_LIST;
                }

                break;

            default:
                /* Wrong value, drop message */
                nhdp_decrement_addr_usage(current_addr);
                return RFC5444_DROP_MESSAGE;
        }
    }
    else if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_OTHER_NEIGHB].tlv) {
        switch (*_nhdp_addr_tlvs[RFC5444_ADDRTLV_OTHER_NEIGHB].tlv->single_value) {
            case RFC5444_OTHERNEIGHB_SYMMETRIC:
                add_temp_metric_value(current_addr);
                current_addr->in_tmp_table = NHDP_ADDR_TMP_TH_SYM_LIST;
                break;

            case RFC5444_OTHERNEIGHB_LOST:
                current_addr->in_tmp_table = NHDP_ADDR_TMP_TH_REM_LIST;
                break;

            default:
                /* Wrong value, drop message */
                nhdp_decrement_addr_usage(current_addr);
                return RFC5444_DROP_MESSAGE;
        }
    }
    else {
        /* Addresses without expected TLV are ignored */
        nhdp_decrement_addr_usage(current_addr);
        return RFC5444_DROP_ADDRESS;
    }

    return RFC5444_OKAY;
}