Exemplo n.º 1
0
static void ip6_sublist_rcv_finish(struct list_head *head)
{
	struct sk_buff *skb, *next;

	list_for_each_entry_safe(skb, next, head, list)
		dst_input(skb);
}
Exemplo n.º 2
0
int ip6_rcv_finish( struct sk_buff *skb)
{
	if (skb_dst(skb) == NULL)
		ip6_route_input(skb);

	return dst_input(skb);
}
Exemplo n.º 3
0
static int ip_rcv_finish(struct sk_buff *skb)
{
	const struct iphdr *iph = ip_hdr(skb);
	struct rtable *rt;

	if (sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {
		const struct net_protocol *ipprot;
		int protocol = iph->protocol;

		ipprot = rcu_dereference(inet_protos[protocol]);
		if (ipprot && ipprot->early_demux) {
			ipprot->early_demux(skb);
			/* must reload iph, skb->head might have changed */
			iph = ip_hdr(skb);
		}
	}

	/*
	 *	Initialise the virtual path cache for the packet. It describes
	 *	how the packet travels inside Linux networking.
	 */
	if (!skb_dst(skb)) {
		int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
					       iph->tos, skb->dev);
		if (unlikely(err)) {
			if (err == -EXDEV)
				NET_INC_STATS_BH(dev_net(skb->dev),
						 LINUX_MIB_IPRPFILTER);
			goto drop;
		}
	}

#ifdef CONFIG_IP_ROUTE_CLASSID
	if (unlikely(skb_dst(skb)->tclassid)) {
		struct ip_rt_acct *st = this_cpu_ptr(ip_rt_acct);
		u32 idx = skb_dst(skb)->tclassid;
		st[idx&0xFF].o_packets++;
		st[idx&0xFF].o_bytes += skb->len;
		st[(idx>>16)&0xFF].i_packets++;
		st[(idx>>16)&0xFF].i_bytes += skb->len;
	}
#endif

	if (iph->ihl > 5 && ip_rcv_options(skb))
		goto drop;

	rt = skb_rtable(skb);
	if (rt->rt_type == RTN_MULTICAST) {
		IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), IPSTATS_MIB_INMCAST,
				skb->len);
	} else if (rt->rt_type == RTN_BROADCAST)
		IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), IPSTATS_MIB_INBCAST,
				skb->len);

	return dst_input(skb);

drop:
	kfree_skb(skb);
	return NET_RX_DROP;
}
Exemplo n.º 4
0
/**
 * dn_route_rx_packet - Try and find a route for an incoming packet
 * @skb: The packet to find a route for
 *
 * Returns: result of input function if route is found, error code otherwise
 */
static int dn_route_rx_packet(struct sk_buff *skb)
{
	struct dn_skb_cb *cb = DN_SKB_CB(skb);
	int err;

	if ((err = dn_route_input(skb)) == 0)
		return dst_input(skb);

	if (decnet_debug_level & 4) {
		char *devname = skb->dev ? skb->dev->name : "???";
		struct dn_skb_cb *cb = DN_SKB_CB(skb);
		printk(KERN_DEBUG
			"DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n",
			(int)cb->rt_flags, devname, skb->len,
			dn_ntohs(cb->src), dn_ntohs(cb->dst),
			err, skb->pkt_type);
	}

	if ((skb->pkt_type == PACKET_HOST) && (cb->rt_flags & DN_RT_F_RQR)) {
		switch(cb->rt_flags & DN_RT_PKT_MSK) {
			case DN_RT_PKT_SHORT:
				return dn_return_short(skb);
			case DN_RT_PKT_LONG:
				return dn_return_long(skb);
		}
	}

	kfree_skb(skb);
	return NET_RX_DROP;
}
Exemplo n.º 5
0
static inline int ip6_rcv_finish( struct sk_buff *skb) 
{
	if (skb->dst == NULL)
		ip6_route_input(skb);

	return dst_input(skb);
}
Exemplo n.º 6
0
int ip_rcv_finish(struct sk_buff *skb)
{
    const struct iphdr *iph = ip_hdr(skb);
    struct rtable *rt;

    /*
     *	Initialise the virtual path cache for the packet. It describes
     *	how the packet travels inside Linux networking.
     */
    if (skb_dst(skb) == NULL) {
        int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
                                       iph->tos, skb->dev);
        if (unlikely(err)) {
            if (err == -EHOSTUNREACH)
                IP_INC_STATS_BH(dev_net(skb->dev),
                                IPSTATS_MIB_INADDRERRORS);
            else if (err == -ENETUNREACH)
                IP_INC_STATS_BH(dev_net(skb->dev),
                                IPSTATS_MIB_INNOROUTES);
            else if (err == -EXDEV)
                NET_INC_STATS_BH(dev_net(skb->dev),
                                 LINUX_MIB_IPRPFILTER);
            goto drop;
        }
    }

