2 * Network Configuration Module
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * This file implements wifi direct group functions.
23 * @file wifi-direct-group.c
24 * @author Gibyoung Kim (lastkgb.kim@samsung.com)
34 #include <wifi-direct.h>
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"
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)
51 __WDS_LOG_FUNC_ENTER__;
52 wfd_group_s *group = NULL;
53 wfd_manager_s *manager = (wfd_manager_s*) data;
55 if (!manager || !group_info) {
56 WDS_LOGE("Invalid parameter");
57 __WDS_LOG_FUNC_EXIT__;
60 wfd_oem_group_data_s *edata = (wfd_oem_group_data_s *)group_info->edata;
63 WDS_LOGE("Invalid parameter");
64 __WDS_LOG_FUNC_EXIT__;
68 group = manager->group;
70 WDS_LOGE("Group already exist");
71 __WDS_LOG_FUNC_EXIT__;
76 group = (wfd_group_s*) g_try_malloc0(sizeof(wfd_group_s));
78 WDS_LOGE("Failed to allocate memory for group. [%s]", strerror(errno));
79 __WDS_LOG_FUNC_EXIT__;
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);
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;
93 manager->group = group;
94 manager->local->dev_role = group_info->dev_role;
96 wfd_util_dhcps_start(group->ifname);
97 group->pending = FALSE;
98 WDS_LOGD("Role is Group Owner. DHCP Server started");
100 __WDS_LOG_FUNC_EXIT__;
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)
107 __WDS_LOG_FUNC_ENTER__;
108 wfd_group_s *group = NULL;
109 wfd_manager_s *manager = (wfd_manager_s*) data;
111 if (!manager || !bssid) {
112 WDS_LOGE("Invalid parameter");
113 __WDS_LOG_FUNC_EXIT__;
117 group = manager->group;
119 WDS_LOGE("Group already exist");
120 __WDS_LOG_FUNC_EXIT__;
125 group = (wfd_group_s*) g_try_malloc0(sizeof(wfd_group_s));
127 WDS_LOGE("Failed to allocate memory for group. [%s]", strerror(errno));
128 __WDS_LOG_FUNC_EXIT__;
132 memcpy(group->bssid, bssid, MACADDR_LEN);
133 group->flags &= WFD_GROUP_FLAG_NONE;
134 group->pending = TRUE;
136 __WDS_LOG_FUNC_EXIT__;
140 int wfd_group_complete(void *data, wfd_oem_event_s *group_info)
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;
148 if (!manager || !group_info) {
149 WDS_LOGE("Invalid parameter");
150 __WDS_LOG_FUNC_EXIT__;
153 wfd_oem_group_data_s *edata = (wfd_oem_group_data_s *)group_info->edata;
156 WDS_LOGE("Invalid parameter");
157 __WDS_LOG_FUNC_EXIT__;
161 group = manager->group;
163 WDS_LOGE("Group not found");
164 __WDS_LOG_FUNC_EXIT__;
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);
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;
179 manager->local->dev_role = group_info->dev_role;
180 group->pending = FALSE;
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.");
188 * TODO: Add handling for Reinvoked Persistent Group.
190 __WDS_LOG_FUNC_EXIT__;
193 WDS_LOGD("Failed to find peer by device address[" MACSECSTR "]",
194 MAC2SECSTR(edata->go_dev_addr));
195 __WDS_LOG_FUNC_EXIT__;
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");
205 WDS_LOGE("Peer is not in the session");
206 __WDS_LOG_FUNC_EXIT__;
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));
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);
229 __WDS_LOG_FUNC_EXIT__;
233 int wfd_destroy_group(void *data)
235 __WDS_LOG_FUNC_ENTER__;
236 wfd_group_s *group = NULL;
237 wfd_manager_s *manager = (wfd_manager_s*) data;
239 wfd_device_s *member = NULL;
243 WDS_LOGE("Invalid parameter");
244 __WDS_LOG_FUNC_EXIT__;
248 group = manager->group;
250 WDS_LOGE("Group not exist");
251 __WDS_LOG_FUNC_EXIT__;
254 manager->group = NULL;
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);
261 wfd_util_dhcpc_stop(group->ifname);
263 memset(manager->local->ip_addr, 0x0, IPADDR_LEN);
265 temp = g_list_first(group->members);
266 while (temp && count < group->member_count) {
268 WDS_LOGD("%dth member[%s] will be removed", count, member->dev_name);
271 temp = g_list_next(temp);
275 if (group->members) {
276 g_list_free(group->members);
277 group->members = NULL;
282 manager->local->dev_role = WFD_DEV_ROLE_NONE;
283 __WDS_LOG_FUNC_EXIT__;
288 int wfd_group_get_channel(wfd_group_s *group)
290 __WDS_LOG_FUNC_ENTER__;
293 WDS_LOGE("Invalid parameter");
294 __WDS_LOG_FUNC_EXIT__;
298 __WDS_LOG_FUNC_EXIT__;
303 int wfd_group_is_autonomous(wfd_group_s *group)
305 __WDS_LOG_FUNC_ENTER__;
308 WDS_LOGE("Invalid parameter");
309 __WDS_LOG_FUNC_EXIT__;
313 __WDS_LOG_FUNC_EXIT__;
314 return ((group->flags & WFD_GROUP_FLAG_AUTONOMOUS) == WFD_GROUP_FLAG_AUTONOMOUS);
318 int wfd_group_get_members()
320 __WDS_LOG_FUNC_ENTER__;
322 __WDS_LOG_FUNC_EXIT__;
326 int wfd_group_make_persistent()
328 __WDS_LOG_FUNC_ENTER__;
330 __WDS_LOG_FUNC_EXIT__;
334 int wfd_group_get_flags(wfd_group_s *group)
336 __WDS_LOG_FUNC_ENTER__;
339 WDS_LOGE("Invalid parameter");
340 __WDS_LOG_FUNC_EXIT__;
344 __WDS_LOG_FUNC_EXIT__;
349 wfd_device_s *wfd_group_find_member_by_addr(wfd_group_s *group, unsigned char *addr)
351 __WDS_LOG_FUNC_ENTER__;
353 wfd_device_s *member = NULL;
355 if (!group || !addr) {
356 WDS_LOGE("Invalid parameter");
357 __WDS_LOG_FUNC_EXIT__;
361 if (!group->member_count) {
362 WDS_LOGE("There is no members");
363 __WDS_LOG_FUNC_EXIT__;
367 temp = g_list_first(group->members);
370 if (!memcmp(member->intf_addr, addr, MACADDR_LEN) ||
371 !memcmp(member->dev_addr, addr, MACADDR_LEN)) {
372 WDS_LOGD("Member found");
375 temp = g_list_next(temp);
379 __WDS_LOG_FUNC_EXIT__;
383 int wfd_group_add_member(wfd_group_s *group, unsigned char *addr)
385 __WDS_LOG_FUNC_ENTER__;
386 wfd_device_s *member = NULL;
387 wfd_manager_s *manager = wfd_get_manager();
389 if (!group || !addr) {
390 WDS_LOGE("Invalid parameter");
391 __WDS_LOG_FUNC_EXIT__;
395 member = wfd_group_find_member_by_addr(group, addr);
397 WDS_LOGE("Member already exist");
401 member = wfd_peer_find_by_addr(manager, addr);
403 WDS_LOGE("Peer not found");
405 group->members = g_list_prepend(group->members, member);
406 group->member_count++;
408 manager->peers = g_list_remove(manager->peers, member);
409 manager->peer_count--;
411 __WDS_LOG_FUNC_EXIT__;
415 int wfd_group_remove_member(wfd_group_s *group, unsigned char *addr)
417 __WDS_LOG_FUNC_ENTER__;
418 wfd_device_s *member = NULL;
419 wfd_manager_s *manager = wfd_get_manager();
421 if (!group || !addr) {
422 WDS_LOGE("Invalid parameter");
423 __WDS_LOG_FUNC_EXIT__;
427 if (group->member_count == 0) {
428 WDS_LOGE("There is no members");
429 __WDS_LOG_FUNC_EXIT__;
433 member = wfd_group_find_member_by_addr(group, addr);
435 WDS_LOGD("Member not found [MAC: " MACSECSTR "]",
437 __WDS_LOG_FUNC_EXIT__;
441 group->members = g_list_remove(group->members, member);
443 group->member_count--;
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);
452 wfd_oem_destroy_group(manager->oem_ops, group->ifname);
453 wfd_destroy_group(manager);
454 wfd_peer_clear_all(manager);
457 __WDS_LOG_FUNC_EXIT__;