linux 网络管理与开发

各种接品网络接口函数与结构体:
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain,int type,int protocol);
int bind(int socket,const struct sockaddr*address,size_t address_len);
int listen(int socket,int backlog);
int accept(int socket,struct sockaddr*address,size_t*address_len);
int connect(int socket,const struct sockaddr*address,size_t address_len);
fcntl();
struct sockaddr_un{               //sys/un.h
     sa_family_t      sun_family;            //AF_UNIX
     char                    sun_path[];   //108字节 路径名
}

struct sockaddr_in{          //netinet/in.h          
     short int                  sin_family; 地址族
     unsigned short int      sin_port;  端口号
     struct in_addr           sin_addr{unsigned long int s_addr};  以太网地址(32位无符号整数,8位表示点分十进制)
}
struct sockaddr{
     sa_family_t      sa_family;  协议族                  192.168.1.0
     char                 sa_data[14];  协议地址 sa_data = "\000\000\300\250\001\000\000\000\000\000\000\000\000"}
}
struct in_addr{
     unsigned long int      s_addr;      // in_addr_t
}

主机字节与网络字节序转换:
unsinged long int htonl(unsigned long int hostlong);
unsinged short int htons(unsigned short int hostshort);
unsinged long int nhohl(unsigned long int netlong);
unsigned short int ntohs(unsigned short int netshort);

#include <netdb.h>
struct hostent *gethostbyaddr(void*addr,size_t len,int type);
struct hostent *gethostbyname(char*name);
struct hostent{
     char*h_name;          //主机名
     char**h_aliases
     int h_addrtype;     //地址类型
     int h_length;               //地址长度
     char**h_addr_list;  //地址(网络字节序)
}

struct servent *getservbyname(char*name,char*proto);
struct servent *getservbyport(int port,char*proto);
struct servent{
     char*s_name;     //服务名
     char**s_aliases;
     int s_port;          //端口号
     char*s_proto;  //服务类型,tcp ,udp
}

#include <arpa/inet.h>
#include <netinet/in.h>
char *inet_ntoa(struct in_addr in);            //整数到 IP字符串
in_addr_t inet_addr(char*cp);                  //IP字符串到整数    
int inet_aton(const char* cp,struct in_addr *inp);  // 

#include <unistd.h>
int gethostname(char*name,int namelength);


#include <sys/types.h>
#include <ifaddrs.h>
int getifaddrs(struct ifaddrs**ifap);
void freeifaddrs(struct ifaddrs*ifa);
struct ifaddrs{         
          struct ifaddrs     *ifa_next;          //下一条记录
          char                         *ifa_name;     //接口名
          unsigned int          ifa_flags;    标志 从SIOCGIFFLAGS
          struct sockaddr *ifa_addr;     地址
          struct sockaddr *ifa_netmask;     子网掩码
          union{
               struct sockaddr *ifu_broadaddr; //组播地址
               struct sockaddr *ifu_dstaddr;    //点到点目的地址
          }ifa_ifu;
     #define     ifa_broadaddr  ifa_ifu.ifu_broadaddr
     #define    ifa_dstaddr           ifa_ifu.ifu_dstaddr
     void *ifa_data         
}



