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