From patchwork Thu Feb 9 23:41:42 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 1548 Return-Path: Received: from latitanza.investici.org (latitanza.investici.org [82.94.249.234]) by open-mesh.org (Postfix) with ESMTPS id 308AC6008BD for ; Fri, 10 Feb 2012 00:42:54 +0100 (CET) Authentication-Results: open-mesh.org; dkim=pass (1024-bit key) header.i=@autistici.org; dkim-adsp=pass Received: from [82.94.249.234] (latitanza [82.94.249.234]) (Authenticated sender: ordex@autistici.org) by localhost (Postfix) with ESMTPSA id 8A52698053; Thu, 9 Feb 2012 23:42:53 +0000 (UTC) X-DKIM: Sendmail DKIM Filter v2.8.2 latitanza.investici.org 8A52698053 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=autistici.org; s=stigmate; t=1328830973; bh=p9KWOVnLviWHdxsnmrTvow76rpqpH1F2t7TSn9hsjbE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=pkiUqXZXN46bbMG3pHcYjNwsUbbim1hcp2S/0vTo0XGSptJ8BFsvEfsCnaOSI0NQb wVhozJOHhWFj+Ka0VpTuq83ycmJ6OiWnIOh4H3+b0jYgdvhekCSDjyxEDrgG8c4FY4 eUjpy1e5+wzy3IA11cW703xU0bmZx+kVHybTXLu0= From: Antonio Quartulli To: b.a.t.m.a.n@lists.open-mesh.org Date: Fri, 10 Feb 2012 00:41:42 +0100 Message-Id: <1328830902-11574-10-git-send-email-ordex@autistici.org> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1328830902-11574-1-git-send-email-ordex@autistici.org> References: <1328830902-11574-1-git-send-email-ordex@autistici.org> Subject: [B.A.T.M.A.N.] [PATCHv5 9/9] batman-adv: Distributed ARP Table - use unicast_4addr_packet for DHT messages X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.13 Precedence: list Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Feb 2012 23:42:54 -0000 In order to enable an higher verbosity level of the DAT debug messages, the unicast_4addr_packet is now used to carry ARP packets generated by the DAT internal mechanism. This packet type will enable batman-adv to recognise each DAT related message and to print its source (this will help to track possibly bogus ARP entries) Signed-off-by: Antonio Quartulli --- distributed-arp-table.c | 129 +++++++++++++++++++++++++++++++--------------- distributed-arp-table.h | 16 +++--- soft-interface.c | 15 +++-- 3 files changed, 105 insertions(+), 55 deletions(-) diff --git a/distributed-arp-table.c b/distributed-arp-table.c index 48e97e0..239b5c4 100644 --- a/distributed-arp-table.c +++ b/distributed-arp-table.c @@ -31,6 +31,7 @@ #include "originator.h" #include "send.h" #include "soft-interface.h" +#include "translation-table.h" #include "types.h" #include "translation-table.h" #include "unicast.h" @@ -38,10 +39,44 @@ #ifdef CONFIG_BATMAN_ADV_DEBUG static inline void bat_dbg_arp(struct bat_priv *bat_priv, - struct sk_buff *skb, uint16_t type) { + struct sk_buff *skb, uint16_t type, + int hdr_size) { + struct unicast_4addr_packet *unicast_4addr_packet; + bat_dbg(DBG_ARP, bat_priv, "ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]\n", - ARP_HW_SRC(skb), &ARP_IP_SRC(skb), ARP_HW_DST(skb), - &ARP_IP_DST(skb)); + ARP_HW_SRC(skb, hdr_size), &ARP_IP_SRC(skb, hdr_size), + ARP_HW_DST(skb, hdr_size), &ARP_IP_DST(skb, hdr_size)); + + if (hdr_size == 0) + return; + + /* if the AP packet is encapsulated in a batman packet, let's print some + * debug messages */ + unicast_4addr_packet = (struct unicast_4addr_packet *)skb->data; + + switch (unicast_4addr_packet->u.header.packet_type) { + case BAT_UNICAST: + bat_dbg(DBG_ARP, bat_priv, "encapsulated within a UNICAST " + "packet\n"); + break; + case BAT_UNICAST_4ADDR: + bat_dbg(DBG_ARP, bat_priv, "encapsulated within a " + "UNICAST_4ADDR packet (src: %pM)\n", + unicast_4addr_packet->src); + if (unicast_4addr_packet->subtype != BAT_P_DHT_PUT || + unicast_4addr_packet->subtype != BAT_P_DHT_GET) + bat_dbg(DBG_ARP, bat_priv, "It's a DAT message\n"); + break; + case BAT_BCAST: + bat_dbg(DBG_ARP, bat_priv, "encapsulated within a BCAST packet " + "(src: %pM)\n", + ((struct bcast_packet *)unicast_4addr_packet)->orig); + break; + default: + bat_dbg(DBG_ARP, bat_priv, "encapsulated within an unknown " + "packet type (0x%x)\n", + unicast_4addr_packet->u.header.packet_type); + } } #else @@ -184,7 +219,8 @@ static bool dht_send_data(struct bat_priv *bat_priv, struct sk_buff *skb, goto free_orig; tmp_skb = pskb_copy(skb, GFP_ATOMIC); - if (prepare_unicast_packet(tmp_skb, cand[i].orig_node)) + if (prepare_unicast_4addr_packet(bat_priv, tmp_skb, + cand[i].orig_node)) send_skb_packet(tmp_skb, neigh_node->if_incoming, neigh_node->addr); else @@ -228,24 +264,28 @@ out: /* Returns arphdr->ar_op if the skb contains a valid ARP packet, otherwise * returns 0 */ -static uint16_t arp_get_type(struct bat_priv *bat_priv, struct sk_buff *skb) +static uint16_t arp_get_type(struct bat_priv *bat_priv, struct sk_buff *skb, + int hdr_size) { struct arphdr *arphdr; struct ethhdr *ethhdr; uint16_t type = 0; - if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) + /* pull the ethernet header */ + if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN))) goto out; - ethhdr = (struct ethhdr *)skb_mac_header(skb); + ethhdr = (struct ethhdr *)(skb->data + hdr_size); if (ethhdr->h_proto != htons(ETH_P_ARP)) goto out; - if (unlikely(!pskb_may_pull(skb, ETH_HLEN + arp_hdr_len(skb->dev)))) + /* pull the ARP payload */ + if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN + + arp_hdr_len(skb->dev)))) goto out; - arphdr = (struct arphdr *)(skb->data + sizeof(struct ethhdr)); + arphdr = (struct arphdr *)(skb->data + hdr_size + ETH_HLEN); /* Check whether the ARP packet carries a valid * IP information */ @@ -263,10 +303,10 @@ static uint16_t arp_get_type(struct bat_priv *bat_priv, struct sk_buff *skb) /* Check for bad reply/request. If the ARP message is not sane, DAT * will simply ignore it */ - if (ipv4_is_loopback(ARP_IP_SRC(skb)) || - ipv4_is_multicast(ARP_IP_SRC(skb)) || - ipv4_is_loopback(ARP_IP_DST(skb)) || - ipv4_is_multicast(ARP_IP_DST(skb))) + if (ipv4_is_loopback(ARP_IP_SRC(skb, hdr_size)) || + ipv4_is_multicast(ARP_IP_SRC(skb, hdr_size)) || + ipv4_is_loopback(ARP_IP_DST(skb, hdr_size)) || + ipv4_is_multicast(ARP_IP_DST(skb, hdr_size))) goto out; type = ntohs(arphdr->ar_op); @@ -288,18 +328,18 @@ bool dat_snoop_outgoing_arp_request(struct bat_priv *bat_priv, struct hard_iface *primary_if = NULL; struct sk_buff *skb_new; - type = arp_get_type(bat_priv, skb); + type = arp_get_type(bat_priv, skb, 0); /* If we get an ARP_REQUEST we have to send the unicast message to the * selected DHT candidates */ if (type != ARPOP_REQUEST) goto out; bat_dbg(DBG_ARP, bat_priv, "Parsing outgoing ARP REQUEST\n"); - bat_dbg_arp(bat_priv, skb, type); + bat_dbg_arp(bat_priv, skb, type, 0); - ip_src = ARP_IP_SRC(skb); - hw_src = ARP_HW_SRC(skb); - ip_dst = ARP_IP_DST(skb); + ip_src = ARP_IP_SRC(skb, 0); + hw_src = ARP_HW_SRC(skb, 0); + ip_dst = ARP_IP_DST(skb, 0); primary_if = primary_if_get_selected(bat_priv); if (!primary_if) @@ -341,7 +381,7 @@ out: * into the local table. If found, an ARP reply is sent immediately, otherwise * the caller has to deliver the ARP request to the upper layer */ bool dat_snoop_incoming_arp_request(struct bat_priv *bat_priv, - struct sk_buff *skb) + struct sk_buff *skb, int hdr_size) { uint16_t type; uint32_t ip_src, ip_dst; @@ -351,16 +391,16 @@ bool dat_snoop_incoming_arp_request(struct bat_priv *bat_priv, struct neighbour *n = NULL; bool ret = false; - type = arp_get_type(bat_priv, skb); + type = arp_get_type(bat_priv, skb, hdr_size); if (type != ARPOP_REQUEST) goto out; - hw_src = ARP_HW_SRC(skb); - ip_src = ARP_IP_SRC(skb); - ip_dst = ARP_IP_DST(skb); + hw_src = ARP_HW_SRC(skb, hdr_size); + ip_src = ARP_IP_SRC(skb, hdr_size); + ip_dst = ARP_IP_DST(skb, hdr_size); bat_dbg(DBG_ARP, bat_priv, "Parsing incoming ARP REQUEST\n"); - bat_dbg_arp(bat_priv, skb, type); + bat_dbg_arp(bat_priv, skb, type, hdr_size); primary_if = primary_if_get_selected(bat_priv); if (!primary_if) @@ -380,7 +420,7 @@ bool dat_snoop_incoming_arp_request(struct bat_priv *bat_priv, if (!skb_new) goto out; - unicast_send_skb(skb_new, bat_priv); + unicast_4addr_send_skb(skb_new, bat_priv); ret = true; out: @@ -404,17 +444,17 @@ bool dat_snoop_outgoing_arp_reply(struct bat_priv *bat_priv, uint8_t *hw_src, *hw_dst; bool ret = false; - type = arp_get_type(bat_priv, skb); + type = arp_get_type(bat_priv, skb, 0); if (type != ARPOP_REPLY) goto out; bat_dbg(DBG_ARP, bat_priv, "Parsing outgoing ARP REPLY\n"); - bat_dbg_arp(bat_priv, skb, type); + bat_dbg_arp(bat_priv, skb, type, 0); - hw_src = ARP_HW_SRC(skb); - ip_src = ARP_IP_SRC(skb); - hw_dst = ARP_HW_DST(skb); - ip_dst = ARP_IP_DST(skb); + hw_src = ARP_HW_SRC(skb, 0); + ip_src = ARP_IP_SRC(skb, 0); + hw_dst = ARP_HW_DST(skb, 0); + ip_dst = ARP_IP_DST(skb, 0); arp_neigh_update(bat_priv, ip_src, hw_src); arp_neigh_update(bat_priv, ip_dst, hw_dst); @@ -431,24 +471,24 @@ out: /* This function has to be invoked on an ARP reply coming into the soft * interface from the mesh network. The local table has to be updated */ bool dat_snoop_incoming_arp_reply(struct bat_priv *bat_priv, - struct sk_buff *skb) + struct sk_buff *skb, int hdr_size) { uint16_t type; uint32_t ip_src, ip_dst; uint8_t *hw_src, *hw_dst; bool ret = false; - type = arp_get_type(bat_priv, skb); + type = arp_get_type(bat_priv, skb, hdr_size); if (type != ARPOP_REPLY) goto out; bat_dbg(DBG_ARP, bat_priv, "Parsing incoming ARP REPLY\n"); - bat_dbg_arp(bat_priv, skb, type); + bat_dbg_arp(bat_priv, skb, type, hdr_size); - hw_src = ARP_HW_SRC(skb); - ip_src = ARP_IP_SRC(skb); - hw_dst = ARP_HW_DST(skb); - ip_dst = ARP_IP_DST(skb); + hw_src = ARP_HW_SRC(skb, hdr_size); + ip_src = ARP_IP_SRC(skb, hdr_size); + hw_dst = ARP_HW_DST(skb, hdr_size); + ip_dst = ARP_IP_DST(skb, hdr_size); /* Update our internal cache with both the IP addresses we fetched from * the ARP reply */ @@ -471,20 +511,25 @@ bool arp_drop_broadcast_packet(struct bat_priv *bat_priv, /* If this packet is an ARP_REQUEST and we already have the information * that it is going to ask, we can drop the packet */ if (!forw_packet->num_packets && - (arp_get_type(bat_priv, forw_packet->skb) == + (arp_get_type(bat_priv, forw_packet->skb, + sizeof(struct bcast_packet)) == ARPOP_REQUEST)) { - n = neigh_lookup(&arp_tbl, &ARP_IP_DST(forw_packet->skb), + n = neigh_lookup(&arp_tbl, + &ARP_IP_DST(forw_packet->skb, + sizeof(struct bcast_packet)), forw_packet->if_incoming->soft_iface); /* check if we already know this neigh */ if (n && (n->nud_state & NUD_CONNECTED)) { bat_dbg(DBG_ARP, bat_priv, "ARP Request for %pI4: " "fallback prevented\n", - &ARP_IP_DST(forw_packet->skb)); + &ARP_IP_DST(forw_packet->skb, + sizeof(struct bcast_packet))); return true; } bat_dbg(DBG_ARP, bat_priv, "ARP Request for %pI4: fallback\n", - &ARP_IP_DST(forw_packet->skb)); + &ARP_IP_DST(forw_packet->skb, + sizeof(struct bcast_packet))); } return false; } diff --git a/distributed-arp-table.h b/distributed-arp-table.h index 98fc2e1..a81b021 100644 --- a/distributed-arp-table.h +++ b/distributed-arp-table.h @@ -41,20 +41,22 @@ struct forw_packet; #define dat_addr_t uint16_t #define DAT_ADDR_MAX biggest_unsigned_int(dat_addr_t) -#define ARP_HW_SRC(skb) ((uint8_t *)(skb->data) + sizeof(struct ethhdr) + \ - sizeof(struct arphdr)) -#define ARP_IP_SRC(skb) (*(uint32_t *)(ARP_HW_SRC(skb) + ETH_ALEN)) -#define ARP_HW_DST(skb) (ARP_HW_SRC(skb) + ETH_ALEN + 4) -#define ARP_IP_DST(skb) (*(uint32_t *)(ARP_HW_SRC(skb) + ETH_ALEN * 2 + 4)) +#define ARP_HW_SRC(skb, hdr_size) ((uint8_t *)(skb->data + hdr_size) + \ + sizeof(struct ethhdr) + sizeof(struct arphdr)) +#define ARP_IP_SRC(skb, hdr_size) (*(uint32_t *)(ARP_HW_SRC(skb, hdr_size) + \ + ETH_ALEN)) +#define ARP_HW_DST(skb, hdr_size) (ARP_HW_SRC(skb, hdr_size) + ETH_ALEN + 4) +#define ARP_IP_DST(skb, hdr_size) (*(uint32_t *)(ARP_HW_SRC(skb, hdr_size) + \ + ETH_ALEN * 2 + 4)) bool dat_snoop_outgoing_arp_request(struct bat_priv *bat_priv, struct sk_buff *skb); bool dat_snoop_incoming_arp_request(struct bat_priv *bat_priv, - struct sk_buff *skb); + struct sk_buff *skb, int hdr_size); bool dat_snoop_outgoing_arp_reply(struct bat_priv *bat_priv, struct sk_buff *skb); bool dat_snoop_incoming_arp_reply(struct bat_priv *bat_priv, - struct sk_buff *skb); + struct sk_buff *skb, int hdr_size); bool arp_drop_broadcast_packet(struct bat_priv *bat_priv, struct forw_packet *forw_packet); void arp_change_timeout(struct net_device *soft_iface, const char *name); diff --git a/soft-interface.c b/soft-interface.c index 4426e36..b21171b 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -258,6 +258,7 @@ void interface_rx(struct net_device *soft_iface, int hdr_size) { struct bat_priv *bat_priv = netdev_priv(soft_iface); + struct unicast_4addr_packet *unicast_4addr_packet; struct ethhdr *ethhdr; struct vlan_ethhdr *vhdr; short vid = -1; @@ -266,6 +267,14 @@ void interface_rx(struct net_device *soft_iface, if (!pskb_may_pull(skb, hdr_size)) goto dropped; + unicast_4addr_packet = (struct unicast_4addr_packet *)skb->data; + + if (dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size)) + goto out; + + if (dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size)) + goto out; + skb_pull_rcsum(skb, hdr_size); skb_reset_mac_header(skb); @@ -284,12 +293,6 @@ void interface_rx(struct net_device *soft_iface, goto dropped; } - if (dat_snoop_incoming_arp_request(bat_priv, skb)) - goto out; - - if (dat_snoop_incoming_arp_reply(bat_priv, skb)) - goto out; - /* skb->dev & skb->pkt_type are set here */ if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) goto dropped;