#include<sys/ioctl.h>
#include <net/if.h>
struct ifreq{     //网络接口请求
          char ifr_name[IFNAMSIZ]; //接口名     SIOCSIFNAME
          union{                                                                 设置                              获取
               struct sockaddr ifr_addr;                    //SIOCSIFADDR               SIOCGIFADDR
               struct sockaddr ifr_dstaddr;          //SIOCSIFDSTADDR   SIOCGIFDSTADDR
               struct sockaddr ifr_broadaddr;     //SIOCSIFBRDADDR   SIOCGIFBRDADDR
               struct sockaddr ifr_netmask;          //SIOCSIFNETMASK    SIOCGIFNETMASK
               sturct sockaddr ifr_hwaddr;          //SIOCSIFHWADDR     SIOCGIFHWADDR
               short                    ifr_flags;        //SIOCSIFFLAGS    SIOCGIFFLAGS   
                                                                  IFF_UP = 0x1,               /* Interface is up.  */
                                                                  IFF_BROADCAST = 0x2,        /* Broadcast address valid.  */
                                                                  IFF_DEBUG = 0x4,            /* Turn on debugging.  */
                                                                  IFF_LOOPBACK = 0x8,         /* Is a loopback net.  */
                                                                  IFF_POINTOPOINT = 0x10,     /* Interface is point-to-point link.  */
                                                                  IFF_NOTRAILERS = 0x20,      /* Avoid use of trailers.  */
                                                                  IFF_RUNNING = 0x40,         /* Resources allocated.  */
                                                                  IFF_NOARP = 0x80,           /* No address resolution protocol.  */
                                                                  IFF_PROMISC = 0x100,        /* Receive all packets.  */
                                                                     /* Not supported */
                                                                  IFF_ALLMULTI = 0x200,       /* Receive all multicast packets.  */
                                                                  IFF_MASTER = 0x400,         /* Master of a load balancer.  */
                                                                  IFF_SLAVE = 0x800,          /* Slave of a load balancer.  */
                                                                  IFF_MULTICAST = 0x1000,     /* Supports multicast.  */
                                                                  IFF_PORTSEL = 0x2000,       /* Can set media type.  */
                                                                  IFF_AUTOMEDIA = 0x4000,     /* Auto media select active.  */
                                                               IFF_DYNAMIC = 0x8000        /* Dialup device with changing addresses.  */                                                                                                                                           
               int                          ifr_ifindex;            //SIOCGIFINDEX    
               int                          ifr_metric;            //SIOCSIFMETRIC     SIOCGIFMETRIC
               int                          ifr_mtu;               //SIOCSIFMTU          SIOCGIFMTU
               struct ifmap          ifr_map;
               char                     ifr_slave[IFNAMSIZ];
               char                         ifr_newname[IFNAMSIZ];
               char                     *ifr_data;                //SKEEPALIVE  SIOCETHTOOL(此时ifr_data指向ethtool_cmd)
               };
     } 
     struct ifconf{  //网络接口配置          //SIOCGIFCONF
          int     ifc_len;   //buffer大小
          union{
                    char     *ifc_buf; //buffer地址
                    struct ifreq     *ifc_req; //结构数组
          }
     }    
     struct ifmap{     //网卡设备的映射属性
          unsigned long mem_start;//开始地址
          unsigned long mem_end;//结束地址
          unsigned short base_addr;//基地址
          unsigned char irq;//中断号
          unsigned char dma;//DMA
          unsigned char port;//端口
     }
    
     struct ethtool_cmd{               //ethtool.h
          __u32     cmd;
          __u32     supported;    //接口支持类型
          __u32     advertising;
          __u16     speed;          //接口速率 低位
          __u8       duplex;           //half 或 full 单双工,全双工
          __u8       port;           //端口类型
          __u8       phy_address;  //物理地址
          __u8       transceiver;   //收发器类型
          __u8      autoneg;         //使能或禁止 自动协商
          __u8      mdio_support;
          __u32     maxtxpkt;
          __u32     maxrxpkt;
          __u16     speed_hi;   //接口速率 高位
          __u8     eth_tp_mdix;
          __u8     eth_tp_mdix_ctrl;
          __u32     lp_advertising;
          __u32     reserved[2];   
     }
     
