if_wi patch

Ritz, Bruno bruno_ritz at gmx.ch
Mon Jun 23 12:15:52 PDT 2003


hi

i recently found messages about problems with the if_wi driver in 5.1 (it worked
in 5.0-release).

i have a patch for this. it brings back missing features (wep, authmode etc). i
could not test it for every possible case but it works fine for my network.


regards
bruno




--- if_wi.c.orig	Sun Jun  8 02:32:57 2003
+++ if_wi.c	Sun Jun  8 02:33:20 2003
@@ -48,7 +48,7 @@
  * without an NDA (if at all). What they do release is an API library
  * called the HCF (Hardware Control Functions) which is supposed to
  * do the device-specific operations of a device driver for you. The
- * publically available version of the HCF library (the 'HCF Light') is
+ * publically available version of the HCF library (the 'HCF Light') is
  * a) extremely gross, b) lacks certain features, particularly support
  * for 802.11 frames, and c) is contaminated by the GNU Public License.
  *
@@ -848,7 +848,7 @@
 			}
 			IFQ_DEQUEUE(&ifp->if_snd, m0);
 			ifp->if_opackets++;
-			m_copydata(m0, 0, ETHER_HDR_LEN,
+			m_copydata(m0, 0, ETHER_HDR_LEN,
 			    (caddr_t)&frmhdr.wi_ehdr);
 #if NBPFILTER > 0
 			BPF_MTAP(ifp, m0);
@@ -858,7 +858,7 @@
 				ifp->if_oerrors++;
 				continue;
 			}
-                        wh = mtod(m0, struct ieee80211_frame *);
+			wh = mtod(m0, struct ieee80211_frame *);
 			if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
 			    !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
 			    (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
@@ -942,7 +942,7 @@
 	int i;
 	int error = 0;
 	int tries;
-
+
 	/* Symbol firmware cannot be initialized more than once */
 	if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_reset)
 		return (0);
@@ -1024,7 +1024,7 @@
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ifreq *ifr = (struct ifreq *)data;
 	struct ieee80211req *ireq;
-	u_int8_t nodename[IEEE80211_NWID_LEN];
+	/* u_int8_t nodename[IEEE80211_NWID_LEN]; */
 	int error = 0;
 #if __FreeBSD_version >= 500000
 	struct thread *td = curthread;
@@ -1032,6 +1032,10 @@
 	struct proc *td = curproc;		/* Little white lie */
 #endif
 	struct wi_req wreq;
+
+	char tmpkey[IEEE80211_KEYBUF_SIZE];
+	int len;
+
 	WI_LOCK_DECL();

 	WI_LOCK(sc);
