diff options
author | Xin Long <lucien.xin@gmail.com> | 2021-06-22 20:05:00 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-06-22 20:28:52 +0200 |
commit | 9e47df005cab63e545671dba8dfd6852fff1c2cf (patch) | |
tree | 6b2ec63ad7dc082cda99e8d15046ec55907e2b94 /net/sctp/input.c | |
parent | sctp: extract sctp_v4_err_handle function from sctp_v4_err (diff) | |
download | linux-9e47df005cab63e545671dba8dfd6852fff1c2cf.tar.xz linux-9e47df005cab63e545671dba8dfd6852fff1c2cf.zip |
sctp: process sctp over udp icmp err on sctp side
Previously, sctp over udp was using udp tunnel's icmp err process, which
only does sk lookup on sctp side. However for sctp's icmp error process,
there are more things to do, like syncing assoc pmtu/retransmit packets
for toobig type err, and starting proto_unreach_timer for unreach type
err etc.
Now after adding PLPMTUD, which also requires to process toobig type err
on sctp side. This patch is to process icmp err on sctp side by parsing
the type/code/info in .encap_err_lookup and call sctp's icmp processing
functions. Note as the 'redirect' err process needs to know the outer
ip(v6) header's, we have to leave it to udp(v6)_err to handle it.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/input.c')
-rw-r--r-- | net/sctp/input.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c index 83d58d42ea45..fe6429cc012f 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -645,6 +645,36 @@ int sctp_v4_err(struct sk_buff *skb, __u32 info) return 0; } +int sctp_udp_v4_err(struct sock *sk, struct sk_buff *skb) +{ + struct net *net = dev_net(skb->dev); + struct sctp_association *asoc; + struct sctp_transport *t; + struct icmphdr *hdr; + __u32 info = 0; + + skb->transport_header += sizeof(struct udphdr); + sk = sctp_err_lookup(net, AF_INET, skb, sctp_hdr(skb), &asoc, &t); + if (!sk) { + __ICMP_INC_STATS(net, ICMP_MIB_INERRORS); + return -ENOENT; + } + + skb->transport_header -= sizeof(struct udphdr); + hdr = (struct icmphdr *)(skb_network_header(skb) - sizeof(struct icmphdr)); + if (hdr->type == ICMP_REDIRECT) { + /* can't be handled without outer iphdr known, leave it to udp_err */ + sctp_err_finish(sk, t); + return 0; + } + if (hdr->type == ICMP_DEST_UNREACH && hdr->code == ICMP_FRAG_NEEDED) + info = ntohs(hdr->un.frag.mtu); + sctp_v4_err_handle(t, skb, hdr->type, hdr->code, info); + + sctp_err_finish(sk, t); + return 1; +} + /* * RFC 2960, 8.4 - Handle "Out of the blue" Packets. * |