📄 mydevinet.c
字号:
#define MY_IN_DEV_PROMOTE_SECONDARIES(in_dev) \ (myipv4_devconf.promote_secondaries || (in_dev)->cnf.promote_secondaries)static struct notifier_block *myinetaddr_chain;static void mydevinet_sysctl_register(struct in_device *in_dev, struct ipv4_devconf *p);static void mydevinet_sysctl_unregister(struct ipv4_devconf *p);static void myrtmsg_ifa(int event, struct in_ifaddr* ifa);void myip_mc_up(struct in_device *in_dev);void myip_mc_down(struct in_device *in_dev);void myip_mc_init_dev(struct in_device *in_dev);struct ipv4_devconf myipv4_devconf = { .accept_redirects = 1, .send_redirects = 1, .secure_redirects = 1, .shared_media = 1,};static struct ipv4_devconf myipv4_devconf_dflt = { .accept_redirects = 1, .send_redirects = 1, .secure_redirects = 1, .shared_media = 1, .accept_source_route = 1,};static __inline__ int myinet_abc_len(u32 addr){ int rc = -1; if (ZERONET(addr)) rc = 0; else{ addr = ntohl(addr); if (IN_CLASSA(addr)) rc = 8; else if (IN_CLASSB(addr)) rc = 16; else if (IN_CLASSC(addr)) rc = 24; } return rc;}struct in_device *myinetdev_by_index(int ifindex){ struct net_device *dev; struct in_device *in_dev = NULL; read_lock(&dev_base_lock); dev = __dev_get_by_index(ifindex); if (dev) in_dev = in_dev_get(dev); read_unlock(&dev_base_lock); return in_dev;}static u32 myconfirm_addr_indev(struct in_device *in_dev, u32 dst, u32 local, int scope){ int same = 0; u32 addr = 0; for_ifa(in_dev) { if (!addr && (local == ifa->ifa_local || !local) && ifa->ifa_scope <= scope) { addr = ifa->ifa_local; if (same) break; } if (!same) { same = (!local || inet_ifa_match(local, ifa)) && (!dst || inet_ifa_match(dst, ifa)); if (same && addr) { if (local || !dst) break; if (inet_ifa_match(addr, ifa)) break; if (ifa->ifa_scope <= scope) { addr = ifa->ifa_local; break; } same = 0; } } } endfor_ifa(in_dev); return same? addr : 0;}u32 myinet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope){ u32 addr = 0; struct in_device *in_dev; if (dev) { rcu_read_lock(); if ((in_dev = __in_dev_get_rcu(dev))) addr = myconfirm_addr_indev(in_dev, dst, local, scope); rcu_read_unlock(); return addr; } read_lock(&dev_base_lock); rcu_read_lock(); for (dev = dev_base; dev; dev = dev->next) { if ((in_dev = __in_dev_get_rcu(dev))) { addr = myconfirm_addr_indev(in_dev, dst, local, scope); if (addr) break; } } rcu_read_unlock(); read_unlock(&dev_base_lock); return addr;}int myinet_addr_onlink(struct in_device *in_dev, u32 a, u32 b){ rcu_read_lock(); for_primary_ifa(in_dev) { if (inet_ifa_match(a, ifa)) { if (!b || inet_ifa_match(b, ifa)) { rcu_read_unlock(); return 1; } } } endfor_ifa(in_dev); rcu_read_unlock(); return 0;}u32 myinet_select_addr(const struct net_device *dev, u32 dst, int scope){ u32 addr = 0; struct in_device *in_dev; rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); if (!in_dev) goto no_in_dev; for_primary_ifa(in_dev) { if (ifa->ifa_scope > scope) continue; if (!dst || inet_ifa_match(dst, ifa)) { addr = ifa->ifa_local; break; } if (!addr) addr = ifa->ifa_local; } endfor_ifa(in_dev);no_in_dev: rcu_read_unlock(); if (addr) goto out; read_lock(&dev_base_lock); rcu_read_lock(); for (dev = dev_base; dev; dev = dev->next) { if ((in_dev = __in_dev_get_rcu(dev)) == NULL) continue; for_primary_ifa(in_dev) { if (ifa->ifa_scope != RT_SCOPE_LINK && ifa->ifa_scope <= scope) { addr = ifa->ifa_local; goto out_unlock_both; } } endfor_ifa(in_dev); }out_unlock_both: read_unlock( &dev_base_lock ); rcu_read_unlock();out: return addr;}static int mydevinet_sysctl_forward(ctl_table *ctl, int write, struct file* filp, void __user *buffer, size_t *lenp, loff_t *ppos){ return 0;}int myipv4_doint_and_flush(ctl_table *ctl, int write, struct file* filp, void __user *buffer, size_t *lenp, loff_t *ppos){ return 0;}int myipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, void __user *newval, size_t newlen, void **context){ return 0;}#define NET_MYIPV4 18static struct mydevinet_sysctl_table{ struct ctl_table_header *sysctl_header; ctl_table devinet_vars[__NET_IPV4_CONF_MAX]; ctl_table devinet_dev[2]; ctl_table devinet_conf_dir[2]; ctl_table devinet_proto_dir[2]; ctl_table devinet_root_dir[2];} mydevinet_sysctl = { .devinet_vars = { { .ctl_name = NET_IPV4_CONF_FORWARDING, .procname = "forwarding", .data = &myipv4_devconf.forwarding, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &mydevinet_sysctl_forward, }, { .ctl_name = NET_IPV4_CONF_MC_FORWARDING, .procname = "mc_forwarding", .data = &myipv4_devconf.mc_forwarding, .maxlen = sizeof(int), .mode = 0444, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_ACCEPT_REDIRECTS, .procname = "accept_redirects", .data = &myipv4_devconf.accept_redirects, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_SECURE_REDIRECTS, .procname = "secure_redirects", .data = &myipv4_devconf.secure_redirects, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_SHARED_MEDIA, .procname = "shared_media", .data = &myipv4_devconf.shared_media, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_RP_FILTER, .procname = "rp_filter", .data = &myipv4_devconf.rp_filter, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_SEND_REDIRECTS, .procname = "send_redirects", .data = &myipv4_devconf.send_redirects, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE, .procname = "accept_source_route", .data = &myipv4_devconf.accept_source_route, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_PROXY_ARP, .procname = "proxy_arp", .data = &myipv4_devconf.proxy_arp, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_MEDIUM_ID, .procname = "medium_id", .data = &myipv4_devconf.medium_id, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_BOOTP_RELAY, .procname = "bootp_relay", .data = &myipv4_devconf.bootp_relay, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_LOG_MARTIANS, .procname = "log_martians", .data = &myipv4_devconf.log_martians, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_TAG, .procname = "tag", .data = &myipv4_devconf.tag, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_ARPFILTER, .procname = "arp_filter", .data = &myipv4_devconf.arp_filter, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_ARP_ANNOUNCE, .procname = "arp_announce", .data = &myipv4_devconf.arp_announce, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_ARP_IGNORE, .procname = "arp_ignore", .data = &myipv4_devconf.arp_ignore, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = NET_IPV4_CONF_NOXFRM, .procname = "disable_xfrm", .data = &myipv4_devconf.no_xfrm, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &myipv4_doint_and_flush, .strategy = &myipv4_doint_and_flush_strategy, }, { .ctl_name = NET_IPV4_CONF_NOPOLICY, .procname = "disable_policy", .data = &myipv4_devconf.no_policy, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &myipv4_doint_and_flush, .strategy = &myipv4_doint_and_flush_strategy, }, { .ctl_name = NET_IPV4_CONF_FORCE_IGMP_VERSION, .procname = "force_igmp_version", .data = &myipv4_devconf.force_igmp_version, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &myipv4_doint_and_flush, .strategy = &myipv4_doint_and_flush_strategy, }, { .ctl_name = NET_IPV4_CONF_PROMOTE_SECONDARIES, .procname = "promote_secondaries", .data = &myipv4_devconf.promote_secondaries, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &myipv4_doint_and_flush, .strategy = &myipv4_doint_and_flush_strategy, }, }, .devinet_dev = { { .ctl_name = NET_PROTO_CONF_ALL, .procname = "all", .mode = 0555, .child = mydevinet_sysctl.devinet_vars, }, }, .devinet_conf_dir = { { .ctl_name = NET_IPV4_CONF, .procname = "conf", .mode = 0555, .child = mydevinet_sysctl.devinet_dev, }, }, .devinet_proto_dir = { { .ctl_name = NET_MYIPV4, .procname = "myipv4", .mode = 0555, .child = mydevinet_sysctl.devinet_conf_dir, }, }, .devinet_root_dir = { { .ctl_name = CTL_NET, .procname = "net", .mode = 0555, .child = mydevinet_sysctl.devinet_proto_dir, }, },};static void myinetdev_destroy(struct in_device *in_dev){}static int myinet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg){ return 0;}static int myinet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg){ return 0;}static int myinet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb){ return 0;}int myinet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg){ return 0;}int myinet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg){ return 0;}int myinet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg){ return 0;}int myinet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb){ return 0;}int myinet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg){ return 0;}int myinet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg){ return 0;}int myinet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb){ return 0;}static struct rtnetlink_link myinet_rtnetlink_table[RTM_NR_MSGTYPES] = { [RTM_NEWADDR - RTM_BASE] = { .doit = myinet_rtm_newaddr, }, [RTM_DELADDR - RTM_BASE] = { .doit = myinet_rtm_deladdr, }, [RTM_GETADDR - RTM_BASE] = { .dumpit = myinet_dump_ifaddr, }, [RTM_NEWROUTE - RTM_BASE] = { .doit = myinet_rtm_newroute, }, [RTM_DELROUTE - RTM_BASE] = { .doit = myinet_rtm_delroute, }, [RTM_GETROUTE - RTM_BASE] = { .doit = myinet_rtm_getroute, .dumpit = myinet_dump_fib, },#ifdef CONFIG_IP_MULTIPLE_TABLES [RTM_NEWRULE - RTM_BASE] = { .doit = myinet_rtm_newrule, }, [RTM_DELRULE - RTM_BASE] = { .doit = myinet_rtm_delrule, }, [RTM_GETRULE - RTM_BASE] = { .dumpit = myinet_dump_rules, },#endif};static void myinet_rcu_free_ifa(struct rcu_head *head){ struct in_ifaddr *ifa = container_of(head, struct in_ifaddr, rcu_head); if (ifa->ifa_dev) in_dev_put(ifa->ifa_dev); kfree(ifa);}static inline void myinet_free_ifa(struct in_ifaddr *ifa){ call_rcu(&ifa->rcu_head, myinet_rcu_free_ifa);}static int myinet_insert_ifa(struct in_ifaddr *ifa){ struct in_device *in_dev = ifa->ifa_dev; struct in_ifaddr *ifa1, **ifap, **last_primary; ASSERT_RTNL(); if (!ifa->ifa_local) { myinet_free_ifa(ifa); return 0; } 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) 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){ myinet_free_ifa(ifa); return -EEXIST; } if (ifa1->ifa_scope != ifa->ifa_scope){ myinet_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; } ifa->ifa_next = *ifap; *ifap = ifa; myrtmsg_ifa(RTM_NEWADDR, ifa); notifier_call_chain(&myinetaddr_chain, NETDEV_UP, ifa); return 0;}static void myinetdev_changename(struct net_device *dev, struct in_device *in_dev)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -