gateway_client.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (C) B.A.T.M.A.N. contributors:
  3. *
  4. * Marek Lindner
  5. */
  6. #include "gateway_client.h"
  7. #include "main.h"
  8. #include <linux/atomic.h>
  9. #include <linux/byteorder/generic.h>
  10. #include <linux/container_of.h>
  11. #include <linux/errno.h>
  12. #include <linux/etherdevice.h>
  13. #include <linux/gfp.h>
  14. #include <linux/if_ether.h>
  15. #include <linux/if_vlan.h>
  16. #include <linux/in.h>
  17. #include <linux/ip.h>
  18. #include <linux/ipv6.h>
  19. #include <linux/kref.h>
  20. #include <linux/list.h>
  21. #include <linux/lockdep.h>
  22. #include <linux/netdevice.h>
  23. #include <linux/netlink.h>
  24. #include <linux/rculist.h>
  25. #include <linux/rcupdate.h>
  26. #include <linux/skbuff.h>
  27. #include <linux/slab.h>
  28. #include <linux/spinlock.h>
  29. #include <linux/sprintf.h>
  30. #include <linux/stddef.h>
  31. #include <linux/udp.h>
  32. #include <net/sock.h>
  33. #include <uapi/linux/batadv_packet.h>
  34. #include <uapi/linux/batman_adv.h>
  35. #include "hard-interface.h"
  36. #include "log.h"
  37. #include "netlink.h"
  38. #include "originator.h"
  39. #include "routing.h"
  40. #include "soft-interface.h"
  41. #include "translation-table.h"
  42. /* These are the offsets of the "hw type" and "hw address length" in the dhcp
  43. * packet starting at the beginning of the dhcp header
  44. */
  45. #define BATADV_DHCP_HTYPE_OFFSET 1
  46. #define BATADV_DHCP_HLEN_OFFSET 2
  47. /* Value of htype representing Ethernet */
  48. #define BATADV_DHCP_HTYPE_ETHERNET 0x01
  49. /* This is the offset of the "chaddr" field in the dhcp packet starting at the
  50. * beginning of the dhcp header
  51. */
  52. #define BATADV_DHCP_CHADDR_OFFSET 28
  53. /**
  54. * batadv_gw_node_release() - release gw_node from lists and queue for free
  55. * after rcu grace period
  56. * @ref: kref pointer of the gw_node
  57. */
  58. void batadv_gw_node_release(struct kref *ref)
  59. {
  60. struct batadv_gw_node *gw_node;
  61. gw_node = container_of(ref, struct batadv_gw_node, refcount);
  62. batadv_orig_node_put(gw_node->orig_node);
  63. kfree_rcu(gw_node, rcu);
  64. }
  65. /**
  66. * batadv_gw_get_selected_gw_node() - Get currently selected gateway
  67. * @bat_priv: the bat priv with all the soft interface information
  68. *
  69. * Return: selected gateway (with increased refcnt), NULL on errors
  70. */
  71. struct batadv_gw_node *
  72. batadv_gw_get_selected_gw_node(struct batadv_priv *bat_priv)
  73. {
  74. struct batadv_gw_node *gw_node;
  75. rcu_read_lock();
  76. gw_node = rcu_dereference(bat_priv->gw.curr_gw);
  77. if (!gw_node)
  78. goto out;
  79. if (!kref_get_unless_zero(&gw_node->refcount))
  80. gw_node = NULL;
  81. out:
  82. rcu_read_unlock();
  83. return gw_node;
  84. }
  85. /**
  86. * batadv_gw_get_selected_orig() - Get originator of currently selected gateway
  87. * @bat_priv: the bat priv with all the soft interface information
  88. *
  89. * Return: orig_node of selected gateway (with increased refcnt), NULL on errors
  90. */
  91. struct batadv_orig_node *
  92. batadv_gw_get_selected_orig(struct batadv_priv *bat_priv)
  93. {
  94. struct batadv_gw_node *gw_node;
  95. struct batadv_orig_node *orig_node = NULL;
  96. gw_node = batadv_gw_get_selected_gw_node(bat_priv);
  97. if (!gw_node)
  98. goto out;
  99. rcu_read_lock();
  100. orig_node = gw_node->orig_node;
  101. if (!orig_node)
  102. goto unlock;
  103. if (!kref_get_unless_zero(&orig_node->refcount))
  104. orig_node = NULL;
  105. unlock:
  106. rcu_read_unlock();
  107. out:
  108. batadv_gw_node_put(gw_node);
  109. return orig_node;
  110. }
  111. static void batadv_gw_select(struct batadv_priv *bat_priv,
  112. struct batadv_gw_node *new_gw_node)
  113. {
  114. struct batadv_gw_node *curr_gw_node;
  115. spin_lock_bh(&bat_priv->gw.list_lock);
  116. if (new_gw_node)
  117. kref_get(&new_gw_node->refcount);
  118. curr_gw_node = rcu_replace_pointer(bat_priv->gw.curr_gw, new_gw_node,
  119. true);
  120. batadv_gw_node_put(curr_gw_node);
  121. spin_unlock_bh(&bat_priv->gw.list_lock);
  122. }
  123. /**
  124. * batadv_gw_reselect() - force a gateway reselection
  125. * @bat_priv: the bat priv with all the soft interface information
  126. *
  127. * Set a flag to remind the GW component to perform a new gateway reselection.
  128. * However this function does not ensure that the current gateway is going to be
  129. * deselected. The reselection mechanism may elect the same gateway once again.
  130. *
  131. * This means that invoking batadv_gw_reselect() does not guarantee a gateway
  132. * change and therefore a uevent is not necessarily expected.
  133. */
  134. void batadv_gw_reselect(struct batadv_priv *bat_priv)
  135. {
  136. atomic_set(&bat_priv->gw.reselect, 1);
  137. }
  138. /**
  139. * batadv_gw_check_client_stop() - check if client mode has been switched off
  140. * @bat_priv: the bat priv with all the soft interface information
  141. *
  142. * This function assumes the caller has checked that the gw state *is actually
  143. * changing*. This function is not supposed to be called when there is no state
  144. * change.
  145. */
  146. void batadv_gw_check_client_stop(struct batadv_priv *bat_priv)
  147. {
  148. struct batadv_gw_node *curr_gw;
  149. if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT)
  150. return;
  151. curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
  152. if (!curr_gw)
  153. return;
  154. /* deselect the current gateway so that next time that client mode is
  155. * enabled a proper GW_ADD event can be sent
  156. */
  157. batadv_gw_select(bat_priv, NULL);
  158. /* if batman-adv is switching the gw client mode off and a gateway was
  159. * already selected, send a DEL uevent
  160. */
  161. batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_DEL, NULL);
  162. batadv_gw_node_put(curr_gw);
  163. }
  164. /**
  165. * batadv_gw_election() - Elect the best gateway
  166. * @bat_priv: the bat priv with all the soft interface information
  167. */
  168. void batadv_gw_election(struct batadv_priv *bat_priv)
  169. {
  170. struct batadv_gw_node *curr_gw = NULL;
  171. struct batadv_gw_node *next_gw = NULL;
  172. struct batadv_neigh_node *router = NULL;
  173. struct batadv_neigh_ifinfo *router_ifinfo = NULL;
  174. char gw_addr[18] = { '\0' };
  175. if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT)
  176. goto out;
  177. if (!bat_priv->algo_ops->gw.get_best_gw_node)
  178. goto out;
  179. curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
  180. if (!batadv_atomic_dec_not_zero(&bat_priv->gw.reselect) && curr_gw)
  181. goto out;
  182. /* if gw.reselect is set to 1 it means that a previous call to
  183. * gw.is_eligible() said that we have a new best GW, therefore it can
  184. * now be picked from the list and selected
  185. */
  186. next_gw = bat_priv->algo_ops->gw.get_best_gw_node(bat_priv);
  187. if (curr_gw == next_gw)
  188. goto out;
  189. if (next_gw) {
  190. sprintf(gw_addr, "%pM", next_gw->orig_node->orig);
  191. router = batadv_orig_router_get(next_gw->orig_node,
  192. BATADV_IF_DEFAULT);
  193. if (!router) {
  194. batadv_gw_reselect(bat_priv);
  195. goto out;
  196. }
  197. router_ifinfo = batadv_neigh_ifinfo_get(router,
  198. BATADV_IF_DEFAULT);
  199. if (!router_ifinfo) {
  200. batadv_gw_reselect(bat_priv);
  201. goto out;
  202. }
  203. }
  204. if (curr_gw && !next_gw) {
  205. batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
  206. "Removing selected gateway - no gateway in range\n");
  207. batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_DEL,
  208. NULL);
  209. } else if (!curr_gw && next_gw) {
  210. batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
  211. "Adding route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n",
  212. next_gw->orig_node->orig,
  213. next_gw->bandwidth_down / 10,
  214. next_gw->bandwidth_down % 10,
  215. next_gw->bandwidth_up / 10,
  216. next_gw->bandwidth_up % 10,
  217. router_ifinfo->bat_iv.tq_avg);
  218. batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD,
  219. gw_addr);
  220. } else {
  221. batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
  222. "Changing route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n",
  223. next_gw->orig_node->orig,
  224. next_gw->bandwidth_down / 10,
  225. next_gw->bandwidth_down % 10,
  226. next_gw->bandwidth_up / 10,
  227. next_gw->bandwidth_up % 10,
  228. router_ifinfo->bat_iv.tq_avg);
  229. batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE,
  230. gw_addr);
  231. }
  232. batadv_gw_select(bat_priv, next_gw);
  233. out:
  234. batadv_gw_node_put(curr_gw);
  235. batadv_gw_node_put(next_gw);
  236. batadv_neigh_node_put(router);
  237. batadv_neigh_ifinfo_put(router_ifinfo);
  238. }
  239. /**
  240. * batadv_gw_check_election() - Elect orig node as best gateway when eligible
  241. * @bat_priv: the bat priv with all the soft interface information
  242. * @orig_node: orig node which is to be checked
  243. */
  244. void batadv_gw_check_election(struct batadv_priv *bat_priv,
  245. struct batadv_orig_node *orig_node)
  246. {
  247. struct batadv_orig_node *curr_gw_orig;
  248. /* abort immediately if the routing algorithm does not support gateway
  249. * election
  250. */
  251. if (!bat_priv->algo_ops->gw.is_eligible)
  252. return;
  253. curr_gw_orig = batadv_gw_get_selected_orig(bat_priv);
  254. if (!curr_gw_orig)
  255. goto reselect;
  256. /* this node already is the gateway */
  257. if (curr_gw_orig == orig_node)
  258. goto out;
  259. if (!bat_priv->algo_ops->gw.is_eligible(bat_priv, curr_gw_orig,
  260. orig_node))
  261. goto out;
  262. reselect:
  263. batadv_gw_reselect(bat_priv);
  264. out:
  265. batadv_orig_node_put(curr_gw_orig);
  266. }
  267. /**
  268. * batadv_gw_node_add() - add gateway node to list of available gateways
  269. * @bat_priv: the bat priv with all the soft interface information
  270. * @orig_node: originator announcing gateway capabilities
  271. * @gateway: announced bandwidth information
  272. *
  273. * Has to be called with the appropriate locks being acquired
  274. * (gw.list_lock).
  275. */
  276. static void batadv_gw_node_add(struct batadv_priv *bat_priv,
  277. struct batadv_orig_node *orig_node,
  278. struct batadv_tvlv_gateway_data *gateway)
  279. {
  280. struct batadv_gw_node *gw_node;
  281. lockdep_assert_held(&bat_priv->gw.list_lock);
  282. if (gateway->bandwidth_down == 0)
  283. return;
  284. gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC);
  285. if (!gw_node)
  286. return;
  287. kref_init(&gw_node->refcount);
  288. INIT_HLIST_NODE(&gw_node->list);
  289. kref_get(&orig_node->refcount);
  290. gw_node->orig_node = orig_node;
  291. gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
  292. gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
  293. kref_get(&gw_node->refcount);
  294. hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.gateway_list);
  295. bat_priv->gw.generation++;
  296. batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
  297. "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n",
  298. orig_node->orig,
  299. ntohl(gateway->bandwidth_down) / 10,
  300. ntohl(gateway->bandwidth_down) % 10,
  301. ntohl(gateway->bandwidth_up) / 10,
  302. ntohl(gateway->bandwidth_up) % 10);
  303. /* don't return reference to new gw_node */
  304. batadv_gw_node_put(gw_node);
  305. }
  306. /**
  307. * batadv_gw_node_get() - retrieve gateway node from list of available gateways
  308. * @bat_priv: the bat priv with all the soft interface information
  309. * @orig_node: originator announcing gateway capabilities
  310. *
  311. * Return: gateway node if found or NULL otherwise.
  312. */
  313. struct batadv_gw_node *batadv_gw_node_get(struct batadv_priv *bat_priv,
  314. struct batadv_orig_node *orig_node)
  315. {
  316. struct batadv_gw_node *gw_node_tmp, *gw_node = NULL;
  317. rcu_read_lock();
  318. hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.gateway_list,
  319. list) {
  320. if (gw_node_tmp->orig_node != orig_node)
  321. continue;
  322. if (!kref_get_unless_zero(&gw_node_tmp->refcount))
  323. continue;
  324. gw_node = gw_node_tmp;
  325. break;
  326. }
  327. rcu_read_unlock();
  328. return gw_node;
  329. }
  330. /**
  331. * batadv_gw_node_update() - update list of available gateways with changed
  332. * bandwidth information
  333. * @bat_priv: the bat priv with all the soft interface information
  334. * @orig_node: originator announcing gateway capabilities
  335. * @gateway: announced bandwidth information
  336. */
  337. void batadv_gw_node_update(struct batadv_priv *bat_priv,
  338. struct batadv_orig_node *orig_node,
  339. struct batadv_tvlv_gateway_data *gateway)
  340. {
  341. struct batadv_gw_node *gw_node, *curr_gw = NULL;
  342. spin_lock_bh(&bat_priv->gw.list_lock);
  343. gw_node = batadv_gw_node_get(bat_priv, orig_node);
  344. if (!gw_node) {
  345. batadv_gw_node_add(bat_priv, orig_node, gateway);
  346. spin_unlock_bh(&bat_priv->gw.list_lock);
  347. goto out;
  348. }
  349. spin_unlock_bh(&bat_priv->gw.list_lock);
  350. if (gw_node->bandwidth_down == ntohl(gateway->bandwidth_down) &&
  351. gw_node->bandwidth_up == ntohl(gateway->bandwidth_up))
  352. goto out;
  353. batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
  354. "Gateway bandwidth of originator %pM changed from %u.%u/%u.%u MBit to %u.%u/%u.%u MBit\n",
  355. orig_node->orig,
  356. gw_node->bandwidth_down / 10,
  357. gw_node->bandwidth_down % 10,
  358. gw_node->bandwidth_up / 10,
  359. gw_node->bandwidth_up % 10,
  360. ntohl(gateway->bandwidth_down) / 10,
  361. ntohl(gateway->bandwidth_down) % 10,
  362. ntohl(gateway->bandwidth_up) / 10,
  363. ntohl(gateway->bandwidth_up) % 10);
  364. gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
  365. gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
  366. if (ntohl(gateway->bandwidth_down) == 0) {
  367. batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
  368. "Gateway %pM removed from gateway list\n",
  369. orig_node->orig);
  370. /* Note: We don't need a NULL check here, since curr_gw never
  371. * gets dereferenced.
  372. */
  373. spin_lock_bh(&bat_priv->gw.list_lock);
  374. if (!hlist_unhashed(&gw_node->list)) {
  375. hlist_del_init_rcu(&gw_node->list);
  376. batadv_gw_node_put(gw_node);
  377. bat_priv->gw.generation++;
  378. }
  379. spin_unlock_bh(&bat_priv->gw.list_lock);
  380. curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
  381. if (gw_node == curr_gw)
  382. batadv_gw_reselect(bat_priv);
  383. batadv_gw_node_put(curr_gw);
  384. }
  385. out:
  386. batadv_gw_node_put(gw_node);
  387. }
  388. /**
  389. * batadv_gw_node_delete() - Remove orig_node from gateway list
  390. * @bat_priv: the bat priv with all the soft interface information
  391. * @orig_node: orig node which is currently in process of being removed
  392. */
  393. void batadv_gw_node_delete(struct batadv_priv *bat_priv,
  394. struct batadv_orig_node *orig_node)
  395. {
  396. struct batadv_tvlv_gateway_data gateway;
  397. gateway.bandwidth_down = 0;
  398. gateway.bandwidth_up = 0;
  399. batadv_gw_node_update(bat_priv, orig_node, &gateway);
  400. }
  401. /**
  402. * batadv_gw_node_free() - Free gateway information from soft interface
  403. * @bat_priv: the bat priv with all the soft interface information
  404. */
  405. void batadv_gw_node_free(struct batadv_priv *bat_priv)
  406. {
  407. struct batadv_gw_node *gw_node;
  408. struct hlist_node *node_tmp;
  409. spin_lock_bh(&bat_priv->gw.list_lock);
  410. hlist_for_each_entry_safe(gw_node, node_tmp,
  411. &bat_priv->gw.gateway_list, list) {
  412. hlist_del_init_rcu(&gw_node->list);
  413. batadv_gw_node_put(gw_node);
  414. bat_priv->gw.generation++;
  415. }
  416. spin_unlock_bh(&bat_priv->gw.list_lock);
  417. }
  418. /**
  419. * batadv_gw_dump() - Dump gateways into a message
  420. * @msg: Netlink message to dump into
  421. * @cb: Control block containing additional options
  422. *
  423. * Return: Error code, or length of message
  424. */
  425. int batadv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb)
  426. {
  427. struct batadv_hard_iface *primary_if = NULL;
  428. struct net *net = sock_net(cb->skb->sk);
  429. struct net_device *soft_iface;
  430. struct batadv_priv *bat_priv;
  431. int ifindex;
  432. int ret;
  433. ifindex = batadv_netlink_get_ifindex(cb->nlh,
  434. BATADV_ATTR_MESH_IFINDEX);
  435. if (!ifindex)
  436. return -EINVAL;
  437. soft_iface = dev_get_by_index(net, ifindex);
  438. if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
  439. ret = -ENODEV;
  440. goto out;
  441. }
  442. bat_priv = netdev_priv(soft_iface);
  443. primary_if = batadv_primary_if_get_selected(bat_priv);
  444. if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
  445. ret = -ENOENT;
  446. goto out;
  447. }
  448. if (!bat_priv->algo_ops->gw.dump) {
  449. ret = -EOPNOTSUPP;
  450. goto out;
  451. }
  452. bat_priv->algo_ops->gw.dump(msg, cb, bat_priv);
  453. ret = msg->len;
  454. out:
  455. batadv_hardif_put(primary_if);
  456. dev_put(soft_iface);
  457. return ret;
  458. }
  459. /**
  460. * batadv_gw_dhcp_recipient_get() - check if a packet is a DHCP message
  461. * @skb: the packet to check
  462. * @header_len: a pointer to the batman-adv header size
  463. * @chaddr: buffer where the client address will be stored. Valid
  464. * only if the function returns BATADV_DHCP_TO_CLIENT
  465. *
  466. * This function may re-allocate the data buffer of the skb passed as argument.
  467. *
  468. * Return:
  469. * - BATADV_DHCP_NO if the packet is not a dhcp message or if there was an error
  470. * while parsing it
  471. * - BATADV_DHCP_TO_SERVER if this is a message going to the DHCP server
  472. * - BATADV_DHCP_TO_CLIENT if this is a message going to a DHCP client
  473. */
  474. enum batadv_dhcp_recipient
  475. batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len,
  476. u8 *chaddr)
  477. {
  478. enum batadv_dhcp_recipient ret = BATADV_DHCP_NO;
  479. struct ethhdr *ethhdr;
  480. struct iphdr *iphdr;
  481. struct ipv6hdr *ipv6hdr;
  482. struct udphdr *udphdr;
  483. struct vlan_ethhdr *vhdr;
  484. int chaddr_offset;
  485. __be16 proto;
  486. u8 *p;
  487. /* check for ethernet header */
  488. if (!pskb_may_pull(skb, *header_len + ETH_HLEN))
  489. return BATADV_DHCP_NO;
  490. ethhdr = eth_hdr(skb);
  491. proto = ethhdr->h_proto;
  492. *header_len += ETH_HLEN;
  493. /* check for initial vlan header */
  494. if (proto == htons(ETH_P_8021Q)) {
  495. if (!pskb_may_pull(skb, *header_len + VLAN_HLEN))
  496. return BATADV_DHCP_NO;
  497. vhdr = vlan_eth_hdr(skb);
  498. proto = vhdr->h_vlan_encapsulated_proto;
  499. *header_len += VLAN_HLEN;
  500. }
  501. /* check for ip header */
  502. switch (proto) {
  503. case htons(ETH_P_IP):
  504. if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr)))
  505. return BATADV_DHCP_NO;
  506. iphdr = (struct iphdr *)(skb->data + *header_len);
  507. *header_len += iphdr->ihl * 4;
  508. /* check for udp header */
  509. if (iphdr->protocol != IPPROTO_UDP)
  510. return BATADV_DHCP_NO;
  511. break;
  512. case htons(ETH_P_IPV6):
  513. if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr)))
  514. return BATADV_DHCP_NO;
  515. ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len);
  516. *header_len += sizeof(*ipv6hdr);
  517. /* check for udp header */
  518. if (ipv6hdr->nexthdr != IPPROTO_UDP)
  519. return BATADV_DHCP_NO;
  520. break;
  521. default:
  522. return BATADV_DHCP_NO;
  523. }
  524. if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr)))
  525. return BATADV_DHCP_NO;
  526. udphdr = (struct udphdr *)(skb->data + *header_len);
  527. *header_len += sizeof(*udphdr);
  528. /* check for bootp port */
  529. switch (proto) {
  530. case htons(ETH_P_IP):
  531. if (udphdr->dest == htons(67))
  532. ret = BATADV_DHCP_TO_SERVER;
  533. else if (udphdr->source == htons(67))
  534. ret = BATADV_DHCP_TO_CLIENT;
  535. break;
  536. case htons(ETH_P_IPV6):
  537. if (udphdr->dest == htons(547))
  538. ret = BATADV_DHCP_TO_SERVER;
  539. else if (udphdr->source == htons(547))
  540. ret = BATADV_DHCP_TO_CLIENT;
  541. break;
  542. }
  543. chaddr_offset = *header_len + BATADV_DHCP_CHADDR_OFFSET;
  544. /* store the client address if the message is going to a client */
  545. if (ret == BATADV_DHCP_TO_CLIENT) {
  546. if (!pskb_may_pull(skb, chaddr_offset + ETH_ALEN))
  547. return BATADV_DHCP_NO;
  548. /* check if the DHCP packet carries an Ethernet DHCP */
  549. p = skb->data + *header_len + BATADV_DHCP_HTYPE_OFFSET;
  550. if (*p != BATADV_DHCP_HTYPE_ETHERNET)
  551. return BATADV_DHCP_NO;
  552. /* check if the DHCP packet carries a valid Ethernet address */
  553. p = skb->data + *header_len + BATADV_DHCP_HLEN_OFFSET;
  554. if (*p != ETH_ALEN)
  555. return BATADV_DHCP_NO;
  556. ether_addr_copy(chaddr, skb->data + chaddr_offset);
  557. }
  558. return ret;
  559. }
  560. /**
  561. * batadv_gw_out_of_range() - check if the dhcp request destination is the best
  562. * gateway
  563. * @bat_priv: the bat priv with all the soft interface information
  564. * @skb: the outgoing packet
  565. *
  566. * Check if the skb is a DHCP request and if it is sent to the current best GW
  567. * server. Due to topology changes it may be the case that the GW server
  568. * previously selected is not the best one anymore.
  569. *
  570. * This call might reallocate skb data.
  571. * Must be invoked only when the DHCP packet is going TO a DHCP SERVER.
  572. *
  573. * Return: true if the packet destination is unicast and it is not the best gw,
  574. * false otherwise.
  575. */
  576. bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
  577. struct sk_buff *skb)
  578. {
  579. struct batadv_neigh_node *neigh_curr = NULL;
  580. struct batadv_neigh_node *neigh_old = NULL;
  581. struct batadv_orig_node *orig_dst_node = NULL;
  582. struct batadv_gw_node *gw_node = NULL;
  583. struct batadv_gw_node *curr_gw = NULL;
  584. struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo;
  585. struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
  586. bool out_of_range = false;
  587. u8 curr_tq_avg;
  588. unsigned short vid;
  589. vid = batadv_get_vid(skb, 0);
  590. if (is_multicast_ether_addr(ethhdr->h_dest))
  591. goto out;
  592. orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
  593. ethhdr->h_dest, vid);
  594. if (!orig_dst_node)
  595. goto out;
  596. gw_node = batadv_gw_node_get(bat_priv, orig_dst_node);
  597. if (!gw_node)
  598. goto out;
  599. switch (atomic_read(&bat_priv->gw.mode)) {
  600. case BATADV_GW_MODE_SERVER:
  601. /* If we are a GW then we are our best GW. We can artificially
  602. * set the tq towards ourself as the maximum value
  603. */
  604. curr_tq_avg = BATADV_TQ_MAX_VALUE;
  605. break;
  606. case BATADV_GW_MODE_CLIENT:
  607. curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
  608. if (!curr_gw)
  609. goto out;
  610. /* packet is going to our gateway */
  611. if (curr_gw->orig_node == orig_dst_node)
  612. goto out;
  613. /* If the dhcp packet has been sent to a different gw,
  614. * we have to evaluate whether the old gw is still
  615. * reliable enough
  616. */
  617. neigh_curr = batadv_find_router(bat_priv, curr_gw->orig_node,
  618. NULL);
  619. if (!neigh_curr)
  620. goto out;
  621. curr_ifinfo = batadv_neigh_ifinfo_get(neigh_curr,
  622. BATADV_IF_DEFAULT);
  623. if (!curr_ifinfo)
  624. goto out;
  625. curr_tq_avg = curr_ifinfo->bat_iv.tq_avg;
  626. batadv_neigh_ifinfo_put(curr_ifinfo);
  627. break;
  628. case BATADV_GW_MODE_OFF:
  629. default:
  630. goto out;
  631. }
  632. neigh_old = batadv_find_router(bat_priv, orig_dst_node, NULL);
  633. if (!neigh_old)
  634. goto out;
  635. old_ifinfo = batadv_neigh_ifinfo_get(neigh_old, BATADV_IF_DEFAULT);
  636. if (!old_ifinfo)
  637. goto out;
  638. if ((curr_tq_avg - old_ifinfo->bat_iv.tq_avg) > BATADV_GW_THRESHOLD)
  639. out_of_range = true;
  640. batadv_neigh_ifinfo_put(old_ifinfo);
  641. out:
  642. batadv_orig_node_put(orig_dst_node);
  643. batadv_gw_node_put(curr_gw);
  644. batadv_gw_node_put(gw_node);
  645. batadv_neigh_node_put(neigh_old);
  646. batadv_neigh_node_put(neigh_curr);
  647. return out_of_range;
  648. }