From 1033c7b8a4283c20208394d8e75b8608dd2710a1 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Sat, 22 Mar 2014 18:44:28 +0100
Subject: [PATCH 1/2] kernel/802_11: Fix panic when the desired ratectl
 algorithm is unavailable.

Set the default to NONE. When a driver calls ieee80211_ratectl_init(), try
to use AMRR etc. if NONE is selected. Drivers may still select other
algorithms using ieee80211_ratectl_set() prior to calling _init().

Due to our broken ieee80211_load_module(), we do not currently autoload
the desired ratectl algorithm like FreeBSD does. Instead, a message about
manually loading the module will be printed (see ieee80211_dragonfly.c).

Reported-by: profmakx
Taken-from:  FreeBSD
---
 sys/conf/files                                    |   1 +
 sys/netproto/802_11/ieee80211_ratectl.h           |  20 +--
 sys/netproto/802_11/wlan/Makefile                 |   4 +-
 sys/netproto/802_11/wlan/ieee80211_ratectl.c      |  28 +++-
 sys/netproto/802_11/wlan/ieee80211_ratectl_none.c | 155 ++++++++++------------
 5 files changed, 104 insertions(+), 104 deletions(-)

diff --git a/sys/conf/files b/sys/conf/files
index 2e8eadd..660c858 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1232,6 +1232,7 @@ netproto/802_11/wlan/ieee80211_power.c      optional wlan
 netproto/802_11/wlan/ieee80211_proto.c      optional wlan
 netproto/802_11/wlan/ieee80211_radiotap.c   optional wlan
 netproto/802_11/wlan/ieee80211_ratectl.c    optional wlan
+netproto/802_11/wlan/ieee80211_ratectl_none.c optional wlan
 netproto/802_11/wlan/ieee80211_regdomain.c  optional wlan
 netproto/802_11/wlan/ieee80211_rssadapt.c   optional wlan_rssadapt
 netproto/802_11/wlan/ieee80211_scan.c       optional wlan
diff --git a/sys/netproto/802_11/ieee80211_ratectl.h b/sys/netproto/802_11/ieee80211_ratectl.h
index b652e80..37e80e4 100644
--- a/sys/netproto/802_11/ieee80211_ratectl.h
+++ b/sys/netproto/802_11/ieee80211_ratectl.h
@@ -22,14 +22,15 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/net80211/ieee80211_ratectl.h 206398 2010-04-08 13:34:08Z rpaulo $
+ * $FreeBSD: head/sys/net80211/ieee80211_ratectl.h 215289 2010-11-14 09:59:52Z bschmidt $
  */
 
 enum ieee80211_ratealgs {
-	IEEE80211_RATECTL_AMRR 		= 0,
+	IEEE80211_RATECTL_AMRR		= 0,
 	IEEE80211_RATECTL_RSSADAPT	= 1,
 	IEEE80211_RATECTL_ONOE		= 2,
 	IEEE80211_RATECTL_SAMPLE	= 3,
+	IEEE80211_RATECTL_NONE		= 4,
 	IEEE80211_RATECTL_MAX
 };
 