@@ -1112,11 +1116,80 @@
 	case SIOCG80211:
 		ireq = (struct ieee80211req *) data;
 		switch (ireq->i_type) {
+		case IEEE80211_IOC_SSID:
+			if ((ireq->i_val == -1) || (ireq->i_val == 0)) {
+				error = copyout(sc->sc_net_name,
+				    ireq->i_data,
+				    IEEE80211_NWID_LEN);
+				ireq->i_len = IEEE80211_NWID_LEN;
+			} else
+				error = EINVAL;
+			break;
+		case IEEE80211_IOC_NUMSSIDS:
+			ireq->i_val = 1;
+			break;
+		case IEEE80211_IOC_WEP:
+			if (!(sc->sc_ic.ic_flags & IEEE80211_F_HASWEP)) {
+				ireq->i_val = IEEE80211_WEP_NOSUP;
+			} else {
+				if (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) {
+					ireq->i_val =
+					    IEEE80211_WEP_MIXED;
+				} else {
+					ireq->i_val =
+					    IEEE80211_WEP_OFF;
+				}
+			}
+			break;
+		case IEEE80211_IOC_WEPKEY:
+			if (!(sc->sc_ic.ic_flags & IEEE80211_F_HASWEP) ||
+			    ireq->i_val < 0 || ireq->i_val > 3) {
+				error = EINVAL;
+				break;
+			}
+			len = sc->sc_ic.ic_nw_keys[ireq->i_val].wk_len;
+			if (suser(td))
+				bcopy(sc->sc_ic.ic_nw_keys[ireq->i_val].wk_key,
+				    &tmpkey, len);
+			else
+				bzero(&tmpkey, len);
+
+			ireq->i_len = len;
+			error = copyout(&tmpkey, ireq->i_data, len);
+
+			break;
+		case IEEE80211_IOC_NUMWEPKEYS:
+			if (!(sc->sc_ic.ic_flags & IEEE80211_F_HASWEP))
+				error = EINVAL;
+			else
+				ireq->i_val = 4;
+			break;
+		case IEEE80211_IOC_WEPTXKEY:
+			if (!(sc->sc_ic.ic_flags & IEEE80211_F_HASWEP))
+				error = EINVAL;
+			else
+				ireq->i_val = sc->sc_ic.ic_wep_txkey;
+			break;
+		case IEEE80211_IOC_AUTHMODE:
+			ireq->i_val = sc->sc_cnfauthmode;
+			break;
 		case IEEE80211_IOC_STATIONNAME:
 			ireq->i_len = sc->sc_nodelen + 1;
 			error = copyout(sc->sc_nodename, ireq->i_data,
 					ireq->i_len);
 			break;
+		case IEEE80211_IOC_CHANNEL:
+				ireq->i_val = sc->sc_ic.ic_ibss_chan;
+			break;
+		case IEEE80211_IOC_POWERSAVE:
+			if (sc->sc_ic.ic_flags & IEEE80211_F_PMGTON)
+				ireq->i_val = IEEE80211_POWERSAVE_ON;
+			else
+				ireq->i_val = IEEE80211_POWERSAVE_OFF;
+			break;
+		case IEEE80211_IOC_POWERSAVESLEEP:
+			ireq->i_val = sc->sc_ic.ic_lintval;
+			break;
 		default:
 			error = ieee80211_ioctl(ifp, cmd, data);
 			break;
@@ -1128,30 +1201,106 @@
 			break;
 		ireq = (struct ieee80211req *) data;
 		switch (ireq->i_type) {
-		case IEEE80211_IOC_STATIONNAME:
+		case IEEE80211_IOC_SSID:
 			if (ireq->i_val != 0 ||
 			    ireq->i_len > IEEE80211_NWID_LEN) {
 				error = EINVAL;
 				break;
 			}
-			memset(nodename, 0, IEEE80211_NWID_LEN);
-			error = copyin(ireq->i_data, nodename, ireq->i_len);
-			if (error)
+			// We set both of them
+			bzero(sc->sc_net_name, IEEE80211_NWID_LEN);
+			error = copyin(ireq->i_data,
+			    sc->sc_net_name, ireq->i_len);
+			bcopy(sc->sc_net_name, sc->sc_ic.ic_bss.ni_essid, IEEE80211_NWID_LEN);
+			break;
+		case IEEE80211_IOC_WEP:
+			/*
+			 * These cards only support one mode so
+			 * we just turn wep on what ever is
+			 * passed in if it's not OFF.
+			 */
+			if (ireq->i_val == IEEE80211_WEP_OFF) {
+				sc->sc_ic.ic_flags = (sc->sc_ic.ic_flags | IEEE80211_F_WEPON) ^
IEEE80211_F_WEPON;
+			} else {
+				sc->sc_ic.ic_flags |= IEEE80211_F_WEPON;
+			}
+			break;
+		case IEEE80211_IOC_WEPKEY:
+			if (ireq->i_val < 0 || ireq->i_val > 3 ||
+				ireq->i_len > 13) {
+				error = EINVAL;
+				break;
+			}
+			bzero(sc->sc_ic.ic_nw_keys[ireq->i_val].wk_key, 13);
+			error = copyin(ireq->i_data,
+			    sc->sc_ic.ic_nw_keys[ireq->i_val].wk_key,
+			    ireq->i_len);
+			if(error) {
+				break;
+			}
+			sc->sc_ic.ic_nw_keys[ireq->i_val].wk_len =
+				    ireq->i_len;
+			break;
+		case IEEE80211_IOC_WEPTXKEY:
+			if (ireq->i_val < 0 || ireq->i_val > 3) {
+				error = EINVAL;
+				break;
+			}
+			sc->sc_ic.ic_wep_txkey = ireq->i_val;
+			break;
+		case IEEE80211_IOC_AUTHMODE:
+			sc->sc_cnfauthmode = ireq->i_val;
+			break;
+		case IEEE80211_IOC_STATIONNAME:
+			if (ireq->i_len > 32) {
+				error = EINVAL;
+				break;
+			}
+			bzero(sc->sc_nodename, 32);
+			error = copyin(ireq->i_data,
+			    sc->sc_nodename, ireq->i_len);
+			break;
+		case IEEE80211_IOC_CHANNEL:
+			/*
+			 * The actual range is 1-14, but if you
+			 * set it to 0 you get the default. So
+			 * we let that work too.
+			 */
+			if (ireq->i_val < 0 || ireq->i_val > 14) {
+				error = EINVAL;
+				break;
+			}
+			sc->sc_ic.ic_ibss_chan = ireq->i_val;
+			break;
+		case IEEE80211_IOC_POWERSAVE:
+			switch (ireq->i_val) {
+			case IEEE80211_POWERSAVE_OFF:
+				sc->sc_ic.ic_flags = (sc->sc_ic.ic_flags | IEEE80211_F_PMGTON) ^
IEEE80211_F_PMGTON;
+				break;
+			case IEEE80211_POWERSAVE_ON:
+				sc->sc_ic.ic_flags |= IEEE80211_F_PMGTON;
+				break;
+			default:
+				error = EINVAL;
 				break;
-			if (sc->sc_enabled) {
-				error = wi_write_ssid(sc, WI_RID_NODENAME,
-					nodename, ireq->i_len);
-				if (error)
-					break;
 			}
-			memcpy(sc->sc_nodename, nodename, IEEE80211_NWID_LEN);
-			sc->sc_nodelen = ireq->i_len;
+			break;
+		case IEEE80211_IOC_POWERSAVESLEEP:
+			if (ireq->i_val < 0) {
+				error = EINVAL;
+				break;
+			}
+			sc->sc_ic.ic_lintval= ireq->i_val;
 			break;
 		default:
 			error = ieee80211_ioctl(ifp, cmd, data);
 			break;
 		}
+
+		/* Reinitialize WaveLAN. */
+		//wi_init(sc);
 		break;
+
 	default:
 		error = ieee80211_ioctl(ifp, cmd, data);
 		break;
@@ -2146,7 +2295,7 @@
 {
 	int			i, s = 0;
 	static volatile int count  = 0;
-
+
 	if (count > 0)
 		panic("Hey partner, hold on there!");
 	count++;
@@ -2904,7 +3053,7 @@
 		    (const uint16_t *)p, len / 2);
 		p += len;
 	}
-
+
 	/*
 	 * PDR: id[4], address[4], length[4];
 	 */




More information about the freebsd-hackers mailing list