IFF_UP 和 IFF_RUNNING 的差別在哪?就實際功用而言,兩者都代表了網路裝置是否正常啟用,但是更仔細觀察可以發現拔除網路線時會造成 IFF_RUNNING 的改變,至於 IFF_UP 不會因插拔網路線而有任何變化

 

 

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

#include <sys/ioctl.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <string.h>

#include <fcntl.h>

#include <errno.h>

#include <sys/types.h>

#include <linux/if.h>

#include <linux/sockios.h>

#include <linux/ethtool.h>

#define SLEEP_TIME (1000*1000)

typedef struct nic_t

{

    char if_name[5];

    int status;

    int old_status;

}nic;

void init_daemon(void);

int get_netlink_status(const char *if_name);

void auto_up_down_eth(nic* pnic);

void auto_route_eth(nic* pnic);

void init_nic(nic* pnic, const char* if_name)

{

    memset(pnic, 0, sizeof(nic));

    strcpy(pnic->if_name, if_name);

}

int main(int argc, char* argv[])

{

    init_daemon();

    if(getuid() != 0)

    {

        fprintf(stderr, "Netlink Status Check Need Root Power.\n");

        return 1;

    }

    nic eth[2];

    init_nic(&eth[0], "eth0");

    init_nic(&eth[1], "eth1");

    while(1)

    {

        auto_up_down_eth(eth);

        auto_up_down_eth(eth+1);

        //auto_route_eth(eth);

        //auto_route_eth(eth+1);

        //get_netlink_status("eth1");

        usleep(SLEEP_TIME);

    }

    return 0;

}

#define IFCONFIG_CMD "ifconfig %s %s"

void ifconfig_cmd(const char* if_name, int up_down)

{

    char cmd[48];

    sprintf(cmd, IFCONFIG_CMD, if_name, up_down==1?"up":"down");

    system(cmd);

}

#define LINK_UP "up"

#define LINK_DOWN "down"

void auto_up_down_eth(nic* pnic)

{

    pnic->status = get_netlink_status(pnic->if_name);

    if(pnic->status!=pnic->old_status)

    {

        printf("%s Net link status: %s\n", pnic->if_name, pnic->status==1?"up":"down");

        ifconfig_cmd(pnic->if_name, pnic->status);

        pnic->old_status = pnic->status;

    }

}

#define ROUTE_DEL_CMD "route del -net %s netmask %s dev %s"

//route del -net 192.168.3.0 netmask 255.255.255.0 dev eth1

void route_del_cmd(const char* if_name, int up_down)

{

    char cmd[48];

    sprintf(cmd, "./delroute.sh %s", if_name);

    if(up_down!=1)

    {

        system(cmd);

    }

}

void auto_route_eth(nic* pnic)

{

    pnic->status = get_netlink_status(pnic->if_name);

    if(pnic->status!=pnic->old_status)

    {

        printf("%s Net link status: %s\n", pnic->if_name, pnic->status==1?"up":"down");

        route_del_cmd(pnic->if_name, pnic->status);

        pnic->old_status = pnic->status;

    }

}

// if_name like "ath0", "eth0". Notice: call this function

// need root privilege.

// return value:

// -1 -- error , details can check errno

// 1 -- interface link up

// 0 -- interface link down.

#if 1

int get_netlink_status(const char *if_name)

{

    int skfd;

    struct ifreq ifr;

    struct ethtool_value edata;

    edata.cmd = ETHTOOL_GLINK;

    edata.data = 0;

    memset(&ifr, 0, sizeof(ifr));

    strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name) - 1);

    ifr.ifr_data = (char *) &edata;

    if (( skfd = socket( AF_INET, SOCK_DGRAM, 0 )) == 0)

        return -1;

    if(ioctl( skfd, SIOCETHTOOL, &ifr ) == -1)

    {

        close(skfd);

        return -1;

    }

    close(skfd);

    return edata.data;

}

#else

int get_netlink_status(const char *if_name)

{

    struct ifreq ifr;

    int sockfd;

    int ret = 0;

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    bzero(&ifr, sizeof(ifr));

    strcpy(ifr.ifr_name, if_name);

    ioctl(sockfd, SIOCGIFFLAGS, &ifr);

    /*

     ifr_flags 的各項旗標和說明:

         IFF_UP              裝置正在運作

         IFF_BROADCAST       有效的廣播位址

         IFF_DEBUG           Debug 標誌

         IFF_LOOPBACK        這是 Loopback 裝置

         IFF_POINTOPOINT     這是點到點的網路裝置介面

         IFF_RUNNING         資源已分配

         IFF_NOARP           無arp協議,沒有設置第二層目的地址

         IFF_PROMISC         介面為雜湊(promiscuous)模式

         IFF_NOTRAILERS      避免使用 trailer

         IFF_ALLMULTI        接收所有群組廣播(multicast)封包資料

         IFF_MASTER          主負載平衡群(bundle)

         IFF_SLAVE           從負載平衡群(bundle)

         IFF_MULTICAST       支持群組廣播(multicast)

         IFF_PORTSEL         可以通過 ifmap 選擇 media 類型

         IFF_AUTOMEDIA       自動選擇 media

         IFF_DYNAMIC         裝置介面關閉時丟棄地址

    */

    if (ifr.ifr_flags & IFF_UP)

    {

        printf("%s is IFF_UP!\n", if_name);

        ret = 1;

    }

    else

    {

        printf("%s is !IFF_UP!\n", if_name);

        ret = 0;

    }

    if (ifr.ifr_flags & IFF_RUNNING)

    {

        printf("%s is IFF_RUNNING!\n", if_name);

    }

    else

    {

        printf("%s is !IFF_RUNNING!\n", if_name);

    }

    close(sockfd);

    return ret;

}

#endif

#include <unistd.h>

#include <signal.h>

#include <sys/param.h>

#include <sys/types.h>

#include <sys/stat.h>

void init_daemon(void)

{

int pid;

int i;

if(pid=fork())

exit(0);//是父进程,结束父进程

else if(pid< 0)

exit(1);//fork失败,退出

//是第一子进程,后台继续执行

setsid();//第一子进程成为新的会话组长和进程组长

//并与控制终端分离

if(pid=fork())

exit(0);//是第一子进程,结束第一子进程

else if(pid< 0)

exit(1);//fork失败,退出

//是第二子进程,继续

//第二子进程不再是会话组长

for(i=0;i< NOFILE;++i)//关闭打开的文件描述符

close(i);

//linzhming add:这个我们不需要

chdir("/tmp");//改变工作目录到/tmp

umask(0);//重设文件创建掩模

return;

}