1/*
2 * Miscellaneous services
3 *
4 * Copyright (C) 2009, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * $Id: services.c,v 1.100 2010/03/04 09:39:18 Exp $
19 */
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25#include <errno.h>
26#include <sys/time.h>
27#include <time.h>
28#include <bcmnvram.h>
29#include <shutils.h>
30#include <dirent.h>
31#include <sys/mount.h>
32#include <sys/vfs.h>
33#include <rc.h>
34#include <shared.h>
35#include <arpa/inet.h>
36#include <time.h>
37#include <sys/time.h>
38#include <errno.h>
39#include <security_ipc.h>
40#include <bcmutils.h>
41#include <wlutils.h>
42#include <wlscan.h>
43#ifdef RTCONFIG_WPS
44#include <wps_ui.h>
45#endif
46
47#ifdef RTCONFIG_QTN
48#include "web-qtn.h"
49#endif
50
51static int
52set_wps_env(char *uibuf)
53{
54	int wps_fd = -1;
55	struct sockaddr_in to;
56	int sentBytes = 0;
57	uint32 uilen = strlen(uibuf);
58
59	//if (is_wps_enabled() == 0)
60	//	return -1;
61
62	if ((wps_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
63		goto exit;
64	}
65
66	/* send to WPS */
67	to.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
68	to.sin_family = AF_INET;
69	to.sin_port = htons(WPS_UI_PORT);
70
71	sentBytes = sendto(wps_fd, uibuf, uilen, 0, (struct sockaddr *) &to,
72		sizeof(struct sockaddr_in));
73
74	if (sentBytes != uilen) {
75		goto exit;
76	}
77
78	/* Sleep 100 ms to make sure
79	   WPS have received socket */
80	usleep(100*1000);
81	close(wps_fd);
82	return 0;
83
84exit:
85	if (wps_fd >= 0)
86		close(wps_fd);
87
88	/* Show error message ?  */
89	return -1;
90}
91
92
93
94/*
95 * input variables:
96 * 	nvram: wps_band:
97 * 	nvram: wps_action: WPS_UI_ACT_ADDENROLLEE/WPS_UI_ACT_CONFIGAe
98 *	       (wps_method: (according to wps_sta_pin)
99 *	nvram: wps_sta_pin:
100 *	nvram: wps_version2:
101 *	nvram: wps_autho_sta_mac:
102 *
103 * output variables:
104 * 	wps_proc_status
105 */
106
107int
108start_wps_method(void)
109{
110	int wps_band;
111	int wps_action;
112//	int wps_method;
113	char *wps_sta_pin;
114	char prefix[]="wlXXXXXX_", tmp[100];
115	char buf[256] = "SET ";
116	int len = 4;
117
118	if (getpid()!=1) {
119		notify_rc("start_wps_method");
120		return 0;
121	}
122
123	wps_band = nvram_get_int("wps_band");
124	snprintf(prefix, sizeof(prefix), "wl%d_", wps_band);
125	wps_action = nvram_get_int("wps_action");
126//	wps_method = nvram_get_int("wps_method"); // useless
127	wps_sta_pin = nvram_safe_get("wps_sta_pin");
128
129#ifdef RTCONFIG_QTN
130	int retval;
131
132#ifdef RTCONFIG_WPS_DUALBAND
133	if (1)
134#else
135	if (wps_band)
136#endif
137	{
138		if (strlen(wps_sta_pin) && strcmp(wps_sta_pin, "00000000") && (wl_wpsPincheck(wps_sta_pin) == 0))
139		{
140			retval = rpc_qcsapi_wps_registrar_report_pin(WIFINAME, wps_sta_pin);
141			if (retval < 0)
142				dbG("rpc_qcsapi_wps_registrar_report_pin %s error, return: %d\n", WIFINAME, retval);
143		}
144		else
145		{
146			retval = rpc_qcsapi_wps_registrar_report_button_press(WIFINAME);
147			if (retval < 0)
148				dbG("rpc_qcsapi_wps_registrar_report_button_press %s error, return: %d\n", WIFINAME, retval);
149		}
150
151#ifdef RTCONFIG_WPS_DUALBAND
152		// return 0;
153#else
154		return 0;
155#endif
156	}
157#endif
158
159	if (strlen(wps_sta_pin) && strcmp(wps_sta_pin, "00000000") && (wl_wpsPincheck(wps_sta_pin) == 0))
160		len += sprintf(buf + len, "wps_method=%d ", WPS_UI_METHOD_PIN);
161	else
162		len += sprintf(buf + len, "wps_method=%d ", WPS_UI_METHOD_PBC);
163
164	if (nvram_match("wps_version2", "enabled") && strlen(nvram_safe_get("wps_autho_sta_mac")))
165		len += sprintf(buf + len, "wps_autho_sta_mac=%s ", nvram_safe_get("wps_autho_sta_mac"));
166
167	if (strlen(wps_sta_pin))
168		len += sprintf(buf + len, "wps_sta_pin=%s ", wps_sta_pin);
169	else
170		len += sprintf(buf + len, "wps_sta_pin=00000000 ");
171
172//	len += sprintf(buf + len, "wps_action=%d ", wps_action);
173	len += sprintf(buf + len, "wps_action=%d ", WPS_UI_ACT_ADDENROLLEE);
174
175	len += sprintf(buf + len, "wps_config_command=%d ", WPS_UI_CMD_START);
176
177	nvram_set("wps_proc_status", "0");
178
179	len += sprintf(buf + len, "wps_pbc_method=%d ", WPS_UI_PBC_SW);
180	len += sprintf(buf + len, "wps_ifname=%s ", nvram_safe_get(strcat_r(prefix, "ifname", tmp)));
181
182	dbG("wps env buffer: %s\n", buf);
183
184//	nvram_unset("wps_sta_devname");
185//	nvram_unset("wps_sta_mac");
186//	nvram_unset("wps_pinfail");
187//	nvram_unset("wps_pinfail_mac");
188//	nvram_unset("wps_pinfail_name");
189//	nvram_unset("wps_pinfail_state");
190
191	nvram_set("wps_env_buf", buf);
192	nvram_set_int("wps_restart_war", 1);
193	set_wps_env(buf);
194
195	sprintf(tmp, "%lu", uptime());
196	nvram_set("wps_uptime", tmp);
197
198	return 0;
199}
200
201void
202restart_wps_monitor(void)
203{
204	int unit;
205	char word[256], *next;
206	char tmp[100], prefix[]="wlXXXXXXX_";
207	char *wps_argv[] = {"/bin/wps_monitor", NULL};
208	pid_t pid;
209
210	unlink("/tmp/wps_monitor.pid");
211
212	if (nvram_match("wps_enable", "1"))
213	{
214		unit = 0;
215		foreach(word, nvram_safe_get("wl_ifnames"), next)
216		{
217			snprintf(prefix, sizeof(prefix), "wl%d_", unit);
218			nvram_set(strcat_r(prefix, "wps_mode", tmp), "enabled");
219
220			unit++;
221		}
222
223		killall_tk("wps_monitor");
224
225		_eval(wps_argv, NULL, 0, &pid);
226	}
227}
228
229int
230stop_wps_method(void)
231{
232	char buf[256] = "SET ";
233	int len = 4;
234
235	if (getpid()!=1) {
236		notify_rc("stop_wps_method");
237		return 0;
238	}
239
240#ifdef RTCONFIG_QTN
241	int retval = rpc_qcsapi_wps_cancel(WIFINAME);
242	if (retval < 0)
243		dbG("rpc_qcsapi_wps_cancel %s error, return: %d\n", WIFINAME, retval);
244#endif
245
246	len += sprintf(buf + len, "wps_config_command=%d ", WPS_UI_CMD_STOP);
247	len += sprintf(buf + len, "wps_action=%d ", WPS_UI_ACT_NONE);
248
249	set_wps_env(buf);
250
251	usleep(100*1000);
252
253	int status = nvram_get_int("wps_proc_status");
254	if (status != 2 && status != 7)
255	restart_wps_monitor();
256
257	return 0;
258}
259
260int is_wps_stopped(void)
261{
262	int ret = 1;
263#ifdef RTCONFIG_QTN
264#ifdef RTCONFIG_WPS_DUALBAND
265	int ret_qtn = 1;
266#endif
267#endif
268	int status = nvram_get_int("wps_proc_status");
269	time_t now = uptime();
270	time_t wps_uptime = strtoul(nvram_safe_get("wps_uptime"), NULL, 10);
271	char tmp[100];
272
273	if ((now - wps_uptime) < 2)
274		return 0;
275
276#ifdef RTCONFIG_QTN
277	char wps_state[32], state_str[32];
278	int retval, state = -1 ;
279
280#ifdef RTCONFIG_WPS_DUALBAND
281	if (nvram_get_int("wps_enable"))
282#else
283	if (nvram_get_int("wps_enable") && nvram_get_int("wps_band"))
284#endif
285	{
286		retval = rpc_qcsapi_wps_get_state(WIFINAME, wps_state, sizeof(wps_state));
287		if (retval < 0)
288			dbG("rpc_qcsapi_wps_get_state %s error, return: %d\n", WIFINAME, retval);
289		else
290		{
291			if (sscanf(wps_state, "%d %s", &state, state_str) != 2)
292				dbG("prase wps state error!\n");
293
294			switch (state) {
295				case 0: /* WPS_INITIAL */
296					dbg("QTN: WPS Init\n");
297					break;
298				case 1: /* WPS_START */
299					dbg("QTN: Processing WPS start...\n");
300					ret = 0;
301#ifdef RTCONFIG_WPS_DUALBAND
302					ret_qtn = 0;
303#endif
304					break;
305				case 2: /* WPS_SUCCESS */
306					dbg("QTN: WPS Success\n");
307					break;
308				case 3: /* WPS_ERROR */
309					dbg("QTN: WPS Fail due to message exange error!\n");
310					break;
311				case 4: /* WPS_TIMEOUT */
312					dbg("QTN: WPS Fail due to time out!\n");
313					break;
314				case 5: /* WPS_OVERLAP */
315					dbg("QTN: WPS Fail due to PBC session overlap!\n");
316					break;
317				default:
318					ret = 0;
319#ifdef RTCONFIG_WPS_DUALBAND
320					ret_qtn = 0;
321#endif
322					break;
323			}
324		}
325
326#ifdef RTCONFIG_WPS_DUALBAND
327		// return ret;
328#else
329		return ret;
330#endif
331	}
332#endif
333
334	switch (status) {
335		case 0: /* Init */
336			dbg("Init again?\n");
337			if (nvram_get_int("wps_restart_war") && (now - wps_uptime) < 3)
338			{
339				dbg("Re-send WPS env!!!\n");
340				set_wps_env(nvram_safe_get("wps_env_buf"));
341				nvram_unset("wps_env_buf");
342				nvram_set_int("wps_restart_war", 0);
343				sprintf(tmp, "%lu", uptime());
344				nvram_set("wps_uptime", tmp);
345				return 0;
346			}
347			break;
348		case 1: /* WPS_ASSOCIATED */
349			dbg("Processing WPS start...\n");
350			ret = 0;
351			break;
352		case 2: /* WPS_OK */
353		case 7: /* WPS_MSGDONE */
354			dbg("WPS Success\n");
355			break;
356		case 3: /* WPS_MSG_ERR */
357			dbg("WPS Fail due to message exange error!\n");
358			break;
359		case 4: /* WPS_TIMEOUT */
360			dbg("WPS Fail due to time out!\n");
361			break;
362		default:
363			ret = 0;
364			break;
365	}
366
367#ifdef RTCONFIG_WPS_DUALBAND
368	if(ret == 1 || ret_qtn == 1){
369		nvram_set("wps_proc_status", "0");
370		return 1;
371	}else{
372		return 0;
373	}
374	// return ret;
375#else
376	return ret;
377#endif
378	// TODO: handle enrollee
379}
380