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 */
batadv_tvlv_handler_release(struct kref * ref)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 */
batadv_tvlv_handler_put(struct batadv_tvlv_handler * tvlv_handler)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 *
batadv_tvlv_handler_get(struct batadv_priv * bat_priv,u8 type,u8 version)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 */
batadv_tvlv_container_release(struct kref * ref)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 */
batadv_tvlv_container_put(struct batadv_tvlv_container * tvlv)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 *
batadv_tvlv_container_get(struct batadv_priv * bat_priv,u8 type,u8 version)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 */
batadv_tvlv_container_list_size(struct batadv_priv * bat_priv)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 */
batadv_tvlv_container_remove(struct batadv_priv * bat_priv,struct batadv_tvlv_container * tvlv)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 */
batadv_tvlv_container_unregister(struct batadv_priv * bat_priv,u8 type,u8 version)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 */
batadv_tvlv_container_register(struct batadv_priv * bat_priv,u8 type,u8 version,void * tvlv_value,u16 tvlv_value_len)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 */
batadv_tvlv_realloc_packet_buff(struct batadv_ogm_buf * ogm_buff,size_t additional_packet_len)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 */
batadv_tvlv_container_ogm_append(struct batadv_priv * bat_priv,struct batadv_ogm_buf * ogm_buff)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 */
batadv_tvlv_call_handler(struct batadv_priv * bat_priv,struct batadv_tvlv_handler * tvlv_handler,u8 packet_type,struct batadv_orig_node * orig_node,struct sk_buff * skb,void * tvlv_value,u16 tvlv_value_len)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 */
batadv_tvlv_hdr_next(void ** tvlv_value,u16 * tvlv_value_len)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 */
batadv_tvlv_containers_contain(void * tvlv_value,u16 tvlv_value_len,u8 type,u8 version)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 */
batadv_tvlv_containers_process(struct batadv_priv * bat_priv,u8 packet_type,struct batadv_orig_node * orig_node,struct sk_buff * skb,void * tvlv_value,u16 tvlv_value_len)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 */
batadv_tvlv_ogm_receive(struct batadv_priv * bat_priv,struct batadv_ogm_packet * batadv_ogm_packet,struct batadv_orig_node * orig_node)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 */
batadv_tvlv_handler_register(struct batadv_priv * bat_priv,void (* optr)(struct batadv_priv * bat_priv,struct batadv_orig_node * orig,u8 flags,void * tvlv_value,u16 tvlv_value_len),int (* uptr)(struct batadv_priv * bat_priv,u8 * src,u8 * dst,void * tvlv_value,u16 tvlv_value_len),int (* mptr)(struct batadv_priv * bat_priv,struct sk_buff * skb),u8 type,u8 version,u8 flags)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 */
batadv_tvlv_handler_unregister(struct batadv_priv * bat_priv,u8 type,u8 version)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 */
batadv_tvlv_unicast_send(struct batadv_priv * bat_priv,const u8 * src,const u8 * dst,u8 type,u8 version,void * tvlv_value,u16 tvlv_value_len)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