Skip to content

Commit 258bbb1

Browse files
teknoraverdavem330
authored andcommitted
icmp: don't fail on fragment reassembly time exceeded
The ICMP implementation currently replies to an ICMP time exceeded message (type 11) with an ICMP host unreachable message (type 3, code 1). However, time exceeded messages can either represent "time to live exceeded in transit" (code 0) or "fragment reassembly time exceeded" (code 1). Unconditionally replying to "fragment reassembly time exceeded" with host unreachable messages might cause unjustified connection resets which are now easily triggered as UFO has been removed, because, in turn, sending large buffers triggers IP fragmentation. The issue can be easily reproduced by running a lot of UDP streams which is likely to trigger IP fragmentation: # start netserver in the test namespace ip netns add test ip netns exec test netserver # create a VETH pair ip link add name veth0 type veth peer name veth0 netns test ip link set veth0 up ip -n test link set veth0 up for i in $(seq 20 29); do # assign addresses to both ends ip addr add dev veth0 192.168.$i.1/24 ip -n test addr add dev veth0 192.168.$i.2/24 # start the traffic netperf -L 192.168.$i.1 -H 192.168.$i.2 -t UDP_STREAM -l 0 & done # wait send_data: data send error: No route to host (errno 113) netperf: send_omni: send_data failed: No route to host We need to differentiate instead: if fragment reassembly time exceeded is reported, we need to silently drop the packet, if time to live exceeded is reported, maintain the current behaviour. In both cases increment the related error count "icmpInTimeExcds". While at it, fix a typo in a comment, and convert the if statement into a switch to mate it more readable. Signed-off-by: Matteo Croce <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a00344b commit 258bbb1

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

net/ipv4/icmp.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,7 @@ static bool icmp_tag_validation(int proto)
782782
}
783783

784784
/*
785-
* Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, ICMP_QUENCH, and
785+
* Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEEDED, ICMP_QUENCH, and
786786
* ICMP_PARAMETERPROB.
787787
*/
788788

@@ -810,7 +810,8 @@ static bool icmp_unreach(struct sk_buff *skb)
810810
if (iph->ihl < 5) /* Mangled header, drop. */
811811
goto out_err;
812812

813-
if (icmph->type == ICMP_DEST_UNREACH) {
813+
switch (icmph->type) {
814+
case ICMP_DEST_UNREACH:
814815
switch (icmph->code & 15) {
815816
case ICMP_NET_UNREACH:
816817
case ICMP_HOST_UNREACH:
@@ -846,8 +847,16 @@ static bool icmp_unreach(struct sk_buff *skb)
846847
}
847848
if (icmph->code > NR_ICMP_UNREACH)
848849
goto out;
849-
} else if (icmph->type == ICMP_PARAMETERPROB)
850+
break;
851+
case ICMP_PARAMETERPROB:
850852
info = ntohl(icmph->un.gateway) >> 24;
853+
break;
854+
case ICMP_TIME_EXCEEDED:
855+
__ICMP_INC_STATS(net, ICMP_MIB_INTIMEEXCDS);
856+
if (icmph->code == ICMP_EXC_FRAGTIME)
857+
goto out;
858+
break;
859+
}
851860

852861
/*
853862
* Throw it at our lower layers

0 commit comments

Comments
 (0)