X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/857bb5029f52934e05cdbb7da49229e009a2bc66..f251f740878af188b1f27d19ec921efa6c577349:/package/madwifi/patches/370-wdsvap.patch diff --git a/package/madwifi/patches/370-wdsvap.patch b/package/madwifi/patches/370-wdsvap.patch index d1f255d6c..8a0e823ae 100644 --- a/package/madwifi/patches/370-wdsvap.patch +++ b/package/madwifi/patches/370-wdsvap.patch @@ -44,7 +44,7 @@ if (ic->ic_dev->flags & IFF_RUNNING) { /* needs to disable hardware too */ -@@ -1271,8 +1269,12 @@ ath_vap_create(struct ieee80211com *ic, +@@ -1271,8 +1269,12 @@ ath_vap_create(struct ieee80211com *ic, } else ic_opmode = opmode; break; @@ -58,7 +58,7 @@ /* permit multiple APs and/or WDS links */ /* XXX sta+ap for repeater/bridge application */ if ((sc->sc_nvaps != 0) && (ic->ic_opmode == IEEE80211_M_STA)) -@@ -1304,7 +1306,7 @@ ath_vap_create(struct ieee80211com *ic, +@@ -1304,7 +1306,7 @@ ath_vap_create(struct ieee80211com *ic, } avp = dev->priv; @@ -77,7 +77,7 @@ rfilt |= HAL_RX_FILTER_BEACON; if (sc->sc_nmonvaps > 0) rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON | -@@ -9030,8 +9031,6 @@ ath_calibrate(unsigned long arg) +@@ -9032,8 +9033,6 @@ ath_calibrate(unsigned long arg) * set sc->beacons if we might need to restart * them after ath_reset. */ if (!sc->sc_beacons && @@ -124,7 +124,7 @@ { #define IEEE80211_C_OPMODE \ (IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | IEEE80211_C_AHDEMO | \ -@@ -510,9 +525,18 @@ ieee80211_vap_setup(struct ieee80211com +@@ -510,9 +525,18 @@ ieee80211_vap_setup(struct ieee80211com vap->iv_monitor_crc_errors = 0; vap->iv_monitor_phy_errors = 0; @@ -528,7 +528,7 @@ switch (cmd) { case SIOCG80211STATS: -@@ -5921,8 +5922,20 @@ ieee80211_ioctl(struct net_device *dev, +@@ -5921,8 +5922,20 @@ ieee80211_ioctl(struct net_device *dev, case SIOC80211IFDESTROY: if (!capable(CAP_NET_ADMIN)) return -EPERM; @@ -748,7 +748,7 @@ IEEE80211_NODE_STAT(ni, rx_data); IEEE80211_NODE_STAT_ADD(ni, rx_bytes, skb->len); ic->ic_lastdata = jiffies; -@@ -1114,6 +1142,17 @@ ieee80211_deliver_data(struct ieee80211_ +@@ -1114,6 +1142,18 @@ ieee80211_deliver_data(struct ieee80211_ dev = vap->iv_xrvap->iv_dev; #endif @@ -757,6 +757,7 @@ + if (ni->ni_subif && ((eh)->ether_type != __constant_htons(ETHERTYPE_PAE))) { + if (ni->ni_vap == ni->ni_subif) { + ieee80211_dev_kfree_skb(&skb); ++ return; + } else { + vap = ni->ni_subif; + dev = vap->iv_dev; @@ -766,7 +767,7 @@ /* perform as a bridge within the vap */ /* XXX intra-vap bridging only */ if (vap->iv_opmode == IEEE80211_M_HOSTAP && -@@ -1139,7 +1178,16 @@ ieee80211_deliver_data(struct ieee80211_ +@@ -1139,7 +1179,16 @@ ieee80211_deliver_data(struct ieee80211_ if (ni1 != NULL) { if (ni1->ni_vap == vap && ieee80211_node_is_authorized(ni1) && @@ -783,7 +784,7 @@ skb1 = skb; skb = NULL; } -@@ -3084,8 +3132,7 @@ ieee80211_recv_mgmt(struct ieee80211vap +@@ -3084,8 +3133,7 @@ ieee80211_recv_mgmt(struct ieee80211vap (vap->iv_opmode == IEEE80211_M_STA && ni->ni_associd) || (vap->iv_opmode == IEEE80211_M_IBSS) || ((subtype == IEEE80211_FC0_SUBTYPE_BEACON) && @@ -793,7 +794,7 @@ vap->iv_stats.is_rx_mgtdiscard++; return; } -@@ -3471,13 +3518,54 @@ ieee80211_recv_mgmt(struct ieee80211vap +@@ -3471,13 +3519,56 @@ ieee80211_recv_mgmt(struct ieee80211vap */ if (ic->ic_flags & IEEE80211_F_SCAN) { ieee80211_add_scan(vap, &scan, wh, subtype, rssi, rtsf); @@ -813,28 +814,30 @@ + (vap->iv_opmode == IEEE80211_M_WDS)) && + (scan.capinfo & IEEE80211_CAPINFO_ESS))) { + struct ieee80211vap *avp = NULL; ++ int found = 0; + + IEEE80211_LOCK_IRQ(vap->iv_ic); + if (vap->iv_opmode == IEEE80211_M_HOSTAP) { -+ int found = 0; -+ + TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) { + if (!memcmp(avp->wds_mac, wh->i_addr2, IEEE80211_ADDR_LEN)) { + if (avp->iv_state != IEEE80211_S_RUN) + continue; ++ if (!avp->iv_wdsnode) ++ continue; + found = 1; + break; + } + } -+ if (!found) -+ break; -+ -+ ni = ni_or_null = avp->iv_wdsnode; -+ } else if (vap->iv_opmode == IEEE80211_M_WDS) { ++ if (found) ++ ni = ni_or_null = avp->iv_wdsnode; ++ } else if ((vap->iv_opmode == IEEE80211_M_WDS) && vap->iv_wdsnode) { ++ found = 1; + ni = ni_or_null = vap->iv_wdsnode; + } + IEEE80211_UNLOCK_IRQ(vap->iv_ic); + ++ if (!found) ++ break; + if (ni_or_null == NULL) { - /* Create a new entry in the neighbor table. */ @@ -853,7 +856,7 @@ } else { /* * Copy data from beacon to neighbor table. -@@ -3490,6 +3578,7 @@ ieee80211_recv_mgmt(struct ieee80211vap +@@ -3490,6 +3581,7 @@ ieee80211_recv_mgmt(struct ieee80211vap IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3); memcpy(ni->ni_tstamp.data, scan.tstamp, sizeof(ni->ni_tstamp)); @@ -883,6 +886,15 @@ ieee80211_node_table_reset(&ic->ic_sta, vap); if (vap->iv_bss != NULL) { ieee80211_unref_node(&vap->iv_bss); +@@ -309,7 +314,7 @@ ieee80211_create_ibss(struct ieee80211va + /* Check to see if we already have a node for this mac + * NB: we gain a node reference here + */ +- ni = ieee80211_find_node(&ic->ic_sta, vap->iv_myaddr); ++ ni = ieee80211_find_txnode(vap, vap->iv_myaddr); + if (ni == NULL) { + ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr); + IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC, @@ -831,12 +836,18 @@ node_table_leave_locked(struct ieee80211 LIST_REMOVE(ni, ni_hash); } @@ -903,7 +915,7 @@ } /* This is overridden by ath_node_alloc in ath/if_ath.c, and so -@@ -1134,6 +1145,62 @@ ieee80211_alloc_node(struct ieee80211vap +@@ -1134,6 +1145,65 @@ ieee80211_alloc_node(struct ieee80211vap return ni; } @@ -957,6 +969,9 @@ + if (ni->ni_subif) + return; + ++ if (!ni->ni_table) ++ return; ++ + ieee80211_ref_node(ni); + ni->ni_subif = ni->ni_vap; + IEEE80211_INIT_WORK(&ni->ni_create, ieee80211_wds_do_addif); @@ -966,7 +981,7 @@ /* Add wds address to the node table */ int #ifdef IEEE80211_DEBUG_REFCNT -@@ -1553,22 +1620,39 @@ ieee80211_find_rxnode(struct ieee80211co +@@ -1553,22 +1623,39 @@ ieee80211_find_rxnode(struct ieee80211co ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL) struct ieee80211_node_table *nt; struct ieee80211_node *ni; @@ -1015,7 +1030,7 @@ #endif IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt); -@@ -1596,9 +1680,19 @@ ieee80211_find_txnode_debug(struct ieee8 +@@ -1596,9 +1683,19 @@ ieee80211_find_txnode_debug(struct ieee8 ieee80211_find_txnode(struct ieee80211vap *vap, const u_int8_t *mac) #endif { @@ -1035,7 +1050,7 @@ /* * The destination address should be in the node table * unless we are operating in station mode or this is a -@@ -1669,6 +1763,11 @@ ieee80211_free_node(struct ieee80211_nod +@@ -1669,6 +1766,11 @@ ieee80211_free_node(struct ieee80211_nod { struct ieee80211vap *vap = ni->ni_vap; @@ -1047,7 +1062,7 @@ atomic_dec(&ni->ni_ic->ic_node_counter); node_print_message(IEEE80211_MSG_NODE|IEEE80211_MSG_NODE_REF, 1 /* show counter */, -@@ -1781,22 +1880,6 @@ restart: +@@ -1781,22 +1883,6 @@ restart: jiffies > ni->ni_rxfragstamp + HZ) { ieee80211_dev_kfree_skb(&ni->ni_rxfrag); } @@ -1070,7 +1085,7 @@ ni->ni_inact--; if (ni->ni_associd != 0 || isadhoc) { struct ieee80211vap *vap = ni->ni_vap; -@@ -2263,6 +2346,36 @@ ieee80211_node_leave_11g(struct ieee8021 +@@ -2263,6 +2349,35 @@ ieee80211_node_leave_11g(struct ieee8021 } } @@ -1081,15 +1096,14 @@ + struct ieee80211vap *vap; + struct ieee80211com *ic; + ++ /* wait for full initialization before we start the teardown ++ * otherwise we could leak interfaces */ ++ while (ni->ni_subif == ni->ni_vap) ++ schedule(); ++ + rtnl_lock(); + vap = ni->ni_subif; + -+ /* if addif is waiting for the timer to fire, cancel! */ -+ if (vap == ni->ni_vap) { -+ ni->ni_subif = NULL; -+ goto done; -+ } -+ + if (!vap) + goto done; + @@ -1107,7 +1121,7 @@ /* * Handle bookkeeping for a station/neighbor leaving * the bss when operating in ap or adhoc modes. -@@ -2279,6 +2392,12 @@ ieee80211_node_leave(struct ieee80211_no +@@ -2279,6 +2394,12 @@ ieee80211_node_leave(struct ieee80211_no ni, "station with aid %d leaves (refcnt %u)", IEEE80211_NODE_AID(ni), atomic_read(&ni->ni_refcnt)); @@ -1143,7 +1157,7 @@ /* calculate priority so drivers can find the TX queue */ if (ieee80211_classify(ni, skb)) { IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT, ni, -@@ -334,20 +335,33 @@ void ieee80211_parent_queue_xmit(struct +@@ -334,20 +335,33 @@ void ieee80211_parent_queue_xmit(struct * constructing a frame as it sets i_fc[1]; other bits can * then be or'd in. */ @@ -1162,12 +1176,12 @@ + struct ieee80211_frame *wh; + int len = sizeof(struct ieee80211_frame); + int opmode = vap->iv_opmode; - ++ + if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) { + if ((opmode == IEEE80211_M_STA) && + (vap->iv_flags_ext & IEEE80211_FEXT_WDS)) + opmode = IEEE80211_M_WDS; -+ + + if (opmode == IEEE80211_M_WDS) + len = sizeof(struct ieee80211_frame_addr4); + } @@ -1354,7 +1368,20 @@ }; --- a/net80211/ieee80211_proto.c +++ b/net80211/ieee80211_proto.c -@@ -1081,6 +1081,8 @@ ieee80211_init(struct net_device *dev, i +@@ -979,6 +979,12 @@ ieee80211_init(struct net_device *dev, i + "start running (state=%d)\n", vap->iv_state); + + ++ if (vap->iv_master && vap->iv_master->iv_state == IEEE80211_S_INIT) { ++ int ret = ieee80211_init(vap->iv_master->iv_dev, forcescan); ++ if (ret < 0) ++ return ret; ++ } ++ + if ((dev->flags & IFF_RUNNING) == 0) { + if (ic->ic_nopened++ == 0 && + (parent->flags & IFF_RUNNING) == 0) +@@ -1081,6 +1087,8 @@ ieee80211_init(struct net_device *dev, i int ieee80211_open(struct net_device *dev) { @@ -1363,7 +1390,7 @@ return ieee80211_init(dev, 0); } -@@ -1090,7 +1092,7 @@ ieee80211_open(struct net_device *dev) +@@ -1090,7 +1098,7 @@ ieee80211_open(struct net_device *dev) void ieee80211_start_running(struct ieee80211com *ic) { @@ -1372,7 +1399,7 @@ struct net_device *dev; /* XXX locking */ -@@ -1099,6 +1101,16 @@ ieee80211_start_running(struct ieee80211 +@@ -1099,6 +1107,16 @@ ieee80211_start_running(struct ieee80211 /* NB: avoid recursion */ if ((dev->flags & IFF_UP) && !(dev->flags & IFF_RUNNING)) ieee80211_open(dev); @@ -1389,7 +1416,7 @@ } } EXPORT_SYMBOL(ieee80211_start_running); -@@ -1116,11 +1128,43 @@ ieee80211_stop(struct net_device *dev) +@@ -1116,11 +1134,43 @@ ieee80211_stop(struct net_device *dev) struct ieee80211vap *vap = dev->priv; struct ieee80211com *ic = vap->iv_ic; struct net_device *parent = ic->ic_dev; @@ -1433,7 +1460,7 @@ ieee80211_new_state(vap, IEEE80211_S_INIT, -1); if (dev->flags & IFF_RUNNING) { dev->flags &= ~IFF_RUNNING; /* mark us stopped */ -@@ -1148,7 +1192,7 @@ EXPORT_SYMBOL(ieee80211_stop); +@@ -1148,7 +1198,7 @@ EXPORT_SYMBOL(ieee80211_stop); void ieee80211_stop_running(struct ieee80211com *ic) { @@ -1442,7 +1469,7 @@ struct net_device *dev; /* XXX locking */ -@@ -1156,6 +1200,12 @@ ieee80211_stop_running(struct ieee80211c +@@ -1156,6 +1206,12 @@ ieee80211_stop_running(struct ieee80211c dev = vap->iv_dev; if (dev->flags & IFF_RUNNING) /* NB: avoid recursion */ ieee80211_stop(dev); @@ -1455,7 +1482,7 @@ } } EXPORT_SYMBOL(ieee80211_stop_running); -@@ -1342,9 +1392,9 @@ ieee80211_new_state(struct ieee80211vap +@@ -1342,9 +1398,9 @@ ieee80211_new_state(struct ieee80211vap struct ieee80211com *ic = vap->iv_ic; int rc; @@ -1467,7 +1494,7 @@ return rc; } -@@ -1557,57 +1607,12 @@ __ieee80211_newstate(struct ieee80211vap +@@ -1557,57 +1613,12 @@ __ieee80211_newstate(struct ieee80211vap switch (ostate) { case IEEE80211_S_INIT: if (vap->iv_opmode == IEEE80211_M_MONITOR || @@ -1525,7 +1552,7 @@ break; } /* fall thru... */ -@@ -1675,6 +1680,7 @@ __ieee80211_newstate(struct ieee80211vap +@@ -1675,6 +1686,7 @@ __ieee80211_newstate(struct ieee80211vap */ if (ni->ni_authmode != IEEE80211_AUTH_8021X) ieee80211_node_authorize(ni); @@ -1533,7 +1560,7 @@ #ifdef ATH_SUPERG_XR /* * fire a timer to bring up XR vap if configured. -@@ -1808,6 +1814,11 @@ ieee80211_newstate(struct ieee80211vap * +@@ -1808,6 +1820,11 @@ ieee80211_newstate(struct ieee80211vap * ieee80211_state_name[dstate]); ieee80211_update_link_status(vap, nstate, ostate); @@ -1545,7 +1572,7 @@ switch (nstate) { case IEEE80211_S_AUTH: case IEEE80211_S_ASSOC: -@@ -1930,8 +1941,15 @@ ieee80211_newstate(struct ieee80211vap * +@@ -1930,8 +1947,15 @@ ieee80211_newstate(struct ieee80211vap * if (ostate == IEEE80211_S_SCAN || ostate == IEEE80211_S_AUTH || ostate == IEEE80211_S_ASSOC) {