@@ -56,17 +57,12 @@ struct ieee80211_ratectl {
 
 void	ieee80211_ratectl_register(int, const struct ieee80211_ratectl *);
 void	ieee80211_ratectl_unregister(int);
+void	ieee80211_ratectl_init(struct ieee80211vap *);
 void	ieee80211_ratectl_set(struct ieee80211vap *, int);
 
 MALLOC_DECLARE(M_80211_RATECTL);
 
 static __inline void
-ieee80211_ratectl_init(struct ieee80211vap *vap)
-{
-	vap->iv_rate->ir_init(vap);
-}
-
-static __inline void
 ieee80211_ratectl_deinit(struct ieee80211vap *vap)
 {
 	vap->iv_rate->ir_deinit(vap);
@@ -85,8 +81,6 @@ ieee80211_ratectl_node_deinit(struct ieee80211_node *ni)
 {
 	const struct ieee80211vap *vap = ni->ni_vap;
 
-	if (ni->ni_rctls == NULL)	/* ratectl not setup */
-		return;
 	vap->iv_rate->ir_node_deinit(ni);
 }
 
@@ -95,8 +89,6 @@ ieee80211_ratectl_rate(struct ieee80211_node *ni, void *arg, uint32_t iarg)
 {
 	const struct ieee80211vap *vap = ni->ni_vap;
 
-	if (ni->ni_rctls == NULL)	/* ratectl not setup */
-		return 0;
 	return vap->iv_rate->ir_rate(ni, arg, iarg);
 }
 
@@ -104,8 +96,6 @@ static __inline void
 ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap,
     const struct ieee80211_node *ni, int status, void *arg1, void *arg2)
 {
-	if (ni->ni_rctls == NULL)	/* ratectl not setup */
-		return;
 	vap->iv_rate->ir_tx_complete(vap, ni, status, arg1, arg2);
 }
 
@@ -115,8 +105,6 @@ ieee80211_ratectl_tx_update(const struct ieee80211vap *vap,
 {
 	if (vap->iv_rate->ir_tx_update == NULL)
 		return;
-	if (ni->ni_rctls == NULL)	/* ratectl not setup */
-		return;
 	vap->iv_rate->ir_tx_update(vap, ni, arg1, arg2, arg3);
 }
 
diff --git a/sys/netproto/802_11/wlan/Makefile b/sys/netproto/802_11/wlan/Makefile
index e71893d..4d2ea39 100644
--- a/sys/netproto/802_11/wlan/Makefile
+++ b/sys/netproto/802_11/wlan/Makefile
@@ -1,5 +1,3 @@
-# $DragonFly: src/sys/netproto/802_11/wlan/Makefile,v 1.6 2006/09/01 15:12:11 sephe Exp $
-
 KMOD	 = wlan
 SRCS	 = ieee80211.c ieee80211_action.c ieee80211_adhoc.c ieee80211_ageq.c
 #SRCS	+= ieee80211_amrr.c
@@ -9,7 +7,7 @@ SRCS	+= ieee80211_ht.c ieee80211_hwmp.c ieee80211_input.c ieee80211_ioctl.c
 SRCS	+= ieee80211_mesh.c ieee80211_monitor.c ieee80211_node.c
 SRCS	+= ieee80211_output.c ieee80211_phy.c ieee80211_power.c
 SRCS	+= ieee80211_proto.c ieee80211_radiotap.c
-SRCS	+= ieee80211_ratectl.c 
+SRCS	+= ieee80211_ratectl.c ieee80211_ratectl_none.c
 SRCS	+= ieee80211_regdomain.c ieee80211_rssadapt.c
 SRCS	+= ieee80211_scan.c ieee80211_scan_sta.c ieee80211_sta.c
 SRCS	+= ieee80211_superg.c ieee80211_tdma.c ieee80211_wds.c
diff --git a/sys/netproto/802_11/wlan/ieee80211_ratectl.c b/sys/netproto/802_11/wlan/ieee80211_ratectl.c
index e66aabc..cea3e59 100644
--- a/sys/netproto/802_11/wlan/ieee80211_ratectl.c
+++ b/sys/netproto/802_11/wlan/ieee80211_ratectl.c
@@ -22,7 +22,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: head/sys/net80211/ieee80211_ratectl.c 206358 2010-04-07 15:29:13Z rpaulo $
+ * $FreeBSD: head/sys/net80211/ieee80211_ratectl.c 214894 2010-11-06 18:17:20Z bschmidt $
  */
 
 #include <sys/param.h>
@@ -38,6 +38,14 @@
 
 static const struct ieee80211_ratectl *ratectls[IEEE80211_RATECTL_MAX];
 
+static const char *ratectl_modnames[IEEE80211_RATECTL_MAX] = {
+	[IEEE80211_RATECTL_AMRR]	= "wlan_amrr",
+	[IEEE80211_RATECTL_RSSADAPT]	= "wlan_rssadapt",
+	[IEEE80211_RATECTL_ONOE]	= "wlan_onoe",
+	[IEEE80211_RATECTL_SAMPLE]	= "wlan_sample",
+	[IEEE80211_RATECTL_NONE]	= "wlan_none",
+};
+
 MALLOC_DEFINE(M_80211_RATECTL, "80211ratectl", "802.11 rate control");
 
 void
@@ -57,9 +65,27 @@ ieee80211_ratectl_unregister(int type)
 }
 
 void
+ieee80211_ratectl_init(struct ieee80211vap *vap)
+{
+	if (vap->iv_rate == ratectls[IEEE80211_RATECTL_NONE])
+		ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR);
+	vap->iv_rate->ir_init(vap);
+}
+
+void
 ieee80211_ratectl_set(struct ieee80211vap *vap, int type)
 {
 	if (type >= IEEE80211_RATECTL_MAX)
 		return;
+	if (ratectls[type] == NULL) {
+		ieee80211_load_module(ratectl_modnames[type]);
+		if (ratectls[type] == NULL) {
+			IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL,
+			    "%s: unable to load algo %u, module %s\n",
+			    __func__, type, ratectl_modnames[type]);
+			vap->iv_rate = ratectls[IEEE80211_RATECTL_NONE];
+			return;
+		}
+	}
 	vap->iv_rate = ratectls[type];
 }
