Fixed: Coding rule issues.
[platform/core/connectivity/wifi-direct-manager.git] / src / wifi-direct-group.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 /**
21  * This file implements wifi direct group functions.
22  *
23  * @file                wifi-direct-group.c
24  * @author      Gibyoung Kim (lastkgb.kim@samsung.com)
25  * @version     0.7
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <errno.h>
31
32 #include <glib.h>
33
34 #include <wifi-direct.h>
35
36 #include "wifi-direct-ipc.h"
37 #include "wifi-direct-manager.h"
38 #include "wifi-direct-state.h"
39 #include "wifi-direct-peer.h"
40 #include "wifi-direct-oem.h"
41 #include "wifi-direct-group.h"
42 #include "wifi-direct-util.h"
43 #include "wifi-direct-session.h"
44 #include "wifi-direct-log.h"
45
46
47 /* Check the group instance which has same interface name,
48  * before using this function */
49 wfd_group_s *wfd_create_group(void *data, wfd_oem_event_s *group_info)
50 {
51         __WDS_LOG_FUNC_ENTER__;
52         wfd_group_s *group = NULL;
53         wfd_manager_s *manager = (wfd_manager_s*) data;
54
55         if (!manager || !group_info) {
56                 WDS_LOGE("Invalid parameter");
57                 __WDS_LOG_FUNC_EXIT__;
58                 return NULL;
59         }
60         wfd_oem_group_data_s *edata = (wfd_oem_group_data_s *)group_info->edata;
61
62         if (!edata) {
63                 WDS_LOGE("Invalid parameter");
64                 __WDS_LOG_FUNC_EXIT__;
65                 return NULL;
66         }
67
68         group = manager->group;
69         if (group) {
70                 WDS_LOGE("Group already exist");
71                 __WDS_LOG_FUNC_EXIT__;
72                 return NULL;
73         }
74
75         errno = 0;
76         group = (wfd_group_s*) g_try_malloc0(sizeof(wfd_group_s));
77         if (!group) {
78                 WDS_LOGE("Failed to allocate memory for group. [%s]", strerror(errno));
79                 __WDS_LOG_FUNC_EXIT__;
80                 return NULL;
81         }
82
83         memcpy(group->ifname, group_info->ifname, IFACE_NAME_LEN);
84         group->ifname[IFACE_NAME_LEN] = '\0';
85         group->role = group_info->dev_role;
86         memcpy(group->go_dev_addr, edata->go_dev_addr, MACADDR_LEN);
87
88         g_strlcpy(group->ssid, edata->ssid, DEV_NAME_LEN + 1);
89         g_strlcpy(group->passphrase, edata->pass, PASSPHRASE_LEN_MAX + 1);
90         memset(manager->local->passphrase, 0x0, PASSPHRASE_LEN_MAX + 1);
91         group->freq = edata->freq;
92
93         manager->group = group;
94         manager->local->dev_role = group_info->dev_role;
95
96         wfd_util_dhcps_start(group->ifname);
97         group->pending = FALSE;
98         WDS_LOGD("Role is Group Owner. DHCP Server started");
99
100         __WDS_LOG_FUNC_EXIT__;
101         return group;
102 }
103
104 /* Used for CTRL-EVENT_CONNECTED event that comes before group created */
105 wfd_group_s *wfd_create_pending_group(void *data, unsigned char * bssid)
106 {
107         __WDS_LOG_FUNC_ENTER__;
108         wfd_group_s *group = NULL;
109         wfd_manager_s *manager = (wfd_manager_s*) data;
110
111         if (!manager || !bssid) {
112                 WDS_LOGE("Invalid parameter");
113                 __WDS_LOG_FUNC_EXIT__;
114                 return NULL;
115         }
116
117         group = manager->group;
118         if (group) {
119                 WDS_LOGE("Group already exist");
120                 __WDS_LOG_FUNC_EXIT__;
121                 return NULL;
122         }
123
124         errno = 0;
125         group = (wfd_group_s*) g_try_malloc0(sizeof(wfd_group_s));
126         if (!group) {
127                 WDS_LOGE("Failed to allocate memory for group. [%s]", strerror(errno));
128                 __WDS_LOG_FUNC_EXIT__;
129                 return NULL;
130         }
131
132         memcpy(group->bssid, bssid, MACADDR_LEN);
133         group->flags &= WFD_GROUP_FLAG_NONE;
134         group->pending = TRUE;
135
136         __WDS_LOG_FUNC_EXIT__;
137         return group;
138 }
139
140 int wfd_group_complete(void *data, wfd_oem_event_s *group_info)
141 {
142         __WDS_LOG_FUNC_ENTER__;
143         wfd_manager_s *manager = (wfd_manager_s*) data;
144         wfd_session_s *session = NULL;
145         wfd_group_s *group = NULL;
146         wfd_device_s *peer = NULL;
147
148         if (!manager || !group_info) {
149                 WDS_LOGE("Invalid parameter");
150                 __WDS_LOG_FUNC_EXIT__;
151                 return -1;
152         }
153         wfd_oem_group_data_s *edata = (wfd_oem_group_data_s *)group_info->edata;
154
155         if (!edata) {
156                 WDS_LOGE("Invalid parameter");
157                 __WDS_LOG_FUNC_EXIT__;
158                 return -1;
159         }
160
161         group = manager->group;
162         if (!group) {
163                 WDS_LOGE("Group not found");
164                 __WDS_LOG_FUNC_EXIT__;
165                 return -1;
166         }
167
168         g_strlcpy(group->ifname, group_info->ifname, IFACE_NAME_LEN + 1);
169         group->role = group_info->dev_role;
170         memcpy(group->go_dev_addr, edata->go_dev_addr, MACADDR_LEN);
171
172         g_strlcpy(group->ssid, edata->ssid, DEV_NAME_LEN + 1);
173         g_strlcpy(group->passphrase, edata->pass, PASSPHRASE_LEN_MAX + 1);
174         memset(manager->local->passphrase, 0x0, PASSPHRASE_LEN_MAX + 1);
175         group->freq = edata->freq;
176         if (edata->is_persistent)
177                 group->flags |= WFD_GROUP_FLAG_PERSISTENT;
178
179         manager->local->dev_role = group_info->dev_role;
180         group->pending = FALSE;
181
182         session = manager->session;
183         peer = wfd_session_get_peer(session);
184         if (!peer && !(group->flags & WFD_GROUP_FLAG_AUTONOMOUS)) {
185                 if (!session && (group->flags & WFD_GROUP_FLAG_PERSISTENT)) {
186                         WDS_LOGE("Group created by supplicant is persistent group.");
187                         /**
188                          * TODO: Add handling for Reinvoked Persistent Group.
189                          */
190                         __WDS_LOG_FUNC_EXIT__;
191                         return -1;
192                 } else {
193                         WDS_LOGD("Failed to find peer by device address[" MACSECSTR "]",
194                                                         MAC2SECSTR(edata->go_dev_addr));
195                         __WDS_LOG_FUNC_EXIT__;
196                         return -1;
197                 }
198         }
199
200         if (group->role == WFD_DEV_ROLE_GO) {
201                 wfd_util_dhcps_start(group->ifname);
202                 WDS_LOGD("Role is Group Owner. DHCP Server started");
203         } else {
204                 if (!peer) {
205                         WDS_LOGE("Peer is not in the session");
206                         __WDS_LOG_FUNC_EXIT__;
207                         return -1;
208                 }
209
210                 WDS_LOGD("Role is Group Client.complete session and add peer to member");
211                 memcpy(peer->intf_addr, group->go_dev_addr, MACADDR_LEN);
212                 wfd_group_add_member(group, peer->dev_addr);
213                 session->state = SESSION_STATE_COMPLETED;
214                 peer->state = WFD_PEER_STATE_CONNECTED;
215 #ifdef TIZEN_FEATURE_IP_OVER_EAPOL
216                 if (edata->ip_addr[3] && edata->ip_addr_go[3]) {
217                         peer->ip_type = WFD_IP_TYPE_OVER_EAPOL;
218                         memcpy(peer->client_ip_addr, edata->ip_addr, IPADDR_LEN);
219                         WDS_LOGE("Peer's client IP [" IPSTR "]", IP2STR((char*) &peer->client_ip_addr));
220                         memcpy(peer->go_ip_addr, edata->ip_addr_go, IPADDR_LEN);
221                         WDS_LOGE("Peer's GO IP [" IPSTR "]", IP2STR((char*) &peer->go_ip_addr));
222                 }
223
224                 if (peer->ip_type != WFD_IP_TYPE_OVER_EAPOL)
225 #endif /* TIZEN_FEATURE_IP_OVER_EAPOL */
226                 wfd_util_dhcpc_start(group->ifname, peer);
227         }
228
229         __WDS_LOG_FUNC_EXIT__;
230         return 0;
231 }
232
233 int wfd_destroy_group(void *data)
234 {
235         __WDS_LOG_FUNC_ENTER__;
236         wfd_group_s *group = NULL;
237         wfd_manager_s *manager = (wfd_manager_s*) data;
238         GList *temp = NULL;
239         wfd_device_s *member = NULL;
240         int count = 0;
241
242         if (!data) {
243                 WDS_LOGE("Invalid parameter");
244                 __WDS_LOG_FUNC_EXIT__;
245                 return -1;
246         }
247
248         group = manager->group;
249         if (!group) {
250                 WDS_LOGE("Group not exist");
251                 __WDS_LOG_FUNC_EXIT__;
252                 return -1;
253         }
254         manager->group = NULL;
255
256         if (group->pending == FALSE) {
257                 wfd_util_ip_unset(group->ifname);
258                 if (group->role == WFD_DEV_ROLE_GO)
259                         wfd_util_dhcps_stop(group->ifname);
260                 else
261                         wfd_util_dhcpc_stop(group->ifname);
262         }
263         memset(manager->local->ip_addr, 0x0, IPADDR_LEN);
264
265         temp = g_list_first(group->members);
266         while (temp && count < group->member_count) {
267                 member = temp->data;
268                 WDS_LOGD("%dth member[%s] will be removed", count, member->dev_name);
269                 g_free(member);
270                 member = NULL;
271                 temp = g_list_next(temp);
272                 count++;
273         }
274
275         if (group->members) {
276                 g_list_free(group->members);
277                 group->members = NULL;
278         }
279
280         g_free(group);
281
282         manager->local->dev_role = WFD_DEV_ROLE_NONE;
283         __WDS_LOG_FUNC_EXIT__;
284         return 0;
285 }
286
287 #if 0
288 int wfd_group_get_channel(wfd_group_s *group)
289 {
290         __WDS_LOG_FUNC_ENTER__;
291
292         if (!group) {
293                 WDS_LOGE("Invalid parameter");
294                 __WDS_LOG_FUNC_EXIT__;
295                 return -1;
296         }
297
298         __WDS_LOG_FUNC_EXIT__;
299         return group->freq;
300 }
301 #endif
302
303 int wfd_group_is_autonomous(wfd_group_s *group)
304 {
305         __WDS_LOG_FUNC_ENTER__;
306
307         if (!group) {
308                 WDS_LOGE("Invalid parameter");
309                 __WDS_LOG_FUNC_EXIT__;
310                 return -1;
311         }
312
313         __WDS_LOG_FUNC_EXIT__;
314         return ((group->flags & WFD_GROUP_FLAG_AUTONOMOUS) == WFD_GROUP_FLAG_AUTONOMOUS);
315 }
316
317 #if 0
318 int wfd_group_get_members()
319 {
320         __WDS_LOG_FUNC_ENTER__;
321
322         __WDS_LOG_FUNC_EXIT__;
323         return 0;
324 }
325
326 int wfd_group_make_persistent()
327 {
328         __WDS_LOG_FUNC_ENTER__;
329
330         __WDS_LOG_FUNC_EXIT__;
331         return 0;
332 }
333
334 int wfd_group_get_flags(wfd_group_s *group)
335 {
336         __WDS_LOG_FUNC_ENTER__;
337
338         if (!group) {
339                 WDS_LOGE("Invalid parameter");
340                 __WDS_LOG_FUNC_EXIT__;
341                 return -1;
342         }
343
344         __WDS_LOG_FUNC_EXIT__;
345         return group->flags;
346 }
347 #endif
348
349 wfd_device_s *wfd_group_find_member_by_addr(wfd_group_s *group, unsigned char *addr)
350 {
351         __WDS_LOG_FUNC_ENTER__;
352         GList *temp = NULL;
353         wfd_device_s *member = NULL;
354
355         if (!group || !addr) {
356                 WDS_LOGE("Invalid parameter");
357                 __WDS_LOG_FUNC_EXIT__;
358                 return NULL;
359         }
360
361         if (!group->member_count) {
362                 WDS_LOGE("There is no members");
363                 __WDS_LOG_FUNC_EXIT__;
364                 return NULL;
365         }
366
367         temp = g_list_first(group->members);
368         while (temp) {
369                 member = temp->data;
370                 if (!memcmp(member->intf_addr, addr, MACADDR_LEN) ||
371                                 !memcmp(member->dev_addr, addr, MACADDR_LEN)) {
372                         WDS_LOGD("Member found");
373                         break;
374                 }
375                 temp = g_list_next(temp);
376                 member = NULL;
377         }
378
379         __WDS_LOG_FUNC_EXIT__;
380         return member;
381 }
382
383 int wfd_group_add_member(wfd_group_s *group, unsigned char *addr)
384 {
385         __WDS_LOG_FUNC_ENTER__;
386         wfd_device_s *member = NULL;
387         wfd_manager_s *manager = wfd_get_manager();
388
389         if (!group || !addr) {
390                 WDS_LOGE("Invalid parameter");
391                 __WDS_LOG_FUNC_EXIT__;
392                 return -1;
393         }
394
395         member = wfd_group_find_member_by_addr(group, addr);
396         if (member) {
397                 WDS_LOGE("Member already exist");
398                 return -1;
399         }
400
401         member = wfd_peer_find_by_addr(manager, addr);
402         if (!member)
403                 WDS_LOGE("Peer not found");
404
405         group->members = g_list_prepend(group->members, member);
406         group->member_count++;
407
408         manager->peers = g_list_remove(manager->peers, member);
409         manager->peer_count--;
410
411         __WDS_LOG_FUNC_EXIT__;
412         return 0;
413 }
414
415 int wfd_group_remove_member(wfd_group_s *group, unsigned char *addr)
416 {
417         __WDS_LOG_FUNC_ENTER__;
418         wfd_device_s *member = NULL;
419         wfd_manager_s *manager = wfd_get_manager();
420
421         if (!group || !addr) {
422                 WDS_LOGE("Invalid parameter");
423                 __WDS_LOG_FUNC_EXIT__;
424                 return -1;
425         }
426
427         if (group->member_count == 0) {
428                 WDS_LOGE("There is no members");
429                 __WDS_LOG_FUNC_EXIT__;
430                 return -1;
431         }
432
433         member = wfd_group_find_member_by_addr(group, addr);
434         if (!member) {
435                 WDS_LOGD("Member not found [MAC: " MACSECSTR "]",
436                                                 MAC2SECSTR(addr));
437                 __WDS_LOG_FUNC_EXIT__;
438                 return -1;
439         }
440
441         group->members = g_list_remove(group->members, member);
442         g_free(member);
443         group->member_count--;
444
445         if (group->role == WFD_DEV_ROLE_GO) {
446                 if (!group->member_count && wfd_util_is_remove_group_allowed()) {
447                         wfd_oem_destroy_group(manager->oem_ops, group->ifname);
448                         wfd_destroy_group(manager);
449                         wfd_peer_clear_all(manager);
450                 }
451         } else {
452                 wfd_oem_destroy_group(manager->oem_ops, group->ifname);
453                 wfd_destroy_group(manager);
454                 wfd_peer_clear_all(manager);
455         }
456
457         __WDS_LOG_FUNC_EXIT__;
458         return 0;
459 }