Silence ifconfig down errors in mac80211 (#4067)
[openwrt.git] / package / madwifi / patches / 371-wds_sta_separation.patch
index 57b62b0..a37ebd4 100644 (file)
                if (skb->len < hdrspace) {
                        IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
                                wh, "data", "too short: len %u, expecting %u",
-@@ -446,15 +447,20 @@
+@@ -445,16 +446,24 @@
+               }
                switch (vap->iv_opmode) {
                case IEEE80211_M_STA:
-                       if ((dir != IEEE80211_FC1_DIR_FROMDS) &&
+-                      if ((dir != IEEE80211_FC1_DIR_FROMDS) &&
 -                          (!((vap->iv_flags_ext & IEEE80211_FEXT_WDS) &&
 -                          (dir == IEEE80211_FC1_DIR_DSTODS)))) {
-+                          (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS) &&
-+                           (dir == IEEE80211_FC1_DIR_DSTODS))) {
++                      switch(dir) {
++                      case IEEE80211_FC1_DIR_FROMDS:
++                              break;
++                      case IEEE80211_FC1_DIR_DSTODS:
++                              if (vap->iv_flags_ext & IEEE80211_FEXT_WDS)
++                                      break;
++                      default:
                                IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
                                        wh, "data", "invalid dir 0x%x", dir);
                                vap->iv_stats.is_rx_wrongdir++;
 -                      if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
 +                      if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
 +                              /* ignore 3-addr mcast if we're WDS STA */
-+                              if ((vap->iv_flags_ext & IEEE80211_FEXT_WDS) &&
-+                                      (dir != IEEE80211_FC1_DIR_DSTODS))
++                              if (vap->iv_flags_ext & IEEE80211_FEXT_WDS)
 +                                      goto out;
 +
                                /* Discard multicast if IFF_MULTICAST not set */
                                if ((0 != memcmp(wh->i_addr3, dev->broadcast, ETH_ALEN)) && 
                                        (0 == (dev->flags & IFF_MULTICAST))) {
-@@ -482,24 +488,6 @@
+@@ -482,24 +491,10 @@
                                        vap->iv_stats.is_rx_mcastecho++;
                                        goto out;
                                }
 -                                              goto out;
 -                                      }
 -                              }
++                      } else {
++                              /* Same BSSID, but not meant for us to receive */
++                              if (!IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr))
++                                      goto out;
                        }
                        break;
                case IEEE80211_M_IBSS:
-@@ -548,7 +536,7 @@
+@@ -541,6 +536,11 @@
+                               vap->iv_stats.is_rx_notassoc++;
+                               goto err;
+                       }
++
++                      /* subif isn't fully set up yet, drop the frame */
++                      if (ni->ni_subif == ni->ni_vap)
++                              goto err;
++
+                       /*
+                        * If we're a 4 address packet, make sure we have an entry in
+                        * the node table for the packet source address (addr4).
+@@ -548,9 +548,16 @@
                         */
  
                        /* check for wds link first */
 +                      if ((dir == IEEE80211_FC1_DIR_DSTODS) && !ni->ni_subif) {
                                struct ieee80211vap *avp;
  
-                               TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
-@@ -562,11 +550,13 @@
-                               if (ni_wds != NULL) {
-                                       ieee80211_unref_node(&ni);
-                                       ni = ieee80211_ref_node(ni_wds);
-+                              } else if (vap->iv_flags_ext & IEEE80211_FEXT_WDSSEP) {
++                              if (vap->iv_flags_ext & IEEE80211_FEXT_WDSSEP) {
 +                                      ieee80211_wds_addif(ni);
-                               }
++                                      /* we must drop frames here until the interface has
++                                       * been fully separated, otherwise a bridge might get
++                                       * confused */
++                                      goto err;
++                              }
+                               TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
+                                       if (!memcmp(avp->wds_mac, wh->i_addr2, IEEE80211_ADDR_LEN)) {
+                                               IEEE80211_LOCK_IRQ(ni->ni_ic);
+@@ -566,7 +573,7 @@
                        }
  
                        /* XXX: Useless node mgmt API; make better */
                                struct ieee80211_node_table *nt = &ic->ic_sta;
                                struct ieee80211_frame_addr4 *wh4;
  
-@@ -626,6 +616,11 @@
+@@ -626,6 +633,11 @@
                        goto out;
                }
  
                /*
                 * Handle privacy requirements.  Note that we
                 * must not be preempted from here until after
-@@ -698,8 +693,12 @@
+@@ -698,8 +710,12 @@
                if (! accept_data_frame(vap, ni, key, skb, eh))
                        goto out;
  
                IEEE80211_NODE_STAT(ni, rx_data);
                IEEE80211_NODE_STAT_ADD(ni, rx_bytes, skb->len);
                ic->ic_lastdata = jiffies;
-@@ -1132,6 +1131,13 @@
+@@ -1132,6 +1148,13 @@
                dev = vap->iv_xrvap->iv_dev;
  #endif
  
        /* perform as a bridge within the vap */
        /* XXX intra-vap bridging only */
        if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