diff --git a/sys/netproto/802_11/wlan/ieee80211_ratectl_none.c b/sys/netproto/802_11/wlan/ieee80211_ratectl_none.c
index 6b2a591..0b745d9 100644
--- a/sys/netproto/802_11/wlan/ieee80211_ratectl_none.c
+++ b/sys/netproto/802_11/wlan/ieee80211_ratectl_none.c
@@ -1,129 +1,116 @@
-/*
- * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
- * 
- * This code is derived from software contributed to The DragonFly Project
- * by Sepherosa Ziehau <sepherosa@gmail.com>
- * 
+/*-
+ * Copyright (c) 2010 Bernhard Schmidt <bschmidt@FreeBSD.org>
+ * All rights reserved.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name of The DragonFly Project nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific, prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * 
- * $DragonFly: src/sys/netproto/802_11/wlan/ieee80211_ratectl_none.c,v 1.3 2008/01/15 09:01:13 sephe Exp $
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: head/sys/net80211/ieee80211_ratectl_none.c 257179 2013-10-26 18:18:50Z glebius $
  */
 
+#include "opt_wlan.h"
+
 #include <sys/param.h>
+#include <sys/systm.h>
 #include <sys/kernel.h>
- 
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
 #include <net/if.h>
 #include <net/if_media.h>
-#include <net/if_arp.h>
-
-#include <netproto/802_11/ieee80211_var.h>
+#include <net/ethernet.h>
 
-static void	*none_ratectl_attach(struct ieee80211vap *);
-static void	none_ratectl_detach(void *);
-static void none_ratectl_init(struct ieee80211vap *);
-static void none_ratectl_deinit(struct ieee80211vap *);
-static void none_ratectl_node_init(struct ieee80211_node *);
-static void none_ratectl_node_deinit(struct ieee80211_node *);
-static void none_ratectl_rate(struct ieee80211vap *, void *, uint32_t);
-static void	none_ratectl_tx_complete(const struct ieee80211vap *,
-			struct ieee80211_node *, int, void *, void *);
-static void none_ratectl_tx_update(const struct ieee80211vap *,
-			const struct ieee80211_node *, void *, void *, void *);
-static void none_ratectl_setinterval(const struct ieee80211vap *, int);
-
-const struct ieee80211_ratectl ieee80211_ratectl_none = {
-	.rc_name	= "none",
-	.rc_attach	= none_ratectl_attach,
-	.rc_detach	= none_ratectl_detach,
-	.rc_init	= none_ratectl_init,
-	.rc_deinit	= none_ratectl_deinit,
-	.rc_node_init	= none_ratectl_node_init,
-	.rc_node_deinit	= none_ratectl_node_deinit,
-	.rc_rate = none_ratectl_rate,
-	.rc_tx_complete	= none_ratectl_tx_complete,
-	.rc_tx_update = none_ratectl_tx_update,
-	.rc_setinterval = none_ratectl_setinterval,
-};
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
 
