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

📄 addrconf.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 4 页
字号:
				       ifp->prefix_len,				       ifp->scope,				       ifp->flags,				       ifp->idev->dev->name);			pos=begin+len;			if(pos<offset) {				len=0;				begin=pos;			}			if(pos>offset+length) {				read_unlock_bh(&addrconf_hash_lock);				goto done;			}		}		read_unlock_bh(&addrconf_hash_lock);	}done:	*start=buffer+(offset-begin);	len-=(offset-begin);	if(len>length)		len=length;	if(len<0)		len=0;	return len;}#endif	/* CONFIG_PROC_FS *//* *	Periodic address status verification */void addrconf_verify(unsigned long foo){	struct inet6_ifaddr *ifp;	unsigned long now = jiffies;	int i;	for (i=0; i < IN6_ADDR_HSIZE; i++) {restart:		write_lock(&addrconf_hash_lock);		for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) {			unsigned long age;			if (ifp->flags & IFA_F_PERMANENT)				continue;			age = (now - ifp->tstamp) / HZ;			if (age > ifp->valid_lft) {				in6_ifa_hold(ifp);				write_unlock(&addrconf_hash_lock);				ipv6_del_addr(ifp);				goto restart;			} else if (age > ifp->prefered_lft) {				int deprecate = 0;				spin_lock(&ifp->lock);				if (!(ifp->flags&IFA_F_DEPRECATED)) {					deprecate = 1;					ifp->flags |= IFA_F_DEPRECATED;				}				spin_unlock(&ifp->lock);				if (deprecate) {					in6_ifa_hold(ifp);					write_unlock(&addrconf_hash_lock);					ipv6_ifa_notify(0, ifp);					in6_ifa_put(ifp);					goto restart;				}			}		}		write_unlock(&addrconf_hash_lock);	}	mod_timer(&addr_chk_timer, jiffies + ADDR_CHECK_FREQUENCY);}static intinet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg){	struct rtattr **rta = arg;	struct ifaddrmsg *ifm = NLMSG_DATA(nlh);	struct in6_addr *pfx;	pfx = NULL;	if (rta[IFA_ADDRESS-1]) {		if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*pfx))			return -EINVAL;		pfx = RTA_DATA(rta[IFA_ADDRESS-1]);	}	if (rta[IFA_LOCAL-1]) {		if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))			return -EINVAL;		pfx = RTA_DATA(rta[IFA_LOCAL-1]);	}	if (pfx == NULL)		return -EINVAL;	return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen);}static intinet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg){	struct rtattr  **rta = arg;	struct ifaddrmsg *ifm = NLMSG_DATA(nlh);	struct in6_addr *pfx;	pfx = NULL;	if (rta[IFA_ADDRESS-1]) {		if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*pfx))			return -EINVAL;		pfx = RTA_DATA(rta[IFA_ADDRESS-1]);	}	if (rta[IFA_LOCAL-1]) {		if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))			return -EINVAL;		pfx = RTA_DATA(rta[IFA_LOCAL-1]);	}	if (pfx == NULL)		return -EINVAL;	return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen);}static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,			     u32 pid, u32 seq, int event){	struct ifaddrmsg *ifm;	struct nlmsghdr  *nlh;	struct ifa_cacheinfo ci;	unsigned char	 *b = skb->tail;	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));	ifm = NLMSG_DATA(nlh);	ifm->ifa_family = AF_INET6;	ifm->ifa_prefixlen = ifa->prefix_len;	ifm->ifa_flags = ifa->flags;	ifm->ifa_scope = RT_SCOPE_UNIVERSE;	if (ifa->scope&IFA_HOST)		ifm->ifa_scope = RT_SCOPE_HOST;	else if (ifa->scope&IFA_LINK)		ifm->ifa_scope = RT_SCOPE_LINK;	else if (ifa->scope&IFA_SITE)		ifm->ifa_scope = RT_SCOPE_SITE;	ifm->ifa_index = ifa->idev->dev->ifindex;	RTA_PUT(skb, IFA_ADDRESS, 16, &ifa->addr);	if (!(ifa->flags&IFA_F_PERMANENT)) {		ci.ifa_prefered = ifa->prefered_lft;		ci.ifa_valid = ifa->valid_lft;		if (ci.ifa_prefered != 0xFFFFFFFF) {			long tval = (jiffies - ifa->tstamp)/HZ;			ci.ifa_prefered -= tval;			if (ci.ifa_valid != 0xFFFFFFFF)				ci.ifa_valid -= tval;		}		RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);	}	nlh->nlmsg_len = skb->tail - b;	return skb->len;nlmsg_failure:rtattr_failure:	skb_trim(skb, b - skb->data);	return -1;}static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb){	int idx, ip_idx;	int s_idx, s_ip_idx; 	struct inet6_ifaddr *ifa;	s_idx = cb->args[0];	s_ip_idx = ip_idx = cb->args[1];	for (idx=0; idx < IN6_ADDR_HSIZE; idx++) {		if (idx < s_idx)			continue;		if (idx > s_idx)			s_ip_idx = 0;		read_lock_bh(&addrconf_hash_lock);		for (ifa=inet6_addr_lst[idx], ip_idx = 0; ifa;		     ifa = ifa->lst_next, ip_idx++) {			if (ip_idx < s_ip_idx)				continue;			if (inet6_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,					      cb->nlh->nlmsg_seq, RTM_NEWADDR) <= 0) {				read_unlock_bh(&addrconf_hash_lock);				goto done;			}		}		read_unlock_bh(&addrconf_hash_lock);	}done:	cb->args[0] = idx;	cb->args[1] = ip_idx;	return skb->len;}static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa){	struct sk_buff *skb;	int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128);	skb = alloc_skb(size, GFP_ATOMIC);	if (!skb) {		netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFADDR, ENOBUFS);		return;	}	if (inet6_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {		kfree_skb(skb);		netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFADDR, EINVAL);		return;	}	NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_IFADDR;	netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_IFADDR, GFP_ATOMIC);}static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX-RTM_BASE+1] ={	{ NULL,			NULL,			},	{ NULL,			NULL,			},	{ NULL,			NULL,			},	{ NULL,			NULL,			},	{ inet6_rtm_newaddr,	NULL,			},	{ inet6_rtm_deladdr,	NULL,			},	{ NULL,			inet6_dump_ifaddr,	},	{ NULL,			NULL,			},	{ inet6_rtm_newroute,	NULL,			},	{ inet6_rtm_delroute,	NULL,			},	{ inet6_rtm_getroute,	inet6_dump_fib,		},	{ NULL,			NULL,			},};static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp){	inet6_ifa_notify(event ? : RTM_NEWADDR, ifp);	switch (event) {	case RTM_NEWADDR:		ip6_rt_addr_add(&ifp->addr, ifp->idev->dev);		break;	case RTM_DELADDR:		addrconf_leave_solict(ifp->idev->dev, &ifp->addr);		if (!ipv6_chk_addr(&ifp->addr, ifp->idev->dev))			ip6_rt_addr_del(&ifp->addr, ifp->idev->dev);		break;	}}#ifdef CONFIG_SYSCTLstaticint addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,			   void *buffer, size_t *lenp){	int *valp = ctl->data;	int val = *valp;	int ret;	ret = proc_dointvec(ctl, write, filp, buffer, lenp);	if (write && *valp != val && valp != &ipv6_devconf_dflt.forwarding) {		struct inet6_dev *idev = NULL;		if (valp != &ipv6_devconf.forwarding) {			struct net_device *dev = dev_get_by_index(ctl->ctl_name);			if (dev) {				idev = in6_dev_get(dev);				dev_put(dev);			}			if (idev == NULL)				return ret;		} else			ipv6_devconf_dflt.forwarding = ipv6_devconf.forwarding;		addrconf_forward_change(idev);		if (*valp)			rt6_purge_dflt_routers(0);		if (idev)			in6_dev_put(idev);	}        return ret;}static struct addrconf_sysctl_table{	struct ctl_table_header *sysctl_header;	ctl_table addrconf_vars[11];	ctl_table addrconf_dev[2];	ctl_table addrconf_conf_dir[2];	ctl_table addrconf_proto_dir[2];	ctl_table addrconf_root_dir[2];} addrconf_sysctl = {	NULL,        {{NET_IPV6_FORWARDING, "forwarding",         &ipv6_devconf.forwarding, sizeof(int), 0644, NULL,         &addrconf_sysctl_forward},	{NET_IPV6_HOP_LIMIT, "hop_limit",         &ipv6_devconf.hop_limit, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_IPV6_MTU, "mtu",         &ipv6_devconf.mtu6, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_IPV6_ACCEPT_RA, "accept_ra",         &ipv6_devconf.accept_ra, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_IPV6_ACCEPT_REDIRECTS, "accept_redirects",         &ipv6_devconf.accept_redirects, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_IPV6_AUTOCONF, "autoconf",         &ipv6_devconf.autoconf, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_IPV6_DAD_TRANSMITS, "dad_transmits",         &ipv6_devconf.dad_transmits, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_IPV6_RTR_SOLICITS, "router_solicitations",         &ipv6_devconf.rtr_solicits, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_IPV6_RTR_SOLICIT_INTERVAL, "router_solicitation_interval",         &ipv6_devconf.rtr_solicit_interval, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies},	{NET_IPV6_RTR_SOLICIT_DELAY, "router_solicitation_delay",         &ipv6_devconf.rtr_solicit_delay, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies},	{0}},	{{NET_PROTO_CONF_ALL, "all", NULL, 0, 0555, addrconf_sysctl.addrconf_vars},{0}},	{{NET_IPV6_CONF, "conf", NULL, 0, 0555, addrconf_sysctl.addrconf_dev},{0}},	{{NET_IPV6, "ipv6", NULL, 0, 0555, addrconf_sysctl.addrconf_conf_dir},{0}},	{{CTL_NET, "net", NULL, 0, 0555, addrconf_sysctl.addrconf_proto_dir},{0}}};static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf *p){	int i;	struct net_device *dev = idev ? idev->dev : NULL;	struct addrconf_sysctl_table *t;	t = kmalloc(sizeof(*t), GFP_KERNEL);	if (t == NULL)		return;	memcpy(t, &addrconf_sysctl, sizeof(*t));	for (i=0; i<sizeof(t->addrconf_vars)/sizeof(t->addrconf_vars[0])-1; i++) {		t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf;		t->addrconf_vars[i].de = NULL;	}	if (dev) {		t->addrconf_dev[0].procname = dev->name;		t->addrconf_dev[0].ctl_name = dev->ifindex;	} else {		t->addrconf_dev[0].procname = "default";		t->addrconf_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;	}	t->addrconf_dev[0].child = t->addrconf_vars;	t->addrconf_dev[0].de = NULL;	t->addrconf_conf_dir[0].child = t->addrconf_dev;	t->addrconf_conf_dir[0].de = NULL;	t->addrconf_proto_dir[0].child = t->addrconf_conf_dir;	t->addrconf_proto_dir[0].de = NULL;	t->addrconf_root_dir[0].child = t->addrconf_proto_dir;	t->addrconf_root_dir[0].de = NULL;	t->sysctl_header = register_sysctl_table(t->addrconf_root_dir, 0);	if (t->sysctl_header == NULL)		kfree(t);	else		p->sysctl = t;}static void addrconf_sysctl_unregister(struct ipv6_devconf *p){	if (p->sysctl) {		struct addrconf_sysctl_table *t = p->sysctl;		p->sysctl = NULL;		unregister_sysctl_table(t->sysctl_header);		kfree(t);	}}#endif/* *      Device notifier */int register_inet6addr_notifier(struct notifier_block *nb){        return notifier_chain_register(&inet6addr_chain, nb);}int unregister_inet6addr_notifier(struct notifier_block *nb){        return notifier_chain_unregister(&inet6addr_chain,nb);}/* *	Init / cleanup code */void __init addrconf_init(void){#ifdef MODULE	struct net_device *dev;	/* This takes sense only during module load. */	rtnl_lock();	for (dev = dev_base; dev; dev = dev->next) {		if (!(dev->flags&IFF_UP))			continue;		switch (dev->type) {		case ARPHRD_LOOPBACK:				init_loopback(dev);			break;		case ARPHRD_ETHER:		case ARPHRD_FDDI:		case ARPHRD_IEEE802_TR:				addrconf_dev_config(dev);			break;		default:;			/* Ignore all other */		}	}	rtnl_unlock();#endif#ifdef CONFIG_PROC_FS	proc_net_create("if_inet6", 0, iface_proc_info);#endif		addr_chk_timer.expires = jiffies + ADDR_CHECK_FREQUENCY;	add_timer(&addr_chk_timer);	rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;#ifdef CONFIG_SYSCTL	addrconf_sysctl.sysctl_header =		register_sysctl_table(addrconf_sysctl.addrconf_root_dir, 0);	addrconf_sysctl_register(NULL, &ipv6_devconf_dflt);#endif}#ifdef MODULEvoid addrconf_cleanup(void){ 	struct net_device *dev; 	struct inet6_dev *idev; 	struct inet6_ifaddr *ifa;	int i;	rtnetlink_links[PF_INET6] = NULL;#ifdef CONFIG_SYSCTL	addrconf_sysctl_unregister(&ipv6_devconf_dflt);	addrconf_sysctl_unregister(&ipv6_devconf);#endif	rtnl_lock();	/*	 *	clean dev list.	 */	for (dev=dev_base; dev; dev=dev->next) {		if ((idev = __in6_dev_get(dev)) == NULL)			continue;		addrconf_ifdown(dev, 1);	}	/*	 *	Check hash table.	 */	write_lock_bh(&addrconf_hash_lock);	for (i=0; i < IN6_ADDR_HSIZE; i++) {		for (ifa=inet6_addr_lst[i]; ifa; ) {			struct inet6_ifaddr *bifa;			bifa = ifa;			ifa = ifa->lst_next;			printk(KERN_DEBUG "bug: IPv6 address leakage detected: ifa=%p\n", bifa);			/* Do not free it; something is wrong.			   Now we can investigate it with debugger.			 */		}	}	write_unlock_bh(&addrconf_hash_lock);	del_timer(&addr_chk_timer);	rtnl_unlock();#ifdef CONFIG_PROC_FS	proc_net_remove("if_inet6");#endif}#endif	/* MODULE */

⌨️ 快捷键说明

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