// 相同子网: // 掩码相同,网络地址相同 // 为设备配置ip地址 // 函数主要任务: // 1.合理性检查; // 1.1 相同子网内该地址没有被添加过 // 1.2 相同子网内的地址scope应该相同 // 2.将ifa插入到in_device->ifa_list中 // 3.通知netlink,inetaddr_chain 新地址的加入 // 注:地址在in_device->ifa_list中的排列: // 1.主地址:插入的如果为主地址,则按照scope从大到小的顺序排列 // 2.辅地址: 总是插入到列表的最尾端 // 调用路径:inet_rtm_newaddr->inet_insert_ifa 1.1 static int inet_insert_ifa(struct in_ifaddr *ifa) { struct in_device *in_dev = ifa->ifa_dev; struct in_ifaddr *ifa1, **ifap, **last_primary; //辅地址标志 ifa->ifa_flags &= ~IFA_F_SECONDARY; //主地址列表 last_primary = &in_dev->ifa_list; //遍历主地址列表 for (ifap = &in_dev->ifa_list; (ifa1 = *ifap) != NULL; ifap = &ifa1->ifa_next) { if (!(ifa1->ifa_flags & IFA_F_SECONDARY) &&//主地址 ifa->ifa_scope <= ifa1->ifa_scope)//ifa的scope小于等于主地址的scope last_primary = &ifa1->ifa_next; //相同子网: // 子网掩码长度相同的情况,网络地址相同 if (ifa1->ifa_mask == ifa->ifa_mask && inet_ifa_match(ifa1->ifa_address, ifa)) {//网络地址有重叠 if (ifa1->ifa_local == ifa->ifa_local) {//本地地址相同 inet_free_ifa(ifa);//重复添加 return -EEXIST; } if (ifa1->ifa_scope != ifa->ifa_scope) { inet_free_ifa(ifa); return -EINVAL; } //子网掩码长度相同,网络地址有重叠,设置为辅地址 ifa->ifa_flags |= IFA_F_SECONDARY; } } //加入新子网 // 子网掩码或网络地址没有重叠 if (!(ifa->ifa_flags & IFA_F_SECONDARY)) { net_srandom(ifa->ifa_local); ifap = last_primary; } //上一个scope大于本ip地址的主地址 ifa->ifa_next = *ifap; *ifap = ifa; //向netlink发送消息,新添加了ip地址 rtmsg_ifa(RTM_NEWADDR, ifa); //通知inetaddr_chain,ip地址加入到设备 notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); return 0; } // 删除设备的ip地址 // 函数主要任务: // 1.如果为主地址,则删除同一子网内的所有辅地址 // 2.删除该地址 // 3.通知netlink,inetaddr_chain // 调用路径:inet_rtm_deladdr->inet_del_ifa 1.2 static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy) { struct in_ifaddr *ifa1 = *ifap; //1.删除主地址,同一子网内所有辅助地址都被删除 if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) { struct in_ifaddr *ifa; struct in_ifaddr **ifap1 = &ifa1->ifa_next; while ((ifa = *ifap1) != NULL) { if (!(ifa->ifa_flags & IFA_F_SECONDARY) || ifa1->ifa_mask != ifa->ifa_mask || !inet_ifa_match(ifa1->ifa_address, ifa)) { ifap1 = &ifa->ifa_next; continue; } //同一子网内的辅助地址 *ifap1 = ifa->ifa_next; //通知netlink,inetaddr_chain rtmsg_ifa(RTM_DELADDR, ifa); notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); //释放ifa inet_free_ifa(ifa); } } //将地址从地址列表删除 *ifap = ifa1->ifa_next; //通知netlink,inetaddr_chain,地址删除 rtmsg_ifa(RTM_DELADDR, ifa1); notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); //释放ifa if (destroy) { inet_free_ifa(ifa1); //如果没有配置的地址信息,释放配置信息控制块 if (!in_dev->ifa_list) inetdev_destroy(in_dev); } }
时间: 2025-01-30 05:49:05