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

📄 route.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 3 页
字号:
{	struct flow_rule *frule;	struct rt6_info *nrt = NULL;	struct pol_chain *pol;	for (pol = rt6_pol_list; pol; pol = pol->next) {		struct fib6_node *fn;		struct rt6_info *sprt;		fn = fib6_lookup(pol->rules, daddr, saddr);		do {			for (sprt = fn->leaf; sprt; sprt=sprt->u.next) {				int res;				frule = sprt->rt6i_flowr;#if RT6_DEBUG >= 2				if (frule == NULL) {					printk(KERN_DEBUG "NULL flowr\n");					goto error;				}#endif				res = frule->ops->accept(rt, sprt, args, &nrt);				switch (res) {				case FLOWR_SELECT:					goto found;				case FLOWR_CLEAR:					goto next_policy;				case FLOWR_NODECISION:					break;				default:					goto error;				};			}			fn = fn->parent;		} while ((fn->fn_flags & RTN_TL_ROOT) == 0);	next_policy:	}error:	dst_clone(&ip6_null_entry.u.dst);	return &ip6_null_entry;found:	if (nrt == NULL)		goto error;	nrt->rt6i_flags |= RTF_CACHE;	dst_clone(&nrt->u.dst);	err = rt6_ins(nrt);	if (err)		nrt->u.dst.error = err;	return nrt;}#endifstatic int fib6_ifdown(struct rt6_info *rt, void *arg){	if (((void*)rt->rt6i_dev == arg || arg == NULL) &&	    rt != &ip6_null_entry) {		RT6_TRACE("deleted by ifdown %p\n", rt);		return -1;	}	return 0;}void rt6_ifdown(struct net_device *dev){	write_lock_bh(&rt6_lock);	fib6_clean_tree(&ip6_routing_table, fib6_ifdown, 0, dev);	write_unlock_bh(&rt6_lock);}struct rt6_mtu_change_arg{	struct net_device *dev;	unsigned mtu;};static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg){	struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg;	/* In IPv6 pmtu discovery is not optional,	   so that RTAX_MTU lock cannot disable it.	   We still use this lock to block changes	   caused by addrconf/ndisc.	*/	if (rt->rt6i_dev == arg->dev &&	    rt->u.dst.pmtu > arg->mtu &&	    !(rt->u.dst.mxlock&(1<<RTAX_MTU)))		rt->u.dst.pmtu = arg->mtu;	rt->u.dst.advmss = max_t(unsigned int, arg->mtu - 60, ip6_rt_min_advmss);	if (rt->u.dst.advmss > 65535-20)		rt->u.dst.advmss = 65535;	return 0;}void rt6_mtu_change(struct net_device *dev, unsigned mtu){	struct rt6_mtu_change_arg arg;	arg.dev = dev;	arg.mtu = mtu;	read_lock_bh(&rt6_lock);	fib6_clean_tree(&ip6_routing_table, rt6_mtu_change_route, 0, &arg);	read_unlock_bh(&rt6_lock);}static int inet6_rtm_to_rtmsg(struct rtmsg *r, struct rtattr **rta,			      struct in6_rtmsg *rtmsg){	memset(rtmsg, 0, sizeof(*rtmsg));	rtmsg->rtmsg_dst_len = r->rtm_dst_len;	rtmsg->rtmsg_src_len = r->rtm_src_len;	rtmsg->rtmsg_flags = RTF_UP;	if (r->rtm_type == RTN_UNREACHABLE)		rtmsg->rtmsg_flags |= RTF_REJECT;	if (rta[RTA_GATEWAY-1]) {		if (rta[RTA_GATEWAY-1]->rta_len != RTA_LENGTH(16))			return -EINVAL;		memcpy(&rtmsg->rtmsg_gateway, RTA_DATA(rta[RTA_GATEWAY-1]), 16);		rtmsg->rtmsg_flags |= RTF_GATEWAY;	}	if (rta[RTA_DST-1]) {		if (RTA_PAYLOAD(rta[RTA_DST-1]) < ((r->rtm_dst_len+7)>>3))			return -EINVAL;		memcpy(&rtmsg->rtmsg_dst, RTA_DATA(rta[RTA_DST-1]), ((r->rtm_dst_len+7)>>3));	}	if (rta[RTA_SRC-1]) {		if (RTA_PAYLOAD(rta[RTA_SRC-1]) < ((r->rtm_src_len+7)>>3))			return -EINVAL;		memcpy(&rtmsg->rtmsg_src, RTA_DATA(rta[RTA_SRC-1]), ((r->rtm_src_len+7)>>3));	}	if (rta[RTA_OIF-1]) {		if (rta[RTA_OIF-1]->rta_len != RTA_LENGTH(sizeof(int)))			return -EINVAL;		memcpy(&rtmsg->rtmsg_ifindex, RTA_DATA(rta[RTA_OIF-1]), sizeof(int));	}	if (rta[RTA_PRIORITY-1]) {		if (rta[RTA_PRIORITY-1]->rta_len != RTA_LENGTH(4))			return -EINVAL;		memcpy(&rtmsg->rtmsg_metric, RTA_DATA(rta[RTA_PRIORITY-1]), 4);	}	return 0;}int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg){	struct rtmsg *r = NLMSG_DATA(nlh);	struct in6_rtmsg rtmsg;	if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))		return -EINVAL;	return ip6_route_del(&rtmsg);}int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg){	struct rtmsg *r = NLMSG_DATA(nlh);	struct in6_rtmsg rtmsg;	if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))		return -EINVAL;	return ip6_route_add(&rtmsg);}struct rt6_rtnl_dump_arg{	struct sk_buff *skb;	struct netlink_callback *cb;};static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,			 struct in6_addr *dst,			 struct in6_addr *src,			 int iif,			 int type, u32 pid, u32 seq){	struct rtmsg *rtm;	struct nlmsghdr  *nlh;	unsigned char	 *b = skb->tail;	struct rta_cacheinfo ci;	nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*rtm));	rtm = NLMSG_DATA(nlh);	rtm->rtm_family = AF_INET6;	rtm->rtm_dst_len = rt->rt6i_dst.plen;	rtm->rtm_src_len = rt->rt6i_src.plen;	rtm->rtm_tos = 0;	rtm->rtm_table = RT_TABLE_MAIN;	if (rt->rt6i_flags&RTF_REJECT)		rtm->rtm_type = RTN_UNREACHABLE;	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 = RTPROT_BOOT;	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.mxlock) < 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 - rt->u.dst.lastuse;	if (rt->rt6i_expires)		ci.rta_expires = 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;	return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,			     NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq);}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;	struct sk_buff *skb;	struct flowi fl;	struct rt6_info *rt;	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);	if (skb == NULL)		return -ENOBUFS;	/* 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));	fl.proto = 0;	fl.nl_u.ip6_u.daddr = NULL;	fl.nl_u.ip6_u.saddr = NULL;	fl.uli_u.icmpt.type = 0;	fl.uli_u.icmpt.code = 0;	if (rta[RTA_SRC-1])		fl.nl_u.ip6_u.saddr = (struct in6_addr*)RTA_DATA(rta[RTA_SRC-1]);	if (rta[RTA_DST-1])		fl.nl_u.ip6_u.daddr = (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)			return -ENODEV;	}	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.nl_u.ip6_u.daddr,			    fl.nl_u.ip6_u.saddr,			    iif,			    RTM_NEWROUTE, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq);	if (err < 0)		return -EMSGSIZE;	err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);	if (err < 0)		return err;	return 0;}void inet6_rt_notify(int event, struct rt6_info *rt){	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) < 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_proc_stats(char *buffer, char **start, off_t offset, int length){	int len;	len = sprintf(buffer, "%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));	len -= offset;	if (len > length)		len = length;	if(len < 0)		len = 0;	*start = buffer + offset;	return len;}#endif	/* CONFIG_PROC_FS */#ifdef CONFIG_SYSCTLstatic int flush_delay;staticint ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp,			      void *buffer, size_t *lenp){	if (write) {		proc_dointvec(ctl, write, filp, buffer, lenp);		if (flush_delay < 0)			flush_delay = 0;		fib6_run_gc((unsigned long)flush_delay);		return 0;	} else		return -EINVAL;}ctl_table ipv6_route_table[] = {        {NET_IPV6_ROUTE_FLUSH, "flush",         &flush_delay, sizeof(int), 0644, NULL,         &ipv6_sysctl_rtcache_flush},	{NET_IPV6_ROUTE_GC_THRESH, "gc_thresh",         &ip6_dst_ops.gc_thresh, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_IPV6_ROUTE_MAX_SIZE, "max_size",         &ip6_rt_max_size, sizeof(int), 0644, NULL,         &proc_dointvec},	{NET_IPV6_ROUTE_GC_MIN_INTERVAL, "gc_min_interval",         &ip6_rt_gc_min_interval, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies, &sysctl_jiffies},	{NET_IPV6_ROUTE_GC_TIMEOUT, "gc_timeout",         &ip6_rt_gc_timeout, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies, &sysctl_jiffies},	{NET_IPV6_ROUTE_GC_INTERVAL, "gc_interval",         &ip6_rt_gc_interval, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies, &sysctl_jiffies},	{NET_IPV6_ROUTE_GC_ELASTICITY, "gc_elasticity",         &ip6_rt_gc_elasticity, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies, &sysctl_jiffies},	{NET_IPV6_ROUTE_MTU_EXPIRES, "mtu_expires",         &ip6_rt_mtu_expires, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies, &sysctl_jiffies},	{NET_IPV6_ROUTE_MIN_ADVMSS, "min_adv_mss",         &ip6_rt_min_advmss, sizeof(int), 0644, NULL,         &proc_dointvec_jiffies, &sysctl_jiffies},	 {0}};#endifvoid __init ip6_route_init(void){	ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache",						     sizeof(struct rt6_info),						     0, SLAB_HWCACHE_ALIGN,						     NULL, NULL);	fib6_init();#ifdef 	CONFIG_PROC_FS	proc_net_create("ipv6_route", 0, rt6_proc_info);	proc_net_create("rt6_stats", 0, rt6_proc_stats);#endif}#ifdef MODULEvoid ip6_route_cleanup(void){#ifdef CONFIG_PROC_FS	proc_net_remove("ipv6_route");	proc_net_remove("rt6_stats");#endif	rt6_ifdown(NULL);	fib6_gc_cleanup();}#endif	/* MODULE */

⌨️ 快捷键说明

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