]>
Commit | Line | Data |
---|---|---|
f7056d33 | 1 | // SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) |
00b3ed16 | 2 | /* src/p80211/p80211req.c |
3aa4ecf7 SP |
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 | */ | |
00b3ed16 | 53 | |
00b3ed16 GKH |
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> | |
00b3ed16 GKH |
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 | ||
00b3ed16 GKH |
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 | ||
c97efa34 SP |
76 | static void p80211req_handlemsg(struct wlandevice *wlandev, |
77 | struct p80211msg *msg); | |
c9573a8d | 78 | static void p80211req_mibset_mibget(struct wlandevice *wlandev, |
b1f3b305 SP |
79 | struct p80211msg_dot11req_mibget *mib_msg, |
80 | int isget); | |
00b3ed16 | 81 | |
2f479125 CB |
82 | static 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 | ||
00b3ed16 | 97 | /*---------------------------------------------------------------- |
3aa4ecf7 SP |
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 | */ | |
c9573a8d | 114 | int p80211req_dorequest(struct wlandevice *wlandev, u8 *msgbuf) |
00b3ed16 | 115 | { |
0e21fa46 | 116 | struct p80211msg *msg = (struct p80211msg *)msgbuf; |
00b3ed16 | 117 | |
00b3ed16 | 118 | /* Check to make sure the MSD is running */ |
b1de9675 | 119 | if (!((wlandev->msdstate == WLAN_MSD_HWPRESENT && |
eb7c161c | 120 | msg->msgcode == DIDMSG_LNXREQ_IFSTATE) || |
b1de9675 MM |
121 | wlandev->msdstate == WLAN_MSD_RUNNING || |
122 | wlandev->msdstate == WLAN_MSD_FWLOAD)) { | |
00b3ed16 GKH |
123 | return -ENODEV; |
124 | } | |
125 | ||
126 | /* Check Permissions */ | |
67a7b378 | 127 | if (!capable(CAP_NET_ADMIN) && |
08ac8573 | 128 | (msg->msgcode != DIDMSG_DOT11REQ_MIBGET)) { |
02d9b1eb VO |
129 | netdev_err(wlandev->netdev, |
130 | "%s: only dot11req_mibget allowed for non-root.\n", | |
131 | wlandev->name); | |
00b3ed16 GKH |
132 | return -EPERM; |
133 | } | |
134 | ||
135 | /* Check for busy status */ | |
d4e1818a | 136 | if (test_and_set_bit(1, &wlandev->request_pending)) |
00b3ed16 | 137 | return -EBUSY; |
00b3ed16 GKH |
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 */ | |
6c55d50e | 145 | if (wlandev->mlmerequest) |
00b3ed16 GKH |
146 | wlandev->mlmerequest(wlandev, msg); |
147 | ||
d4e1818a | 148 | clear_bit(1, &wlandev->request_pending); |
4764ca98 | 149 | return 0; /* if result==0, msg->status still may contain an err */ |
00b3ed16 GKH |
150 | } |
151 | ||
152 | /*---------------------------------------------------------------- | |
3aa4ecf7 SP |
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 | */ | |
c97efa34 SP |
171 | static void p80211req_handlemsg(struct wlandevice *wlandev, |
172 | struct p80211msg *msg) | |
00b3ed16 | 173 | { |
00b3ed16 | 174 | switch (msg->msgcode) { |
27575665 | 175 | case DIDMSG_LNXREQ_HOSTWEP: { |
009629ef | 176 | struct p80211msg_lnxreq_hostwep *req = |
0e21fa46 | 177 | (struct p80211msg_lnxreq_hostwep *)msg; |
009629ef DN |
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; | |
00b3ed16 | 184 | |
27575665 | 185 | break; |
009629ef | 186 | } |
08ac8573 | 187 | case DIDMSG_DOT11REQ_MIBGET: |
27575665 | 188 | case DIDMSG_DOT11REQ_MIBSET: { |
08ac8573 | 189 | int isget = (msg->msgcode == DIDMSG_DOT11REQ_MIBGET); |
009629ef | 190 | struct p80211msg_dot11req_mibget *mib_msg = |
0e21fa46 | 191 | (struct p80211msg_dot11req_mibget *)msg; |
009629ef | 192 | p80211req_mibset_mibget(wlandev, mib_msg, isget); |
27575665 | 193 | break; |
009629ef | 194 | } |
b1de9675 | 195 | } /* switch msg->msgcode */ |
00b3ed16 GKH |
196 | } |
197 | ||
c9573a8d | 198 | static void p80211req_mibset_mibget(struct wlandevice *wlandev, |
b1f3b305 SP |
199 | struct p80211msg_dot11req_mibget *mib_msg, |
200 | int isget) | |
00b3ed16 | 201 | { |
17475c50 IC |
202 | struct p80211itemd *mibitem = |
203 | (struct p80211itemd *)mib_msg->mibattribute.data; | |
3fd1e3fc SP |
204 | struct p80211pstrd *pstr = (struct p80211pstrd *)mibitem->data; |
205 | u8 *key = mibitem->data + sizeof(struct p80211pstrd); | |
00b3ed16 | 206 | |
00b3ed16 | 207 | switch (mibitem->did) { |
ce0f34e4 TC |
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): | |
7694538c | 212 | if (!isget) |
37f92cf0 CB |
213 | wep_change_key(wlandev, |
214 | P80211DID_ITEM(mibitem->did) - 1, | |
215 | key, pstr->len); | |
216 | break; | |
217 | ||
27575665 | 218 | case DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID: { |
0e21fa46 | 219 | u32 *data = (u32 *)mibitem->data; |
00b3ed16 | 220 | |
7694538c DN |
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); | |
b1de9675 | 226 | } |
27575665 | 227 | break; |
7694538c | 228 | } |
27575665 | 229 | case DIDMIB_DOT11SMT_PRIVACYTABLE_PRIVACYINVOKED: { |
0e21fa46 | 230 | u32 *data = (u32 *)mibitem->data; |
7694538c | 231 | |
2f479125 CB |
232 | p80211req_handle_action(wlandev, data, isget, |
233 | HOSTWEP_PRIVACYINVOKED); | |
27575665 | 234 | break; |
7694538c | 235 | } |
27575665 | 236 | case DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED: { |
0e21fa46 | 237 | u32 *data = (u32 *)mibitem->data; |
7694538c | 238 | |
2f479125 CB |
239 | p80211req_handle_action(wlandev, data, isget, |
240 | HOSTWEP_EXCLUDEUNENCRYPTED); | |
27575665 | 241 | break; |
7694538c | 242 | } |
00b3ed16 | 243 | } |
00b3ed16 | 244 | } |