IP结构与操作之inet_confirm_addr && confirm_addr_indev
确认给定参数范围的ip地址是否存在;
1 /* 2 * Confirm that local IP address exists using wildcards: 3 * - net: netns to check, cannot be NULL 4 * - in_dev: only on this interface, NULL=any interface 5 * - dst: only in the same subnet as dst, 0=any dst 6 * - local: address, 0=autoselect the local address 7 * - scope: maximum allowed scope value for the local address 8 */ 9 10 /* 11 确认参数中给定的本地地址是否存在 12 net: net命名空间,不能为空 13 in_dev: 在此ip控制块上,空表示任何设备上的控制块 14 dst: 与dst在同一子网,0表示不限制 15 local: 本地地址,0表示自动选择本地地址 16 scope: 本地地址最大允许的地址范围 17 */ 18 19 __be32 inet_confirm_addr(struct net *net, struct in_device *in_dev, 20 __be32 dst, __be32 local, int scope) 21 { 22 __be32 addr = 0; 23 struct net_device *dev; 24 25 /* ip控制块存在,则从该控制块中选择地址 */ 26 if (in_dev) 27 return confirm_addr_indev(in_dev, dst, local, scope); 28 29 rcu_read_lock(); 30 /* ip控制块不存在,则遍历所有设备 */ 31 for_each_netdev_rcu(net, dev) { 32 /* 找到设备中的ip控制块 */ 33 in_dev = __in_dev_get_rcu(dev); 34 35 /* 如果ip控制块存在 */ 36 if (in_dev) { 37 /* 从该控制块选择地址 */ 38 addr = confirm_addr_indev(in_dev, dst, local, scope); 39 /* 找到则结束 */ 40 if (addr) 41 break; 42 } 43 } 44 rcu_read_unlock(); 45 46 return addr; 47 }
1 /* 2 从指定ip控制块中获取参数允许范围内的地址 3 1. local dst都不在,找一个满足范围的ip 4 2. local存在,dst不存在,找与local相等的满足范围的ip 5 3. local不存在,dst存在,找满足范围的与dst在同一子网的ip 6 4. local dst都存在,找与local相等,并且与dst在同一子网的ip 7 */ 8 static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, 9 __be32 local, int scope) 10 { 11 int same = 0; 12 __be32 addr = 0; 13 14 /* 遍历地址列表 */ 15 for_ifa(in_dev) { 16 17 if (!addr && /* 目标地址为空 */ 18 (local == ifa->ifa_local || !local) && /* 本地地址相等或者参数地址为空 */ 19 ifa->ifa_scope <= scope) { /* 当前地址满足<= 参数地址范围 */ 20 /* 找到目标地址 */ 21 addr = ifa->ifa_local; 22 23 /* 满足子网要求 */ 24 if (same) 25 break; 26 } 27 28 /* 未判断子网是否相同 */ 29 if (!same) { 30 /* local dst不要求,或者在同一子网 */ 31 same = (!local || inet_ifa_match(local, ifa)) && 32 (!dst || inet_ifa_match(dst, ifa)); 33 34 /* 满足子网要求且地址存在,则具体判断是哪种情况 */ 35 if (same && addr) { 36 37 /* local存在或者local和dst都不存在 */ 38 if (local || !dst) 39 break; 40 41 /* local不存在,dst存在 */ 42 43 /* Is the selected addr into dst subnet? */ 44 /* 目标地址与dst在同一子网 */ 45 if (inet_ifa_match(addr, ifa)) 46 break; 47 48 /* 目标地址与dst不在同一子网 */ 49 50 /* No, then can we use new local src? */ 51 /* 如果ifa满足范围,则使用这个ifa的地址 */ 52 if (ifa->ifa_scope <= scope) { 53 addr = ifa->ifa_local; 54 break; 55 } 56 57 /* 查找失败,继续查找 */ 58 59 /* search for large dst subnet for addr */ 60 same = 0; 61 } 62 } 63 } endfor_ifa(in_dev); 64 65 return same ? addr : 0; 66 }