1/*
2
3	Tomato Firmware
4	Copyright (C) 2006-2009 Jonathan Zarate
5
6*/
7#include <string.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <unistd.h>
11#include <fcntl.h>
12#include <sys/stat.h>
13#include <stdarg.h>
14#include <syslog.h>
15#include <sys/ioctl.h>
16#include <net/if.h>
17#include <sys/socket.h>
18#include <arpa/inet.h>
19#include <ifaddrs.h>
20#include <sys/sysinfo.h>
21#include <sys/types.h>
22#include <sys/wait.h>
23#include <dirent.h>
24#include <ctype.h>
25#include <sys/socket.h>
26#include <netdb.h>
27
28#include <bcmnvram.h>
29#include <bcmdevs.h>
30#include <wlutils.h>
31
32#include "shutils.h"
33#include "shared.h"
34
35#ifndef ETHER_ADDR_LEN
36#define	ETHER_ADDR_LEN		6
37#endif
38
39extern char *read_whole_file(const char *target){
40	FILE *fp;
41	char *buffer, *new_str;
42	int i;
43	unsigned int read_bytes = 0;
44	unsigned int each_size = 1024;
45
46	if((fp = fopen(target, "r")) == NULL)
47		return NULL;
48
49	buffer = (char *)malloc(sizeof(char)*each_size);
50	if(buffer == NULL){
51		_dprintf("No memory \"buffer\".\n");
52		fclose(fp);
53		return NULL;
54	}
55	memset(buffer, 0, each_size);
56
57	while ((i = fread(buffer+read_bytes, each_size * sizeof(char), 1, fp)) == 1){
58		read_bytes += each_size;
59		new_str = (char *)malloc(sizeof(char)*(each_size+read_bytes));
60		if(new_str == NULL){
61			_dprintf("No memory \"new_str\".\n");
62			free(buffer);
63			fclose(fp);
64			return NULL;
65		}
66		memset(new_str, 0, sizeof(char)*(each_size+read_bytes));
67		memcpy(new_str, buffer, read_bytes);
68
69		free(buffer);
70		buffer = new_str;
71	}
72
73	fclose(fp);
74	return buffer;
75}
76
77extern char *get_line_from_buffer(const char *buf, char *line, const int line_size){
78	int buf_len, len;
79	char *ptr;
80
81	if(buf == NULL || (buf_len = strlen(buf)) <= 0)
82		return NULL;
83
84	if((ptr = strchr(buf, '\n')) == NULL)
85		ptr = (char *)(buf+buf_len);
86
87	if((len = ptr-buf) < 0)
88		len = buf-ptr;
89	++len; // include '\n'.
90
91	memset(line, 0, line_size);
92	strncpy(line, buf, len);
93
94	return line;
95}
96
97extern char *get_upper_str(const char *const str, char **target){
98	int len, i;
99	char *ptr;
100
101	len = strlen(str);
102	*target = (char *)malloc(sizeof(char)*(len+1));
103	if(*target == NULL){
104		_dprintf("No memory \"*target\".\n");
105		return NULL;
106	}
107	ptr = *target;
108	for(i = 0; i < len; ++i)
109		ptr[i] = toupper(str[i]);
110	ptr[len] = 0;
111
112	return ptr;
113}
114
115extern int upper_strcmp(const char *const str1, const char *const str2){
116	char *upper_str1, *upper_str2;
117	int ret;
118
119	if(str1 == NULL || str2 == NULL)
120		return -1;
121
122	if(get_upper_str(str1, &upper_str1) == NULL)
123		return -1;
124
125	if(get_upper_str(str2, &upper_str2) == NULL){
126		free(upper_str1);
127		return -1;
128	}
129
130	ret = strcmp(upper_str1, upper_str2);
131	free(upper_str1);
132	free(upper_str2);
133
134	return ret;
135}
136
137extern int upper_strncmp(const char *const str1, const char *const str2, int count){
138	char *upper_str1, *upper_str2;
139	int ret;
140
141	if(str1 == NULL || str2 == NULL)
142		return -1;
143
144	if(get_upper_str(str1, &upper_str1) == NULL)
145		return -1;
146
147	if(get_upper_str(str2, &upper_str2) == NULL){
148		free(upper_str1);
149		return -1;
150	}
151
152	ret = strncmp(upper_str1, upper_str2, count);
153	free(upper_str1);
154	free(upper_str2);
155
156	return ret;
157}
158
159extern char *upper_strstr(const char *const str, const char *const target){
160	char *upper_str, *upper_target;
161	char *ret;
162	int len;
163
164	if(str == NULL || target == NULL)
165		return NULL;
166
167	if(get_upper_str(str, &upper_str) == NULL)
168		return NULL;
169
170	if(get_upper_str(target, &upper_target) == NULL){
171		free(upper_str);
172		return NULL;
173	}
174
175	ret = strstr(upper_str, upper_target);
176	if(ret == NULL){
177		free(upper_str);
178		free(upper_target);
179		return NULL;
180	}
181
182	if((len = upper_str-ret) < 0)
183		len = ret-upper_str;
184
185	free(upper_str);
186	free(upper_target);
187
188	return (char *)(str+len);
189}
190
191#ifdef RTCONFIG_IPV6
192char *ipv6_nvname_by_unit(const char *name, int unit)
193{
194	static char name_ipv6[128];
195
196	if (strncmp(name, "ipv6_", sizeof("ipv6_") - 1) != 0) {
197		_dprintf("Wrong ipv6 nvram namespace: \"%s\"\n", name);
198		return (char *)name;
199	}
200
201	if (unit == 0)
202		return (char *)name;
203
204	snprintf(name_ipv6, sizeof(name_ipv6), "ipv6%d_%s", unit, name + sizeof("ipv6_") - 1);
205
206	return name_ipv6;
207}
208
209char *ipv6_nvname(const char *name)
210{
211	return ipv6_nvname_by_unit(name, wan_primary_ifunit());
212}
213
214int get_ipv6_service_by_unit(int unit)
215{
216	static const struct {
217		char *name;
218		int service;
219	} services[] = {
220		{ "dhcp6",	IPV6_NATIVE_DHCP },
221#ifdef RTCONFIG_6RELAYD
222		{ "ipv6pt",     IPV6_PASSTHROUGH },
223#endif
224		{ "6to4",	IPV6_6TO4 },
225		{ "6in4",	IPV6_6IN4 },
226		{ "6rd",	IPV6_6RD },
227		{ "other",	IPV6_MANUAL },
228		{ "static6",	IPV6_MANUAL }, /* legacy */
229		{ NULL }
230	};
231	char *value;
232	int i;
233
234	value = nvram_safe_get(ipv6_nvname_by_unit("ipv6_service", unit));
235	for (i = 0; services[i].name; i++) {
236		if (strcmp(value, services[i].name) == 0)
237			return services[i].service;
238	}
239	return IPV6_DISABLED;
240}
241
242int get_ipv6_service(void)
243{
244	return get_ipv6_service_by_unit(wan_primary_ifunit());
245}
246
247const char *ipv6_router_address(struct in6_addr *in6addr)
248{
249	char *p;
250	struct in6_addr addr;
251	static char addr6[INET6_ADDRSTRLEN];
252
253	addr6[0] = '\0';
254	memset(&addr, 0, sizeof(addr));
255
256	if ((p = nvram_get(ipv6_nvname("ipv6_rtr_addr"))) && *p) {
257		inet_pton(AF_INET6, p, &addr);
258	} else if ((p = nvram_get(ipv6_nvname("ipv6_prefix"))) && *p) {
259		inet_pton(AF_INET6, p, &addr);
260		addr.s6_addr16[7] = htons(0x0001);
261	} else
262		return addr6;
263
264	inet_ntop(AF_INET6, &addr, addr6, sizeof(addr6));
265	if (in6addr)
266		memcpy(in6addr, &addr, sizeof(addr));
267
268	return addr6;
269}
270
271// trim useless 0 from IPv6 address
272const char *ipv6_address(const char *ipaddr6)
273{
274	struct in6_addr addr;
275	static char addr6[INET6_ADDRSTRLEN];
276
277	addr6[0] = '\0';
278
279	if (inet_pton(AF_INET6, ipaddr6, &addr) > 0)
280		inet_ntop(AF_INET6, &addr, addr6, sizeof(addr6));
281
282	return addr6;
283}
284
285// extract prefix from configured IPv6 address
286const char *ipv6_prefix(struct in6_addr *in6addr)
287{
288	static char prefix[INET6_ADDRSTRLEN];
289	struct in6_addr addr;
290	int i, r;
291
292	prefix[0] = '\0';
293	memset(&addr, 0, sizeof(addr));
294
295	if (inet_pton(AF_INET6, nvram_safe_get(ipv6_nvname("ipv6_rtr_addr")), &addr) > 0) {
296		r = nvram_get_int(ipv6_nvname("ipv6_prefix_length")) ? : 64;
297		for (r = 128 - r, i = 15; r > 0; r -= 8) {
298			if (r >= 8)
299				addr.s6_addr[i--] = 0;
300			else
301				addr.s6_addr[i--] &= (0xff << r);
302		}
303		inet_ntop(AF_INET6, &addr, prefix, sizeof(prefix));
304	}
305
306	if (in6addr)
307		memcpy(in6addr, &addr, sizeof(addr));
308
309	return prefix;
310}
311
312#if 0 /* unused */
313const char *ipv6_prefix(const char *ifname)
314{
315	return getifaddr(ifname, AF_INET6, GIF_PREFIX) ? : "";
316}
317
318int ipv6_prefix_len(const char *ifname)
319{
320	const char *value;
321
322	value = getifaddr(ifname, AF_INET6, /*GIF_PREFIX |*/ GIF_PREFIXLEN);
323	if (value == NULL)
324		return 0;
325
326	value = strchr(value, '/');
327	if (value)
328		return atoi(value + 1);
329
330	return 128;
331}
332#endif
333
334void reset_ipv6_linklocal_addr(const char *ifname, int flush)
335{
336	static char buf[INET6_ADDRSTRLEN];
337	struct in6_addr addr;
338	struct ifreq ifr;
339	char *mac;
340	int fd;
341
342	if (!ifname ||
343	    !strcmp(ifname, "lo") || !strncmp(ifname, "ppp", 3))
344		return;
345
346	if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
347		return;
348
349	memset(&ifr, 0, sizeof(ifr));
350	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
351	mac = (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) ?
352		NULL : ifr.ifr_hwaddr.sa_data;
353	close(fd);
354
355	if (mac == NULL)
356		return;
357
358	addr.s6_addr32[0] = htonl(0xfe800000);
359	addr.s6_addr32[1] = 0;
360	memcpy(&addr.s6_addr[8], mac, 3);
361	memcpy(&addr.s6_addr[13], mac + 3, 3);
362	addr.s6_addr[8] ^= 0x02;
363	addr.s6_addr[11] = 0xff;
364	addr.s6_addr[12] = 0xfe;
365
366	if (flush)
367		eval("ip", "-6", "addr", "flush", "dev", (char *) ifname);
368	if (inet_ntop(AF_INET6, &addr, buf, sizeof(buf)))
369		eval("ip", "-6", "addr", "add", buf, "dev", (char *) ifname);
370}
371
372int with_ipv6_linklocal_addr(const char *ifname)
373{
374	return (getifaddr(ifname, AF_INET6, GIF_LINKLOCAL) != NULL);
375}
376
377static int ipv6_expand(char *buf, char *str, struct in6_addr *addr)
378{
379	char *dst = buf;
380	char *src = str;
381	int i;
382
383	for (i = 1; dst < src && *src; i++) {
384		*dst++ = *src++;
385		if (i % 4 == 0) *dst++ = ':';
386	}
387	return inet_pton(AF_INET6, buf, addr);
388}
389
390const char *ipv6_gateway_address(void)
391{
392	static char buf[INET6_ADDRSTRLEN] = "";
393	FILE *fp;
394	struct in6_addr addr;
395	char dest[41], nexthop[41], dev[17];
396	int mask, prefix, metric, flags;
397	int maxprefix, minmetric = minmetric;
398
399	fp = fopen("/proc/net/ipv6_route", "r");
400	if (fp == NULL) {
401		perror("/proc/net/ipv6_route");
402		return NULL;
403	}
404
405	maxprefix = -1;
406	while (fscanf(fp, "%32s%x%*s%*x%32s%x%*x%*x%x%16s\n",
407		      &dest[7], &prefix, &nexthop[7], &metric, &flags, dev) == 6) {
408		/* Skip interfaces that are down and host routes */
409		if ((flags & (RTF_UP | RTF_HOST)) != RTF_UP)
410			continue;
411
412		/* Skip dst not in "::/0 - 2000::/3" */
413		if (prefix > 3)
414			continue;
415		if (ipv6_expand(dest, &dest[7], &addr) <= 0)
416			continue;
417		mask = htons((0xffff0000 >> prefix) & 0xffff);
418		if ((addr.s6_addr16[0] & mask) != (htons(0x2000) & mask))
419			continue;
420
421		/* Skip dups & worse routes */
422		if ((maxprefix > prefix) ||
423		    (maxprefix == prefix && minmetric <= metric))
424			continue;
425
426		if (flags & RTF_GATEWAY) {
427			if (ipv6_expand(nexthop, &nexthop[7], &addr) <= 0)
428				continue;
429			inet_ntop(AF_INET6, &addr, buf, sizeof(buf));
430		} else
431			snprintf(buf, sizeof(buf), "::");
432		maxprefix = prefix;
433		minmetric = metric;
434
435		if (prefix == 0)
436			break;
437	}
438	fclose(fp);
439
440	return *buf ? buf : NULL;
441}
442#endif
443
444int wl_client(int unit, int subunit)
445{
446	char *mode = nvram_safe_get(wl_nvname("mode", unit, subunit));
447
448	return ((strcmp(mode, "sta") == 0) || (strcmp(mode, "wet") == 0));
449}
450
451int foreach_wif(int include_vifs, void *param,
452	int (*func)(int idx, int unit, int subunit, void *param))
453{
454	char ifnames[256];
455	char name[64], ifname[64], *next = NULL;
456	int unit = -1, subunit = -1;
457	int i;
458	int ret = 0;
459
460	snprintf(ifnames, sizeof(ifnames), "%s %s",
461		 nvram_safe_get("lan_ifnames"), nvram_safe_get("wan_ifnames"));
462	remove_dups(ifnames, sizeof(ifnames));
463
464	i = 0;
465	foreach(name, ifnames, next) {
466		if (nvifname_to_osifname(name, ifname, sizeof(ifname)) != 0)
467			continue;
468
469#ifdef CONFIG_BCMWL5
470		if (wl_probe(ifname) || wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit)))
471			continue;
472#endif
473
474		// Convert eth name to wl name
475		if (osifname_to_nvifname(name, ifname, sizeof(ifname)) != 0)
476			continue;
477
478#ifdef CONFIG_BCMWL5
479		// Slave intefaces have a '.' in the name
480		if (strchr(ifname, '.') && !include_vifs)
481			continue;
482#endif
483
484		if (get_ifname_unit(ifname, &unit, &subunit) < 0)
485			continue;
486
487		ret |= func(i++, unit, subunit, param);
488	}
489	return ret;
490}
491
492void notice_set(const char *path, const char *format, ...)
493{
494	char p[256];
495	char buf[2048];
496	va_list args;
497
498	va_start(args, format);
499	vsnprintf(buf, sizeof(buf), format, args);
500	va_end(args);
501
502	mkdir("/var/notice", 0755);
503	snprintf(p, sizeof(p), "/var/notice/%s", path);
504	f_write_string(p, buf, 0, 0);
505	if (buf[0]) syslog(LOG_INFO, "notice[%s]: %s", path, buf);
506}
507
508
509//	#define _x_dprintf(args...)	syslog(LOG_DEBUG, args);
510#define _x_dprintf(args...)	do { } while (0);
511
512// -----------------------------------------------------------------------------
513#define ACT_COMM_LEN	20
514struct action_s {
515	char comm[ACT_COMM_LEN];
516	pid_t pid;
517	int action;
518};
519
520void set_action(int a)
521{
522	int r = 3;
523	struct action_s act;
524	char *s, *p, stat[sizeof("/proc/XXXXXX/statXXXXXX")];
525
526	act.action = a;
527	act.pid = getpid();
528	snprintf(stat, sizeof(stat), "/proc/%d/stat", act.pid);
529	s = file2str(stat);
530	if (s) {
531		if ((p = strrchr(s, ')')) != NULL)
532			*p = '\0';
533		if ((p = strchr(s, '(')) != NULL)
534			snprintf(act.comm, sizeof(act.comm), "%s", ++p);
535		free(s);
536		s = (p && *act.comm) ? act.comm : NULL;
537	}
538	if (!s)
539		snprintf(act.comm, sizeof(act.comm), "%d <UNKNOWN>", act.pid);
540	_dprintf("%d: set_action %d\n", getpid(), act.action);
541	while (f_write_excl(ACTION_LOCK, &act, sizeof(act), 0, 0600) != sizeof(act)) {
542		sleep(1);
543		if (--r == 0) return;
544	}
545	if (a != ACT_IDLE) sleep(2);
546}
547
548static int __check_action(struct action_s *pa)
549{
550	int r = 3;
551	struct action_s act;
552
553	while (f_read_excl(ACTION_LOCK, &act, sizeof(act)) != sizeof(act)) {
554		sleep(1);
555		if (--r == 0) return ACT_UNKNOWN;
556	}
557	if (pa)
558		*pa = act;
559	_dprintf("%d: check_action %d\n", getpid(), act.action);
560
561	return act.action;
562}
563
564int check_action(void)
565{
566	return __check_action(NULL);
567}
568
569int wait_action_idle(int n)
570{
571	int r;
572	struct action_s act;
573
574	while (n-- > 0) {
575		act.pid = 0;
576		if (__check_action(&act) == ACT_IDLE) return 1;
577		if (act.pid > 0 && !process_exists(act.pid)) {
578			if (!(r = unlink(ACTION_LOCK)) || errno == ENOENT) {
579				_dprintf("Terminated process, pid %d %s, hold action lock %d !!!\n",
580					act.pid, act.comm, act.action);
581				return 1;
582			}
583			_dprintf("Remove " ACTION_LOCK " failed. errno %d (%s)\n", errno, strerror(errno));
584		}
585		sleep(1);
586	}
587	_dprintf("pid %d %s hold action lock %d !!!\n", act.pid, act.comm, act.action);
588	return 0;
589}
590
591const char *get_wanip(void)
592{
593	char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")];
594
595	snprintf(prefix, sizeof(prefix), "wan%d_", wan_primary_ifunit());
596
597	return nvram_safe_get(strcat_r(prefix, "ipaddr", tmp));
598}
599
600int get_wanstate(void)
601{
602	char tmp[100], prefix[sizeof("wanXXXXXXXXXX_")];
603
604	snprintf(prefix, sizeof(prefix), "wan%d_", wan_primary_ifunit());
605
606	return nvram_get_int(strcat_r(prefix, "state_t", tmp));
607}
608
609const char *get_wanface(void)
610{
611	return get_wan_ifname(wan_primary_ifunit());
612}
613
614#ifdef RTCONFIG_IPV6
615const char *get_wan6face(void)
616{
617	switch (get_ipv6_service()) {
618	case IPV6_NATIVE_DHCP:
619#ifdef RTCONFIG_6RELAYD
620	case IPV6_PASSTHROUGH:
621#endif
622	case IPV6_MANUAL:
623		return get_wanface();
624	case IPV6_6TO4:
625		return "v6to4";
626	case IPV6_6IN4:
627		return "v6in4";
628	case IPV6_6RD:
629		return "6rd";
630	}
631	return "";
632}
633
634int update_6rd_info(void)
635{
636	char tmp[100], prefix[]="wanXXXXX_";
637	char addr6[INET6_ADDRSTRLEN + 1], *value;
638	struct in6_addr addr;
639
640	if (get_ipv6_service() != IPV6_6RD || !nvram_get_int(ipv6_nvname("ipv6_6rd_dhcp")))
641		return -1;
642
643	snprintf(prefix, sizeof(prefix), "wan%d_", wan_primary_ifunit());
644
645	value = nvram_safe_get(strcat_r(prefix, "6rd_prefix", tmp));
646	if (*value ) {
647		/* try to compact IPv6 prefix */
648		if (inet_pton(AF_INET6, value, &addr) > 0)
649			value = (char *) inet_ntop(AF_INET6, &addr, addr6, sizeof(addr6));
650		nvram_set(ipv6_nvname("ipv6_6rd_prefix"), value);
651		nvram_set(ipv6_nvname("ipv6_6rd_router"), nvram_safe_get(strcat_r(prefix, "6rd_router", tmp)));
652		nvram_set(ipv6_nvname("ipv6_6rd_prefixlen"), nvram_safe_get(strcat_r(prefix, "6rd_prefixlen", tmp)));
653		nvram_set(ipv6_nvname("ipv6_6rd_ip4size"), nvram_safe_get(strcat_r(prefix, "6rd_ip4size", tmp)));
654		return 1;
655	}
656
657	return 0;
658}
659#endif
660
661const char *_getifaddr(const char *ifname, int family, int flags, char *buf, int size)
662{
663	struct ifaddrs *ifap, *ifa;
664	union {
665#ifdef RTCONFIG_IPV6
666		struct in6_addr in6;
667#endif
668		struct in_addr in;
669	} addrbuf;
670	unsigned char *addr, *netmask, *paddr, *pnetmask;
671	unsigned char len, maxlen;
672
673	if (getifaddrs(&ifap) != 0) {
674		_dprintf("getifaddrs failed: %s\n", strerror(errno));
675		return NULL;
676	}
677
678	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
679		if (ifa->ifa_addr == NULL ||
680		    ifa->ifa_addr->sa_family != family ||
681		    strncmp(ifa->ifa_name, ifname, IFNAMSIZ) != 0)
682			continue;
683
684		switch (ifa->ifa_addr->sa_family) {
685#ifdef RTCONFIG_IPV6
686		case AF_INET6:
687			addr = (void *) &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr;
688			if (IN6_IS_ADDR_LINKLOCAL(addr) ^ !!(flags & GIF_LINKLOCAL))
689				continue;
690			netmask = (void *) &((struct sockaddr_in6 *) ifa->ifa_netmask)->sin6_addr;
691			maxlen = sizeof(struct in6_addr) * 8;
692			break;
693#endif
694		case AF_INET:
695			addr = (void *) &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
696			netmask = (void *) &((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr;
697			maxlen = sizeof(struct in_addr) * 8;
698			break;
699		default:
700			continue;
701		}
702
703		if ((flags & GIF_PREFIX) && addr && netmask) {
704			paddr = addr = memcpy(&addrbuf, addr, maxlen / 8);
705			pnetmask = netmask;
706			for (len = 0; len < maxlen; len += 8)
707				*paddr++ &= *pnetmask++;
708		}
709
710		if (addr && inet_ntop(ifa->ifa_addr->sa_family, addr, buf, size) != NULL) {
711			if ((flags & GIF_PREFIXLEN) && netmask) {
712				for (len = 0; len < maxlen && *netmask == 0xff; len += 8)
713					netmask++;
714				if (len < maxlen && *netmask) {
715					switch (*netmask) {
716					case 0xfe: len += 7; break;
717					case 0xfc: len += 6; break;
718					case 0xf8: len += 5; break;
719					case 0xf0: len += 4; break;
720					case 0xe0: len += 3; break;
721					case 0xc0: len += 2; break;
722					case 0x80: len += 1; break;
723					default:
724						_dprintf("getifaddrs netmask error: %x\n", *netmask);
725						goto error;
726					}
727				}
728				if (len < maxlen) {
729					netmask = memchr(buf, 0, size);
730					if (netmask)
731						snprintf(netmask, size - ((char *) netmask - buf), "/%d", len);
732				}
733			}
734			freeifaddrs(ifap);
735			return buf;
736		}
737	}
738
739error:
740	freeifaddrs(ifap);
741	return NULL;
742}
743
744const char *getifaddr(const char *ifname, int family, int flags)
745{
746	static char buf[INET6_ADDRSTRLEN];
747
748	return _getifaddr(ifname, family, flags, buf, sizeof(buf));
749}
750
751int is_intf_up(const char* ifname)
752{
753	struct ifreq ifr;
754	int sfd;
755	int ret = 0;
756
757	if (!((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0))
758	{
759		strcpy(ifr.ifr_name, ifname);
760		if (!ioctl(sfd, SIOCGIFFLAGS, &ifr) && (ifr.ifr_flags & IFF_UP))
761			ret = 1;
762
763		close(sfd);
764	}
765
766	return ret;
767}
768
769char *wl_nvname(const char *nv, int unit, int subunit)
770{
771	static char tmp[128];
772	char prefix[] = "wlXXXXXXXXXX_";
773
774	if (unit < 0)
775		strcpy(prefix, "wl_");
776	else if (subunit > 0)
777		snprintf(prefix, sizeof(prefix), "wl%d.%d_", unit, subunit);
778	else
779		snprintf(prefix, sizeof(prefix), "wl%d_", unit);
780	return strcat_r(prefix, nv, tmp);
781}
782
783// -----------------------------------------------------------------------------
784
785int mtd_getinfo(const char *mtdname, int *part, int *size)
786{
787	FILE *f;
788	char s[256];
789	char t[256];
790	int r;
791
792	r = 0;
793	if ((strlen(mtdname) < 128)) { // && (strcmp(mtdname, "pmon") != 0)) { //Yau dbg
794		sprintf(t, "\"%s\"", mtdname);
795		if ((f = fopen("/proc/mtd", "r")) != NULL) {
796			while (fgets(s, sizeof(s), f) != NULL) {
797				if ((sscanf(s, "mtd%d: %x", part, size) == 2) && (strstr(s, t) != NULL)) {
798					// don't accidentally mess with bl (0)
799					if (*part >= 0) r = 1; //Yau > -> >=
800					r =1;
801					break;
802				}
803			}
804			fclose(f);
805		}
806	}
807	if (!r) {
808		*size = 0;
809		*part = -1;
810	}
811	return r;
812}
813
814#if defined(RTCONFIG_UBIFS)
815#define UBI_SYSFS_DIR	"/sys/class/ubi"
816/* return device number, volume id, and volume size in bytes
817 * @return:
818 *      1:	ubi volume not found
819 * 	0:	success
820 *     -1:	invalid parameter
821 *     -2:	UBI not exist (open /sys/class/ubi failed)
822 *     <0:	error
823 */
824int ubi_getinfo(const char *ubiname, int *dev, int *part, int *size)
825{
826	DIR *dir;
827	int d, p, l, cmp, ret = 1;
828	char *s1, *s2, path[PATH_MAX];
829	struct dirent *ent;
830
831	if (!ubiname || *ubiname == '\0' || !dev || !part || !size)
832		return -1;
833
834	if ((dir = opendir(UBI_SYSFS_DIR)) == NULL)
835		return -2;
836
837	while (ret && (ent = readdir(dir)) != NULL) {
838		if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || strncmp(ent->d_name, "ubi", 3))
839			continue;
840		if (sscanf(ent->d_name, "ubi%d_%d", &d, &p) != 2)
841			continue;
842
843		snprintf(path, sizeof(path), "%s/ubi%d_%d/name", UBI_SYSFS_DIR, d, p);
844		if (!(s1 = file2str(path)))
845			continue;
846		/* remove tailed line-feed character */
847		l = strlen(s1);
848		if (*(s1+l-1) == '\xa')
849			*(s1+l-1) = '\0';
850		cmp = strcmp(ubiname, s1);
851		free(s1);
852		if (cmp)
853			continue;
854
855		snprintf(path, sizeof(path), "%s/ubi%d_%d/data_bytes", UBI_SYSFS_DIR, d, p);
856		if (!(s2 = file2str(path)))
857			continue;
858		*dev = d;
859		*part = p;
860		*size = atoi(s2);
861		free(s2);
862		ret = 0;
863	}
864	closedir(dir);
865
866	return ret;
867}
868#endif
869
870// -----------------------------------------------------------------------------
871
872int nvram_get_int(const char *key)
873{
874	return atoi(nvram_safe_get(key));
875}
876
877int nvram_set_int(const char *key, int value)
878{
879	char nvramstr[16];
880
881	snprintf(nvramstr, sizeof(nvramstr), "%d", value);
882	return nvram_set(key, nvramstr);
883}
884
885double nvram_get_double(const char *key)
886{
887	return atof(nvram_safe_get(key));
888}
889
890int nvram_set_double(const char *key, double value)
891{
892	char nvramstr[33];
893
894	snprintf(nvramstr, sizeof(nvramstr), "%.9g", value);
895	return nvram_set(key, nvramstr);
896}
897
898#if defined(RTCONFIG_SSH) || defined(RTCONFIG_HTTPS)
899int nvram_get_file(const char *key, const char *fname, int max)
900{
901	int n;
902	char *p;
903	char *b;
904	int r;
905
906	r = 0;
907	p = nvram_safe_get(key);
908	n = strlen(p);
909	if (n <= max) {
910		if ((b = malloc(base64_decoded_len(n) + 128)) != NULL) {
911			n = base64_decode(p, (unsigned char *) b, n);
912			if (n > 0) r = (f_write(fname, b, n, 0, 0644) == n);
913			free(b);
914		}
915	}
916	return r;
917/*
918	char b[2048];
919	int n;
920	char *p;
921
922	p = nvram_safe_get(key);
923	n = strlen(p);
924	if (n <= max) {
925		n = base64_decode(p, b, n);
926		if (n > 0) return (f_write(fname, b, n, 0, 0700) == n);
927	}
928	return 0;
929*/
930}
931
932int nvram_set_file(const char *key, const char *fname, int max)
933{
934	char *in;
935	char *out;
936	long len;
937	int n;
938	int r;
939
940	if ((len = f_size(fname)) > max) return 0;
941	max = (int)len;
942	r = 0;
943	if (f_read_alloc(fname, &in, max) == max) {
944		if ((out = malloc(base64_encoded_len(max) + 128)) != NULL) {
945			n = base64_encode((unsigned char *) in, out, max);
946			out[n] = 0;
947			nvram_set(key, out);
948			free(out);
949			r = 1;
950		}
951		free(in);
952	}
953	return r;
954/*
955	char a[2048];
956	char b[4096];
957	int n;
958
959	if (((n = f_read(fname, &a, sizeof(a))) > 0) && (n <= max)) {
960		n = base64_encode(a, b, n);
961		b[n] = 0;
962		nvram_set(key, b);
963		return 1;
964	}
965	return 0;
966*/
967}
968#endif
969
970int nvram_contains_word(const char *key, const char *word)
971{
972	return (find_word(nvram_safe_get(key), word) != NULL);
973}
974
975int nvram_is_empty(const char *key)
976{
977	char *p;
978	return (((p = nvram_get(key)) == NULL) || (*p == 0));
979}
980
981void nvram_commit_x(void)
982{
983	if (!nvram_get_int("debug_nocommit")) nvram_commit();
984}
985
986void chld_reap(int sig)
987{
988	while (waitpid(-1, NULL, WNOHANG) > 0) {}
989}
990
991static uint32 crc_table[256]={ 0x00000000,0x77073096,0xEE0E612C,0x990951BA,
9920x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,
9930x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2,
9940xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,
9950x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
9960x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,
9970xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,
9980xDCD60DCF,0xABD13D59,0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,
9990x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,
10000x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,0x76DC4190,0x01DB7106,0x98D220BC,
10010xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,
10020x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,0x6B6B51F4,
10030x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,
10040x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,
10050xFBD44C65,0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,
10060xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,
10070x33031DE5,0xAA0A4C5F,0xDD0D7CC9,0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,
10080x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,
10090xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,
10100x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,
10110x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
10120xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,
10130x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,
10140x17B7BE43,0x60B08ED5,0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,
10150xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,
10160xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,
10170x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,
10180x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,0x9B64C2B0,
10190xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,
10200x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,
10210x0BDBDF21,0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,
10220x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,
10230xF862AE69,0x616BFFD3,0x166CCF45,0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,
10240xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,
10250x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,0xBDBDF21C,0xCABAC28A,
10260x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,
10270xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D};
1028
1029uint32_t crc_calc(uint32_t crc, const char *buf, int len)
1030{
1031	crc = crc ^ 0xffffffff;
1032	while (len-- > 0) {
1033		crc = crc_table[(crc ^ *((unsigned char *)buf)) & 0xFF] ^ (crc >> 8);
1034		buf++;
1035	}
1036	crc = crc ^ 0xffffffff;
1037	return crc;
1038}
1039
1040// ugly solution and doesn't support wantag
1041void bcmvlan_models(int model, char *vlan)
1042{
1043	switch (model) {
1044	case MODEL_DSLAC68U:
1045	case MODEL_RPAC68U:
1046	case MODEL_RTAC68U:
1047	case MODEL_RTAC87U:
1048	case MODEL_RTAC56S:
1049	case MODEL_RTAC56U:
1050	case MODEL_RTAC66U:
1051	case MODEL_RTN66U:
1052	case MODEL_RTN16:
1053	case MODEL_RTN18U:
1054	case MODEL_RTN15U:
1055	case MODEL_RTAC53U:
1056	case MODEL_RTAC3200:
1057	case MODEL_RTAC88U:
1058	case MODEL_RTAC3100:
1059	case MODEL_RTAC5300:
1060	case MODEL_RTAC5300R:
1061	case MODEL_RTAC1200G:
1062	case MODEL_RTAC1200GP:
1063		strcpy(vlan, "vlan1");
1064		break;
1065	case MODEL_RTN53:
1066	case MODEL_RTN12:
1067	case MODEL_RTN12B1:
1068	case MODEL_RTN12C1:
1069	case MODEL_RTN12D1:
1070	case MODEL_RTN12VP:
1071	case MODEL_RTN12HP:
1072	case MODEL_RTN12HP_B1:
1073	case MODEL_RTN14UHP:
1074	case MODEL_RTN10U:
1075	case MODEL_RTN10P:
1076	case MODEL_RTN10D1:
1077	case MODEL_RTN10PV2:
1078		strcpy(vlan, "vlan0");
1079		break;
1080	default:
1081		strcpy(vlan, "");
1082		break;
1083	}
1084}
1085
1086char *get_productid(void)
1087{
1088	char *productid = nvram_safe_get("productid");
1089#ifdef RTCONFIG_ODMPID
1090	char *odmpid = nvram_safe_get("odmpid");
1091	if (*odmpid)
1092		productid = odmpid;
1093#endif
1094	return productid;
1095}
1096
1097int backup_rx;
1098int backup_tx;
1099int backup_set = 0;
1100
1101unsigned int netdev_calc(char *ifname, char *ifname_desc, unsigned long *rx, unsigned long *tx, char *ifname_desc2, unsigned long *rx2, unsigned long *tx2)
1102{
1103	char word[100], word1[100], *next, *next1;
1104	char tmp[100];
1105	char modelvlan[32];
1106	int i, j, model, unit;
1107	strcpy(ifname_desc2, "");
1108
1109	model = get_model();
1110	bcmvlan_models(model, modelvlan);
1111
1112	// find in LAN interface
1113	if(nvram_contains_word("lan_ifnames", ifname))
1114	{
1115		// find Wireless interface
1116		i=0;
1117		foreach(word, nvram_safe_get("wl_ifnames"), next) {
1118			if(strcmp(word, ifname)==0) {
1119				sprintf(ifname_desc, "WIRELESS%d", i);
1120				return 1;
1121			}
1122
1123#ifdef RTCONFIG_RALINK
1124			if(model == MODEL_RTN65U && strncmp(ifname, "rai", 3) == 0) // invalid traffic amount for interface
1125				return 0;
1126#endif
1127
1128			sprintf(tmp, "wl%d_vifnames", i);
1129			j = 0;
1130			foreach(word1, nvram_safe_get(tmp), next1) {
1131				if(strcmp(word1, wif_to_vif(ifname))==0)
1132				{
1133					sprintf(ifname_desc, "WIRELESS%d.%d", i, j);
1134					return 1;
1135				}
1136				j++;
1137			}
1138
1139			i++;
1140		}
1141
1142#if defined(RTCONFIG_RALINK) && defined(RTCONFIG_WLMODULE_RT3352_INIC_MII)
1143		if(model == MODEL_RTN65U)
1144		{
1145			i = 0;
1146			j = 0;
1147			foreach(word, nvram_safe_get("nic_lan_ifnames"), next) {
1148				if(strcmp(word, ifname)==0)
1149				{
1150					sprintf(tmp, "wl%d_vifnames", 0);
1151					foreach(word1, nvram_safe_get(tmp), next1) {
1152						char vifname[32];
1153						sprintf(vifname, "%s_ifname", word1);
1154						if(strlen(nvram_safe_get(vifname)) > 0)
1155						{
1156							if(i-- == 0)
1157								break;
1158						}
1159						j++;
1160					}
1161				sprintf(ifname_desc, "WIRELESS%d.%d", 0, j);
1162					return 1;
1163				}
1164				i++;
1165			}
1166		}
1167#endif
1168
1169		// find wired interface
1170		strcpy(ifname_desc, "WIRED");
1171
1172		if(model == MODEL_DSLAC68U)
1173			return 1;
1174
1175#ifdef RTCONFIG_BCM5301X_TRAFFIC_MONITOR
1176			return 1;
1177#endif
1178
1179		// special handle for non-tag wan of broadcom solution
1180		// pretend vlanX is must called after ethX
1181		if(nvram_match("switch_wantag", "none")) { //Don't calc if select IPTV
1182			if(backup_set && strlen(modelvlan) && strcmp(ifname, modelvlan)==0) {
1183				backup_set  = 0;
1184				backup_rx -= *rx;
1185				backup_tx -= *tx;
1186
1187				*rx2 = backup_rx;
1188				*tx2 = backup_tx;
1189				/* Cherry Cho modified for RT-AC3200 Bug#202 in 2014/11/4. */
1190				unit = get_wan_unit("eth0");
1191
1192#ifdef RTCONFIG_DUALWAN
1193				if ( (unit == wan_primary_ifunit()) || ( !strstr(nvram_safe_get("wans_dualwan"), "none") && nvram_match("wans_mode", "lb")) )
1194				{
1195					if (unit == WAN_UNIT_FIRST)
1196						strcpy(ifname_desc2, "INTERNET");
1197					else
1198						sprintf(ifname_desc2,"INTERNET%d", unit);
1199				}
1200#else
1201				if(unit == wan_primary_ifunit())
1202					strcpy(ifname_desc2, "INTERNET");
1203#endif	/* RTCONFIG_DUALWAN */
1204			}
1205		}//End of switch_wantag
1206
1207		return 1;
1208	}
1209	// find bridge interface
1210	else if(nvram_match("lan_ifname", ifname))
1211	{
1212		strcpy(ifname_desc, "BRIDGE");
1213		return 1;
1214	}
1215	// find in WAN interface
1216	else if (ifname && (unit = get_wan_unit(ifname)) >= 0)	{
1217		if (dualwan_unit__nonusbif(unit)) {
1218#if defined(RA_ESW)
1219#if defined(RTCONFIG_RALINK_MT7620)
1220			get_mt7620_wan_unit_bytecount(unit, tx, rx);
1221#elif defined(RTCONFIG_RALINK_MT7621)
1222			get_mt7621_wan_unit_bytecount(unit, tx, rx);
1223#endif
1224#endif
1225#ifndef RTCONFIG_BCM5301X_TRAFFIC_MONITOR
1226			if(strlen(modelvlan) && strcmp(ifname, "eth0")==0) {
1227				backup_rx = *rx;
1228				backup_tx = *tx;
1229				backup_set  = 1;
1230			}
1231			else{
1232#endif
1233#ifdef RTCONFIG_DUALWAN
1234				if ( (unit == wan_primary_ifunit()) || ( !strstr(nvram_safe_get("wans_dualwan"), "none") && nvram_match("wans_mode", "lb")) )
1235				{
1236					if (unit == WAN_UNIT_FIRST) {
1237						strcpy(ifname_desc, "INTERNET");
1238						return 1;
1239					}
1240					else {
1241						sprintf(ifname_desc,"INTERNET%d", unit);
1242						return 1;
1243					}
1244				}
1245#else
1246				if(unit == wan_primary_ifunit()){
1247					strcpy(ifname_desc, "INTERNET");
1248					return 1;
1249				}
1250#endif	/* RTCONFIG_DUALWAN */
1251#ifndef RTCONFIG_BCM5301X_TRAFFIC_MONITOR
1252			}
1253#endif
1254		}
1255		else if (dualwan_unit__usbif(unit)) {
1256#ifdef RTCONFIG_DUALWAN
1257			if ( (unit == wan_primary_ifunit()) || ( !strstr(nvram_safe_get("wans_dualwan"), "none") && nvram_match("wans_mode", "lb")) )
1258			{
1259				if(unit == WAN_UNIT_FIRST){//Cherry Cho modified in 2014/11/4.
1260					strcpy(ifname_desc, "INTERNET");
1261					return 1;
1262				}
1263				else{
1264					sprintf(ifname_desc,"INTERNET%d", unit);
1265					return 1;
1266				}
1267			}
1268#else
1269			if(unit == wan_primary_ifunit()){
1270				strcpy(ifname_desc, "INTERNET");
1271				return 1;
1272			}
1273#endif	/* RTCONFIG_DUALWAN */
1274		}
1275		else {
1276			_dprintf("%s: unknown ifname %s\n", __func__, ifname);
1277		}
1278	}
1279
1280	return 0;
1281}
1282
1283// 0: Not private subnet, 1: A class, 2: B class, 3: C class.
1284int is_private_subnet(const char *ip)
1285{
1286	unsigned long long ip_num;
1287	unsigned long long A_class_start, A_class_end;
1288	unsigned long long B_class_start, B_class_end;
1289	unsigned long long C_class_start, C_class_end;
1290
1291	if(ip == NULL)
1292		return 0;
1293
1294	A_class_start = inet_network("10.0.0.0");
1295	A_class_end = inet_network("10.255.255.255");
1296	B_class_start = inet_network("172.16.0.0");
1297	B_class_end = inet_network("172.31.255.255");
1298	C_class_start = inet_network("192.168.0.0");
1299	C_class_end = inet_network("192.168.255.255");
1300
1301	ip_num = inet_network(ip);
1302
1303	if(ip_num > A_class_start && ip_num < A_class_end)
1304		return 1;
1305	else if(ip_num > B_class_start && ip_num < B_class_end)
1306		return 2;
1307	else if(ip_num > C_class_start && ip_num < C_class_end)
1308		return 3;
1309	else
1310		return 0;
1311}
1312
1313// clean_mode: 0~3, clean_time: 0~(LONG_MAX-1), threshold(KB): 0: always act, >0: act when lower than.
1314int free_caches(const char *clean_mode, const int clean_time, const unsigned int threshold){
1315	int test_num;
1316	FILE *fp;
1317	char memdata[256] = {0};
1318	unsigned int memfree = 0;
1319
1320#ifdef RTCONFIG_BCMARM
1321	return 0;
1322#endif
1323
1324	/* Paul add 2012/7/17, skip free caches for DSL model. */
1325	#ifdef RTCONFIG_DSL
1326		return 0;
1327	#endif
1328
1329	if(!clean_mode || clean_time < 0)
1330		return -1;
1331
1332_dprintf("clean_mode(%s) clean_time(%d) threshold(%u)\n", clean_mode, clean_time, threshold);
1333	test_num = strtol(clean_mode, NULL, 10);
1334	if(test_num == LONG_MIN || test_num == LONG_MAX
1335			|| test_num < atoi(FREE_MEM_NONE) || test_num > atoi(FREE_MEM_ALL)
1336			)
1337		return -1;
1338
1339	if(threshold > 0){
1340		if((fp = fopen("/proc/meminfo", "r")) != NULL){
1341			while(fgets(memdata, 255, fp) != NULL){
1342				if(strstr(memdata, "MemFree") != NULL){
1343					sscanf(memdata, "MemFree: %d kB", &memfree);
1344_dprintf("%s: memfree=%u.\n", __FUNCTION__, memfree);
1345					break;
1346				}
1347			}
1348			fclose(fp);
1349			if(memfree > threshold){
1350_dprintf("%s: memfree > threshold.\n", __FUNCTION__);
1351				return 0;
1352			}
1353		}
1354	}
1355
1356_dprintf("%s: Start syncing...\n", __FUNCTION__);
1357	sync();
1358
1359_dprintf("%s: Start cleaning...\n", __FUNCTION__);
1360	f_write_string("/proc/sys/vm/drop_caches", clean_mode, 0, 0);
1361	if(clean_time > 0){
1362_dprintf("%s: waiting %d second...\n", __FUNCTION__, clean_time);
1363		sleep(clean_time);
1364_dprintf("%s: Finish.\n", __FUNCTION__);
1365		f_write_string("/proc/sys/vm/drop_caches", FREE_MEM_NONE, 0, 0);
1366	}
1367
1368	return 0;
1369}
1370
1371void logmessage_normal(char *logheader, char *fmt, ...){
1372  va_list args;
1373  char buf[512];
1374
1375  va_start(args, fmt);
1376
1377  vsnprintf(buf, sizeof(buf), fmt, args);
1378
1379  openlog(logheader, 0, 0);
1380  syslog(0, buf);
1381  closelog();
1382  va_end(args);
1383}
1384
1385char *get_logfile_path(void)
1386{
1387	static char prefix[] = "/jffsXXXXXX";
1388
1389#if defined(RTCONFIG_PSISTLOG)
1390	strcpy(prefix, "/jffs");
1391	if (!check_if_dir_writable(prefix)) {
1392		_dprintf("logfile output directory: /tmp.\n");
1393		strcpy(prefix, "/tmp");
1394	}
1395#else
1396	strcpy(prefix, "/tmp");
1397#endif
1398
1399	return prefix;
1400}
1401
1402char *get_syslog_fname(unsigned int idx)
1403{
1404	char prefix[] = "/jffsXXXXXX";
1405	static char buf[PATH_MAX];
1406
1407#if defined(RTCONFIG_PSISTLOG)
1408	strcpy(prefix, "/jffs");
1409	if (!check_if_dir_writable(prefix)) {
1410		_dprintf("syslog output directory: /tmp.\n");
1411		strcpy(prefix, "/tmp");
1412	}
1413#else
1414	strcpy(prefix, "/tmp");
1415#endif
1416
1417	if (!idx)
1418		sprintf(buf, "%s/syslog.log", prefix);
1419	else
1420		sprintf(buf, "%s/syslog.log-%d", prefix, idx);
1421
1422	return buf;
1423}
1424
1425#ifdef RTCONFIG_USB_MODEM
1426char *get_modemlog_fname(void){
1427	char prefix[] = "/tmpXXXXXX";
1428	static char buf[PATH_MAX];
1429
1430	strcpy(prefix, "/tmp");
1431	sprintf(buf, "%s/3ginfo.txt", prefix);
1432
1433	return buf;
1434}
1435#endif
1436
1437#ifdef RTCONFIG_BCMWL6
1438#ifdef RTCONFIG_PROXYSTA
1439int is_psta(int unit)
1440{
1441	if (unit < 0) return 0;
1442	if ((nvram_get_int("sw_mode") == SW_MODE_AP) &&
1443		(nvram_get_int("wlc_psta") == 1) &&
1444		((nvram_get_int("wlc_band") == unit)
1445#ifdef PXYSTA_DUALBAND
1446		|| (nvram_match("exband", "1") && nvram_get_int("wlc_band_ex") == unit)
1447#endif
1448		))
1449		return 1;
1450
1451	return 0;
1452}
1453
1454int is_psr(int unit)
1455{
1456	if (unit < 0) return 0;
1457#ifdef RTCONFIG_QTN
1458	if (unit == 1) return 0;
1459#endif
1460	if ((nvram_get_int("sw_mode") == SW_MODE_AP) &&
1461		(nvram_get_int("wlc_psta") == 2) &&
1462		((nvram_get_int("wlc_band") == unit)
1463#ifdef PXYSTA_DUALBAND
1464		||  (nvram_match("exband", "1") && nvram_get_int("wlc_band_ex") == unit)
1465#endif
1466		))
1467		return 1;
1468
1469	return 0;
1470}
1471
1472int psta_exist()
1473{
1474	char word[256], *next;
1475	int idx = 0;
1476
1477	foreach (word, nvram_safe_get("wl_ifnames"), next) {
1478		if (is_psta(idx)) return 1;
1479		idx++;
1480	}
1481
1482	return 0;
1483}
1484
1485int psta_exist_except(int unit)
1486{
1487	char word[256], *next;
1488	int idx = 0;
1489
1490	if (unit < 0) return 0;
1491	foreach (word, nvram_safe_get("wl_ifnames"), next) {
1492		if (idx == unit) goto END;
1493		if (is_psta(idx)) return 1;
1494END:
1495		idx++;
1496	}
1497
1498	return 0;
1499}
1500
1501int psr_exist()
1502{
1503	char word[256], *next;
1504	int idx = 0;
1505
1506	foreach (word, nvram_safe_get("wl_ifnames"), next) {
1507		if (is_psr(idx)) return 1;
1508		idx++;
1509	}
1510
1511	return 0;
1512}
1513
1514int psr_exist_except(int unit)
1515{
1516	char word[256], *next;
1517	int idx = 0;
1518
1519	if (unit < 0) return 0;
1520	foreach (word, nvram_safe_get("wl_ifnames"), next) {
1521		if (idx == unit) goto END;
1522		if (is_psr(idx)) return 1;
1523END:
1524		idx++;
1525	}
1526
1527	return 0;
1528}
1529#endif
1530#endif
1531
1532#ifdef RTCONFIG_OPENVPN
1533char *get_parsed_crt(const char *name, char *buf, size_t buf_len)
1534{
1535	char *value;
1536	int len, i;
1537#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS)
1538	FILE *fp;
1539	char tmpBuf[256] = {0};
1540	char *p = buf;
1541#endif
1542
1543	value = nvram_safe_get(name);
1544	len = strlen(value);
1545
1546#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS)
1547	if(!check_if_dir_exist(OVPN_FS_PATH))
1548		mkdir(OVPN_FS_PATH, S_IRWXU);
1549	snprintf(tmpBuf, sizeof(tmpBuf) -1, "%s/%s", OVPN_FS_PATH, name);
1550#endif
1551
1552	if(len) {
1553		for (i=0; (i < len); i++) {
1554			if (value[i] == '>')
1555				buf[i] = '\n';
1556			else
1557				buf[i] = value[i];
1558		}
1559		buf[i] = '\0';
1560
1561#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS)
1562		//save to file and then clear nvram value
1563		fp = fopen(tmpBuf, "w");
1564		if(fp) {
1565			chmod(tmpBuf, S_IRUSR|S_IWUSR);
1566			fprintf(fp, "%s", buf);
1567			fclose(fp);
1568			nvram_set(name, "");
1569		}
1570#endif
1571	}
1572	else {
1573#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS)
1574		//nvram value cleard, get from file
1575		fp = fopen(tmpBuf, "r");
1576		if(fp) {
1577			while(fgets(buf, buf_len, fp)) {
1578				if(!strncmp(buf, "-----BEGIN", 10))
1579					break;
1580			}
1581			if(feof(fp)) {
1582				fclose(fp);
1583				memset(buf, 0, buf_len);
1584				return buf;
1585			}
1586			p += strlen(buf);
1587			memset(tmpBuf, 0, sizeof(tmpBuf));
1588			while(fgets(tmpBuf, sizeof(tmpBuf), fp)) {
1589				strncpy(p, tmpBuf, strlen(tmpBuf));
1590				p += strlen(tmpBuf);
1591			}
1592			*p = '\0';
1593			fclose(fp);
1594		}
1595#endif
1596	}
1597	return buf;
1598}
1599
1600int set_crt_parsed(const char *name, char *file_path)
1601{
1602#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS)
1603	char target_file_path[128] ={0};
1604
1605	if(!check_if_dir_exist(OVPN_FS_PATH))
1606		mkdir(OVPN_FS_PATH, S_IRWXU);
1607
1608	if(check_if_file_exist(file_path)) {
1609		snprintf(target_file_path, sizeof(target_file_path) -1, "%s/%s", OVPN_FS_PATH, name);
1610		return eval("cp", file_path, target_file_path);
1611	}
1612	else {
1613		return -1;
1614	}
1615#else
1616	FILE *fp=fopen(file_path, "r");
1617	char buffer[4000] = {0};
1618	char buffer2[256] = {0};
1619	char *p = buffer;
1620
1621	if(fp) {
1622		while(fgets(buffer, sizeof(buffer), fp)) {
1623			if(!strncmp(buffer, "-----BEGIN", 10))
1624				break;
1625		}
1626		if(feof(fp)) {
1627			fclose(fp);
1628			return -EINVAL;
1629		}
1630		p += strlen(buffer);
1631		//if( *(p-1) == '\n' )
1632			//*(p-1) = '>';
1633		while(fgets(buffer2, sizeof(buffer2), fp)) {
1634			strncpy(p, buffer2, strlen(buffer2));
1635			p += strlen(buffer2);
1636			//if( *(p-1) == '\n' )
1637				//*(p-1) = '>';
1638		}
1639		*p = '\0';
1640		nvram_set(name, buffer);
1641		fclose(fp);
1642		return 0;
1643	}
1644	else
1645		return -ENOENT;
1646#endif
1647}
1648
1649int ovpn_crt_is_empty(const char *name)
1650{
1651	char file_path[128] ={0};
1652	struct stat st;
1653
1654	if( nvram_is_empty(name) ) {
1655#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS)
1656		//check file
1657		if(d_exists(OVPN_FS_PATH)) {
1658			snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, name);
1659			if(stat(file_path, &st) == 0) {
1660				if( !S_ISDIR(st.st_mode) && st.st_size ) {
1661					return 0;
1662				}
1663				else {
1664					return 1;
1665				}
1666			}
1667			else {
1668				return 1;
1669			}
1670		}
1671		else {
1672			mkdir(OVPN_FS_PATH, S_IRWXU);
1673			return 1;
1674		}
1675#else
1676		return 1;
1677#endif
1678	}
1679	else {
1680		return 0;
1681	}
1682}
1683#endif
1684
1685#ifdef RTCONFIG_DUALWAN
1686/**
1687 * Get wan_unit of USB interface
1688 * @return
1689 *  >= 0:	wan_unit
1690 *  <  0:	not found
1691 */
1692int get_usbif_dualwan_unit(void)
1693{
1694	int wan_unit;
1695
1696	for (wan_unit = WAN_UNIT_FIRST; wan_unit < WAN_UNIT_MAX; ++wan_unit)
1697		if (dualwan_unit__usbif(wan_unit))
1698			break;
1699
1700	if (wan_unit == WAN_UNIT_MAX)
1701		wan_unit = -1;
1702
1703	return wan_unit;
1704}
1705
1706/**
1707 * Get unit of primary interface (WAN/LAN/USB only)
1708 * @return
1709 *  >= 0:	wan_unit
1710 *  <  0:	not found
1711 */
1712int get_primaryif_dualwan_unit(void)
1713{
1714	int unit, wan_type;
1715
1716	for(unit = WAN_UNIT_FIRST; unit < WAN_UNIT_MAX; ++unit){
1717		if (unit != wan_primary_ifunit() && !nvram_match("wans_mode", "lb"))
1718			continue;
1719
1720		wan_type = get_dualwan_by_unit(unit);
1721		if (wan_type != WANS_DUALWAN_IF_WAN
1722		    && wan_type != WANS_DUALWAN_IF_LAN
1723		    && wan_type != WANS_DUALWAN_IF_USB)
1724			continue;
1725
1726		break;
1727	}
1728
1729	if(unit == WAN_UNIT_MAX)
1730		unit = -1;
1731
1732	return unit;
1733}
1734#endif
1735
1736/* Return WiFi unit number in accordance with interface name.
1737 * @wif:	pointer to WiFi interface name.
1738 * @return:
1739 * 	< 0:	invalid
1740 *  otherwise:	unit
1741 */
1742int get_wifi_unit(char *wif)
1743{
1744	int i;
1745	char word[256], *next, *ifn, nv[20];
1746
1747	if (!wif || *wif == '\0')
1748		return -1;
1749	foreach (word, nvram_safe_get("wl_ifnames"), next) {
1750		if (strncmp(word, wif, strlen(word)))
1751			continue;
1752
1753		for (i = 0; i <= 1; ++i) {
1754			sprintf(nv, "wl%d_ifname", i);
1755			ifn = nvram_safe_get(nv);
1756			if (!strncmp(word, ifn, strlen(word)))
1757				return i;
1758		}
1759	}
1760	return -1;
1761}
1762
1763
1764#ifdef RTCONFIG_YANDEXDNS
1765int get_yandex_dns(int family, int mode, char **server, int max_count)
1766{
1767	static const struct {
1768		int mode;
1769		int family;
1770		char *server;
1771	} table[] = {
1772		{ YADNS_BASIC, AF_INET, "77.88.8.8" },			/* dns.yandex.ru  */
1773		{ YADNS_BASIC, AF_INET, "77.88.8.1" },			/* secondary.dns.yandex.ru */
1774		{ YADNS_SAFE, AF_INET, "77.88.8.88" },			/* safe.dns.yandex.ru */
1775		{ YADNS_SAFE, AF_INET, "77.88.8.2" },			/* secondary.safe.dns.yandex.ru */
1776		{ YADNS_FAMILY, AF_INET, "77.88.8.7" },			/* family.dns.yandex.ru */
1777		{ YADNS_FAMILY, AF_INET, "77.88.8.3" },			/* secondary.family.dns.yandex.ru */
1778#ifdef RTCONFIG_IPV6
1779		{ YADNS_BASIC, AF_INET6, "2a02:6b8::feed:0ff" },	/* dns.yandex.ru  */
1780		{ YADNS_BASIC, AF_INET6, "2a02:6b8:0:1::feed:0ff" },	/* secondary.dns.yandex.ru */
1781		{ YADNS_SAFE, AF_INET6, "2a02:6b8::feed:bad" },		/* safe.dns.yandex.ru */
1782		{ YADNS_SAFE, AF_INET6, "2a02:6b8:0:1::feed:bad" },	/* secondary.safe.dns.yandex.ru */
1783		{ YADNS_FAMILY, AF_INET6, "2a02:6b8::feed:a11" },	/* family.dns.yandex.ru */
1784		{ YADNS_FAMILY, AF_INET6, "2a02:6b8:0:1::feed:a11" },	/* secondary.family.dns.yandex.ru */
1785#endif
1786	};
1787	int i, count = 0;
1788
1789	if (mode < YADNS_FIRST || mode >= YADNS_COUNT)
1790		return -1;
1791
1792	for (i = 0; i < sizeof(table)/sizeof(table[0]) && count < max_count; i++) {
1793		if ((mode == table[i].mode) &&
1794		    (family == AF_UNSPEC || family == table[i].family))
1795			server[count++] = table[i].server;
1796	}
1797
1798	return count;
1799}
1800#endif
1801
1802#ifdef RTCONFIG_BWDPI
1803/*
1804	usage in rc or bwdpi for checking service
1805*/
1806int check_bwdpi_nvram_setting()
1807{
1808	int enabled = 1;
1809	int debug = nvram_get_int("bwdpi_debug");
1810
1811	// check no qos service
1812	if(nvram_get_int("wrs_enable") == 0 && nvram_get_int("wrs_app_enable") == 0 &&
1813		nvram_get_int("wrs_vp_enable") == 0 && nvram_get_int("wrs_cc_enable") == 0 &&
1814		nvram_get_int("wrs_mals_enable") == 0 &&
1815		nvram_get_int("bwdpi_db_enable") == 0 &&
1816		nvram_get_int("apps_analysis") == 0 &&
1817		nvram_get_int("bwdpi_wh_enable") == 0 &&
1818		nvram_get_int("qos_enable") == 0)
1819		enabled = 0;
1820
1821	// check qos service (not adaptive qos)
1822	if(nvram_get_int("wrs_enable") == 0 && nvram_get_int("wrs_app_enable") == 0 &&
1823		nvram_get_int("wrs_vp_enable") == 0 && nvram_get_int("wrs_cc_enable") == 0 &&
1824		nvram_get_int("wrs_mals_enable") == 0 &&
1825		nvram_get_int("bwdpi_db_enable") == 0 &&
1826		nvram_get_int("apps_analysis") == 0 &&
1827		nvram_get_int("bwdpi_wh_enable") == 0 &&
1828		nvram_get_int("qos_enable") == 1 && nvram_get_int("qos_type") != 1)
1829		enabled = 0;
1830
1831	if(debug) dbg("[check_bwdpi_nvram_setting] enabled= %d\n", enabled);
1832
1833	return enabled;
1834}
1835#endif
1836
1837/*
1838	transfer timestamp into date
1839	ex. date = 2014-07-14 19:20:10
1840*/
1841void StampToDate(unsigned long timestamp, char *date)
1842{
1843	struct tm *local;
1844	time_t now;
1845
1846	now = timestamp;
1847	local = localtime(&now);
1848	strftime(date, 30, "%Y-%m-%d %H:%M:%S", local);
1849}
1850
1851/*
1852	check filesize is over or not
1853	if over size, return 1, else return 0
1854*/
1855int check_filesize_over(char *path, long int size)
1856{
1857	struct stat st;
1858	off_t cursize;
1859
1860	stat(path, &st);
1861	cursize = st.st_size;
1862
1863	size = size * 1024; // KB
1864
1865	if(cursize > size)
1866		return 1;
1867	else
1868		return 0;
1869}
1870
1871/*
1872	get last month's timestamp
1873	ex.
1874	now = 1445817600
1875	tm  = 2015/10/26 00:00:00
1876	t   = 2015/10/01 00:00:00
1877	t_t = 1443628800
1878*/
1879time_t get_last_month_timestamp()
1880{
1881	struct tm local, t;
1882	time_t now, t_t = 0;
1883
1884	// get timestamp and tm
1885	time(&now);
1886	localtime_r(&now, &local);
1887
1888	// copy t from local
1889	t.tm_year = local.tm_year;
1890	t.tm_mon = local.tm_mon;
1891	t.tm_mday = 1;
1892	t.tm_hour = 0;
1893	t.tm_min = 0;
1894	t.tm_sec = 0;
1895
1896	// transfer tm to timestamp
1897	t_t = mktime(&t);
1898
1899	return t_t;
1900}
1901
1902int get_iface_hwaddr(char *name, unsigned char *hwaddr)
1903{
1904	struct ifreq ifr;
1905	int ret = 0;
1906	int s;
1907
1908	/* open socket to kernel */
1909	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1910		perror("socket");
1911		return errno;
1912	}
1913
1914	/* do it */
1915	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)-1);
1916	ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
1917	if ((ret = ioctl(s, SIOCGIFHWADDR, &ifr)) == 0)
1918		memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
1919
1920	/* cleanup */
1921	close(s);
1922	return ret;
1923}
1924
1925int internet_ready(void)
1926{
1927	if(nvram_get_int("ntp_ready") == 1)
1928		return 1;
1929	return 0;
1930}
1931
1932void set_no_internet_ready(void)
1933{
1934	nvram_set("ntp_ready", "0");
1935}
1936
1937#ifdef RTCONFIG_TRAFFIC_LIMITER
1938static char *traffic_limiter_get_path(const char *type)
1939{
1940	if (type == NULL)
1941		return NULL;
1942	else if (strcmp(type, "limit") == 0)
1943		return "/jffs/tld/tl_limit";
1944	else if (strcmp(type, "alert") == 0)
1945		return "/jffs/tld/tl_alert";
1946	else if (strcmp(type, "count") == 0)
1947		return "/jffs/tld/tl_count";
1948
1949	return NULL;
1950}
1951
1952unsigned int traffic_limiter_read_bit(const char *type)
1953{
1954	char *path;
1955	char buf[sizeof("4294967295")];
1956	unsigned int val = 0;
1957	int debug = nvram_get_int("tl_debug");
1958
1959	path = traffic_limiter_get_path(type);
1960	if (path && f_read_string(path, buf, sizeof(buf)) > 0)
1961		val = strtoul(buf, NULL, 10);
1962
1963	if (debug) dbg("%s : path = %s, val=%u\n", __FUNCTION__, path ? : "NULL", val);
1964	return val;
1965}
1966
1967void traffic_limiter_set_bit(const char *type, int unit)
1968{
1969	char *path;
1970	char buf[sizeof("4294967295")];
1971	unsigned int val = 0;
1972	int debug = nvram_get_int("tl_debug");
1973
1974	path = traffic_limiter_get_path(type);
1975	if (path) {
1976		val = traffic_limiter_read_bit(type);
1977		val |= (1U << unit);
1978		snprintf(buf, sizeof(buf), "%u", val);
1979		f_write_string(path, buf, 0, 0);
1980	}
1981
1982	if (debug) dbg("%s : path = %s, val=%u\n", __FUNCTION__, path ? : "NULL", val);
1983}
1984
1985void traffic_limiter_clear_bit(const char *type, int unit)
1986{
1987	char *path;
1988	char buf[sizeof("4294967295")];
1989	unsigned int val = 0;
1990	int debug = nvram_get_int("tl_debug");
1991
1992	path = traffic_limiter_get_path(type);
1993	if (path) {
1994		val = traffic_limiter_read_bit(type);
1995		val &= ~(1U << unit);
1996		snprintf(buf, sizeof(buf), "%u", val);
1997		f_write_string(path, buf, 0, 0);
1998	}
1999
2000	if (debug) dbg("%s : path = %s, val=%u\n", __FUNCTION__, path ? : "NULL", val);
2001}
2002
2003double traffic_limiter_get_realtime(int unit)
2004{
2005	char path[PATH_MAX];
2006	char buf[32];
2007	double val = 0;
2008
2009	snprintf(path, sizeof(path), "/tmp/tl%d_realtime", unit);
2010	if (f_read_string(path, buf, sizeof(buf)) > 0)
2011		val = atof(buf);
2012
2013	return val;
2014}
2015
2016int TL_UNIT_S; // traffic limiter dual wan unit start
2017int TL_UNIT_E; // traffic limiter dual wan unit end
2018
2019int traffic_limiter_dualwan_check(char *dualwan_mode)
2020{
2021	int ret = 1;
2022
2023	/* check daul wan mode */
2024	if (!strcmp(dualwan_mode, "lb"))
2025	{
2026		// load balance
2027		TL_UNIT_S = WAN_UNIT_FIRST;
2028		TL_UNIT_E = WAN_UNIT_MAX;
2029	}
2030	else if (!strcmp(dualwan_mode, "fo") || !strcmp(dualwan_mode, "fb"))
2031	{
2032		// fail over or fail back
2033		TL_UNIT_S = wan_primary_ifunit();
2034		TL_UNIT_E = wan_primary_ifunit() + 1;
2035	}
2036	else
2037	{
2038		printf("%s : can't identify daulwan_mode\n", __FUNCTION__);
2039		ret = 0;
2040	}
2041
2042	return ret;
2043}
2044#endif
2045