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

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
...@@ -73,6 +73,9 @@ ...@@ -73,6 +73,9 @@
FN(FRAG_TOO_FAR) \ FN(FRAG_TOO_FAR) \
FN(TCP_MINTTL) \ FN(TCP_MINTTL) \
FN(IPV6_BAD_EXTHDR) \ FN(IPV6_BAD_EXTHDR) \
FN(IPV6_NDISC_FRAG) \
FN(IPV6_NDISC_HOP_LIMIT) \
FN(IPV6_NDISC_BAD_CODE) \
FNe(MAX) FNe(MAX)
/** /**
...@@ -321,6 +324,12 @@ enum skb_drop_reason { ...@@ -321,6 +324,12 @@ enum skb_drop_reason {
SKB_DROP_REASON_TCP_MINTTL, SKB_DROP_REASON_TCP_MINTTL,
/** @SKB_DROP_REASON_IPV6_BAD_EXTHDR: Bad IPv6 extension header. */ /** @SKB_DROP_REASON_IPV6_BAD_EXTHDR: Bad IPv6 extension header. */
SKB_DROP_REASON_IPV6_BAD_EXTHDR, 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 * @SKB_DROP_REASON_MAX: the maximum of drop reason, which shouldn't be
* used as a real 'reason' * used as a real 'reason'
......
...@@ -445,7 +445,7 @@ int ndisc_late_init(void); ...@@ -445,7 +445,7 @@ int ndisc_late_init(void);
void ndisc_late_cleanup(void); void ndisc_late_cleanup(void);
void ndisc_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, struct sk_buff *ndisc_ns_create(struct net_device *dev, const struct in6_addr *solicit,
const struct in6_addr *saddr, u64 nonce); const struct in6_addr *saddr, u64 nonce);
......
...@@ -969,7 +969,7 @@ static int icmpv6_rcv(struct sk_buff *skb) ...@@ -969,7 +969,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
case NDISC_NEIGHBOUR_SOLICITATION: case NDISC_NEIGHBOUR_SOLICITATION:
case NDISC_NEIGHBOUR_ADVERTISEMENT: case NDISC_NEIGHBOUR_ADVERTISEMENT:
case NDISC_REDIRECT: case NDISC_REDIRECT:
ndisc_rcv(skb); reason = ndisc_rcv(skb);
break; break;
case ICMPV6_MGM_QUERY: case ICMPV6_MGM_QUERY:
......
...@@ -1804,15 +1804,16 @@ static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb) ...@@ -1804,15 +1804,16 @@ static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
return false; return false;
} }
int ndisc_rcv(struct sk_buff *skb) enum skb_drop_reason ndisc_rcv(struct sk_buff *skb)
{ {
struct nd_msg *msg; struct nd_msg *msg;
SKB_DR(reason);
if (ndisc_suppress_frag_ndisc(skb)) if (ndisc_suppress_frag_ndisc(skb))
return 0; return SKB_DROP_REASON_IPV6_NDISC_FRAG;
if (skb_linearize(skb)) if (skb_linearize(skb))
return 0; return SKB_DROP_REASON_NOMEM;
msg = (struct nd_msg *)skb_transport_header(skb); msg = (struct nd_msg *)skb_transport_header(skb);
...@@ -1821,13 +1822,13 @@ int ndisc_rcv(struct sk_buff *skb) ...@@ -1821,13 +1822,13 @@ int ndisc_rcv(struct sk_buff *skb)
if (ipv6_hdr(skb)->hop_limit != 255) { if (ipv6_hdr(skb)->hop_limit != 255) {
ND_PRINTK(2, warn, "NDISC: invalid hop-limit: %d\n", ND_PRINTK(2, warn, "NDISC: invalid hop-limit: %d\n",
ipv6_hdr(skb)->hop_limit); ipv6_hdr(skb)->hop_limit);
return 0; return SKB_DROP_REASON_IPV6_NDISC_HOP_LIMIT;
} }
if (msg->icmph.icmp6_code != 0) { if (msg->icmph.icmp6_code != 0) {
ND_PRINTK(2, warn, "NDISC: invalid ICMPv6 code: %d\n", ND_PRINTK(2, warn, "NDISC: invalid ICMPv6 code: %d\n",
msg->icmph.icmp6_code); msg->icmph.icmp6_code);
return 0; return SKB_DROP_REASON_IPV6_NDISC_BAD_CODE;
} }
switch (msg->icmph.icmp6_type) { switch (msg->icmph.icmp6_type) {
...@@ -1853,7 +1854,7 @@ int ndisc_rcv(struct sk_buff *skb) ...@@ -1853,7 +1854,7 @@ int ndisc_rcv(struct sk_buff *skb)
break; break;
} }
return 0; return reason;
} }
static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment