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

📄 route.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
	else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK))		rtm->rtm_type = RTN_LOCAL;	else		rtm->rtm_type = RTN_UNICAST;	rtm->rtm_flags = 0;	rtm->rtm_scope = RT_SCOPE_UNIVERSE;	rtm->rtm_protocol = rt->rt6i_protocol;	if (rt->rt6i_flags&RTF_DYNAMIC)		rtm->rtm_protocol = RTPROT_REDIRECT;	else if (rt->rt6i_flags&(RTF_ADDRCONF|RTF_ALLONLINK))		rtm->rtm_protocol = RTPROT_KERNEL;	else if (rt->rt6i_flags&RTF_DEFAULT)		rtm->rtm_protocol = RTPROT_RA;	if (rt->rt6i_flags&RTF_CACHE)		rtm->rtm_flags |= RTM_F_CLONED;	if (dst) {		RTA_PUT(skb, RTA_DST, 16, dst);	        rtm->rtm_dst_len = 128;	} else if (rtm->rtm_dst_len)		RTA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr);#ifdef CONFIG_IPV6_SUBTREES	if (src) {		RTA_PUT(skb, RTA_SRC, 16, src);	        rtm->rtm_src_len = 128;	} else if (rtm->rtm_src_len)		RTA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr);#endif	if (iif)		RTA_PUT(skb, RTA_IIF, 4, &iif);	else if (dst) {		struct in6_addr saddr_buf;		if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0)			RTA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);	}	if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)		goto rtattr_failure;	if (rt->u.dst.neighbour)		RTA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key);	if (rt->u.dst.dev)		RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->rt6i_dev->ifindex);	RTA_PUT(skb, RTA_PRIORITY, 4, &rt->rt6i_metric);	ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);	if (rt->rt6i_expires)		ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies);	else		ci.rta_expires = 0;	ci.rta_used = rt->u.dst.__use;	ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);	ci.rta_error = rt->u.dst.error;	ci.rta_id = 0;	ci.rta_ts = 0;	ci.rta_tsage = 0;	RTA_PUT(skb, RTA_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 rt6_dump_route(struct rt6_info *rt, void *p_arg){	struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg;	int prefix;	if (arg->cb->nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(struct rtmsg))) {		struct rtmsg *rtm = NLMSG_DATA(arg->cb->nlh);		prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0;	} else		prefix = 0;	return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,		     NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,		     NULL, prefix);}static int fib6_dump_node(struct fib6_walker_t *w){	int res;	struct rt6_info *rt;	for (rt = w->leaf; rt; rt = rt->u.next) {		res = rt6_dump_route(rt, w->args);		if (res < 0) {			/* Frame is full, suspend walking */			w->leaf = rt;			return 1;		}		BUG_TRAP(res!=0);	}	w->leaf = NULL;	return 0;}static void fib6_dump_end(struct netlink_callback *cb){	struct fib6_walker_t *w = (void*)cb->args[0];	if (w) {		cb->args[0] = 0;		fib6_walker_unlink(w);		kfree(w);	}	if (cb->args[1]) {		cb->done = (void*)cb->args[1];		cb->args[1] = 0;	}}static int fib6_dump_done(struct netlink_callback *cb){	fib6_dump_end(cb);	return cb->done(cb);}int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb){	struct rt6_rtnl_dump_arg arg;	struct fib6_walker_t *w;	int res;	arg.skb = skb;	arg.cb = cb;	w = (void*)cb->args[0];	if (w == NULL) {		/* New dump:		 * 		 * 1. hook callback destructor.		 */		cb->args[1] = (long)cb->done;		cb->done = fib6_dump_done;		/*		 * 2. allocate and initialize walker.		 */		w = kmalloc(sizeof(*w), GFP_ATOMIC);		if (w == NULL)			return -ENOMEM;		RT6_TRACE("dump<%p", w);		memset(w, 0, sizeof(*w));		w->root = &ip6_routing_table;		w->func = fib6_dump_node;		w->args = &arg;		cb->args[0] = (long)w;		read_lock_bh(&rt6_lock);		res = fib6_walk(w);		read_unlock_bh(&rt6_lock);	} else {		w->args = &arg;		read_lock_bh(&rt6_lock);		res = fib6_walk_continue(w);		read_unlock_bh(&rt6_lock);	}#if RT6_DEBUG >= 3	if (res <= 0 && skb->len == 0)		RT6_TRACE("%p>dump end\n", w);#endif	res = res < 0 ? res : skb->len;	/* res < 0 is an error. (really, impossible)	   res == 0 means that dump is complete, but skb still can contain data.	   res > 0 dump is not complete, but frame is full.	 */	/* Destroy walker, if dump of this table is complete. */	if (res <= 0)		fib6_dump_end(cb);	return res;}int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg){	struct rtattr **rta = arg;	int iif = 0;	int err = -ENOBUFS;	struct sk_buff *skb;	struct flowi fl;	struct rt6_info *rt;	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);	if (skb == NULL)		goto out;	/* Reserve room for dummy headers, this skb can pass	   through good chunk of routing engine.	 */	skb->mac.raw = skb->data;	skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));	memset(&fl, 0, sizeof(fl));	if (rta[RTA_SRC-1])		ipv6_addr_copy(&fl.fl6_src,			       (struct in6_addr*)RTA_DATA(rta[RTA_SRC-1]));	if (rta[RTA_DST-1])		ipv6_addr_copy(&fl.fl6_dst,			       (struct in6_addr*)RTA_DATA(rta[RTA_DST-1]));	if (rta[RTA_IIF-1])		memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));	if (iif) {		struct net_device *dev;		dev = __dev_get_by_index(iif);		if (!dev) {			err = -ENODEV;			goto out_free;		}	}	fl.oif = 0;	if (rta[RTA_OIF-1])		memcpy(&fl.oif, RTA_DATA(rta[RTA_OIF-1]), sizeof(int));	rt = (struct rt6_info*)ip6_route_output(NULL, &fl);	skb->dst = &rt->u.dst;	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;	err = rt6_fill_node(skb, rt, 			    &fl.fl6_dst, &fl.fl6_src,			    iif,			    RTM_NEWROUTE, NETLINK_CB(in_skb).pid,			    nlh->nlmsg_seq, nlh, 0);	if (err < 0) {		err = -EMSGSIZE;		goto out_free;	}	err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);	if (err > 0)		err = 0;out:	return err;out_free:	kfree_skb(skb);	goto out;	}void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh){	struct sk_buff *skb;	int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);	skb = alloc_skb(size, gfp_any());	if (!skb) {		netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);		return;	}	if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh, 0) < 0) {		kfree_skb(skb);		netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);		return;	}	NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_ROUTE;	netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_ROUTE, gfp_any());}/* *	/proc */#ifdef CONFIG_PROC_FS#define RT6_INFO_LEN (32 + 4 + 32 + 4 + 32 + 40 + 5 + 1)struct rt6_proc_arg{	char *buffer;	int offset;	int length;	int skip;	int len;};static int rt6_info_route(struct rt6_info *rt, void *p_arg){	struct rt6_proc_arg *arg = (struct rt6_proc_arg *) p_arg;	int i;	if (arg->skip < arg->offset / RT6_INFO_LEN) {		arg->skip++;		return 0;	}	if (arg->len >= arg->length)		return 0;	for (i=0; i<16; i++) {		sprintf(arg->buffer + arg->len, "%02x",			rt->rt6i_dst.addr.s6_addr[i]);		arg->len += 2;	}	arg->len += sprintf(arg->buffer + arg->len, " %02x ",			    rt->rt6i_dst.plen);#ifdef CONFIG_IPV6_SUBTREES	for (i=0; i<16; i++) {		sprintf(arg->buffer + arg->len, "%02x",			rt->rt6i_src.addr.s6_addr[i]);		arg->len += 2;	}	arg->len += sprintf(arg->buffer + arg->len, " %02x ",			    rt->rt6i_src.plen);#else	sprintf(arg->buffer + arg->len,		"00000000000000000000000000000000 00 ");	arg->len += 36;#endif	if (rt->rt6i_nexthop) {		for (i=0; i<16; i++) {			sprintf(arg->buffer + arg->len, "%02x",				rt->rt6i_nexthop->primary_key[i]);			arg->len += 2;		}	} else {		sprintf(arg->buffer + arg->len,			"00000000000000000000000000000000");		arg->len += 32;	}	arg->len += sprintf(arg->buffer + arg->len,			    " %08x %08x %08x %08x %8s\n",			    rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt),			    rt->u.dst.__use, rt->rt6i_flags, 			    rt->rt6i_dev ? rt->rt6i_dev->name : "");	return 0;}static int rt6_proc_info(char *buffer, char **start, off_t offset, int length){	struct rt6_proc_arg arg;	arg.buffer = buffer;	arg.offset = offset;	arg.length = length;	arg.skip = 0;	arg.len = 0;	read_lock_bh(&rt6_lock);	fib6_clean_tree(&ip6_routing_table, rt6_info_route, 0, &arg);	read_unlock_bh(&rt6_lock);	*start = buffer;	if (offset)		*start += offset % RT6_INFO_LEN;	arg.len -= offset % RT6_INFO_LEN;	if (arg.len > length)		arg.len = length;	if (arg.len < 0)		arg.len = 0;	return arg.len;}extern struct rt6_statistics rt6_stats;static int rt6_stats_seq_show(struct seq_file *seq, void *v){	seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n",		      rt6_stats.fib_nodes, rt6_stats.fib_route_nodes,		      rt6_stats.fib_rt_alloc, rt6_stats.fib_rt_entries,		      rt6_stats.fib_rt_cache,		      atomic_read(&ip6_dst_ops.entries),		      rt6_stats.fib_discarded_routes);	return 0;}static int rt6_stats_seq_open(struct inode *inode, struct file *file){	return single_open(file, rt6_stats_seq_show, NULL);}static struct file_operations rt6_stats_seq_fops = {	.owner	 = THIS_MODULE,	.open	 = rt6_stats_seq_open,	.read	 = seq_read,	.llseek	 = seq_lseek,	.release = single_release,};#endif	/* CONFIG_PROC_FS */#ifdef CONFIG_SYSCTLstatic int flush_delay;staticint ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp,			      void __user *buffer, size_t *lenp, loff_t *ppos){	if (write) {		proc_dointvec(ctl, write, filp, buffer, lenp, ppos);		if (flush_delay < 0)			flush_delay = 0;		fib6_run_gc((unsigned long)flush_delay);		return 0;	} else		return -EINVAL;}ctl_table ipv6_route_table[] = {        {		.ctl_name	=	NET_IPV6_ROUTE_FLUSH, 		.procname	=	"flush",         	.data		=	&flush_delay,		.maxlen		=	sizeof(int),		.mode		=	0644,         	.proc_handler	=	&ipv6_sysctl_rtcache_flush	},	{		.ctl_name	=	NET_IPV6_ROUTE_GC_THRESH,		.procname	=	"gc_thresh",         	.data		=	&ip6_dst_ops.gc_thresh,		.maxlen		=	sizeof(int),		.mode		=	0644,         	.proc_handler	=	&proc_dointvec,	},	{		.ctl_name	=	NET_IPV6_ROUTE_MAX_SIZE,		.procname	=	"max_size",         	.data		=	&ip6_rt_max_size,		.maxlen		=	sizeof(int),		.mode		=	0644,         	.proc_handler	=	&proc_dointvec,	},	{		.ctl_name	=	NET_IPV6_ROUTE_GC_MIN_INTERVAL,		.procname	=	"gc_min_interval",         	.data		=	&ip6_rt_gc_min_interval,		.maxlen		=	sizeof(int),		.mode		=	0644,         	.proc_handler	=	&proc_dointvec_jiffies,		.strategy	=	&sysctl_jiffies,	},	{		.ctl_name	=	NET_IPV6_ROUTE_GC_TIMEOUT,		.procname	=	"gc_timeout",         	.data		=	&ip6_rt_gc_timeout,		.maxlen		=	sizeof(int),		.mode		=	0644,         	.proc_handler	=	&proc_dointvec_jiffies,		.strategy	=	&sysctl_jiffies,	},	{		.ctl_name	=	NET_IPV6_ROUTE_GC_INTERVAL,		.procname	=	"gc_interval",         	.data		=	&ip6_rt_gc_interval,		.maxlen		=	sizeof(int),		.mode		=	0644,         	.proc_handler	=	&proc_dointvec_jiffies,		.strategy	=	&sysctl_jiffies,	},	{		.ctl_name	=	NET_IPV6_ROUTE_GC_ELASTICITY,		.procname	=	"gc_elasticity",         	.data		=	&ip6_rt_gc_elasticity,		.maxlen		=	sizeof(int),		.mode		=	0644,         	.proc_handler	=	&proc_dointvec_jiffies,		.strategy	=	&sysctl_jiffies,	},	{		.ctl_name	=	NET_IPV6_ROUTE_MTU_EXPIRES,		.procname	=	"mtu_expires",         	.data		=	&ip6_rt_mtu_expires,		.maxlen		=	sizeof(int),		.mode		=	0644,         	.proc_handler	=	&proc_dointvec_jiffies,		.strategy	=	&sysctl_jiffies,	},	{		.ctl_name	=	NET_IPV6_ROUTE_MIN_ADVMSS,		.procname	=	"min_adv_mss",         	.data		=	&ip6_rt_min_advmss,		.maxlen		=	sizeof(int),		.mode		=	0644,         	.proc_handler	=	&proc_dointvec_jiffies,		.strategy	=	&sysctl_jiffies,	},	{ .ctl_name = 0 }};#endifvoid __init ip6_route_init(void){	struct proc_dir_entry *p;	ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache",						     sizeof(struct rt6_info),						     0, SLAB_HWCACHE_ALIGN,						     NULL, NULL);	if (!ip6_dst_ops.kmem_cachep)		panic("cannot create ip6_dst_cache");	fib6_init();#ifdef 	CONFIG_PROC_FS	p = proc_net_create("ipv6_route", 0, rt6_proc_info);	if (p)		p->owner = THIS_MODULE;	proc_net_fops_create("rt6_stats", S_IRUGO, &rt6_stats_seq_fops);#endif#ifdef CONFIG_XFRM	xfrm6_init();#endif}void __exit ip6_route_cleanup(void){#ifdef CONFIG_PROC_FS	proc_net_remove("ipv6_route");	proc_net_remove("rt6_stats");#endif#ifdef CONFIG_XFRM	xfrm6_fini();#endif	rt6_ifdown(NULL);	fib6_gc_cleanup();	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);}

⌨️ 快捷键说明

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