예제 #1
0
파일: ip6_input.c 프로젝트: Chong-Li/cse522
int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
	if (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);
}
예제 #2
0
static void ip6_rcv_finish_core(struct net *net, struct sock *sk,
				struct sk_buff *skb)
{
	void (*edemux)(struct sk_buff *skb);

	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 && (edemux = READ_ONCE(ipprot->early_demux)))
			edemux(skb);
	}
	if (!skb_valid_dst(skb))
		ip6_route_input(skb);
}
예제 #3
0
파일: ip6_input.c 프로젝트: oldzhu/linux
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);
}
예제 #4
0
파일: ip6_input.c 프로젝트: oldzhu/linux
int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
    const struct ipv6hdr *hdr;
    u32 pkt_len;
    struct inet6_dev *idev;
    struct net *net = dev_net(skb->dev);

    if (skb->pkt_type == PACKET_OTHERHOST) {
        kfree_skb(skb);
        return NET_RX_DROP;
    }

    rcu_read_lock();

    idev = __in6_dev_get(skb->dev);

    __IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_IN, skb->len);

    if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
            !idev || unlikely(idev->cnf.disable_ipv6)) {
        __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
        goto drop;
    }

    memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));

    /*
     * Store incoming device index. When the packet will
     * be queued, we cannot refer to skb->dev anymore.
     *
     * BTW, when we send a packet for our own local address on a
     * non-loopback interface (e.g. ethX), it is being delivered
     * via the loopback interface (lo) here; skb->dev = loopback_dev.
     * It, however, should be considered as if it is being
     * arrived via the sending interface (ethX), because of the
     * nature of scoping architecture. --yoshfuji
     */
    IP6CB(skb)->iif = skb_valid_dst(skb) ? ip6_dst_idev(skb_dst(skb))->dev->ifindex : dev->ifindex;

    if (unlikely(!pskb_may_pull(skb, sizeof(*hdr))))
        goto err;

    hdr = ipv6_hdr(skb);

    if (hdr->version != 6)
        goto err;

    __IP6_ADD_STATS(net, idev,
                    IPSTATS_MIB_NOECTPKTS +
                    (ipv6_get_dsfield(hdr) & INET_ECN_MASK),
                    max_t(unsigned short, 1, skb_shinfo(skb)->gso_segs));
    /*
     * RFC4291 2.5.3
     * A packet received on an interface with a destination address
     * of loopback must be dropped.
     */
    if (!(dev->flags & IFF_LOOPBACK) &&
            ipv6_addr_loopback(&hdr->daddr))
        goto err;

    /* RFC4291 Errata ID: 3480
     * Interface-Local scope spans only a single interface on a
     * node and is useful only for loopback transmission of
     * multicast.  Packets with interface-local scope received
     * from another node must be discarded.
     */
    if (!(skb->pkt_type == PACKET_LOOPBACK ||
            dev->flags & IFF_LOOPBACK) &&
            ipv6_addr_is_multicast(&hdr->daddr) &&
            IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1)
        goto err;

    /* If enabled, drop unicast packets that were encapsulated in link-layer
     * multicast or broadcast to protected against the so-called "hole-196"
     * attack in 802.11 wireless.
     */
    if (!ipv6_addr_is_multicast(&hdr->daddr) &&
            (skb->pkt_type == PACKET_BROADCAST ||
             skb->pkt_type == PACKET_MULTICAST) &&
            idev->cnf.drop_unicast_in_l2_multicast)
        goto err;

    /* RFC4291 2.7
     * Nodes must not originate a packet to a multicast address whose scope
     * field contains the reserved value 0; if such a packet is received, it
     * must be silently dropped.
     */
    if (ipv6_addr_is_multicast(&hdr->daddr) &&
            IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0)
        goto err;

    /*
     * RFC4291 2.7
     * Multicast addresses must not be used as source addresses in IPv6
     * packets or appear in any Routing header.
     */
    if (ipv6_addr_is_multicast(&hdr->saddr))
        goto err;

    skb->transport_header = skb->network_header + sizeof(*hdr);
    IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);

    pkt_len = ntohs(hdr->payload_len);

    /* pkt_len may be zero if Jumbo payload option is present */
    if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
        if (pkt_len + sizeof(struct ipv6hdr) > skb->len) {
            __IP6_INC_STATS(net,
                            idev, IPSTATS_MIB_INTRUNCATEDPKTS);
            goto drop;
        }
        if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) {
            __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
            goto drop;
        }
        hdr = ipv6_hdr(skb);
    }

    if (hdr->nexthdr == NEXTHDR_HOP) {
        if (ipv6_parse_hopopts(skb) < 0) {
            __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
            rcu_read_unlock();
            return NET_RX_DROP;
        }
    }

    rcu_read_unlock();

    /* Must drop socket now because of tproxy. */
    skb_orphan(skb);

    return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING,
                   net, NULL, skb, dev, NULL,
                   ip6_rcv_finish);
err:
    __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
drop:
    rcu_read_unlock();
    kfree_skb(skb);
    return NET_RX_DROP;
}
예제 #5
0
파일: ip_input.c 프로젝트: 020gzh/linux
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;
}