双网卡同网段, 监测网卡连接

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;
}

原文地址:https://www.cnblogs.com/cute/p/2090894.html