本示例实现了控制有线网口灯,无线网络灯和reset按键的使能,并且可以自适应切换route和ap模式,代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdbool.h>
#include <unistd.h>
///
/// 宏定义常量区 ///
///
#define MAX_PORT_NUM 5
#define DEFAULT_WAN_PORT 3
#define CKECK_WAIT_TIME 15
#define MAX_MSG_BUFFER_SIZE 256
#define SIGUSR1 10
#define _SC_OPEN_MAX 4
#define MIB_OP_MODE 192
#define RTF_UP 0x0001
#define RTF_GATEWAY 0x0002
#define NET_CARD "eth1"
#define _PATH_PROCNET_ROUTE "/proc/net/route"
#define _PATH_PROCNET_PORT "/proc/rtl865x/port_status"
#define CMD_IFCONFIG "ifconfig"
#define _DHCPD_PID_PATH "/var/run"
#define _DHCPD_PROG_NAME "udhcpd"
#define _CONFIG_SCRIPT_PROG "init.sh"
///
/// 类型定义区 /
///
typedef enum
{
HW_SETTING = 1,
DEFAULT_SETTING = 2,
CURRENT_SETTING = 4,
#ifdef CUSTOMER_HW_SETTING_SUPPORT
CUSTOMER_HW_SETTING = 8,
#endif
#ifdef RF_DPK_SETTING_SUPPORT
RF_DPK_SETTING = 16,
#endif /* RF_DPK_SETTING_SUPPORT */
#ifdef BLUETOOTH_HW_SETTING_SUPPORT
BLUETOOTH_HW_SETTING = 64,
#endif
END_OF_SETTING = 4096
} CONFIG_DATA_T;
typedef enum _op_mode_e
{
GATEWAY_MODE = 0,
BRIDGE_MODE = 1,
WISP_MODE = 2
} OPMODE_T;
typedef enum _mode_e
{
ROUTE,
AP,
} MODE;
typedef enum _port_link_status
{
LINK_ERROR,
LINK_UP,
LINK_DOWN,
LINK_UNDEF = 0xff,
} PORT_LINK_STATUS;
typedef struct _port_s
{
unsigned char port_number;
PORT_LINK_STATUS port_status;
} PORT;
///
/// 宏定义函数定义区 ///
///
#define console(fmt, ...) \
do \
{ \
printf("[%s~%04d] " fmt, __func__, __LINE__, ##__VA_ARGS__); \
} while(0)
#define CREATE_WLAN_LED_GPIO_DEVICE \
do \
{ \
if ( system( "echo 33 > /sys/class/gpio/export" ) == -1 ) \
console( "init wan led gpio failed !\n" ); \
if ( system( "echo out > /sys/class/gpio/gpio33/direction" ) == -1 ) \
console( "GPIO enable failed !\n" ); \
if ( system( "echo 1 > /sys/class/gpio/gpio33/value" ) == -1 ) \
console( "close wan led failed !\n" ); \
} while(0)
#define CREATE_NET_LED_GPIO_DEVICE \
do \
{ \
if ( system( "echo 57 > /sys/class/gpio/export" ) == -1 ) \
console( "init wan led gpio failed !\n" ); \
if ( system( "echo out > /sys/class/gpio/gpio57/direction" ) == -1 ) \
console( "GPIO enable failed !\n" ); \
if ( system( "echo 1 > /sys/class/gpio/gpio57/value" ) == -1 ) \
console( "close wan led failed !\n" ); \
} while(0)
#define CREATE_RESET_GPIO_DEVICE \
do \
{ \
if ( system( "echo 54 > /sys/class/gpio/export" ) == -1 ) \
console( "init reset gpio failed !\n" ); \
if ( system( "echo in > /sys/class/gpio/gpio54/direction" ) == -1 ) \
console( "GPIO 54 enable failed !\n" ); \
} while(0)
#define SET_NET_LED( flag ) \
do \
{\
if ( flag == 1 ) \
{ \
if ( system( "echo 0 > /sys/class/gpio/gpio57/value" ) == -1 ) \
console( "open net led failed !\n" ); \
} \
else \
{ \
if ( system( "echo 1 > /sys/class/gpio/gpio57/value" ) == -1 ) \
console( "close net led failed !\n" ); \
} \
} while(0)
#define SET_WLAN_LED( flag ) \
do \
{ \
if ( flag == 1 ) \
{ \
if ( system( "echo 0 > /sys/class/gpio/gpio33/value" ) == -1 ) \
console( "open wlan led failed !\n" ); \
} \
else \
{ \
if ( system( "echo 1 > /sys/class/gpio/gpio33/value" ) == -1 ) \
console( "close wlan led failed !\n" ); \
} \
} while(0)
///
/ 函数声明区 ///
///
extern int apmib_get( int id, void *value );
extern int apmib_set( int id, void *value );
static void portCheckProcess();
static inline int get_phy_port_status( PORT *info );
static inline int get_br0_net_status();
static void modeSwitching();
void extractIPAddress( const char *input, char *output, size_t output_size );
bool containsIPAddress( const char *data, const char *ipAddress );
static int get_default_route( char *interface, unsigned long *route );
int getPid( char *filename );
void killSomeDaemon( void );
void run_init_script( char *arg );
static void DOCMD( const char *format, ... );
static inline void waitSonFork( pid_t pid );
///
全局静态变量定义区 /
///
static PORT port[MAX_PORT_NUM];
///
/ 函数定义区 ///
///
int main()
{
console( "start init wired cable led...\n" );
CREATE_WLAN_LED_GPIO_DEVICE;
console( "start init wireless led...\n" );
CREATE_NET_LED_GPIO_DEVICE;
SET_WLAN_LED( 1 );
console( "start init reset listen...\n" );
CREATE_RESET_GPIO_DEVICE;
console( "start fork new process...\n" );
pid_t pid = fork();
if ( pid < 0 )
{
console( "fork failed" );
exit( 1 );
}
// 子进程
else if ( pid == 0 )
{
console( "child process create success, PID is %d\n", getpid() );
portCheckProcess();
}
else
{
waitSonFork(pid);
}
return 0;
}
static inline void waitSonFork( pid_t pid )
{
// 父进程循环等待子进程结束
while ( 1 )
{
int status;
pid_t result = waitpid( pid, &status, WNOHANG );
if ( result == 0 )
{
// 子进程还在运行
sleep( 1 );
}
else if ( result == -1 )
{
// 发生错误
console( "waitpid failed\n" );
break;
}
else
{
// 子进程已结束
console( "child process %d terminated with status %d\n", pid, status );
break;
}
}
}
static void DOCMD( const char *format, ... )
{
char cmd[1024];
va_list args;
memset( cmd, 0, sizeof( cmd ) );
va_start( args, format );
vsnprintf( cmd, sizeof( cmd ), format, args );
va_end( args );
if ( system( cmd ) == -1 )
return;
}
static void portCheckProcess()
{
unsigned char i;
static PORT_LINK_STATUS last_status = LINK_UNDEF;
console( "start listen port 2.\n" );
while ( 1 )
{
for ( i = 0; i < MAX_PORT_NUM; i++ )
{
port[i].port_number = i;
get_phy_port_status( &port[i] );
}
if ( ( port[2].port_status != LINK_UP ) && ( port[3].port_status != LINK_UP ) )
SET_NET_LED( 0 );
else
SET_NET_LED( 1 );
console( "port[2]'status=%d, last port'status=%d\n", port[2].port_status, last_status );
if ( ( port[2].port_status != last_status && port[2].port_status == LINK_UP ) || ( last_status == LINK_UNDEF ) )
{
last_status = port[2].port_status;
console( "Forking a new process.\n" );
pid_t pid = fork();
if ( pid < 0 )
continue;
else if ( pid == 0 )
{
console( "child process create success, PID is %d\n", getpid() );
modeSwitching();
}
else
{
waitSonFork(pid);
}
}
usleep( 1 * 1000 * 1000 );
}
}
static inline int get_phy_port_status( PORT *info )
{
FILE *fh;
int found_port = 0;
char cur_port[12];
unsigned char buffer[128];
memset( cur_port, 0, 12 );
sprintf( cur_port, "Port%d", info->port_number );
fh = fopen( _PATH_PROCNET_PORT, "r" );
if ( !fh )
{
console( "cannot open %s\n", _PATH_PROCNET_PORT );
return -1;
}
while ( fgets( buffer, 128, fh ) )
{
//console( "buffer=%s, cur_port=%s\n", buffer, cur_port );
if ( strncmp( buffer, cur_port, strlen( cur_port ) ) == 0 )
found_port = 1;
if ( found_port )
if ( strstr( buffer, "Link" ) )
{
if ( buffer[4] == 'U' )
info->port_status = LINK_UP;
else if ( buffer[4] == 'D' )
info->port_status = LINK_DOWN;
else
info->port_status = LINK_ERROR;
break;
}
}
//console( "port[%d]'s status= %d\n", port->port_number, port->port_status );
fclose( fh );
return 0;
}
static inline int get_br0_net_status()
{
char ifconfig_output[4096];
char buffer[64];
FILE *fp;
fp = popen( "ifconfig", "r" );
if ( fp == NULL )
{
perror( "popen failed" );
return 0;
}
ifconfig_output[0] = '\0';
while ( fgets( buffer, sizeof( buffer ), fp ) != NULL )
strncat( ifconfig_output, buffer, sizeof( ifconfig_output ) - strlen( ifconfig_output ) - 1 );
if ( pclose( fp ) == -1 )
{
perror( "pclose failed" );
return 0;
}
fp = popen( "flash get IP_ADDR", "r" );
if ( fp == NULL )
{
perror( "popen failed" );
return 0;
}
char ip_address[16];
while ( fgets( buffer, sizeof( buffer ), fp ) != NULL )
{
extractIPAddress( buffer, ip_address, sizeof( ip_address ) );
console( "Extracted IP address: %s\n", ip_address );
if ( containsIPAddress( ifconfig_output, ip_address ) )
{
console( "The IP address %s is found in the network data.\n", ip_address );
return 1;
}
else
{
console( "The IP address %s is not found in the network data.\n", ip_address );
return 0;
}
}
if ( pclose( fp ) == -1 )
perror( "pclose failed" );
}
static void modeSwitching()
{
unsigned int status;
unsigned char i, count = 1;
MODE current_mode = ROUTE;
while ( 1 )
{
apmib_get( MIB_OP_MODE, ( void * ) ¤t_mode );
console( "current_mode=%d\n", current_mode );
if ( current_mode == ROUTE )
{
console( "port[2].port_status=%d\n", port[2].port_status );
if ( port[2].port_status == LINK_UP )
{
for ( ;; )
{
usleep( 1 * 1000 * 1000 );
if ( count++ >= 15 )
{
status = 2;
break;
}
unsigned long ip_addr_hex = 0;
if ( get_default_route( NET_CARD, &ip_addr_hex ) )
{
console( "ip_addr_hex=0x%x\n", ip_addr_hex );
status = 1;
break;
}
else
continue;
}
}
else
status = 2;
if ( status == 1 )
usleep( 3 * 1000 * 1000 );
else if ( status == 2 )
{
OPMODE_T tmp = BRIDGE_MODE;
apmib_set( MIB_OP_MODE, ( void * ) &tmp );
apmib_update( CURRENT_SETTING );
run_init_script( "all" );
DOCMD( "flash set DHCP 1" );
}
}
else if ( current_mode == AP )
{
if ( !get_br0_net_status() )
{
get_phy_port_status( &port[2] );
if ( port[2].port_status == LINK_UP )
status = 1;
else
status = 2;
}
else
status = 2;
if ( status == 1 )
{
OPMODE_T tmp = GATEWAY_MODE;
apmib_set( MIB_OP_MODE, ( void * ) &tmp );
apmib_update( CURRENT_SETTING );
run_init_script( "all" );
DOCMD( "flash set DHCP 2" );
break;
}
else if ( status == 2 )
usleep( 3 * 1000 * 1000 );
}
}
exit( 1 );
}
void extractIPAddress( const char *input, char *output, size_t output_size )
{
const char *key = "IP_ADDR=";
const char *start = strstr( input, key );
if ( start != NULL )
{
start += strlen( key );
const char *end = strpbrk( start, " \t\n\r" );
if ( end == NULL )
end = start + strlen( start );
size_t length = end - start;
if ( length >= output_size )
length = output_size - 1;
strncpy( output, start, length );
output[length] = '\0';
}
else
output[0] = '\0';
}
bool containsIPAddress( const char *data, const char *ipAddress )
{
const char *line = data;
const char *nextLine;
while ( ( nextLine = strchr( line, '\n' ) ) != NULL )
{
unsigned int lineLength = nextLine - line;
char currentLine[lineLength + 1];
strncpy( currentLine, line, lineLength );
currentLine[lineLength] = '\0';
if ( strstr( currentLine, ipAddress ) != NULL )
return true;
line = nextLine + 1;
}
if ( strstr( line, ipAddress ) != NULL )
return true;
return false;
}
static int get_default_route( char *interface, unsigned long *route )
{
unsigned long addr;
char buff[1024], iface[16], *fmt, gate_addr[128], net_addr[128], mask_addr[128];
int num, iflags, metric, refcnt, use, mss, window, irtt;
FILE *fp = fopen( _PATH_PROCNET_ROUTE, "r" );
if ( !fp )
{
console( "Open %s file error.\n", _PATH_PROCNET_ROUTE );
return 0;
}
fmt = "%16s %128s %128s %X %d %d %d %128s %d %d %d";
while ( fgets( buff, 1023, fp ) )
{
num = sscanf( buff, fmt, iface, net_addr, gate_addr, &iflags, &refcnt, &use, &metric, mask_addr, &mss, &window, &irtt );
if ( num < 10 || !( iflags &RTF_UP ) || !( iflags &RTF_GATEWAY ) || strcmp( iface, interface ) )
continue;
sscanf( gate_addr, "%lx", &addr );
*route = addr;
break;
}
fclose( fp );
return 1;
}
int getPid( char *filename )
{
struct stat status;
char buff[100];
FILE *fp;
if ( stat( filename, &status ) < 0 )
return -1;
fp = fopen( filename, "r" );
if ( !fp )
{
fprintf( stderr, "Read pid file error!\n" );
return -1;
}
fgets( buff, 100, fp );
fclose( fp );
return ( atoi( buff ) );
}
void killSomeDaemon( void )
{
system( "killall -9 sleep 2> /dev/null" );
system( "killall -9 routed 2> /dev/null" );
system( "killall -9 dnrd 2> /dev/null" );
system( "killall -9 ntpclient 2> /dev/null" );
system( "killall -9 lld2d 2> /dev/null" );
system( "killall -9 iapp 2> /dev/null" );
system( "killall -9 wscd 2> /dev/null" );
system( "killall -9 mini_upnpd 2> /dev/null" );
system( "killall -9 iwcontrol 2> /dev/null" );
system( "killall -9 auth 2> /dev/null" );
system( "killall -9 disc_server 2> /dev/null" );
system( "killall -9 igmpproxy 2> /dev/null" );
system( "killall -9 syslogd 2> /dev/null" );
system( "killall -9 klogd 2> /dev/null" );
system( "killall -9 ppp_inet 2> /dev/null" );
#ifdef VOIP_SUPPORT
system( "killall -9 snmpd 2> /dev/null" );
system( "killall -9 solar_monitor 2> /dev/null" );
system( "killall -9 solar 2> /dev/null" );
system( "killall -9 dns_task 2> /dev/null" );
system( "killall -9 ivrserver 2> /dev/null" );
#endif
#ifdef CONFIG_SNMP
system( "killall -9 snmpd 2> /dev/null" );
#endif
}
void run_init_script( char *arg )
{
#ifdef NO_ACTION
// do nothing
#else
int pid = 0;
int i;
char tmpBuf[MAX_MSG_BUFFER_SIZE] = {0};
#ifdef REBOOT_CHECK
if ( run_init_script_flag == 1 )
{
#endif
#ifdef RTK_MESH_CONFIG
#define RTK_CAPWAP_UI_CONFIG_FILE "/tmp/capwap_config"
FILE *file = NULL;
char cmd[100];
int capwapMode, sleep_count = 0, val = 1;
apmib_get( MIB_CAPWAP_MODE, ( void * ) &capwapMode );
if ( capwapMode &CAPWAP_AUTO_CONFIG_ENABLE )
{
sprintf( cmd, "echo 1 > %s", RTK_CAPWAP_UI_CONFIG_FILE );
system( cmd );
pid = find_pid_by_name( "WTP" );
if ( pid > 0 )
{
kill( pid, SIGUSR1 );
console( "Send SIGUSR1 signal to WTP\n" );
while ( val && sleep_count <= 5 )
{
sleep( 1 );
sleep_count++;
file = fopen( RTK_CAPWAP_UI_CONFIG_FILE, "r" );
char tmpbuf[10] = {0};
if ( file )
{
fgets( tmpbuf, 10, file );
val = atoi( tmpbuf );
fclose( file );
}
}
}
else
console( "WTP cannot be found...\n" );
console( "<%s>%d: capwapMode=%d count=%d\n", __FUNCTION__, __LINE__, capwapMode, sleep_count );
}
#endif
#ifdef RTK_USB3G
system( "killall -9 mnet 2> /dev/null" );
system( "killall -9 hub-ctrl 2> /dev/null" );
system( "killall -9 usb_modeswitch 2> /dev/null" );
system( "killall -9 ppp_inet 2> /dev/null" );
system( "killall -9 pppd 2> /dev/null" );
system( "rm /etc/ppp/connectfile >/dev/null 2>&1" );
#endif /* #ifdef RTK_USB3G */
#if defined(CONFIG_DOMAIN_NAME_QUERY_SUPPORT)
Stop_Domain_Query_Process();
Reset_Domain_Query_Setting();
#endif
#if defined(CONFIG_RTL_ULINKER)
{
extern int kill_ppp( void );
int wan_mode, op_mode;
apmib_get( MIB_OP_MODE, ( void * ) &op_mode );
apmib_get( MIB_WAN_DHCP, ( void * ) &wan_mode );
if ( wan_mode == PPPOE && op_mode == GATEWAY_MODE )
kill_ppp();
stop_dhcpc();
stop_dhcpd();
clean_auto_dhcp_flag();
disable_bridge_dhcp_filter();
}
#endif
snprintf( tmpBuf, MAX_MSG_BUFFER_SIZE, "%s/%s.pid", _DHCPD_PID_PATH, _DHCPD_PROG_NAME );
pid = getPid( tmpBuf );
if ( pid > 0 )
kill( pid, SIGUSR1 );
usleep( 1000 );
if ( pid > 0 )
{
system( "killall -9 udhcpd 2> /dev/null" );
system( "rm -f /var/run/udhcpd.pid 2> /dev/null" );
}
killSomeDaemon();
system( "killsh.sh" ); // kill all running script
#ifdef CONFIG_IPV6
system( "ip tunnel del tun 2> /dev/null" );
#ifdef CONFIG_DSLITE_SUPPORT
system( "ip -6 tunnel del ds-lite 2> /dev/null" ); // delete ds-lite tunnel
system( "rm -f /var/ds-lite.script 2> /dev/null" );
#endif
#ifdef CONFIG_SIXRD_SUPPORT
system( "ip tunnel del tun6rd 2> /dev/null" );
#endif
#endif
#ifdef REBOOT_CHECK
run_init_script_flag = 0;
needReboot = 0;
#endif
// added by rock /
#ifdef VOIP_SUPPORT
web_restart_solar();
#endif
pid = fork();
if ( pid == 0 )
{
#ifdef HOME_GATEWAY
sprintf( tmpBuf, "%s gw %s", _CONFIG_SCRIPT_PROG, arg );
#elif defined(VOIP_SUPPORT) && defined(ATA867x)
sprintf( tmpBuf, "%s ATA867x %s", _CONFIG_SCRIPT_PROG, arg );
#else
sprintf( tmpBuf, "%s ap %s", _CONFIG_SCRIPT_PROG, arg );
#endif
for ( i = 3; i < sysconf( _SC_OPEN_MAX ); i++ )
close( i );
sleep( 1 );
system( tmpBuf );
exit( 1 );
}
#ifdef REBOOT_CHECK
}
else
{
}
#endif
#endif
}