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)
35 #include <wifi-direct.h>
37 #include "wifi-direct-ipc.h"
38 #include "wifi-direct-manager.h"
39 #include "wifi-direct-state.h"
40 #include "wifi-direct-peer.h"
41 #include "wifi-direct-oem.h"
42 #include "wifi-direct-group.h"
43 #include "wifi-direct-util.h"
44 #include "wifi-direct-session.h"
45 #include "wifi-direct-log.h"
47 /* Check the group instance which has same interface name,
48 * before using this function */
50 /* Used for CTRL-EVENT_CONNECTED event that comes before group created */
51 wfd_group_s *wfd_create_pending_group(void *data, unsigned char * bssid)
53 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
54 wfd_group_s *group = NULL;
55 wfd_manager_s *manager = (wfd_manager_s*) data;
56 char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
58 if (!manager || !bssid) {
59 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
60 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
64 group = manager->group;
66 WDS_LOGE("Group already exist");//LCOV_EXCL_LINE
67 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
72 group = (wfd_group_s*) g_try_malloc0(sizeof(wfd_group_s));
74 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
75 WDS_LOGE("Failed to allocate memory for group. [%s]", error_buf);
76 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
80 memcpy(group->bssid, bssid, MACADDR_LEN);
81 group->flags &= WFD_GROUP_FLAG_NONE;
82 group->pending = TRUE;
84 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
88 int wfd_group_complete(void *data, wfd_oem_event_s *group_info)
90 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
91 wfd_manager_s *manager = (wfd_manager_s*) data;
92 wfd_session_s *session = NULL;
93 wfd_group_s *group = NULL;
94 wfd_device_s *peer = NULL;
96 if (!manager || !group_info) {
97 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
98 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
101 wfd_oem_group_data_s *edata = (wfd_oem_group_data_s *)group_info->edata;
104 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
105 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
109 group = manager->group;
111 WDS_LOGE("Group not found");//LCOV_EXCL_LINE
112 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
116 g_strlcpy(group->ifname, group_info->ifname, IFACE_NAME_LEN + 1);
117 group->role = group_info->dev_role;
118 memcpy(group->go_dev_addr, edata->go_dev_addr, MACADDR_LEN);
120 g_strlcpy(group->ssid, edata->ssid, DEV_NAME_LEN + 1);
121 g_strlcpy(group->passphrase, edata->pass, PASSPHRASE_LEN_MAX + 1);
122 memset(manager->local->passphrase, 0x0, PASSPHRASE_LEN_MAX + 1);
123 group->freq = edata->freq;
124 if (edata->is_persistent)
125 group->flags |= WFD_GROUP_FLAG_PERSISTENT;
127 manager->local->dev_role = group_info->dev_role;
128 group->pending = FALSE;
130 session = manager->session;
131 peer = wfd_session_get_peer(session);
132 if (!peer && !(group->flags & WFD_GROUP_FLAG_AUTONOMOUS)) {
133 if (!session && (group->flags & WFD_GROUP_FLAG_PERSISTENT)) {
134 WDS_LOGE("Group created by supplicant is persistent group.");//LCOV_EXCL_LINE
136 * 1. When GO, start dhcpd and start session at peer joined event.
137 * 2. When GC, start dhcpc after adding GO Address as peer.
139 if (group->role == WFD_DEV_ROLE_GC) {
140 peer = wfd_peer_find_by_addr(manager,
143 WDS_LOGI("Add peer GO");//LCOV_EXCL_LINE
144 peer = wfd_add_peer(manager,
150 WDS_LOGD("Failed to find peer by device address[" MACSECSTR "]",
151 MAC2SECSTR(edata->go_dev_addr));
152 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
157 if (group->role == WFD_DEV_ROLE_GO) {
158 wfd_util_dhcps_start(group->ifname);
159 WDS_LOGD("Role is Group Owner. DHCP Server started");//LCOV_EXCL_LINE
162 WDS_LOGE("Peer is not in the session");//LCOV_EXCL_LINE
163 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
167 WDS_LOGD("Role is Group Client.complete session and add peer to member");//LCOV_EXCL_LINE
168 memcpy(peer->intf_addr, group->go_dev_addr, MACADDR_LEN);
169 wfd_group_add_member(group, peer->dev_addr);
171 session->state = SESSION_STATE_COMPLETED;
172 peer->state = WFD_PEER_STATE_CONNECTED;
173 if (edata->ip_addr[3] && edata->ip_addr_go[3]) {
174 peer->ip_type = WFD_IP_TYPE_OVER_EAPOL;
175 memcpy(peer->client_ip_addr, edata->ip_addr, IPADDR_LEN);
176 WDS_LOGE("Peer's client IP [" IPSTR "]", IP2STR((char*) &peer->client_ip_addr));
177 memcpy(peer->go_ip_addr, edata->ip_addr_go, IPADDR_LEN);
178 WDS_LOGE("Peer's GO IP [" IPSTR "]", IP2STR((char*) &peer->go_ip_addr));
180 if (peer->ip_type != WFD_IP_TYPE_OVER_EAPOL)
181 wfd_util_dhcpc_start(group->ifname, peer);
184 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
188 int wfd_destroy_group(void *data)
190 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
191 wfd_group_s *group = NULL;
192 wfd_manager_s *manager = (wfd_manager_s*) data;
194 wfd_device_s *member = NULL;
198 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
199 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
203 group = manager->group;
205 WDS_LOGE("Group not exist");//LCOV_EXCL_LINE
206 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
209 manager->group = NULL;
211 if (group->pending == FALSE) {
212 wfd_util_ip_unset(group->ifname);
213 if (group->role == WFD_DEV_ROLE_GO)
214 wfd_util_dhcps_stop(group->ifname);
216 wfd_util_dhcpc_stop(group->ifname);
218 memset(manager->local->ip_addr, 0x0, IPADDR_LEN);
220 temp = g_list_first(group->members);
221 while (temp && count < group->member_count) {
223 WDS_LOGD("%dth member[%p: %s] will be removed", count, member, member->dev_name);
224 wfd_peer_destroy(member);
226 temp = g_list_next(temp);
230 if (group->members) {
231 g_list_free(group->members);
232 group->members = NULL;
237 manager->local->dev_role = WFD_DEV_ROLE_NONE;
238 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
243 int wfd_group_get_channel(wfd_group_s *group)
245 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
248 WDS_LOGE("Invalid parameter");
249 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
253 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
258 int wfd_group_is_autonomous(wfd_group_s *group)
260 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
263 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
264 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
268 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
269 return ((group->flags & WFD_GROUP_FLAG_AUTONOMOUS) == WFD_GROUP_FLAG_AUTONOMOUS);
273 int wfd_group_get_members()
275 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
277 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
281 int wfd_group_make_persistent()
283 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
285 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
289 int wfd_group_get_flags(wfd_group_s *group)
291 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
294 WDS_LOGE("Invalid parameter");
295 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
299 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
304 wfd_device_s *wfd_group_find_member_by_addr(wfd_group_s *group, unsigned char *addr)
306 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
308 wfd_device_s *member = NULL;
310 if (!group || !addr) {
311 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
312 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
316 if (!group->member_count) {
317 WDS_LOGE("There is no members");//LCOV_EXCL_LINE
318 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
322 temp = g_list_first(group->members);
325 if (!memcmp(member->intf_addr, addr, MACADDR_LEN) ||
326 !memcmp(member->dev_addr, addr, MACADDR_LEN)) {
327 WDS_LOGD("Member found");//LCOV_EXCL_LINE
330 temp = g_list_next(temp);
334 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
338 int wfd_group_add_member(wfd_group_s *group, unsigned char *addr)
340 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
341 wfd_device_s *member = NULL;
342 wfd_manager_s *manager = wfd_get_manager();
344 if (!group || !addr) {
345 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
346 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
350 member = wfd_group_find_member_by_addr(group, addr);
352 WDS_LOGE("Member already exist");//LCOV_EXCL_LINE
353 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
357 member = wfd_peer_find_by_addr(manager, addr);
359 WDS_LOGE("Peer not found");//LCOV_EXCL_LINE
361 group->members = g_list_prepend(group->members, member);
362 group->member_count++;
364 manager->peers = g_list_remove(manager->peers, member);
365 manager->peer_count--;
367 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
371 int wfd_group_remove_member(wfd_group_s *group, unsigned char *addr)
373 __WDS_LOG_FUNC_ENTER__;//LCOV_EXCL_LINE
374 wfd_device_s *member = NULL;
375 wfd_manager_s *manager = wfd_get_manager();
378 if (!group || !addr) {
379 WDS_LOGE("Invalid parameter");//LCOV_EXCL_LINE
380 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
384 if (group->member_count == 0) {
385 WDS_LOGE("There is no members");//LCOV_EXCL_LINE
386 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
390 member = wfd_group_find_member_by_addr(group, addr);
392 WDS_LOGD("Member not found [MAC: " MACSECSTR "]",
394 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE
398 group->members = g_list_remove(group->members, member);
399 wfd_peer_destroy(member);
400 group->member_count--;
401 member_cnt = group->member_count;
403 if (group->role == WFD_DEV_ROLE_GO) {
404 if (!group->member_count && wfd_util_is_remove_group_allowed()) {
405 wfd_oem_destroy_group(manager->oem_ops, group->ifname);
406 wfd_destroy_group(manager);
407 wfd_peer_clear_all(manager);
410 wfd_oem_destroy_group(manager->oem_ops, group->ifname);
411 wfd_destroy_group(manager);
412 wfd_peer_clear_all(manager);
415 __WDS_LOG_FUNC_EXIT__;//LCOV_EXCL_LINE