#ifdef CONFIG_IP_ROUTE_CLASSID
    if (unlikely(skb_dst(skb)->tclassid)) {
        struct ip_rt_acct *st = this_cpu_ptr(ip_rt_acct);
        u32 idx = skb_dst(skb)->tclassid;
        st[idx&0xFF].o_packets++;
        st[idx&0xFF].o_bytes += skb->len;
        st[(idx>>16)&0xFF].i_packets++;
        st[(idx>>16)&0xFF].i_bytes += skb->len;
    }
#endif

    if (iph->ihl > 5 && ip_rcv_options(skb))
        goto drop;

    rt = skb_rtable(skb);
    if (rt->rt_type == RTN_MULTICAST) {
        IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), IPSTATS_MIB_INMCAST,
                           skb->len);
    } else if (rt->rt_type == RTN_BROADCAST)
        IP_UPD_PO_STATS_BH(dev_net(rt->dst.dev), IPSTATS_MIB_INBCAST,
                           skb->len);

    return dst_input(skb);

drop:
    kfree_skb(skb);
    return NET_RX_DROP;
}
Exemplo n.º 7
0
int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
	/* if ingress device is enslaved to an L3 master device pass the
	 * skb to its handler for processing
	 */
	skb = l3mdev_ip6_rcv(skb);
	if (!skb)
		return NET_RX_SUCCESS;
	ip6_rcv_finish_core(net, sk, skb);

	return dst_input(skb);
}
Exemplo n.º 8
0
static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb)
{
	if (skb_dst(skb) == NULL) {
		const struct iphdr *iph = ip_hdr(skb);

		if (ip_route_input_noref(skb, iph->daddr, iph->saddr,
					 iph->tos, skb->dev))
			goto drop;
	}
	return dst_input(skb);
drop:
	kfree_skb(skb);
	return NET_RX_DROP;
}
Exemplo n.º 9
0
int ip6_rcv_finish(struct sk_buff *skb)
{
	if (sysctl_ip_early_demux && !skb_dst(skb)) {
		const struct inet6_protocol *ipprot;

		ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]);
		if (ipprot && ipprot->early_demux)
			ipprot->early_demux(skb);
	}
	if (!skb_dst(skb))
		ip6_route_input(skb);

	return dst_input(skb);
}
Exemplo n.º 10
0
static inline int ip_rcv_finish(struct sk_buff *skb)
{
	struct iphdr *iph = skb->nh.iph;

	/*
	 *	Initialise the virtual path cache for the packet. It describes
	 *	how the packet travels inside Linux networking.
	 */ 
	if (likely(skb->dst == NULL)) {


		/* TF1: CONFIG_VIPSEC */
        /* Function which does all the IPSec multicast/broadcast processing */
           if (ipsec_mcastforward_lookup_hook != NULL){
		 
              (*ipsec_mcastforward_lookup_hook)(skb);
		}
        /* TF1: CONFIG_VIPSEC */

		int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
					 skb->dev);
		if (unlikely(err)) {
			if (err == -EHOSTUNREACH)
				IP_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
			goto drop; 
		}
	}

#ifdef CONFIG_NET_CLS_ROUTE
	if (unlikely(skb->dst->tclassid)) {
		struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
		u32 idx = skb->dst->tclassid;
		st[idx&0xFF].o_packets++;
		st[idx&0xFF].o_bytes+=skb->len;
		st[(idx>>16)&0xFF].i_packets++;
		st[(idx>>16)&0xFF].i_bytes+=skb->len;
	}
