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"
46 /* Check the group instance which has same interface name,
47 * before using this function */
48 wfd_group_s *wfd_create_group(void *data, wfd_oem_event_s *group_info)
50 __WDS_LOG_FUNC_ENTER__;
51 wfd_group_s *group = NULL;
52 wfd_manager_s *manager = (wfd_manager_s*) data;
53 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
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 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
79 WDS_LOGE("Failed to allocate memory for group. [%s]", error_buf);
80 __WDS_LOG_FUNC_EXIT__;
84 memcpy(group->ifname, group_info->ifname, IFACE_NAME_LEN);
85 group->ifname[IFACE_NAME_LEN] = '\0';
86 group->role = group_info->dev_role;
87 memcpy(group->go_dev_addr, edata->go_dev_addr, MACADDR_LEN);
89 g_strlcpy(group->ssid, edata->ssid, DEV_NAME_LEN + 1);
90 g_strlcpy(group->passphrase, edata->pass, PASSPHRASE_LEN_MAX + 1);
91 memset(manager->local->passphrase, 0x0, PASSPHRASE_LEN_MAX + 1);
92 group->freq = edata->freq;
94 manager->group = group;
95 manager->local->dev_role = group_info->dev_role;
97 wfd_util_dhcps_start(group->ifname);
98 group->pending = FALSE;
99 WDS_LOGD("Role is Group Owner. DHCP Server started");
101 __WDS_LOG_FUNC_EXIT__;
105 /* Used for CTRL-EVENT_CONNECTED event that comes before group created */
106 wfd_group_s *wfd_create_pending_group(void *data, unsigned char * bssid)
108 __WDS_LOG_FUNC_ENTER__;
109 wfd_group_s *group = NULL;
110 wfd_manager_s *manager = (wfd_manager_s*) data;
111 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
113 if (!manager || !bssid) {
114 WDS_LOGE("Invalid parameter");
115 __WDS_LOG_FUNC_EXIT__;
119 group = manager->group;
121 WDS_LOGE("Group already exist");
122 __WDS_LOG_FUNC_EXIT__;
127 group = (wfd_group_s*) g_try_malloc0(sizeof(wfd_group_s));
129 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
130 WDS_LOGE("Failed to allocate memory for group. [%s]", error_buf);
131 __WDS_LOG_FUNC_EXIT__;
135 memcpy(group->bssid, bssid, MACADDR_LEN);
136 group->flags &= WFD_GROUP_FLAG_NONE;
137 group->pending = TRUE;
139 __WDS_LOG_FUNC_EXIT__;
143 int wfd_group_complete(void *data, wfd_oem_event_s *group_info)
145 __WDS_LOG_FUNC_ENTER__;
146 wfd_manager_s *manager = (wfd_manager_s*) data;
147 wfd_session_s *session = NULL;
148 wfd_group_s *group = NULL;
149 wfd_device_s *peer = NULL;
151 if (!manager || !group_info) {
152 WDS_LOGE("Invalid parameter");
153 __WDS_LOG_FUNC_EXIT__;
156 wfd_oem_group_data_s *edata = (wfd_oem_group_data_s *)group_info->edata;
159 WDS_LOGE("Invalid parameter");
160 __WDS_LOG_FUNC_EXIT__;
164 group = manager->group;
166 WDS_LOGE("Group not found");
167 __WDS_LOG_FUNC_EXIT__;
171 g_strlcpy(group->ifname, group_info->ifname, IFACE_NAME_LEN + 1);
172 group->role = group_info->dev_role;
173 memcpy(group->go_dev_addr, edata->go_dev_addr, MACADDR_LEN);
175 g_strlcpy(group->ssid, edata->ssid, DEV_NAME_LEN + 1);
176 g_strlcpy(group->passphrase, edata->pass, PASSPHRASE_LEN_MAX + 1);
177 memset(manager->local->passphrase, 0x0, PASSPHRASE_LEN_MAX + 1);
178 group->freq = edata->freq;
179 if (edata->is_persistent)
180 group->flags |= WFD_GROUP_FLAG_PERSISTENT;
182 manager->local->dev_role = group_info->dev_role;
183 group->pending = FALSE;
185 session = manager->session;
186 peer = wfd_session_get_peer(session);
187 if (!peer && !(group->flags & WFD_GROUP_FLAG_AUTONOMOUS)) {
188 if (!session && (group->flags & WFD_GROUP_FLAG_PERSISTENT)) {
189 WDS_LOGE("Group created by supplicant is persistent group.");
191 * 1. When GO, start dhcpd and start session at peer joined event.
192 * 2. When GC, start dhcpc after adding GO Address as peer.
194 if (group->role == WFD_DEV_ROLE_GC) {
195 peer = wfd_peer_find_by_addr(manager,
198 WDS_LOGI("Add peer GO");
199 peer = wfd_add_peer(manager,
205 WDS_LOGD("Failed to find peer by device address[" MACSECSTR "]",
206 MAC2SECSTR(edata->go_dev_addr));
207 __WDS_LOG_FUNC_EXIT__;
212 if (group->role == WFD_DEV_ROLE_GO) {
213 wfd_util_dhcps_start(group->ifname);
214 WDS_LOGD("Role is Group Owner. DHCP Server started");
217 WDS_LOGE("Peer is not in the session");
218 __WDS_LOG_FUNC_EXIT__;
222 WDS_LOGD("Role is Group Client.complete session and add peer to member");
223 memcpy(peer->intf_addr, group->go_dev_addr, MACADDR_LEN);
224 wfd_group_add_member(group, peer->dev_addr);
225 session->state = SESSION_STATE_COMPLETED;
226 peer->state = WFD_PEER_STATE_CONNECTED;
227 if (edata->ip_addr[3] && edata->ip_addr_go[3]) {
228 peer->ip_type = WFD_IP_TYPE_OVER_EAPOL;
229 memcpy(peer->client_ip_addr, edata->ip_addr, IPADDR_LEN);
230 WDS_LOGE("Peer's client IP [" IPSTR "]", IP2STR((char*) &peer->client_ip_addr));
231 memcpy(peer->go_ip_addr, edata->ip_addr_go, IPADDR_LEN);
232 WDS_LOGE("Peer's GO IP [" IPSTR "]", IP2STR((char*) &peer->go_ip_addr));
234 if (peer->ip_type != WFD_IP_TYPE_OVER_EAPOL)
235 wfd_util_dhcpc_start(group->ifname, peer);
238 __WDS_LOG_FUNC_EXIT__;
242 int wfd_destroy_group(void *data)
244 __WDS_LOG_FUNC_ENTER__;
245 wfd_group_s *group = NULL;
246 wfd_manager_s *manager = (wfd_manager_s*) data;
248 wfd_device_s *member = NULL;
252 WDS_LOGE("Invalid parameter");
253 __WDS_LOG_FUNC_EXIT__;
257 group = manager->group;
259 WDS_LOGE("Group not exist");
260 __WDS_LOG_FUNC_EXIT__;
263 manager->group = NULL;
265 if (group->pending == FALSE) {
266 wfd_util_ip_unset(group->ifname);
267 if (group->role == WFD_DEV_ROLE_GO)
268 wfd_util_dhcps_stop(group->ifname);
270 wfd_util_dhcpc_stop(group->ifname);
272 memset(manager->local->ip_addr, 0x0, IPADDR_LEN);
274 temp = g_list_first(group->members);
275 while (temp && count < group->member_count) {
277 WDS_LOGD("%dth member[%s] will be removed", count, member->dev_name);
280 temp = g_list_next(temp);
284 if (group->members) {
285 g_list_free(group->members);
286 group->members = NULL;
291 manager->local->dev_role = WFD_DEV_ROLE_NONE;
292 __WDS_LOG_FUNC_EXIT__;
297 int wfd_group_get_channel(wfd_group_s *group)
299 __WDS_LOG_FUNC_ENTER__;
302 WDS_LOGE("Invalid parameter");
303 __WDS_LOG_FUNC_EXIT__;
307 __WDS_LOG_FUNC_EXIT__;
312 int wfd_group_is_autonomous(wfd_group_s *group)
314 __WDS_LOG_FUNC_ENTER__;
317 WDS_LOGE("Invalid parameter");
318 __WDS_LOG_FUNC_EXIT__;
322 __WDS_LOG_FUNC_EXIT__;
323 return ((group->flags & WFD_GROUP_FLAG_AUTONOMOUS) == WFD_GROUP_FLAG_AUTONOMOUS);
327 int wfd_group_get_members()
329 __WDS_LOG_FUNC_ENTER__;
331 __WDS_LOG_FUNC_EXIT__;
335 int wfd_group_make_persistent()
337 __WDS_LOG_FUNC_ENTER__;
339 __WDS_LOG_FUNC_EXIT__;
343 int wfd_group_get_flags(wfd_group_s *group)
345 __WDS_LOG_FUNC_ENTER__;
348 WDS_LOGE("Invalid parameter");
349 __WDS_LOG_FUNC_EXIT__;
353 __WDS_LOG_FUNC_EXIT__;
358 wfd_device_s *wfd_group_find_member_by_addr(wfd_group_s *group, unsigned char *addr)
360 __WDS_LOG_FUNC_ENTER__;
362 wfd_device_s *member = NULL;
364 if (!group || !addr) {
365 WDS_LOGE("Invalid parameter");
366 __WDS_LOG_FUNC_EXIT__;
370 if (!group->member_count) {
371 WDS_LOGE("There is no members");
372 __WDS_LOG_FUNC_EXIT__;
376 temp = g_list_first(group->members);
379 if (!memcmp(member->intf_addr, addr, MACADDR_LEN) ||
380 !memcmp(member->dev_addr, addr, MACADDR_LEN)) {
381 WDS_LOGD("Member found");
384 temp = g_list_next(temp);
388 __WDS_LOG_FUNC_EXIT__;
392 int wfd_group_add_member(wfd_group_s *group, unsigned char *addr)
394 __WDS_LOG_FUNC_ENTER__;
395 wfd_device_s *member = NULL;
396 wfd_manager_s *manager = wfd_get_manager();
398 if (!group || !addr) {
399 WDS_LOGE("Invalid parameter");
400 __WDS_LOG_FUNC_EXIT__;
404 member = wfd_group_find_member_by_addr(group, addr);
406 WDS_LOGE("Member already exist");
407 __WDS_LOG_FUNC_EXIT__;
411 member = wfd_peer_find_by_addr(manager, addr);
413 WDS_LOGE("Peer not found");
415 group->members = g_list_prepend(group->members, member);
416 group->member_count++;
418 manager->peers = g_list_remove(manager->peers, member);
419 manager->peer_count--;
421 __WDS_LOG_FUNC_EXIT__;
425 int wfd_group_remove_member(wfd_group_s *group, unsigned char *addr)
427 __WDS_LOG_FUNC_ENTER__;
428 wfd_device_s *member = NULL;
429 wfd_manager_s *manager = wfd_get_manager();
431 if (!group || !addr) {
432 WDS_LOGE("Invalid parameter");
433 __WDS_LOG_FUNC_EXIT__;
437 if (group->member_count == 0) {
438 WDS_LOGE("There is no members");
439 __WDS_LOG_FUNC_EXIT__;
443 member = wfd_group_find_member_by_addr(group, addr);
445 WDS_LOGD("Member not found [MAC: " MACSECSTR "]",
447 __WDS_LOG_FUNC_EXIT__;
451 group->members = g_list_remove(group->members, member);
453 group->member_count--;
455 if (group->role == WFD_DEV_ROLE_GO) {
456 if (!group->member_count && wfd_util_is_remove_group_allowed()) {
457 wfd_oem_destroy_group(manager->oem_ops, group->ifname);
458 wfd_destroy_group(manager);
459 wfd_peer_clear_all(manager);
462 wfd_oem_destroy_group(manager->oem_ops, group->ifname);
463 wfd_destroy_group(manager);
464 wfd_peer_clear_all(manager);
467 __WDS_LOG_FUNC_EXIT__;