root/net/batman-adv/tvlv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. batadv_tvlv_handler_release
  2. batadv_tvlv_handler_put
  3. batadv_tvlv_handler_get
  4. batadv_tvlv_container_release
  5. batadv_tvlv_container_put
  6. batadv_tvlv_container_get
  7. batadv_tvlv_container_list_size
  8. batadv_tvlv_container_remove
  9. batadv_tvlv_container_unregister
  10. batadv_tvlv_container_register
  11. batadv_tvlv_realloc_packet_buff
  12. batadv_tvlv_container_ogm_append
  13. batadv_tvlv_call_handler
  14. batadv_tvlv_containers_process
  15. batadv_tvlv_ogm_receive
  16. batadv_tvlv_handler_register
  17. batadv_tvlv_handler_unregister
  18. batadv_tvlv_unicast_send

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

/* [<][>][^][v][top][bottom][index][help] */