Added WirelessManager, a port of wpa_supplicant.
[AROS.git] / workbench / network / WirelessManager / src / wps / wps_ufd.c
blob1a911e1d4ceb23975e3b45e130b87e896a3906c6
1 /*
2 * UFD routines for Wi-Fi Protected Setup
3 * Copyright (c) 2009, Masashi Honma <honma@ictec.co.jp>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
16 #include "common.h"
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/wait.h>
20 #include <fcntl.h>
21 #include <dirent.h>
23 #include "wps/wps.h"
24 #include "wps/wps_i.h"
26 #ifdef CONFIG_NATIVE_WINDOWS
27 #define UFD_DIR1 "%s\\SMRTNTKY"
28 #define UFD_DIR2 UFD_DIR1 "\\WFAWSC"
29 #define UFD_FILE UFD_DIR2 "\\%s"
30 #else /* CONFIG_NATIVE_WINDOWS */
31 #define UFD_DIR1 "%s/SMRTNTKY"
32 #define UFD_DIR2 UFD_DIR1 "/WFAWSC"
33 #define UFD_FILE UFD_DIR2 "/%s"
34 #endif /* CONFIG_NATIVE_WINDOWS */
37 struct wps_ufd_data {
38 int ufd_fd;
42 static int dev_pwd_e_file_filter(const struct dirent *entry)
44 unsigned int prefix;
45 char ext[5];
47 if (sscanf(entry->d_name, "%8x.%4s", &prefix, ext) != 2)
48 return 0;
49 if (prefix == 0)
50 return 0;
51 if (os_strcasecmp(ext, "WFA") != 0)
52 return 0;
54 return 1;
58 static int wps_get_dev_pwd_e_file_name(char *path, char *file_name)
60 struct dirent **namelist;
61 int i, file_num;
63 file_num = scandir(path, &namelist, &dev_pwd_e_file_filter,
64 alphasort);
65 if (file_num < 0) {
66 wpa_printf(MSG_ERROR, "WPS: OOB file not found: %d (%s)",
67 errno, strerror(errno));
68 return -1;
70 if (file_num == 0) {
71 wpa_printf(MSG_ERROR, "WPS: OOB file not found");
72 os_free(namelist);
73 return -1;
75 os_strlcpy(file_name, namelist[0]->d_name, 13);
76 for (i = 0; i < file_num; i++)
77 os_free(namelist[i]);
78 os_free(namelist);
79 return 0;
83 static int get_file_name(struct wps_context *wps, int registrar,
84 const char *path, char *file_name)
86 switch (wps->oob_conf.oob_method) {
87 case OOB_METHOD_CRED:
88 os_snprintf(file_name, 13, "00000000.WSC");
89 break;
90 case OOB_METHOD_DEV_PWD_E:
91 if (registrar) {
92 char temp[128];
93 os_snprintf(temp, sizeof(temp), UFD_DIR2, path);
94 if (wps_get_dev_pwd_e_file_name(temp, file_name) < 0)
95 return -1;
96 } else {
97 u8 *mac_addr = wps->dev.mac_addr;
99 os_snprintf(file_name, 13, "%02X%02X%02X%02X.WFA",
100 mac_addr[2], mac_addr[3], mac_addr[4],
101 mac_addr[5]);
103 break;
104 case OOB_METHOD_DEV_PWD_R:
105 os_snprintf(file_name, 13, "00000000.WFA");
106 break;
107 default:
108 wpa_printf(MSG_ERROR, "WPS: Invalid USBA OOB method");
109 return -1;
111 return 0;
115 static int ufd_mkdir(const char *path)
117 if (mkdir(path, S_IRWXU) < 0 && errno != EEXIST) {
118 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to create directory "
119 "'%s': %d (%s)", path, errno, strerror(errno));
120 return -1;
122 return 0;
126 static void * init_ufd(struct wps_context *wps,
127 struct oob_device_data *oob_dev, int registrar)
129 int write_f;
130 char temp[128];
131 char *path = oob_dev->device_path;
132 char filename[13];
133 struct wps_ufd_data *data;
134 int ufd_fd;
136 if (path == NULL)
137 return NULL;
139 write_f = wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ?
140 !registrar : registrar;
142 if (get_file_name(wps, registrar, path, filename) < 0) {
143 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file name");
144 return NULL;
147 if (write_f) {
148 os_snprintf(temp, sizeof(temp), UFD_DIR1, path);
149 if (ufd_mkdir(temp))
150 return NULL;
151 os_snprintf(temp, sizeof(temp), UFD_DIR2, path);
152 if (ufd_mkdir(temp))
153 return NULL;
156 os_snprintf(temp, sizeof(temp), UFD_FILE, path, filename);
157 if (write_f)
158 ufd_fd = open(temp, O_WRONLY | O_CREAT | O_TRUNC,
159 S_IRUSR | S_IWUSR);
160 else
161 ufd_fd = open(temp, O_RDONLY);
162 if (ufd_fd < 0) {
163 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to open %s: %s",
164 temp, strerror(errno));
165 return NULL;
168 data = os_zalloc(sizeof(*data));
169 if (data == NULL)
170 return NULL;
171 data->ufd_fd = ufd_fd;
172 return data;
176 static struct wpabuf * read_ufd(void *priv)
178 struct wps_ufd_data *data = priv;
179 struct wpabuf *buf;
180 struct stat s;
181 size_t file_size;
183 if (fstat(data->ufd_fd, &s) < 0) {
184 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file size");
185 return NULL;
188 file_size = s.st_size;
189 buf = wpabuf_alloc(file_size);
190 if (buf == NULL) {
191 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to alloc read "
192 "buffer");
193 return NULL;
196 if (read(data->ufd_fd, wpabuf_mhead(buf), file_size) !=
197 (int) file_size) {
198 wpabuf_free(buf);
199 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to read");
200 return NULL;
202 wpabuf_put(buf, file_size);
203 return buf;
207 static int write_ufd(void *priv, struct wpabuf *buf)
209 struct wps_ufd_data *data = priv;
211 if (write(data->ufd_fd, wpabuf_mhead(buf), wpabuf_len(buf)) !=
212 (int) wpabuf_len(buf)) {
213 wpa_printf(MSG_ERROR, "WPS (UFD): Failed to write");
214 return -1;
216 return 0;
220 static void deinit_ufd(void *priv)
222 struct wps_ufd_data *data = priv;
223 close(data->ufd_fd);
224 os_free(data);
228 struct oob_device_data oob_ufd_device_data = {
229 .device_name = NULL,
230 .device_path = NULL,
231 .init_func = init_ufd,
232 .read_func = read_ufd,
233 .write_func = write_ufd,
234 .deinit_func = deinit_ufd,