X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/537de4718f6800f9e0d64a64ce0133478877fdb8..88d51739a3144fc2a93cc1b99618f8324ffbc0ff:/package/madwifi/patches/370-wdsvap.patch diff --git a/package/madwifi/patches/370-wdsvap.patch b/package/madwifi/patches/370-wdsvap.patch index f35e65772..8a0e823ae 100644 --- a/package/madwifi/patches/370-wdsvap.patch +++ b/package/madwifi/patches/370-wdsvap.patch @@ -44,12 +44,13 @@ if (ic->ic_dev->flags & IFF_RUNNING) { /* needs to disable hardware too */ -@@ -1271,8 +1269,11 @@ ath_vap_create(struct ieee80211com *ic, +@@ -1271,8 +1269,12 @@ ath_vap_create(struct ieee80211com *ic, } else ic_opmode = opmode; break; - case IEEE80211_M_HOSTAP: case IEEE80211_M_WDS: ++ ic_opmode = ic->ic_opmode; + if (!master) + return NULL; + break; @@ -57,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 +1305,7 @@ ath_vap_create(struct ieee80211com *ic, +@@ -1304,7 +1306,7 @@ ath_vap_create(struct ieee80211com *ic, } avp = dev->priv; @@ -66,7 +67,7 @@ /* override with driver methods */ vap = &avp->av_vap; avp->av_newstate = vap->iv_newstate; -@@ -4209,8 +4210,7 @@ ath_calcrxfilter(struct ath_softc *sc) +@@ -4209,8 +4211,7 @@ ath_calcrxfilter(struct ath_softc *sc) if (ic->ic_opmode == IEEE80211_M_STA || sc->sc_opmode == HAL_M_IBSS || /* NB: AHDEMO too */ (sc->sc_nostabeacons) || sc->sc_scanning || @@ -76,7 +77,7 @@ rfilt |= HAL_RX_FILTER_BEACON; if (sc->sc_nmonvaps > 0) rfilt |= (HAL_RX_FILTER_CONTROL | HAL_RX_FILTER_BEACON | -@@ -9030,8 +9030,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 && @@ -123,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; @@ -527,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; @@ -680,14 +681,10 @@ } break; case IEEE80211_M_IBSS: -@@ -540,16 +548,32 @@ ieee80211_input(struct ieee80211vap * va +@@ -540,16 +548,28 @@ ieee80211_input(struct ieee80211vap * va 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 @@ -716,7 +713,7 @@ if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS)) { IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT, -@@ -557,7 +581,6 @@ ieee80211_input(struct ieee80211vap * va +@@ -557,7 +577,6 @@ ieee80211_input(struct ieee80211vap * va goto err; } wh4 = (struct ieee80211_frame_addr4 *)skb->data; @@ -724,7 +721,7 @@ ni_wds = ieee80211_find_wds_node(nt, wh4->i_addr4); /* Last call increments ref count if !NULL */ if ((ni_wds != NULL) && (ni_wds != ni)) { -@@ -608,6 +631,11 @@ ieee80211_input(struct ieee80211vap * va +@@ -608,6 +627,11 @@ ieee80211_input(struct ieee80211vap * va goto out; } @@ -736,7 +733,7 @@ /* * Handle privacy requirements. Note that we * must not be preempted from here until after -@@ -680,8 +708,12 @@ ieee80211_input(struct ieee80211vap * va +@@ -680,8 +704,12 @@ ieee80211_input(struct ieee80211vap * va if (! accept_data_frame(vap, ni, key, skb, eh)) goto out; @@ -751,21 +748,26 @@ IEEE80211_NODE_STAT(ni, rx_data); IEEE80211_NODE_STAT_ADD(ni, rx_bytes, skb->len); ic->ic_lastdata = jiffies; -@@ -1114,6 +1146,13 @@ ieee80211_deliver_data(struct ieee80211_ +@@ -1114,6 +1142,18 @@ ieee80211_deliver_data(struct ieee80211_ dev = vap->iv_xrvap->iv_dev; #endif + /* if the node has a wds subif, move data frames there, + * but keep EAP traffic on the master */ + if (ni->ni_subif && ((eh)->ether_type != __constant_htons(ETHERTYPE_PAE))) { -+ vap = ni->ni_subif; -+ dev = vap->iv_dev; ++ if (ni->ni_vap == ni->ni_subif) { ++ ieee80211_dev_kfree_skb(&skb); ++ return; ++ } else { ++ vap = ni->ni_subif; ++ dev = vap->iv_dev; ++ } + } + /* 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) && @@ -782,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) && @@ -792,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); @@ -812,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. */ @@ -852,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)); @@ -882,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); } @@ -902,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; } @@ -956,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); @@ -965,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; @@ -1014,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 { @@ -1034,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; @@ -1046,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); } @@ -1069,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 } } @@ -1080,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; + @@ -1106,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)); @@ -1142,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. */ @@ -1161,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); + } @@ -1353,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) { @@ -1362,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) { @@ -1371,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); @@ -1388,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; @@ -1432,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) { @@ -1441,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); @@ -1454,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; @@ -1466,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 || @@ -1524,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); @@ -1532,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); @@ -1544,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) {