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

📄 addrconf.c

📁 ipv6地址转换器
💻 C
📖 第 1 页 / 共 3 页
字号:
		rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex;		ip6_route_add(&rtmsg);	}}/* *	Duplicate Address Detection */static void addrconf_dad_start(struct inet6_ifaddr *ifp){	struct device *dev;	unsigned long rand_num;	dev = ifp->idev->dev;	addrconf_join_solict(dev, &ifp->addr);	if (ifp->prefix_len != 128 && (ifp->flags&ADDR_PERMANENT))		addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, 0, RTF_ADDRCONF);	if (dev->flags&(IFF_NOARP|IFF_LOOPBACK)) {		start_bh_atomic();		ifp->flags &= ~DAD_INCOMPLETE;		addrconf_dad_completed(ifp);		end_bh_atomic();		return;	}	net_srandom(ifp->addr.s6_addr32[3]);	ifp->probes = ifp->idev->cnf.dad_transmits;	ifp->flags |= DAD_INCOMPLETE;	rand_num = net_random() % ifp->idev->cnf.rtr_solicit_delay;	ifp->timer.function = addrconf_dad_timer;	ifp->timer.expires = jiffies + rand_num;	add_timer(&ifp->timer);}static void addrconf_dad_timer(unsigned long data){	struct inet6_ifaddr *ifp;	struct in6_addr unspec;	struct in6_addr mcaddr;	ifp = (struct inet6_ifaddr *) data;	if (ifp->probes == 0) {		/*		 * DAD was successful		 */		ifp->flags &= ~DAD_INCOMPLETE;		addrconf_dad_completed(ifp);		return;	}	ifp->probes--;	/* send a neighbour solicitation for our addr */	memset(&unspec, 0, sizeof(unspec));#ifdef CONFIG_IPV6_EUI64	addrconf_addr_solict_mult_new(&ifp->addr, &mcaddr);	ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec);#endif#ifndef CONFIG_IPV6_NO_PB	addrconf_addr_solict_mult_old(&ifp->addr, &mcaddr);	ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec);#endif	ifp->timer.expires = jiffies + ifp->idev->cnf.rtr_solicit_interval;	add_timer(&ifp->timer);}static void addrconf_dad_completed(struct inet6_ifaddr *ifp){	struct device *	dev = ifp->idev->dev;	/*	 *	Configure the address for reception. Now it is valid.	 */	ipv6_ifa_notify(RTM_NEWADDR, ifp);	/* If added prefix is link local and forwarding is off,	   start sending router solicitations.	 */	if (ifp->idev->cnf.forwarding == 0 &&	    (dev->flags&IFF_LOOPBACK) == 0 &&	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {		struct in6_addr all_routers;		ipv6_addr_all_routers(&all_routers);		/*		 *	If a host as already performed a random delay		 *	[...] as part of DAD [...] there is no need		 *	to delay again before sending the first RS		 */		ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers);		ifp->probes = 1;		ifp->timer.function = addrconf_rs_timer;		ifp->timer.expires = (jiffies +				      ifp->idev->cnf.rtr_solicit_interval);		ifp->idev->if_flags |= IF_RS_SENT;		add_timer(&ifp->timer);	}}#ifdef CONFIG_PROC_FSstatic int iface_proc_info(char *buffer, char **start, off_t offset,			   int length, int dummy){	struct inet6_ifaddr *ifp;	int i;	int len = 0;	off_t pos=0;	off_t begin=0;	addrconf_lock();	for (i=0; i < IN6_ADDR_HSIZE; i++) {		for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) {			int j;			for (j=0; j<16; j++) {				sprintf(buffer + len, "%02x",					ifp->addr.s6_addr[j]);				len += 2;			}			len += sprintf(buffer + len,				       " %02x %02x %02x %02x %8s\n",				       ifp->idev->dev->ifindex,				       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)				goto done;		}	}done:	addrconf_unlock();	*start=buffer+(offset-begin);	len-=(offset-begin);	if(len>length)		len=length;	if(len<0)		len=0;	return len;}struct proc_dir_entry iface_proc_entry ={        0, 8, "if_inet6",        S_IFREG | S_IRUGO, 1, 0, 0,        0, NULL,        &iface_proc_info};#endif	/* CONFIG_PROC_FS *//* *	Periodic address status verification */void addrconf_verify(unsigned long foo){	struct inet6_ifaddr *ifp;	unsigned long now = jiffies;	int i;	if (atomic_read(&addr_list_lock)) {		addr_chk_timer.expires = jiffies + 1*HZ;		add_timer(&addr_chk_timer);		return;	}	for (i=0; i < IN6_ADDR_HSIZE; i++) {		for (ifp=inet6_addr_lst[i]; ifp;) {			if (ifp->flags & ADDR_INVALID) {				struct inet6_ifaddr *bp = ifp;				ifp= ifp->lst_next;				ipv6_del_addr(bp);				continue;			}			if (!(ifp->flags & ADDR_PERMANENT)) {				struct inet6_ifaddr *bp;				unsigned long age;				age = (now - ifp->tstamp) / HZ;				bp = ifp;				ifp= ifp->lst_next;								if (age > bp->valid_lft)					ipv6_del_addr(bp);				else if (age > bp->prefered_lft) {					bp->flags |= ADDR_DEPRECATED;					ipv6_ifa_notify(0, bp);				}				continue;			}			ifp = ifp->lst_next;		}	}	addr_chk_timer.expires = jiffies + ADDR_CHECK_FREQUENCY;	add_timer(&addr_chk_timer);}#ifdef CONFIG_RTNETLINKstatic 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 & ~ADDR_INVALID;	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;		start_bh_atomic();		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) {				end_bh_atomic();				goto done;			}		}		end_bh_atomic();	}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,			},};#endifstatic void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp){#ifdef CONFIG_RTNETLINK	inet6_ifa_notify(event ? : RTM_NEWADDR, ifp);#endif	switch (event) {	case RTM_NEWADDR:		ip6_rt_addr_add(&ifp->addr, ifp->idev->dev);		break;	case RTM_DELADDR:		start_bh_atomic();		addrconf_leave_solict(ifp->idev->dev, &ifp->addr);		if (ipv6_chk_addr(&ifp->addr, ifp->idev->dev, 0) == NULL)			ip6_rt_addr_del(&ifp->addr, ifp->idev->dev);		end_bh_atomic();		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 device *dev = dev_get_by_index(ctl->ctl_name);			if (dev)				idev = ipv6_get_idev(dev);			if (idev == NULL)				return ret;		} else			ipv6_devconf_dflt.forwarding = ipv6_devconf.forwarding;		addrconf_forward_change(idev);		if (*valp) {			start_bh_atomic();			rt6_purge_dflt_routers(0);			end_bh_atomic();		}	}        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 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/* *	Init / cleanup code */__initfunc(void addrconf_init(void)){#ifdef MODULE	struct device *dev;	/* This takes sense only during module load. */	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:				addrconf_dev_config(dev);			break;		default:			/* Ignore all other */		}	}#endif	#ifdef CONFIG_PROC_FS	proc_net_register(&iface_proc_entry);#endif		addr_chk_timer.expires = jiffies + ADDR_CHECK_FREQUENCY;	add_timer(&addr_chk_timer);#ifdef CONFIG_RTNETLINK	rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;#endif#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 inet6_dev *idev; 	struct inet6_ifaddr *ifa;	int i;#ifdef CONFIG_RTNETLINK	rtnetlink_links[PF_INET6] = NULL;#endif#ifdef CONFIG_SYSCTL	addrconf_sysctl_unregister(&ipv6_devconf_dflt);	addrconf_sysctl_unregister(&ipv6_devconf);#endif	del_timer(&addr_chk_timer);	/*	 *	clean dev list.	 */	for (i=0; i < IN6_ADDR_HSIZE; i++) {		struct inet6_dev *next;		for (idev = inet6_dev_lst[i]; idev; idev = next) {			next = idev->next;			addrconf_ifdown(idev->dev, 1);		}	}	start_bh_atomic();	/*	 *	clean addr_list	 */	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.			 */		}	}	end_bh_atomic();#ifdef CONFIG_PROC_FS	proc_net_unregister(iface_proc_entry.low_ino);#endif}#endif	/* MODULE */

⌨️ 快捷键说明

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