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

📄 route.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
		 */		if (res.fi && res.prefixlen < 4) {			fib_info_put(res.fi);			res.fi = NULL;		}	}	rth = dst_alloc(&ipv4_dst_ops);	if (!rth)		goto e_nobufs;	atomic_set(&rth->u.dst.__refcnt, 1);	rth->u.dst.flags= DST_HOST;	if (in_dev->cnf.no_xfrm)		rth->u.dst.flags |= DST_NOXFRM;	if (in_dev->cnf.no_policy)		rth->u.dst.flags |= DST_NOPOLICY;	rth->fl.fl4_dst	= oldflp->fl4_dst;	rth->fl.fl4_tos	= tos;	rth->fl.fl4_src	= oldflp->fl4_src;	rth->fl.oif	= oldflp->oif;#ifdef CONFIG_IP_ROUTE_FWMARK	rth->fl.fl4_fwmark= oldflp->fl4_fwmark;#endif	rth->rt_dst	= fl.fl4_dst;	rth->rt_src	= fl.fl4_src;	rth->rt_iif	= oldflp->oif ? : dev_out->ifindex;	rth->u.dst.dev	= dev_out;	dev_hold(dev_out);	rth->idev	= in_dev_get(dev_out);	rth->rt_gateway = fl.fl4_dst;	rth->rt_spec_dst= fl.fl4_src;	rth->u.dst.output=ip_output;	RT_CACHE_STAT_INC(out_slow_tot);	if (flags & RTCF_LOCAL) {		rth->u.dst.input = ip_local_deliver;		rth->rt_spec_dst = fl.fl4_dst;	}	if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {		rth->rt_spec_dst = fl.fl4_src;		if (flags & RTCF_LOCAL && !(dev_out->flags & IFF_LOOPBACK)) {			rth->u.dst.output = ip_mc_output;			RT_CACHE_STAT_INC(out_slow_mc);		}#ifdef CONFIG_IP_MROUTE		if (res.type == RTN_MULTICAST) {			if (IN_DEV_MFORWARD(in_dev) &&			    !LOCAL_MCAST(oldflp->fl4_dst)) {				rth->u.dst.input = ip_mr_input;				rth->u.dst.output = ip_mc_output;			}		}#endif	}	rt_set_nexthop(rth, &res, 0);		rth->rt_flags = flags;	hash = rt_hash_code(oldflp->fl4_dst, oldflp->fl4_src ^ (oldflp->oif << 5), tos);	err = rt_intern_hash(hash, rth, rp);done:	if (free_res)		fib_res_put(&res);	if (dev_out)		dev_put(dev_out);	if (in_dev)		in_dev_put(in_dev);out:	return err;e_inval:	err = -EINVAL;	goto done;e_nobufs:	err = -ENOBUFS;	goto done;}int __ip_route_output_key(struct rtable **rp, const struct flowi *flp){	unsigned hash;	struct rtable *rth;	hash = rt_hash_code(flp->fl4_dst, flp->fl4_src ^ (flp->oif << 5), flp->fl4_tos);	rcu_read_lock_bh();	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;		rth = rcu_dereference(rth->u.rt_next)) {		if (rth->fl.fl4_dst == flp->fl4_dst &&		    rth->fl.fl4_src == flp->fl4_src &&		    rth->fl.iif == 0 &&		    rth->fl.oif == flp->oif &&#ifdef CONFIG_IP_ROUTE_FWMARK		    rth->fl.fl4_fwmark == flp->fl4_fwmark &&#endif		    !((rth->fl.fl4_tos ^ flp->fl4_tos) &			    (IPTOS_RT_MASK | RTO_ONLINK))) {			rth->u.dst.lastuse = jiffies;			dst_hold(&rth->u.dst);			rth->u.dst.__use++;			RT_CACHE_STAT_INC(out_hit);			rcu_read_unlock_bh();			*rp = rth;			return 0;		}		RT_CACHE_STAT_INC(out_hlist_search);	}	rcu_read_unlock_bh();	return ip_route_output_slow(rp, flp);}int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags){	int err;	if ((err = __ip_route_output_key(rp, flp)) != 0)		return err;	if (flp->proto) {		if (!flp->fl4_src)			flp->fl4_src = (*rp)->rt_src;		if (!flp->fl4_dst)			flp->fl4_dst = (*rp)->rt_dst;		return xfrm_lookup((struct dst_entry **)rp, flp, sk, flags);	}	return 0;}int ip_route_output_key(struct rtable **rp, struct flowi *flp){	return ip_route_output_flow(rp, flp, NULL, 0);}static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,			int nowait){	struct rtable *rt = (struct rtable*)skb->dst;	struct rtmsg *r;	struct nlmsghdr  *nlh;	unsigned char	 *b = skb->tail;	struct rta_cacheinfo ci;#ifdef CONFIG_IP_MROUTE	struct rtattr *eptr;#endif	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));	r = NLMSG_DATA(nlh);	nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;	r->rtm_family	 = AF_INET;	r->rtm_dst_len	= 32;	r->rtm_src_len	= 0;	r->rtm_tos	= rt->fl.fl4_tos;	r->rtm_table	= RT_TABLE_MAIN;	r->rtm_type	= rt->rt_type;	r->rtm_scope	= RT_SCOPE_UNIVERSE;	r->rtm_protocol = RTPROT_UNSPEC;	r->rtm_flags	= (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;	if (rt->rt_flags & RTCF_NOTIFY)		r->rtm_flags |= RTM_F_NOTIFY;	RTA_PUT(skb, RTA_DST, 4, &rt->rt_dst);	if (rt->fl.fl4_src) {		r->rtm_src_len = 32;		RTA_PUT(skb, RTA_SRC, 4, &rt->fl.fl4_src);	}	if (rt->u.dst.dev)		RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex);#ifdef CONFIG_NET_CLS_ROUTE	if (rt->u.dst.tclassid)		RTA_PUT(skb, RTA_FLOW, 4, &rt->u.dst.tclassid);#endif	if (rt->fl.iif)		RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_spec_dst);	else if (rt->rt_src != rt->fl.fl4_src)		RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_src);	if (rt->rt_dst != rt->rt_gateway)		RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway);	if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)		goto rtattr_failure;	ci.rta_lastuse	= jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);	ci.rta_used	= rt->u.dst.__use;	ci.rta_clntref	= atomic_read(&rt->u.dst.__refcnt);	if (rt->u.dst.expires)		ci.rta_expires = jiffies_to_clock_t(rt->u.dst.expires - jiffies);	else		ci.rta_expires = 0;	ci.rta_error	= rt->u.dst.error;	ci.rta_id	= ci.rta_ts = ci.rta_tsage = 0;	if (rt->peer) {		ci.rta_id = rt->peer->ip_id_count;		if (rt->peer->tcp_ts_stamp) {			ci.rta_ts = rt->peer->tcp_ts;			ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp;		}	}#ifdef CONFIG_IP_MROUTE	eptr = (struct rtattr*)skb->tail;#endif	RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);	if (rt->fl.iif) {#ifdef CONFIG_IP_MROUTE		u32 dst = rt->rt_dst;		if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&		    ipv4_devconf.mc_forwarding) {			int err = ipmr_get_route(skb, r, nowait);			if (err <= 0) {				if (!nowait) {					if (err == 0)						return 0;					goto nlmsg_failure;				} else {					if (err == -EMSGSIZE)						goto nlmsg_failure;					((struct rta_cacheinfo*)RTA_DATA(eptr))->rta_error = err;				}			}		} else#endif			RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif);	}	nlh->nlmsg_len = skb->tail - b;	return skb->len;nlmsg_failure:rtattr_failure:	skb_trim(skb, b - skb->data);	return -1;}int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg){	struct rtattr **rta = arg;	struct rtmsg *rtm = NLMSG_DATA(nlh);	struct rtable *rt = NULL;	u32 dst = 0;	u32 src = 0;	int iif = 0;	int err = -ENOBUFS;	struct sk_buff *skb;	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);	if (!skb)		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 iphdr));	if (rta[RTA_SRC - 1])		memcpy(&src, RTA_DATA(rta[RTA_SRC - 1]), 4);	if (rta[RTA_DST - 1])		memcpy(&dst, RTA_DATA(rta[RTA_DST - 1]), 4);	if (rta[RTA_IIF - 1])		memcpy(&iif, RTA_DATA(rta[RTA_IIF - 1]), sizeof(int));	if (iif) {		struct net_device *dev = __dev_get_by_index(iif);		err = -ENODEV;		if (!dev)			goto out_free;		skb->protocol	= htons(ETH_P_IP);		skb->dev	= dev;		local_bh_disable();		err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);		local_bh_enable();		rt = (struct rtable*)skb->dst;		if (!err && rt->u.dst.error)			err = -rt->u.dst.error;	} else {		struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst,							 .saddr = src,							 .tos = rtm->rtm_tos } } };		int oif = 0;		if (rta[RTA_OIF - 1])			memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int));		fl.oif = oif;		err = ip_route_output_key(&rt, &fl);	}	if (err)		goto out_free;	skb->dst = &rt->u.dst;	if (rtm->rtm_flags & RTM_F_NOTIFY)		rt->rt_flags |= RTCF_NOTIFY;	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;	err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,				RTM_NEWROUTE, 0);	if (!err)		goto out_free;	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;}int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb){	struct rtable *rt;	int h, s_h;	int idx, s_idx;	s_h = cb->args[0];	s_idx = idx = cb->args[1];	for (h = 0; h <= rt_hash_mask; h++) {		if (h < s_h) continue;		if (h > s_h)			s_idx = 0;		rcu_read_lock_bh();		for (rt = rcu_dereference(rt_hash_table[h].chain), idx = 0; rt;		     rt = rcu_dereference(rt->u.rt_next), idx++) {			if (idx < s_idx)				continue;			skb->dst = dst_clone(&rt->u.dst);			if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,					 cb->nlh->nlmsg_seq,					 RTM_NEWROUTE, 1) <= 0) {				dst_release(xchg(&skb->dst, NULL));				rcu_read_unlock_bh();				goto done;			}			dst_release(xchg(&skb->dst, NULL));		}		rcu_read_unlock_bh();	}done:	cb->args[0] = h;	cb->args[1] = idx;	return skb->len;}void ip_rt_multicast_event(struct in_device *in_dev){	rt_cache_flush(0);}#ifdef CONFIG_SYSCTLstatic int flush_delay;static int ipv4_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);		rt_cache_flush(flush_delay);		return 0;	} 	return -EINVAL;}static int ipv4_sysctl_rtcache_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 delay;	if (newlen != sizeof(int))		return -EINVAL;	if (get_user(delay, (int __user *)newval))		return -EFAULT; 	rt_cache_flush(delay); 	return 0;}ctl_table ipv4_route_table[] = {        {		.ctl_name 	= NET_IPV4_ROUTE_FLUSH,		.procname	= "flush",		.data		= &flush_delay,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &ipv4_sysctl_rtcache_flush,		.strategy	= &ipv4_sysctl_rtcache_flush_strategy,	},	{		.ctl_name	= NET_IPV4_ROUTE_MIN_DELAY,		.procname	= "min_delay",		.data		= &ip_rt_min_delay,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec_jiffies,		.strategy	= &sysctl_jiffies,	},	{		.ctl_name	= NET_IPV4_ROUTE_MAX_DELAY,		.procname	= "max_delay",		.data		= &ip_rt_max_delay,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec_jiffies,		.strategy	= &sysctl_jiffies,	},	{		.ctl_name	= NET_IPV4_ROUTE_GC_THRESH,		.procname	= "gc_thresh",		.data		= &ipv4_dst_ops.gc_thresh,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec,	},	{		.ctl_name	= NET_IPV4_ROUTE_MAX_SIZE,		.procname	= "max_size",		.data		= &ip_rt_max_size,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec,	},	{		.ctl_name	= NET_IPV4_ROUTE_GC_MIN_INTERVAL,		.procname	= "gc_min_interval",		.data		= &ip_rt_gc_min_interval,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec_jiffies,		.strategy	= &sysctl_jiffies,	},	{		.ctl_name	= NET_IPV4_ROUTE_GC_TIMEOUT,		.procname	= "gc_timeout",		.data		= &ip_rt_gc_timeout,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec_jiffies,		.strategy	= &sysctl_jiffies,	},	{		.ctl_name	= NET_IPV4_ROUTE_GC_INTERVAL,		.procname	= "gc_interval",		.data		= &ip_rt_gc_interval,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec_jiffies,		.strategy	= &sysctl_jiffies,	},	{		.ctl_name	= NET_IPV4_ROUTE_REDIRECT_LOAD,		.procname	= "redirect_load",		.data		= &ip_rt_redirect_load,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec,	},	{		.ctl_name	= NET_IPV4_ROUTE_REDIRECT_NUMBER,		.procname	= "redirect_number",		.data		= &ip_rt_redirect_number,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec,	},	{		.ctl_name	= NET_IPV4_ROUTE_REDIRECT_SILENCE,		.procname	= "redirect_silence",		.data		= &ip_rt_redirect_silence,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec,	},	{		.ctl_name	= NET_IPV4_ROUTE_ERROR_COST,		.procname	= "error_cost",		.data		= &ip_rt_error_cost,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec,	},	{		.ctl_name	= NET_IPV4_ROUTE_ERROR_BURST,		.procname	= "error_burst",		.data		= &ip_rt_error_burst,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec,	},	{		.ctl_name	= NET_IPV4_ROUTE_GC_ELASTICITY,		.procname	= "gc_elasticity",		.data		= &ip_rt_gc_elasticity,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec,	},	{		.ctl_name	= NET_IPV4_ROUTE_MTU_EXPIRES,		.procname	= "mtu_expires",		.data		= &ip_rt_mtu_expires,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &proc_dointvec_jiffies,		.strategy	= &sysctl_jiffies,	},	{		.ctl_name	= NET_IPV4_ROUTE_MIN_PMTU,		.procname	= "min_pmtu",		.data		= &ip_rt_min_pmtu,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	=

⌨️ 快捷键说明

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