source: mainline/uspace/lib/ieee80211/src/ieee80211_iface_impl.c@ cc575ef9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cc575ef9 was 053fc2b, checked in by Jan Kolarik <kolarik@…>, 10 years ago

Locking, correctly disconnecting device, sending DHCP address discover after connecting to WiFi network

  • Property mode set to 100644
File size: 6.7 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#include <str.h>
30#include <errno.h>
31
32#include <ieee80211_private.h>
33#include <ieee80211_iface_impl.h>
34
35/** @addtogroup libieee80211
36 * @{
37 */
38
39/** @file ieee80211_iface_impl.c
40 *
41 * IEEE 802.11 default interface functions implementation.
42 */
43
44/**
45 * Implementation of fetching scan results.
46 *
47 * @param fun Device function.
48 * @param results Structure where should be stored scan results.
49 *
50 * @return EOK if everything went OK, EREFUSED when device is not ready yet.
51 */
52int ieee80211_get_scan_results_impl(ddf_fun_t *fun,
53 ieee80211_scan_results_t *results, bool now)
54{
55 nic_t *nic_data = nic_get_from_ddf_fun(fun);
56 ieee80211_dev_t *ieee80211_dev = nic_get_specific(nic_data);
57
58 if(!ieee80211_is_ready(ieee80211_dev))
59 return EREFUSED;
60
61 if(now) {
62 ieee80211_dev->ops->scan(ieee80211_dev);
63 }
64
65 fibril_mutex_lock(&ieee80211_dev->ap_list.results_mutex);
66 if(results) {
67 ieee80211_scan_result_list_t *result_list =
68 &ieee80211_dev->ap_list;
69
70 int i = 0;
71 ieee80211_scan_result_list_foreach(*result_list, result) {
72 memcpy(&results->results[i],
73 &result->scan_result,
74 sizeof(ieee80211_scan_result_t));
75 i++;
76 }
77
78 results->length = i;
79 }
80 fibril_mutex_unlock(&ieee80211_dev->ap_list.results_mutex);
81
82 return EOK;
83}
84
85static uint16_t ieee80211_channel_to_freq(uint8_t channel)
86{
87 return IEEE80211_CHANNEL_GAP * (channel - 1) + IEEE80211_FIRST_FREQ;
88}
89
90/**
91 * Working procedure of connect function.
92 *
93 * @param ieee80211_dev Pointer to IEEE 802.11 device.
94 * @param auth_data Selected AP data we want to connect to.
95 *
96 * @return EOK if everything OK, ETIMEOUT when timeout during authenticating.
97 */
98static int ieee80211_connect_proc(ieee80211_dev_t *ieee80211_dev,
99 ieee80211_scan_result_link_t *auth_data, char *password)
100{
101 ieee80211_dev->bssid_info.res_link = auth_data;
102
103 /* Set channel. */
104 int rc = ieee80211_dev->ops->set_freq(ieee80211_dev,
105 ieee80211_channel_to_freq(auth_data->scan_result.channel));
106 if(rc != EOK)
107 return rc;
108
109 /* Try to authenticate. */
110 ieee80211_authenticate(ieee80211_dev);
111 fibril_mutex_lock(&ieee80211_dev->gen_mutex);
112 rc = fibril_condvar_wait_timeout(&ieee80211_dev->gen_cond,
113 &ieee80211_dev->gen_mutex,
114 AUTH_TIMEOUT);
115 fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
116 if(rc != EOK)
117 return rc;
118 if(ieee80211_get_auth_phase(ieee80211_dev) !=
119 IEEE80211_AUTH_AUTHENTICATED) {
120 ieee80211_set_auth_phase(ieee80211_dev,
121 IEEE80211_AUTH_DISCONNECTED);
122 return EINVAL;
123 }
124
125 /* Try to associate. */
126 ieee80211_associate(ieee80211_dev, password);
127 fibril_mutex_lock(&ieee80211_dev->gen_mutex);
128 rc = fibril_condvar_wait_timeout(&ieee80211_dev->gen_cond,
129 &ieee80211_dev->gen_mutex,
130 AUTH_TIMEOUT);
131 fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
132 if(rc != EOK)
133 return rc;
134 if(ieee80211_get_auth_phase(ieee80211_dev) !=
135 IEEE80211_AUTH_ASSOCIATED) {
136 ieee80211_set_auth_phase(ieee80211_dev,
137 IEEE80211_AUTH_DISCONNECTED);
138 return EINVAL;
139 }
140
141 /* On open network, we are finished. */
142 if(auth_data->scan_result.security.type != IEEE80211_SECURITY_OPEN) {
143 /* Otherwise wait for 4-way handshake to complete. */
144 fibril_mutex_lock(&ieee80211_dev->gen_mutex);
145 rc = fibril_condvar_wait_timeout(&ieee80211_dev->gen_cond,
146 &ieee80211_dev->gen_mutex,
147 HANDSHAKE_TIMEOUT);
148 fibril_mutex_unlock(&ieee80211_dev->gen_mutex);
149 if(rc != EOK) {
150 ieee80211_deauthenticate(ieee80211_dev);
151 return rc;
152 }
153 }
154
155 ieee80211_set_auth_phase(ieee80211_dev, IEEE80211_AUTH_CONNECTED);
156
157 return EOK;
158}
159
160/**
161 * Implementation of connecting to specified SSID.
162 *
163 * @param fun Device function.
164 * @param ssid_start SSID prefix of access point we want to connect to.
165 *
166 * @return EOK if everything OK, ETIMEOUT when timeout during authenticating,
167 * EINVAL when SSID not in scan results list, EPERM when incorrect password
168 * passed, EREFUSED when device is not ready yet.
169 */
170int ieee80211_connect_impl(ddf_fun_t *fun, char *ssid_start, char *password)
171{
172 assert(ssid_start);
173 assert(password);
174
175 int rc;
176
177 nic_t *nic_data = nic_get_from_ddf_fun(fun);
178 ieee80211_dev_t *ieee80211_dev = nic_get_specific(nic_data);
179
180 if(!ieee80211_is_ready(ieee80211_dev))
181 return EREFUSED;
182
183 if(ieee80211_is_connected(ieee80211_dev)) {
184 rc = ieee80211_dev->iface->disconnect(fun);
185 if(rc != EOK)
186 return rc;
187 }
188
189 ieee80211_set_connect_request(ieee80211_dev);
190
191 rc = ENOENT;
192 fibril_mutex_lock(&ieee80211_dev->scan_mutex);
193
194 ieee80211_dev->pending_conn_req = false;
195
196 ieee80211_scan_result_list_foreach(ieee80211_dev->ap_list, result) {
197 if(!str_lcmp(ssid_start,
198 result->scan_result.ssid,
199 str_size(ssid_start))) {
200 rc = ieee80211_connect_proc(ieee80211_dev, result,
201 password);
202 break;
203 }
204 }
205
206 fibril_mutex_unlock(&ieee80211_dev->scan_mutex);
207
208 return rc;
209}
210
211/**
212 * Implementation of disconnecting device from network.
213 *
214 * @param fun Device function.
215 *
216 * @return EOK if everything OK, EREFUSED if device is not ready yet.
217 */
218int ieee80211_disconnect_impl(ddf_fun_t *fun)
219{
220 nic_t *nic_data = nic_get_from_ddf_fun(fun);
221 ieee80211_dev_t *ieee80211_dev = nic_get_specific(nic_data);
222
223 if(!ieee80211_is_ready(ieee80211_dev))
224 return EREFUSED;
225
226 if(!ieee80211_is_connected(ieee80211_dev)) {
227 return EOK;
228 } else {
229 fibril_mutex_lock(&ieee80211_dev->ap_list.results_mutex);
230 int rc = ieee80211_deauthenticate(ieee80211_dev);
231 fibril_mutex_unlock(&ieee80211_dev->ap_list.results_mutex);
232 return rc;
233 }
234}
235
236/** @}
237 */
Note: See TracBrowser for help on using the repository browser.