diff options
| -rw-r--r-- | net/batman-adv/Kconfig | 4 | ||||
| -rw-r--r-- | net/batman-adv/distributed-arp-table.c | 202 | ||||
| -rw-r--r-- | net/batman-adv/distributed-arp-table.h | 2 | ||||
| -rw-r--r-- | net/batman-adv/packet.h | 8 |
4 files changed, 213 insertions, 3 deletions
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig index 53f5244e28f8..e77f805d38da 100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | config BATMAN_ADV | 5 | config BATMAN_ADV |
| 6 | tristate "B.A.T.M.A.N. Advanced Meshing Protocol" | 6 | tristate "B.A.T.M.A.N. Advanced Meshing Protocol" |
| 7 | depends on NET | 7 | depends on NET && INET |
| 8 | select CRC16 | 8 | select CRC16 |
| 9 | default n | 9 | default n |
| 10 | help | 10 | help |
| @@ -16,7 +16,7 @@ config BATMAN_ADV | |||
| 16 | 16 | ||
| 17 | config BATMAN_ADV_BLA | 17 | config BATMAN_ADV_BLA |
| 18 | bool "Bridge Loop Avoidance" | 18 | bool "Bridge Loop Avoidance" |
| 19 | depends on BATMAN_ADV && INET | 19 | depends on BATMAN_ADV |
| 20 | default y | 20 | default y |
| 21 | help | 21 | help |
| 22 | This option enables BLA (Bridge Loop Avoidance), a mechanism | 22 | This option enables BLA (Bridge Loop Avoidance), a mechanism |
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 2ef90e3ea2c4..49a213ce2aac 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/if_arp.h> | 21 | #include <linux/if_arp.h> |
| 22 | 22 | ||
| 23 | #include "main.h" | 23 | #include "main.h" |
| 24 | #include "hash.h" | ||
| 24 | #include "distributed-arp-table.h" | 25 | #include "distributed-arp-table.h" |
| 25 | #include "hard-interface.h" | 26 | #include "hard-interface.h" |
| 26 | #include "originator.h" | 27 | #include "originator.h" |
| @@ -142,6 +143,59 @@ static int batadv_compare_dat(const struct hlist_node *node, const void *data2) | |||
| 142 | } | 143 | } |
| 143 | 144 | ||
| 144 | /** | 145 | /** |
| 146 | * batadv_arp_hw_src - extract the hw_src field from an ARP packet | ||
| 147 | * @skb: ARP packet | ||
| 148 | * @hdr_size: size of the possible header before the ARP packet | ||
| 149 | * | ||
| 150 | * Returns the value of the hw_src field in the ARP packet | ||
| 151 | */ | ||
| 152 | static uint8_t *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size) | ||
| 153 | { | ||
| 154 | uint8_t *addr; | ||
| 155 | |||
| 156 | addr = (uint8_t *)(skb->data + hdr_size); | ||
| 157 | addr += ETH_HLEN + sizeof(struct arphdr); | ||
| 158 | |||
| 159 | return addr; | ||
| 160 | } | ||
| 161 | |||
| 162 | /** | ||
| 163 | * batadv_arp_ip_src - extract the ip_src field from an ARP packet | ||
| 164 | * @skb: ARP packet | ||
| 165 | * @hdr_size: size of the possible header before the ARP packet | ||
| 166 | * | ||
| 167 | * Returns the value of the ip_src field in the ARP packet | ||
| 168 | */ | ||
| 169 | static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size) | ||
| 170 | { | ||
| 171 | return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN); | ||
| 172 | } | ||
| 173 | |||
| 174 | /** | ||
| 175 | * batadv_arp_hw_dst - extract the hw_dst field from an ARP packet | ||
| 176 | * @skb: ARP packet | ||
| 177 | * @hdr_size: size of the possible header before the ARP packet | ||
| 178 | * | ||
| 179 | * Returns the value of the hw_dst field in the ARP packet | ||
| 180 | */ | ||
| 181 | static uint8_t *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size) | ||
| 182 | { | ||
| 183 | return batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN + 4; | ||
| 184 | } | ||
| 185 | |||
| 186 | /** | ||
| 187 | * batadv_arp_ip_dst - extract the ip_dst field from an ARP packet | ||
| 188 | * @skb: ARP packet | ||
| 189 | * @hdr_size: size of the possible header before the ARP packet | ||
| 190 | * | ||
| 191 | * Returns the value of the ip_dst field in the ARP packet | ||
| 192 | */ | ||
| 193 | static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size) | ||
| 194 | { | ||
| 195 | return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4); | ||
| 196 | } | ||
| 197 | |||
| 198 | /** | ||
| 145 | * batadv_hash_dat - compute the hash value for an IP address | 199 | * batadv_hash_dat - compute the hash value for an IP address |
| 146 | * @data: data to hash | 200 | * @data: data to hash |
| 147 | * @size: size of the hash table | 201 | * @size: size of the hash table |
| @@ -257,6 +311,93 @@ out: | |||
| 257 | batadv_dat_entry_free_ref(dat_entry); | 311 | batadv_dat_entry_free_ref(dat_entry); |
| 258 | } | 312 | } |
| 259 | 313 | ||
| 314 | #ifdef CONFIG_BATMAN_ADV_DEBUG | ||
| 315 | |||
| 316 | /** | ||
| 317 | * batadv_dbg_arp - print a debug message containing all the ARP packet details | ||
| 318 | * @bat_priv: the bat priv with all the soft interface information | ||
| 319 | * @skb: ARP packet | ||
| 320 | * @type: ARP type | ||
| 321 | * @hdr_size: size of the possible header before the ARP packet | ||
| 322 | * @msg: message to print together with the debugging information | ||
| 323 | */ | ||
| 324 | static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||
| 325 | uint16_t type, int hdr_size, char *msg) | ||
| 326 | { | ||
| 327 | struct batadv_unicast_4addr_packet *unicast_4addr_packet; | ||
| 328 | struct batadv_bcast_packet *bcast_pkt; | ||
| 329 | uint8_t *orig_addr; | ||
| 330 | __be32 ip_src, ip_dst; | ||
| 331 | |||
| 332 | if (msg) | ||
| 333 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "%s\n", msg); | ||
| 334 | |||
| 335 | ip_src = batadv_arp_ip_src(skb, hdr_size); | ||
| 336 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); | ||
| 337 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
| 338 | "ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]\n", | ||
| 339 | batadv_arp_hw_src(skb, hdr_size), &ip_src, | ||
| 340 | batadv_arp_hw_dst(skb, hdr_size), &ip_dst); | ||
| 341 | |||
| 342 | if (hdr_size == 0) | ||
| 343 | return; | ||
| 344 | |||
| 345 | /* if the ARP packet is encapsulated in a batman packet, let's print | ||
| 346 | * some debug messages | ||
| 347 | */ | ||
| 348 | unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; | ||
| 349 | |||
| 350 | switch (unicast_4addr_packet->u.header.packet_type) { | ||
| 351 | case BATADV_UNICAST: | ||
| 352 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
| 353 | "* encapsulated within a UNICAST packet\n"); | ||
| 354 | break; | ||
| 355 | case BATADV_UNICAST_4ADDR: | ||
| 356 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
| 357 | "* encapsulated within a UNICAST_4ADDR packet (src: %pM)\n", | ||
| 358 | unicast_4addr_packet->src); | ||
| 359 | switch (unicast_4addr_packet->subtype) { | ||
| 360 | case BATADV_P_DAT_DHT_PUT: | ||
| 361 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_PUT\n"); | ||
| 362 | break; | ||
| 363 | case BATADV_P_DAT_DHT_GET: | ||
| 364 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_GET\n"); | ||
| 365 | break; | ||
| 366 | case BATADV_P_DAT_CACHE_REPLY: | ||
| 367 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
| 368 | "* type: DAT_CACHE_REPLY\n"); | ||
| 369 | break; | ||
| 370 | case BATADV_P_DATA: | ||
| 371 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DATA\n"); | ||
| 372 | break; | ||
| 373 | default: | ||
| 374 | batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n", | ||
| 375 | unicast_4addr_packet->u.header.packet_type); | ||
| 376 | } | ||
| 377 | break; | ||
| 378 | case BATADV_BCAST: | ||
| 379 | bcast_pkt = (struct batadv_bcast_packet *)unicast_4addr_packet; | ||
| 380 | orig_addr = bcast_pkt->orig; | ||
| 381 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
| 382 | "* encapsulated within a BCAST packet (src: %pM)\n", | ||
| 383 | orig_addr); | ||
| 384 | break; | ||
| 385 | default: | ||
| 386 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | ||
| 387 | "* encapsulated within an unknown packet type (0x%x)\n", | ||
| 388 | unicast_4addr_packet->u.header.packet_type); | ||
| 389 | } | ||
| 390 | } | ||
| 391 | |||
| 392 | #else | ||
| 393 | |||
| 394 | static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||
| 395 | uint16_t type, int hdr_size, char *msg) | ||
| 396 | { | ||
| 397 | } | ||
| 398 | |||
| 399 | #endif /* CONFIG_BATMAN_ADV_DEBUG */ | ||
| 400 | |||
| 260 | /** | 401 | /** |
| 261 | * batadv_is_orig_node_eligible - check whether a node can be a DHT candidate | 402 | * batadv_is_orig_node_eligible - check whether a node can be a DHT candidate |
| 262 | * @res: the array with the already selected candidates | 403 | * @res: the array with the already selected candidates |
| @@ -564,3 +705,64 @@ out: | |||
| 564 | batadv_hardif_free_ref(primary_if); | 705 | batadv_hardif_free_ref(primary_if); |
| 565 | return 0; | 706 | return 0; |
| 566 | } | 707 | } |
| 708 | |||
| 709 | /** | ||
| 710 | * batadv_arp_get_type - parse an ARP packet and gets the type | ||
| 711 | * @bat_priv: the bat priv with all the soft interface information | ||
| 712 | * @skb: packet to analyse | ||
| 713 | * @hdr_size: size of the possible header before the ARP packet in the skb | ||
| 714 | * | ||
| 715 | * Returns the ARP type if the skb contains a valid ARP packet, 0 otherwise | ||
| 716 | */ | ||
| 717 | static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv, | ||
| 718 | struct sk_buff *skb, int hdr_size) | ||
| 719 | { | ||
| 720 | struct arphdr *arphdr; | ||
| 721 | struct ethhdr *ethhdr; | ||
| 722 | __be32 ip_src, ip_dst; | ||
| 723 | uint16_t type = 0; | ||
| 724 | |||
| 725 | /* pull the ethernet header */ | ||
| 726 | if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN))) | ||
| 727 | goto out; | ||
| 728 | |||
| 729 | ethhdr = (struct ethhdr *)(skb->data + hdr_size); | ||
| 730 | |||
| 731 | if (ethhdr->h_proto != htons(ETH_P_ARP)) | ||
| 732 | goto out; | ||
| 733 | |||
| 734 | /* pull the ARP payload */ | ||
| 735 | if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN + | ||
| 736 | arp_hdr_len(skb->dev)))) | ||
| 737 | goto out; | ||
| 738 | |||
| 739 | arphdr = (struct arphdr *)(skb->data + hdr_size + ETH_HLEN); | ||
| 740 | |||
| 741 | /* Check whether the ARP packet carries a valid | ||
| 742 | * IP information | ||
| 743 | */ | ||
| 744 | if (arphdr->ar_hrd != htons(ARPHRD_ETHER)) | ||
| 745 | goto out; | ||
| 746 | |||
| 747 | if (arphdr->ar_pro != htons(ETH_P_IP)) | ||
| 748 | goto out; | ||
| 749 | |||
| 750 | if (arphdr->ar_hln != ETH_ALEN) | ||
| 751 | goto out; | ||
| 752 | |||
| 753 | if (arphdr->ar_pln != 4) | ||
| 754 | goto out; | ||
| 755 | |||
| 756 | /* Check for bad reply/request. If the ARP message is not sane, DAT | ||
| 757 | * will simply ignore it | ||
| 758 | */ | ||
| 759 | ip_src = batadv_arp_ip_src(skb, hdr_size); | ||
| 760 | ip_dst = batadv_arp_ip_dst(skb, hdr_size); | ||
| 761 | if (ipv4_is_loopback(ip_src) || ipv4_is_multicast(ip_src) || | ||
| 762 | ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst)) | ||
| 763 | goto out; | ||
| 764 | |||
| 765 | type = ntohs(arphdr->ar_op); | ||
| 766 | out: | ||
| 767 | return type; | ||
| 768 | } | ||
diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h index 1b88303ed6c2..f4e282a6e634 100644 --- a/net/batman-adv/distributed-arp-table.h +++ b/net/batman-adv/distributed-arp-table.h | |||
| @@ -23,6 +23,8 @@ | |||
| 23 | #include "types.h" | 23 | #include "types.h" |
| 24 | #include "originator.h" | 24 | #include "originator.h" |
| 25 | 25 | ||
| 26 | #include <linux/if_arp.h> | ||
| 27 | |||
| 26 | #define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0) | 28 | #define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0) |
| 27 | 29 | ||
| 28 | /** | 30 | /** |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 0f8dcf337df2..df548ed196d3 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
| @@ -37,9 +37,15 @@ enum batadv_packettype { | |||
| 37 | /** | 37 | /** |
| 38 | * enum batadv_subtype - packet subtype for unicast4addr | 38 | * enum batadv_subtype - packet subtype for unicast4addr |
| 39 | * @BATADV_P_DATA: user payload | 39 | * @BATADV_P_DATA: user payload |
| 40 | * @BATADV_P_DAT_DHT_GET: DHT request message | ||
| 41 | * @BATADV_P_DAT_DHT_PUT: DHT store message | ||
| 42 | * @BATADV_P_DAT_CACHE_REPLY: ARP reply generated by DAT | ||
| 40 | */ | 43 | */ |
| 41 | enum batadv_subtype { | 44 | enum batadv_subtype { |
| 42 | BATADV_P_DATA = 0x01, | 45 | BATADV_P_DATA = 0x01, |
| 46 | BATADV_P_DAT_DHT_GET = 0x02, | ||
| 47 | BATADV_P_DAT_DHT_PUT = 0x03, | ||
| 48 | BATADV_P_DAT_CACHE_REPLY = 0x04, | ||
| 43 | }; | 49 | }; |
| 44 | 50 | ||
| 45 | /* this file is included by batctl which needs these defines */ | 51 | /* this file is included by batctl which needs these defines */ |
