2 * Copyright (c) 2015 Jan Kolarik
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
29 /** @addtogroup libdrv
34 * @brief Driver-side RPC skeletons for IEEE 802.11 interface
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"
46 #define MAX_STRING_SIZE 32
48 /** IEEE 802.11 RPC functions IDs. */
50 IEEE80211_GET_SCAN_RESULTS
,
55 /** Get scan results from IEEE 802.11 device
57 * @param[in] dev_sess Device session.
58 * @param[out] results Structure where to put scan results.
60 * @return EOK If the operation was successfully completed,
61 * error code otherwise.
64 errno_t
ieee80211_get_scan_results(async_sess_t
*dev_sess
,
65 ieee80211_scan_results_t
*results
, bool now
)
69 async_exch_t
*exch
= async_exchange_begin(dev_sess
);
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
);
78 async_wait_for(aid
, &res
);
86 static bool mac_matches(uint8_t *mac1
, uint8_t *mac2
)
88 for (size_t i
= 0; i
< ETH_ADDR
; i
++) {
89 if (mac1
[i
] != mac2
[i
])
96 static sysarg_t
get_link_id(uint8_t *mac
)
99 inet_link_info_t link_info
;
102 errno_t rc
= inetcfg_get_link_list(&link_list
, &count
);
106 for (size_t i
= 0; i
< count
; i
++) {
107 rc
= inetcfg_link_get(link_list
[i
], &link_info
);
111 if (mac_matches(mac
, link_info
.mac_addr
))
118 /** Connect to specified network.
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).
124 * @return EOK If the operation was successfully completed,
125 * error code otherwise.
128 errno_t
ieee80211_connect(async_sess_t
*dev_sess
, char *ssid_start
, char *password
)
134 async_exch_t
*exch
= async_exchange_begin(dev_sess
);
136 aid_t aid
= async_send_1(exch
, DEV_IFACE_ID(IEEE80211_DEV_IFACE
),
137 IEEE80211_CONNECT
, NULL
);
139 errno_t rc
= async_data_write_start(exch
, ssid_start
,
140 str_size(ssid_start
) + 1);
142 async_exchange_end(exch
);
143 async_wait_for(aid
, &rc_orig
);
148 return (errno_t
) rc_orig
;
151 // FIXME: Typecasting string literal
152 if (password
== NULL
)
153 password
= (char *) "";
155 rc
= async_data_write_start(exch
, password
, str_size(password
) + 1);
157 async_exchange_end(exch
);
158 async_wait_for(aid
, &rc_orig
);
163 return (errno_t
) rc_orig
;
166 async_exchange_end(exch
);
168 async_wait_for(aid
, &rc
);
172 /* Send DHCP discover. */
173 nic_address_t wifi_mac
;
174 rc
= nic_get_address(dev_sess
, &wifi_mac
);
178 sysarg_t link_id
= get_link_id(wifi_mac
.address
);
179 if (link_id
== ((sysarg_t
) -1))
182 rc
= dhcp_discover(link_id
);
187 /** Disconnect device from network.
189 * @param[in] dev_sess Device session.
191 * @return EOK If the operation was successfully completed,
192 * error code otherwise.
195 errno_t
ieee80211_disconnect(async_sess_t
*dev_sess
)
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
);
205 nic_address_t wifi_mac
;
206 rc
= nic_get_address(dev_sess
, &wifi_mac
);
210 inet_link_info_t link_info
;
211 inet_addr_info_t addr_info
;
212 inet_sroute_info_t route_info
;
214 sysarg_t
*route_list
;
217 /* Remove previous DHCP address. */
218 rc
= inetcfg_get_addr_list(&addr_list
, &count
);
222 for (size_t i
= 0; i
< count
; i
++) {
223 rc
= inetcfg_addr_get(addr_list
[i
], &addr_info
);
227 rc
= inetcfg_link_get(addr_info
.ilink
, &link_info
);
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
]);
243 * TODO: At this moment there can be only one DHCP route,
244 * so it must be reimplemented after this limitation will be
247 /* Remove previous DHCP static route. */
248 rc
= inetcfg_get_sroute_list(&route_list
, &count
);
252 for (size_t i
= 0; i
< count
; i
++) {
253 rc
= inetcfg_sroute_get(route_list
[i
], &route_info
);
257 if (str_test_prefix(route_info
.name
, "dhcp")) {
258 rc
= inetcfg_sroute_delete(route_list
[i
]);
269 static void remote_ieee80211_get_scan_results(ddf_fun_t
*fun
, void *iface
,
272 ieee80211_iface_t
*ieee80211_iface
= (ieee80211_iface_t
*) iface
;
273 assert(ieee80211_iface
->get_scan_results
);
275 ieee80211_scan_results_t scan_results
;
276 memset(&scan_results
, 0, sizeof(ieee80211_scan_results_t
));
278 bool now
= IPC_GET_ARG2(*call
);
280 errno_t rc
= ieee80211_iface
->get_scan_results(fun
, &scan_results
, now
);
284 if (!async_data_read_receive(&data
, &max_len
)) {
285 async_answer_0(&data
, EINVAL
);
286 async_answer_0(call
, EINVAL
);
290 if (max_len
< sizeof(ieee80211_scan_results_t
)) {
291 async_answer_0(&data
, ELIMIT
);
292 async_answer_0(call
, ELIMIT
);
296 async_data_read_finalize(&data
, &scan_results
,
297 sizeof(ieee80211_scan_results_t
));
300 async_answer_0(call
, rc
);
303 static void remote_ieee80211_connect(ddf_fun_t
*fun
, void *iface
,
306 ieee80211_iface_t
*ieee80211_iface
= (ieee80211_iface_t
*) iface
;
307 assert(ieee80211_iface
->connect
);
309 char ssid_start
[MAX_STRING_SIZE
];
310 char password
[MAX_STRING_SIZE
];
314 if (!async_data_write_receive(&data
, &len
)) {
315 async_answer_0(&data
, EINVAL
);
316 async_answer_0(call
, EINVAL
);
320 if (len
> MAX_STRING_SIZE
) {
321 async_answer_0(&data
, EINVAL
);
322 async_answer_0(call
, EINVAL
);
326 errno_t rc
= async_data_write_finalize(&data
, ssid_start
, len
);
328 async_answer_0(&data
, EINVAL
);
329 async_answer_0(call
, EINVAL
);
333 if (!async_data_write_receive(&data
, &len
)) {
334 async_answer_0(&data
, EINVAL
);
335 async_answer_0(call
, EINVAL
);
339 if (len
> MAX_STRING_SIZE
) {
340 async_answer_0(&data
, EINVAL
);
341 async_answer_0(call
, EINVAL
);
345 rc
= async_data_write_finalize(&data
, password
, len
);
347 async_answer_0(&data
, EINVAL
);
348 async_answer_0(call
, EINVAL
);
352 rc
= ieee80211_iface
->connect(fun
, ssid_start
, password
);
354 async_answer_0(call
, rc
);
357 static void remote_ieee80211_disconnect(ddf_fun_t
*fun
, void *iface
,
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
);
366 /** Remote IEEE 802.11 interface operations.
369 static 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
375 /** Remote IEEE 802.11 interface structure.
377 * Interface for processing request from remote
378 * clients addressed to the IEEE 802.11 interface.
381 const remote_iface_t remote_ieee80211_iface
= {
382 .method_count
= ARRAY_SIZE(remote_ieee80211_iface_ops
),
383 .methods
= remote_ieee80211_iface_ops