1 /* Copyright (C) 2009-2013 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, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 * 02110-1301, USA 18 */ 19 20 #include "main.h" 21 #include "sysfs.h" 22 #include "gateway_client.h" 23 #include "gateway_common.h" 24 #include "hard-interface.h" 25 #include "originator.h" 26 #include "translation-table.h" 27 #include "routing.h" 28 #include <linux/ip.h> 29 #include <linux/ipv6.h> 30 #include <linux/udp.h> 31 #include <linux/if_vlan.h> 32 33 /* This is the offset of the options field in a dhcp packet starting at 34 * the beginning of the dhcp header 35 */ 36 #define BATADV_DHCP_OPTIONS_OFFSET 240 37 #define BATADV_DHCP_REQUEST 3 38 39 static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node) 40 { 41 if (atomic_dec_and_test(&gw_node->refcount)) 42 kfree_rcu(gw_node, rcu); 43 } 44 45 static struct batadv_gw_node * 46 batadv_gw_get_selected_gw_node(struct batadv_priv *bat_priv) 47 { 48 struct batadv_gw_node *gw_node; 49 50 rcu_read_lock(); 51 gw_node = rcu_dereference(bat_priv->gw.curr_gw); 52 if (!gw_node) 53 goto out; 54 55 if (!atomic_inc_not_zero(&gw_node->refcount)) 56 gw_node = NULL; 57 58 out: 59 rcu_read_unlock(); 60 return gw_node; 61 } 62 63 struct batadv_orig_node * 64 batadv_gw_get_selected_orig(struct batadv_priv *bat_priv) 65 { 66 struct batadv_gw_node *gw_node; 67 struct batadv_orig_node *orig_node = NULL; 68 69 gw_node = batadv_gw_get_selected_gw_node(bat_priv); 70 if (!gw_node) 71 goto out; 72 73 rcu_read_lock(); 74 orig_node = gw_node->orig_node; 75 if (!orig_node) 76 goto unlock; 77 78 if (!atomic_inc_not_zero(&orig_node->refcount)) 79 orig_node = NULL; 80 81 unlock: 82 rcu_read_unlock(); 83 out: 84 if (gw_node) 85 batadv_gw_node_free_ref(gw_node); 86 return orig_node; 87 } 88 89 static void batadv_gw_select(struct batadv_priv *bat_priv, 90 struct batadv_gw_node *new_gw_node) 91 { 92 struct batadv_gw_node *curr_gw_node; 93 94 spin_lock_bh(&bat_priv->gw.list_lock); 95 96 if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount)) 97 new_gw_node = NULL; 98 99 curr_gw_node = rcu_dereference_protected(bat_priv->gw.curr_gw, 1); 100 rcu_assign_pointer(bat_priv->gw.curr_gw, new_gw_node); 101 102 if (curr_gw_node) 103 batadv_gw_node_free_ref(curr_gw_node); 104 105 spin_unlock_bh(&bat_priv->gw.list_lock); 106 } 107 108 void batadv_gw_deselect(struct batadv_priv *bat_priv) 109 { 110 atomic_set(&bat_priv->gw.reselect, 1); 111 } 112 113 static struct batadv_gw_node * 114 batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) 115 { 116 struct batadv_neigh_node *router; 117 struct batadv_gw_node *gw_node, *curr_gw = NULL; 118 uint32_t max_gw_factor = 0, tmp_gw_factor = 0; 119 uint32_t gw_divisor; 120 uint8_t max_tq = 0; 121 int down, up; 122 uint8_t tq_avg; 123 struct batadv_orig_node *orig_node; 124 125 gw_divisor = BATADV_TQ_LOCAL_WINDOW_SIZE * BATADV_TQ_LOCAL_WINDOW_SIZE; 126 gw_divisor *= 64; 127 128 rcu_read_lock(); 129 hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) { 130 if (gw_node->deleted) 131 continue; 132 133 orig_node = gw_node->orig_node; 134 router = batadv_orig_node_get_router(orig_node); 135 if (!router) 136 continue; 137 138 if (!atomic_inc_not_zero(&gw_node->refcount)) 139 goto next; 140 141 tq_avg = router->tq_avg; 142 143 switch (atomic_read(&bat_priv->gw_sel_class)) { 144 case 1: /* fast connection */ 145 batadv_gw_bandwidth_to_kbit(orig_node->gw_flags, 146 &down, &up); 147 148 tmp_gw_factor = tq_avg * tq_avg * down * 100 * 100; 149 tmp_gw_factor /= gw_divisor; 150 151 if ((tmp_gw_factor > max_gw_factor) || 152 ((tmp_gw_factor == max_gw_factor) && 153 (tq_avg > max_tq))) { 154 if (curr_gw) 155 batadv_gw_node_free_ref(curr_gw); 156 curr_gw = gw_node; 157 atomic_inc(&curr_gw->refcount); 158 } 159 break; 160 161 default: /* 2: stable connection (use best statistic) 162 * 3: fast-switch (use best statistic but change as 163 * soon as a better gateway appears) 164 * XX: late-switch (use best statistic but change as 165 * soon as a better gateway appears which has 166 * $routing_class more tq points) 167 */ 168 if (tq_avg > max_tq) { 169 if (curr_gw) 170 batadv_gw_node_free_ref(curr_gw); 171 curr_gw = gw_node; 172 atomic_inc(&curr_gw->refcount); 173 } 174 break; 175 } 176 177 if (tq_avg > max_tq) 178 max_tq = tq_avg; 179 180 if (tmp_gw_factor > max_gw_factor) 181 max_gw_factor = tmp_gw_factor; 182 183 batadv_gw_node_free_ref(gw_node); 184 185 next: 186 batadv_neigh_node_free_ref(router); 187 } 188 rcu_read_unlock(); 189 190 return curr_gw; 191 } 192 193 /** 194 * batadv_gw_check_client_stop - check if client mode has been switched off 195 * @bat_priv: the bat priv with all the soft interface information 196 * 197 * This function assumes the caller has checked that the gw state *is actually 198 * changing*. This function is not supposed to be called when there is no state 199 * change. 200 */ 201 void batadv_gw_check_client_stop(struct batadv_priv *bat_priv) 202 { 203 struct batadv_gw_node *curr_gw; 204 205 if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) 206 return; 207 208 curr_gw = batadv_gw_get_selected_gw_node(bat_priv); 209 if (!curr_gw) 210 return; 211 212 /* if batman-adv is switching the gw client mode off and a gateway was 213 * already selected, send a DEL uevent 214 */ 215 batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_DEL, NULL); 216 217 batadv_gw_node_free_ref(curr_gw); 218 } 219 220 void batadv_gw_election(struct batadv_priv *bat_priv) 221 { 222 struct batadv_gw_node *curr_gw = NULL, *next_gw = NULL; 223 struct batadv_neigh_node *router = NULL; 224 char gw_addr[18] = { '\0' }; 225 226 /* The batman daemon checks here if we already passed a full originator 227 * cycle in order to make sure we don't choose the first gateway we 228 * hear about. This check is based on the daemon's uptime which we 229 * don't have. 230 */ 231 if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) 232 goto out; 233 234 curr_gw = batadv_gw_get_selected_gw_node(bat_priv); 235 236 if (!batadv_atomic_dec_not_zero(&bat_priv->gw.reselect) && curr_gw) 237 goto out; 238 239 next_gw = batadv_gw_get_best_gw_node(bat_priv); 240 241 if (curr_gw == next_gw) 242 goto out; 243 244 if (next_gw) { 245 sprintf(gw_addr, "%pM", next_gw->orig_node->orig); 246 247 router = batadv_orig_node_get_router(next_gw->orig_node); 248 if (!router) { 249 batadv_gw_deselect(bat_priv); 250 goto out; 251 } 252 } 253 254 if ((curr_gw) && (!next_gw)) { 255 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 256 "Removing selected gateway - no gateway in range\n"); 257 batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_DEL, 258 NULL); 259 } else if ((!curr_gw) && (next_gw)) { 260 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 261 "Adding route to gateway %pM (gw_flags: %i, tq: %i)\n", 262 next_gw->orig_node->orig, 263 next_gw->orig_node->gw_flags, router->tq_avg); 264 batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, 265 gw_addr); 266 } else { 267 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 268 "Changing route to gateway %pM (gw_flags: %i, tq: %i)\n", 269 next_gw->orig_node->orig, 270 next_gw->orig_node->gw_flags, router->tq_avg); 271 batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, 272 gw_addr); 273 } 274 275 batadv_gw_select(bat_priv, next_gw); 276 277 out: 278 if (curr_gw) 279 batadv_gw_node_free_ref(curr_gw); 280 if (next_gw) 281 batadv_gw_node_free_ref(next_gw); 282 if (router) 283 batadv_neigh_node_free_ref(router); 284 } 285 286 void batadv_gw_check_election(struct batadv_priv *bat_priv, 287 struct batadv_orig_node *orig_node) 288 { 289 struct batadv_orig_node *curr_gw_orig; 290 struct batadv_neigh_node *router_gw = NULL, *router_orig = NULL; 291 uint8_t gw_tq_avg, orig_tq_avg; 292 293 curr_gw_orig = batadv_gw_get_selected_orig(bat_priv); 294 if (!curr_gw_orig) 295 goto deselect; 296 297 router_gw = batadv_orig_node_get_router(curr_gw_orig); 298 if (!router_gw) 299 goto deselect; 300 301 /* this node already is the gateway */ 302 if (curr_gw_orig == orig_node) 303 goto out; 304 305 router_orig = batadv_orig_node_get_router(orig_node); 306 if (!router_orig) 307 goto out; 308 309 gw_tq_avg = router_gw->tq_avg; 310 orig_tq_avg = router_orig->tq_avg; 311 312 /* the TQ value has to be better */ 313 if (orig_tq_avg < gw_tq_avg) 314 goto out; 315 316 /* if the routing class is greater than 3 the value tells us how much 317 * greater the TQ value of the new gateway must be 318 */ 319 if ((atomic_read(&bat_priv->gw_sel_class) > 3) && 320 (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_sel_class))) 321 goto out; 322 323 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 324 "Restarting gateway selection: better gateway found (tq curr: %i, tq new: %i)\n", 325 gw_tq_avg, orig_tq_avg); 326 327 deselect: 328 batadv_gw_deselect(bat_priv); 329 out: 330 if (curr_gw_orig) 331 batadv_orig_node_free_ref(curr_gw_orig); 332 if (router_gw) 333 batadv_neigh_node_free_ref(router_gw); 334 if (router_orig) 335 batadv_neigh_node_free_ref(router_orig); 336 337 return; 338 } 339 340 static void batadv_gw_node_add(struct batadv_priv *bat_priv, 341 struct batadv_orig_node *orig_node, 342 uint8_t new_gwflags) 343 { 344 struct batadv_gw_node *gw_node; 345 int down, up; 346 347 gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); 348 if (!gw_node) 349 return; 350 351 INIT_HLIST_NODE(&gw_node->list); 352 gw_node->orig_node = orig_node; 353 atomic_set(&gw_node->refcount, 1); 354 355 spin_lock_bh(&bat_priv->gw.list_lock); 356 hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); 357 spin_unlock_bh(&bat_priv->gw.list_lock); 358 359 batadv_gw_bandwidth_to_kbit(new_gwflags, &down, &up); 360 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 361 "Found new gateway %pM -> gw_class: %i - %i%s/%i%s\n", 362 orig_node->orig, new_gwflags, 363 (down > 2048 ? down / 1024 : down), 364 (down > 2048 ? "MBit" : "KBit"), 365 (up > 2048 ? up / 1024 : up), 366 (up > 2048 ? "MBit" : "KBit")); 367 } 368 369 void batadv_gw_node_update(struct batadv_priv *bat_priv, 370 struct batadv_orig_node *orig_node, 371 uint8_t new_gwflags) 372 { 373 struct batadv_gw_node *gw_node, *curr_gw; 374 375 /* Note: We don't need a NULL check here, since curr_gw never gets 376 * dereferenced. If curr_gw is NULL we also should not exit as we may 377 * have this gateway in our list (duplication check!) even though we 378 * have no currently selected gateway. 379 */ 380 curr_gw = batadv_gw_get_selected_gw_node(bat_priv); 381 382 rcu_read_lock(); 383 hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) { 384 if (gw_node->orig_node != orig_node) 385 continue; 386 387 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 388 "Gateway class of originator %pM changed from %i to %i\n", 389 orig_node->orig, gw_node->orig_node->gw_flags, 390 new_gwflags); 391 392 gw_node->deleted = 0; 393 394 if (new_gwflags == BATADV_NO_FLAGS) { 395 gw_node->deleted = jiffies; 396 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, 397 "Gateway %pM removed from gateway list\n", 398 orig_node->orig); 399 400 if (gw_node == curr_gw) 401 goto deselect; 402 } 403 404 goto unlock; 405 } 406 407 if (new_gwflags == BATADV_NO_FLAGS) 408 goto unlock; 409 410 batadv_gw_node_add(bat_priv, orig_node, new_gwflags); 411 goto unlock; 412 413 deselect: 414 batadv_gw_deselect(bat_priv); 415 unlock: 416 rcu_read_unlock(); 417 418 if (curr_gw) 419 batadv_gw_node_free_ref(curr_gw); 420 } 421 422 void batadv_gw_node_delete(struct batadv_priv *bat_priv, 423 struct batadv_orig_node *orig_node) 424 { 425 batadv_gw_node_update(bat_priv, orig_node, 0); 426 } 427 428 void batadv_gw_node_purge(struct batadv_priv *bat_priv) 429 { 430 struct batadv_gw_node *gw_node, *curr_gw; 431 struct hlist_node *node_tmp; 432 unsigned long timeout = msecs_to_jiffies(2 * BATADV_PURGE_TIMEOUT); 433 int do_deselect = 0; 434 435 curr_gw = batadv_gw_get_selected_gw_node(bat_priv); 436 437 spin_lock_bh(&bat_priv->gw.list_lock); 438 439 hlist_for_each_entry_safe(gw_node, node_tmp, 440 &bat_priv->gw.list, list) { 441 if (((!gw_node->deleted) || 442 (time_before(jiffies, gw_node->deleted + timeout))) && 443 atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) 444 continue; 445 446 if (curr_gw == gw_node) 447 do_deselect = 1; 448 449 hlist_del_rcu(&gw_node->list); 450 batadv_gw_node_free_ref(gw_node); 451 } 452 453 spin_unlock_bh(&bat_priv->gw.list_lock); 454 455 /* gw_deselect() needs to acquire the gw_list_lock */ 456 if (do_deselect) 457 batadv_gw_deselect(bat_priv); 458 459 if (curr_gw) 460 batadv_gw_node_free_ref(curr_gw); 461 } 462 463 /* fails if orig_node has no router */ 464 static int batadv_write_buffer_text(struct batadv_priv *bat_priv, 465 struct seq_file *seq, 466 const struct batadv_gw_node *gw_node) 467 { 468 struct batadv_gw_node *curr_gw; 469 struct batadv_neigh_node *router; 470 int down, up, ret = -1; 471 472 batadv_gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up); 473 474 router = batadv_orig_node_get_router(gw_node->orig_node); 475 if (!router) 476 goto out; 477 478 curr_gw = batadv_gw_get_selected_gw_node(bat_priv); 479 480 ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", 481 (curr_gw == gw_node ? "=>" : " "), 482 gw_node->orig_node->orig, 483 router->tq_avg, router->addr, 484 router->if_incoming->net_dev->name, 485 gw_node->orig_node->gw_flags, 486 (down > 2048 ? down / 1024 : down), 487 (down > 2048 ? "MBit" : "KBit"), 488 (up > 2048 ? up / 1024 : up), 489 (up > 2048 ? "MBit" : "KBit")); 490 491 batadv_neigh_node_free_ref(router); 492 if (curr_gw) 493 batadv_gw_node_free_ref(curr_gw); 494 out: 495 return ret; 496 } 497 498 int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) 499 { 500 struct net_device *net_dev = (struct net_device *)seq->private; 501 struct batadv_priv *bat_priv = netdev_priv(net_dev); 502 struct batadv_hard_iface *primary_if; 503 struct batadv_gw_node *gw_node; 504 int gw_count = 0; 505 506 primary_if = batadv_seq_print_text_primary_if_get(seq); 507 if (!primary_if) 508 goto out; 509 510 seq_printf(seq, 511 " %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", 512 "Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF", 513 BATADV_SOURCE_VERSION, primary_if->net_dev->name, 514 primary_if->net_dev->dev_addr, net_dev->name); 515 516 rcu_read_lock(); 517 hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) { 518 if (gw_node->deleted) 519 continue; 520 521 /* fails if orig_node has no router */ 522 if (batadv_write_buffer_text(bat_priv, seq, gw_node) < 0) 523 continue; 524 525 gw_count++; 526 } 527 rcu_read_unlock(); 528 529 if (gw_count == 0) 530 seq_puts(seq, "No gateways in range ...\n"); 531 532 out: 533 if (primary_if) 534 batadv_hardif_free_ref(primary_if); 535 return 0; 536 } 537 538 /* this call might reallocate skb data */ 539 static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len) 540 { 541 int ret = false; 542 unsigned char *p; 543 int pkt_len; 544 545 if (skb_linearize(skb) < 0) 546 goto out; 547 548 pkt_len = skb_headlen(skb); 549 550 if (pkt_len < header_len + BATADV_DHCP_OPTIONS_OFFSET + 1) 551 goto out; 552 553 p = skb->data + header_len + BATADV_DHCP_OPTIONS_OFFSET; 554 pkt_len -= header_len + BATADV_DHCP_OPTIONS_OFFSET + 1; 555 556 /* Access the dhcp option lists. Each entry is made up by: 557 * - octet 1: option type 558 * - octet 2: option data len (only if type != 255 and 0) 559 * - octet 3: option data 560 */ 561 while (*p != 255 && !ret) { 562 /* p now points to the first octet: option type */ 563 if (*p == 53) { 564 /* type 53 is the message type option. 565 * Jump the len octet and go to the data octet 566 */ 567 if (pkt_len < 2) 568 goto out; 569 p += 2; 570 571 /* check if the message type is what we need */ 572 if (*p == BATADV_DHCP_REQUEST) 573 ret = true; 574 break; 575 } else if (*p == 0) { 576 /* option type 0 (padding), just go forward */ 577 if (pkt_len < 1) 578 goto out; 579 pkt_len--; 580 p++; 581 } else { 582 /* This is any other option. So we get the length... */ 583 if (pkt_len < 1) 584 goto out; 585 pkt_len--; 586 p++; 587 588 /* ...and then we jump over the data */ 589 if (pkt_len < 1 + (*p)) 590 goto out; 591 pkt_len -= 1 + (*p); 592 p += 1 + (*p); 593 } 594 } 595 out: 596 return ret; 597 } 598 599 /* this call might reallocate skb data */ 600 bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len) 601 { 602 struct ethhdr *ethhdr; 603 struct iphdr *iphdr; 604 struct ipv6hdr *ipv6hdr; 605 struct udphdr *udphdr; 606 607 /* check for ethernet header */ 608 if (!pskb_may_pull(skb, *header_len + ETH_HLEN)) 609 return false; 610 ethhdr = (struct ethhdr *)skb->data; 611 *header_len += ETH_HLEN; 612 613 /* check for initial vlan header */ 614 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { 615 if (!pskb_may_pull(skb, *header_len + VLAN_HLEN)) 616 return false; 617 ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); 618 *header_len += VLAN_HLEN; 619 } 620 621 /* check for ip header */ 622 switch (ntohs(ethhdr->h_proto)) { 623 case ETH_P_IP: 624 if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr))) 625 return false; 626 iphdr = (struct iphdr *)(skb->data + *header_len); 627 *header_len += iphdr->ihl * 4; 628 629 /* check for udp header */ 630 if (iphdr->protocol != IPPROTO_UDP) 631 return false; 632 633 break; 634 case ETH_P_IPV6: 635 if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr))) 636 return false; 637 ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len); 638 *header_len += sizeof(*ipv6hdr); 639 640 /* check for udp header */ 641 if (ipv6hdr->nexthdr != IPPROTO_UDP) 642 return false; 643 644 break; 645 default: 646 return false; 647 } 648 649 if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr))) 650 return false; 651 652 /* skb->data might have been reallocated by pskb_may_pull() */ 653 ethhdr = (struct ethhdr *)skb->data; 654 if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) 655 ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); 656 657 udphdr = (struct udphdr *)(skb->data + *header_len); 658 *header_len += sizeof(*udphdr); 659 660 /* check for bootp port */ 661 if ((ntohs(ethhdr->h_proto) == ETH_P_IP) && 662 (ntohs(udphdr->dest) != 67)) 663 return false; 664 665 if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) && 666 (ntohs(udphdr->dest) != 547)) 667 return false; 668 669 return true; 670 } 671 672 /* this call might reallocate skb data */ 673 bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, 674 struct sk_buff *skb) 675 { 676 struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; 677 struct batadv_orig_node *orig_dst_node = NULL; 678 struct batadv_gw_node *curr_gw = NULL; 679 struct ethhdr *ethhdr; 680 bool ret, out_of_range = false; 681 unsigned int header_len = 0; 682 uint8_t curr_tq_avg; 683 684 ret = batadv_gw_is_dhcp_target(skb, &header_len); 685 if (!ret) 686 goto out; 687 688 ethhdr = (struct ethhdr *)skb->data; 689 orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source, 690 ethhdr->h_dest); 691 if (!orig_dst_node) 692 goto out; 693 694 if (!orig_dst_node->gw_flags) 695 goto out; 696 697 ret = batadv_is_type_dhcprequest(skb, header_len); 698 if (!ret) 699 goto out; 700 701 switch (atomic_read(&bat_priv->gw_mode)) { 702 case BATADV_GW_MODE_SERVER: 703 /* If we are a GW then we are our best GW. We can artificially 704 * set the tq towards ourself as the maximum value 705 */ 706 curr_tq_avg = BATADV_TQ_MAX_VALUE; 707 break; 708 case BATADV_GW_MODE_CLIENT: 709 curr_gw = batadv_gw_get_selected_gw_node(bat_priv); 710 if (!curr_gw) 711 goto out; 712 713 /* packet is going to our gateway */ 714 if (curr_gw->orig_node == orig_dst_node) 715 goto out; 716 717 /* If the dhcp packet has been sent to a different gw, 718 * we have to evaluate whether the old gw is still 719 * reliable enough 720 */ 721 neigh_curr = batadv_find_router(bat_priv, curr_gw->orig_node, 722 NULL); 723 if (!neigh_curr) 724 goto out; 725 726 curr_tq_avg = neigh_curr->tq_avg; 727 break; 728 case BATADV_GW_MODE_OFF: 729 default: 730 goto out; 731 } 732 733 neigh_old = batadv_find_router(bat_priv, orig_dst_node, NULL); 734 if (!neigh_old) 735 goto out; 736 737 if (curr_tq_avg - neigh_old->tq_avg > BATADV_GW_THRESHOLD) 738 out_of_range = true; 739 740 out: 741 if (orig_dst_node) 742 batadv_orig_node_free_ref(orig_dst_node); 743 if (curr_gw) 744 batadv_gw_node_free_ref(curr_gw); 745 if (neigh_old) 746 batadv_neigh_node_free_ref(neigh_old); 747 if (neigh_curr) 748 batadv_neigh_node_free_ref(neigh_curr); 749 return out_of_range; 750 } 751