batman-adv: fix packet checksum in receive path
[pandora-kernel.git] / net / batman-adv / soft-interface.c
index 05dd351..dbe1a8c 100644 (file)
@@ -445,30 +445,31 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
 {
        struct bat_priv *bat_priv = netdev_priv(dev);
        struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
-       struct batman_packet *batman_packet;
+       struct batman_ogm_packet *batman_ogm_packet;
        struct softif_neigh *softif_neigh = NULL;
        struct hard_iface *primary_if = NULL;
        struct softif_neigh *curr_softif_neigh = NULL;
 
        if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
-               batman_packet = (struct batman_packet *)
+               batman_ogm_packet = (struct batman_ogm_packet *)
                                        (skb->data + ETH_HLEN + VLAN_HLEN);
        else
-               batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN);
+               batman_ogm_packet = (struct batman_ogm_packet *)
+                                                       (skb->data + ETH_HLEN);
 
-       if (batman_packet->version != COMPAT_VERSION)
+       if (batman_ogm_packet->version != COMPAT_VERSION)
                goto out;
 
-       if (batman_packet->packet_type != BAT_PACKET)
+       if (batman_ogm_packet->packet_type != BAT_OGM)
                goto out;
 
-       if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
+       if (!(batman_ogm_packet->flags & PRIMARIES_FIRST_HOP))
                goto out;
 
-       if (is_my_mac(batman_packet->orig))
+       if (is_my_mac(batman_ogm_packet->orig))
                goto out;
 
-       softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid);
+       softif_neigh = softif_neigh_get(bat_priv, batman_ogm_packet->orig, vid);
        if (!softif_neigh)
                goto out;
 
@@ -532,11 +533,11 @@ static int interface_set_mac_addr(struct net_device *dev, void *p)
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
-       /* only modify transtable if it has been initialised before */
+       /* only modify transtable if it has been initialized before */
        if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
                tt_local_remove(bat_priv, dev->dev_addr,
                                "mac address changed", false);
-               tt_local_add(dev, addr->sa_data);
+               tt_local_add(dev, addr->sa_data, NULL_IFINDEX);
        }
 
        memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
@@ -595,11 +596,12 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
                goto dropped;
 
        /* Register the client MAC in the transtable */
-       tt_local_add(soft_iface, ethhdr->h_source);
+       tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
 
-       orig_node = transtable_search(bat_priv, ethhdr->h_dest);
+       orig_node = transtable_search(bat_priv, ethhdr->h_source,
+                                     ethhdr->h_dest);
        do_bcast = is_multicast_ether_addr(ethhdr->h_dest);
-       if (do_bcast || (orig_node && orig_node->gw_flags)) {
+       if (do_bcast || (orig_node && orig_node->gw_flags)) {
                ret = gw_is_target(bat_priv, skb, orig_node);
 
                if (ret < 0)
@@ -684,10 +686,16 @@ void interface_rx(struct net_device *soft_iface,
        skb_pull_rcsum(skb, hdr_size);
        skb_reset_mac_header(skb);
 
+       if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
+               goto dropped;
+
        ethhdr = (struct ethhdr *)skb_mac_header(skb);
 
        switch (ntohs(ethhdr->h_proto)) {
        case ETH_P_8021Q:
+               if (!pskb_may_pull(skb, VLAN_ETH_HLEN))
+                       goto dropped;
+
                vhdr = (struct vlan_ethhdr *)skb->data;
                vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
 
@@ -724,21 +732,17 @@ void interface_rx(struct net_device *soft_iface,
        }
 
        /* skb->dev & skb->pkt_type are set here */
-       if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
-               goto dropped;
        skb->protocol = eth_type_trans(skb, soft_iface);
-
-       /* should not be necessary anymore as we use skb_pull_rcsum()
-        * TODO: please verify this and remove this TODO
-        * -- Dec 21st 2009, Simon Wunderlich */
-
-/*     skb->ip_summed = CHECKSUM_UNNECESSARY;*/
+       skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
 
        bat_priv->stats.rx_packets++;
        bat_priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr);
 
        soft_iface->last_rx = jiffies;
 
+       if (is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
+               goto dropped;
+
        netif_rx(skb);
        goto out;
 
@@ -796,10 +800,8 @@ struct net_device *softif_create(const char *name)
 
        soft_iface = alloc_netdev(sizeof(*bat_priv), name, interface_setup);
 
-       if (!soft_iface) {
-               pr_err("Unable to allocate the batman interface: %s\n", name);
+       if (!soft_iface)
                goto out;
-       }
 
        ret = register_netdevice(soft_iface);
        if (ret < 0) {
@@ -812,6 +814,7 @@ struct net_device *softif_create(const char *name)
 
        atomic_set(&bat_priv->aggregated_ogms, 1);
        atomic_set(&bat_priv->bonding, 0);
+       atomic_set(&bat_priv->ap_isolation, 0);
        atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
        atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
        atomic_set(&bat_priv->gw_sel_class, 20);