ifconfig调用流程
ioctl(4, SIOCSIFADDR, {ifr_name="eth6", ifr_addr={AF_INET, inet_addr("20.20.20.20")}}) = 0
ioctl(4, SIOCGIFFLAGS, {ifr_name="eth6", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_MULTICAST}) = 0
ioctl(4, SIOCSIFFLAGS, {ifr_name="eth6", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0
ioctl(4, SIOCSIFNETMASK, {ifr_name="eth6", ifr_netmask={AF_INET, inet_addr("255.255.255.0")}}) = 0
ifconfig配置IP地址的函数调用,第一个内核里被调用到的函数是inet_ioctl(),经过devinet_ioctl函数会调用fib_inetaddr_event():
net/ipv4/af_inet.c inet_ioctl()
net/ipv4/devinet.c devinet_ioctl()
blocking_notifier_call_chain(&inetaddr_chain,NETDEV_UP, ifa); 执行接口通知连
static struct notifier_block fib_inetaddr_notifier = {
.notifier_call = fib_inetaddr_event,
};
register_inetaddr_notifier(&fib_inetaddr_notifier);
int register_inetaddr_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&inetaddr_chain, nb);
}
fib_inetaddr_event()这个函数是注册的通知链函数,从这个函数的命名(fib forward information base)就可以看出其和路由是有直接关系关系的,就从这个函数开始。
static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
struct net_device *dev = ifa->ifa_dev->dev;
struct net *net = dev_net(dev);
switch (event) {
case NETDEV_UP:
fib_add_ifaddr(ifa);
-----------------------------------
break;
----------------------
return NOTIFY_DONE;
}
/*
在添加IP地址时,内核会自动维护本机相关的路由项,具体如下:
在local表中添加一条目的地址为该IP地址的主机路由项(子网掩码长度为32),使得接收数据时可以精准匹配;
在local表中添加一条目的地址为该IP广播地址的主机路由项,使得收发的广播数据可以精准匹配;
在main表添加一条到该IP地址所在网络的网络路由项,使得可以到达该网络;
在local表中添加目的地址为该子网的广播地址路由项;
*/
void fib_add_ifaddr(struct in_ifaddr *ifa)
{
struct in_device *in_dev = ifa->ifa_dev;
struct net_device *dev = in_dev->dev;
struct in_ifaddr *prim = ifa;
__be32 mask = ifa->ifa_mask;
__be32 addr = ifa->ifa_local;
__be32 prefix = ifa->ifa_address & mask;
if (ifa->ifa_flags & IFA_F_SECONDARY) {
prim = inet_ifa_byprefix(in_dev, prefix, mask);
if (!prim) {//如果flag参数指定了配置IP对象为从属设备或者临时设备,但是根据索引找不到该设备,返回错误
pr_warn("%s: bug: prim == NULL\n", __func__);
return;
}
}
/*/在ID等于255的表中,插入一条目的地址为主地址的主机路由项(子网掩码长度为32)。
//ID等于255的表示是LOCAL表,即该表中的所有IP项的目的地址均是本机。类型见IP地址类型。*/
fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);
if (!(dev->flags & IFF_UP))// 网络设备尚未使能,后续地址不添加
return;
/* Add broadcast address, if it is explicitly assigned. 处理广播包的路由项。主机号全为1和主机号全为0,实际的过程有点复杂*/
//添加一条到所在网络广播地址的主机路由项
if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF))
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) &&
(prefix != addr || ifa->ifa_prefixlen < 32)) {
if (!(ifa->ifa_flags & IFA_F_NOPREFIXROUTE))// 添加的地址是某个子网中的一个主机地址,那么也需要生成到达该子网的路由项
fib_magic(RTM_NEWROUTE, dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
prefix, ifa->ifa_prefixlen, prim);
/* Add network specific broadcasts, when it takes a sense
生成到达该子网广播地址的路由项,这里可以看出,主机号全0和全1都是去往该网络的广播地址*/
if (ifa->ifa_prefixlen < 31) {
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim);
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix | ~mask,
32, prim);
}
}
}
/*
在添加IP地址时,内核会自动维护本机相关的路由项,具体如下:
在local表中添加一条目的地址为该IP地址的主机路由项(子网掩码长度为32),使得接收数据时可以精准匹配;
在local表中添加一条目的地址为该IP广播地址的主机路由项,使得收发的广播数据可以精准匹配;
在main表添加一条到该IP地址所在网络的网络路由项,使得可以到达该网络;
在local表中添加目的地址为该子网的广播地址路由项;
*/
void fib_add_ifaddr(struct in_ifaddr *ifa)
{
struct in_device *in_dev = ifa->ifa_dev;
struct net_device *dev = in_dev->dev;
struct in_ifaddr *prim = ifa;
__be32 mask = ifa->ifa_mask;
__be32 addr = ifa->ifa_local;
__be32 prefix = ifa->ifa_address & mask;
if (ifa->ifa_flags & IFA_F_SECONDARY) {
prim = inet_ifa_byprefix(in_dev, prefix, mask);
if (!prim) {//如果flag参数指定了配置IP对象为从属设备或者临时设备,但是根据索引找不到该设备,返回错误
pr_warn("%s: bug: prim == NULL\n", __func__);
return;
}
}
/*/在ID等于255的表中,插入一条目的地址为主地址的主机路由项(子网掩码长度为32)。
//ID等于255的表示是LOCAL表,即该表中的所有IP项的目的地址均是本机。类型见IP地址类型。*/
fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);
if (!(dev->flags & IFF_UP))// 网络设备尚未使能,后续地址不添加
return;
/* Add broadcast address, if it is explicitly assigned. 处理广播包的路由项。主机号全为1和主机号全为0,实际的过程有点复杂*/
//添加一条到所在网络广播地址的主机路由项
if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF))
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) &&
(prefix != addr || ifa->ifa_prefixlen < 32)) {
if (!(ifa->ifa_flags & IFA_F_NOPREFIXROUTE))// 添加的地址是某个子网中的一个主机地址,那么也需要生成到达该子网的路由项
fib_magic(RTM_NEWROUTE, dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
prefix, ifa->ifa_prefixlen, prim);
/* Add network specific broadcasts, when it takes a sense
生成到达该子网广播地址的路由项,这里可以看出,主机号全0和全1都是去往该网络的广播地址*/
if (ifa->ifa_prefixlen < 31) {
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim);
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix | ~mask,
32, prim);
}
}
}
http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!!
但行好事 莫问前程
--身高体重180的胖子