#endif

	if (iph->ihl > 5 && ip_rcv_options(skb))
		goto drop;

	return dst_input(skb);

drop:
        kfree_skb(skb);
        return NET_RX_DROP;
}
Exemplo n.º 11
0
inline int ip6_rcv_finish( struct sk_buff *skb)
{
    /* <DTS2012092706169 w00211169 2012-10-20 begin */
    /* <DTS2012082701764 w00211169 2012-9-17 begin */
#if 0    
    if (skb->dst == NULL)
        ip6_fakesrc_process(skb);
#endif    
    /* DTS2012082701764 w00211169 2012-9-17 end> */
    /* DTS2012092706169 w00211169 2012-10-20 end> */
    
	if (skb->dst == NULL)
		ip6_route_input(skb);

	return dst_input(skb);
}
Exemplo n.º 12
0
static int ip_rcv_finish(struct sk_buff *skb)
{
	const struct iphdr *iph = ip_hdr(skb);
	struct rtable *rt;

	/*
	 *	Initialise the virtual path cache for the packet. It describes
	 *	how the packet travels inside Linux networking.
	 */
	if (skb->dst == NULL) {
		int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
					 skb->dev);
		if (unlikely(err)) {
			if (err == -EHOSTUNREACH)
				IP_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS);
			else if (err == -ENETUNREACH)
				IP_INC_STATS_BH(IPSTATS_MIB_INNOROUTES);
			goto drop;
		}
	}

#ifdef CONFIG_NET_CLS_ROUTE
	if (unlikely(skb->dst->tclassid)) {
		struct ip_rt_acct *st = per_cpu_ptr(ip_rt_acct, smp_processor_id());
		u32 idx = skb->dst->tclassid;
		st[idx&0xFF].o_packets++;
		st[idx&0xFF].o_bytes+=skb->len;
		st[(idx>>16)&0xFF].i_packets++;
		st[(idx>>16)&0xFF].i_bytes+=skb->len;
	}
#endif

	if (iph->ihl > 5 && ip_rcv_options(skb))
		goto drop;

	rt = skb->rtable;
	if (rt->rt_type == RTN_MULTICAST)
		IP_INC_STATS_BH(IPSTATS_MIB_INMCASTPKTS);
	else if (rt->rt_type == RTN_BROADCAST)
		IP_INC_STATS_BH(IPSTATS_MIB_INBCASTPKTS);

	return dst_input(skb);

