Commit 545dbcd1 authored by Eric Dumazet's avatar Eric Dumazet Committed by Jakub Kicinski
Browse files

ipv6: icmp6: add drop reason support to ndisc_rcv()



Creates three new drop reasons:

SKB_DROP_REASON_IPV6_NDISC_FRAG: invalid frag (suppress_frag_ndisc).

SKB_DROP_REASON_IPV6_NDISC_HOP_LIMIT: invalid hop limit.

SKB_DROP_REASON_IPV6_NDISC_BAD_CODE: invalid NDISC icmp6 code.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 30c89bad
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -73,6 +73,9 @@
	FN(FRAG_TOO_FAR)		\
	FN(TCP_MINTTL)			\
	FN(IPV6_BAD_EXTHDR)		\
	FN(IPV6_NDISC_FRAG)		\
	FN(IPV6_NDISC_HOP_LIMIT)	\
	FN(IPV6_NDISC_BAD_CODE)		\
	FNe(MAX)

/**
@@ -321,6 +324,12 @@ enum skb_drop_reason {
	SKB_DROP_REASON_TCP_MINTTL,
	/** @SKB_DROP_REASON_IPV6_BAD_EXTHDR: Bad IPv6 extension header. */
	SKB_DROP_REASON_IPV6_BAD_EXTHDR,
	/** @SKB_DROP_REASON_IPV6_NDISC_FRAG: invalid frag (suppress_frag_ndisc). */
	SKB_DROP_REASON_IPV6_NDISC_FRAG,
	/** @SKB_DROP_REASON_IPV6_NDISC_HOP_LIMIT: invalid hop limit. */
	SKB_DROP_REASON_IPV6_NDISC_HOP_LIMIT,
	/** @SKB_DROP_REASON_IPV6_NDISC_BAD_CODE: invalid NDISC icmp6 code. */
	SKB_DROP_REASON_IPV6_NDISC_BAD_CODE,
	/**
	 * @SKB_DROP_REASON_MAX: the maximum of drop reason, which shouldn't be
	 * used as a real 'reason'
+1 −1
Original line number Diff line number Diff line
@@ -445,7 +445,7 @@ int ndisc_late_init(void);
void ndisc_late_cleanup(void);
void ndisc_cleanup(void);

int ndisc_rcv(struct sk_buff *skb);
enum skb_drop_reason ndisc_rcv(struct sk_buff *skb);

struct sk_buff *ndisc_ns_create(struct net_device *dev, const struct in6_addr *solicit,
				const struct in6_addr *saddr, u64 nonce);
+1 −1
Original line number Diff line number Diff line
@@ -969,7 +969,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
	case NDISC_NEIGHBOUR_SOLICITATION:
	case NDISC_NEIGHBOUR_ADVERTISEMENT:
	case NDISC_REDIRECT:
		ndisc_rcv(skb);
		reason = ndisc_rcv(skb);
		break;

	case ICMPV6_MGM_QUERY:
+7 −6
Original line number Diff line number Diff line
@@ -1804,15 +1804,16 @@ static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
	return false;
}

int ndisc_rcv(struct sk_buff *skb)
enum skb_drop_reason ndisc_rcv(struct sk_buff *skb)
{
	struct nd_msg *msg;
	SKB_DR(reason);

	if (ndisc_suppress_frag_ndisc(skb))
		return 0;
		return SKB_DROP_REASON_IPV6_NDISC_FRAG;

	if (skb_linearize(skb))
		return 0;
		return SKB_DROP_REASON_NOMEM;

	msg = (struct nd_msg *)skb_transport_header(skb);

@@ -1821,13 +1822,13 @@ int ndisc_rcv(struct sk_buff *skb)
	if (ipv6_hdr(skb)->hop_limit != 255) {
		ND_PRINTK(2, warn, "NDISC: invalid hop-limit: %d\n",
			  ipv6_hdr(skb)->hop_limit);
		return 0;
		return SKB_DROP_REASON_IPV6_NDISC_HOP_LIMIT;
	}

	if (msg->icmph.icmp6_code != 0) {
		ND_PRINTK(2, warn, "NDISC: invalid ICMPv6 code: %d\n",
			  msg->icmph.icmp6_code);
		return 0;
		return SKB_DROP_REASON_IPV6_NDISC_BAD_CODE;
	}

	switch (msg->icmph.icmp6_type) {
@@ -1853,7 +1854,7 @@ int ndisc_rcv(struct sk_buff *skb)
		break;
	}

	return 0;
	return reason;
}

static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)