hc
2024-02-19 1c055e55a242a33e574e48be530e06770a210dcd
kernel/net/batman-adv/distributed-arp-table.c
....@@ -1,24 +1,13 @@
11 // SPDX-License-Identifier: GPL-2.0
2
-/* Copyright (C) 2011-2018 B.A.T.M.A.N. contributors:
2
+/* Copyright (C) 2011-2020 B.A.T.M.A.N. contributors:
33 *
44 * Antonio Quartulli
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of version 2 of the GNU General Public
8
- * License as published by the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope that it will be useful, but
11
- * WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
175 */
186
197 #include "distributed-arp-table.h"
208 #include "main.h"
219
10
+#include <asm/unaligned.h>
2211 #include <linux/atomic.h>
2312 #include <linux/bitops.h>
2413 #include <linux/byteorder/generic.h>
....@@ -29,6 +18,7 @@
2918 #include <linux/if_ether.h>
3019 #include <linux/if_vlan.h>
3120 #include <linux/in.h>
21
+#include <linux/ip.h>
3222 #include <linux/jiffies.h>
3323 #include <linux/kernel.h>
3424 #include <linux/kref.h>
....@@ -42,6 +32,7 @@
4232 #include <linux/spinlock.h>
4333 #include <linux/stddef.h>
4434 #include <linux/string.h>
35
+#include <linux/udp.h>
4536 #include <linux/workqueue.h>
4637 #include <net/arp.h>
4738 #include <net/genetlink.h>
....@@ -60,6 +51,49 @@
6051 #include "translation-table.h"
6152 #include "tvlv.h"
6253
54
+enum batadv_bootpop {
55
+ BATADV_BOOTREPLY = 2,
56
+};
57
+
58
+enum batadv_boothtype {
59
+ BATADV_HTYPE_ETHERNET = 1,
60
+};
61
+
62
+enum batadv_dhcpoptioncode {
63
+ BATADV_DHCP_OPT_PAD = 0,
64
+ BATADV_DHCP_OPT_MSG_TYPE = 53,
65
+ BATADV_DHCP_OPT_END = 255,
66
+};
67
+
68
+enum batadv_dhcptype {
69
+ BATADV_DHCPACK = 5,
70
+};
71
+
72
+/* { 99, 130, 83, 99 } */
73
+#define BATADV_DHCP_MAGIC 1669485411
74
+
75
+struct batadv_dhcp_packet {
76
+ __u8 op;
77
+ __u8 htype;
78
+ __u8 hlen;
79
+ __u8 hops;
80
+ __be32 xid;
81
+ __be16 secs;
82
+ __be16 flags;
83
+ __be32 ciaddr;
84
+ __be32 yiaddr;
85
+ __be32 siaddr;
86
+ __be32 giaddr;
87
+ __u8 chaddr[16];
88
+ __u8 sname[64];
89
+ __u8 file[128];
90
+ __be32 magic;
91
+ __u8 options[];
92
+};
93
+
94
+#define BATADV_DHCP_YIADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->yiaddr)
95
+#define BATADV_DHCP_CHADDR_LEN sizeof(((struct batadv_dhcp_packet *)0)->chaddr)
96
+
6397 static void batadv_dat_purge(struct work_struct *work);
6498
6599 /**
....@@ -68,7 +102,6 @@
68102 */
69103 static void batadv_dat_start_timer(struct batadv_priv *bat_priv)
70104 {
71
- INIT_DELAYED_WORK(&bat_priv->dat.work, batadv_dat_purge);
72105 queue_delayed_work(batadv_event_workqueue, &bat_priv->dat.work,
73106 msecs_to_jiffies(10000));
74107 }
....@@ -94,6 +127,9 @@
94127 */
95128 static void batadv_dat_entry_put(struct batadv_dat_entry *dat_entry)
96129 {
130
+ if (!dat_entry)
131
+ return;
132
+
97133 kref_put(&dat_entry->refcount, batadv_dat_entry_release);
98134 }
99135
....@@ -212,7 +248,7 @@
212248 */
213249 static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size)
214250 {
215
- return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN);
251
+ return *(__force __be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN);
216252 }
217253
218254 /**
....@@ -236,7 +272,9 @@
236272 */
237273 static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
238274 {
239
- return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4);
275
+ u8 *dst = batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4;
276
+
277
+ return *(__force __be32 *)dst;
240278 }
241279
242280 /**
....@@ -254,7 +292,7 @@
254292 __be16 vid;
255293 u32 i;
256294
257
- key = (const unsigned char *)&dat->ip;
295
+ key = (__force const unsigned char *)&dat->ip;
258296 for (i = 0; i < sizeof(dat->ip); i++) {
259297 hash += key[i];
260298 hash += (hash << 10);
....@@ -623,22 +661,22 @@
623661 }
624662
625663 /**
626
- * batadv_dat_send_data() - send a payload to the selected candidates
664
+ * batadv_dat_forward_data() - copy and send payload to the selected candidates
627665 * @bat_priv: the bat priv with all the soft interface information
628666 * @skb: payload to send
629667 * @ip: the DHT key
630668 * @vid: VLAN identifier
631669 * @packet_subtype: unicast4addr packet subtype to use
632670 *
633
- * This function copies the skb with pskb_copy() and is sent as unicast packet
671
+ * This function copies the skb with pskb_copy() and is sent as a unicast packet
634672 * to each of the selected candidates.
635673 *
636674 * Return: true if the packet is sent to at least one candidate, false
637675 * otherwise.
638676 */
639
-static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
640
- struct sk_buff *skb, __be32 ip,
641
- unsigned short vid, int packet_subtype)
677
+static bool batadv_dat_forward_data(struct batadv_priv *bat_priv,
678
+ struct sk_buff *skb, __be32 ip,
679
+ unsigned short vid, int packet_subtype)
642680 {
643681 int i;
644682 bool ret = false;
....@@ -783,6 +821,7 @@
783821 if (!bat_priv->dat.hash)
784822 return -ENOMEM;
785823
824
+ INIT_DELAYED_WORK(&bat_priv->dat.work, batadv_dat_purge);
786825 batadv_dat_start_timer(bat_priv);
787826
788827 batadv_tvlv_handler_register(bat_priv, batadv_dat_tvlv_ogm_handler_v1,
....@@ -865,22 +904,26 @@
865904 * netlink socket
866905 * @msg: buffer for the message
867906 * @portid: netlink port
868
- * @seq: Sequence number of netlink message
907
+ * @cb: Control block containing additional options
869908 * @dat_entry: entry to dump
870909 *
871910 * Return: 0 or error code.
872911 */
873912 static int
874
-batadv_dat_cache_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
913
+batadv_dat_cache_dump_entry(struct sk_buff *msg, u32 portid,
914
+ struct netlink_callback *cb,
875915 struct batadv_dat_entry *dat_entry)
876916 {
877917 int msecs;
878918 void *hdr;
879919
880
- hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
881
- NLM_F_MULTI, BATADV_CMD_GET_DAT_CACHE);
920
+ hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
921
+ &batadv_netlink_family, NLM_F_MULTI,
922
+ BATADV_CMD_GET_DAT_CACHE);
882923 if (!hdr)
883924 return -ENOBUFS;
925
+
926
+ genl_dump_check_consistent(cb, hdr);
884927
885928 msecs = jiffies_to_msecs(jiffies - dat_entry->last_update);
886929
....@@ -903,27 +946,31 @@
903946 * a netlink socket
904947 * @msg: buffer for the message
905948 * @portid: netlink port
906
- * @seq: Sequence number of netlink message
907
- * @head: bucket to dump
949
+ * @cb: Control block containing additional options
950
+ * @hash: hash to dump
951
+ * @bucket: bucket index to dump
908952 * @idx_skip: How many entries to skip
909953 *
910954 * Return: 0 or error code.
911955 */
912956 static int
913
-batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
914
- struct hlist_head *head, int *idx_skip)
957
+batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid,
958
+ struct netlink_callback *cb,
959
+ struct batadv_hashtable *hash, unsigned int bucket,
960
+ int *idx_skip)
915961 {
916962 struct batadv_dat_entry *dat_entry;
917963 int idx = 0;
918964
919
- rcu_read_lock();
920
- hlist_for_each_entry_rcu(dat_entry, head, hash_entry) {
965
+ spin_lock_bh(&hash->list_locks[bucket]);
966
+ cb->seq = atomic_read(&hash->generation) << 1 | 1;
967
+
968
+ hlist_for_each_entry(dat_entry, &hash->table[bucket], hash_entry) {
921969 if (idx < *idx_skip)
922970 goto skip;
923971
924
- if (batadv_dat_cache_dump_entry(msg, portid, seq,
925
- dat_entry)) {
926
- rcu_read_unlock();
972
+ if (batadv_dat_cache_dump_entry(msg, portid, cb, dat_entry)) {
973
+ spin_unlock_bh(&hash->list_locks[bucket]);
927974 *idx_skip = idx;
928975
929976 return -EMSGSIZE;
....@@ -932,7 +979,7 @@
932979 skip:
933980 idx++;
934981 }
935
- rcu_read_unlock();
982
+ spin_unlock_bh(&hash->list_locks[bucket]);
936983
937984 return 0;
938985 }
....@@ -953,7 +1000,6 @@
9531000 struct batadv_hashtable *hash;
9541001 struct batadv_priv *bat_priv;
9551002 int bucket = cb->args[0];
956
- struct hlist_head *head;
9571003 int idx = cb->args[1];
9581004 int ifindex;
9591005 int ret = 0;
....@@ -979,10 +1025,7 @@
9791025 }
9801026
9811027 while (bucket < hash->size) {
982
- head = &hash->table[bucket];
983
-
984
- if (batadv_dat_cache_dump_bucket(msg, portid,
985
- cb->nlh->nlmsg_seq, head,
1028
+ if (batadv_dat_cache_dump_bucket(msg, portid, cb, hash, bucket,
9861029 &idx))
9871030 break;
9881031
....@@ -1229,8 +1272,8 @@
12291272 ret = true;
12301273 } else {
12311274 /* Send the request to the DHT */
1232
- ret = batadv_dat_send_data(bat_priv, skb, ip_dst, vid,
1233
- BATADV_P_DAT_DHT_GET);
1275
+ ret = batadv_dat_forward_data(bat_priv, skb, ip_dst, vid,
1276
+ BATADV_P_DAT_DHT_GET);
12341277 }
12351278 out:
12361279 if (dat_entry)
....@@ -1344,8 +1387,10 @@
13441387 /* Send the ARP reply to the candidates for both the IP addresses that
13451388 * the node obtained from the ARP reply
13461389 */
1347
- batadv_dat_send_data(bat_priv, skb, ip_src, vid, BATADV_P_DAT_DHT_PUT);
1348
- batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT);
1390
+ batadv_dat_forward_data(bat_priv, skb, ip_src, vid,
1391
+ BATADV_P_DAT_DHT_PUT);
1392
+ batadv_dat_forward_data(bat_priv, skb, ip_dst, vid,
1393
+ BATADV_P_DAT_DHT_PUT);
13491394 }
13501395
13511396 /**
....@@ -1440,6 +1485,363 @@
14401485 }
14411486
14421487 /**
1488
+ * batadv_dat_check_dhcp_ipudp() - check skb for IP+UDP headers valid for DHCP
1489
+ * @skb: the packet to check
1490
+ * @ip_src: a buffer to store the IPv4 source address in
1491
+ *
1492
+ * Checks whether the given skb has an IP and UDP header valid for a DHCP
1493
+ * message from a DHCP server. And if so, stores the IPv4 source address in
1494
+ * the provided buffer.
1495
+ *
1496
+ * Return: True if valid, false otherwise.
1497
+ */
1498
+static bool
1499
+batadv_dat_check_dhcp_ipudp(struct sk_buff *skb, __be32 *ip_src)
1500
+{
1501
+ unsigned int offset = skb_network_offset(skb);
1502
+ struct udphdr *udphdr, _udphdr;
1503
+ struct iphdr *iphdr, _iphdr;
1504
+
1505
+ iphdr = skb_header_pointer(skb, offset, sizeof(_iphdr), &_iphdr);
1506
+ if (!iphdr || iphdr->version != 4 || iphdr->ihl * 4 < sizeof(_iphdr))
1507
+ return false;
1508
+
1509
+ if (iphdr->protocol != IPPROTO_UDP)
1510
+ return false;
1511
+
1512
+ offset += iphdr->ihl * 4;
1513
+ skb_set_transport_header(skb, offset);
1514
+
1515
+ udphdr = skb_header_pointer(skb, offset, sizeof(_udphdr), &_udphdr);
1516
+ if (!udphdr || udphdr->source != htons(67))
1517
+ return false;
1518
+
1519
+ *ip_src = get_unaligned(&iphdr->saddr);
1520
+
1521
+ return true;
1522
+}
1523
+
1524
+/**
1525
+ * batadv_dat_check_dhcp() - examine packet for valid DHCP message
1526
+ * @skb: the packet to check
1527
+ * @proto: ethernet protocol hint (behind a potential vlan)
1528
+ * @ip_src: a buffer to store the IPv4 source address in
1529
+ *
1530
+ * Checks whether the given skb is a valid DHCP packet. And if so, stores the
1531
+ * IPv4 source address in the provided buffer.
1532
+ *
1533
+ * Caller needs to ensure that the skb network header is set correctly.
1534
+ *
1535
+ * Return: If skb is a valid DHCP packet, then returns its op code
1536
+ * (e.g. BOOTREPLY vs. BOOTREQUEST). Otherwise returns -EINVAL.
1537
+ */
1538
+static int
1539
+batadv_dat_check_dhcp(struct sk_buff *skb, __be16 proto, __be32 *ip_src)
1540
+{
1541
+ __be32 *magic, _magic;
1542
+ unsigned int offset;
1543
+ struct {
1544
+ __u8 op;
1545
+ __u8 htype;
1546
+ __u8 hlen;
1547
+ __u8 hops;
1548
+ } *dhcp_h, _dhcp_h;
1549
+
1550
+ if (proto != htons(ETH_P_IP))
1551
+ return -EINVAL;
1552
+
1553
+ if (!batadv_dat_check_dhcp_ipudp(skb, ip_src))
1554
+ return -EINVAL;
1555
+
1556
+ offset = skb_transport_offset(skb) + sizeof(struct udphdr);
1557
+ if (skb->len < offset + sizeof(struct batadv_dhcp_packet))
1558
+ return -EINVAL;
1559
+
1560
+ dhcp_h = skb_header_pointer(skb, offset, sizeof(_dhcp_h), &_dhcp_h);
1561
+ if (!dhcp_h || dhcp_h->htype != BATADV_HTYPE_ETHERNET ||
1562
+ dhcp_h->hlen != ETH_ALEN)
1563
+ return -EINVAL;
1564
+
1565
+ offset += offsetof(struct batadv_dhcp_packet, magic);
1566
+
1567
+ magic = skb_header_pointer(skb, offset, sizeof(_magic), &_magic);
1568
+ if (!magic || get_unaligned(magic) != htonl(BATADV_DHCP_MAGIC))
1569
+ return -EINVAL;
1570
+
1571
+ return dhcp_h->op;
1572
+}
1573
+
1574
+/**
1575
+ * batadv_dat_get_dhcp_message_type() - get message type of a DHCP packet
1576
+ * @skb: the DHCP packet to parse
1577
+ *
1578
+ * Iterates over the DHCP options of the given DHCP packet to find a
1579
+ * DHCP Message Type option and parse it.
1580
+ *
1581
+ * Caller needs to ensure that the given skb is a valid DHCP packet and
1582
+ * that the skb transport header is set correctly.
1583
+ *
1584
+ * Return: The found DHCP message type value, if found. -EINVAL otherwise.
1585
+ */
1586
+static int batadv_dat_get_dhcp_message_type(struct sk_buff *skb)
1587
+{
1588
+ unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr);
1589
+ u8 *type, _type;
1590
+ struct {
1591
+ u8 type;
1592
+ u8 len;
1593
+ } *tl, _tl;
1594
+
1595
+ offset += sizeof(struct batadv_dhcp_packet);
1596
+
1597
+ while ((tl = skb_header_pointer(skb, offset, sizeof(_tl), &_tl))) {
1598
+ if (tl->type == BATADV_DHCP_OPT_MSG_TYPE)
1599
+ break;
1600
+
1601
+ if (tl->type == BATADV_DHCP_OPT_END)
1602
+ break;
1603
+
1604
+ if (tl->type == BATADV_DHCP_OPT_PAD)
1605
+ offset++;
1606
+ else
1607
+ offset += tl->len + sizeof(_tl);
1608
+ }
1609
+
1610
+ /* Option Overload Code not supported */
1611
+ if (!tl || tl->type != BATADV_DHCP_OPT_MSG_TYPE ||
1612
+ tl->len != sizeof(_type))
1613
+ return -EINVAL;
1614
+
1615
+ offset += sizeof(_tl);
1616
+
1617
+ type = skb_header_pointer(skb, offset, sizeof(_type), &_type);
1618
+ if (!type)
1619
+ return -EINVAL;
1620
+
1621
+ return *type;
1622
+}
1623
+
1624
+/**
1625
+ * batadv_dat_get_dhcp_yiaddr() - get yiaddr from a DHCP packet
1626
+ * @skb: the DHCP packet to parse
1627
+ * @buf: a buffer to store the yiaddr in
1628
+ *
1629
+ * Caller needs to ensure that the given skb is a valid DHCP packet and
1630
+ * that the skb transport header is set correctly.
1631
+ *
1632
+ * Return: True on success, false otherwise.
1633
+ */
1634
+static bool batadv_dat_dhcp_get_yiaddr(struct sk_buff *skb, __be32 *buf)
1635
+{
1636
+ unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr);
1637
+ __be32 *yiaddr;
1638
+
1639
+ offset += offsetof(struct batadv_dhcp_packet, yiaddr);
1640
+ yiaddr = skb_header_pointer(skb, offset, BATADV_DHCP_YIADDR_LEN, buf);
1641
+
1642
+ if (!yiaddr)
1643
+ return false;
1644
+
1645
+ if (yiaddr != buf)
1646
+ *buf = get_unaligned(yiaddr);
1647
+
1648
+ return true;
1649
+}
1650
+
1651
+/**
1652
+ * batadv_dat_get_dhcp_chaddr() - get chaddr from a DHCP packet
1653
+ * @skb: the DHCP packet to parse
1654
+ * @buf: a buffer to store the chaddr in
1655
+ *
1656
+ * Caller needs to ensure that the given skb is a valid DHCP packet and
1657
+ * that the skb transport header is set correctly.
1658
+ *
1659
+ * Return: True on success, false otherwise
1660
+ */
1661
+static bool batadv_dat_get_dhcp_chaddr(struct sk_buff *skb, u8 *buf)
1662
+{
1663
+ unsigned int offset = skb_transport_offset(skb) + sizeof(struct udphdr);
1664
+ u8 *chaddr;
1665
+
1666
+ offset += offsetof(struct batadv_dhcp_packet, chaddr);
1667
+ chaddr = skb_header_pointer(skb, offset, BATADV_DHCP_CHADDR_LEN, buf);
1668
+
1669
+ if (!chaddr)
1670
+ return false;
1671
+
1672
+ if (chaddr != buf)
1673
+ memcpy(buf, chaddr, BATADV_DHCP_CHADDR_LEN);
1674
+
1675
+ return true;
1676
+}
1677
+
1678
+/**
1679
+ * batadv_dat_put_dhcp() - puts addresses from a DHCP packet into the DHT and
1680
+ * DAT cache
1681
+ * @bat_priv: the bat priv with all the soft interface information
1682
+ * @chaddr: the DHCP client MAC address
1683
+ * @yiaddr: the DHCP client IP address
1684
+ * @hw_dst: the DHCP server MAC address
1685
+ * @ip_dst: the DHCP server IP address
1686
+ * @vid: VLAN identifier
1687
+ *
1688
+ * Adds given MAC/IP pairs to the local DAT cache and propagates them further
1689
+ * into the DHT.
1690
+ *
1691
+ * For the DHT propagation, client MAC + IP will appear as the ARP Reply
1692
+ * transmitter (and hw_dst/ip_dst as the target).
1693
+ */
1694
+static void batadv_dat_put_dhcp(struct batadv_priv *bat_priv, u8 *chaddr,
1695
+ __be32 yiaddr, u8 *hw_dst, __be32 ip_dst,
1696
+ unsigned short vid)
1697
+{
1698
+ struct sk_buff *skb;
1699
+
1700
+ skb = batadv_dat_arp_create_reply(bat_priv, yiaddr, ip_dst, chaddr,
1701
+ hw_dst, vid);
1702
+ if (!skb)
1703
+ return;
1704
+
1705
+ skb_set_network_header(skb, ETH_HLEN);
1706
+
1707
+ batadv_dat_entry_add(bat_priv, yiaddr, chaddr, vid);
1708
+ batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
1709
+
1710
+ batadv_dat_forward_data(bat_priv, skb, yiaddr, vid,
1711
+ BATADV_P_DAT_DHT_PUT);
1712
+ batadv_dat_forward_data(bat_priv, skb, ip_dst, vid,
1713
+ BATADV_P_DAT_DHT_PUT);
1714
+
1715
+ consume_skb(skb);
1716
+
1717
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
1718
+ "Snooped from outgoing DHCPACK (server address): %pI4, %pM (vid: %i)\n",
1719
+ &ip_dst, hw_dst, batadv_print_vid(vid));
1720
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
1721
+ "Snooped from outgoing DHCPACK (client address): %pI4, %pM (vid: %i)\n",
1722
+ &yiaddr, chaddr, batadv_print_vid(vid));
1723
+}
1724
+
1725
+/**
1726
+ * batadv_dat_check_dhcp_ack() - examine packet for valid DHCP message
1727
+ * @skb: the packet to check
1728
+ * @proto: ethernet protocol hint (behind a potential vlan)
1729
+ * @ip_src: a buffer to store the IPv4 source address in
1730
+ * @chaddr: a buffer to store the DHCP Client Hardware Address in
1731
+ * @yiaddr: a buffer to store the DHCP Your IP Address in
1732
+ *
1733
+ * Checks whether the given skb is a valid DHCPACK. And if so, stores the
1734
+ * IPv4 server source address (ip_src), client MAC address (chaddr) and client
1735
+ * IPv4 address (yiaddr) in the provided buffers.
1736
+ *
1737
+ * Caller needs to ensure that the skb network header is set correctly.
1738
+ *
1739
+ * Return: True if the skb is a valid DHCPACK. False otherwise.
1740
+ */
1741
+static bool
1742
+batadv_dat_check_dhcp_ack(struct sk_buff *skb, __be16 proto, __be32 *ip_src,
1743
+ u8 *chaddr, __be32 *yiaddr)
1744
+{
1745
+ int type;
1746
+
1747
+ type = batadv_dat_check_dhcp(skb, proto, ip_src);
1748
+ if (type != BATADV_BOOTREPLY)
1749
+ return false;
1750
+
1751
+ type = batadv_dat_get_dhcp_message_type(skb);
1752
+ if (type != BATADV_DHCPACK)
1753
+ return false;
1754
+
1755
+ if (!batadv_dat_dhcp_get_yiaddr(skb, yiaddr))
1756
+ return false;
1757
+
1758
+ if (!batadv_dat_get_dhcp_chaddr(skb, chaddr))
1759
+ return false;
1760
+
1761
+ return true;
1762
+}
1763
+
1764
+/**
1765
+ * batadv_dat_snoop_outgoing_dhcp_ack() - snoop DHCPACK and fill DAT with it
1766
+ * @bat_priv: the bat priv with all the soft interface information
1767
+ * @skb: the packet to snoop
1768
+ * @proto: ethernet protocol hint (behind a potential vlan)
1769
+ * @vid: VLAN identifier
1770
+ *
1771
+ * This function first checks whether the given skb is a valid DHCPACK. If
1772
+ * so then its source MAC and IP as well as its DHCP Client Hardware Address
1773
+ * field and DHCP Your IP Address field are added to the local DAT cache and
1774
+ * propagated into the DHT.
1775
+ *
1776
+ * Caller needs to ensure that the skb mac and network headers are set
1777
+ * correctly.
1778
+ */
1779
+void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv,
1780
+ struct sk_buff *skb,
1781
+ __be16 proto,
1782
+ unsigned short vid)
1783
+{
1784
+ u8 chaddr[BATADV_DHCP_CHADDR_LEN];
1785
+ __be32 ip_src, yiaddr;
1786
+
1787
+ if (!atomic_read(&bat_priv->distributed_arp_table))
1788
+ return;
1789
+
1790
+ if (!batadv_dat_check_dhcp_ack(skb, proto, &ip_src, chaddr, &yiaddr))
1791
+ return;
1792
+
1793
+ batadv_dat_put_dhcp(bat_priv, chaddr, yiaddr, eth_hdr(skb)->h_source,
1794
+ ip_src, vid);
1795
+}
1796
+
1797
+/**
1798
+ * batadv_dat_snoop_incoming_dhcp_ack() - snoop DHCPACK and fill DAT cache
1799
+ * @bat_priv: the bat priv with all the soft interface information
1800
+ * @skb: the packet to snoop
1801
+ * @hdr_size: header size, up to the tail of the batman-adv header
1802
+ *
1803
+ * This function first checks whether the given skb is a valid DHCPACK. If
1804
+ * so then its source MAC and IP as well as its DHCP Client Hardware Address
1805
+ * field and DHCP Your IP Address field are added to the local DAT cache.
1806
+ */
1807
+void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv,
1808
+ struct sk_buff *skb, int hdr_size)
1809
+{
1810
+ u8 chaddr[BATADV_DHCP_CHADDR_LEN];
1811
+ struct ethhdr *ethhdr;
1812
+ __be32 ip_src, yiaddr;
1813
+ unsigned short vid;
1814
+ __be16 proto;
1815
+ u8 *hw_src;
1816
+
1817
+ if (!atomic_read(&bat_priv->distributed_arp_table))
1818
+ return;
1819
+
1820
+ if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN)))
1821
+ return;
1822
+
1823
+ ethhdr = (struct ethhdr *)(skb->data + hdr_size);
1824
+ skb_set_network_header(skb, hdr_size + ETH_HLEN);
1825
+ proto = ethhdr->h_proto;
1826
+
1827
+ if (!batadv_dat_check_dhcp_ack(skb, proto, &ip_src, chaddr, &yiaddr))
1828
+ return;
1829
+
1830
+ hw_src = ethhdr->h_source;
1831
+ vid = batadv_dat_get_vid(skb, &hdr_size);
1832
+
1833
+ batadv_dat_entry_add(bat_priv, yiaddr, chaddr, vid);
1834
+ batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
1835
+
1836
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
1837
+ "Snooped from incoming DHCPACK (server address): %pI4, %pM (vid: %i)\n",
1838
+ &ip_src, hw_src, batadv_print_vid(vid));
1839
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
1840
+ "Snooped from incoming DHCPACK (client address): %pI4, %pM (vid: %i)\n",
1841
+ &yiaddr, chaddr, batadv_print_vid(vid));
1842
+}
1843
+
1844
+/**
14431845 * batadv_dat_drop_broadcast_packet() - check if an ARP request has to be
14441846 * dropped (because the node has already obtained the reply via DAT) or not
14451847 * @bat_priv: the bat priv with all the soft interface information