2 * Network Configuration Module
4 * Copyright (c) 2017 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.
20 #include <tzplatform_config.h>
21 #include <openssl/evp.h>
22 #include <openssl/sha.h>
30 #include <netinet/in.h>
31 #include <sys/socket.h>
34 #include <sys/types.h>
39 #include "mesh-util.h"
40 #include "mesh-service.h"
41 #include "mesh-softap.h"
43 #define MOBILE_AP_WIFI_KEY_MAX_LEN 64 /**< Maximum length of wifi hash key */
45 #define HOSTAPD_VENDOR_ELEMENTS_WIFI_AP "DD050016321000" /* Specific application mode AP (e.g. GroupPlay) */
46 #define HOSTAPD_CONF "interface=%s\n" \
48 "ctrl_interface=%s\n" \
51 "ignore_broadcast_ssid=%d\n" \
55 "accept_mac_file=%s\n" \
56 "deny_mac_file=%s\n" \
58 #define HOSTAPD_CONF_LEN 1024
59 #define HOSTAPD_BIN "/usr/sbin/hostapd"
60 #define HOSTAPD_DEBUG_FILE "/var/log/mesh_hostapd.log"
61 #define HOSTAPD_ENTROPY_FILE tzplatform_mkpath(TZ_SYS_VAR, "/lib/misc/hostapd.bin")
62 #define HOSTAPD_MESH_CONF_FILE tzplatform_mkpath(TZ_SYS_VAR, "/lib/mesh/mesh_hostapd.conf")
63 #define HOSTAPD_CTRL_INTF_DIR tzplatform_mkpath(TZ_SYS_RUN, "/hostapd")
64 #define HOSTAPD_ALLOWED_LIST tzplatform_mkpath(TZ_SYS_VAR, "/lib/hostapd/hostapd.accept")
65 #define HOSTAPD_BLOCKED_LIST tzplatform_mkpath(TZ_SYS_VAR, "/lib/hostapd/hostapd.deny")
66 #define HOSTAPD_RETRY_MAX 5
67 #define HOSTAPD_RETRY_DELAY 500000 /* us */
69 #define MH_CTRL_INTF "/tmp/mesh_hostapd_wpa_ctrl"
71 #define PSK_ITERATION_COUNT 4096
72 #define MAX_BUF_SIZE (256u)
74 static pid_t hostapd_pid = 0;
75 static int hostapd_ctrl_fd = 0;
77 static int __get_psk_hexascii(const char *pass, const unsigned char *salt,
78 char *psk, unsigned int psk_len)
83 unsigned char buf[SHA256_DIGEST_LENGTH] = {0, };
85 if (pass == NULL || salt == NULL || psk == NULL
86 || psk_len < (SHA256_DIGEST_LENGTH * 2 + 1)) {
87 MESH_LOGE("Invalid parameter");
88 return MESHD_ERROR_INVALID_PARAMETER;
91 if (!PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass),
92 salt, strlen((const char *)salt),
93 PSK_ITERATION_COUNT, sizeof(buf), buf)) {
94 MESH_LOGE("Getting psk is failed");
95 return MESHD_ERROR_OPERATION_FAILED;
98 for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
102 psk[i << 1] = d_16 < 10 ? d_16 + '0' : d_16 - 10 + 'a';
103 psk[(i << 1) + 1] = r_16 < 10 ? r_16 + '0' : r_16 - 10 + 'a';
107 return MESHD_ERROR_NONE;
110 static int __config_hostapd(const char *softap_interface, const char *ssid,
111 const char *security, const char *passphrase, const char* mode,
112 int channel, int visibility, int mac_filter, int max_sta)
116 char buf[HOSTAPD_CONF_LEN] = "";
119 char key[MOBILE_AP_WIFI_KEY_MAX_LEN + 1];
120 char *hw_mode = NULL;
123 hw_mode = g_strdup("g");
125 hw_mode = g_strdup(mode);
128 snprintf(buf, sizeof(buf), HOSTAPD_CONF,
130 HOSTAPD_CTRL_INTF_DIR,
133 (visibility ? 0 : 2),
137 HOSTAPD_ALLOWED_LIST,
138 HOSTAPD_BLOCKED_LIST);
139 conf = g_strdup(buf);
143 /* Vendor elements conf. */
144 snprintf(buf, sizeof(buf),
145 "vendor_elements=%s\n", HOSTAPD_VENDOR_ELEMENTS_WIFI_AP);
147 conf = g_strconcat(old_conf, buf, NULL);
151 if (security != NULL && g_strcmp0(security, "wpa2-psk") == 0) {
152 ret = __get_psk_hexascii(passphrase,
153 (const unsigned char *)ssid, key, sizeof(key));
154 if (ret != MESHD_ERROR_NONE) {
156 MESH_LOGE("hex conversion failed");
157 return MESHD_ERROR_OPERATION_FAILED;
159 snprintf(buf, sizeof(buf),
160 "wpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", key);
163 conf = g_strconcat(old_conf, buf, NULL);
166 MESH_LOGD("Open connection [%s]", security);
169 fp = fopen(HOSTAPD_MESH_CONF_FILE, "w");
171 MESH_LOGE("Could not create the file.");
173 return MESHD_ERROR_IO_ERROR;
182 return MESHD_ERROR_NONE;
185 static int __open_hostapd_intf(const char* softap_interface, int *fd,
189 char ctrl_intf[255] = {0, };
190 struct sockaddr_un src;
191 struct sockaddr_un dest;
192 struct stat stat_buf;
194 if (fd == NULL || intf == NULL) {
195 MESH_LOGE("fd is NULL");
196 return MESHD_ERROR_INVALID_PARAMETER;
199 *fd = socket(PF_UNIX, SOCK_DGRAM, 0);
201 MESH_LOGE("socket is failed");
202 return MESHD_ERROR_OPERATION_FAILED;
205 src.sun_family = AF_UNIX;
206 g_strlcpy(src.sun_path, intf, sizeof(src.sun_path));
208 if (stat(src.sun_path, &stat_buf) == 0)
209 unlink(src.sun_path);
211 if (bind(*fd, (struct sockaddr *)&src, sizeof(src)) < 0) {
212 MESH_LOGE("bind is failed");
215 unlink(src.sun_path);
216 return MESHD_ERROR_OPERATION_FAILED;
219 snprintf(ctrl_intf, sizeof(ctrl_intf), "%s/%s",
220 HOSTAPD_CTRL_INTF_DIR, softap_interface);
221 dest.sun_family = AF_UNIX;
222 g_strlcpy(dest.sun_path, ctrl_intf, sizeof(dest.sun_path));
224 while (connect(*fd, (struct sockaddr *)&dest, sizeof(dest)) < 0) {
225 if (++retry >= HOSTAPD_RETRY_MAX)
227 usleep(HOSTAPD_RETRY_DELAY);
229 MESH_LOGD("Successfully open interface[%s] to hostapd", intf);
231 return MESHD_ERROR_NONE;
234 MESH_LOGE("Cannot make connection to hostapd");
237 unlink(src.sun_path);
239 return MESHD_ERROR_OPERATION_FAILED;
242 static int __close_hostapd_intf(int *fd)
245 MESH_LOGE("fd is NULL");
246 return MESHD_ERROR_INVALID_PARAMETER;
253 return MESHD_ERROR_NONE;
256 static int __terminate_hostapd()
260 if (hostapd_pid == 0) {
261 MESH_LOGE("There is no hostapd");
262 return MESHD_ERROR_NONE;
265 ret = __close_hostapd_intf(&hostapd_ctrl_fd);
266 if (ret != MESHD_ERROR_NONE) {
267 MESH_LOGE("__close_hostapd_intf is failed");
270 kill(hostapd_pid, SIGTERM);
271 waitpid(hostapd_pid, NULL, 0);
274 return MESHD_ERROR_NONE;
277 static int __execute_hostapd()
282 MESH_LOGE("hostapd is running already");
283 return MESHD_ERROR_OPERATION_FAILED;
288 MESH_LOGE("fork failed");
289 return MESHD_ERROR_IO_ERROR;
293 if (execl(HOSTAPD_BIN, HOSTAPD_BIN, "-e", HOSTAPD_ENTROPY_FILE,
294 HOSTAPD_MESH_CONF_FILE,
295 "-f", HOSTAPD_DEBUG_FILE, "-ddd",
297 MESH_LOGE("execl failed");
300 MESH_LOGE("Should not get here!");
306 return MESHD_ERROR_NONE;
309 int mesh_softap_set_configuration(const char* softap_interface,
310 const char *ssid, const char* mode, int channel, int visibility,
311 int max_sta, int security, const char* passphrase)
313 int ret = MESHD_ERROR_NONE;
314 const char *sec = (security == 0) ? NULL : "wpa2-psk";
317 ret = __config_hostapd(softap_interface, ssid, sec, passphrase,
318 mode, channel, visibility, mac_filter, max_sta);
323 int mesh_softap_enable_softap(const char* softap_interface)
325 int ret = MESHD_ERROR_NONE;
327 if (NULL == softap_interface) {
328 MESH_LOGE("Invalid parameter");
329 return MESHD_ERROR_INVALID_PARAMETER;
332 ret = __execute_hostapd();
333 if (ret != MESHD_ERROR_NONE) {
334 MESH_LOGE("__execute_hostapd is failed");
335 return MESHD_ERROR_OPERATION_FAILED;
338 ret = __open_hostapd_intf(softap_interface,
339 &hostapd_ctrl_fd, MH_CTRL_INTF);
340 if (ret != MESHD_ERROR_NONE) {
341 MESH_LOGE("__open_hostapd_intf is failed");
342 __terminate_hostapd();
348 int mesh_softap_disable_softap()
350 int ret = MESHD_ERROR_NONE;
352 ret = __terminate_hostapd();
353 if (ret != MESHD_ERROR_NONE) {
354 MESH_LOGE("__execute_hostapd is failed");
355 return MESHD_ERROR_OPERATION_FAILED;