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; }
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; }
/** * 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; }