source: mainline/uspace/lib/drv/generic/remote_ieee80211.c@ 3061bc1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3061bc1 was b7fd2a0, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Use errno_t in all uspace and kernel code.

Change type of every variable, parameter and return value that holds an
<errno.h> constant to either errno_t (the usual case), or sys_errno_t
(some places in kernel). This is for the purpose of self-documentation,
as well as for type-checking with a bit of type definition hackery.

Although this is a massive commit, it is a simple text replacement, and thus
is very easy to verify. Simply do the following:

`
git checkout <this commit's hash>
git reset HEAD
git add .
tools/srepl '\berrno_t\b' int
git add .
tools/srepl '\bsys_errno_t\b' sysarg_t
git reset
git diff
`

While this doesn't ensure that the replacements are correct, it does ensure
that the commit doesn't do anything except those replacements. Since errno_t
is typedef'd to int in the usual case (and sys_errno_t to sysarg_t), even if
incorrect, this commit cannot change behavior.

  • Property mode set to 100644
File size: 9.5 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_callid_t callid, 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_callid_t data_callid;
283 size_t max_len;
284 if (!async_data_read_receive(&data_callid, &max_len)) {
285 async_answer_0(data_callid, EINVAL);
286 async_answer_0(callid, EINVAL);
287 return;
288 }
289
290 if (max_len < sizeof(ieee80211_scan_results_t)) {
291 async_answer_0(data_callid, ELIMIT);
292 async_answer_0(callid, ELIMIT);
293 return;
294 }
295
296 async_data_read_finalize(data_callid, &scan_results,
297 sizeof(ieee80211_scan_results_t));
298 }
299
300 async_answer_0(callid, rc);
301}
302
303static void remote_ieee80211_connect(ddf_fun_t *fun, void *iface,
304 ipc_callid_t callid, 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_callid_t data_callid;
313 size_t len;
314 if (!async_data_write_receive(&data_callid, &len)) {
315 async_answer_0(data_callid, EINVAL);
316 async_answer_0(callid, EINVAL);
317 return;
318 }
319
320 if (len > MAX_STRING_SIZE) {
321 async_answer_0(data_callid, EINVAL);
322 async_answer_0(callid, EINVAL);
323 return;
324 }
325
326 errno_t rc = async_data_write_finalize(data_callid, ssid_start, len);
327 if (rc != EOK) {
328 async_answer_0(data_callid, EINVAL);
329 async_answer_0(callid, EINVAL);
330 return;
331 }
332
333 if (!async_data_write_receive(&data_callid, &len)) {
334 async_answer_0(data_callid, EINVAL);
335 async_answer_0(callid, EINVAL);
336 return;
337 }
338
339 if (len > MAX_STRING_SIZE) {
340 async_answer_0(data_callid, EINVAL);
341 async_answer_0(callid, EINVAL);
342 return;
343 }
344
345 rc = async_data_write_finalize(data_callid, password, len);
346 if (rc != EOK) {
347 async_answer_0(data_callid, EINVAL);
348 async_answer_0(callid, EINVAL);
349 return;
350 }
351
352 rc = ieee80211_iface->connect(fun, ssid_start, password);
353
354 async_answer_0(callid, rc);
355}
356
357static void remote_ieee80211_disconnect(ddf_fun_t *fun, void *iface,
358 ipc_callid_t callid, 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(callid, 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.