batman-adv: tvlv: extract tvlv header iterator

batadv_tvlv_containers_contain() and batadv_tvlv_containers_process() are
using the same code to iterate through the TVLV containers. To simplify the
code, extract the shared portions of both functions.

Signed-off-by: Sven Eckelmann <sven@narfation.org>
This commit is contained in:
Sven Eckelmann 2026-06-14 11:55:27 +02:00
parent ba2d97e873
commit 278e589070
No known key found for this signature in database
GPG Key ID: 4D0F772BD314F5CB

View File

@ -442,6 +442,54 @@ static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,
return NET_RX_SUCCESS;
}
/**
* batadv_tvlv_hdr_next() - move a tvlv buffer cursor to the next container
* @tvlv_value: cursor into the tvlv buffer, advanced past the returned
* container's content on success
* @tvlv_value_len: remaining length of the tvlv buffer, reduced by the returned
* container's size on success
*
* Parses a single container header at the current cursor position and, if a
* complete container is available, advances the cursor and remaining length
* past it. The returned header stays valid; its content is located at
* (returned header + 1) and is ntohs(hdr->len) bytes long.
*
* Return: pointer to the next tvlv container header, or NULL if no further
* complete container is present in the buffer.
*/
static struct batadv_tvlv_hdr *batadv_tvlv_hdr_next(void **tvlv_value, u16 *tvlv_value_len)
{
struct batadv_tvlv_hdr *tvlv_hdr;
u16 tvlv_value_cont_len;
void *tvlv_value_cont;
u16 tvlv_len;
tvlv_value_cont = *tvlv_value;
tvlv_len = *tvlv_value_len;
if (tvlv_len < sizeof(*tvlv_hdr))
return NULL;
tvlv_hdr = tvlv_value_cont;
tvlv_value_cont_len = ntohs(tvlv_hdr->len);
tvlv_value_cont = tvlv_hdr + 1;
tvlv_len -= sizeof(*tvlv_hdr);
if (tvlv_value_cont_len > tvlv_len)
return NULL;
/* the next tvlv header is accessed assuming (at least) 2-byte
* alignment, so it must start at an even offset.
*/
if (tvlv_value_cont_len & 1)
return NULL;
*tvlv_value = (u8 *)tvlv_value_cont + tvlv_value_cont_len;
*tvlv_value_len = tvlv_len - tvlv_value_cont_len;
return tvlv_hdr;
}
/**
* batadv_tvlv_containers_contain() - check if a tvlv buffer holds a container
* @tvlv_value: tvlv content
@ -457,28 +505,10 @@ static bool batadv_tvlv_containers_contain(void *tvlv_value,
u8 version)
{
struct batadv_tvlv_hdr *tvlv_hdr;
u16 tvlv_value_cont_len;
while (tvlv_value_len >= sizeof(*tvlv_hdr)) {
tvlv_hdr = tvlv_value;
tvlv_value_cont_len = ntohs(tvlv_hdr->len);
tvlv_value = tvlv_hdr + 1;
tvlv_value_len -= sizeof(*tvlv_hdr);
if (tvlv_value_cont_len > tvlv_value_len)
break;
/* the next tvlv header is accessed assuming (at least) 2-byte
* alignment, so it must start at an even offset.
*/
if (tvlv_value_cont_len & 1)
break;
while ((tvlv_hdr = batadv_tvlv_hdr_next(&tvlv_value, &tvlv_value_len))) {
if (tvlv_hdr->type == type && tvlv_hdr->version == version)
return true;
tvlv_value = (u8 *)tvlv_value + tvlv_value_cont_len;
tvlv_value_len -= tvlv_value_cont_len;
}
return false;
@ -511,20 +541,8 @@ int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
u8 cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND;
int ret = NET_RX_SUCCESS;
while (tvlv_value_len >= sizeof(*tvlv_hdr)) {
tvlv_hdr = tvlv_value;
while ((tvlv_hdr = batadv_tvlv_hdr_next(&tvlv_value, &tvlv_value_len))) {
tvlv_value_cont_len = ntohs(tvlv_hdr->len);
tvlv_value = tvlv_hdr + 1;
tvlv_value_len -= sizeof(*tvlv_hdr);
if (tvlv_value_cont_len > tvlv_value_len)
break;
/* the next tvlv header is accessed assuming (at least) 2-byte
* alignment, so it must start at an even offset.
*/
if (tvlv_value_cont_len & 1)
break;
tvlv_handler = batadv_tvlv_handler_get(bat_priv,
tvlv_hdr->type,
@ -532,11 +550,9 @@ int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
ret |= batadv_tvlv_call_handler(bat_priv, tvlv_handler,
packet_type, orig_node, skb,
tvlv_value,
tvlv_hdr + 1,
tvlv_value_cont_len);
batadv_tvlv_handler_put(tvlv_handler);
tvlv_value = (u8 *)tvlv_value + tvlv_value_cont_len;
tvlv_value_len -= tvlv_value_cont_len;
}
if (packet_type != BATADV_IV_OGM &&