⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devinet.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
}static struct notifier_block ip_netdev_notifier = {	.notifier_call =inetdev_event,};static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,			    u32 pid, u32 seq, int event){	struct ifaddrmsg *ifm;	struct nlmsghdr  *nlh;	unsigned char	 *b = skb->tail;	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));	if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;	ifm = NLMSG_DATA(nlh);	ifm->ifa_family = AF_INET;	ifm->ifa_prefixlen = ifa->ifa_prefixlen;	ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT;	ifm->ifa_scope = ifa->ifa_scope;	ifm->ifa_index = ifa->ifa_dev->dev->ifindex;	if (ifa->ifa_address)		RTA_PUT(skb, IFA_ADDRESS, 4, &ifa->ifa_address);	if (ifa->ifa_local)		RTA_PUT(skb, IFA_LOCAL, 4, &ifa->ifa_local);	if (ifa->ifa_broadcast)		RTA_PUT(skb, IFA_BROADCAST, 4, &ifa->ifa_broadcast);	if (ifa->ifa_anycast)		RTA_PUT(skb, IFA_ANYCAST, 4, &ifa->ifa_anycast);	if (ifa->ifa_label[0])		RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);	nlh->nlmsg_len = skb->tail - b;	return skb->len;nlmsg_failure:rtattr_failure:	skb_trim(skb, b - skb->data);	return -1;}static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb){	int idx, ip_idx;	struct net_device *dev;	struct in_device *in_dev;	struct in_ifaddr *ifa;	int s_ip_idx, s_idx = cb->args[0];	s_ip_idx = ip_idx = cb->args[1];	read_lock(&dev_base_lock);	for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {		if (idx < s_idx)			continue;		if (idx > s_idx)			s_ip_idx = 0;		rcu_read_lock();		if ((in_dev = __in_dev_get(dev)) == NULL) {			rcu_read_unlock();			continue;		}		for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;		     ifa = ifa->ifa_next, ip_idx++) {			if (ip_idx < s_ip_idx)				continue;			if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,					     cb->nlh->nlmsg_seq,					     RTM_NEWADDR) <= 0) {				rcu_read_unlock();				goto done;			}		}		rcu_read_unlock();	}done:	read_unlock(&dev_base_lock);	cb->args[0] = idx;	cb->args[1] = ip_idx;	return skb->len;}static void rtmsg_ifa(int event, struct in_ifaddr* ifa){	int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + 128);	struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);	if (!skb)		netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, ENOBUFS);	else if (inet_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {		kfree_skb(skb);		netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, EINVAL);	} else {		NETLINK_CB(skb).dst_groups = RTMGRP_IPV4_IFADDR;		netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV4_IFADDR, GFP_KERNEL);	}}static struct rtnetlink_link inet_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {	 [4] = { .doit	 = inet_rtm_newaddr,  },	 [5] = { .doit	 = inet_rtm_deladdr,  },	 [6] = { .dumpit = inet_dump_ifaddr,  },	 [8] = { .doit	 = inet_rtm_newroute, },	 [9] = { .doit	 = inet_rtm_delroute, },	[10] = { .doit	 = inet_rtm_getroute, .dumpit = inet_dump_fib, },#ifdef CONFIG_IP_MULTIPLE_TABLES	[16] = { .doit	 = inet_rtm_newrule, },	[17] = { .doit	 = inet_rtm_delrule, },	[18] = { .dumpit = inet_dump_rules,  },#endif};#ifdef CONFIG_SYSCTLvoid inet_forward_change(void){	struct net_device *dev;	int on = ipv4_devconf.forwarding;	ipv4_devconf.accept_redirects = !on;	ipv4_devconf_dflt.forwarding = on;	read_lock(&dev_base_lock);	for (dev = dev_base; dev; dev = dev->next) {		struct in_device *in_dev;		rcu_read_lock();		in_dev = __in_dev_get(dev);		if (in_dev)			in_dev->cnf.forwarding = on;		rcu_read_unlock();	}	read_unlock(&dev_base_lock);	rt_cache_flush(0);}static int devinet_sysctl_forward(ctl_table *ctl, int write,				  struct file* filp, void __user *buffer,				  size_t *lenp, loff_t *ppos){	int *valp = ctl->data;	int val = *valp;	int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);	if (write && *valp != val) {		if (valp == &ipv4_devconf.forwarding)			inet_forward_change();		else if (valp != &ipv4_devconf_dflt.forwarding)			rt_cache_flush(0);	}	return ret;}int ipv4_doint_and_flush(ctl_table *ctl, int write,			 struct file* filp, void __user *buffer,			 size_t *lenp, loff_t *ppos){	int *valp = ctl->data;	int val = *valp;	int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);	if (write && *valp != val)		rt_cache_flush(0);	return ret;}int ipv4_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){	int *valp = table->data;	int new;	if (!newval || !newlen)		return 0;	if (newlen != sizeof(int))		return -EINVAL;	if (get_user(new, (int __user *)newval))		return -EFAULT;	if (new == *valp)		return 0;	if (oldval && oldlenp) {		size_t len;		if (get_user(len, oldlenp))			return -EFAULT;		if (len) {			if (len > table->maxlen)				len = table->maxlen;			if (copy_to_user(oldval, valp, len))				return -EFAULT;			if (put_user(len, oldlenp))				return -EFAULT;		}	}	*valp = new;	rt_cache_flush(0);	return 1;}static struct devinet_sysctl_table {	struct ctl_table_header *sysctl_header;	ctl_table		devinet_vars[20];	ctl_table		devinet_dev[2];	ctl_table		devinet_conf_dir[2];	ctl_table		devinet_proto_dir[2];	ctl_table		devinet_root_dir[2];} devinet_sysctl = {	.devinet_vars = {		{			.ctl_name	= NET_IPV4_CONF_FORWARDING,			.procname	= "forwarding",			.data		= &ipv4_devconf.forwarding,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &devinet_sysctl_forward,		},		{			.ctl_name	= NET_IPV4_CONF_MC_FORWARDING,			.procname	= "mc_forwarding",			.data		= &ipv4_devconf.mc_forwarding,			.maxlen		= sizeof(int),			.mode		= 0444,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_ACCEPT_REDIRECTS,			.procname	= "accept_redirects",			.data		= &ipv4_devconf.accept_redirects,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_SECURE_REDIRECTS,			.procname	= "secure_redirects",			.data		= &ipv4_devconf.secure_redirects,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_SHARED_MEDIA,			.procname	= "shared_media",			.data		= &ipv4_devconf.shared_media,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_RP_FILTER,			.procname	= "rp_filter",			.data		= &ipv4_devconf.rp_filter,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_SEND_REDIRECTS,			.procname	= "send_redirects",			.data		= &ipv4_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		= &ipv4_devconf.accept_source_route,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_PROXY_ARP,			.procname	= "proxy_arp",			.data		= &ipv4_devconf.proxy_arp,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_MEDIUM_ID,			.procname	= "medium_id",			.data		= &ipv4_devconf.medium_id,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_BOOTP_RELAY,			.procname	= "bootp_relay",			.data		= &ipv4_devconf.bootp_relay,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_LOG_MARTIANS,			.procname	= "log_martians",			.data		= &ipv4_devconf.log_martians,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_TAG,			.procname	= "tag",			.data		= &ipv4_devconf.tag,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_ARPFILTER,			.procname	= "arp_filter",			.data		= &ipv4_devconf.arp_filter,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_ARP_ANNOUNCE,			.procname	= "arp_announce",			.data		= &ipv4_devconf.arp_announce,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_ARP_IGNORE,			.procname	= "arp_ignore",			.data		= &ipv4_devconf.arp_ignore,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &proc_dointvec,		},		{			.ctl_name	= NET_IPV4_CONF_NOXFRM,			.procname	= "disable_xfrm",			.data		= &ipv4_devconf.no_xfrm,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &ipv4_doint_and_flush,			.strategy	= &ipv4_doint_and_flush_strategy,		},		{			.ctl_name	= NET_IPV4_CONF_NOPOLICY,			.procname	= "disable_policy",			.data		= &ipv4_devconf.no_policy,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &ipv4_doint_and_flush,			.strategy	= &ipv4_doint_and_flush_strategy,		},		{			.ctl_name	= NET_IPV4_CONF_FORCE_IGMP_VERSION,			.procname	= "force_igmp_version",			.data		= &ipv4_devconf.force_igmp_version,			.maxlen		= sizeof(int),			.mode		= 0644,			.proc_handler	= &ipv4_doint_and_flush,			.strategy	= &ipv4_doint_and_flush_strategy,		},	},	.devinet_dev = {		{			.ctl_name	= NET_PROTO_CONF_ALL,			.procname	= "all",			.mode		= 0555,			.child		= devinet_sysctl.devinet_vars,		},	},	.devinet_conf_dir = {	        {			.ctl_name	= NET_IPV4_CONF,			.procname	= "conf",			.mode		= 0555,			.child		= devinet_sysctl.devinet_dev,		},	},	.devinet_proto_dir = {		{			.ctl_name	= NET_IPV4,			.procname	= "ipv4",			.mode		= 0555,			.child 		= devinet_sysctl.devinet_conf_dir,		},	},	.devinet_root_dir = {		{			.ctl_name	= CTL_NET,			.procname 	= "net",			.mode		= 0555,			.child		= devinet_sysctl.devinet_proto_dir,		},	},};static void devinet_sysctl_register(struct in_device *in_dev,				    struct ipv4_devconf *p){	int i;	struct net_device *dev = in_dev ? in_dev->dev : NULL;	struct devinet_sysctl_table *t = kmalloc(sizeof(*t), GFP_KERNEL);	char *dev_name = NULL;	if (!t)		return;	memcpy(t, &devinet_sysctl, sizeof(*t));	for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {		t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;		t->devinet_vars[i].de = NULL;	}	if (dev) {		dev_name = dev->name; 		t->devinet_dev[0].ctl_name = dev->ifindex;	} else {		dev_name = "default";		t->devinet_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;	}	/* 	 * Make a copy of dev_name, because '.procname' is regarded as const 	 * by sysctl and we wouldn't want anyone to change it under our feet	 * (see SIOCSIFNAME).	 */		dev_name = net_sysctl_strdup(dev_name);	if (!dev_name)	    goto free;	t->devinet_dev[0].procname    = dev_name;	t->devinet_dev[0].child	      = t->devinet_vars;	t->devinet_dev[0].de	      = NULL;	t->devinet_conf_dir[0].child  = t->devinet_dev;	t->devinet_conf_dir[0].de     = NULL;	t->devinet_proto_dir[0].child = t->devinet_conf_dir;	t->devinet_proto_dir[0].de    = NULL;	t->devinet_root_dir[0].child  = t->devinet_proto_dir;	t->devinet_root_dir[0].de     = NULL;	t->sysctl_header = register_sysctl_table(t->devinet_root_dir, 0);	if (!t->sysctl_header)	    goto free_procname;	p->sysctl = t;	return;	/* error path */ free_procname:	kfree(dev_name); free:	kfree(t);	return;}static void devinet_sysctl_unregister(struct ipv4_devconf *p){	if (p->sysctl) {		struct devinet_sysctl_table *t = p->sysctl;		p->sysctl = NULL;		unregister_sysctl_table(t->sysctl_header);		kfree(t->devinet_dev[0].procname);		kfree(t);	}}#endifvoid __init devinet_init(void){	register_gifconf(PF_INET, inet_gifconf);	register_netdevice_notifier(&ip_netdev_notifier);	rtnetlink_links[PF_INET] = inet_rtnetlink_table;#ifdef CONFIG_SYSCTL	devinet_sysctl.sysctl_header =		register_sysctl_table(devinet_sysctl.devinet_root_dir, 0);	devinet_sysctl_register(NULL, &ipv4_devconf_dflt);#endif}EXPORT_SYMBOL(devinet_ioctl);EXPORT_SYMBOL(in_dev_finish_destroy);EXPORT_SYMBOL(inet_select_addr);EXPORT_SYMBOL(inetdev_by_index);EXPORT_SYMBOL(register_inetaddr_notifier);EXPORT_SYMBOL(unregister_inetaddr_notifier);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -