tvlv.c 19 KB

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