source: mainline/uspace/lib/drv/generic/remote_ieee80211.c@ 984a9ba

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 984a9ba was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

  • Property mode set to 100644
File size: 9.3 KB
Line 
1/*
2 * Copyright (c) 2015 Jan Kolarik
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libdrv
30 * @{
31 */
32/**
33 * @file
34 * @brief Driver-side RPC skeletons for IEEE 802.11 interface
35 */
36
37#include <errno.h>
38#include <macros.h>
39#include <str.h>
40#include <inet/dhcp.h>
41#include <inet/inetcfg.h>
42#include "ops/ieee80211.h"
43#include "ieee80211_iface.h"
44#include "nic_iface.h"
45
46#define MAX_STRING_SIZE 32
47
48/** IEEE 802.11 RPC functions IDs. */
49typedef enum {
50 IEEE80211_GET_SCAN_RESULTS,
51 IEEE80211_CONNECT,
52 IEEE80211_DISCONNECT
53} ieee80211_funcs_t;
54
55/** Get scan results from IEEE 802.11 device
56 *
57 * @param[in] dev_sess Device session.
58 * @param[out] results Structure where to put scan results.
59 *
60 * @return EOK If the operation was successfully completed,
61 * error code otherwise.
62 *
63 */
64errno_t ieee80211_get_scan_results(async_sess_t *dev_sess,
65 ieee80211_scan_results_t *results, bool now)
66{
67 assert(results);
68
69 async_exch_t *exch = async_exchange_begin(dev_sess);
70
71 aid_t aid = async_send_2(exch, DEV_IFACE_ID(IEEE80211_DEV_IFACE),
72 IEEE80211_GET_SCAN_RESULTS, now, NULL);
73 errno_t rc = async_data_read_start(exch, results,
74 sizeof(ieee80211_scan_results_t));
75 async_exchange_end(exch);
76
77 errno_t res;
78 async_wait_for(aid, &res);
79
80 if (res != EOK)
81 return (errno_t) res;
82
83 return rc;
84}
85
86static bool mac_matches(uint8_t *mac1, uint8_t *mac2)
87{
88 for (size_t i = 0; i < ETH_ADDR; i++) {
89 if (mac1[i] != mac2[i])
90 return false;
91 }
92
93 return true;
94}
95
96static sysarg_t get_link_id(uint8_t *mac)
97{
98 sysarg_t *link_list;
99 inet_link_info_t link_info;
100 size_t count;
101
102 errno_t rc = inetcfg_get_link_list(&link_list, &count);
103 if (rc != EOK)
104 return -1;
105
106 for (size_t i = 0; i < count; i++) {
107 rc = inetcfg_link_get(link_list[i], &link_info);
108 if (rc != EOK)
109 return -1;
110
111 if (mac_matches(mac, link_info.mac_addr))
112 return link_list[i];
113 }
114
115 return -1;
116}
117
118/** Connect to specified network.
119 *
120 * @param[in] dev_sess Device session.
121 * @param[in] ssid_start Network SSID prefix.
122 * @param[in] password Network password (pass empty string if not needed).
123 *
124 * @return EOK If the operation was successfully completed,
125 * error code otherwise.
126 *
127 */
128errno_t ieee80211_connect(async_sess_t *dev_sess, char *ssid_start, char *password)
129{
130 assert(ssid_start);
131
132 errno_t rc_orig;
133
134 async_exch_t *exch = async_exchange_begin(dev_sess);
135
136 aid_t aid = async_send_1(exch, DEV_IFACE_ID(IEEE80211_DEV_IFACE),
137 IEEE80211_CONNECT, NULL);
138
139 errno_t rc = async_data_write_start(exch, ssid_start,
140 str_size(ssid_start) + 1);
141 if (rc != EOK) {
142 async_exchange_end(exch);
143 async_wait_for(aid, &rc_orig);
144
145 if (rc_orig == EOK)
146 return (errno_t) rc;
147
148 return (errno_t) rc_orig;
149 }
150
151 // FIXME: Typecasting string literal
152 if (password == NULL)
153 password = (char *) "";
154
155 rc = async_data_write_start(exch, password, str_size(password) + 1);
156 if (rc != EOK) {
157 async_exchange_end(exch);
158 async_wait_for(aid, &rc_orig);
159
160 if (rc_orig == EOK)
161 return (errno_t) rc;
162
163 return (errno_t) rc_orig;
164 }
165
166 async_exchange_end(exch);
167
168 async_wait_for(aid, &rc);
169 if (rc != EOK)
170 return rc;
171
172 /* Send DHCP discover. */
173 nic_address_t wifi_mac;
174 rc = nic_get_address(dev_sess, &wifi_mac);
175 if (rc != EOK)
176 return rc;
177
178 sysarg_t link_id = get_link_id(wifi_mac.address);
179 if (link_id == ((sysarg_t) -1))
180 return EINVAL;
181
182 rc = dhcp_discover(link_id);
183
184 return (errno_t) rc;
185}
186
187/** Disconnect device from network.
188 *
189 * @param[in] dev_sess Device session.
190 *
191 * @return EOK If the operation was successfully completed,
192 * error code otherwise.
193 *
194 */
195errno_t ieee80211_disconnect(async_sess_t *dev_sess)
196{
197 async_exch_t *exch = async_exchange_begin(dev_sess);
198 errno_t rc = async_req_1_0(exch, DEV_IFACE_ID(IEEE80211_DEV_IFACE),
199 IEEE80211_DISCONNECT);
200 async_exchange_end(exch);
201
202 if (rc != EOK)
203 return rc;
204
205 nic_address_t wifi_mac;
206 rc = nic_get_address(dev_sess, &wifi_mac);
207 if (rc != EOK)
208 return rc;
209
210 inet_link_info_t link_info;
211 inet_addr_info_t addr_info;
212 inet_sroute_info_t route_info;
213 sysarg_t *addr_list;
214 sysarg_t *route_list;
215 size_t count;
216
217 /* Remove previous DHCP address. */
218 rc = inetcfg_get_addr_list(&addr_list, &count);
219 if (rc != EOK)
220 return rc;
221
222 for (size_t i = 0; i < count; i++) {
223 rc = inetcfg_addr_get(addr_list[i], &addr_info);
224 if (rc != EOK)
225 return rc;
226
227 rc = inetcfg_link_get(addr_info.ilink, &link_info);
228 if (rc != EOK)
229 return rc;
230
231 if (mac_matches(wifi_mac.address, link_info.mac_addr)) {
232 if (str_test_prefix(addr_info.name, "dhcp")) {
233 rc = inetcfg_addr_delete(addr_list[i]);
234 if (rc != EOK)
235 return rc;
236
237 break;
238 }
239 }
240 }
241
242 /*
243 * TODO: At this moment there can be only one DHCP route,
244 * so it must be reimplemented after this limitation will be
245 * dropped.
246 */
247 /* Remove previous DHCP static route. */
248 rc = inetcfg_get_sroute_list(&route_list, &count);
249 if (rc != EOK)
250 return rc;
251
252 for (size_t i = 0; i < count; i++) {
253 rc = inetcfg_sroute_get(route_list[i], &route_info);
254 if (rc != EOK)
255 return rc;
256
257 if (str_test_prefix(route_info.name, "dhcp")) {
258 rc = inetcfg_sroute_delete(route_list[i]);
259 if (rc != EOK)
260 return rc;
261
262 break;
263 }
264 }
265
266 return rc;
267}
268
269static void remote_ieee80211_get_scan_results(ddf_fun_t *fun, void *iface,
270 ipc_call_t *call)
271{
272 ieee80211_iface_t *ieee80211_iface = (ieee80211_iface_t *) iface;
273 assert(ieee80211_iface->get_scan_results);
274
275 ieee80211_scan_results_t scan_results;
276 memset(&scan_results, 0, sizeof(ieee80211_scan_results_t));
277
278 bool now = IPC_GET_ARG2(*call);
279
280 errno_t rc = ieee80211_iface->get_scan_results(fun, &scan_results, now);
281 if (rc == EOK) {
282 ipc_call_t data;
283 size_t max_len;
284 if (!async_data_read_receive(&data, &max_len)) {
285 async_answer_0(&data, EINVAL);
286 async_answer_0(call, EINVAL);
287 return;
288 }
289
290 if (max_len < sizeof(ieee80211_scan_results_t)) {
291 async_answer_0(&data, ELIMIT);
292 async_answer_0(call, ELIMIT);
293 return;
294 }
295
296 async_data_read_finalize(&data, &scan_results,
297 sizeof(ieee80211_scan_results_t));
298 }
299
300 async_answer_0(call, rc);
301}
302
303static void remote_ieee80211_connect(ddf_fun_t *fun, void *iface,
304 ipc_call_t *call)
305{
306 ieee80211_iface_t *ieee80211_iface = (ieee80211_iface_t *) iface;
307 assert(ieee80211_iface->connect);
308
309 char ssid_start[MAX_STRING_SIZE];
310 char password[MAX_STRING_SIZE];
311
312 ipc_call_t data;
313 size_t len;
314 if (!async_data_write_receive(&data, &len)) {
315 async_answer_0(&data, EINVAL);
316 async_answer_0(call, EINVAL);
317 return;
318 }
319
320 if (len > MAX_STRING_SIZE) {
321 async_answer_0(&data, EINVAL);
322 async_answer_0(call, EINVAL);
323 return;
324 }
325
326 errno_t rc = async_data_write_finalize(&data, ssid_start, len);
327 if (rc != EOK) {
328 async_answer_0(&data, EINVAL);
329 async_answer_0(call, EINVAL);
330 return;
331 }
332
333 if (!async_data_write_receive(&data, &len)) {
334 async_answer_0(&data, EINVAL);
335 async_answer_0(call, EINVAL);
336 return;
337 }
338
339 if (len > MAX_STRING_SIZE) {
340 async_answer_0(&data, EINVAL);
341 async_answer_0(call, EINVAL);
342 return;
343 }
344
345 rc = async_data_write_finalize(&data, password, len);
346 if (rc != EOK) {
347 async_answer_0(&data, EINVAL);
348 async_answer_0(call, EINVAL);
349 return;
350 }
351
352 rc = ieee80211_iface->connect(fun, ssid_start, password);
353
354 async_answer_0(call, rc);
355}
356
357static void remote_ieee80211_disconnect(ddf_fun_t *fun, void *iface,
358 ipc_call_t *call)
359{
360 ieee80211_iface_t *ieee80211_iface = (ieee80211_iface_t *) iface;
361 assert(ieee80211_iface->disconnect);
362 errno_t rc = ieee80211_iface->disconnect(fun);
363 async_answer_0(call, rc);
364}
365
366/** Remote IEEE 802.11 interface operations.
367 *
368 */
369static const remote_iface_func_ptr_t remote_ieee80211_iface_ops[] = {
370 [IEEE80211_GET_SCAN_RESULTS] = remote_ieee80211_get_scan_results,
371 [IEEE80211_CONNECT] = remote_ieee80211_connect,
372 [IEEE80211_DISCONNECT] = remote_ieee80211_disconnect
373};
374
375/** Remote IEEE 802.11 interface structure.
376 *
377 * Interface for processing request from remote
378 * clients addressed to the IEEE 802.11 interface.
379 *
380 */
381const remote_iface_t remote_ieee80211_iface = {
382 .method_count = ARRAY_SIZE(remote_ieee80211_iface_ops),
383 .methods = remote_ieee80211_iface_ops
384};
385
386/**
387 * @}
388 */
Note: See TracBrowser for help on using the repository browser.