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