cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tvlv.c (19177B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (C) B.A.T.M.A.N. contributors:
      3 *
      4 * Marek Lindner, Simon Wunderlich
      5 */
      6
      7#include "main.h"
      8
      9#include <linux/byteorder/generic.h>
     10#include <linux/container_of.h>
     11#include <linux/etherdevice.h>
     12#include <linux/gfp.h>
     13#include <linux/if_ether.h>
     14#include <linux/kref.h>
     15#include <linux/list.h>
     16#include <linux/lockdep.h>
     17#include <linux/netdevice.h>
     18#include <linux/pkt_sched.h>
     19#include <linux/rculist.h>
     20#include <linux/rcupdate.h>
     21#include <linux/skbuff.h>
     22#include <linux/slab.h>
     23#include <linux/spinlock.h>
     24#include <linux/stddef.h>
     25#include <linux/string.h>
     26#include <linux/types.h>
     27#include <uapi/linux/batadv_packet.h>
     28
     29#include "originator.h"
     30#include "send.h"
     31#include "tvlv.h"
     32
     33/**
     34 * batadv_tvlv_handler_release() - release tvlv handler from lists and queue for
     35 *  free after rcu grace period
     36 * @ref: kref pointer of the tvlv
     37 */
     38static void batadv_tvlv_handler_release(struct kref *ref)
     39{
     40	struct batadv_tvlv_handler *tvlv_handler;
     41
     42	tvlv_handler = container_of(ref, struct batadv_tvlv_handler, refcount);
     43	kfree_rcu(tvlv_handler, rcu);
     44}
     45
     46/**
     47 * batadv_tvlv_handler_put() - decrement the tvlv container refcounter and
     48 *  possibly release it
     49 * @tvlv_handler: the tvlv handler to free
     50 */
     51static void batadv_tvlv_handler_put(struct batadv_tvlv_handler *tvlv_handler)
     52{
     53	if (!tvlv_handler)
     54		return;
     55
     56	kref_put(&tvlv_handler->refcount, batadv_tvlv_handler_release);
     57}
     58
     59/**
     60 * batadv_tvlv_handler_get() - retrieve tvlv handler from the tvlv handler list
     61 *  based on the provided type and version (both need to match)
     62 * @bat_priv: the bat priv with all the soft interface information
     63 * @type: tvlv handler type to look for
     64 * @version: tvlv handler version to look for
     65 *
     66 * Return: tvlv handler if found or NULL otherwise.
     67 */
     68static struct batadv_tvlv_handler *
     69batadv_tvlv_handler_get(struct batadv_priv *bat_priv, u8 type, u8 version)
     70{
     71	struct batadv_tvlv_handler *tvlv_handler_tmp, *tvlv_handler = NULL;
     72
     73	rcu_read_lock();
     74	hlist_for_each_entry_rcu(tvlv_handler_tmp,
     75				 &bat_priv->tvlv.handler_list, list) {
     76		if (tvlv_handler_tmp->type != type)
     77			continue;
     78
     79		if (tvlv_handler_tmp->version != version)
     80			continue;
     81
     82		if (!kref_get_unless_zero(&tvlv_handler_tmp->refcount))
     83			continue;
     84
     85		tvlv_handler = tvlv_handler_tmp;
     86		break;
     87	}
     88	rcu_read_unlock();
     89
     90	return tvlv_handler;
     91}
     92
     93/**
     94 * batadv_tvlv_container_release() - release tvlv from lists and free
     95 * @ref: kref pointer of the tvlv
     96 */
     97static void batadv_tvlv_container_release(struct kref *ref)
     98{
     99	struct batadv_tvlv_container *tvlv;
    100
    101	tvlv = container_of(ref, struct batadv_tvlv_container, refcount);
    102	kfree(tvlv);
    103}
    104
    105/**
    106 * batadv_tvlv_container_put() - decrement the tvlv container refcounter and
    107 *  possibly release it
    108 * @tvlv: the tvlv container to free
    109 */
    110static void batadv_tvlv_container_put(struct batadv_tvlv_container *tvlv)
    111{
    112	if (!tvlv)
    113		return;
    114
    115	kref_put(&tvlv->refcount, batadv_tvlv_container_release);
    116}
    117
    118/**
    119 * batadv_tvlv_container_get() - retrieve tvlv container from the tvlv container
    120 *  list based on the provided type and version (both need to match)
    121 * @bat_priv: the bat priv with all the soft interface information
    122 * @type: tvlv container type to look for
    123 * @version: tvlv container version to look for
    124 *
    125 * Has to be called with the appropriate locks being acquired
    126 * (tvlv.container_list_lock).
    127 *
    128 * Return: tvlv container if found or NULL otherwise.
    129 */
    130static struct batadv_tvlv_container *
    131batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version)
    132{
    133	struct batadv_tvlv_container *tvlv_tmp, *tvlv = NULL;
    134
    135	lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
    136
    137	hlist_for_each_entry(tvlv_tmp, &bat_priv->tvlv.container_list, list) {
    138		if (tvlv_tmp->tvlv_hdr.type != type)
    139			continue;
    140
    141		if (tvlv_tmp->tvlv_hdr.version != version)
    142			continue;
    143
    144		kref_get(&tvlv_tmp->refcount);
    145		tvlv = tvlv_tmp;
    146		break;
    147	}
    148
    149	return tvlv;
    150}
    151
    152/**
    153 * batadv_tvlv_container_list_size() - calculate the size of the tvlv container
    154 *  list entries
    155 * @bat_priv: the bat priv with all the soft interface information
    156 *
    157 * Has to be called with the appropriate locks being acquired
    158 * (tvlv.container_list_lock).
    159 *
    160 * Return: size of all currently registered tvlv containers in bytes.
    161 */
    162static u16 batadv_tvlv_container_list_size(struct batadv_priv *bat_priv)
    163{
    164	struct batadv_tvlv_container *tvlv;
    165	u16 tvlv_len = 0;
    166
    167	lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
    168
    169	hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
    170		tvlv_len += sizeof(struct batadv_tvlv_hdr);
    171		tvlv_len += ntohs(tvlv->tvlv_hdr.len);
    172	}
    173
    174	return tvlv_len;
    175}
    176
    177/**
    178 * batadv_tvlv_container_remove() - remove tvlv container from the tvlv
    179 *  container list
    180 * @bat_priv: the bat priv with all the soft interface information
    181 * @tvlv: the to be removed tvlv container
    182 *
    183 * Has to be called with the appropriate locks being acquired
    184 * (tvlv.container_list_lock).
    185 */
    186static void batadv_tvlv_container_remove(struct batadv_priv *bat_priv,
    187					 struct batadv_tvlv_container *tvlv)
    188{
    189	lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
    190
    191	if (!tvlv)
    192		return;
    193
    194	hlist_del(&tvlv->list);
    195
    196	/* first call to decrement the counter, second call to free */
    197	batadv_tvlv_container_put(tvlv);
    198	batadv_tvlv_container_put(tvlv);
    199}
    200
    201/**
    202 * batadv_tvlv_container_unregister() - unregister tvlv container based on the
    203 *  provided type and version (both need to match)
    204 * @bat_priv: the bat priv with all the soft interface information
    205 * @type: tvlv container type to unregister
    206 * @version: tvlv container type to unregister
    207 */
    208void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv,
    209				      u8 type, u8 version)
    210{
    211	struct batadv_tvlv_container *tvlv;
    212
    213	spin_lock_bh(&bat_priv->tvlv.container_list_lock);
    214	tvlv = batadv_tvlv_container_get(bat_priv, type, version);
    215	batadv_tvlv_container_remove(bat_priv, tvlv);
    216	spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
    217}
    218
    219/**
    220 * batadv_tvlv_container_register() - register tvlv type, version and content
    221 *  to be propagated with each (primary interface) OGM
    222 * @bat_priv: the bat priv with all the soft interface information
    223 * @type: tvlv container type
    224 * @version: tvlv container version
    225 * @tvlv_value: tvlv container content
    226 * @tvlv_value_len: tvlv container content length
    227 *
    228 * If a container of the same type and version was already registered the new
    229 * content is going to replace the old one.
    230 */
    231void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
    232				    u8 type, u8 version,
    233				    void *tvlv_value, u16 tvlv_value_len)
    234{
    235	struct batadv_tvlv_container *tvlv_old, *tvlv_new;
    236
    237	if (!tvlv_value)
    238		tvlv_value_len = 0;
    239
    240	tvlv_new = kzalloc(sizeof(*tvlv_new) + tvlv_value_len, GFP_ATOMIC);
    241	if (!tvlv_new)
    242		return;
    243
    244	tvlv_new->tvlv_hdr.version = version;
    245	tvlv_new->tvlv_hdr.type = type;
    246	tvlv_new->tvlv_hdr.len = htons(tvlv_value_len);
    247
    248	memcpy(tvlv_new + 1, tvlv_value, ntohs(tvlv_new->tvlv_hdr.len));
    249	INIT_HLIST_NODE(&tvlv_new->list);
    250	kref_init(&tvlv_new->refcount);
    251
    252	spin_lock_bh(&bat_priv->tvlv.container_list_lock);
    253	tvlv_old = batadv_tvlv_container_get(bat_priv, type, version);
    254	batadv_tvlv_container_remove(bat_priv, tvlv_old);
    255
    256	kref_get(&tvlv_new->refcount);
    257	hlist_add_head(&tvlv_new->list, &bat_priv->tvlv.container_list);
    258	spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
    259
    260	/* don't return reference to new tvlv_container */
    261	batadv_tvlv_container_put(tvlv_new);
    262}
    263
    264/**
    265 * batadv_tvlv_realloc_packet_buff() - reallocate packet buffer to accommodate
    266 *  requested packet size
    267 * @packet_buff: packet buffer
    268 * @packet_buff_len: packet buffer size
    269 * @min_packet_len: requested packet minimum size
    270 * @additional_packet_len: requested additional packet size on top of minimum
    271 *  size
    272 *
    273 * Return: true of the packet buffer could be changed to the requested size,
    274 * false otherwise.
    275 */
    276static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff,
    277					    int *packet_buff_len,
    278					    int min_packet_len,
    279					    int additional_packet_len)
    280{
    281	unsigned char *new_buff;
    282
    283	new_buff = kmalloc(min_packet_len + additional_packet_len, GFP_ATOMIC);
    284
    285	/* keep old buffer if kmalloc should fail */
    286	if (!new_buff)
    287		return false;
    288
    289	memcpy(new_buff, *packet_buff, min_packet_len);
    290	kfree(*packet_buff);
    291	*packet_buff = new_buff;
    292	*packet_buff_len = min_packet_len + additional_packet_len;
    293
    294	return true;
    295}
    296
    297/**
    298 * batadv_tvlv_container_ogm_append() - append tvlv container content to given
    299 *  OGM packet buffer
    300 * @bat_priv: the bat priv with all the soft interface information
    301 * @packet_buff: ogm packet buffer
    302 * @packet_buff_len: ogm packet buffer size including ogm header and tvlv
    303 *  content
    304 * @packet_min_len: ogm header size to be preserved for the OGM itself
    305 *
    306 * The ogm packet might be enlarged or shrunk depending on the current size
    307 * and the size of the to-be-appended tvlv containers.
    308 *
    309 * Return: size of all appended tvlv containers in bytes.
    310 */
    311u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
    312				     unsigned char **packet_buff,
    313				     int *packet_buff_len, int packet_min_len)
    314{
    315	struct batadv_tvlv_container *tvlv;
    316	struct batadv_tvlv_hdr *tvlv_hdr;
    317	u16 tvlv_value_len;
    318	void *tvlv_value;
    319	bool ret;
    320
    321	spin_lock_bh(&bat_priv->tvlv.container_list_lock);
    322	tvlv_value_len = batadv_tvlv_container_list_size(bat_priv);
    323
    324	ret = batadv_tvlv_realloc_packet_buff(packet_buff, packet_buff_len,
    325					      packet_min_len, tvlv_value_len);
    326
    327	if (!ret)
    328		goto end;
    329
    330	if (!tvlv_value_len)
    331		goto end;
    332
    333	tvlv_value = (*packet_buff) + packet_min_len;
    334
    335	hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
    336		tvlv_hdr = tvlv_value;
    337		tvlv_hdr->type = tvlv->tvlv_hdr.type;
    338		tvlv_hdr->version = tvlv->tvlv_hdr.version;
    339		tvlv_hdr->len = tvlv->tvlv_hdr.len;
    340		tvlv_value = tvlv_hdr + 1;
    341		memcpy(tvlv_value, tvlv + 1, ntohs(tvlv->tvlv_hdr.len));
    342		tvlv_value = (u8 *)tvlv_value + ntohs(tvlv->tvlv_hdr.len);
    343	}
    344
    345end:
    346	spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
    347	return tvlv_value_len;
    348}
    349
    350/**
    351 * batadv_tvlv_call_handler() - parse the given tvlv buffer to call the
    352 *  appropriate handlers
    353 * @bat_priv: the bat priv with all the soft interface information
    354 * @tvlv_handler: tvlv callback function handling the tvlv content
    355 * @ogm_source: flag indicating whether the tvlv is an ogm or a unicast packet
    356 * @orig_node: orig node emitting the ogm packet
    357 * @src: source mac address of the unicast packet
    358 * @dst: destination mac address of the unicast packet
    359 * @tvlv_value: tvlv content
    360 * @tvlv_value_len: tvlv content length
    361 *
    362 * Return: success if the handler was not found or the return value of the
    363 * handler callback.
    364 */
    365static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,
    366				    struct batadv_tvlv_handler *tvlv_handler,
    367				    bool ogm_source,
    368				    struct batadv_orig_node *orig_node,
    369				    u8 *src, u8 *dst,
    370				    void *tvlv_value, u16 tvlv_value_len)
    371{
    372	if (!tvlv_handler)
    373		return NET_RX_SUCCESS;
    374
    375	if (ogm_source) {
    376		if (!tvlv_handler->ogm_handler)
    377			return NET_RX_SUCCESS;
    378
    379		if (!orig_node)
    380			return NET_RX_SUCCESS;
    381
    382		tvlv_handler->ogm_handler(bat_priv, orig_node,
    383					  BATADV_NO_FLAGS,
    384					  tvlv_value, tvlv_value_len);
    385		tvlv_handler->flags |= BATADV_TVLV_HANDLER_OGM_CALLED;
    386	} else {
    387		if (!src)
    388			return NET_RX_SUCCESS;
    389
    390		if (!dst)
    391			return NET_RX_SUCCESS;
    392
    393		if (!tvlv_handler->unicast_handler)
    394			return NET_RX_SUCCESS;
    395
    396		return tvlv_handler->unicast_handler(bat_priv, src,
    397						     dst, tvlv_value,
    398						     tvlv_value_len);
    399	}
    400
    401	return NET_RX_SUCCESS;
    402}
    403
    404/**
    405 * batadv_tvlv_containers_process() - parse the given tvlv buffer to call the
    406 *  appropriate handlers
    407 * @bat_priv: the bat priv with all the soft interface information
    408 * @ogm_source: flag indicating whether the tvlv is an ogm or a unicast packet
    409 * @orig_node: orig node emitting the ogm packet
    410 * @src: source mac address of the unicast packet
    411 * @dst: destination mac address of the unicast packet
    412 * @tvlv_value: tvlv content
    413 * @tvlv_value_len: tvlv content length
    414 *
    415 * Return: success when processing an OGM or the return value of all called
    416 * handler callbacks.
    417 */
    418int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
    419				   bool ogm_source,
    420				   struct batadv_orig_node *orig_node,
    421				   u8 *src, u8 *dst,
    422				   void *tvlv_value, u16 tvlv_value_len)
    423{
    424	struct batadv_tvlv_handler *tvlv_handler;
    425	struct batadv_tvlv_hdr *tvlv_hdr;
    426	u16 tvlv_value_cont_len;
    427	u8 cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND;
    428	int ret = NET_RX_SUCCESS;
    429
    430	while (tvlv_value_len >= sizeof(*tvlv_hdr)) {
    431		tvlv_hdr = tvlv_value;
    432		tvlv_value_cont_len = ntohs(tvlv_hdr->len);
    433		tvlv_value = tvlv_hdr + 1;
    434		tvlv_value_len -= sizeof(*tvlv_hdr);
    435
    436		if (tvlv_value_cont_len > tvlv_value_len)
    437			break;
    438
    439		tvlv_handler = batadv_tvlv_handler_get(bat_priv,
    440						       tvlv_hdr->type,
    441						       tvlv_hdr->version);
    442
    443		ret |= batadv_tvlv_call_handler(bat_priv, tvlv_handler,
    444						ogm_source, orig_node,
    445						src, dst, tvlv_value,
    446						tvlv_value_cont_len);
    447		batadv_tvlv_handler_put(tvlv_handler);
    448		tvlv_value = (u8 *)tvlv_value + tvlv_value_cont_len;
    449		tvlv_value_len -= tvlv_value_cont_len;
    450	}
    451
    452	if (!ogm_source)
    453		return ret;
    454
    455	rcu_read_lock();
    456	hlist_for_each_entry_rcu(tvlv_handler,
    457				 &bat_priv->tvlv.handler_list, list) {
    458		if ((tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) &&
    459		    !(tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CALLED))
    460			tvlv_handler->ogm_handler(bat_priv, orig_node,
    461						  cifnotfound, NULL, 0);
    462
    463		tvlv_handler->flags &= ~BATADV_TVLV_HANDLER_OGM_CALLED;
    464	}
    465	rcu_read_unlock();
    466
    467	return NET_RX_SUCCESS;
    468}
    469
    470/**
    471 * batadv_tvlv_ogm_receive() - process an incoming ogm and call the appropriate
    472 *  handlers
    473 * @bat_priv: the bat priv with all the soft interface information
    474 * @batadv_ogm_packet: ogm packet containing the tvlv containers
    475 * @orig_node: orig node emitting the ogm packet
    476 */
    477void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
    478			     struct batadv_ogm_packet *batadv_ogm_packet,
    479			     struct batadv_orig_node *orig_node)
    480{
    481	void *tvlv_value;
    482	u16 tvlv_value_len;
    483
    484	if (!batadv_ogm_packet)
    485		return;
    486
    487	tvlv_value_len = ntohs(batadv_ogm_packet->tvlv_len);
    488	if (!tvlv_value_len)
    489		return;
    490
    491	tvlv_value = batadv_ogm_packet + 1;
    492
    493	batadv_tvlv_containers_process(bat_priv, true, orig_node, NULL, NULL,
    494				       tvlv_value, tvlv_value_len);
    495}
    496
    497/**
    498 * batadv_tvlv_handler_register() - register tvlv handler based on the provided
    499 *  type and version (both need to match) for ogm tvlv payload and/or unicast
    500 *  payload
    501 * @bat_priv: the bat priv with all the soft interface information
    502 * @optr: ogm tvlv handler callback function. This function receives the orig
    503 *  node, flags and the tvlv content as argument to process.
    504 * @uptr: unicast tvlv handler callback function. This function receives the
    505 *  source & destination of the unicast packet as well as the tvlv content
    506 *  to process.
    507 * @type: tvlv handler type to be registered
    508 * @version: tvlv handler version to be registered
    509 * @flags: flags to enable or disable TVLV API behavior
    510 */
    511void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
    512				  void (*optr)(struct batadv_priv *bat_priv,
    513					       struct batadv_orig_node *orig,
    514					       u8 flags,
    515					       void *tvlv_value,
    516					       u16 tvlv_value_len),
    517				  int (*uptr)(struct batadv_priv *bat_priv,
    518					      u8 *src, u8 *dst,
    519					      void *tvlv_value,
    520					      u16 tvlv_value_len),
    521				  u8 type, u8 version, u8 flags)
    522{
    523	struct batadv_tvlv_handler *tvlv_handler;
    524
    525	spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
    526
    527	tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
    528	if (tvlv_handler) {
    529		spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
    530		batadv_tvlv_handler_put(tvlv_handler);
    531		return;
    532	}
    533
    534	tvlv_handler = kzalloc(sizeof(*tvlv_handler), GFP_ATOMIC);
    535	if (!tvlv_handler) {
    536		spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
    537		return;
    538	}
    539
    540	tvlv_handler->ogm_handler = optr;
    541	tvlv_handler->unicast_handler = uptr;
    542	tvlv_handler->type = type;
    543	tvlv_handler->version = version;
    544	tvlv_handler->flags = flags;
    545	kref_init(&tvlv_handler->refcount);
    546	INIT_HLIST_NODE(&tvlv_handler->list);
    547
    548	kref_get(&tvlv_handler->refcount);
    549	hlist_add_head_rcu(&tvlv_handler->list, &bat_priv->tvlv.handler_list);
    550	spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
    551
    552	/* don't return reference to new tvlv_handler */
    553	batadv_tvlv_handler_put(tvlv_handler);
    554}
    555
    556/**
    557 * batadv_tvlv_handler_unregister() - unregister tvlv handler based on the
    558 *  provided type and version (both need to match)
    559 * @bat_priv: the bat priv with all the soft interface information
    560 * @type: tvlv handler type to be unregistered
    561 * @version: tvlv handler version to be unregistered
    562 */
    563void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv,
    564				    u8 type, u8 version)
    565{
    566	struct batadv_tvlv_handler *tvlv_handler;
    567
    568	tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
    569	if (!tvlv_handler)
    570		return;
    571
    572	batadv_tvlv_handler_put(tvlv_handler);
    573	spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
    574	hlist_del_rcu(&tvlv_handler->list);
    575	spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
    576	batadv_tvlv_handler_put(tvlv_handler);
    577}
    578
    579/**
    580 * batadv_tvlv_unicast_send() - send a unicast packet with tvlv payload to the
    581 *  specified host
    582 * @bat_priv: the bat priv with all the soft interface information
    583 * @src: source mac address of the unicast packet
    584 * @dst: destination mac address of the unicast packet
    585 * @type: tvlv type
    586 * @version: tvlv version
    587 * @tvlv_value: tvlv content
    588 * @tvlv_value_len: tvlv content length
    589 */
    590void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, const u8 *src,
    591			      const u8 *dst, u8 type, u8 version,
    592			      void *tvlv_value, u16 tvlv_value_len)
    593{
    594	struct batadv_unicast_tvlv_packet *unicast_tvlv_packet;
    595	struct batadv_tvlv_hdr *tvlv_hdr;
    596	struct batadv_orig_node *orig_node;
    597	struct sk_buff *skb;
    598	unsigned char *tvlv_buff;
    599	unsigned int tvlv_len;
    600	ssize_t hdr_len = sizeof(*unicast_tvlv_packet);
    601
    602	orig_node = batadv_orig_hash_find(bat_priv, dst);
    603	if (!orig_node)
    604		return;
    605
    606	tvlv_len = sizeof(*tvlv_hdr) + tvlv_value_len;
    607
    608	skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + hdr_len + tvlv_len);
    609	if (!skb)
    610		goto out;
    611
    612	skb->priority = TC_PRIO_CONTROL;
    613	skb_reserve(skb, ETH_HLEN);
    614	tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
    615	unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
    616	unicast_tvlv_packet->packet_type = BATADV_UNICAST_TVLV;
    617	unicast_tvlv_packet->version = BATADV_COMPAT_VERSION;
    618	unicast_tvlv_packet->ttl = BATADV_TTL;
    619	unicast_tvlv_packet->reserved = 0;
    620	unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
    621	unicast_tvlv_packet->align = 0;
    622	ether_addr_copy(unicast_tvlv_packet->src, src);
    623	ether_addr_copy(unicast_tvlv_packet->dst, dst);
    624
    625	tvlv_buff = (unsigned char *)(unicast_tvlv_packet + 1);
    626	tvlv_hdr = (struct batadv_tvlv_hdr *)tvlv_buff;
    627	tvlv_hdr->version = version;
    628	tvlv_hdr->type = type;
    629	tvlv_hdr->len = htons(tvlv_value_len);
    630	tvlv_buff += sizeof(*tvlv_hdr);
    631	memcpy(tvlv_buff, tvlv_value, tvlv_value_len);
    632
    633	batadv_send_skb_to_orig(skb, orig_node, NULL);
    634out:
    635	batadv_orig_node_put(orig_node);
    636}