drop:
	kfree_skb(skb);
	return NET_RX_DROP;
}
Exemplo n.º 13
0
int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
    /* if ingress device is enslaved to an L3 master device pass the
     * skb to its handler for processing
     */
    skb = l3mdev_ip6_rcv(skb);
    if (!skb)
        return NET_RX_SUCCESS;

    if (net->ipv4.sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {
        const struct inet6_protocol *ipprot;

        ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]);
        if (ipprot && ipprot->early_demux)
            ipprot->early_demux(skb);
    }
    if (!skb_valid_dst(skb))
        ip6_route_input(skb);

    return dst_input(skb);
}
Exemplo n.º 14
0
int ip_rcv_finish(struct sk_buff *skb)
{
        struct iphdr *iph = skb->nh.iph;
        /*
         *  Initialise the virtual path cache for the packet. It describes
         *  how the packet travels inside Linux networking.
         */
		
        if (skb->dst == NULL) {
            int err = 1;
            
            if(g_session_forward_enable)
            {
				if (skb->nfct && IP_CT_DIR_REPLY == CTINFO2DIR(skb->nfctinfo)
	                && !(((struct ff_cache_info_ex*)skb->nfct)->ff_info[IP_CT_DIR_ORIGINAL].flag & DRV_FF_FLAG_LINUX)
	                && !is_vpn_pkt(skb)){
	                sessfw_debug(1, "--- don't lookup route ---\n" TUPLE_INFO(
	                   &((struct ff_cache_info_ex*)skb->nfct)->ct.tuplehash[IP_CT_DIR_ORIGINAL].tuple,
	                   &((struct ff_cache_info_ex*)skb->nfct)->ct.tuplehash[IP_CT_DIR_REPLY].tuple));
	                err = 0;
	                goto route_label;
				}
				#ifdef CONFIG_NETSESSION
				if (skb->ns && NS_DIR_REPLY == NSINFO2DIR(skb->nsinfo) && 
					!(((struct net_session *)skb->ns)->ff_info[NS_DIR_ORIGINAL].flag & NS_FF_LINUX)){
					err = 0;
	                goto route_label;
				}
				#endif
            }
            if (0 != err)
            {
                sessfw_debug(2, "--- lookup route ---\n" TUPLE_INFO(
                   &((struct ff_cache_info_ex*)skb->nfct)->ct.tuplehash[IP_CT_DIR_ORIGINAL].tuple,
                   &((struct ff_cache_info_ex*)skb->nfct)->ct.tuplehash[IP_CT_DIR_REPLY].tuple));
                err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
                         skb->dev);                
            }
			
            
route_label:
            if (unlikely(err)) {
                if (err == -EHOSTUNREACH)
                    IP_INC_STATS_BH(if_dev_vrf(skb->dev), IPSTATS_MIB_INADDRERRORS);
                goto drop;
            }
        }

        if (iph->ihl > 5 && ip_rcv_options(skb))
    	{
			goto drop;
    	}
            //goto drop;

        
        /*A new entry of mcast packet. add by wangdi*/
        if (MULTICAST(iph->daddr))
        {
            return ipv4_mcast_rcv(skb, iph);
        }
		else if (g_session_forward_enable)
		{
			s32 ret;
			ret = session_forward_fix[ns_mode](skb);
			if (ret != 2)
				return ret;
			else
				return dst_input(skb);/* 没匹配上会话转发 */
		}
        else
            return dst_input(skb);

    drop:
        kfree_skb(skb);
        return NET_RX_DROP;
}
Exemplo n.º 15
0
static int ip_rcv_finish(struct sk_buff *skb)
{
	const struct iphdr *iph = ip_hdr(skb);
	struct rtable *rt;

	/*
	 *	Initialise the virtual path cache for the packet. It describes
	 *	how the packet travels inside Linux networking.
	 */
	if (skb->dst == NULL) {
		int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
					 skb->dev);
		if (unlikely(err)) {
			if (err == -EHOSTUNREACH)
				IP_INC_STATS_BH(dev_net(skb->dev),
						IPSTATS_MIB_INADDRERRORS);
			else if (err == -ENETUNREACH)
				IP_INC_STATS_BH(dev_net(skb->dev),
						IPSTATS_MIB_INNOROUTES);
			goto drop;
		}
	}
#if defined (CONFIG_RTL_819X)
	/*to fix guest can access local web ui*/
	#include <linux/udp.h>
        if (skb->dst->input == &ip_local_deliver) {
                if (skb->__unused == 0xe5 && iph->protocol== IPPROTO_UDP) {
                        struct udphdr *hdr = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
                        if (hdr->dest == 53 || hdr->dest == 67) // DNS Domain or dhcp
                                skb->__unused = 0;
                }

                if (skb->__unused == 0xe5 && iph->protocol== IPPROTO_TCP) {
                        struct udphdr *hdr = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
                        if (hdr->dest == 52869) // IGD port
                                skb->__unused = 0;
                }

                if (skb->__unused == 0xe5)
                        goto drop;
        }
#endif
#ifdef CONFIG_NET_CLS_ROUTE
	if (unlikely(skb->dst->tclassid)) {
		struct ip_rt_acct *st = per_cpu_ptr(ip_rt_acct, smp_processor_id());
		u32 idx = skb->dst->tclassid;
		st[idx&0xFF].o_packets++;
		st[idx&0xFF].o_bytes += skb->len;
		st[(idx>>16)&0xFF].i_packets++;
		st[(idx>>16)&0xFF].i_bytes += skb->len;
	}
