各种接品网络接口函数与结构体:
#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位表示点分十进制)
}
#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>
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;
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
网络信息通过D-Bus接口导出给任何感兴趣的应用程序,并提供了丰富的API来检查和控制网络设置和操作。
}
路由设备:
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
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
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
网络配置文件:
设置模式
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初始化脚本处理。
通过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]:
选项:
每个脚本接收两个参数,第一个为:发生事件的设备接口名,第二个为:动作
可能的动作有:
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 d[evice] show 显示所有设备名及状态
nmcli c[onnection] 显示设备名及对应的UUID
nmcli c[onnection] delete UUID 删除对应的连接
分发过程:
分发脚本,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 关闭所有无线网线
案例 :监听网卡状态变化( 原理图如下)
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 ;
}
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
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 可执行,则执行。(二进制程序)
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
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 .
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字节补 齐后的长度)
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;
};
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 ;
}