xref: /linux/net/batman-adv/tvlv.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
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/bug.h>
10 #include <linux/byteorder/generic.h>
11 #include <linux/container_of.h>
12 #include <linux/errno.h>
13 #include <linux/etherdevice.h>
14 #include <linux/gfp.h>
15 #include <linux/if_ether.h>
16 #include <linux/kref.h>
17 #include <linux/limits.h>
18 #include <linux/list.h>
19 #include <linux/lockdep.h>
20 #include <linux/log2.h>
21 #include <linux/netdevice.h>
22 #include <linux/pkt_sched.h>
23 #include <linux/rculist.h>
24 #include <linux/rcupdate.h>
25 #include <linux/skbuff.h>
26 #include <linux/slab.h>
27 #include <linux/spinlock.h>
28 #include <linux/stddef.h>
29 #include <linux/string.h>
30 #include <linux/types.h>
31 #include <uapi/linux/batadv_packet.h>
32 
33 #include "originator.h"
34 #include "send.h"
35 #include "tvlv.h"
36 
37 /**
38  * batadv_tvlv_handler_release() - release tvlv handler from lists and queue for
39  *  free after rcu grace period
40  * @ref: kref pointer of the tvlv
41  */
42 static void batadv_tvlv_handler_release(struct kref *ref)
43 {
44 	struct batadv_tvlv_handler *tvlv_handler;
45 
46 	tvlv_handler = container_of(ref, struct batadv_tvlv_handler, refcount);
47 	kfree_rcu(tvlv_handler, rcu);
48 }
49 
50 /**
51  * batadv_tvlv_handler_put() - decrement the tvlv handler refcounter and
52  *  possibly release it
53  * @tvlv_handler: the tvlv handler to free
54  */
55 static void batadv_tvlv_handler_put(struct batadv_tvlv_handler *tvlv_handler)
56 {
57 	if (!tvlv_handler)
58 		return;
59 
60 	kref_put(&tvlv_handler->refcount, batadv_tvlv_handler_release);
61 }
62 
63 /**
64  * batadv_tvlv_handler_get() - retrieve tvlv handler from the tvlv handler list
65  *  based on the provided type and version (both need to match)
66  * @bat_priv: the bat priv with all the mesh interface information
67  * @type: tvlv handler type to look for
68  * @version: tvlv handler version to look for
69  *
70  * Return: tvlv handler if found or NULL otherwise.
71  */
72 static struct batadv_tvlv_handler *
73 batadv_tvlv_handler_get(struct batadv_priv *bat_priv, u8 type, u8 version)
74 {
75 	struct batadv_tvlv_handler *tvlv_handler = NULL;
76 	struct batadv_tvlv_handler *tvlv_handler_tmp;
77 
78 	rcu_read_lock();
79 	hlist_for_each_entry_rcu(tvlv_handler_tmp,
80 				 &bat_priv->tvlv.handler_list, list) {
81 		if (tvlv_handler_tmp->type != type)
82 			continue;
83 
84 		if (tvlv_handler_tmp->version != version)
85 			continue;
86 
87 		if (!kref_get_unless_zero(&tvlv_handler_tmp->refcount))
88 			continue;
89 
90 		tvlv_handler = tvlv_handler_tmp;
91 		break;
92 	}
93 	rcu_read_unlock();
94 
95 	return tvlv_handler;
96 }
97 
98 /**
99  * batadv_tvlv_container_release() - release tvlv from lists and free
100  * @ref: kref pointer of the tvlv
101  */
102 static void batadv_tvlv_container_release(struct kref *ref)
103 {
104 	struct batadv_tvlv_container *tvlv;
105 
106 	tvlv = container_of(ref, struct batadv_tvlv_container, refcount);
107 	kfree(tvlv);
108 }
109 
110 /**
111  * batadv_tvlv_container_put() - decrement the tvlv container refcounter and
112  *  possibly release it
113  * @tvlv: the tvlv container to free
114  */
115 static void batadv_tvlv_container_put(struct batadv_tvlv_container *tvlv)
116 {
117 	if (!tvlv)
118 		return;
119 
120 	kref_put(&tvlv->refcount, batadv_tvlv_container_release);
121 }
122 
123 /**
124  * batadv_tvlv_container_get() - retrieve tvlv container from the tvlv container
125  *  list based on the provided type and version (both need to match)
126  * @bat_priv: the bat priv with all the mesh interface information
127  * @type: tvlv container type to look for
128  * @version: tvlv container version to look for
129  *
130  * Has to be called with the appropriate locks being acquired
131  * (tvlv.container_list_lock).
132  *
133  * Return: tvlv container if found or NULL otherwise.
134  */
135 static struct batadv_tvlv_container *
136 batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version)
137 {
138 	struct batadv_tvlv_container *tvlv = NULL;
139 	struct batadv_tvlv_container *tvlv_tmp;
140 
141 	lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
142 
143 	hlist_for_each_entry(tvlv_tmp, &bat_priv->tvlv.container_list, list) {
144 		if (tvlv_tmp->tvlv_hdr.type != type)
145 			continue;
146 
147 		if (tvlv_tmp->tvlv_hdr.version != version)
148 			continue;
149 
150 		kref_get(&tvlv_tmp->refcount);
151 		tvlv = tvlv_tmp;
152 		break;
153 	}
154 
155 	return tvlv;
156 }
157 
158 /**
159  * batadv_tvlv_container_list_size() - calculate the size of the tvlv container
160  *  list entries
161  * @bat_priv: the bat priv with all the mesh interface information
162  *
163  * Has to be called with the appropriate locks being acquired
164  * (tvlv.container_list_lock).
165  *
166  * Return: size of all currently registered tvlv containers in bytes.
167  */
168 static size_t batadv_tvlv_container_list_size(struct batadv_priv *bat_priv)
169 {
170 	struct batadv_tvlv_container *tvlv;
171 	size_t tvlv_len = 0;
172 
173 	lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
174 
175 	hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
176 		tvlv_len += sizeof(struct batadv_tvlv_hdr);
177 		tvlv_len += ntohs(tvlv->tvlv_hdr.len);
178 	}
179 
180 	return tvlv_len;
181 }
182 
183 /**
184  * batadv_tvlv_container_remove() - remove tvlv container from the tvlv
185  *  container list
186  * @bat_priv: the bat priv with all the mesh interface information
187  * @tvlv: the to be removed tvlv container
188  *
189  * Has to be called with the appropriate locks being acquired
190  * (tvlv.container_list_lock).
191  */
192 static void batadv_tvlv_container_remove(struct batadv_priv *bat_priv,
193 					 struct batadv_tvlv_container *tvlv)
194 {
195 	lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
196 
197 	if (!tvlv)
198 		return;
199 
200 	hlist_del(&tvlv->list);
201 
202 	/* first call to decrement the counter, second call to free */
203 	batadv_tvlv_container_put(tvlv);
204 	batadv_tvlv_container_put(tvlv);
205 }
206 
207 /**
208  * batadv_tvlv_container_unregister() - unregister tvlv container based on the
209  *  provided type and version (both need to match)
210  * @bat_priv: the bat priv with all the mesh interface information
211  * @type: tvlv container type to unregister
212  * @version: tvlv container type to unregister
213  */
214 void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv,
215 				      u8 type, u8 version)
216 {
217 	struct batadv_tvlv_container *tvlv;
218 
219 	spin_lock_bh(&bat_priv->tvlv.container_list_lock);
220 	tvlv = batadv_tvlv_container_get(bat_priv, type, version);
221 	batadv_tvlv_container_remove(bat_priv, tvlv);
222 	spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
223 }
224 
225 /**
226  * batadv_tvlv_container_register() - register tvlv type, version and content
227  *  to be propagated with each (primary interface) OGM
228  * @bat_priv: the bat priv with all the mesh interface information
229  * @type: tvlv container type
230  * @version: tvlv container version
231  * @tvlv_value: tvlv container content
232  * @tvlv_value_len: tvlv container content length
233  *
234  * If a container of the same type and version was already registered the new
235  * content is going to replace the old one.
236  */
237 void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
238 				    u8 type, u8 version,
239 				    void *tvlv_value, u16 tvlv_value_len)
240 {
241 	struct batadv_tvlv_container *tvlv_old;
242 	struct batadv_tvlv_container *tvlv_new;
243 
244 	if (!tvlv_value)
245 		tvlv_value_len = 0;
246 
247 	tvlv_new = kzalloc(sizeof(*tvlv_new) + tvlv_value_len, GFP_ATOMIC);
248 	if (!tvlv_new)
249 		return;
250 
251 	tvlv_new->tvlv_hdr.version = version;
252 	tvlv_new->tvlv_hdr.type = type;
253 	tvlv_new->tvlv_hdr.len = htons(tvlv_value_len);
254 
255 	memcpy(tvlv_new + 1, tvlv_value, ntohs(tvlv_new->tvlv_hdr.len));
256 	INIT_HLIST_NODE(&tvlv_new->list);
257 	kref_init(&tvlv_new->refcount);
258 
259 	spin_lock_bh(&bat_priv->tvlv.container_list_lock);
260 	tvlv_old = batadv_tvlv_container_get(bat_priv, type, version);
261 	batadv_tvlv_container_remove(bat_priv, tvlv_old);
262 
263 	kref_get(&tvlv_new->refcount);
264 	hlist_add_head(&tvlv_new->list, &bat_priv->tvlv.container_list);
265 	spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
266 
267 	/* don't return reference to new tvlv_container */
268 	batadv_tvlv_container_put(tvlv_new);
269 }
270 
271 /**
272  * batadv_tvlv_realloc_packet_buff() - reallocate packet buffer to accommodate
273  *  requested packet size
274  * @ogm_buff: ogm packet buffer
275  * @additional_packet_len: requested additional packet size on top of minimum
276  *  size
277  *
278  * Return: true if the packet buffer could be changed to the requested size,
279  * false otherwise.
280  */
281 static bool batadv_tvlv_realloc_packet_buff(struct batadv_ogm_buf *ogm_buff,
282 					    size_t additional_packet_len)
283 {
284 	unsigned char *new_buff;
285 	size_t newcapacity;
286 	size_t newlen;
287 
288 	newlen = ogm_buff->header_length + additional_packet_len;
289 	newcapacity = roundup_pow_of_two(newlen);
290 
291 	/* nothing to reallocate */
292 	if (newcapacity == ogm_buff->capacity) {
293 		ogm_buff->len = newlen;
294 		return true;
295 	}
296 
297 	new_buff = kmalloc(newcapacity, GFP_ATOMIC);
298 
299 	/* keep old buffer if kmalloc should fail */
300 	if (!new_buff) {
301 		/* continue to use oversize buffer if new data fits */
302 		if (newlen <= ogm_buff->capacity) {
303 			ogm_buff->len = newlen;
304 			return true;
305 		}
306 
307 		return false;
308 	}
309 
310 	memcpy(new_buff, ogm_buff->buf, ogm_buff->header_length);
311 	kfree(ogm_buff->buf);
312 
313 	ogm_buff->buf = new_buff;
314 	ogm_buff->len = newlen;
315 	ogm_buff->capacity = newcapacity;
316 
317 	return true;
318 }
319 
320 /**
321  * batadv_tvlv_container_ogm_append() - append tvlv container content to given
322  *  OGM packet buffer
323  * @bat_priv: the bat priv with all the mesh interface information
324  * @ogm_buff: ogm packet buffer
325  *
326  * The ogm packet might be enlarged or shrunk depending on the current size
327  * and the size of the to-be-appended tvlv containers.
328  *
329  * Return: size of all appended tvlv containers in bytes (max U16_MAX), negative
330  *  if operation failed
331  */
332 int batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
333 				     struct batadv_ogm_buf *ogm_buff)
334 {
335 	struct batadv_tvlv_container *tvlv;
336 	struct batadv_tvlv_hdr *tvlv_hdr;
337 	size_t tvlv_value_len;
338 	void *tvlv_value;
339 	int tvlv_len_ret;
340 	bool ret;
341 
342 	spin_lock_bh(&bat_priv->tvlv.container_list_lock);
343 	tvlv_value_len = batadv_tvlv_container_list_size(bat_priv);
344 	if (tvlv_value_len > U16_MAX) {
345 		tvlv_len_ret = -E2BIG;
346 		goto end;
347 	}
348 
349 	ret = batadv_tvlv_realloc_packet_buff(ogm_buff, tvlv_value_len);
350 	if (!ret) {
351 		tvlv_len_ret = -ENOMEM;
352 		goto end;
353 	}
354 
355 	tvlv_len_ret = tvlv_value_len;
356 
357 	if (!tvlv_value_len)
358 		goto end;
359 
360 	tvlv_value = (u8 *)ogm_buff->buf + ogm_buff->header_length;
361 
362 	hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
363 		tvlv_hdr = tvlv_value;
364 		tvlv_hdr->type = tvlv->tvlv_hdr.type;
365 		tvlv_hdr->version = tvlv->tvlv_hdr.version;
366 		tvlv_hdr->len = tvlv->tvlv_hdr.len;
367 		tvlv_value = tvlv_hdr + 1;
368 		memcpy(tvlv_value, tvlv + 1, ntohs(tvlv->tvlv_hdr.len));
369 		tvlv_value = (u8 *)tvlv_value + ntohs(tvlv->tvlv_hdr.len);
370 	}
371 
372 end:
373 	spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
374 
375 	return tvlv_len_ret;
376 }
377 
378 /**
379  * batadv_tvlv_call_handler() - parse the given tvlv buffer to call the
380  *  appropriate handlers
381  * @bat_priv: the bat priv with all the mesh interface information
382  * @tvlv_handler: tvlv callback function handling the tvlv content
383  * @packet_type: indicates for which packet type the TVLV handler is called
384  * @orig_node: orig node emitting the ogm packet
385  * @skb: the skb the TVLV handler is called for
386  * @tvlv_value: tvlv content
387  * @tvlv_value_len: tvlv content length
388  *
389  * Return: NET_RX_SUCCESS if the handler was not found or the return value of
390  * the handler callback. The latter is NET_RX_SUCCESS or NET_RX_DROP for the
391  * unicast handler and additionally a negative errno code for the mcast handler.
392  */
393 static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,
394 				    struct batadv_tvlv_handler *tvlv_handler,
395 				    u8 packet_type,
396 				    struct batadv_orig_node *orig_node,
397 				    struct sk_buff *skb, void *tvlv_value,
398 				    u16 tvlv_value_len)
399 {
400 	unsigned int tvlv_offset;
401 	u8 *src;
402 	u8 *dst;
403 
404 	if (!tvlv_handler)
405 		return NET_RX_SUCCESS;
406 
407 	switch (packet_type) {
408 	case BATADV_IV_OGM:
409 	case BATADV_OGM2:
410 		if (!tvlv_handler->ogm_handler)
411 			return NET_RX_SUCCESS;
412 
413 		if (!orig_node)
414 			return NET_RX_SUCCESS;
415 
416 		tvlv_handler->ogm_handler(bat_priv, orig_node,
417 					  BATADV_NO_FLAGS,
418 					  tvlv_value, tvlv_value_len);
419 		break;
420 	case BATADV_UNICAST_TVLV:
421 		if (!skb)
422 			return NET_RX_SUCCESS;
423 
424 		if (!tvlv_handler->unicast_handler)
425 			return NET_RX_SUCCESS;
426 
427 		src = ((struct batadv_unicast_tvlv_packet *)skb->data)->src;
428 		dst = ((struct batadv_unicast_tvlv_packet *)skb->data)->dst;
429 
430 		return tvlv_handler->unicast_handler(bat_priv, src,
431 						     dst, tvlv_value,
432 						     tvlv_value_len);
433 	case BATADV_MCAST:
434 		if (!skb)
435 			return NET_RX_SUCCESS;
436 
437 		if (!tvlv_handler->mcast_handler)
438 			return NET_RX_SUCCESS;
439 
440 		tvlv_offset = (unsigned char *)tvlv_value - skb->data;
441 		if (!skb_set_transport_header_careful(skb,
442 						      tvlv_offset + tvlv_value_len))
443 			return -EINVAL;
444 
445 		skb_set_network_header(skb, tvlv_offset);
446 
447 		return tvlv_handler->mcast_handler(bat_priv, skb);
448 	}
449 
450 	return NET_RX_SUCCESS;
451 }
452 
453 /**
454  * batadv_tvlv_hdr_next() - move a tvlv buffer cursor to the next container
455  * @tvlv_value: cursor into the tvlv buffer, advanced past the returned
456  *  container's content on success
457  * @tvlv_value_len: remaining length of the tvlv buffer, reduced by the returned
458  *  container's size on success
459  *
460  * Parses a single container header at the current cursor position and, if a
461  * complete container is available, advances the cursor and remaining length
462  * past it. The returned header stays valid; its content is located at
463  * (returned header + 1) and is ntohs(hdr->len) bytes long.
464  *
465  * Return: pointer to the next tvlv container header, or NULL if no further
466  * complete container is present in the buffer.
467  */
468 static struct batadv_tvlv_hdr *batadv_tvlv_hdr_next(void **tvlv_value, u16 *tvlv_value_len)
469 {
470 	struct batadv_tvlv_hdr *tvlv_hdr;
471 	u16 tvlv_value_cont_len;
472 	void *tvlv_value_cont;
473 	u16 tvlv_len;
474 
475 	tvlv_value_cont = *tvlv_value;
476 	tvlv_len = *tvlv_value_len;
477 
478 	if (tvlv_len < sizeof(*tvlv_hdr))
479 		return NULL;
480 
481 	tvlv_hdr = tvlv_value_cont;
482 	tvlv_value_cont_len = ntohs(tvlv_hdr->len);
483 	tvlv_value_cont = tvlv_hdr + 1;
484 	tvlv_len -= sizeof(*tvlv_hdr);
485 
486 	if (tvlv_value_cont_len > tvlv_len)
487 		return NULL;
488 
489 	/* the next tvlv header is accessed assuming (at least) 2-byte
490 	 * alignment, so it must start at an even offset.
491 	 */
492 	if (tvlv_value_cont_len & 1)
493 		return NULL;
494 
495 	*tvlv_value = (u8 *)tvlv_value_cont + tvlv_value_cont_len;
496 	*tvlv_value_len = tvlv_len - tvlv_value_cont_len;
497 
498 	return tvlv_hdr;
499 }
500 
501 /**
502  * batadv_tvlv_containers_contain() - check if a tvlv buffer holds a container
503  * @tvlv_value: tvlv content
504  * @tvlv_value_len: tvlv content length
505  * @type: tvlv container type to look for
506  * @version: tvlv container version to look for
507  *
508  * Return: true if a container of the given type and version is present in the
509  * tvlv buffer, false otherwise.
510  */
511 static bool batadv_tvlv_containers_contain(void *tvlv_value,
512 					   u16 tvlv_value_len, u8 type,
513 					   u8 version)
514 {
515 	struct batadv_tvlv_hdr *tvlv_hdr;
516 
517 	while ((tvlv_hdr = batadv_tvlv_hdr_next(&tvlv_value, &tvlv_value_len))) {
518 		if (tvlv_hdr->type == type && tvlv_hdr->version == version)
519 			return true;
520 	}
521 
522 	return false;
523 }
524 
525 /**
526  * batadv_tvlv_containers_process() - parse the given tvlv buffer to call the
527  *  appropriate handlers
528  * @bat_priv: the bat priv with all the mesh interface information
529  * @packet_type: indicates for which packet type the TVLV handler is called
530  * @orig_node: orig node emitting the ogm packet
531  * @skb: the skb the TVLV handler is called for
532  * @tvlv_value: tvlv content
533  * @tvlv_value_len: tvlv content length
534  *
535  * Return: NET_RX_SUCCESS when processing an OGM or the combined return value of
536  * all called handler callbacks. The latter is NET_RX_SUCCESS, NET_RX_DROP or,
537  * for BATADV_MCAST packets, a negative errno code.
538  */
539 int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
540 				   u8 packet_type,
541 				   struct batadv_orig_node *orig_node,
542 				   struct sk_buff *skb, void *tvlv_value,
543 				   u16 tvlv_value_len)
544 {
545 	u8 cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND;
546 	u16 tvlv_value_start_len = tvlv_value_len;
547 	struct batadv_tvlv_handler *tvlv_handler;
548 	void *tvlv_value_start = tvlv_value;
549 	struct batadv_tvlv_hdr *tvlv_hdr;
550 	int ret = NET_RX_SUCCESS;
551 	u16 tvlv_value_cont_len;
552 	int res;
553 
554 	while ((tvlv_hdr = batadv_tvlv_hdr_next(&tvlv_value, &tvlv_value_len))) {
555 		tvlv_value_cont_len = ntohs(tvlv_hdr->len);
556 
557 		tvlv_handler = batadv_tvlv_handler_get(bat_priv,
558 						       tvlv_hdr->type,
559 						       tvlv_hdr->version);
560 
561 		res = batadv_tvlv_call_handler(bat_priv, tvlv_handler,
562 					       packet_type, orig_node, skb,
563 					       tvlv_hdr + 1,
564 					       tvlv_value_cont_len);
565 		if (ret == NET_RX_SUCCESS || res < 0)
566 			ret = res;
567 
568 		batadv_tvlv_handler_put(tvlv_handler);
569 	}
570 
571 	if (packet_type != BATADV_IV_OGM &&
572 	    packet_type != BATADV_OGM2)
573 		return ret;
574 
575 	rcu_read_lock();
576 	hlist_for_each_entry_rcu(tvlv_handler,
577 				 &bat_priv->tvlv.handler_list, list) {
578 		if (!tvlv_handler->ogm_handler)
579 			continue;
580 
581 		if (!(tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND))
582 			continue;
583 
584 		/* if the corresponding container was present then the handler
585 		 * was already called from the loop above
586 		 */
587 		if (batadv_tvlv_containers_contain(tvlv_value_start,
588 						   tvlv_value_start_len,
589 						   tvlv_handler->type,
590 						   tvlv_handler->version))
591 			continue;
592 
593 		tvlv_handler->ogm_handler(bat_priv, orig_node,
594 					  cifnotfound, NULL, 0);
595 	}
596 	rcu_read_unlock();
597 
598 	return NET_RX_SUCCESS;
599 }
600 
601 /**
602  * batadv_tvlv_ogm_receive() - process an incoming ogm and call the appropriate
603  *  handlers
604  * @bat_priv: the bat priv with all the mesh interface information
605  * @batadv_ogm_packet: ogm packet containing the tvlv containers
606  * @orig_node: orig node emitting the ogm packet
607  */
608 void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
609 			     struct batadv_ogm_packet *batadv_ogm_packet,
610 			     struct batadv_orig_node *orig_node)
611 {
612 	u16 tvlv_value_len;
613 	void *tvlv_value;
614 
615 	if (!batadv_ogm_packet)
616 		return;
617 
618 	tvlv_value_len = ntohs(batadv_ogm_packet->tvlv_len);
619 	if (!tvlv_value_len)
620 		return;
621 
622 	tvlv_value = batadv_ogm_packet + 1;
623 
624 	batadv_tvlv_containers_process(bat_priv, BATADV_IV_OGM, orig_node, NULL,
625 				       tvlv_value, tvlv_value_len);
626 }
627 
628 /**
629  * batadv_tvlv_handler_register() - register tvlv handler based on the provided
630  *  type and version (both need to match) for ogm tvlv payload and/or unicast
631  *  payload
632  * @bat_priv: the bat priv with all the mesh interface information
633  * @optr: ogm tvlv handler callback function. This function receives the orig
634  *  node, flags and the tvlv content as argument to process.
635  * @uptr: unicast tvlv handler callback function. This function receives the
636  *  source & destination of the unicast packet as well as the tvlv content
637  *  to process.
638  * @mptr: multicast packet tvlv handler callback function. This function
639  *  receives the full skb to process, with the skb network header pointing
640  *  to the current tvlv and the skb transport header pointing to the first
641  *  byte after the current tvlv.
642  * @type: tvlv handler type to be registered
643  * @version: tvlv handler version to be registered
644  * @flags: flags to enable or disable TVLV API behavior
645  */
646 void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
647 				  void (*optr)(struct batadv_priv *bat_priv,
648 					       struct batadv_orig_node *orig,
649 					       u8 flags,
650 					       void *tvlv_value,
651 					       u16 tvlv_value_len),
652 				  int (*uptr)(struct batadv_priv *bat_priv,
653 					      u8 *src, u8 *dst,
654 					      void *tvlv_value,
655 					      u16 tvlv_value_len),
656 				  int (*mptr)(struct batadv_priv *bat_priv,
657 					      struct sk_buff *skb),
658 				  u8 type, u8 version, u8 flags)
659 {
660 	struct batadv_tvlv_handler *tvlv_handler;
661 
662 	spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
663 
664 	tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
665 	if (tvlv_handler) {
666 		spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
667 		batadv_tvlv_handler_put(tvlv_handler);
668 		return;
669 	}
670 
671 	tvlv_handler = kzalloc_obj(*tvlv_handler, GFP_ATOMIC);
672 	if (!tvlv_handler) {
673 		spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
674 		return;
675 	}
676 
677 	tvlv_handler->ogm_handler = optr;
678 	tvlv_handler->unicast_handler = uptr;
679 	tvlv_handler->mcast_handler = mptr;
680 	tvlv_handler->type = type;
681 	tvlv_handler->version = version;
682 	tvlv_handler->flags = flags;
683 	kref_init(&tvlv_handler->refcount);
684 	INIT_HLIST_NODE(&tvlv_handler->list);
685 
686 	kref_get(&tvlv_handler->refcount);
687 	hlist_add_head_rcu(&tvlv_handler->list, &bat_priv->tvlv.handler_list);
688 	spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
689 
690 	/* don't return reference to new tvlv_handler */
691 	batadv_tvlv_handler_put(tvlv_handler);
692 }
693 
694 /**
695  * batadv_tvlv_handler_unregister() - unregister tvlv handler based on the
696  *  provided type and version (both need to match)
697  * @bat_priv: the bat priv with all the mesh interface information
698  * @type: tvlv handler type to be unregistered
699  * @version: tvlv handler version to be unregistered
700  */
701 void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv,
702 				    u8 type, u8 version)
703 {
704 	struct batadv_tvlv_handler *tvlv_handler;
705 
706 	tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
707 	if (!tvlv_handler)
708 		return;
709 
710 	batadv_tvlv_handler_put(tvlv_handler);
711 	spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
712 	hlist_del_rcu(&tvlv_handler->list);
713 	spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
714 	batadv_tvlv_handler_put(tvlv_handler);
715 }
716 
717 /**
718  * batadv_tvlv_unicast_send() - send a unicast packet with tvlv payload to the
719  *  specified host
720  * @bat_priv: the bat priv with all the mesh interface information
721  * @src: source mac address of the unicast packet
722  * @dst: destination mac address of the unicast packet
723  * @type: tvlv type
724  * @version: tvlv version
725  * @tvlv_value: tvlv content
726  * @tvlv_value_len: tvlv content length
727  */
728 void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, const u8 *src,
729 			      const u8 *dst, u8 type, u8 version,
730 			      void *tvlv_value, u16 tvlv_value_len)
731 {
732 	struct batadv_unicast_tvlv_packet *unicast_tvlv_packet;
733 	ssize_t hdr_len = sizeof(*unicast_tvlv_packet);
734 	struct batadv_orig_node *orig_node;
735 	struct batadv_tvlv_hdr *tvlv_hdr;
736 	unsigned char *tvlv_buff;
737 	unsigned int tvlv_len;
738 	struct sk_buff *skb;
739 
740 	orig_node = batadv_orig_hash_find(bat_priv, dst);
741 	if (!orig_node)
742 		return;
743 
744 	tvlv_len = sizeof(*tvlv_hdr) + tvlv_value_len;
745 
746 	skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + hdr_len + tvlv_len);
747 	if (!skb)
748 		goto out;
749 
750 	skb->priority = TC_PRIO_CONTROL;
751 	skb_reserve(skb, ETH_HLEN);
752 	tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
753 	unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
754 	unicast_tvlv_packet->packet_type = BATADV_UNICAST_TVLV;
755 	unicast_tvlv_packet->version = BATADV_COMPAT_VERSION;
756 	unicast_tvlv_packet->ttl = BATADV_TTL;
757 	unicast_tvlv_packet->reserved = 0;
758 	unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
759 	unicast_tvlv_packet->align = 0;
760 	ether_addr_copy(unicast_tvlv_packet->src, src);
761 	ether_addr_copy(unicast_tvlv_packet->dst, dst);
762 
763 	tvlv_buff = (unsigned char *)(unicast_tvlv_packet + 1);
764 	tvlv_hdr = (struct batadv_tvlv_hdr *)tvlv_buff;
765 	tvlv_hdr->version = version;
766 	tvlv_hdr->type = type;
767 	tvlv_hdr->len = htons(tvlv_value_len);
768 	tvlv_buff += sizeof(*tvlv_hdr);
769 	memcpy(tvlv_buff, tvlv_value, tvlv_value_len);
770 
771 	batadv_send_skb_to_orig(skb, orig_node, NULL);
772 out:
773 	batadv_orig_node_put(orig_node);
774 }
775