#endif

	if (iph->ihl > 5 && ip_rcv_options(skb))
		goto drop;

	rt = skb->rtable;
	if (rt->rt_type == RTN_MULTICAST)
		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCASTPKTS);
	else if (rt->rt_type == RTN_BROADCAST)
		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCASTPKTS);

	return dst_input(skb);

drop:
	kfree_skb(skb);
	return NET_RX_DROP;
}
Exemplo n.º 16
0
static int ip_rcv_finish(struct sk_buff *skb)
{
    const struct iphdr *iph = ip_hdr(skb);
    struct rtable *rt;
    int dcn_flag = 0;

    /* modified by yaom for mpls dcn, 2011-10-20 */
    #if 0
    if ((mpls_dcn_proc) && (NULL == skb_dst(skb)))
    {   
        dcn_flag = mpls_dcn_proc(skb, iph->daddr, 1);
        if (dcn_flag)
        {
            kfree_skb(skb);
            return NET_RX_SUCCESS;
        }
    }
    #endif
    
    if ((dcn_flag != 1) || (NULL == skb_dst(skb)))
    {
        /*
         *  Initialise the virtual path cache for the packet. It describes
         *  how the packet travels inside Linux networking.
         */
        if (skb_dst(skb) == NULL) {
            int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
                         skb->dev);
            if (unlikely(err)) {
                if (err == -EHOSTUNREACH)
                    IP_INC_STATS_BH(dev_net(skb->dev),
                            IPSTATS_MIB_INADDRERRORS);
                else if (err == -ENETUNREACH)
                    IP_INC_STATS_BH(dev_net(skb->dev),
                            IPSTATS_MIB_INNOROUTES);
                goto drop;
            }
        }

#ifdef CONFIG_NET_CLS_ROUTE
        if (unlikely(skb_dst(skb)->tclassid)) {
            struct ip_rt_acct *st = per_cpu_ptr(ip_rt_acct, smp_processor_id());
            u32 idx = skb_dst(skb)->tclassid;
            st[idx&0xFF].o_packets++;
            st[idx&0xFF].o_bytes += skb->len;
            st[(idx>>16)&0xFF].i_packets++;
            st[(idx>>16)&0xFF].i_bytes += skb->len;
        }
#endif

        if (iph->ihl > 5 && ip_rcv_options(skb))
            goto drop;

        rt = skb_rtable(skb);
        if (rt->rt_type == RTN_MULTICAST) {
            IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCAST,
                    skb->len);
        } else if (rt->rt_type == RTN_BROADCAST)
            IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCAST,
                    skb->len);
    }

    return dst_input(skb);

drop:
    kfree_skb(skb);
    return NET_RX_DROP;
}
Exemplo n.º 17
0
static int ip_rcv_finish(struct sk_buff *skb)
{
	const struct iphdr *iph = ip_hdr(skb);
	struct rtable *rt;
	struct direct_tcp_stat *stat;

	stat = per_cpu_ptr(direct_tcp_stats, smp_processor_id());

	/*
	 *	Initialise the virtual path cache for the packet. It describes
	 *	how the packet travels inside Linux networking.
	 */

	if (skb_dst(skb) == NULL) {
		int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
					 skb->dev);
		stat->input_route_slow++;
		//FPRINTK("Skb 0x%p needs to go through route lookup\n", skb);

		if (unlikely(err)) {
			if (err == -EHOSTUNREACH)
				IP_INC_STATS_BH(dev_net(skb->dev),
						IPSTATS_MIB_INADDRERRORS);
			else if (err == -ENETUNREACH)
				IP_INC_STATS_BH(dev_net(skb->dev),
						IPSTATS_MIB_INNOROUTES);
			goto drop;
		}
	} else {
		stat->input_route_fast++;
		//FPRINTK("Skb 0x%p has set dst cache 0x%p[%u]\n", skb, skb_dst(skb), atomic_read(&skb_dst(skb)->__refcnt));
	}

