uip-nd6: bugfix on address resolution by Neighbor Discovery protocol
nbr_table_update_lladdr() fails to update the lladdr of a nbr with a new one when the new lladdr is used in nbr_table. This causes communication errors when NS/NA is employed. uip_ds6_nbr_update_ll() is introduced to resolve this issue. And nbr_table_update_lladdr() is removed since it's not used any more.
This commit is contained in:
parent
55f4f2ab44
commit
601e14ebc7
@ -127,6 +127,41 @@ uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int
|
||||||
|
uip_ds6_nbr_update_ll(uip_ds6_nbr_t **nbr_pp, const uip_lladdr_t *new_ll_addr)
|
||||||
|
{
|
||||||
|
uip_ds6_nbr_t nbr_backup;
|
||||||
|
|
||||||
|
if(nbr_pp == NULL || new_ll_addr == NULL) {
|
||||||
|
LOG_ERR("%s: invalid argument\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure new_ll_addr is not used in some other nbr */
|
||||||
|
if(uip_ds6_nbr_ll_lookup(new_ll_addr) != NULL) {
|
||||||
|
LOG_ERR("%s: new_ll_addr, ", __func__);
|
||||||
|
LOG_ERR_LLADDR((const linkaddr_t *)new_ll_addr);
|
||||||
|
LOG_ERR_(", is already used in another nbr\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&nbr_backup, *nbr_pp, sizeof(uip_ds6_nbr_t));
|
||||||
|
if(uip_ds6_nbr_rm(*nbr_pp) == 0) {
|
||||||
|
LOG_ERR("%s: input nbr cannot be removed\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((*nbr_pp = uip_ds6_nbr_add(&nbr_backup.ipaddr, new_ll_addr,
|
||||||
|
nbr_backup.isrouter, nbr_backup.state,
|
||||||
|
NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) {
|
||||||
|
LOG_ERR("%s: cannot allocate a new nbr for new_ll_addr\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(*nbr_pp, &nbr_backup, sizeof(uip_ds6_nbr_t));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
const uip_ipaddr_t *
|
const uip_ipaddr_t *
|
||||||
uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr)
|
uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr)
|
||||||
|
@ -90,6 +90,7 @@ uip_ds6_nbr_t *uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr,
|
|||||||
nbr_table_reason_t reason, void *data);
|
nbr_table_reason_t reason, void *data);
|
||||||
int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr);
|
int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr);
|
||||||
const uip_lladdr_t *uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr);
|
const uip_lladdr_t *uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr);
|
||||||
|
int uip_ds6_nbr_update_ll(uip_ds6_nbr_t **nbr, const uip_lladdr_t *new_ll_addr);
|
||||||
const uip_ipaddr_t *uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr);
|
const uip_ipaddr_t *uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr);
|
||||||
uip_ds6_nbr_t *uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr);
|
uip_ds6_nbr_t *uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr);
|
||||||
uip_ds6_nbr_t *uip_ds6_nbr_ll_lookup(const uip_lladdr_t *lladdr);
|
uip_ds6_nbr_t *uip_ds6_nbr_ll_lookup(const uip_lladdr_t *lladdr);
|
||||||
|
@ -230,7 +230,9 @@ ns_input(void)
|
|||||||
}
|
}
|
||||||
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||||
lladdr, UIP_LLADDR_LEN) != 0) {
|
lladdr, UIP_LLADDR_LEN) != 0) {
|
||||||
if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) {
|
if(uip_ds6_nbr_update_ll(&nbr,
|
||||||
|
(const uip_lladdr_t *)&lladdr_aligned)
|
||||||
|
< 0) {
|
||||||
/* failed to update the lladdr */
|
/* failed to update the lladdr */
|
||||||
goto discard;
|
goto discard;
|
||||||
}
|
}
|
||||||
@ -534,7 +536,8 @@ na_input(void)
|
|||||||
if(nd6_opt_llao == NULL || !extract_lladdr_from_llao_aligned(&lladdr_aligned)) {
|
if(nd6_opt_llao == NULL || !extract_lladdr_from_llao_aligned(&lladdr_aligned)) {
|
||||||
goto discard;
|
goto discard;
|
||||||
}
|
}
|
||||||
if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) {
|
if(uip_ds6_nbr_update_ll(&nbr,
|
||||||
|
(const uip_lladdr_t *)&lladdr_aligned) < 0) {
|
||||||
/* failed to update the lladdr */
|
/* failed to update the lladdr */
|
||||||
goto discard;
|
goto discard;
|
||||||
}
|
}
|
||||||
@ -561,7 +564,9 @@ na_input(void)
|
|||||||
if(is_override || !is_llchange || nd6_opt_llao == NULL) {
|
if(is_override || !is_llchange || nd6_opt_llao == NULL) {
|
||||||
if(nd6_opt_llao != NULL && is_llchange) {
|
if(nd6_opt_llao != NULL && is_llchange) {
|
||||||
if(!extract_lladdr_from_llao_aligned(&lladdr_aligned) ||
|
if(!extract_lladdr_from_llao_aligned(&lladdr_aligned) ||
|
||||||
nbr_table_update_lladdr((const linkaddr_t *) lladdr, (const linkaddr_t *) &lladdr_aligned, 1) == 0) {
|
uip_ds6_nbr_update_ll(&nbr,
|
||||||
|
(const uip_lladdr_t *)&lladdr_aligned)
|
||||||
|
< 0) {
|
||||||
/* failed to update the lladdr */
|
/* failed to update the lladdr */
|
||||||
goto discard;
|
goto discard;
|
||||||
}
|
}
|
||||||
@ -925,7 +930,8 @@ ra_input(void)
|
|||||||
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
|
||||||
lladdr, UIP_LLADDR_LEN) != 0) {
|
lladdr, UIP_LLADDR_LEN) != 0) {
|
||||||
/* change of link layer address */
|
/* change of link layer address */
|
||||||
if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) {
|
if(uip_ds6_nbr_update_ll(&nbr,
|
||||||
|
(const uip_lladdr_t *)&lladdr_aligned) < 0) {
|
||||||
/* failed to update the lladdr */
|
/* failed to update the lladdr */
|
||||||
goto discard;
|
goto discard;
|
||||||
}
|
}
|
||||||
|
@ -439,39 +439,6 @@ nbr_table_get_lladdr(nbr_table_t *table, const void *item)
|
|||||||
return key != NULL ? &key->lladdr : NULL;
|
return key != NULL ? &key->lladdr : NULL;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* Update link-layer address of an item */
|
|
||||||
int
|
|
||||||
nbr_table_update_lladdr(const linkaddr_t *old_addr, const linkaddr_t *new_addr,
|
|
||||||
int remove_if_duplicate)
|
|
||||||
{
|
|
||||||
int index;
|
|
||||||
int new_index;
|
|
||||||
nbr_table_key_t *key;
|
|
||||||
index = index_from_lladdr(old_addr);
|
|
||||||
if(index == -1) {
|
|
||||||
/* Failure to change since there is nothing to change. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if((new_index = index_from_lladdr(new_addr)) != -1) {
|
|
||||||
/* check if it is a change or not - do not remove / fail if same */
|
|
||||||
if(new_index == index) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* This new entry already exists - failure! - remove if requested. */
|
|
||||||
if(remove_if_duplicate) {
|
|
||||||
remove_key(key_from_index(index));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
key = key_from_index(index);
|
|
||||||
/**
|
|
||||||
* Copy the new lladdr into the key - since we know that there is no
|
|
||||||
* conflicting entry.
|
|
||||||
*/
|
|
||||||
memcpy(&key->lladdr, new_addr, sizeof(linkaddr_t));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
static void
|
static void
|
||||||
print_table()
|
print_table()
|
||||||
|
@ -113,7 +113,6 @@ int nbr_table_unlock(nbr_table_t *table, nbr_table_item_t *item);
|
|||||||
/** \name Neighbor tables: address manipulation */
|
/** \name Neighbor tables: address manipulation */
|
||||||
/** @{ */
|
/** @{ */
|
||||||
linkaddr_t *nbr_table_get_lladdr(nbr_table_t *table, const nbr_table_item_t *item);
|
linkaddr_t *nbr_table_get_lladdr(nbr_table_t *table, const nbr_table_item_t *item);
|
||||||
int nbr_table_update_lladdr(const linkaddr_t *old_addr, const linkaddr_t *new_addr, int remove_if_duplicate);
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#endif /* NBR_TABLE_H_ */
|
#endif /* NBR_TABLE_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user