Add a new wifi error type for association failure
[platform/core/api/wifi-manager.git] / tools / connection-tool / wifi_connect_tool.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <glib.h>
22 #include <wifi-manager.h>
23
24 #define MAX_SSID_LEN 100
25 #define MIN_PASSWORD_LEN 8
26 #define MAX_PASSWORD_LEN 100
27 #define TIMEOUT 20000
28 #define MAX_SCAN_RETRY 3
29
30 #define PRINT_ERROR(...) { \
31         printf("[WIFI][ERROR] " __VA_ARGS__); \
32 }
33
34 #define PRINT_RESULT(...) { \
35         printf("[WIFI] " __VA_ARGS__); \
36 }
37
38 #define DEBUG(...) { \
39         printf("[WIFI][DEBUG] " __VA_ARGS__); \
40 }
41
42 #define EXIT_IF_RET_IS_ERROR(ret, msg) do { \
43         if (ret != WIFI_MANAGER_ERROR_NONE) { \
44                 PRINT_ERROR("Fail %s (%d:%s)\n", msg, ret, __convert_error_to_string(ret)); \
45                 exit(1); \
46         } \
47 } while (0)
48
49 #define RETURN_IF_RET_IS_ERROR(ret, msg) do { \
50         if (ret != WIFI_MANAGER_ERROR_NONE) { \
51                 PRINT_ERROR("Fail %s (%d:%s)\n", msg, ret, __convert_error_to_string(ret)); \
52                 return; \
53         } \
54 } while (0)
55
56 #define RUN_LOOP { \
57         g_wifi_main_loop = g_main_loop_new(NULL, false); \
58         g_timeout_id = g_timeout_add(TIMEOUT, __timeout_cb, g_wifi_main_loop); \
59         g_main_loop_run(g_wifi_main_loop); \
60         g_source_remove(g_timeout_id); \
61         g_wifi_main_loop = NULL; \
62 }
63
64 #define QUIT_LOOP { \
65         g_main_loop_quit(g_wifi_main_loop); \
66 }
67
68 static GMainLoop *g_wifi_main_loop;
69 static int g_timeout_id;
70
71 static wifi_manager_h g_wifi;
72 static wifi_manager_ap_h g_wifi_ap;
73 static char g_ssid[MAX_SSID_LEN + 1];
74 static char g_password[MAX_PASSWORD_LEN + 1];
75
76 static const char *__convert_error_to_string(int err)
77 {
78         switch (err) {
79         case WIFI_MANAGER_ERROR_NONE:
80                 return "NONE";
81         case WIFI_MANAGER_ERROR_INVALID_PARAMETER:
82                 return "INVALID_PARAMETER";
83         case WIFI_MANAGER_ERROR_OUT_OF_MEMORY:
84                 return "OUT_OF_MEMORY";
85         case WIFI_MANAGER_ERROR_INVALID_OPERATION:
86                 return "INVALID_OPERATION";
87         case WIFI_MANAGER_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
88                 return "ADDRESS_FAMILY_NOT_SUPPORTED";
89         case WIFI_MANAGER_ERROR_OPERATION_FAILED:
90                 return "OPERATION_FAILED";
91         case WIFI_MANAGER_ERROR_NO_CONNECTION:
92                 return "NO_CONNECTION";
93         case WIFI_MANAGER_ERROR_NOW_IN_PROGRESS:
94                 return "NOW_IN_PROGRESS";
95         case WIFI_MANAGER_ERROR_ALREADY_EXISTS:
96                 return "ALREADY_EXISTS";
97         case WIFI_MANAGER_ERROR_OPERATION_ABORTED:
98                 return "OPERATION_ABORTED";
99         case WIFI_MANAGER_ERROR_DHCP_FAILED:
100                 return "DHCP_FAILED";
101         case WIFI_MANAGER_ERROR_INVALID_KEY:
102                 return "INVALID_KEY";
103         case WIFI_MANAGER_ERROR_NO_REPLY:
104                 return "NO_REPLY";
105         case WIFI_MANAGER_ERROR_SECURITY_RESTRICTED:
106                 return "SECURITY_RESTRICTED";
107         case WIFI_MANAGER_ERROR_ALREADY_INITIALIZED:
108                 return "ALREADY_INITIALIZED";
109         case WIFI_MANAGER_ERROR_OUT_OF_RANGE:
110                 return "OUT_OF_RANGE";
111         case WIFI_MANAGER_ERROR_CONNECT_FAILED:
112                 return "CONNECT_FAILED";
113         case WIFI_MANAGER_ERROR_LOGIN_FAILED:
114                 return "LOGIN_FAILED";
115         case WIFI_MANAGER_ERROR_AUTHENTICATION_FAILED:
116                 return "AUTH_FAILED";
117         case WIFI_MANAGER_ERROR_ASSOCIATION_FAILED:
118                 return "ASSOC_FAILED";
119         case WIFI_MANAGER_ERROR_PIN_MISSING:
120                 return "PIN_MISSING";
121         case WIFI_MANAGER_ERROR_WPS_OVERLAP:
122                 return "WPS_OVERLAP";
123         case WIFI_MANAGER_ERROR_WPS_TIMEOUT:
124                 return "WPS_TIMEOUT";
125         case WIFI_MANAGER_ERROR_WPS_WEP_PROHIBITED:
126                 return "WPS_WEP_PROHIBITED";
127         case WIFI_MANAGER_ERROR_PERMISSION_DENIED:
128                 return "PERMISSION_DENIED";
129         case WIFI_MANAGER_ERROR_OFFLINE:
130                 return "OFFLINE";
131         case WIFI_MANAGER_ERROR_INVALID_GATEWAY:
132                 return "INVALID_GATEWAY";
133         case WIFI_MANAGER_ERROR_NOT_SUPPORTED:
134                 return "NOT_SUPPORTED";
135         case WIFI_MANAGER_ERROR_NOT_INITIALIZED:
136                 return "NOT_INITIALIZED";
137         default:
138                 return "UNKNOWN";
139         }
140 }
141
142 static gboolean __timeout_cb(gpointer data)
143 {
144         GMainLoop *main_loop = (GMainLoop *)data;
145         if (main_loop == NULL)
146                 PRINT_ERROR("main_loop is NULL\n");
147
148         PRINT_ERROR("Callback Timeout\n");
149         g_main_loop_quit(main_loop);
150         exit(1);
151 }
152
153
154 static void __activate_cb(wifi_manager_error_e error, void *user_data)
155 {
156         if (error != WIFI_MANAGER_ERROR_NONE) {
157                 PRINT_ERROR("Fail to activate %s\n", __convert_error_to_string(error));
158                 exit(1);
159         }
160         QUIT_LOOP;
161 }
162
163 static void activate()
164 {
165         int ret = WIFI_MANAGER_ERROR_NONE;
166         bool power_on = false;
167
168         ret = wifi_manager_is_activated(g_wifi, &power_on);
169         EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_is_activated");
170
171         if (power_on == false) {
172                 ret = wifi_manager_activate(g_wifi, __activate_cb, NULL);
173                 EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_activate");
174                 RUN_LOOP;
175         }
176 }
177
178 static void __forget_cb(wifi_manager_error_e error, void *user_data)
179 {
180         if (error != WIFI_MANAGER_ERROR_NONE) {
181                 PRINT_ERROR("Fail to forget %s\n", __convert_error_to_string(error));
182                 exit(1);
183         }
184         QUIT_LOOP;
185 }
186
187 static bool check_connected_ap()
188 {
189         int ret = WIFI_MANAGER_ERROR_NONE;
190         wifi_manager_ap_h ap = NULL;
191         char *ap_name;
192         bool already_connected = false;
193
194         ret = wifi_manager_get_connected_ap(g_wifi, &ap);
195         if (ret == WIFI_MANAGER_ERROR_NO_CONNECTION)
196                 return false;
197         EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_get_connected_ap");
198
199         if (ap) {
200                 ret = wifi_manager_ap_get_essid(ap, &ap_name);
201                 if (ret != WIFI_MANAGER_ERROR_NONE) {
202                         PRINT_ERROR("Fail wifi_manager_ap_get_essid (%d:%s)\n", ret, __convert_error_to_string(ret));
203                         return false;
204                 }
205
206                 PRINT_RESULT("Connected to %s\n", ap_name);
207
208                 if (!strcmp(ap_name, g_ssid)) {
209                         already_connected = true;
210                 } else {
211                         ret = wifi_manager_forget_ap_async(g_wifi, ap, __forget_cb, NULL);
212                         EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_forget_ap_async");
213                         RUN_LOOP;
214                         PRINT_RESULT("Forget %s\n", ap_name);
215                 }
216
217                 ret = wifi_manager_ap_destroy(ap);
218                 if (ret != WIFI_MANAGER_ERROR_NONE)
219                         PRINT_ERROR("Fail wifi_manager_ap_destroy(%d:%s)\n", ret, __convert_error_to_string(ret));
220                 free(ap_name);
221         }
222
223         return already_connected;
224 }
225
226 static void __scan_cb(wifi_manager_error_e error, void *user_data)
227 {
228         if (error != WIFI_MANAGER_ERROR_NONE) {
229                 PRINT_ERROR("Fail to scan %s\n", __convert_error_to_string(error));
230                 exit(1);
231         }
232         QUIT_LOOP;
233 }
234
235 static bool __found_ap_cb(wifi_manager_ap_h ap, void *user_data)
236 {
237         char *ap_name = NULL;
238         int ret = WIFI_MANAGER_ERROR_NONE;
239
240         if (ap) {
241                 ret = wifi_manager_ap_get_essid(ap, &ap_name);
242                 if (ret != WIFI_MANAGER_ERROR_NONE) {
243                         PRINT_ERROR("Fail wifi_manager_ap_get_essid (%d:%s)\n", ret, __convert_error_to_string(ret));
244                         return true;
245                 }
246
247                 if (!strcmp(ap_name, g_ssid)) {
248                         DEBUG("Found %s\n", g_ssid);
249                         ret = wifi_manager_ap_clone(&g_wifi_ap, ap);
250                         if (ret != WIFI_MANAGER_ERROR_NONE) {
251                                 PRINT_ERROR("Fail wifi_manager_ap_clone(%d:%s)\n", ret, __convert_error_to_string(ret));
252                                 free(ap_name);
253                                 return false;
254                         }
255
256                         if (g_wifi_ap) {
257                                 free(ap_name);
258                                 return false;
259                         }
260                 }
261         }
262
263         free(ap_name);
264
265         return true;
266 }
267
268 static void scan()
269 {
270         int ret = WIFI_MANAGER_ERROR_NONE;
271         ret = wifi_manager_scan(g_wifi, __scan_cb, NULL);
272         RETURN_IF_RET_IS_ERROR(ret, "wifi_manager_scan");
273         RUN_LOOP;
274
275         ret = wifi_manager_foreach_found_ap(g_wifi, __found_ap_cb, NULL);
276         RETURN_IF_RET_IS_ERROR(ret, "wifi_manager_foreach_found_ap");
277 }
278
279 static void __connect_cb(wifi_manager_error_e error, void *user_data)
280 {
281         if (error != WIFI_MANAGER_ERROR_NONE) {
282                 PRINT_ERROR("Fail to connect %s\n", __convert_error_to_string(error));
283                 exit(1);
284         }
285         QUIT_LOOP;
286 }
287
288 static void connect()
289 {
290         int ret = WIFI_MANAGER_ERROR_NONE;
291         ret = wifi_manager_ap_set_passphrase(g_wifi_ap, g_password);
292         EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_ap_set_passphrase");
293
294         ret = wifi_manager_connect(g_wifi, g_wifi_ap, __connect_cb, NULL);
295         RUN_LOOP;
296 }
297
298 static void start()
299 {
300         char *ap_name = NULL;
301         wifi_manager_ap_h connected_ap = NULL;
302         int ret = wifi_manager_initialize(&g_wifi);
303         EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_initialize");
304         PRINT_RESULT("Initialized\n");
305
306         activate();
307         PRINT_RESULT("Activated\n");
308
309         if (!check_connected_ap()) {
310                 for (int i = 0; i < MAX_SCAN_RETRY; ++i) {
311                         g_wifi_ap = NULL;
312                         scan();
313                         if (g_wifi_ap)
314                                 break;
315                         else
316                                 DEBUG("Scan %d: Not found AP %s\n", (i + 1), g_ssid);
317                 }
318                 if (!g_wifi_ap) {
319                         PRINT_ERROR("Not found AP %s\n", g_ssid);
320                         exit(1);
321                 }
322
323                 PRINT_RESULT("Scanned\n");
324
325                 connect();
326         }
327         ret = wifi_manager_get_connected_ap(g_wifi, &connected_ap);
328         EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_get_connected_ap");
329
330         ret = wifi_manager_ap_get_essid(connected_ap, &ap_name);
331         EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_get_essid");
332         PRINT_RESULT("Connected to %s\n", ap_name);
333
334         wifi_manager_ap_destroy(connected_ap);
335         free(ap_name);
336 }
337
338 static const char *convert_state_to_string(wifi_manager_connection_state_e state)
339 {
340         switch (state) {
341         case WIFI_MANAGER_CONNECTION_STATE_FAILURE:
342                 return "Failure";
343         case WIFI_MANAGER_CONNECTION_STATE_DISCONNECTED:
344                 return "Disconnected";
345         case WIFI_MANAGER_CONNECTION_STATE_ASSOCIATION:
346                 return "Association";
347         case WIFI_MANAGER_CONNECTION_STATE_CONFIGURATION:
348                 return "Configuration";
349         case WIFI_MANAGER_CONNECTION_STATE_CONNECTED:
350                 return "Connected";
351         default:
352                 return "Error";
353         }
354 }
355
356 static void show_status()
357 {
358         bool power = false;
359         wifi_manager_connection_state_e state;
360         wifi_manager_ap_h ap = NULL;
361         char *ap_name = NULL;
362         int ret = wifi_manager_initialize(&g_wifi);
363         EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_initialize");
364
365         ret = wifi_manager_is_activated(g_wifi, &power);
366         EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_is_activated");
367
368         if (power) {
369                 ret = wifi_manager_get_connection_state(g_wifi, &state);
370                 EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_get_connection_state");
371
372                 if (state == WIFI_MANAGER_CONNECTION_STATE_CONNECTED) {
373                         ret = wifi_manager_get_connected_ap(g_wifi, &ap);
374                         EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_get_connected_ap");
375
376                         ret = wifi_manager_ap_get_essid(ap, &ap_name);
377                         EXIT_IF_RET_IS_ERROR(ret, "wifi_manager_get_essid");
378                         PRINT_RESULT("Connected to %s\n", ap_name);
379
380                         wifi_manager_ap_destroy(ap);
381                         free(ap_name);
382                 } else {
383                         PRINT_RESULT("%s\n", convert_state_to_string(state));
384                 }
385         } else {
386                 PRINT_RESULT("Power off\n");
387         }
388 }
389
390 static void print_usage()
391 {
392         printf("Usage:\n");
393         printf("  wifi_connect_tool [SSID] [PASSWORD]\n");
394         printf("  wifi_connect_tool status\n");
395 }
396
397 int main(int argc, char **argv)
398 {
399         int passwd_len = 0;
400
401 #if !GLIB_CHECK_VERSION(2, 36, 0)
402         g_type_init();
403 #endif
404
405         if (argc != 3 && argc != 2) {
406                 print_usage();
407                 return 1;
408         }
409
410         if (argc == 2) {
411                 if (strncmp(argv[1], "status", 6) != 0) {
412                         print_usage();
413                         return 1;
414                 }
415                 show_status();
416                 return 0;
417         }
418
419         if (strlen(argv[1]) > MAX_SSID_LEN) {
420                 PRINT_ERROR("Too long SSID\n");
421                 return 1;
422         }
423
424         passwd_len = strlen(argv[2]);
425         if (passwd_len < MIN_PASSWORD_LEN) {
426                 PRINT_ERROR("Too short password\n");
427                 return 1;
428         }
429
430         if (passwd_len > MAX_PASSWORD_LEN) {
431                 PRINT_ERROR("Too long password\n");
432                 return 1;
433         }
434
435         strncpy(g_ssid, argv[1], MAX_SSID_LEN);
436         strncpy(g_password, argv[2], MAX_PASSWORD_LEN);
437
438         printf("Start to connect to a Wi-Fi network\n");
439         start();
440
441         return 0;
442 }