#ifdef CONFIG_NET_CLS_ROUTE
	if (unlikely(skb_dst(skb)->tclassid)) {
		struct ip_rt_acct *st = per_cpu_ptr(ip_rt_acct, smp_processor_id());
		u32 idx = skb_dst(skb)->tclassid;
		st[idx&0xFF].o_packets++;
		st[idx&0xFF].o_bytes += skb->len;
		st[(idx>>16)&0xFF].i_packets++;
		st[(idx>>16)&0xFF].i_bytes += skb->len;
	}
#endif

	if (iph->ihl > 5 && ip_rcv_options(skb))
		goto drop;

	rt = skb_rtable(skb);
	if (rt->rt_type == RTN_MULTICAST) {
		IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCAST,
				skb->len);
	} else if (rt->rt_type == RTN_BROADCAST)
		IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCAST,
				skb->len);

	return dst_input(skb);

drop:
	kfree_skb(skb);
	return NET_RX_DROP;
}
Exemplo n.º 18
0
static int xfrm4_rcv_encap_finish2(struct net *net, struct sock *sk,
				   struct sk_buff *skb)
{
	return dst_input(skb);
}
Exemplo n.º 19
0
int serval_ipv4_forward_out(struct sk_buff *skb)
{
        struct iphdr *iph = ip_hdr(skb);
        int err;

#if defined(ENABLE_DEBUG)
        {
                char srcstr[18], dststr[18];
                LOG_DBG("%s %s->%s skb->len=%u iph_len=[%u] %u\n",
                        skb->dev ? skb->dev->name : "no dev",
                        inet_ntop(AF_INET, &iph->saddr, srcstr, 18),
                        inet_ntop(AF_INET, &iph->daddr, dststr, 18),
                        skb->len, iph->ihl << 2, iph->tos);
        }
#endif
	skb->protocol = htons(ETH_P_IP);

#if defined(OS_LINUX_KERNEL)

        /* IP forwarding must be enabled for this to
           work. */
        err = ip_route_input_noref(skb, 
                                   iph->daddr, 
                                   iph->saddr, 
                                   iph->tos, 
                                   skb->dev);
        
        if (err < 0) {
                LOG_ERR("Could not forward SAL packet, NO route [err=%d]\n", err);
                kfree_skb(skb);
                return NET_RX_DROP;
        } else {
                struct rtable *rt = skb_rtable(skb);
                iph->saddr = rt->rt_src;
        }
#else
        iph->ttl = iph->ttl - 1;
#endif

        /* Update tot_len, we might have added SAL extension
           headers. */
        iph->tot_len = htons(skb->len);

        LOG_DBG("Forwarding skb->len=%u\n",
                skb->len);

        /* Update checksum */
        ip_send_check(iph);

        /* It may seem counter intuitive that we call dst_input
           here. The reason is that we want to call ip_forward, but
           that function is not exported in the kernel. However, if we
           re-route the packet in the kernel (using a new dst
           address), the input function (as called by dst_input) will
           point to ip_forward. The ip_forward function will
           eventually call dst_output, after having updated TTL, etc.
        */
#if defined(OS_LINUX_KERNEL)
        err = dst_input(skb);
#else
        err = dev_queue_xmit(skb);
#endif
        return err;
}
Exemplo n.º 20
0
static inline int ip_rcv_finish(struct sk_buff *skb)
{
	struct net_device *dev = skb->dev;
	struct iphdr *iph = skb->nh.iph;

	/*
	 *	Initialise the virtual path cache for the packet. It describes
	 *	how the packet travels inside Linux networking.
	 */ 
	if (skb->dst == NULL) {
		if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))
			goto drop; 
	}

#ifdef CONFIG_NET_CLS_ROUTE
	if (skb->dst->tclassid) {
		struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
		u32 idx = skb->dst->tclassid;
		st[idx&0xFF].o_packets++;
		st[idx&0xFF].o_bytes+=skb->len;
		st[(idx>>16)&0xFF].i_packets++;
		st[(idx>>16)&0xFF].i_bytes+=skb->len;
	}