路由设备:

     SIOCADDRT     增加路由
     SIOCDELRT   删除路由
     struct rtentry{               // include <net/route.h>
          unsigned     long int rt_pad1;
          struct sockaddr rt_dst;               // target address目标地址,     struct sockaddr_in
          struct sockaddr rt_gateway;     //gateway address  网关
          struct sockaddr rt_genmask;   // target address mask  目标地址掩码
          unsigned short int rt_flags;         标志 // RTF_UP 0x0001     RTF_HOST 0X0004
          short int rt_pad2;                              // RTF_GATEWAY 0x0002
          unsigned     long int rt_pad3;
          unsigned char rt_tos;
          unsigned char rt_class;
          #if __WORDSIZE == 64
               short int rt_pad4[3];
          #else
               short int rt_pad4;
          #endif
               short int rt_metric;                /* +1 for binary compatibility!  */
               char *rt_dev;                       /* Forcing the device at add. 指定网络设备  */
               unsigned long int rt_mtu;           /* Per route MTU/Window.  */
               unsigned long int rt_window;        /* Window clamping.  */
               unsigned short int rt_irtt;         /* Initial RTT.  */
     };
     route add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.1.1
     void setroute(){
          char rt_buf[sizeof(struct rtentry)];
          struct rtentry *const rt=(void*)rt_buf;
          memset(rt,0,sizeoft(rt));
          rt->rt_dst=
                         s_in->sin_family = AF_INET;
                         s_in->sin_port = 0;
                         inet_aton(name, &s_in->sin_addr)
          rt->rt_flags=     RTF_UP(net)  RTF_HOST(host)  RTF_GATEWAY(gw)
                             
          rt->rt_genmask=
                   
          rt->rt_gateway=  or  rt->rt_dev=
          ioctl(skfd,SIOCADDRT,rt);
          ioctl(skfd,SIOCDELRT,rt);
     }
     route del default(0.0.0.0) gw 192.168.1.1          //删除默认网关
     route del -net 192.168.1.0/24 -->route del -net 192.168.1.0 netmask 255.255.255.0
     route add default gw 192.168.1.1     -->route add -net 0.0.0.0 netmask 0.0.0.0 gw 192.168.1.1          //添加默认网关         
     route add default dev eth0  --> route add -net 0.0.0.0 netmask 0.0.0.0 dev eth0
     route del -net 192.168.1.0/24 dev eth0  
          -net 网络路由
          -host 主机路由 : 去往某个主机地址时通过哪 个接口
          route add -host 192.168.1.98 dev eth2 
          route del -host 192.168.1.98 dev eth2
     
ping: unknown host www.baidu.com  ==> /etc/resolv.conf   nameserver 192.168.1.1
   connect: network is unreachable          ==> route add default gw 192.168.1.1
                                 route del default gw 192.168.1.1;route add default gw 192.168.1.1

创建bond设备:
          a.加载驱动模块。modprobe bonding ,网卡驱动。
          b,指定bond设备ip地址。ifconfig bond0 <ip addr> netmask <mask> broadcast <bcast>
          c,添加网络接口到bond设备。 ifenslave -f bond0 eth0 [eht1 ...]
    
          d,关闭bond设备,自动释放所有从网络接口
               ifconfig bond0 down
              
          e,移除一个已死亡的网络接口,而不关闭bond设备
               ifenslave -d bond0 eth0[eth1 ...]          //
         
          f, 更改激活的从接口
               ifenslave -c bond0 eth0        //
         
          g,显示bond设备信息
               ifenslave bond0
          h,显示所有接口的信息
               ifenslave -a                    //
         
          创建bond通过sysfs:
          1,     echo +bond2 > /sys/class/net/bonding_master
                  创建bond2
                       echo 6 > /sys/class/net/bond2/bonding/mode
                              设置模式
                              echo 100 >/sys/class/net/bond2/bonding/miimon
                              设置miimon时间
          3,ifconfig bond2  192.168.1.99    (此时网络可以通,在加入slave之前)
          2,ifconfig eth1 down ;  echo +eth1 > /sys/class/net/bond2/bonding/slave
                 加入从接口          (会创建/sys/class/net/eth0/master-->/sys/class/net/bond2)

                
               echo -eth1 > sys/class/net/bond2/bonding/slave; ifconfig eth1 up
                    删除从接口,
               
    
     例:
     echo balance-alb > /sys/class/net/bond0/bonding/mode
               balance-rr or 0     :循环模式
               active-backup or 1     :主备模式
               balance-xor or 2     :哈希散列
               broadcast or 3 :广播模式
               802.3ad or 4
               balance-tlb or 5     :自适应发送负载均衡
               balance-alb or 6:自适应负载均衡(发送与接收)
              
     ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up
     echo 100 > /sys/class/net/bond0/bonding/miimon
     echo +eth0 > /sys/class/net/bond0/bonding/slaves
     echo +eth1 > /sys/class/net/bond0/bonding/slaves
    
  网络配置文件:
     /etc/hosts:   主机名解析
     /etc/hostname: 主机名  (hostnamectl )
               (有三种类型的主机名,1,pretty显示时主机名,2,statics系统启动时的静态主机名,3,DHCP服务器分配的主机名)          
