1/*
2 * Broadcom Home Gateway Reference Design
3 * Broadcom WiFi Insight Webpage functions
4 *
5 * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: vis_gui.c 458674 2014-08-12 11:23:19Z $
19 */
20#ifdef WEBS
21#include <webs.h>
22#include <uemf.h>
23#include <ej.h>
24#else /* !WEBS */
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <ctype.h>
29#include <errno.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <limits.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/socket.h>
36#include <netinet/in.h>
37#include <arpa/inet.h>
38#include <assert.h>
39#include <httpd.h>
40#endif /* WEBS */
41#include <netdb.h>
42
43#include "vis_gui.h"
44#include <proto/ethernet.h>
45#include <bcmnvram.h>
46
47#ifdef __CONFIG_VISUALIZATION__
48
49#include <signal.h>
50
51#define sys_restart() kill(1, SIGHUP)
52
53/* Indicates the level of debug message to be printed on the console */
54static int vis_debug_level = 0;
55
56/* Header to download DB file */
57char g_vis_download_db_hdr[] =
58"Cache-Control: no-cache\r\n"
59"Pragma: no-cache\r\n"
60"Expires: 0\r\n"
61"Content-Type: application/download\r\n"
62"Content-Disposition: attachment ; filename=visdata.db"
63;
64
65#define INVALID_SOCKET			-1
66#define VIS_SOCKET_WAIT_TIMEOUT		15
67#define MAX_READ_BUFFER			1449
68#define VISUALIZATION_SERVER_PORT	8888
69#define VISUALIZATION_SERVER_ADDRESS	"127.0.0.1"
70#define VIS_LEN_FIELD_SZ		4 /* Number of bytes used to specify the length */
71#define VIS_MAX_XML_LEN			1024
72#define VIS_MAX_REQ_LEN			50
73/* MAC address from WEB has %3A for every : character so length as 30 */
74#define VIS_MAX_MAC_LEN			30
75#define VIS_MAX_BAND_LEN		2
76#define VIS_MAX_IP_LEN			16
77
78/* Visualization error printing defines */
79#define VIS_DEBUG_ERROR			0x0001
80#define VIS_DEBUG_WARNING		0x0002
81#define VIS_DEBUG_INFO			0x0004
82#define VIS_DEBUG_DETAIL		0x0008
83
84#define VIS_ERROR(fmt, arg...) \
85		do { if (vis_debug_level & VIS_DEBUG_ERROR) \
86			printf("VIS-ERROR >> %s : "fmt, __FUNCTION__, ##arg); } while (0)
87
88#define VIS_WARNING(fmt, arg...) \
89		do { if (vis_debug_level & VIS_DEBUG_WARNING) \
90			printf("VIS-WARNING >> %s : "fmt, __FUNCTION__, ##arg); } while (0)
91
92#define VIS_INFO(fmt, arg...) \
93		do { if (vis_debug_level & VIS_DEBUG_INFO) \
94			printf("VIS-INFO >> %s : "fmt, __FUNCTION__, ##arg); } while (0)
95
96#define VIS_DEBUG(fmt, arg...) \
97		do { if (vis_debug_level & VIS_DEBUG_DETAIL) \
98			printf("VIS-DEBUG >> %s : "fmt, __FUNCTION__, ##arg); } while (0)
99
100typedef struct vis_xml_strings_t_ {
101	int nallocated;	/* Number bytes allocated */
102	int nlength;	/* Number of bytes filled */
103	char *str;	/* string to hold the xml data */
104} vis_xml_strings_t;
105
106enum vis_enum_req_args {
107	VIS_UNKNOWN,
108	VIS_REQUEST,
109	VIS_DUTMAC,
110	VIS_STAMAC,
111	VIS_FREQBAND,
112	VIS_INTERVAL,
113	VIS_DBSIZE,
114	VIS_STARTSTOP,
115	VIS_TOTAL,
116	VIS_GRAPHNAME,
117	VIS_DCONIP,
118	VIS_ISREMOTE_ENABLE,
119	VIS_DOSCAN,
120	VIS_ISOVERWRITEDB,
121	VIS_ISAUTOSTART,
122	VIS_WEEKDAYS,
123	VIS_FROMTM,
124	VIS_TOTM,
125	};
126
127typedef struct {
128	enum vis_enum_req_args id; /* ID of the request argument */
129	char *req_name; /* Name of the argument */
130} vis_req_args;
131
132vis_req_args vis_req_args_list[] = {
133	{VIS_UNKNOWN, "Unknown"},
134	{VIS_REQUEST, "Req"},
135	{VIS_DUTMAC, "DutMac"},
136	{VIS_STAMAC, "StaMac"},
137	{VIS_FREQBAND, "FreqBand"},
138	{VIS_INTERVAL, "Interval"},
139	{VIS_DBSIZE, "DBSize"},
140	{VIS_STARTSTOP, "StartStop"},
141	{VIS_TOTAL, "Total"},
142	{VIS_GRAPHNAME, "graphname"},
143	{VIS_DCONIP, "DCONIP"},
144	{VIS_ISREMOTE_ENABLE, "IsRemoteDebugEnabled"},
145	{VIS_DOSCAN, "DoScan"},
146	{VIS_ISOVERWRITEDB, "OverWriteDB"},
147	{VIS_ISAUTOSTART, "AutoStart"},
148	{VIS_WEEKDAYS, "WeekDays"},
149	{VIS_FROMTM, "FromTm"},
150	{VIS_TOTM, "ToTm"}
151};
152
153/* This will check whether to reallocate memory for XML buffer or not */
154#define CHECK_XML_BUFF(xml_strings, nlenreq) if (xml_strings->str == NULL ||\
155		(xml_strings->nallocated < (xml_strings->nlength+nlenreq))) {\
156		if (vis_xml_allocate_buffer(xml_strings, nlenreq) != 0)\
157			return; }
158
159static unsigned char *vis_rdata = NULL;
160
161/* Visualization WebUI handling starts here */
162
163/* Closes the socket given the file descriptor */
164static void
165close_socket(int *sockfd)
166{
167	if (*sockfd == INVALID_SOCKET)
168		return;
169
170	close(*sockfd);
171	*sockfd = INVALID_SOCKET;
172}
173
174/* Sends the buffer to server */
175static int
176send_data(int sockfd, char *data, unsigned int len)
177{
178	int	nret = 0;
179	int	totalsize = len, totalsent = 0;
180
181	while (totalsent < totalsize) {
182		fd_set WriteFDs, ExceptFDs;
183		struct timeval tv;
184
185		FD_ZERO(&WriteFDs);
186		FD_ZERO(&ExceptFDs);
187
188		if (sockfd == INVALID_SOCKET)
189			return INVALID_SOCKET;
190
191		FD_SET(sockfd, &WriteFDs);
192
193		tv.tv_sec = VIS_SOCKET_WAIT_TIMEOUT;
194		tv.tv_usec = 0;
195		if (select(sockfd+1, NULL, &WriteFDs, &ExceptFDs, &tv) > 0) {
196			if (!FD_ISSET(sockfd, &WriteFDs)) {
197				VIS_WARNING("Write descriptor is not set. Not ready to write\n");
198				return INVALID_SOCKET;
199			}
200		}
201
202		nret = send(sockfd, &(data[totalsent]), len, 0);
203		if (nret < 0) {
204			VIS_WARNING("Failed to send data error :  %s\n", strerror(errno));
205			return INVALID_SOCKET;
206		}
207		totalsent += nret;
208		len -= nret;
209		nret = 0;
210	}
211
212	return totalsent;
213}
214
215/* Adds the 4 bytes length and then data to a buffer and sends it to
216 * server
217 */
218static int
219add_length_and_send_data(int sockfd, char *data, unsigned int len)
220{
221	int	ret = 0;
222	char	*sdata = NULL;
223	int	totlen = VIS_LEN_FIELD_SZ + len;
224
225	sdata = (char*)malloc(sizeof(char) * (totlen));
226	if (sdata == NULL) {
227		VIS_DEBUG("Failed to allocate sdata buffer of size : %d\n", totlen);
228		return -1;
229	}
230
231	memcpy(sdata, &totlen, VIS_LEN_FIELD_SZ);
232
233	memcpy(sdata+VIS_LEN_FIELD_SZ, data, len);
234
235	ret = send_data(sockfd, sdata, totlen);
236
237	free(sdata);
238
239	return ret;
240}
241
242/* Recieves the 'size' number of data */
243static int
244recv_data(int sockfd, unsigned char *read_buf, uint32 size)
245{
246	uint32		nbytes, totalread = 0;
247	fd_set		ReadFDs, ExceptFDs;
248	struct timeval	tv;
249
250	FD_ZERO(&ReadFDs);
251	FD_ZERO(&ExceptFDs);
252	FD_SET(sockfd, &ReadFDs);
253	FD_SET(sockfd, &ExceptFDs);
254	tv.tv_sec = VIS_SOCKET_WAIT_TIMEOUT;
255	tv.tv_usec = 0;
256
257	while (totalread < size) {
258		if (select(sockfd+1, &ReadFDs, NULL, &ExceptFDs, &tv) > 0) {
259			if (!FD_ISSET(sockfd, &ReadFDs)) {
260				VIS_WARNING("Read descriptor is not set. Not ready to read\n");
261				return INVALID_SOCKET;
262			}
263		}
264		nbytes = read(sockfd, &(read_buf[totalread]), size);
265
266		if (nbytes <= 0) {
267			VIS_WARNING("Failed to read data error : %s\n", strerror(errno));
268			return INVALID_SOCKET;
269		}
270
271		totalread += nbytes;
272	}
273
274	read_buf[totalread] = '\0';
275
276	return totalread;
277}
278
279/* Recieves the data from server
280 * return value contains the number of bytes read or -1 for error
281 * free the buffer after reading the data
282 */
283static int
284on_receive(int sockfd, unsigned char **data)
285{
286	uint32		sz, size = 0;
287	unsigned char	szbuff[VIS_LEN_FIELD_SZ+1] = {0};
288	unsigned char	*read_buf = NULL;
289
290	sz = recv_data(sockfd, szbuff, VIS_LEN_FIELD_SZ);
291	if (sz <= 0) {
292		return INVALID_SOCKET;
293	}
294
295	if (sz >= VIS_LEN_FIELD_SZ) {
296		memcpy(&size, szbuff, sizeof(size));
297	} else {
298		VIS_DEBUG("Failed to receive length field\n");
299		return -1;
300	}
301
302	read_buf = (unsigned char *)malloc(sizeof(unsigned char) * ((size-VIS_LEN_FIELD_SZ) + 1));
303	if (read_buf == NULL) {
304		VIS_DEBUG("Failed to allocate read_buf buffer of size : %d\n",
305			((size-VIS_LEN_FIELD_SZ) + 1));
306		return -1;
307	}
308
309	sz = recv_data(sockfd, read_buf, (size-VIS_LEN_FIELD_SZ));
310	if (sz <= 0) {
311		if (read_buf != NULL) {
312			free(read_buf);
313			read_buf = NULL;
314		}
315		return INVALID_SOCKET;
316	}
317
318	*data = read_buf;
319
320	return sz;
321}
322
323/* Connects to server given the port and address */
324static int
325connect_to_server(uint32 nport, char *straddrs)
326{
327	int			res, valopt, sockfd;
328	long			arg;
329	socklen_t		lon;
330	fd_set			readfds;
331	struct timeval		tv;
332	struct hostent		*host;
333	struct sockaddr_in	server_addr;
334
335	sockfd = INVALID_SOCKET;
336	memset(&server_addr, 0, sizeof(server_addr));
337
338	if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
339		VIS_DEBUG("Failed to create socket error : %s\n", strerror(errno));
340		goto vis_connect_err;
341	}
342
343	if ((host = gethostbyname(straddrs)) == NULL) {
344		VIS_DEBUG("gethostbyname error : %s\n", strerror(errno));
345		goto vis_connect_err;
346	}
347
348	/* Set nonblock on the socket so we can timeout */
349	if ((arg = fcntl(sockfd, F_GETFL, NULL)) < 0 ||
350		fcntl(sockfd, F_SETFL, arg | O_NONBLOCK) < 0) {
351			VIS_DEBUG("fcntl error : %s\n", strerror(errno));
352			goto vis_connect_err;
353	}
354
355	server_addr.sin_family = AF_INET;
356	server_addr.sin_port = htons(nport);
357	server_addr.sin_addr = *((struct in_addr*)host -> h_addr);
358	res = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
359
360	if (res < 0) {
361		if (errno == EINPROGRESS) {
362			tv.tv_sec = 30;
363			tv.tv_usec = 0;
364			FD_ZERO(&readfds);
365			FD_SET(sockfd, &readfds);
366			if (select(sockfd+1, NULL, &readfds, NULL, &tv) > 0) {
367				lon = sizeof(int);
368				getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon);
369				if (valopt) {
370					VIS_DEBUG("Error in connection() %d - %s\n",
371						valopt, strerror(valopt));
372					goto vis_connect_err;
373				}
374			} else {
375				VIS_DEBUG("Timeout or error() %d - %s\n", valopt, strerror(valopt));
376				goto vis_connect_err;
377			}
378		} else {
379			VIS_DEBUG("Error connecting %d - %s\n", errno, strerror(errno));
380			goto vis_connect_err;
381		}
382	}
383
384	return sockfd;
385
386vis_connect_err:
387	close_socket(&sockfd);
388	return INVALID_SOCKET;
389}
390
391/* Sends the XML data to server */
392static int
393send_ui_frontend_data(char *xmldata)
394{
395	int	sockfd = INVALID_SOCKET;
396	int	ret = 0;
397
398	sockfd = connect_to_server(VISUALIZATION_SERVER_PORT, VISUALIZATION_SERVER_ADDRESS);
399	if (sockfd != INVALID_SOCKET) {
400		ret = add_length_and_send_data(sockfd, xmldata, strlen(xmldata));
401		if (ret != INVALID_SOCKET) {
402			vis_rdata = NULL;
403			ret = on_receive(sockfd, &vis_rdata);
404			if (ret <= 0) {
405				VIS_DEBUG("Failed to recieve data\n");
406			}
407		} else {
408			VIS_DEBUG("Failed to send XML data = %s\n", xmldata);
409		}
410	} else {
411		VIS_DEBUG("Failed to Connect to server : %s Port : %d\n",
412			VISUALIZATION_SERVER_ADDRESS, VISUALIZATION_SERVER_PORT);
413	}
414
415	close_socket(&sockfd);
416
417	return ret;
418}
419
420/* Write json answer to stream */
421void
422vis_do_json_get(char *url, FILE *stream)
423{
424	if (vis_rdata != NULL)
425		fputs((const char*)vis_rdata, stream);
426
427	if (vis_rdata != NULL) {
428		free(vis_rdata);
429		vis_rdata = NULL;
430	}
431}
432
433/* Allocates memory for XML data buffer */
434static inline int
435vis_xml_allocate_buffer(vis_xml_strings_t *xml_strings, int nreq)
436{
437	int nallocate = VIS_MAX_XML_LEN;
438
439	if (xml_strings->nallocated > 0) { /* realloc */
440		if ((xml_strings->nallocated + nallocate) < (xml_strings->nlength + nreq + 1))
441			nallocate = xml_strings->nlength + nreq + 1;
442		else
443			nallocate += xml_strings->nallocated;
444		char *tmpptr = (char*)realloc(xml_strings->str, nallocate);
445		if (tmpptr == NULL) {
446			VIS_DEBUG("Memory reallocation failed of : %d for XML buffer\n", nallocate);
447			return -1;
448		}
449		xml_strings->str = tmpptr;
450		xml_strings->nallocated = nallocate;
451	} else {
452		if (nallocate < (nreq+1))
453			nallocate = nreq+1;
454
455		xml_strings->str = (char*)malloc(sizeof(char)*nallocate);
456		if (xml_strings->str == NULL) {
457			VIS_DEBUG("Memory allocation failed of : %d for XML buffer\n", nallocate);
458			return -1;
459		}
460		xml_strings->nallocated = nallocate;
461	}
462
463	return 0;
464}
465
466/* Frees the XML data buffer */
467static inline void
468vis_xml_free_data_buffer(vis_xml_strings_t *xml_strings)
469{
470	if (xml_strings->str) {
471		free(xml_strings->str);
472		xml_strings->str = NULL;
473	}
474}
475
476/* Add only start or end tag */
477static inline void
478vis_xml_add_only_tag(vis_xml_strings_t *xml_strings, char *tag, bool isstarttag)
479{
480	int nlenreq = 0;
481
482	/* total len required for xml tag is 1Tag's + 2open brackets */
483	nlenreq = strlen(tag) + 2 + 1;
484	if (!isstarttag)
485		nlenreq += 1; /* For end tag need / */
486	CHECK_XML_BUFF(xml_strings, nlenreq);
487
488	if (isstarttag) {
489		xml_strings->nlength += snprintf(xml_strings->str+xml_strings->nlength,
490			xml_strings->nallocated-xml_strings->nlength, "<%s>", tag);
491	} else {
492		xml_strings->nlength += snprintf(xml_strings->str+xml_strings->nlength,
493			xml_strings->nallocated-xml_strings->nlength, "</%s>", tag);
494	}
495}
496
497/* Add only the value into tag */
498static inline void
499vis_xml_add_only_value(vis_xml_strings_t *xml_strings, char *value)
500{
501	int nlenreq = 0;
502
503	/* total len required for xml tag is 1Tag's + 2open brackets */
504	nlenreq = strlen(value) + 1;
505	CHECK_XML_BUFF(xml_strings, nlenreq);
506
507	xml_strings->nlength += snprintf(xml_strings->str+xml_strings->nlength,
508		xml_strings->nallocated-xml_strings->nlength, "%s", value);
509}
510
511/* Adds TAG and Value pair to the xml data buffer */
512static inline void
513vis_xml_add_tag_value(vis_xml_strings_t *xml_strings, char *tag, char *value)
514{
515	int nlenreq = 0;
516
517	/* total len required for one xml tag is
518	 * 2Tag's + 2open brackets + 2closing brackets + one slash + one value
519	 */
520	nlenreq = (2 * strlen(tag)) + 5 + strlen(value) + 1;
521	CHECK_XML_BUFF(xml_strings, nlenreq);
522
523	xml_strings->nlength += snprintf(xml_strings->str+xml_strings->nlength,
524		xml_strings->nallocated-xml_strings->nlength, "<%s>%s</%s>",
525		tag, value, tag);
526}
527
528/* Adds TAG and attribute to the xml data buffer */
529static inline void
530vis_xml_add_tag_and_attribute(vis_xml_strings_t *xml_strings, char *tag,
531	char *attribname, char *attribvalue)
532{
533	int nlenreq = 0;
534
535	/* total len required for one xml tag is
536	 * 1Tag's + 2 brackets
537	 * + one space + one attribute name + one attribute value + one =
538	 */
539	nlenreq = strlen(tag) + 4 + strlen(attribname) + strlen(attribvalue) + 1;
540	CHECK_XML_BUFF(xml_strings, nlenreq);
541
542	xml_strings->nlength += snprintf(xml_strings->str+xml_strings->nlength,
543		xml_strings->nallocated-xml_strings->nlength, "<%s %s=%s>",
544		tag, attribname, attribvalue);
545}
546
547/* Read query from stream in json format treate it and create answer string
548 * The query is a list of commands and treated by 'do_json_command'
549 */
550static void
551create_xml_string(const char *querystring, vis_xml_strings_t *xmlstring)
552{
553	char *pch;
554	char request[VIS_MAX_REQ_LEN] = {0};
555	char dutmac[VIS_MAX_MAC_LEN] = {0};
556	char stamac[VIS_MAX_MAC_LEN] = {0};
557	char band[VIS_MAX_BAND_LEN] = {0};
558	char dcon_ip[VIS_MAX_IP_LEN] = {0};
559	int isenabled = 0;
560	static int donvramread = 1;
561	vis_xml_strings_t configxml = {0};
562	vis_xml_strings_t graphxml = {0};
563	vis_xml_strings_t dutset = {0};
564	vis_xml_strings_t pkthdr = {0};
565
566	/* Read NVRAM variable for debug print. Read only once, that is why checking for 1
567	 * From next time onwards default value 0 will be set to static var
568	 */
569	if (donvramread == 1) {
570		char *tmpdebugflag = nvram_get("vis_debug_level");
571		if (tmpdebugflag)
572			vis_debug_level = strtoul(tmpdebugflag, NULL, 0);
573		donvramread = 0;
574	}
575
576	VIS_DEBUG("Request : %s\n", querystring);
577
578	vis_xml_add_tag_and_attribute(&pkthdr, "PacketVersion", "Name", "\"1\"");
579	vis_xml_add_only_tag(&pkthdr, "PacketHeader", TRUE); /* Open packet header tag */
580	vis_xml_add_tag_value(&pkthdr, "PacketType", "1");
581	vis_xml_add_tag_value(&pkthdr, "From", "2");
582
583	vis_xml_add_only_tag(&configxml, "Config", TRUE); /* Open Config tag */
584	vis_xml_add_only_tag(&graphxml, "EnabledGraphs", TRUE); /* Open enabled graphs tag */
585
586	pch = strtok((char*)querystring, "?=&");
587	while (pch != NULL) {
588		int i;
589		enum vis_enum_req_args id = VIS_UNKNOWN;
590
591		for (i = 0; i < (sizeof(vis_req_args_list)/sizeof(vis_req_args)); i++) {
592			if (strstr(pch, vis_req_args_list[i].req_name) != NULL) {
593				pch = strtok(NULL, "?=&");
594				if (pch == NULL)
595					break;
596				id = vis_req_args_list[i].id;
597				break;
598			}
599		}
600		switch (id) {
601			case VIS_REQUEST: /* Get the request name */
602				snprintf(request, sizeof(request), "%s", pch);
603				vis_xml_add_tag_value(&pkthdr, "ReqRespType", request);
604				break;
605			case VIS_DUTMAC: /* Get the DUTMAC */
606				snprintf(dutmac, sizeof(dutmac), "%s", pch);
607				break;
608			case VIS_STAMAC: /* Get the STAMAC */
609				snprintf(stamac, sizeof(stamac), "%s", pch);
610				break;
611			case VIS_FREQBAND: /* Get the FreqBand */
612				snprintf(band, sizeof(band), "%s", pch);
613				vis_xml_add_tag_value(&pkthdr, "FreqBand", band);
614				break;
615			case VIS_INTERVAL: /* Get Interval for config settings */
616				vis_xml_add_tag_value(&configxml, "SampleInterval", pch);
617				break;
618			case VIS_DBSIZE: /* Get Max database size for config settings */
619				vis_xml_add_tag_value(&configxml, "dbsize", pch);
620				break;
621			case VIS_STARTSTOP: /* Tells to stop or start the data collection */
622				vis_xml_add_tag_value(&configxml, "startstop", pch);
623				break;
624			case VIS_TOTAL: /* Get total graph names for config settings */
625				vis_xml_add_tag_value(&graphxml, "Total", pch);
626				break;
627			case VIS_GRAPHNAME: /* Get graphname for config settings */
628				vis_xml_add_tag_value(&graphxml, "graphname", pch);
629				break;
630			case VIS_DCONIP: /* Server IP for remote debug */
631				snprintf(dcon_ip, sizeof(dcon_ip), "%s", pch);
632				break;
633			case VIS_ISREMOTE_ENABLE: /* Flag for remote debugging enabled */
634				isenabled = atoi(pch);
635				break;
636			case VIS_DOSCAN: /* Flag for DO scan flag */
637				vis_xml_add_only_tag(&dutset, "DUTSet", TRUE);
638				vis_xml_add_tag_value(&dutset, "DoScan", pch);
639				vis_xml_add_only_tag(&dutset, "DUTSet", FALSE);
640				break;
641			case VIS_ISOVERWRITEDB: /* Get Overwrite DB flag for config settings */
642				vis_xml_add_tag_value(&configxml, "overwrtdb", pch);
643				break;
644			case VIS_ISAUTOSTART: /* Get Is Auto Start flag for config settings */
645				vis_xml_add_tag_value(&configxml, "autost", pch);
646				break;
647			case VIS_WEEKDAYS: /* Get Weekdays for config settings */
648				vis_xml_add_tag_value(&configxml, "wkdays", pch);
649				break;
650			case VIS_FROMTM: /* Get From Time for config settings */
651				vis_xml_add_tag_value(&configxml, "frmtm", pch);
652				break;
653			case VIS_TOTM: /* Get To Time for config settings */
654				vis_xml_add_tag_value(&configxml, "totm", pch);
655				break;
656			case VIS_UNKNOWN:
657				break;
658		}
659		pch = strtok(NULL, "?=&");
660	}
661
662	if (strcmp(request, "RemoteSettings") == 0) {
663		char *tmpdcon_ip = nvram_get("vis_dcon_ipaddr");
664		if (tmpdcon_ip == NULL)
665			goto vis_fun_end;
666		char *value = nvram_get("vis_do_remote_dcon");
667		if (value)
668			isenabled = atoi(value);
669		vis_rdata = (unsigned char*)malloc(sizeof(char) * MAX_READ_BUFFER);
670		memset(vis_rdata, 0, MAX_READ_BUFFER);
671		snprintf(vis_rdata, MAX_READ_BUFFER, "{\"IsEnabled\":%d,\"ServerIP\":\"%s\"}",
672			isenabled, tmpdcon_ip);
673		goto vis_fun_end;
674	} else if (strcmp(request, "SetRemoteDebug") == 0) {
675		char tmpbuf[5] = {0};
676
677		nvram_set("vis_dcon_ipaddr", dcon_ip);
678		snprintf(tmpbuf, sizeof(tmpbuf), "%d", isenabled);
679		nvram_set("vis_do_remote_dcon", tmpbuf);
680		nvram_commit();
681		sys_restart();
682		goto vis_fun_end;
683	}
684	vis_xml_add_only_tag(&graphxml, "EnabledGraphs", FALSE); /* Close EnabledGraphs Tag */
685	vis_xml_add_only_value(&configxml, graphxml.str);
686	vis_xml_add_only_tag(&configxml, "Config", FALSE); /* Close Config Tag */
687	vis_xml_add_only_tag(&pkthdr, "PacketHeader", FALSE); /* Close Packet Header Tag */
688
689	vis_xml_add_only_tag(xmlstring, "?xml version=\"1.0\" encoding=\"utf-8\"?", TRUE);
690	vis_xml_add_only_value(&pkthdr, configxml.str);
691	vis_xml_add_only_tag(&pkthdr, "DUT", TRUE); /* Open DUT tag */
692	vis_xml_add_tag_value(&pkthdr, "MAC", dutmac);
693	vis_xml_add_tag_value(&pkthdr, "STAMAC", stamac);
694	vis_xml_add_only_tag(&pkthdr, "DUT", FALSE); /* Close DUT Tag */
695	if (dutset.str)
696		vis_xml_add_only_value(&pkthdr, dutset.str);
697	vis_xml_add_only_tag(&pkthdr, "PacketVersion", FALSE); /* Clsoe PacketVersion Tag */
698	vis_xml_add_only_value(xmlstring, pkthdr.str);
699
700vis_fun_end:
701	/* Free the XML data buffers */
702	vis_xml_free_data_buffer(&configxml);
703	vis_xml_free_data_buffer(&graphxml);
704	vis_xml_free_data_buffer(&dutset);
705	vis_xml_free_data_buffer(&pkthdr);
706}
707
708/* Read query from stream in json format treate it and create answer string
709 * The query is a list of commands and treated by 'do_json_command'
710 */
711void
712vis_do_json_set(const char *url, FILE *stream, int len, const char *boundary)
713{
714	vis_xml_strings_t xmlstring = {0};
715
716	/* create the xml string out of the query string */
717	create_xml_string(url, &xmlstring);
718
719	/* send this xml string to the backend via socket */
720	if (xmlstring.str != NULL) {
721		send_ui_frontend_data(xmlstring.str);
722		vis_xml_free_data_buffer(&xmlstring);
723	}
724}
725
726/*
727 * Create XML and send it to dcon to get the DB file and
728 * then send it to Web UI
729 */
730void
731vis_do_visdbdwnld_cgi(char *url, FILE *stream)
732{
733	vis_xml_strings_t xmlstring = {0};
734	char tmpurl[] = "json.cgi?Req=GetDBFile";
735	int ret = 0;
736
737	/* create the xml string out of the query string */
738	create_xml_string(tmpurl, &xmlstring);
739	if (xmlstring.str != NULL) {
740		ret = send_ui_frontend_data(xmlstring.str);
741		if ((ret > 0) && (vis_rdata != NULL))
742			fwrite(vis_rdata, ret, 1, stream);
743
744		if (vis_rdata != NULL) {
745			free(vis_rdata);
746			vis_rdata = NULL;
747		}
748		vis_xml_free_data_buffer(&xmlstring);
749	}
750
751	websDone(stream, 200);
752}
753
754#endif /* __CONFIG_VISUALIZATION__ */
755