1/* Copyright (C) 2009-2014 B.A.T.M.A.N. contributors:
2 *
3 * Marek Lindner
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "main.h"
19#include "sysfs.h"
20#include "gateway_client.h"
21#include "gateway_common.h"
22#include "hard-interface.h"
23#include "originator.h"
24#include "translation-table.h"
25#include "routing.h"
26#include <linux/ip.h>
27#include <linux/ipv6.h>
28#include <linux/udp.h>
29#include <linux/if_vlan.h>
30
31/* These are the offsets of the "hw type" and "hw address length" in the dhcp
32 * packet starting at the beginning of the dhcp header
33 */
34#define BATADV_DHCP_HTYPE_OFFSET	1
35#define BATADV_DHCP_HLEN_OFFSET		2
36/* Value of htype representing Ethernet */
37#define BATADV_DHCP_HTYPE_ETHERNET	0x01
38/* This is the offset of the "chaddr" field in the dhcp packet starting at the
39 * beginning of the dhcp header
40 */
41#define BATADV_DHCP_CHADDR_OFFSET	28
42
43static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node)
44{
45	if (atomic_dec_and_test(&gw_node->refcount)) {
46		batadv_orig_node_free_ref(gw_node->orig_node);
47		kfree_rcu(gw_node, rcu);
48	}
49}
50
51static struct batadv_gw_node *
52batadv_gw_get_selected_gw_node(struct batadv_priv *bat_priv)
53{
54	struct batadv_gw_node *gw_node;
55
56	rcu_read_lock();
57	gw_node = rcu_dereference(bat_priv->gw.curr_gw);
58	if (!gw_node)
59		goto out;
60
61	if (!atomic_inc_not_zero(&gw_node->refcount))
62		gw_node = NULL;
63
64out:
65	rcu_read_unlock();
66	return gw_node;
67}
68
69struct batadv_orig_node *
70batadv_gw_get_selected_orig(struct batadv_priv *bat_priv)
71{
72	struct batadv_gw_node *gw_node;
73	struct batadv_orig_node *orig_node = NULL;
74
75	gw_node = batadv_gw_get_selected_gw_node(bat_priv);
76	if (!gw_node)
77		goto out;
78
79	rcu_read_lock();
80	orig_node = gw_node->orig_node;
81	if (!orig_node)
82		goto unlock;
83
84	if (!atomic_inc_not_zero(&orig_node->refcount))
85		orig_node = NULL;
86
87unlock:
88	rcu_read_unlock();
89out:
90	if (gw_node)
91		batadv_gw_node_free_ref(gw_node);
92	return orig_node;
93}
94
95static void batadv_gw_select(struct batadv_priv *bat_priv,
96			     struct batadv_gw_node *new_gw_node)
97{
98	struct batadv_gw_node *curr_gw_node;
99
100	spin_lock_bh(&bat_priv->gw.list_lock);
101
102	if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
103		new_gw_node = NULL;
104
105	curr_gw_node = rcu_dereference_protected(bat_priv->gw.curr_gw, 1);
106	rcu_assign_pointer(bat_priv->gw.curr_gw, new_gw_node);
107
108	if (curr_gw_node)
109		batadv_gw_node_free_ref(curr_gw_node);
110
111	spin_unlock_bh(&bat_priv->gw.list_lock);
112}
113
114/**
115 * batadv_gw_reselect - force a gateway reselection
116 * @bat_priv: the bat priv with all the soft interface information
117 *
118 * Set a flag to remind the GW component to perform a new gateway reselection.
119 * However this function does not ensure that the current gateway is going to be
120 * deselected. The reselection mechanism may elect the same gateway once again.
121 *
122 * This means that invoking batadv_gw_reselect() does not guarantee a gateway
123 * change and therefore a uevent is not necessarily expected.
124 */
125void batadv_gw_reselect(struct batadv_priv *bat_priv)
126{
127	atomic_set(&bat_priv->gw.reselect, 1);
128}
129
130static struct batadv_gw_node *
131batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
132{
133	struct batadv_neigh_node *router;
134	struct batadv_neigh_ifinfo *router_ifinfo;
135	struct batadv_gw_node *gw_node, *curr_gw = NULL;
136	uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
137	uint32_t gw_divisor;
138	uint8_t max_tq = 0;
139	uint8_t tq_avg;
140	struct batadv_orig_node *orig_node;
141
142	gw_divisor = BATADV_TQ_LOCAL_WINDOW_SIZE * BATADV_TQ_LOCAL_WINDOW_SIZE;
143	gw_divisor *= 64;
144
145	rcu_read_lock();
146	hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
147		if (gw_node->deleted)
148			continue;
149
150		orig_node = gw_node->orig_node;
151		router = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
152		if (!router)
153			continue;
154
155		router_ifinfo = batadv_neigh_ifinfo_get(router,
156							BATADV_IF_DEFAULT);
157		if (!router_ifinfo)
158			goto next;
159
160		if (!atomic_inc_not_zero(&gw_node->refcount))
161			goto next;
162
163		tq_avg = router_ifinfo->bat_iv.tq_avg;
164
165		switch (atomic_read(&bat_priv->gw_sel_class)) {
166		case 1: /* fast connection */
167			tmp_gw_factor = tq_avg * tq_avg;
168			tmp_gw_factor *= gw_node->bandwidth_down;
169			tmp_gw_factor *= 100 * 100;
170			tmp_gw_factor /= gw_divisor;
171
172			if ((tmp_gw_factor > max_gw_factor) ||
173			    ((tmp_gw_factor == max_gw_factor) &&
174			     (tq_avg > max_tq))) {
175				if (curr_gw)
176					batadv_gw_node_free_ref(curr_gw);
177				curr_gw = gw_node;
178				atomic_inc(&curr_gw->refcount);
179			}
180			break;
181
182		default: /* 2:  stable connection (use best statistic)
183			  * 3:  fast-switch (use best statistic but change as
184			  *     soon as a better gateway appears)
185			  * XX: late-switch (use best statistic but change as
186			  *     soon as a better gateway appears which has
187			  *     $routing_class more tq points)
188			  */
189			if (tq_avg > max_tq) {
190				if (curr_gw)
191					batadv_gw_node_free_ref(curr_gw);
192				curr_gw = gw_node;
193				atomic_inc(&curr_gw->refcount);
194			}
195			break;
196		}
197
198		if (tq_avg > max_tq)
199			max_tq = tq_avg;
200
201		if (tmp_gw_factor > max_gw_factor)
202			max_gw_factor = tmp_gw_factor;
203
204		batadv_gw_node_free_ref(gw_node);
205
206next:
207		batadv_neigh_node_free_ref(router);
208		if (router_ifinfo)
209			batadv_neigh_ifinfo_free_ref(router_ifinfo);
210	}
211	rcu_read_unlock();
212
213	return curr_gw;
214}
215
216/**
217 * batadv_gw_check_client_stop - check if client mode has been switched off
218 * @bat_priv: the bat priv with all the soft interface information
219 *
220 * This function assumes the caller has checked that the gw state *is actually
221 * changing*. This function is not supposed to be called when there is no state
222 * change.
223 */
224void batadv_gw_check_client_stop(struct batadv_priv *bat_priv)
225{
226	struct batadv_gw_node *curr_gw;
227
228	if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT)
229		return;
230
231	curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
232	if (!curr_gw)
233		return;
234
235	/* deselect the current gateway so that next time that client mode is
236	 * enabled a proper GW_ADD event can be sent
237	 */
238	batadv_gw_select(bat_priv, NULL);
239
240	/* if batman-adv is switching the gw client mode off and a gateway was
241	 * already selected, send a DEL uevent
242	 */
243	batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_DEL, NULL);
244
245	batadv_gw_node_free_ref(curr_gw);
246}
247
248void batadv_gw_election(struct batadv_priv *bat_priv)
249{
250	struct batadv_gw_node *curr_gw = NULL, *next_gw = NULL;
251	struct batadv_neigh_node *router = NULL;
252	struct batadv_neigh_ifinfo *router_ifinfo = NULL;
253	char gw_addr[18] = { '\0' };
254
255	if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT)
256		goto out;
257
258	curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
259
260	if (!batadv_atomic_dec_not_zero(&bat_priv->gw.reselect) && curr_gw)
261		goto out;
262
263	next_gw = batadv_gw_get_best_gw_node(bat_priv);
264
265	if (curr_gw == next_gw)
266		goto out;
267
268	if (next_gw) {
269		sprintf(gw_addr, "%pM", next_gw->orig_node->orig);
270
271		router = batadv_orig_router_get(next_gw->orig_node,
272						BATADV_IF_DEFAULT);
273		if (!router) {
274			batadv_gw_reselect(bat_priv);
275			goto out;
276		}
277
278		router_ifinfo = batadv_neigh_ifinfo_get(router,
279							BATADV_IF_DEFAULT);
280		if (!router_ifinfo) {
281			batadv_gw_reselect(bat_priv);
282			goto out;
283		}
284	}
285
286	if ((curr_gw) && (!next_gw)) {
287		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
288			   "Removing selected gateway - no gateway in range\n");
289		batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_DEL,
290				    NULL);
291	} else if ((!curr_gw) && (next_gw)) {
292		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
293			   "Adding route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n",
294			   next_gw->orig_node->orig,
295			   next_gw->bandwidth_down / 10,
296			   next_gw->bandwidth_down % 10,
297			   next_gw->bandwidth_up / 10,
298			   next_gw->bandwidth_up % 10,
299			   router_ifinfo->bat_iv.tq_avg);
300		batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD,
301				    gw_addr);
302	} else {
303		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
304			   "Changing route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n",
305			   next_gw->orig_node->orig,
306			   next_gw->bandwidth_down / 10,
307			   next_gw->bandwidth_down % 10,
308			   next_gw->bandwidth_up / 10,
309			   next_gw->bandwidth_up % 10,
310			   router_ifinfo->bat_iv.tq_avg);
311		batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE,
312				    gw_addr);
313	}
314
315	batadv_gw_select(bat_priv, next_gw);
316
317out:
318	if (curr_gw)
319		batadv_gw_node_free_ref(curr_gw);
320	if (next_gw)
321		batadv_gw_node_free_ref(next_gw);
322	if (router)
323		batadv_neigh_node_free_ref(router);
324	if (router_ifinfo)
325		batadv_neigh_ifinfo_free_ref(router_ifinfo);
326}
327
328void batadv_gw_check_election(struct batadv_priv *bat_priv,
329			      struct batadv_orig_node *orig_node)
330{
331	struct batadv_neigh_ifinfo *router_orig_tq = NULL;
332	struct batadv_neigh_ifinfo *router_gw_tq = NULL;
333	struct batadv_orig_node *curr_gw_orig;
334	struct batadv_neigh_node *router_gw = NULL, *router_orig = NULL;
335	uint8_t gw_tq_avg, orig_tq_avg;
336
337	curr_gw_orig = batadv_gw_get_selected_orig(bat_priv);
338	if (!curr_gw_orig)
339		goto reselect;
340
341	router_gw = batadv_orig_router_get(curr_gw_orig, BATADV_IF_DEFAULT);
342	if (!router_gw)
343		goto reselect;
344
345	router_gw_tq = batadv_neigh_ifinfo_get(router_gw,
346					       BATADV_IF_DEFAULT);
347	if (!router_gw_tq)
348		goto reselect;
349
350	/* this node already is the gateway */
351	if (curr_gw_orig == orig_node)
352		goto out;
353
354	router_orig = batadv_orig_router_get(orig_node, BATADV_IF_DEFAULT);
355	if (!router_orig)
356		goto out;
357
358	router_orig_tq = batadv_neigh_ifinfo_get(router_orig,
359						 BATADV_IF_DEFAULT);
360	if (!router_orig_tq)
361		goto out;
362
363	gw_tq_avg = router_gw_tq->bat_iv.tq_avg;
364	orig_tq_avg = router_orig_tq->bat_iv.tq_avg;
365
366	/* the TQ value has to be better */
367	if (orig_tq_avg < gw_tq_avg)
368		goto out;
369
370	/* if the routing class is greater than 3 the value tells us how much
371	 * greater the TQ value of the new gateway must be
372	 */
373	if ((atomic_read(&bat_priv->gw_sel_class) > 3) &&
374	    (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_sel_class)))
375		goto out;
376
377	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
378		   "Restarting gateway selection: better gateway found (tq curr: %i, tq new: %i)\n",
379		   gw_tq_avg, orig_tq_avg);
380
381reselect:
382	batadv_gw_reselect(bat_priv);
383out:
384	if (curr_gw_orig)
385		batadv_orig_node_free_ref(curr_gw_orig);
386	if (router_gw)
387		batadv_neigh_node_free_ref(router_gw);
388	if (router_orig)
389		batadv_neigh_node_free_ref(router_orig);
390	if (router_gw_tq)
391		batadv_neigh_ifinfo_free_ref(router_gw_tq);
392	if (router_orig_tq)
393		batadv_neigh_ifinfo_free_ref(router_orig_tq);
394}
395
396/**
397 * batadv_gw_node_add - add gateway node to list of available gateways
398 * @bat_priv: the bat priv with all the soft interface information
399 * @orig_node: originator announcing gateway capabilities
400 * @gateway: announced bandwidth information
401 */
402static void batadv_gw_node_add(struct batadv_priv *bat_priv,
403			       struct batadv_orig_node *orig_node,
404			       struct batadv_tvlv_gateway_data *gateway)
405{
406	struct batadv_gw_node *gw_node;
407
408	if (gateway->bandwidth_down == 0)
409		return;
410
411	if (!atomic_inc_not_zero(&orig_node->refcount))
412		return;
413
414	gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC);
415	if (!gw_node) {
416		batadv_orig_node_free_ref(orig_node);
417		return;
418	}
419
420	INIT_HLIST_NODE(&gw_node->list);
421	gw_node->orig_node = orig_node;
422	atomic_set(&gw_node->refcount, 1);
423
424	spin_lock_bh(&bat_priv->gw.list_lock);
425	hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list);
426	spin_unlock_bh(&bat_priv->gw.list_lock);
427
428	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
429		   "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n",
430		   orig_node->orig,
431		   ntohl(gateway->bandwidth_down) / 10,
432		   ntohl(gateway->bandwidth_down) % 10,
433		   ntohl(gateway->bandwidth_up) / 10,
434		   ntohl(gateway->bandwidth_up) % 10);
435}
436
437/**
438 * batadv_gw_node_get - retrieve gateway node from list of available gateways
439 * @bat_priv: the bat priv with all the soft interface information
440 * @orig_node: originator announcing gateway capabilities
441 *
442 * Returns gateway node if found or NULL otherwise.
443 */
444static struct batadv_gw_node *
445batadv_gw_node_get(struct batadv_priv *bat_priv,
446		   struct batadv_orig_node *orig_node)
447{
448	struct batadv_gw_node *gw_node_tmp, *gw_node = NULL;
449
450	rcu_read_lock();
451	hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.list, list) {
452		if (gw_node_tmp->orig_node != orig_node)
453			continue;
454
455		if (gw_node_tmp->deleted)
456			continue;
457
458		if (!atomic_inc_not_zero(&gw_node_tmp->refcount))
459			continue;
460
461		gw_node = gw_node_tmp;
462		break;
463	}
464	rcu_read_unlock();
465
466	return gw_node;
467}
468
469/**
470 * batadv_gw_node_update - update list of available gateways with changed
471 *  bandwidth information
472 * @bat_priv: the bat priv with all the soft interface information
473 * @orig_node: originator announcing gateway capabilities
474 * @gateway: announced bandwidth information
475 */
476void batadv_gw_node_update(struct batadv_priv *bat_priv,
477			   struct batadv_orig_node *orig_node,
478			   struct batadv_tvlv_gateway_data *gateway)
479{
480	struct batadv_gw_node *gw_node, *curr_gw = NULL;
481
482	gw_node = batadv_gw_node_get(bat_priv, orig_node);
483	if (!gw_node) {
484		batadv_gw_node_add(bat_priv, orig_node, gateway);
485		goto out;
486	}
487
488	if ((gw_node->bandwidth_down == ntohl(gateway->bandwidth_down)) &&
489	    (gw_node->bandwidth_up == ntohl(gateway->bandwidth_up)))
490		goto out;
491
492	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
493		   "Gateway bandwidth of originator %pM changed from %u.%u/%u.%u MBit to %u.%u/%u.%u MBit\n",
494		   orig_node->orig,
495		   gw_node->bandwidth_down / 10,
496		   gw_node->bandwidth_down % 10,
497		   gw_node->bandwidth_up / 10,
498		   gw_node->bandwidth_up % 10,
499		   ntohl(gateway->bandwidth_down) / 10,
500		   ntohl(gateway->bandwidth_down) % 10,
501		   ntohl(gateway->bandwidth_up) / 10,
502		   ntohl(gateway->bandwidth_up) % 10);
503
504	gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
505	gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
506
507	gw_node->deleted = 0;
508	if (ntohl(gateway->bandwidth_down) == 0) {
509		gw_node->deleted = jiffies;
510		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
511			   "Gateway %pM removed from gateway list\n",
512			   orig_node->orig);
513
514		/* Note: We don't need a NULL check here, since curr_gw never
515		 * gets dereferenced.
516		 */
517		curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
518		if (gw_node == curr_gw)
519			batadv_gw_reselect(bat_priv);
520	}
521
522out:
523	if (curr_gw)
524		batadv_gw_node_free_ref(curr_gw);
525	if (gw_node)
526		batadv_gw_node_free_ref(gw_node);
527}
528
529void batadv_gw_node_delete(struct batadv_priv *bat_priv,
530			   struct batadv_orig_node *orig_node)
531{
532	struct batadv_tvlv_gateway_data gateway;
533
534	gateway.bandwidth_down = 0;
535	gateway.bandwidth_up = 0;
536
537	batadv_gw_node_update(bat_priv, orig_node, &gateway);
538}
539
540void batadv_gw_node_purge(struct batadv_priv *bat_priv)
541{
542	struct batadv_gw_node *gw_node, *curr_gw;
543	struct hlist_node *node_tmp;
544	unsigned long timeout = msecs_to_jiffies(2 * BATADV_PURGE_TIMEOUT);
545	int do_reselect = 0;
546
547	curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
548
549	spin_lock_bh(&bat_priv->gw.list_lock);
550
551	hlist_for_each_entry_safe(gw_node, node_tmp,
552				  &bat_priv->gw.list, list) {
553		if (((!gw_node->deleted) ||
554		     (time_before(jiffies, gw_node->deleted + timeout))) &&
555		    atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE)
556			continue;
557
558		if (curr_gw == gw_node)
559			do_reselect = 1;
560
561		hlist_del_rcu(&gw_node->list);
562		batadv_gw_node_free_ref(gw_node);
563	}
564
565	spin_unlock_bh(&bat_priv->gw.list_lock);
566
567	/* gw_reselect() needs to acquire the gw_list_lock */
568	if (do_reselect)
569		batadv_gw_reselect(bat_priv);
570
571	if (curr_gw)
572		batadv_gw_node_free_ref(curr_gw);
573}
574
575/* fails if orig_node has no router */
576static int batadv_write_buffer_text(struct batadv_priv *bat_priv,
577				    struct seq_file *seq,
578				    const struct batadv_gw_node *gw_node)
579{
580	struct batadv_gw_node *curr_gw;
581	struct batadv_neigh_node *router;
582	struct batadv_neigh_ifinfo *router_ifinfo = NULL;
583	int ret = -1;
584
585	router = batadv_orig_router_get(gw_node->orig_node, BATADV_IF_DEFAULT);
586	if (!router)
587		goto out;
588
589	router_ifinfo = batadv_neigh_ifinfo_get(router, BATADV_IF_DEFAULT);
590	if (!router_ifinfo)
591		goto out;
592
593	curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
594
595	seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n",
596		   (curr_gw == gw_node ? "=>" : "  "),
597		   gw_node->orig_node->orig,
598		   router_ifinfo->bat_iv.tq_avg, router->addr,
599		   router->if_incoming->net_dev->name,
600		   gw_node->bandwidth_down / 10,
601		   gw_node->bandwidth_down % 10,
602		   gw_node->bandwidth_up / 10,
603		   gw_node->bandwidth_up % 10);
604	ret = seq_has_overflowed(seq) ? -1 : 0;
605
606	if (curr_gw)
607		batadv_gw_node_free_ref(curr_gw);
608out:
609	if (router_ifinfo)
610		batadv_neigh_ifinfo_free_ref(router_ifinfo);
611	if (router)
612		batadv_neigh_node_free_ref(router);
613	return ret;
614}
615
616int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
617{
618	struct net_device *net_dev = (struct net_device *)seq->private;
619	struct batadv_priv *bat_priv = netdev_priv(net_dev);
620	struct batadv_hard_iface *primary_if;
621	struct batadv_gw_node *gw_node;
622	int gw_count = 0;
623
624	primary_if = batadv_seq_print_text_primary_if_get(seq);
625	if (!primary_if)
626		goto out;
627
628	seq_printf(seq,
629		   "      %-12s (%s/%i) %17s [%10s]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
630		   "Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF",
631		   BATADV_SOURCE_VERSION, primary_if->net_dev->name,
632		   primary_if->net_dev->dev_addr, net_dev->name);
633
634	rcu_read_lock();
635	hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) {
636		if (gw_node->deleted)
637			continue;
638
639		/* fails if orig_node has no router */
640		if (batadv_write_buffer_text(bat_priv, seq, gw_node) < 0)
641			continue;
642
643		gw_count++;
644	}
645	rcu_read_unlock();
646
647	if (gw_count == 0)
648		seq_puts(seq, "No gateways in range ...\n");
649
650out:
651	if (primary_if)
652		batadv_hardif_free_ref(primary_if);
653	return 0;
654}
655
656/**
657 * batadv_gw_dhcp_recipient_get - check if a packet is a DHCP message
658 * @skb: the packet to check
659 * @header_len: a pointer to the batman-adv header size
660 * @chaddr: buffer where the client address will be stored. Valid
661 *  only if the function returns BATADV_DHCP_TO_CLIENT
662 *
663 * Returns:
664 * - BATADV_DHCP_NO if the packet is not a dhcp message or if there was an error
665 *   while parsing it
666 * - BATADV_DHCP_TO_SERVER if this is a message going to the DHCP server
667 * - BATADV_DHCP_TO_CLIENT if this is a message going to a DHCP client
668 *
669 * This function may re-allocate the data buffer of the skb passed as argument.
670 */
671enum batadv_dhcp_recipient
672batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len,
673			     uint8_t *chaddr)
674{
675	enum batadv_dhcp_recipient ret = BATADV_DHCP_NO;
676	struct ethhdr *ethhdr;
677	struct iphdr *iphdr;
678	struct ipv6hdr *ipv6hdr;
679	struct udphdr *udphdr;
680	struct vlan_ethhdr *vhdr;
681	int chaddr_offset;
682	__be16 proto;
683	uint8_t *p;
684
685	/* check for ethernet header */
686	if (!pskb_may_pull(skb, *header_len + ETH_HLEN))
687		return BATADV_DHCP_NO;
688
689	ethhdr = eth_hdr(skb);
690	proto = ethhdr->h_proto;
691	*header_len += ETH_HLEN;
692
693	/* check for initial vlan header */
694	if (proto == htons(ETH_P_8021Q)) {
695		if (!pskb_may_pull(skb, *header_len + VLAN_HLEN))
696			return BATADV_DHCP_NO;
697
698		vhdr = vlan_eth_hdr(skb);
699		proto = vhdr->h_vlan_encapsulated_proto;
700		*header_len += VLAN_HLEN;
701	}
702
703	/* check for ip header */
704	switch (proto) {
705	case htons(ETH_P_IP):
706		if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr)))
707			return BATADV_DHCP_NO;
708
709		iphdr = (struct iphdr *)(skb->data + *header_len);
710		*header_len += iphdr->ihl * 4;
711
712		/* check for udp header */
713		if (iphdr->protocol != IPPROTO_UDP)
714			return BATADV_DHCP_NO;
715
716		break;
717	case htons(ETH_P_IPV6):
718		if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr)))
719			return BATADV_DHCP_NO;
720
721		ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len);
722		*header_len += sizeof(*ipv6hdr);
723
724		/* check for udp header */
725		if (ipv6hdr->nexthdr != IPPROTO_UDP)
726			return BATADV_DHCP_NO;
727
728		break;
729	default:
730		return BATADV_DHCP_NO;
731	}
732
733	if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr)))
734		return BATADV_DHCP_NO;
735
736	/* skb->data might have been reallocated by pskb_may_pull() */
737	ethhdr = eth_hdr(skb);
738	if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
739		ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN);
740
741	udphdr = (struct udphdr *)(skb->data + *header_len);
742	*header_len += sizeof(*udphdr);
743
744	/* check for bootp port */
745	switch (proto) {
746	case htons(ETH_P_IP):
747		if (udphdr->dest == htons(67))
748			ret = BATADV_DHCP_TO_SERVER;
749		else if (udphdr->source == htons(67))
750			ret = BATADV_DHCP_TO_CLIENT;
751		break;
752	case htons(ETH_P_IPV6):
753		if (udphdr->dest == htons(547))
754			ret = BATADV_DHCP_TO_SERVER;
755		else if (udphdr->source == htons(547))
756			ret = BATADV_DHCP_TO_CLIENT;
757		break;
758	}
759
760	chaddr_offset = *header_len + BATADV_DHCP_CHADDR_OFFSET;
761	/* store the client address if the message is going to a client */
762	if (ret == BATADV_DHCP_TO_CLIENT &&
763	    pskb_may_pull(skb, chaddr_offset + ETH_ALEN)) {
764		/* check if the DHCP packet carries an Ethernet DHCP */
765		p = skb->data + *header_len + BATADV_DHCP_HTYPE_OFFSET;
766		if (*p != BATADV_DHCP_HTYPE_ETHERNET)
767			return BATADV_DHCP_NO;
768
769		/* check if the DHCP packet carries a valid Ethernet address */
770		p = skb->data + *header_len + BATADV_DHCP_HLEN_OFFSET;
771		if (*p != ETH_ALEN)
772			return BATADV_DHCP_NO;
773
774		ether_addr_copy(chaddr, skb->data + chaddr_offset);
775	}
776
777	return ret;
778}
779
780/**
781 * batadv_gw_out_of_range - check if the dhcp request destination is the best gw
782 * @bat_priv: the bat priv with all the soft interface information
783 * @skb: the outgoing packet
784 *
785 * Check if the skb is a DHCP request and if it is sent to the current best GW
786 * server. Due to topology changes it may be the case that the GW server
787 * previously selected is not the best one anymore.
788 *
789 * Returns true if the packet destination is unicast and it is not the best gw,
790 * false otherwise.
791 *
792 * This call might reallocate skb data.
793 * Must be invoked only when the DHCP packet is going TO a DHCP SERVER.
794 */
795bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
796			    struct sk_buff *skb)
797{
798	struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL;
799	struct batadv_orig_node *orig_dst_node = NULL;
800	struct batadv_gw_node *gw_node = NULL, *curr_gw = NULL;
801	struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo;
802	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
803	bool out_of_range = false;
804	uint8_t curr_tq_avg;
805	unsigned short vid;
806
807	vid = batadv_get_vid(skb, 0);
808
809	orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
810						 ethhdr->h_dest, vid);
811	if (!orig_dst_node)
812		goto out;
813
814	gw_node = batadv_gw_node_get(bat_priv, orig_dst_node);
815	if (!gw_node)
816		goto out;
817
818	switch (atomic_read(&bat_priv->gw_mode)) {
819	case BATADV_GW_MODE_SERVER:
820		/* If we are a GW then we are our best GW. We can artificially
821		 * set the tq towards ourself as the maximum value
822		 */
823		curr_tq_avg = BATADV_TQ_MAX_VALUE;
824		break;
825	case BATADV_GW_MODE_CLIENT:
826		curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
827		if (!curr_gw)
828			goto out;
829
830		/* packet is going to our gateway */
831		if (curr_gw->orig_node == orig_dst_node)
832			goto out;
833
834		/* If the dhcp packet has been sent to a different gw,
835		 * we have to evaluate whether the old gw is still
836		 * reliable enough
837		 */
838		neigh_curr = batadv_find_router(bat_priv, curr_gw->orig_node,
839						NULL);
840		if (!neigh_curr)
841			goto out;
842
843		curr_ifinfo = batadv_neigh_ifinfo_get(neigh_curr,
844						      BATADV_IF_DEFAULT);
845		if (!curr_ifinfo)
846			goto out;
847
848		curr_tq_avg = curr_ifinfo->bat_iv.tq_avg;
849		batadv_neigh_ifinfo_free_ref(curr_ifinfo);
850
851		break;
852	case BATADV_GW_MODE_OFF:
853	default:
854		goto out;
855	}
856
857	neigh_old = batadv_find_router(bat_priv, orig_dst_node, NULL);
858	if (!neigh_old)
859		goto out;
860
861	old_ifinfo = batadv_neigh_ifinfo_get(neigh_old, BATADV_IF_DEFAULT);
862	if (!old_ifinfo)
863		goto out;
864
865	if ((curr_tq_avg - old_ifinfo->bat_iv.tq_avg) > BATADV_GW_THRESHOLD)
866		out_of_range = true;
867	batadv_neigh_ifinfo_free_ref(old_ifinfo);
868
869out:
870	if (orig_dst_node)
871		batadv_orig_node_free_ref(orig_dst_node);
872	if (curr_gw)
873		batadv_gw_node_free_ref(curr_gw);
874	if (gw_node)
875		batadv_gw_node_free_ref(gw_node);
876	if (neigh_old)
877		batadv_neigh_node_free_ref(neigh_old);
878	if (neigh_curr)
879		batadv_neigh_node_free_ref(neigh_curr);
880	return out_of_range;
881}
882