通过sysconfig 文件配置网络接口:
     在/etc/sysconfig/目录中是配置文件和脚本的位置。大多数网络配置信息存储在那里,除了VPN ,移动宽带和PPPoE的配置,
它们存放在/etc/NetworkManager/下。
     例如:接口的具体配置信息,存储在/etc/sysconfig/network-scripts/目录下ifcfg文件中。
     /etc/sysconfig/network 是一个全局配置文件。
     VPN ,移动宽带和PPPoE的配置存在/etc/NetworkManager/system-connections/中。
    
     在RedHat 7中,当你修改ifcfg文件后,NetworkManager不会自动察觉,并提示发现改变。
     如果你使用工具来更新NetworkManager的配置,NetworkManager也不会让它生效直到你重新使用配置文件连接。
     例:如果配置文件修改了,需要通知NetworkManager重新读取配置文件。你可以执行:
               nmcli connection reload
               这个命令读取所有配置文件。相对的,为了只重新加载变化的ifcfg-ifname文件:
               nmcli  con load ifcfg-ifname
               这个命令接受多个文件名。
              
     使用工具如nmcli更改不需要重新加载但需要相关的接口先down 再up。
          如:nmcli dev disconnect eth1
          nmcli con up eth1
          这个命令需要root 权限,关于更多权限与优先级详参见Administrator's Guide and the su(1) and sudo(8) man pages.
         
     NetworkManager 不会触发任何网络脚本,虽然网络脚本会尝试触发它运行的NetworkManager,如果使用ifup命令。
     ifup脚本是一个通用的脚本,做很少的事情,然后调用ifup - ethX,ifup-wireliss,ifup-ppp等接口特定的脚本。
当用户运行手动执行ifup eth0时,会发生以下情况:
     1,ifup查找文件/etc/syconfig/network-scripts/ifcfg-eth0;
     2,如ifcfg 文件存在,ifup在文件中查找TYPER的key来决定调用那种相关的脚本。
     3,ifup 调用ifup-wireless 或ifup-eth 或ifup-xxx基于TYPE.
     4,相关类型的脚本做相关类型的设置;
     5,最后,相关类型的脚本,让常用功能执行IP相关任务,如DHCP或静态IP设置。
    
     在启动时,/etc/init.d/network读取所有的ifcfg文件,然后查找所有ONBOOT=yes,
     并检查NetworkManager是否启动了这个ifcfg 相关的设备。如果启动了,就什么也不做。
     如果还没启动,初始化脚本会继续其传统的行为,并为ifcfg文件调用ifup。
    
     最终,ONBOOT=yes的ifcfg文件会在系统启动时启动,无论是被NetworkManager或initscripts初始化脚本。
     这确保了NetworkManager不能处理的一些传统网络类型(如ISDN或dialup modems),仍能被initscripts初始化脚本处理。
    
    