#endif

	if (iph->ihl > 5) {
		struct ip_options *opt;

		/* It looks as overkill, because not all
		   IP options require packet mangling.
		   But it is the easiest for now, especially taking
		   into account that combination of IP options
		   and running sniffer is extremely rare condition.
		                                      --ANK (980813)
		*/

		if (skb_cow(skb, skb_headroom(skb))) {
			IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
			goto drop;
		}
		iph = skb->nh.iph;

		if (ip_options_compile(NULL, skb))
			goto inhdr_error;

		opt = &(IPCB(skb)->opt);
		if (opt->srr) {
			struct in_device *in_dev = in_dev_get(dev);
			if (in_dev) {
				if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
					if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
						printk(KERN_INFO "source route option %u.%u.%u.%u -> %u.%u.%u.%u\n",
						       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
					in_dev_put(in_dev);
					goto drop;
				}
				in_dev_put(in_dev);
			}
			if (ip_options_rcv_srr(skb))
				goto drop;
		}
	}

	return dst_input(skb);

inhdr_error:
	IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
drop:
        kfree_skb(skb);
        return NET_RX_DROP;
}
Exemplo n.º 21
0
static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
	const struct iphdr *iph = ip_hdr(skb);
	struct rtable *rt;

	if (net->ipv4.sysctl_ip_early_demux &&
	    !skb_dst(skb) &&
	    !skb->sk &&
	    !ip_is_fragment(iph)) {
		const struct net_protocol *ipprot;
		int protocol = iph->protocol;

		ipprot = rcu_dereference(inet_protos[protocol]);
		if (ipprot && ipprot->early_demux) {
			ipprot->early_demux(skb);
			/* must reload iph, skb->head might have changed */
			iph = ip_hdr(skb);
		}
	}

	/*
	 *	Initialise the virtual path cache for the packet. It describes
	 *	how the packet travels inside Linux networking.
	 */
	if (!skb_valid_dst(skb)) {
		int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
					       iph->tos, skb->dev);
		if (unlikely(err)) {
			if (err == -EXDEV)
				NET_INC_STATS_BH(net, LINUX_MIB_IPRPFILTER);
			goto drop;
		}
	}

#ifdef CONFIG_IP_ROUTE_CLASSID
	if (unlikely(skb_dst(skb)->tclassid)) {
		struct ip_rt_acct *st = this_cpu_ptr(ip_rt_acct);
		u32 idx = skb_dst(skb)->tclassid;
		st[idx&0xFF].o_packets++;
		st[idx&0xFF].o_bytes += skb->len;
		st[(idx>>16)&0xFF].i_packets++;
		st[(idx>>16)&0xFF].i_bytes += skb->len;
	}
#endif

	if (iph->ihl > 5 && ip_rcv_options(skb))
		goto drop;

	rt = skb_rtable(skb);
	if (rt->rt_type == RTN_MULTICAST) {
		IP_UPD_PO_STATS_BH(net, IPSTATS_MIB_INMCAST, skb->len);
	} else if (rt->rt_type == RTN_BROADCAST) {
		IP_UPD_PO_STATS_BH(net, IPSTATS_MIB_INBCAST, skb->len);
	} else if (skb->pkt_type == PACKET_BROADCAST ||
		   skb->pkt_type == PACKET_MULTICAST) {
		struct in_device *in_dev = __in_dev_get_rcu(skb->dev);

		/* RFC 1122 3.3.6:
		 *
		 *   When a host sends a datagram to a link-layer broadcast
		 *   address, the IP destination address MUST be a legal IP
		 *   broadcast or IP multicast address.
		 *
		 *   A host SHOULD silently discard a datagram that is received
		 *   via a link-layer broadcast (see Section 2.4) but does not
		 *   specify an IP multicast or broadcast destination address.
		 *
		 * This doesn't explicitly say L2 *broadcast*, but broadcast is
		 * in a way a form of multicast and the most common use case for
		 * this is 802.11 protecting against cross-station spoofing (the
		 * so-called "hole-196" attack) so do it for both.
		 */
		if (in_dev &&
		    IN_DEV_ORCONF(in_dev, DROP_UNICAST_IN_L2_MULTICAST))
			goto drop;
	}

	return dst_input(skb);

drop:
	kfree_skb(skb);
	return NET_RX_DROP;
}