我用netfilter钩子编写Linux内核模块。我想阻止任何不是来自子网的数据包。
是否有任何简单的方法可以在内核模式下获取接口的网络掩码?我发现只有在用户模式下使用ioctl()
才能获得它的方法。
我用netfilter钩子编写Linux内核模块。我想阻止任何不是来自子网的数据包。
是否有任何简单的方法可以在内核模式下获取接口的网络掩码?我发现只有在用户模式下使用ioctl()
才能获得它的方法。
有一种很简单的方法来获取它。
网络设备由struct net_device
描述。<linux/netdevice.h>
:
struct net_device {
...
struct in_device __rcu *ip_ptr;
...
net_device
有一个指向“ inet”设备(in_device
)的指针。
struct in_device {
...
struct in_ifaddr *ifa_list; /* IP ifaddr chain */
...
最终指向包含所有接口信息的in_ifaddr
链:
struct in_ifaddr {
struct hlist_node hash;
struct in_ifaddr *ifa_next;
struct in_device *ifa_dev;
struct rcu_head rcu_head;
__be32 ifa_local;
__be32 ifa_address;
__be32 ifa_mask;
__u32 ifa_rt_priority;
__be32 ifa_broadcast;
unsigned char ifa_scope;
unsigned char ifa_prefixlen;
__u32 ifa_flags;
char ifa_label[IFNAMSIZ];
/* In seconds,relative to tstamp. Expiry is at tstamp + HZ * lft. */
__u32 ifa_valid_lft;
__u32 ifa_preferred_lft;
unsigned long ifa_cstamp; /* created timestamp */
unsigned long ifa_tstamp; /* updated timestamp */
};
为使我的答案更加通用,下面是一个抽象示例(不绑定到netfilter和skb设备逻辑):
struct in_ifaddr *ifa;
struct net_device *dev = dev_get_by_name(&init_net,"wlp7s0");
if(!dev) {
printk(KERN_ERR "Can't obtain device\n");
return;
}
// roughly
rcu_read_lock();
for(ifa = rcu_dereference(dev->ip_ptr->ifa_list);
ifa;
ifa = rcu_dereference(ifa->ifa_next))
printk("address: %pI4,mask: %pI4\n",&ifa->ifa_address,&ifa->ifa_mask);
rcu_read_unlock();
从示例中您可以看到,您可以根据某些特定逻辑来处理整个链(注释中提到的@larsks)。
P.S。不要忘记包含<linux/netdevice.h>
和<linux/inetdevice.h>
。