Commit | Line | Data |
---|---|---|
00b3ed16 GKH |
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 | ||
00b3ed16 GKH |
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/slab.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 | ||
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 | ||
297f06ce MT |
76 | static void p80211req_handlemsg(wlandevice_t *wlandev, p80211msg_t *msg); |
77 | static int p80211req_mibset_mibget(wlandevice_t *wlandev, | |
78 | p80211msg_dot11req_mibget_t *mib_msg, | |
b1de9675 | 79 | int isget); |
00b3ed16 GKH |
80 | |
81 | /*---------------------------------------------------------------- | |
82 | * p80211req_dorequest | |
83 | * | |
84 | * Handles an MLME reqest/confirm message. | |
85 | * | |
86 | * Arguments: | |
87 | * wlandev WLAN device struct | |
88 | * msgbuf Buffer containing a request message | |
89 | * | |
90 | * Returns: | |
91 | * 0 on success, an errno otherwise | |
92 | * | |
93 | * Call context: | |
94 | * Potentially blocks the caller, so it's a good idea to | |
95 | * not call this function from an interrupt context. | |
96 | ----------------------------------------------------------------*/ | |
75f49e07 | 97 | int p80211req_dorequest(wlandevice_t * wlandev, u8 * msgbuf) |
00b3ed16 | 98 | { |
b1de9675 MM |
99 | int result = 0; |
100 | p80211msg_t *msg = (p80211msg_t *) msgbuf; | |
00b3ed16 | 101 | |
00b3ed16 | 102 | /* Check to make sure the MSD is running */ |
b1de9675 MM |
103 | if (!((wlandev->msdstate == WLAN_MSD_HWPRESENT && |
104 | msg->msgcode == DIDmsg_lnxreq_ifstate) || | |
105 | wlandev->msdstate == WLAN_MSD_RUNNING || | |
106 | wlandev->msdstate == WLAN_MSD_FWLOAD)) { | |
00b3ed16 GKH |
107 | return -ENODEV; |
108 | } | |
109 | ||
110 | /* Check Permissions */ | |
b1de9675 MM |
111 | if (!capable(CAP_NET_ADMIN) && (msg->msgcode != DIDmsg_dot11req_mibget)) { |
112 | printk(KERN_ERR | |
113 | "%s: only dot11req_mibget allowed for non-root.\n", | |
114 | wlandev->name); | |
00b3ed16 GKH |
115 | return -EPERM; |
116 | } | |
117 | ||
118 | /* Check for busy status */ | |
b1de9675 | 119 | if (test_and_set_bit(1, &(wlandev->request_pending))) |
00b3ed16 | 120 | return -EBUSY; |
00b3ed16 GKH |
121 | |
122 | /* Allow p80211 to look at msg and handle if desired. */ | |
123 | /* So far, all p80211 msgs are immediate, no waitq/timer necessary */ | |
124 | /* This may change. */ | |
125 | p80211req_handlemsg(wlandev, msg); | |
126 | ||
127 | /* Pass it down to wlandev via wlandev->mlmerequest */ | |
b1de9675 | 128 | if (wlandev->mlmerequest != NULL) |
00b3ed16 GKH |
129 | wlandev->mlmerequest(wlandev, msg); |
130 | ||
b1de9675 | 131 | clear_bit(1, &(wlandev->request_pending)); |
75f49e07 | 132 | return result; /* if result==0, msg->status still may contain an err */ |
00b3ed16 GKH |
133 | } |
134 | ||
135 | /*---------------------------------------------------------------- | |
136 | * p80211req_handlemsg | |
137 | * | |
138 | * p80211 message handler. Primarily looks for messages that | |
139 | * belong to p80211 and then dispatches the appropriate response. | |
140 | * TODO: we don't do anything yet. Once the linuxMIB is better | |
141 | * defined we'll need a get/set handler. | |
142 | * | |
143 | * Arguments: | |
144 | * wlandev WLAN device struct | |
145 | * msg message structure | |
146 | * | |
147 | * Returns: | |
148 | * nothing (any results are set in the status field of the msg) | |
149 | * | |
150 | * Call context: | |
151 | * Process thread | |
152 | ----------------------------------------------------------------*/ | |
297f06ce | 153 | static void p80211req_handlemsg(wlandevice_t *wlandev, p80211msg_t *msg) |
00b3ed16 | 154 | { |
00b3ed16 GKH |
155 | switch (msg->msgcode) { |
156 | ||
b1de9675 MM |
157 | case DIDmsg_lnxreq_hostwep:{ |
158 | p80211msg_lnxreq_hostwep_t *req = | |
159 | (p80211msg_lnxreq_hostwep_t *) msg; | |
160 | wlandev->hostwep &= | |
161 | ~(HOSTWEP_DECRYPT | HOSTWEP_ENCRYPT); | |
162 | if (req->decrypt.data == P80211ENUM_truth_true) | |
163 | wlandev->hostwep |= HOSTWEP_DECRYPT; | |
164 | if (req->encrypt.data == P80211ENUM_truth_true) | |
165 | wlandev->hostwep |= HOSTWEP_ENCRYPT; | |
00b3ed16 | 166 | |
b1de9675 MM |
167 | break; |
168 | } | |
00b3ed16 | 169 | case DIDmsg_dot11req_mibget: |
b1de9675 MM |
170 | case DIDmsg_dot11req_mibset:{ |
171 | int isget = (msg->msgcode == DIDmsg_dot11req_mibget); | |
172 | p80211msg_dot11req_mibget_t *mib_msg = | |
173 | (p80211msg_dot11req_mibget_t *) msg; | |
174 | p80211req_mibset_mibget(wlandev, mib_msg, isget); | |
175 | } | |
00b3ed16 | 176 | default: |
00b3ed16 | 177 | ; |
b1de9675 | 178 | } /* switch msg->msgcode */ |
00b3ed16 | 179 | |
00b3ed16 GKH |
180 | return; |
181 | } | |
182 | ||
297f06ce MT |
183 | static int p80211req_mibset_mibget(wlandevice_t *wlandev, |
184 | p80211msg_dot11req_mibget_t *mib_msg, | |
00b3ed16 GKH |
185 | int isget) |
186 | { | |
b1de9675 MM |
187 | p80211itemd_t *mibitem = (p80211itemd_t *) mib_msg->mibattribute.data; |
188 | p80211pstrd_t *pstr = (p80211pstrd_t *) mibitem->data; | |
aaad4303 | 189 | u8 *key = mibitem->data + sizeof(p80211pstrd_t); |
00b3ed16 | 190 | |
00b3ed16 | 191 | switch (mibitem->did) { |
b1de9675 MM |
192 | case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey0:{ |
193 | if (!isget) | |
194 | wep_change_key(wlandev, 0, key, pstr->len); | |
195 | break; | |
196 | } | |
197 | case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey1:{ | |
198 | if (!isget) | |
199 | wep_change_key(wlandev, 1, key, pstr->len); | |
200 | break; | |
201 | } | |
202 | case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey2:{ | |
203 | if (!isget) | |
204 | wep_change_key(wlandev, 2, key, pstr->len); | |
205 | break; | |
206 | } | |
207 | case DIDmib_dot11smt_dot11WEPDefaultKeysTable_dot11WEPDefaultKey3:{ | |
208 | if (!isget) | |
209 | wep_change_key(wlandev, 3, key, pstr->len); | |
210 | break; | |
211 | } | |
212 | case DIDmib_dot11smt_dot11PrivacyTable_dot11WEPDefaultKeyID:{ | |
213 | u32 *data = (u32 *) mibitem->data; | |
00b3ed16 | 214 | |
b1de9675 MM |
215 | if (isget) { |
216 | *data = | |
217 | wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK; | |
00b3ed16 GKH |
218 | } else { |
219 | wlandev->hostwep &= ~(HOSTWEP_DEFAULTKEY_MASK); | |
220 | ||
b1de9675 MM |
221 | wlandev->hostwep |= |
222 | (*data & HOSTWEP_DEFAULTKEY_MASK); | |
00b3ed16 | 223 | } |
b1de9675 MM |
224 | break; |
225 | } | |
226 | case DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked:{ | |
227 | u32 *data = (u32 *) mibitem->data; | |
00b3ed16 | 228 | |
b1de9675 MM |
229 | if (isget) { |
230 | if (wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) | |
231 | *data = P80211ENUM_truth_true; | |
232 | else | |
233 | *data = P80211ENUM_truth_false; | |
234 | } else { | |
00b3ed16 GKH |
235 | wlandev->hostwep &= ~(HOSTWEP_PRIVACYINVOKED); |
236 | if (*data == P80211ENUM_truth_true) | |
b1de9675 MM |
237 | wlandev->hostwep |= |
238 | HOSTWEP_PRIVACYINVOKED; | |
239 | } | |
240 | break; | |
00b3ed16 | 241 | } |
b1de9675 MM |
242 | case DIDmib_dot11smt_dot11PrivacyTable_dot11ExcludeUnencrypted:{ |
243 | u32 *data = (u32 *) mibitem->data; | |
00b3ed16 | 244 | |
b1de9675 | 245 | if (isget) { |
75f49e07 MT |
246 | if (wlandev->hostwep & |
247 | HOSTWEP_EXCLUDEUNENCRYPTED) | |
b1de9675 MM |
248 | *data = P80211ENUM_truth_true; |
249 | else | |
250 | *data = P80211ENUM_truth_false; | |
251 | } else { | |
252 | wlandev->hostwep &= | |
253 | ~(HOSTWEP_EXCLUDEUNENCRYPTED); | |
254 | if (*data == P80211ENUM_truth_true) | |
255 | wlandev->hostwep |= | |
256 | HOSTWEP_EXCLUDEUNENCRYPTED; | |
257 | } | |
258 | break; | |
00b3ed16 | 259 | } |
00b3ed16 | 260 | default: |
00b3ed16 GKH |
261 | ; |
262 | } | |
263 | ||
00b3ed16 GKH |
264 | return 0; |
265 | } |