1 /* src/p80211/p80211req.c 2 * 3 * Request/Indication/MacMgmt interface handling functions 4 * 5 * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. 6 * -------------------------------------------------------------------- 7 * 8 * linux-wlan 9 * 10 * The contents of this file are subject to the Mozilla Public 11 * License Version 1.1 (the "License"); you may not use this file 12 * except in compliance with the License. You may obtain a copy of 13 * the License at http://www.mozilla.org/MPL/ 14 * 15 * Software distributed under the License is distributed on an "AS 16 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 17 * implied. See the License for the specific language governing 18 * rights and limitations under the License. 19 * 20 * Alternatively, the contents of this file may be used under the 21 * terms of the GNU Public License version 2 (the "GPL"), in which 22 * case the provisions of the GPL are applicable instead of the 23 * above. If you wish to allow the use of your version of this file 24 * only under the terms of the GPL and not to allow others to use 25 * your version of this file under the MPL, indicate your decision 26 * by deleting the provisions above and replace them with the notice 27 * and other provisions required by the GPL. If you do not delete 28 * the provisions above, a recipient may use your version of this 29 * file under either the MPL or the GPL. 30 * 31 * -------------------------------------------------------------------- 32 * 33 * Inquiries regarding the linux-wlan Open Source project can be 34 * made directly to: 35 * 36 * AbsoluteValue Systems Inc. 37 * info@linux-wlan.com 38 * http://www.linux-wlan.com 39 * 40 * -------------------------------------------------------------------- 41 * 42 * Portions of the development of this software were funded by 43 * Intersil Corporation as part of PRISM(R) chipset product development. 44 * 45 * -------------------------------------------------------------------- 46 * 47 * This file contains the functions, types, and macros to support the 48 * MLME request interface that's implemented via the device ioctls. 49 * 50 * -------------------------------------------------------------------- 51 */ 52 53 #include <linux/module.h> 54 #include <linux/kernel.h> 55 #include <linux/sched.h> 56 #include <linux/types.h> 57 #include <linux/skbuff.h> 58 #include <linux/wireless.h> 59 #include <linux/netdevice.h> 60 #include <linux/etherdevice.h> 61 #include <net/sock.h> 62 #include <linux/netlink.h> 63 64 #include "p80211types.h" 65 #include "p80211hdr.h" 66 #include "p80211mgmt.h" 67 #include "p80211conv.h" 68 #include "p80211msg.h" 69 #include "p80211netdev.h" 70 #include "p80211ioctl.h" 71 #include "p80211metadef.h" 72 #include "p80211metastruct.h" 73 #include "p80211req.h" 74 75 static void p80211req_handlemsg(struct wlandevice *wlandev, 76 struct p80211msg *msg); 77 static void p80211req_mibset_mibget(struct wlandevice *wlandev, 78 struct p80211msg_dot11req_mibget *mib_msg, 79 int isget); 80 81 static void p80211req_handle_action(struct wlandevice *wlandev, u32 *data, 82 int isget, u32 flag) 83 { 84 if (isget) { 85 if (wlandev->hostwep & flag) 86 *data = P80211ENUM_truth_true; 87 else 88 *data = P80211ENUM_truth_false; 89 } else { 90 wlandev->hostwep &= ~flag; 91 if (*data == P80211ENUM_truth_true) 92 wlandev->hostwep |= flag; 93 } 94 } 95 96 /*---------------------------------------------------------------- 97 * p80211req_dorequest 98 * 99 * Handles an MLME request/confirm message. 100 * 101 * Arguments: 102 * wlandev WLAN device struct 103 * msgbuf Buffer containing a request message 104 * 105 * Returns: 106 * 0 on success, an errno otherwise 107 * 108 * Call context: 109 * Potentially blocks the caller, so it's a good idea to 110 * not call this function from an interrupt context. 111 *---------------------------------------------------------------- 112 */ 113 int p80211req_dorequest(struct wlandevice *wlandev, u8 *msgbuf) 114 { 115 struct p80211msg *msg = (struct p80211msg *)msgbuf; 116 117 /* Check to make sure the MSD is running */ 118 if (!((wlandev->msdstate == WLAN_MSD_HWPRESENT && 119 msg->msgcode == DIDmsg_lnxreq_ifstate) || 120 wlandev->msdstate == WLAN_MSD_RUNNING || 121 wlandev->msdstate == WLAN_MSD_FWLOAD)) { 122 return -ENODEV; 123 } 124 125 /* Check Permissions */ 126 if (!capable(CAP_NET_ADMIN) && 127 (msg->msgcode != DIDmsg_dot11req_mibget)) { 128 netdev_err(wlandev->netdev, 129 "%s: only dot11req_mibget allowed for non-root.\n", 130 wlandev->name); 131 return -EPERM; 132 } 133 134 /* Check for busy status */ 135 if (test_and_set_bit(1, &wlandev->request_pending)) 136 return -EBUSY; 137 138 /* Allow p80211 to look at msg and handle if desired. */ 139 /* So far, all p80211 msgs are immediate, no waitq/timer necessary */ 140 /* This may change. */ 141 p80211req_handlemsg(wlandev, msg); 142 143 /* Pass it down to wlandev via wlandev->mlmerequest */ 144 if (wlandev->mlmerequest) 145 wlandev->mlmerequest(wlandev, msg); 146 147 clear_bit(1, &wlandev->request_pending); 148 return 0; /* if result==0, msg->status still may contain an err */ 149 } 150 151 /*---------------------------------------------------------------- 152 * p80211req_handlemsg 153 * 154 * p80211 message handler. Primarily looks for messages that 155 * belong to p80211 and then dispatches the appropriate response. 156 * TODO: we don't do anything yet. Once the linuxMIB is better 157 * defined we'll need a get/set handler. 158 * 159 * Arguments: 160 * wlandev WLAN device struct 161 * msg message structure 162 * 163 * Returns: 164 * nothing (any results are set in the status field of the msg) 165 * 166 * Call context: 167 * Process thread 168 *---------------------------------------------------------------- 169 */ 170 static void p80211req_handlemsg(struct wlandevice *wlandev, 171 struct p80211msg *msg) 172 { 173 switch (msg->msgcode) { 174 case DIDmsg_lnxreq_hostwep:{ 175 struct p80211msg_lnxreq_hostwep *req = 176 (struct p80211msg_lnxreq_hostwep *)msg; 177 wlandev->hostwep &= 178 ~(HOSTWEP_DECRYPT | HOSTWEP_ENCRYPT); 179 if (req->decrypt.data == P80211ENUM_truth_true) 180 wlandev->hostwep |= HOSTWEP_DECRYPT; 181 if (req->encrypt.data == P80211ENUM_truth_true) 182 wlandev->hostwep |= HOSTWEP_ENCRYPT; 183 184 break; 185 } 186 case DIDmsg_dot11req_mibget: 187 case DIDmsg_dot11req_mibset:{ 188 int isget = (msg->msgcode == DIDmsg_dot11req_mibget); 189 struct p80211msg_dot11req_mibget *mib_msg = 190 (struct p80211msg_dot11req_mibget *)msg; 191 p80211req_mibset_mibget(wlandev, mib_msg, isget); 192 break; 193 } 194 } /* switch msg->msgcode */ 195 } 196 197 static void p80211req_mibset_mibget(struct wlandevice *wlandev, 198 struct p80211msg_dot11req_mibget *mib_msg, 199 int isget) 200 { 201 struct p80211itemd *mibitem = 202 (struct p80211itemd *)mib_msg->mibattribute.data; 203 struct p80211pstrd *pstr = (struct p80211pstrd *)mibitem->data; 204 u8 *key = mibitem->data + sizeof(struct p80211pstrd); 205 206 switch (mibitem->did) { 207 case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(1): 208 case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(2): 209 case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(3): 210 case DIDmib_dot11smt_dot11WEPDefaultKeysTable_key(4): 211 if (!isget) 212 wep_change_key(wlandev, 213 P80211DID_ITEM(mibitem->did) - 1, 214 key, pstr->len); 215 break; 216 217 case DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID:{ 218 u32 *data = (u32 *)mibitem->data; 219 220 if (isget) { 221 *data = wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; 222 } else { 223 wlandev->hostwep &= ~(HOSTWEP_DEFAULTKEY_MASK); 224 wlandev->hostwep |= (*data & HOSTWEP_DEFAULTKEY_MASK); 225 } 226 break; 227 } 228 case DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked:{ 229 u32 *data = (u32 *)mibitem->data; 230 231 p80211req_handle_action(wlandev, data, isget, 232 HOSTWEP_PRIVACYINVOKED); 233 break; 234 } 235 case DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted:{ 236 u32 *data = (u32 *)mibitem->data; 237 238 p80211req_handle_action(wlandev, data, isget, 239 HOSTWEP_EXCLUDEUNENCRYPTED); 240 break; 241 } 242 } 243 } 244