-@@ -1157,6 +1163,7 @@
+@@ -1157,7 +1180,16 @@
                        if (ni1 != NULL) {
                                if (ni1->ni_vap == vap &&
                                    ieee80211_node_is_authorized(ni1) &&
-+                                      !ni->ni_subif &&
++                                      !ni1->ni_subif &&
                                    ni1 != vap->iv_bss) {
++
++                                      /* tried to bridge to a subif, drop the packet */
++                                      if (ni->ni_subif) {
++                                              ieee80211_unref_node(&ni1);
++                                              ieee80211_dev_kfree_skb(&skb);
++                                              return;
++                                      }
++
                                        skb1 = skb;
                                        skb = NULL;
+                               }
 --- a/net80211/ieee80211_ioctl.h
 +++ b/net80211/ieee80211_ioctl.h
 @@ -649,6 +649,7 @@
        default:
                return -EOPNOTSUPP;
        }
-@@ -5767,6 +5778,10 @@
+@@ -4447,6 +4458,8 @@
+       struct ieee80211vap *vap = ni->ni_vap;
+       size_t ielen;
++      if (req->vap->iv_wdsnode && ni->ni_subif)
++              vap = ni->ni_subif;
+       if (vap != req->vap && vap != req->vap->iv_xrvap)       /* only entries for this vap */
+               return;
+       if ((vap->iv_opmode == IEEE80211_M_HOSTAP ||
+@@ -4466,6 +4479,8 @@
+       size_t ielen, len;
+       u_int8_t *cp;
++      if (req->vap->iv_wdsnode && ni->ni_subif)
++              vap = ni->ni_subif;
+       if (vap != req->vap && vap != req->vap->iv_xrvap)       /* only entries for this vap (or) xrvap */
+               return;
+       if ((vap->iv_opmode == IEEE80211_M_HOSTAP ||
+@@ -5767,6 +5782,10 @@
         0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_minrate"},
        { IEEE80211_IOCTL_SETSCANLIST,
         IW_PRIV_TYPE_CHAR | 255, 0, "setscanlist"},
  
  #ifdef ATH_REVERSE_ENGINEERING
        /*
-@@ -5890,6 +5905,8 @@
+@@ -5890,6 +5909,8 @@
  ieee80211_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  {
        struct ieee80211vap *vap = dev->priv;
  
        switch (cmd) {
        case SIOCG80211STATS:
-@@ -5898,8 +5915,20 @@
+@@ -5898,8 +5919,20 @@
        case SIOC80211IFDESTROY:
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
  /* Locking */
  /* NB: beware, spin_is_locked() is not usefully defined for !(DEBUG || SMP)
   * because spinlocks do not exist in this configuration. Instead IRQs 
-@@ -167,6 +196,18 @@
-       IEEE80211_VAPS_LOCK_ASSERT(_ic);                \
-       spin_unlock_bh(&(_ic)->ic_vapslock);            \
- } while (0)
-+#define       IEEE80211_VAPS_LOCK_IRQ(_ic) do {                                       \
-+      unsigned long __vlockflags;                                     \
-+      IEEE80211_VAPS_LOCK_CHECK(_ic);                                 \
-+      spin_lock_irqsave(&(_ic)->ic_vapslock, __vlockflags);
-+#define       IEEE80211_VAPS_UNLOCK_IRQ(_ic)                                  \
-+      IEEE80211_VAPS_LOCK_ASSERT(_ic);                                        \
-+      spin_unlock_irqrestore(&(_ic)->ic_vapslock, __vlockflags);      \
-+} while (0)
-+#define       IEEE80211_VAPS_UNLOCK_IRQ_EARLY(_ic)                                    \
-+      IEEE80211_VAPS_LOCK_ASSERT(_ic);                                        \
-+      spin_unlock_irqrestore(&(_ic)->ic_vapslock, __vlockflags);
-+
- #if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
- #define IEEE80211_VAPS_LOCK_ASSERT(_ic) \
 --- a/net80211/ieee80211_proto.c
 +++ b/net80211/ieee80211_proto.c
 @@ -1081,6 +1081,8 @@
        ieee80211_new_state(vap, IEEE80211_S_INIT, -1);
        if (dev->flags & IFF_RUNNING) {
                dev->flags &= ~IFF_RUNNING;             /* mark us stopped */
-@@ -1342,9 +1366,9 @@
-       struct ieee80211com *ic = vap->iv_ic;
-       int rc;
--      IEEE80211_VAPS_LOCK_BH(ic);
-+      IEEE80211_VAPS_LOCK_IRQ(ic);
-       rc = vap->iv_newstate(vap, nstate, arg);
--      IEEE80211_VAPS_UNLOCK_BH(ic);
-+      IEEE80211_VAPS_UNLOCK_IRQ(ic);
-       return rc;
- }
 @@ -1630,6 +1654,7 @@
                 */
                if (ni->ni_authmode != IEEE80211_AUTH_8021X)
                hdrsize = sizeof(struct ieee80211_frame);
  
        SKB_CB(skb)->auth_pkt = (eh.ether_type == __constant_htons(ETHERTYPE_PAE));
-+      if (!SKB_CB(skb)->auth_pkt && ni->ni_subif)
++      if (ni->ni_subif)
 +              vap = ni->ni_subif;
  
        switch (vap->iv_opmode) {
This page took 0.028962 seconds and 4 git commands to generate.