1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 *
17 * Copyright 2004, ASUSTeK Inc.
18 * All Rights Reserved.
19 *
20 * THIS SOFTWARE IS OFFERED "AS IS", AND ASUS GRANTS NO WARRANTIES OF ANY
21 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
22 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
23 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
24 *
25 * $Id: common_ex.c,v 1.3 2007/03/29 06:02:23 shinjung Exp $
26 */
27
28#include "rc.h"
29
30#include <stdlib.h>
31#include <stdio.h>
32#include <net/if_arp.h>
33#include <time.h>
34#include <bcmnvram.h>
35#include <shutils.h>
36#include <sys/time.h>
37#include <sys/ioctl.h>
38#include <sys/sysinfo.h>
39#include <stdarg.h>
40#include <arpa/inet.h>	// oleg patch
41#include <string.h>	// oleg patch
42#include <bcmdevs.h>
43#include <wlutils.h>
44#include <dirent.h>
45#include <sys/wait.h>
46#include <shared.h>
47
48#ifdef RTCONFIG_RALINK
49#include <ralink.h>
50#endif
51
52#ifdef RTCONFIG_QCA
53#include <qca.h>
54#endif
55
56#include <mtd.h>
57
58void update_lan_status(int);
59
60in_addr_t inet_addr_(const char *cp)
61{
62	struct in_addr a;
63
64	if (!inet_aton(cp, &a))
65		return INADDR_ANY;
66	else
67		return a.s_addr;
68}
69
70inline int inet_equal(char *addr1, char *mask1, char *addr2, char *mask2)
71{
72	return ((inet_network(addr1) & inet_network(mask1)) ==
73		(inet_network(addr2) & inet_network(mask2)));
74}
75
76/* remove space in the end of string */
77char *trim_r(char *str)
78{
79	int i;
80
81	if (!str || !*str)
82		return str;
83
84	i = strlen(str) - 1;
85	while ((i >= 0) && (str[i] == ' ' || str[i] == '\n' || str[i] == '\r'))
86		str[i--] = 0;
87
88	return str;
89}
90
91/* convert mac address format from XXXXXXXXXXXX to XX:XX:XX:XX:XX:XX */
92char *conv_mac(char *mac, char *buf)
93{
94	int i, j;
95
96	if (strlen(mac)==0)
97	{
98		buf[0] = 0;
99	}
100	else
101	{
102		j=0;
103		for (i=0; i<12; i++)
104		{
105			if (i!=0&&i%2==0) buf[j++] = ':';
106			buf[j++] = mac[i];
107		}
108		buf[j] = 0;	// oleg patch
109	}
110	//buf[j] = 0;
111
112	_dprintf("mac: %s\n", buf);
113
114	return (buf);
115}
116
117// 2010.09 James. {
118/* convert mac address format from XX:XX:XX:XX:XX:XX to XXXXXXXXXXXX */
119char *conv_mac2(char *mac, char *buf)
120{
121	int i,j;
122
123	if(strlen(mac) != 17)
124		buf[0] = 0;
125	else{
126		for(i = 0, j = 0; i < 17; ++i){
127			if(i%3 != 2){
128				buf[j] = mac[i];
129				++j;
130			}
131
132			buf[j] = 0;
133		}
134	}
135
136	return(buf);
137}
138
139
140/* convert mac address format from XXXXXXXXXXXX to XX:XX:XX:XX:XX:XX */
141char *mac_conv(char *mac_name, int idx, char *buf)
142{
143	char *mac, name[32];
144	int i, j;
145
146	if (idx!=-1)
147		sprintf(name, "%s%d", mac_name, idx);
148	else sprintf(name, "%s", mac_name);
149
150	mac = nvram_safe_get(name);
151
152	if (strlen(mac)==0)
153	{
154		buf[0] = 0;
155	}
156	else
157	{
158		j=0;
159		for (i=0; i<12; i++)
160		{
161			if (i!=0&&i%2==0) buf[j++] = ':';
162			buf[j++] = mac[i];
163		}
164		buf[j] = 0;	// oleg patch
165	}
166	//buf[j] = 0;
167
168	_dprintf("mac: %s\n", buf);
169
170	return (buf);
171}
172
173// 2010.09 James. {
174/* convert mac address format from XX:XX:XX:XX:XX:XX to XXXXXXXXXXXX */
175char *mac_conv2(char *mac_name, int idx, char *buf)
176{
177	char *mac, name[32];
178	int i, j;
179
180	if(idx != -1)
181		sprintf(name, "%s%d", mac_name, idx);
182	else
183		sprintf(name, "%s", mac_name);
184
185	mac = nvram_safe_get(name);
186
187	if(strlen(mac) == 0 || strlen(mac) != 17)
188		buf[0] = 0;
189	else{
190		for(i = 0, j = 0; i < 17; ++i){
191			if(i%3 != 2){
192				buf[j] = mac[i];
193				++j;
194			}
195
196			buf[j] = 0;
197		}
198	}
199
200	return(buf);
201}
202// 2010.09 James. }
203
204//#if 0
205void wan_netmask_check(void)
206{
207	unsigned int ip, gw, nm, lip, lnm;
208
209	if (nvram_match("wan0_proto", "static") ||
210	    //nvram_match("wan0_proto", "pptp"))
211	    nvram_match("wan0_proto", "pptp") || nvram_match("wan0_proto", "l2tp"))	// oleg patch
212	{
213		ip = inet_addr(nvram_safe_get("wan_ipaddr"));
214		gw = inet_addr(nvram_safe_get("wan_gateway"));
215		nm = inet_addr(nvram_safe_get("wan_netmask"));
216
217		lip = inet_addr(nvram_safe_get("lan_ipaddr"));
218		lnm = inet_addr(nvram_safe_get("lan_netmask"));
219
220		_dprintf("ip : %x %x %x\n", ip, gw, nm);
221
222		if (ip==0x0 && (nvram_match("wan0_proto", "pptp") || nvram_match("wan0_proto", "l2tp")))	// oleg patch
223			return;
224
225		if (ip==0x0 || (ip&lnm)==(lip&lnm))
226		{
227			nvram_set("wan_ipaddr", "1.1.1.1");
228			nvram_set("wan_netmask", "255.0.0.0");
229			nvram_set("wan0_ipaddr", nvram_safe_get("wan_ipaddr"));
230			nvram_set("wan0_netmask", nvram_safe_get("wan_netmask"));
231		}
232
233		// check netmask here
234		if (gw==0 || gw==0xffffffff || (ip&nm)==(gw&nm))
235		{
236			nvram_set("wan0_netmask", nvram_safe_get("wan_netmask"));
237		}
238		else
239		{
240			for (nm=0xffffffff;nm!=0;nm=(nm>>8))
241			{
242				if ((ip&nm)==(gw&nm)) break;
243			}
244
245			_dprintf("nm: %x\n", nm);
246
247			if (nm==0xffffffff) nvram_set("wan0_netmask", "255.255.255.255");
248			else if (nm==0xffffff) nvram_set("wan0_netmask", "255.255.255.0");
249			else if (nm==0xffff) nvram_set("wan0_netmask", "255.255.0.0");
250			else if (nm==0xff) nvram_set("wan0_netmask", "255.0.0.0");
251			else nvram_set("wan0_netmask", "0.0.0.0");
252		}
253
254		nvram_set("wanx_ipaddr", nvram_safe_get("wan0_ipaddr"));	// oleg patch, he suggests to mark the following 3 lines
255		nvram_set("wanx_netmask", nvram_safe_get("wan0_netmask"));
256		nvram_set("wanx_gateway", nvram_safe_get("wan0_gateway"));
257	}
258}
259
260/*
261 * wanmessage
262 *
263 */
264void wanmessage(char *fmt, ...)
265{
266	va_list args;
267	char buf[512];
268
269	va_start(args, fmt);
270	vsnprintf(buf, sizeof(buf), fmt, args);
271	nvram_set("wan_reason_t", buf);
272	va_end(args);
273}
274
275int pppstatus(void)
276{
277	FILE *fp;
278	char sline[128], buf[128], *p;
279
280	if ((fp = fopen("/tmp/wanstatus.log", "r")) && fgets(sline, sizeof(sline), fp))
281	{
282		fcntl(fileno(fp), F_SETFL, fcntl(fileno(fp), F_GETFL) | O_NONBLOCK);
283		p = strstr(sline, ",");
284		strcpy(buf, p+1);
285	}
286	else
287	{
288		strcpy(buf, "unknown reason");
289	}
290
291	if(fp) fclose(fp);
292
293	if(strstr(buf, "Failed to authenticate ourselves to peer")) return WAN_STOPPED_REASON_PPP_AUTH_FAIL;
294	else if(strstr(buf, "Terminating connection due to lack of activity")) return WAN_STOPPED_REASON_PPP_LACK_ACTIVITY;
295	else if(strstr(buf, "No response from ISP.")) return WAN_STOPPED_REASON_PPP_NO_ACTIVITY;
296	else return WAN_STOPPED_REASON_NONE;
297}
298
299void usage_exit(const char *cmd, const char *help)
300{
301	fprintf(stderr, "Usage: %s %s\n", cmd, help);
302	exit(1);
303}
304
305#if 0 // replaced by #define in rc.h
306int modprobe(const char *mod)
307{
308#if 1
309	return eval("modprobe", "-s", (char *)mod);
310#else
311	int r = eval("modprobe", "-s", (char *)mod);
312	cprintf("modprobe %s = %d\n", mod, r);
313	return r;
314#endif
315}
316#endif // 0
317
318int modprobe_r(const char *mod)
319{
320#if 1
321	return eval("modprobe", "-r", (char *)mod);
322#else
323	int r = eval("modprobe", "-r", (char *)mod);
324	cprintf("modprobe -r %s = %d\n", mod, r);
325	return r;
326#endif
327}
328
329#ifndef ct_modprobe
330#ifdef LINUX26
331#define ct_modprobe(mod, args...) ({ \
332		modprobe("nf_conntrack_"mod, ## args); \
333		modprobe("nf_nat_"mod); \
334})
335#else
336#define ct_modprobe(mod, args...) ({ \
337		modprobe("ip_conntrack_"mod, ## args); \
338		modprobe("ip_nat_"mod, ## args); \
339})
340#endif
341#endif
342
343#ifndef ct_modprobe_r
344#ifdef LINUX26
345#define ct_modprobe_r(mod) ({ \
346	modprobe_r("nf_nat_"mod); \
347	modprobe_r("nf_conntrack_"mod); \
348})
349#else
350#define ct_modprobe_r(mod) ({ \
351	modprobe_r("ip_nat_"mod); \
352	modprobe_r("ip_conntrack_"mod); \
353})
354#endif
355#endif
356
357/*
358 * The various child job starting functions:
359 * _eval()
360 *	Start the child. If ppid param is NULL, wait until the child exits.
361 *	Otherwise, store the child's pid in ppid and return immediately.
362 * eval()
363 *	Call _eval with a NULL ppid, to wait for the child to exit.
364 * xstart()
365 *	Call _eval with a garbage ppid (to not wait), then return.
366 * runuserfile
367 *	Execute each executable in a directory that has the specified extention.
368 *	Call _eval with a ppid (to not wait), then check every second for the child's pid.
369 *	After wtime seconds or when the child has exited, return.
370 *	If any such filename has an '&' character in it, then do *not* wait at
371 *	all for the child to exit, regardless of the wtime.
372 */
373
374int _xstart(const char *cmd, ...)
375{
376	va_list ap;
377	char *argv[16];
378	int argc;
379	int pid;
380
381	argv[0] = (char *)cmd;
382	argc = 1;
383	va_start(ap, cmd);
384	while ((argv[argc++] = va_arg(ap, char *)) != NULL) {
385		//
386	}
387	va_end(ap);
388
389	return _eval(argv, NULL, 0, &pid);
390}
391
392static int endswith(const char *str, char *cmp)
393{
394	int cmp_len, str_len, i;
395
396	cmp_len = strlen(cmp);
397	str_len = strlen(str);
398	if (cmp_len > str_len)
399		return 0;
400	for (i = 0; i < cmp_len; i++) {
401		if (str[(str_len - 1) - i] != cmp[(cmp_len - 1) - i])
402			return 0;
403	}
404	return 1;
405}
406
407static void execute_with_maxwait(char *const argv[], int wtime)
408{
409	pid_t pid;
410
411	if (_eval(argv, NULL, 0, &pid) != 0)
412		pid = -1;
413	else {
414		while (wtime-- > 0) {
415			waitpid(pid, NULL, WNOHANG);	/* Reap the zombie if it has terminated. */
416			if (kill(pid, 0) != 0) break;
417			sleep(1);
418		}
419		_dprintf("%s killdon: errno: %d pid %d\n", argv[0], errno, pid);
420	}
421}
422
423/* This is a bit ugly. Why didn't they allow another parameter to filter???? */
424static char *filter_extension;
425static int endswith_filter(const struct dirent *entry)
426{
427	return endswith(entry->d_name, filter_extension);
428}
429
430/* If the filename has an '&' character in it, don't wait at all. */
431void run_userfile(char *folder, char *extension, const char *arg1, int wtime)
432{
433	unsigned char buf[PATH_MAX + 1];
434	char *argv[] = { (char *)buf, (char *)arg1, NULL };
435	struct dirent **namelist;
436	int i, n;
437
438	/* Do them in sorted order. */
439	filter_extension = extension;
440	n = scandir(folder, &namelist, endswith_filter, alphasort);
441	if (n >= 0) {
442		for (i = 0; i < n; ++i) {
443			sprintf((char *) buf, "%s/%s", folder, namelist[i]->d_name);
444			execute_with_maxwait(argv,
445				strchr(namelist[i]->d_name, '&') ? 0 : wtime);
446			free(namelist[i]);
447		}
448		free(namelist);
449	}
450}
451
452/* Run user-supplied script(s), with 1 argument.
453 * Return when the script(s) have finished,
454 * or after wtime seconds, even if they aren't finished.
455 *
456 * Extract NAME from nvram variable named as "script_NAME".
457 *
458 * The sole exception to the nvram item naming rule is sesx.
459 * That one is "sesx_script" rather than "script_sesx", due
460 * to historical accident.
461 *
462 * The other exception is time-scheduled commands.
463 * These have names that start with "sch_".
464 * No directories are searched for corresponding user scripts.
465 *
466 * Execute in this order:
467 *	nvram item: nv (run as a /bin/sh script)
468 *		(unless nv starts with a dot)
469 *	All files with a suffix of ".NAME" in these directories:
470 *	/etc/config/
471 *	/jffs/etc/config/
472 *	/opt/etc/config/
473 *	/mmc/etc/config/
474 *	/tmp/config/
475 */
476/*
477At this time, the names/events are:
478   (Unless otherwise noted, there are no parameters.  Otherwise, one parameter).
479   sesx		SES/AOSS Button custom script.  Param: ??
480   brau		"bridge/auto" button pushed.  Param: mode (bridge/auto/etc)
481   fire		When firewall service has been started or re-started.
482   shut		At system shutdown, just before wan/lan/usb/etc. are stopped.
483   init		At system startup, just before wan/lan/usb/etc. are started.
484		The root filesystem and /jffs are mounted, but not any USB devices.
485   usbmount	After an auto-mounted USB drive is mounted.
486   usbumount	Before an auto-mounted USB drive is unmounted.
487   usbhotplug	When any USB device is attached or removed.
488   wanup	After WAN has come up.
489   autostop	When a USB partition gets un-mounted.  Param: the mount-point (directory).
490		If unmounted from the GUI, the directory is still mounted and accessible.
491		If the USB drive was unplugged, it is still mounted but not accessible.
492
493User scripts -- no directories are searched.  One parameter.
494   autorun	When a USB disk partition gets auto-mounted. Param: the mount-point (directory).
495		But not if the partition was already mounted.
496		Only the files in that directory will be run.
497*/
498void run_nvscript(const char *nv, const char *arg1, int wtime)
499{
500	FILE *f;
501	char *script;
502	char s[PATH_MAX + 1];
503	char *argv[] = { s, (char *)arg1, NULL };
504	int check_dirs = 1;
505
506	if (nv[0] == '.') {
507		strcpy(s, nv);
508	}
509	else {
510		script = nvram_get(nv);
511
512		if ((script) && (*script != 0)) {
513			sprintf(s, "/tmp/%s.sh", nv);
514			if ((f = fopen(s, "w")) != NULL) {
515				fputs("#!/bin/sh\n", f);
516				fputs(script, f);
517				fputs("\n", f);
518				fclose(f);
519				chmod(s, 0700);
520				chdir("/tmp");
521
522				_dprintf("Running: '%s %s'\n", argv[0], argv[1]? argv[1]: "");
523				execute_with_maxwait(argv, wtime);
524				chdir("/");
525			}
526		}
527
528		sprintf(s, ".%s", nv);
529		if (strncmp("sch_c", nv, 5) == 0) {
530			check_dirs = 0;
531		}
532		else if (strncmp("sesx_", nv, 5) == 0) {
533			s[5] = 0;
534		}
535		else if (strncmp("script_", nv, 7) == 0) {
536			strcpy(&s[1], &nv[7]);
537		}
538	}
539
540	if (nvram_match("userfiles_disable", "1")) {
541		// backdoor to disable user scripts execution
542		check_dirs = 0;
543	}
544
545	if ((check_dirs) && strcmp(s, ".") != 0) {
546		_dprintf("checking for user scripts: '%s'\n", s);
547		run_userfile("/etc/config", s, arg1, wtime);
548		run_userfile("/jffs/etc/config", s, arg1, wtime);
549		run_userfile("/opt/etc/config", s, arg1, wtime);
550		run_userfile("/mmc/etc/config", s, arg1, wtime);
551		run_userfile("/tmp/config", s, arg1, wtime);
552	}
553}
554
555static void write_ct_timeout(const char *type, const char *name, unsigned int val)
556{
557	unsigned char buf[128];
558	char v[16];
559
560	sprintf((char *) buf, "/proc/sys/net/ipv4/netfilter/ip_conntrack_%s_timeout%s%s",
561		type, (name && name[0]) ? "_" : "", name ? name : "");
562	sprintf(v, "%u", val);
563
564	f_write_string((const char *) buf, v, 0, 0);
565}
566
567#ifndef write_tcp_timeout
568#define write_tcp_timeout(name, val) write_ct_timeout("tcp", name, val)
569#endif
570
571#ifndef write_udp_timeout
572#define write_udp_timeout(name, val) write_ct_timeout("udp", name, val)
573#endif
574
575static unsigned int read_ct_timeout(const char *type, const char *name)
576{
577	unsigned char buf[128];
578	unsigned int val = 0;
579	char v[16];
580
581	sprintf((char *) buf, "/proc/sys/net/ipv4/netfilter/ip_conntrack_%s_timeout%s%s",
582		type, (name && name[0]) ? "_" : "", name ? name : "");
583	if (f_read_string((const char *) buf, v, sizeof(v)) > 0)
584		val = atoi(v);
585
586	return val;
587}
588
589#ifndef read_tcp_timeout
590#define read_tcp_timeout(name) read_ct_timeout("tcp", name)
591#endif
592
593#ifndef read_udp_timeout
594#define read_udp_timeout(name) read_ct_timeout("udp", name)
595#endif
596
597
598void setup_ftp_conntrack(int port)
599{
600	char ports[32];
601
602	if(port>0&&port!=21)
603		sprintf(ports, "ports=21,%d", port);
604	else sprintf(ports, "ports=21");
605
606	if(!nvram_match("ftp_ports", ports))
607	{
608		ct_modprobe_r("ftp");
609		ct_modprobe("ftp", ports);
610		nvram_set("ftp_ports", ports);
611	}
612}
613
614void setup_udp_timeout(int connflag)
615{
616	unsigned int v[10];
617	const char *p;
618	char buf[70];
619
620	if (connflag
621#ifdef RTCONFIG_WIRELESSREPEATER
622			&& nvram_get_int("sw_mode")!=SW_MODE_REPEATER
623#endif
624	) {
625		p = nvram_safe_get("ct_udp_timeout");
626		if (sscanf(p, "%u%u", &v[0], &v[1]) == 2) {
627			write_udp_timeout(NULL, v[0]);
628			write_udp_timeout("stream", v[1]);
629		}
630		else {
631			v[0] = read_udp_timeout(NULL);
632			v[1] = read_udp_timeout("stream");
633			sprintf(buf, "%u %u", v[0], v[1]);
634			nvram_set("ct_udp_timeout", buf);
635		}
636	}
637	else {
638		write_udp_timeout(NULL, 1);
639		write_udp_timeout("stream", 6);
640	}
641}
642
643int scan_icmp_unreplied_conntrack()
644{
645	FILE *fp = fopen( "/proc/net/nf_conntrack", "r" );
646	char buff[1024], ipv[16], ipv_num[16], protocol[16], protocol_num[16];
647	int found = 0;
648
649	if (fp == NULL) {
650		perror( "openning /proc/net/nf_conntrack" );
651		return -1;
652	}
653
654	while (fgets(buff, sizeof(buff), fp) != NULL) {
655		sscanf(buff, "%s %s %s %s", ipv, ipv_num, protocol, protocol_num);
656
657		if (memcmp(protocol, "icmp", 4) || !strstr(buff, "UNREPLIED")) continue;
658
659//		dbG("\n%s %s %s %s\n", ipv, ipv_num, protocol, protocol_num);
660
661		found++;
662		break;
663	}
664
665	fclose(fp);
666
667//	if (!found)
668//		dbG("No matching conntrack found\n");
669
670	return found;
671}
672
673void setup_ct_timeout(int connflag)
674{
675	unsigned int v[10];
676	const char *p;
677	char buf[70];
678	int i;
679
680	if (connflag
681#ifdef RTCONFIG_WIRELESSREPEATER
682			&& nvram_get_int("sw_mode")!=SW_MODE_REPEATER
683#endif
684	) {
685		p = nvram_safe_get("ct_timeout");
686		if (sscanf(p, "%u%u", &v[0], &v[1]) == 2) {
687//			write_ct_timeout("generic", NULL, v[0]);
688			write_ct_timeout("icmp", NULL, v[1]);
689		}
690		else {
691			v[0] = read_ct_timeout("generic", NULL);
692			v[1] = read_ct_timeout("icmp", NULL);
693
694			sprintf(buf, "%u %u", v[0], v[1]);
695			nvram_set("ct_timeout", buf);
696		}
697	}
698	else {
699		for (i = 0; i < 3; i++)
700		{
701			if (scan_icmp_unreplied_conntrack() > 0)
702			{
703//				write_ct_timeout("generic", NULL, 0);
704				write_ct_timeout("icmp", NULL, 0);
705				sleep(2);
706			}
707		}
708	}
709}
710
711void setup_conntrack(void)
712{
713	unsigned int v[10];
714	const char *p;
715	char buf[70];
716	int i;
717
718	p = nvram_safe_get("ct_tcp_timeout");
719	if (sscanf(p, "%u%u%u%u%u%u%u%u%u%u",
720		&v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]) == 10) {	// lightly verify
721		write_tcp_timeout("established", v[1]);
722		write_tcp_timeout("syn_sent", v[2]);
723		write_tcp_timeout("syn_recv", v[3]);
724		write_tcp_timeout("fin_wait", v[4]);
725		write_tcp_timeout("time_wait", v[5]);
726		write_tcp_timeout("close", v[6]);
727		write_tcp_timeout("close_wait", v[7]);
728		write_tcp_timeout("last_ack", v[8]);
729	}
730	else {
731		v[1] = read_tcp_timeout("established");
732		v[2] = read_tcp_timeout("syn_sent");
733		v[3] = read_tcp_timeout("syn_recv");
734		v[4] = read_tcp_timeout("fin_wait");
735		v[5] = read_tcp_timeout("time_wait");
736		v[6] = read_tcp_timeout("close");
737		v[7] = read_tcp_timeout("close_wait");
738		v[8] = read_tcp_timeout("last_ack");
739		sprintf(buf, "0 %u %u %u %u %u %u %u %u 0",
740			v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]);
741		nvram_set("ct_tcp_timeout", buf);
742	}
743
744	setup_udp_timeout(FALSE);
745
746	p = nvram_safe_get("ct_timeout");
747	if (sscanf(p, "%u%u", &v[0], &v[1]) == 2) {
748//		write_ct_timeout("generic", NULL, v[0]);
749		write_ct_timeout("icmp", NULL, v[1]);
750	}
751	else {
752		v[0] = read_ct_timeout("generic", NULL);
753		v[1] = read_ct_timeout("icmp", NULL);
754		sprintf(buf, "%u %u", v[0], v[1]);
755		nvram_set("ct_timeout", buf);
756	}
757
758#ifdef LINUX26
759	p = nvram_safe_get("ct_hashsize");
760	i = atoi(p);
761	if (i >= 127) {
762		f_write_string("/sys/module/nf_conntrack/parameters/hashsize", p, 0, 0);
763	}
764	else if (f_read_string("/sys/module/nf_conntrack/parameters/hashsize", buf, sizeof(buf)) > 0) {
765		if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
766		if (atoi(buf) > 0) nvram_set("ct_hashsize", buf);
767	}
768#endif
769#ifdef LINUX26
770	p = nvram_safe_get("ct_max");
771	i = atoi(p);
772	if (i >= 128) {
773		f_write_string("/proc/sys/net/nf_conntrack_max", p, 0, 0);
774	}
775	else if (f_read_string("/proc/sys/net/nf_conntrack_max", buf, sizeof(buf)) > 0) {
776		if (atoi(buf) > 0) nvram_set("ct_max", buf);
777	}
778#else
779	p = nvram_safe_get("ct_max");
780	i = atoi(p);
781	if (i >= 128) {
782		f_write_string("/proc/sys/net/ipv4/netfilter/ip_conntrack_max", p, 0, 0);
783	}
784	else if (f_read_string("/proc/sys/net/ipv4/netfilter/ip_conntrack_max", buf, sizeof(buf)) > 0) {
785		if (atoi(buf) > 0) nvram_set("ct_max", buf);
786	}
787#endif
788#if 0
789	if (!nvram_match("nf_rtsp", "0")) {
790		ct_modprobe("rtsp");
791	}
792	else {
793		ct_modprobe_r("rtsp");
794	}
795
796	if (!nvram_match("nf_h323", "0")) {
797		ct_modprobe("h323");
798	}
799	else {
800		ct_modprobe_r("h323");
801	}
802
803#ifdef LINUX26
804	if (!nvram_match("nf_sip", "0")) {
805		ct_modprobe("sip");
806	}
807	else {
808		ct_modprobe_r("sip");
809	}
810#endif
811#endif
812	// !!TB - FTP Server
813#ifdef RTCONFIG_FTP
814	i = nvram_get_int("ftp_port");
815	if (nvram_match("ftp_enable", "1") && (i > 0) && (i != 21))
816	{
817		char ports[32];
818
819		sprintf(ports, "ports=21,%d", i);
820		ct_modprobe("ftp", ports);
821	}
822	else
823#endif
824	if (!nvram_match("nf_ftp", "0")
825#ifdef RTCONFIG_FTP
826		|| nvram_match("ftp_enable", "1")	// !!TB - FTP Server
827#endif
828		) {
829		ct_modprobe("ftp");
830	}
831	else {
832		ct_modprobe_r("ftp");
833	}
834
835	if (!nvram_match("nf_pptp", "0")) {
836		ct_modprobe("proto_gre");
837		ct_modprobe("pptp");
838	}
839	else {
840		ct_modprobe_r("pptp");
841		ct_modprobe_r("proto_gre");
842	}
843}
844
845void setup_pt_conntrack(void)
846{
847	if (!nvram_match("fw_pt_rtsp", "0")) {
848		ct_modprobe("rtsp", "ports=554,8554");
849	}
850	else {
851		ct_modprobe_r("rtsp");
852	}
853
854	if (!nvram_match("fw_pt_h323", "0")) {
855		ct_modprobe("h323");
856	}
857	else {
858		ct_modprobe_r("h323");
859	}
860
861#ifdef LINUX26
862	if (!nvram_match("fw_pt_sip", "0")) {
863		ct_modprobe("sip");
864	}
865	else {
866		ct_modprobe_r("sip");
867	}
868#endif
869}
870
871void remove_conntrack(void)
872{
873	ct_modprobe_r("pptp");
874	ct_modprobe_r("ftp");
875	ct_modprobe_r("rtsp");
876	ct_modprobe_r("h323");
877#ifdef LINUX26
878	ct_modprobe_r("sip");
879#endif
880}
881
882void inc_mac(char *mac, int plus)
883{
884	unsigned char m[6];
885	int i;
886
887	for (i = 0; i < 6; i++)
888		m[i] = (unsigned char) strtol(mac + (3 * i), (char **)NULL, 16);
889	while (plus != 0) {
890		for (i = 5; i >= 3; --i) {
891			m[i] += (plus < 0) ? -1 : 1;
892			if (m[i] != 0) break;	// continue if rolled over
893		}
894		plus += (plus < 0) ? 1 : -1;
895	}
896	sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X",
897		m[0], m[1], m[2], m[3], m[4], m[5]);
898}
899
900void set_mac(const char *ifname, const char *nvname, int plus)
901{
902	int sfd;
903	struct ifreq ifr;
904	int up;
905	int j;
906	char *et_hwaddr = NULL;
907
908	if ((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
909		_dprintf("%s: %s %d\n", ifname, __FUNCTION__, __LINE__);
910		return;
911	}
912
913	strcpy(ifr.ifr_name, ifname);
914
915	up = 0;
916	if (ioctl(sfd, SIOCGIFFLAGS, &ifr) == 0) {
917		if ((up = ifr.ifr_flags & IFF_UP) != 0) {
918			ifr.ifr_flags &= ~IFF_UP;
919			if (ioctl(sfd, SIOCSIFFLAGS, &ifr) != 0) {
920				_dprintf("%s: %s %d\n", ifname, __FUNCTION__, __LINE__);
921			}
922		}
923	}
924	else {
925		_dprintf("%s: %s %d\n", ifname, __FUNCTION__, __LINE__);
926	}
927#ifdef RTCONFIG_RGMII_BRCM5301X
928	et_hwaddr = nvram_safe_get("lan_hwaddr");
929#elif defined(RTCONFIG_GMAC3)
930	if (nvram_match("gmac3_enable", "1"))
931		et_hwaddr = nvram_safe_get("et2macaddr");
932	else
933		et_hwaddr = nvram_safe_get("et0macaddr");
934#else
935	et_hwaddr = nvram_safe_get("et0macaddr");
936#endif
937
938	if (!ether_atoe(nvram_safe_get(nvname), (unsigned char *)&ifr.ifr_hwaddr.sa_data)) {
939		if (!ether_atoe(et_hwaddr, (unsigned char *)&ifr.ifr_hwaddr.sa_data)) {
940
941			// goofy et0macaddr, make something up
942#ifdef RTCONFIG_RGMII_BRCM5301X
943			nvram_set("lan_hwaddr", "00:01:23:45:67:89");
944#elif defined(RTCONFIG_GMAC3)
945			if (nvram_match("gmac3_enable", "1"))
946				nvram_set("et2macaddr", "00:01:23:45:67:89");
947			else
948				nvram_set("et0macaddr", "00:01:23:45:67:89");
949#else
950			nvram_set("et0macaddr", "00:01:23:45:67:89");
951#endif
952			ifr.ifr_hwaddr.sa_data[0] = 0;
953			ifr.ifr_hwaddr.sa_data[1] = 0x01;
954			ifr.ifr_hwaddr.sa_data[2] = 0x23;
955			ifr.ifr_hwaddr.sa_data[3] = 0x45;
956			ifr.ifr_hwaddr.sa_data[4] = 0x67;
957			ifr.ifr_hwaddr.sa_data[5] = 0x89;
958		}
959
960		while (plus-- > 0) {
961			for (j = 5; j >= 3; --j) {
962				ifr.ifr_hwaddr.sa_data[j]++;
963				if (ifr.ifr_hwaddr.sa_data[j] != 0) break;	// continue if rolled over
964			}
965		}
966	}
967
968	ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
969	if (ioctl(sfd, SIOCSIFHWADDR, &ifr) == -1) {
970		_dprintf("Error setting %s address\n", ifname);
971	}
972
973	if (up) {
974		if (ioctl(sfd, SIOCGIFFLAGS, &ifr) == 0) {
975			ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
976			if (ioctl(sfd, SIOCSIFFLAGS, &ifr) == -1) {
977				_dprintf("%s: %s %d\n", ifname, __FUNCTION__, __LINE__);
978			}
979		}
980		else {
981			_dprintf("%s: %s %d\n", ifname, __FUNCTION__, __LINE__);
982		}
983	}
984
985	close(sfd);
986}
987
988/*
989const char *default_wanif(void)
990{
991	return ((strtoul(nvram_safe_get("boardflags"), NULL, 0) & BFL_ENETVLAN) ||
992		(check_hw_type() == HW_BCM4712)) ? "vlan1" : "eth1";
993}
994*/
995
996/*
997const char *default_wlif(void)
998{
999	switch (check_hw_type()) {
1000	case HW_BCM4702:
1001	case HW_BCM4704_BCM5325F:
1002	case HW_BCM4704_BCM5325F_EWC:
1003		return "eth2";
1004	}
1005	return "eth1";
1006
1007}
1008*/
1009
1010void simple_unlock(const char *name)
1011{
1012	char fn[256];
1013
1014	snprintf(fn, sizeof(fn), "/var/lock/%s.lock", name);
1015	f_write(fn, NULL, 0, 0, 0600);
1016}
1017
1018void simple_lock(const char *name)
1019{
1020	int n;
1021	char fn[256];
1022
1023	n = 5 + (getpid() % 10);
1024	snprintf(fn, sizeof(fn), "/var/lock/%s.lock", name);
1025	while (unlink(fn) != 0) {
1026		if (--n == 0) {
1027			syslog(LOG_DEBUG, "Breaking %s", fn);
1028			break;
1029		}
1030		sleep(1);
1031	}
1032}
1033
1034void killall_tk(const char *name)
1035{
1036	int n;
1037
1038	if (killall(name, SIGTERM) == 0) {
1039		n = 10;
1040		while ((killall(name, 0) == 0) && (n-- > 0)) {
1041			_dprintf("%s: waiting name=%s n=%d\n", __FUNCTION__, name, n);
1042			usleep(100 * 1000);
1043		}
1044		if (n < 0) {
1045			n = 10;
1046			while ((killall(name, SIGKILL) == 0) && (n-- > 0)) {
1047				_dprintf("%s: SIGKILL name=%s n=%d\n", __FUNCTION__, name, n);
1048				usleep(100 * 1000);
1049			}
1050		}
1051	}
1052}
1053
1054void kill_pidfile_tk(const char *pidfile)
1055{
1056	FILE *fp;
1057	char buf[256];
1058	pid_t pid = 0;
1059	int n;
1060
1061	if ((fp = fopen(pidfile, "r")) != NULL) {
1062		if (fgets(buf, sizeof(buf), fp) != NULL)
1063			pid = strtoul(buf, NULL, 0);
1064		fclose(fp);
1065	}
1066
1067	if (pid > 1 && kill(pid, SIGTERM) == 0) {
1068		n = 10;
1069		while ((kill(pid, 0) == 0) && (n-- > 0)) {
1070			_dprintf("%s: waiting pid=%d n=%d\n", __FUNCTION__, pid, n);
1071			usleep(100 * 1000);
1072		}
1073		if (n < 0) {
1074			n = 10;
1075			while ((kill(pid, SIGKILL) == 0) && (n-- > 0)) {
1076				_dprintf("%s: SIGKILL pid=%d n=%d\n", __FUNCTION__, pid, n);
1077				usleep(100 * 1000);
1078			}
1079		}
1080	}
1081}
1082
1083long fappend(FILE *out, const char *fname)
1084{
1085	FILE *in;
1086	char buf[1024];
1087	int n;
1088	long r;
1089
1090	if ((in = fopen(fname, "r")) == NULL) return -1;
1091	r = 0;
1092	while ((n = fread(buf, 1, sizeof(buf), in)) > 0) {
1093		if (fwrite(buf, 1, n, out) != n) {
1094			r = -1;
1095			break;
1096		}
1097		else {
1098			r += n;
1099		}
1100	}
1101	fclose(in);
1102	return r;
1103}
1104
1105long fappend_file(const char *path, const char *fname)
1106{
1107	FILE *f;
1108	int r = -1;
1109
1110	if (f_exists(fname) && (f = fopen(path, "a")) != NULL) {
1111		r = fappend(f, fname);
1112		fclose(f);
1113	}
1114	return r;
1115}
1116
1117/* uclibc accepts any of following:
1118 * [STD][Offset][DST], where
1119 * [STD] ~ any [a-zA-Z]
1120 * [DST] ~ any [a-zA-Z] */
1121#define CONVERT_TZ_TO_GMT_DST
1122#ifdef CONVERT_TZ_TO_GMT_DST
1123int gettzoffset(char *tzstr, char *tzstr1, int size1)
1124{
1125	char offstr[32];
1126	char *tzptr = tzstr;
1127	char *offptr = offstr;
1128	int ret = 0;
1129	int dst = 0;
1130
1131	memset(offstr, 0, sizeof(offstr));
1132	for ( ; *tzptr; tzptr++) {
1133		if (*tzptr=='-'||*tzptr=='+'||*tzptr==':'||isdigit(*tzptr)) {
1134			*offptr++ = *tzptr;
1135			ret = 1;
1136		} else if (ret) {
1137			dst = isalpha(*tzptr);
1138			break;
1139		}
1140	}
1141
1142	if (ret)
1143		snprintf(tzstr1, size1, "GMT%s%s", offstr, dst ? "DST" : "");
1144	return ret;
1145}
1146#endif
1147
1148void time_zone_x_mapping(void)
1149{
1150	FILE *fp;
1151	char tmpstr[32];
1152	char *ptr;
1153
1154	/* pre mapping */
1155	if (nvram_match("time_zone", "KST-9KDT"))
1156		nvram_set("time_zone", "UCT-9_1");
1157	else if (nvram_match("time_zone", "RFT-9RFTDST"))
1158		nvram_set("time_zone", "UCT-9_2");
1159	else if (nvram_match("time_zone", "UTC-2DST_1"))	/*Minsk*/
1160		nvram_set("time_zone", "UTC-3_3");
1161	else if (nvram_match("time_zone", "UTC-4_2"))		/*Moscow, St. Petersburg*/
1162		nvram_set("time_zone", "UTC-3_4");
1163	else if (nvram_match("time_zone", "UTC-4_3"))		/*Volgograd*/
1164		nvram_set("time_zone", "UTC-3_5");
1165	else if (nvram_match("time_zone", "UTC-6_1"))		/*Yekaterinburg*/
1166		nvram_set("time_zone", "UTC-5_1");
1167	else if (nvram_match("time_zone", "UTC-7_1"))		/*Novosibirsk*/
1168		nvram_set("time_zone", "UTC-6_2");
1169	else if (nvram_match("time_zone", "CST-8_2"))		/*Krasnoyarsk*/
1170		nvram_set("time_zone", "CST-7_2");
1171	else if (nvram_match("time_zone", "UTC-9_2"))		/*Irkutsk*/
1172		nvram_set("time_zone", "UTC-8_1");
1173	else if (nvram_match("time_zone", "UTC-10_3"))		/*Yakutsk*/
1174		nvram_set("time_zone", "UTC-9_3");
1175	else if (nvram_match("time_zone", "UTC-11_2"))		/*Vladivostok*/
1176		nvram_set("time_zone", "UTC-10_4");
1177	else if (nvram_match("time_zone", "UTC-12_1"))          /*Magadan*/
1178		nvram_set("time_zone", "UTC-10_5");
1179
1180	snprintf(tmpstr, sizeof(tmpstr), "%s", nvram_safe_get("time_zone"));
1181	/* replace . with : */
1182	while ((ptr=strchr(tmpstr, '.'))!=NULL) *ptr = ':';
1183	/* remove *_? */
1184	while ((ptr=strchr(tmpstr, '_'))!=NULL) *ptr = 0x0;
1185
1186	/* check time_zone_dst for daylight saving */
1187	if (nvram_get_int("time_zone_dst"))
1188		sprintf(tmpstr, "%s,%s", tmpstr, nvram_safe_get("time_zone_dstoff"));
1189#ifdef CONVERT_TZ_TO_GMT_DST
1190	else	gettzoffset(tmpstr, tmpstr, sizeof(tmpstr));
1191#endif
1192
1193	nvram_set("time_zone_x", tmpstr);
1194
1195	/* special mapping */
1196	if (nvram_match("time_zone", "JST"))
1197		nvram_set("time_zone_x", "UCT-9");
1198#if 0
1199	else if (nvram_match("time_zone", "TST-10TDT"))
1200		nvram_set("time_zone_x", "UCT-10");
1201	else if (nvram_match("time_zone", "CST-9:30CDT"))
1202		nvram_set("time_zone_x", "UCT-9:30");
1203#endif
1204
1205	if ((fp = fopen("/etc/TZ", "w")) != NULL) {
1206		fprintf(fp, "%s\n", tmpstr);
1207		fclose(fp);
1208	}
1209}
1210
1211/* Get the timezone from NVRAM and set the timezone in the kernel
1212 * and export the TZ variable
1213 */
1214void
1215setup_timezone(void)
1216{
1217#ifndef RC_BUILDTIME
1218#define RC_BUILDTIME	1438387200	// Aug 1 00:00:00 GMT 2015
1219#endif
1220	time_t now;
1221	struct tm gm, local;
1222	struct timezone tz;
1223	struct timeval tv = { RC_BUILDTIME, 0 };
1224	struct timeval *tvp = NULL;
1225
1226	/* Export TZ variable for the time libraries to
1227	 * use.
1228	 */
1229	time_zone_x_mapping();
1230	setenv("TZ", nvram_get("time_zone_x"), 1);
1231
1232	/* Update kernel timezone */
1233	time(&now);
1234	gmtime_r(&now, &gm);
1235	localtime_r(&now, &local);
1236	gm.tm_isdst = local.tm_isdst;
1237	tz.tz_minuteswest = (mktime(&gm) - mktime(&local)) / 60;
1238
1239	/* Setup sane start time */
1240	if (now < RC_BUILDTIME) {
1241		struct sysinfo info;
1242
1243		sysinfo(&info);
1244		tv.tv_sec += info.uptime;
1245		tvp = &tv;
1246	}
1247
1248	settimeofday(tvp, &tz);
1249}
1250
1251int
1252is_invalid_char_for_hostname(char c)
1253{
1254	int ret = 0;
1255
1256	if (c < 0x20)
1257		ret = 1;
1258#if 0
1259	else if (c >= 0x21 && c <= 0x2c)	/* !"#$%&'()*+, */
1260		ret = 1;
1261#else	/* allow '+' */
1262	else if (c >= 0x21 && c <= 0x2a)	/* !"#$%&'()* */
1263		ret = 1;
1264	else if (c == 0x2c)			/* , */
1265		ret = 1;
1266#endif
1267	else if (c >= 0x2e && c <= 0x2f)	/* ./ */
1268		ret = 1;
1269	else if (c >= 0x3a && c <= 0x40)	/* :;<=>?@ */
1270		ret = 1;
1271#if 0
1272	else if (c >= 0x5b && c <= 0x60)	/* [\]^_ */
1273		ret = 1;
1274#else	/* allow '_' */
1275	else if (c >= 0x5b && c <= 0x5e)	/* [\]^ */
1276		ret = 1;
1277	else if (c == 0x60)			/* ` */
1278		ret = 1;
1279#endif
1280	else if (c >= 0x7b)			/* {|}~ DEL */
1281		ret = 1;
1282#if 0
1283	printf("%c (0x%02x) is %svalid for hostname\n", c, c, (ret == 0) ? "  " : "in");
1284#endif
1285	return ret;
1286}
1287
1288int
1289is_valid_hostname(const char *name)
1290{
1291	int len, i;
1292
1293	if (!name)
1294		return 0;
1295
1296	len = strlen(name);
1297	for (i = 0; i < len ; i++) {
1298		if (is_invalid_char_for_hostname(name[i])) {
1299			len = 0;
1300			break;
1301		}
1302	}
1303#if 0
1304	printf("%s is %svalid for hostname\n", name, len ? "" : "in");
1305#endif
1306	return len;
1307}
1308
1309int get_meminfo_item(const char *name)
1310{
1311	FILE *fp;
1312	char memdata[256] = {0};
1313	int mem = 0;
1314
1315	if (!name || *name == '\0')
1316		return -1;
1317
1318	if ((fp = fopen("/proc/meminfo", "r")) != NULL) {
1319		/* get one memory parameter specified by the name */
1320		while (fgets(memdata, 255, fp) != NULL) {
1321			if (strstr(memdata, name) != NULL) {
1322				sscanf(memdata, "%*s %d kB", &mem);
1323				break;
1324			}
1325		}
1326		fclose(fp);
1327	}
1328
1329	return mem;
1330}
1331
1332#ifdef RTCONFIG_SHP
1333void restart_lfp()
1334{
1335	char v[32];
1336
1337	if(nvram_get_int("lfp_disable")==0) {
1338		sprintf(v, "%x", inet_addr(nvram_safe_get("lan_ipaddr")));
1339		f_write_string("/proc/net/lfpctrl", v, 0, 0);
1340	}
1341	else {
1342		f_write_string("/proc/net/lfpctrl", "", 0, 0);
1343	}
1344}
1345#endif
1346
1347#ifdef CONFIG_BCMWL5
1348int setup_dnsmq(int mode)
1349{
1350	char v[32];
1351	char tmp[32];
1352
1353	if(mode) {
1354		// setup ebtables
1355		eval("ebtables", "-F");
1356		eval("ebtables", "-t", "broute", "-F");
1357		eval("ebtables", "-t", "broute", "-I", "BROUTING", "-d", "00:E0:11:22:33:44", "-j", "redirect", "--redirect-target", "DROP");
1358	}
1359	else {
1360		eval("ebtables", "-F");
1361		eval("ebtables", "-t", "broute", "-F");
1362		eval("ebtables", "-I", "FORWARD", "-i", "eth1", "-j", "DROP");
1363	}
1364
1365	eval("iptables", "-t", "nat", "-F", "PREROUTING");
1366	eval("iptables", "-t", "nat", "-I", "PREROUTING", "-p", "udp", "--dport", "53",
1367		"-j", "DNAT", "--to-destination", strcat_r(nvram_safe_get("lan_ipaddr"), ":18018", tmp));
1368
1369	if(mode) {
1370#if defined(RTCONFIG_BCMWL6) && defined(RTCONFIG_PROXYSTA)
1371		if (!is_psta(nvram_get_int("wlc_band")) && !is_psr(nvram_get_int("wlc_band")))
1372#endif
1373		snprintf(tmp, sizeof(tmp), "%s:%d", nvram_safe_get("lan_ipaddr"), /*nvram_get_int("http_lanport") ? :*/ 80);
1374		eval("iptables", "-t", "nat", "-I", "PREROUTING", "-p", "tcp", "-d", "10.0.0.1", "--dport", "80",
1375			"-j", "DNAT", "--to-destination", tmp);
1376
1377		//sprintf(v, "%x my.%s", inet_addr("10.0.0.1"), get_productid());
1378		sprintf(v, "%x %s", inet_addr(nvram_safe_get("lan_ipaddr")), DUT_DOMAIN_NAME);
1379		f_write_string("/proc/net/dnsmqctrl", v, 0, 0);
1380	}
1381	else {
1382		// setup ebtables and iptables
1383#if defined(RTCONFIG_BCMWL6) && defined(RTCONFIG_PROXYSTA)
1384		if (!is_psta(nvram_get_int("wlc_band")) && !is_psr(nvram_get_int("wlc_band")))
1385#endif
1386		eval("iptables", "-t", "nat", "-I", "PREROUTING", "-p", "tcp", "-d", "10.0.0.1", "--dport", "80",
1387			"-j", "DNAT", "--to-destination", strcat_r(nvram_safe_get("lan_ipaddr"), ":18017", tmp));
1388
1389		f_write_string("/proc/net/dnsmqctrl", "", 0, 0);
1390	}
1391
1392	return 0;
1393}
1394#endif
1395
1396void stop_if_misc(void)
1397{
1398	DIR *dir;
1399	struct dirent *dirent;
1400	struct ifreq ifr;
1401	int sfd;
1402
1403	if ((dir = opendir("/proc/sys/net/ipv4/conf")) != NULL) {
1404		while ((dirent = readdir(dir)) != NULL) {
1405			if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, ".."))
1406				continue;
1407
1408			if (strcmp(dirent->d_name, "all") &&
1409				strcmp(dirent->d_name, "default") &&
1410				strcmp(dirent->d_name, "lo") &&
1411				strncmp(dirent->d_name, "br", 2) &&
1412				strncmp(dirent->d_name, "eth", 3) &&
1413				strncmp(dirent->d_name, "ra", 2) &&
1414				!((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0))
1415			{
1416				strcpy(ifr.ifr_name, dirent->d_name);
1417				if (!ioctl(sfd, SIOCGIFFLAGS, &ifr) && (ifr.ifr_flags & IFF_UP))
1418					ifconfig(ifr.ifr_name, 0, NULL, NULL);
1419
1420				close(sfd);
1421			}
1422
1423		}
1424		closedir(dir);
1425	}
1426}
1427
1428int mssid_mac_validate(const char *macaddr)
1429{
1430	unsigned char mac_binary[6];
1431	unsigned long long macvalue;
1432	char macbuf[13];
1433
1434	if (!macaddr || !strlen(macaddr))
1435		return 0;
1436
1437	ether_atoe(macaddr, mac_binary);
1438	sprintf(macbuf, "%02X%02X%02X%02X%02X%02X",
1439		mac_binary[0],
1440		mac_binary[1],
1441		mac_binary[2],
1442		mac_binary[3],
1443		mac_binary[4],
1444		mac_binary[5]);
1445	macvalue = strtoll(macbuf, (char **) NULL, 16);
1446	if (macvalue % 4)
1447		return 0;
1448	else
1449		return 1;
1450}
1451