-IEEE80211_RATECTL_MODULE(ieee80211_ratectl_none, 1);
-IEEE80211_RATECTL_ALG(ieee80211_ratectl_none, IEEE80211_RATECTL_NONE,
-	ieee80211_ratectl_none);
+#include <netproto/802_11/ieee80211_var.h>
+#include <netproto/802_11/ieee80211_ratectl.h>
 
 static void
-none_ratectl_setinterval(const struct ieee80211vap *vap __unused,
-	int msecs __unused)
+none_init(struct ieee80211vap *vap)
 {
 }
 
-static void *
-none_ratectl_attach(struct ieee80211vap *vap)
-{
-	struct ieee80211_ratectl_state *rc_st = &vap->iv_ratectl;
-
-	rc_st->rc_st_attach(vap, IEEE80211_RATECTL_NONE);
-	return NULL;
-}
-
 static void
-none_ratectl_detach(void *arg __unused)
+none_deinit(struct ieee80211vap *vap)
 {
+	kfree(vap->iv_rs, M_80211_RATECTL);
 }
 
 static void
-none_ratectl_init(struct ieee80211vap *vap __unused)
+none_node_init(struct ieee80211_node *ni)
 {
+	ni->ni_txrate = ni->ni_rates.rs_rates[0] & IEEE80211_RATE_VAL;
 }
 
 static void
-none_ratectl_deinit(struct ieee80211vap *vap __unused)
+none_node_deinit(struct ieee80211_node *ni)
 {
 }
 
-static void
-none_ratectl_node_init(struct ieee80211_node *ni __unused)
+static int
+none_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused)
 {
+	int rix = 0;
+
+	ni->ni_txrate = ni->ni_rates.rs_rates[rix] & IEEE80211_RATE_VAL;
+	return rix;
 }
 
 static void
-none_ratectl_node_deinit(struct ieee80211_node *ni __unused)
+none_tx_complete(const struct ieee80211vap *vap,
+    const struct ieee80211_node *ni, int ok,
+    void *arg1, void *arg2 __unused)
 {
 }
 
 static void
-none_ratectl_tx_complete(const struct ieee80211vap *vap __unused,
-			 struct ieee80211_node *ni __unused, int ok __unused,
-			 void *arg1 __unused, void *arg2 __unused)
+none_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *ni,
+    void *arg1, void *arg2, void *arg3)
 {
 }
 
 static void
-none_ratectl_tx_update(const struct ieee80211vap *vap __unused,
-			 const struct ieee80211_node *ni __unused,
-			 void *arg1 __unused, void *arg2 __unused, void *arg3 __unused)
+none_setinterval(const struct ieee80211vap *vap, int msecs)
 {
 }
+
+/* number of references from net80211 layer */
+static	int nrefs = 0;
+
+static const struct ieee80211_ratectl none = {
+	.ir_name	= "none",
+	.ir_attach	= NULL,
+	.ir_detach	= NULL,
+	.ir_init	= none_init,
+	.ir_deinit	= none_deinit,
+	.ir_node_init	= none_node_init,
+	.ir_node_deinit	= none_node_deinit,
+	.ir_rate	= none_rate,
+	.ir_tx_complete	= none_tx_complete,
+	.ir_tx_update	= none_tx_update,
+	.ir_setinterval	= none_setinterval,
+};
+IEEE80211_RATECTL_MODULE(ratectl_none, 1);
+IEEE80211_RATECTL_ALG(none, IEEE80211_RATECTL_NONE, none);
-- 
1.8.2.2

