[RealTek8197FH 3414b]route和ap(bridge)的自适应切换实现

本示例实现了控制有线网口灯,无线网络灯和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 * ) &current_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
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值