NetworkManager:网络管理守护进程
           NetworkManager的守护进程试图使网络配置和操作很轻松,尽可能自动地管理主要网络连接和其它网络接口,如以太网,WiFi和移动宽带设备。 
           当一个网络设备变的可用时,NetworkManager将连接该设备,除非这个行为被禁止。
     网络信息通过D-Bus接口导出给任何感兴趣的应用程序,并提供了丰富的API来检查和控制网络设置和操作。
          NetworkManager [option]:
                        选项:
   分发过程:
          分发脚本,NetworkManager将根据网络事件按字母顺序执行/etc/NetworkManager/dispatcher.d/目录下的脚本,每个脚本应该是常规可执行文件,必顺由root所有。
      每个脚本接收两个参数,第一个为:发生事件的设备接口名,第二个为:动作
            可能的动作有:
             up:    接口被激活。
             down:  接口被停用。
             vpn-up: 一个VPN 链接已经激活。
             vpn-down:   一个VPN链接被停用。
             hostname:  系统hostname已经更新。使用gethostname来获取。第一个参数接口名为NULL,没有环境变量设置。
             dhcp4-change:     DHCPv4 发生了变化(renewed,rebound,etc)
             dhcp6-change:     DHCPv6  发生了变化

          环境变量包含了更多接口与连接的的信息。下面的变量在分发脚本中是可用的:
                CONNECTION_UUID:The UUID of the connection profile.
                CONNECTION_ID:          The name (ID) of the connection profile.
                DEVICE_IFACE:The interface name of the device.
                DEVICE_IP_IFACE:The IP interface name of the device.
                IP4_ADDRESS_N:The IPv4 address in the format "address/prefix gateway", where N is a number from 0 to(# IPv4 address \- 1).
                IP4_NUM_ADDRESSES:The variable contains the number of IPv4 addresses the script may expect.
                IP4_ROUTE_N:The IPv4 route in the format "address/prefix next-hop metric", where N is a number from 0 to (# IPv4 routes \- 1).
              IP4_NUM_ROUTES:The variable contains the number of IPv4 routes the script may expect.
              IP4_NAMESERVERS:The variable contains a space-separated list of the DNS servers.

              IP4_DOMAINS:The variable contains a space-separated list of the search domains.

       DHCP4_<dhcp-option-name>
           If the connection used DHCP for address configuration, the received DHCP configuration
           is passed in the environment using standard DHCP option names, prefixed with "DHCP4_",
           like "DHCP4_HOST_NAME=foobar".

       IP6_<name> and DHCP6_<name>
           The same variables as for IPv4 are available for IPv6, but the prefixes are IP6_ and
           DHCP6_ instead.

       In case of VPN, VPN_IP_IFACE is set, and IP4_*, IP6_* variables with VPN prefix are exported
       too, like VPN_IP4_ADDRESS_0, VPN_IP4_NUM_ADDRESSES.

 nmcli: NetworkManager的命令行控制工具
       sysctl -w net.ipv6.conf.all.disable_ipv6=1  //运行时关闭IPV6
     ( 修改配置文件: /usr/lib/sysctl.d/00-system.conf   加入 net.ipv6.conf.all.disable_ipv6=1 )
     nmcli d[evice] show 显示所有设备名及状态
     nmcli c[onnection]  显示设备名及对应的UUID
     nmcli c[onnection] delete UUID  删除对应的连接
     nmcli networking off  禁止NetworkManager管理所有接口 (会启动dhclient 获取DHCI 地址,ip addr show 可以看到有两个地址,第一个为静态指定,第二个为DHCP获取。systemctl status NetworkManager.service可以看到是否启动了dhclient )
     nmcli radio  所有无线状态
     nmcli radio wifi   无线wifi状态
     nmcli radio all off  关闭所有无线网线


/etc/init.d/network restart  执行流程:
               a,  /etc/init.d/functions   (各种功能函数)
               b, /etc/sysconfig/network   (配置)
          (cd /etc/sysconfig/network-scripts)
               c,  ./network-funtions    (各种功能函数,)       
               d,获取接口名:interface= $(ls ifcfg-* | sed -e "$__sed_discard_ignored_files" -e '/\(ifcfg-lo$)\/:\/ifcfg-.*-range\)/d' -e '{ s/^ifcfg-//g;s/[0-9]/ &/}' | sort -k1,1 -k 2n | sed 's/  //')
               e,如果 /etc/sysconfig/network-scripts/init.ipv6-global 可执行,则 执行 。start pre 
               f, /etc/init.d/functions: apply_sysctl()  
                              1.如果 /lib/systemd/systemd-sysctl 可执行,则执行。(二进制程序)
                         否则:读取 /usr/lib/sysctl.d/ *.conf  ,/run/sysctl.d/*.conf, /etc/sysctl.d/*.conf , /etc/sysctl.conf .用 sysctl  -e -p file 来设置网络相关参数
              g,  ifup ifcfg-lo
              h,   如果VLAN 为yes ,则modprobe 8021q 
              i,  遍历所有接口interface ,  获取每个接口配置文件的 DEVICE,TYPE,SLAVE, 过滤cipcb(vpn接口) , xDSL, Bridge ,IPSEC(vpn接口),vlan 接口,最后ONBOOT不为NO时,执行:ifup 接口 boot .
                  然后(启动上面过滤的接口):ifup 其它接口 boot

             j,  如果 /etc/sysconfig/static-routes 存在,则route添加静态路由                                                      
    
    
    
    
    



netlink开发:
struct msghdr {    //消息地址
     void     *     msg_name;          /* 地址          */
     int          msg_namelen;          /* 地址长度          */
     struct iovec *     msg_iov;        /* 数据块向量               */
     __kernel_size_t     msg_iovlen; /* 向量元素个数          */
     void      *     msg_control;       /* 辅助数据 (或每个协议的魔数)(eg BSD file descriptor passing) */
     __kernel_size_t     msg_controllen;     /* 辅助数据长度 */
     unsigned int     msg_flags;     //接收时标志         
};

netlink编程:

struct sockaddr_nl {   //netlink通信地址
     __kernel_sa_family_t     nl_family;  /* AF_NETLINK     */
     unsigned short     nl_pad;             /* zero          */
     __u32          nl_pid;                    /* port ID,为0表示目标是内核     */
    __u32          nl_groups;               /* 组播掩码,每个协议下都有多个组 */
};

int socket(int domain,int type,int protocol);
             AF_NETLINK,    SOCK_DGRAM, 协议(内核子系统):NETLINK_ROUTE, NETLINK_NETFILTER  ...
                   
struct nlmsghdr {
     __u32          nlmsg_len;     /* 整个消息的长度,包扩消息头*/
     __u16          nlmsg_type;     /* 消息类型  */
                                             NLMSG_NOOP:  无操作,可直接丢弃
                                             NLMSG_ERROR: 返回消息(eror错误消息),  struct nlmsgerr {}   (响应)
                                             NLMSG_DONE:  如果单个信息的数据量较大,需要分成多个netlink消息发送的话,这表示此是最后一个消息分片。
     __u16          nlmsg_flags;     /* 附加标志*/
                                                  NLM_F_REQUEST: 表示客户端的请求      (请求)
                                                                           服务端向客户端发送通知. nlmsg_seq 一般为0
                                                  NLM_F_MULT: 代表分片消息中的一个.
                                                  NLM_F_ACK: 强制服务端接收请求后加复ACK给客户端。
                                                 
     __u32          nlmsg_seq;     /* 消息序列号 */
     __u32          nlmsg_pid;     /* 发送消息的nl_pid,  为0表示来自内核*/
};

struct nlmsgerr {  //返回消息
     int          error;           // 为0时,表示返回正常的消息, 负值:错误码
     struct nlmsghdr msg;   // 对应请求消息的逍息头。
};

NLMSG_ALIGN(len);                // 获取len按4字节补齐后的长度. (len+3)&(~3)
NLMSG_LENGTH(nlmsg_len);   // 整 个消息包的长度.  nlmsg_len+ (struct nlmsghdr 按4字节补 齐后的长度
NLMSG_SPACE(len);               // NLMSG_ALIGN(NLMSG_LENGTH(len))  补齐后的消息长度
NLMSG_DATA(nlh);               //获取消息中的数据起始地址  (指针向后移消息头长度)
NLMSG_NEXT(nlh,len);          //获取下一条分片消息.    len-=NLMSG_ALIGN(nlh->nlmsg_len); (char*)nlh+NLMSG_ALIGN(nlh->nlmsg_len);
NLMSG_OK(nlh,len);             //用于判断接收到的数据是否包含一个完整的netlink消息
NLMSG_PAYLOAD(nlh,len);    //用于返回数据的长度;  nlh->nlmsg_len-NLMSG_SPACE(len)

struct nlattr {  // 载荷属性
   __u16     nla_len;  // 属性长度
   __u16     nla_type;  // 属性类型
};

struct ifinfomsg {   //链路层消息 
     unsigned char     ifi_family;
     unsigned char     __ifi_pad;
     unsigned short     ifi_type;    /* ARPHRD_* */
     int          ifi_index;              /* Link index     */
     unsigned     ifi_flags;          /* IFF_* flags     */
     unsigned     ifi_change;      /* IFF_* change mask */
};
struct rtattr { // 可选路由信息的通用封装
     unsigned short     rta_len;
     unsigned short     rta_type;
};


案例 :监听网卡状态变化( 原理图如下)
     void parseNetlinkMessage(struct nlmsghdr*nh){                                                                                               
          int len=nh->nlmsg_len-sizeof(*nh);
          struct ifinfomsg *ifinfo;
          if(sizeof(*ifinfo)>len){
               return ;
          }
          ifinfo=(struct ifinfomsg*)NLMSG_DATA(nh);
          if((ifinfo->ifi_flags&IFF_LOOPBACK )!=0){  //0x08=IFF_LOOPBACK
               return ;
          }
          struct rtattr *rta = (struct rtattr *)((char *) ifinfo + NLMSG_ALIGN(sizeof(*ifinfo))); 
          len = NLMSG_PAYLOAD(nh, sizeof(*ifinfo)); 
 
    while(RTA_OK(rta, len)) { 
        switch(rta->rta_type) { 
          case IFLA_IFNAME: 
          { 
            char ifname[IFNAMSIZ]; 
            //char *action;
            int up_flags=0;
            strncpy(ifname,(char*)RTA_DATA(rta),sizeof(ifname));
            //snprintf(ifname, sizeof(ifname), "%s",  (char *) RTA_DATA(rta)); 
            //action = (ifi->ifi_flags & IFF_LOWER_UP) ? "up" : "down"; 
            //action = (ifinfo->ifi_flags & IFF_RUNNING) ? "up" : "down"; 
            up_flags=(ifinfo->ifi_flags & IFF_RUNNING) ? 1 : 0;    // 0x40=IFF_RUNNING
            syslog(5,"vanstor %s link %s !\n", ifname, up_flags?"up":"down"); 
             if(up_flags)
                 //up_netdevice(ifname);
               
          } 
        } 
        rta = RTA_NEXT(rta, len); 
    } 
}  

void do_listen_netstate(){
    int fd;
    struct sockaddr_nl addr;
     char buffer[8192];
     struct nlmsghdr *nlh; 
     int len=0;
    if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) {
        syslog(LOG_ERR, "Could not create netlink socket!\n");
        exit(1);
    }
    close_on_exec(fd);
    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_groups = RTMGRP_LINK;
    if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
        syslog(LOG_ERR, "Could not bind netlink socket!\n");
        exit(1);
    }
     while(1){
            len=recv(fd,buffer,8192,0);  //block
               nlh=(struct nlmsghdr*)buffer;
               while(NLMSG_OK(nlh,len)&&(nlh->nlmsg_type!=NLMSG_DONE)){
                    //syslog(5,"nlmsg_type=0x%x,nlmsg_flags=0x%x \n",nlh->nlmsg_type,nlh->nlmsg_flags);
                    parseNetlinkMessage(nlh);
                    nlh=NLMSG_NEXT(nlh,len);
               }
     }
     close(fd);
     return ;
}

     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值