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