Skip to content

Commit 4c028b9

Browse files
bpf: nat: support IPv4 NAT for ICMP_TIME_EXCEEDED
[ upstream commit 9dd4c01 ] Allow Time-Exceeded packets to pass through the BPF NAT engine. SNAT / RevSNAT is applied similar to other types of ICMP Error messages. We identify the inner packet, match it against an SNAT session, and use the NAT entry to rewrite both the outer and inner headers. Signed-off-by: Julian Wiedmann <jwi@isovalent.com>
1 parent 378c200 commit 4c028b9

File tree

1 file changed

+28
-10
lines changed

1 file changed

+28
-10
lines changed

bpf/lib/nat.h

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -703,8 +703,7 @@ snat_v4_needs_masquerade(struct __ctx_buff *ctx __maybe_unused,
703703
}
704704

705705
static __always_inline __maybe_unused int
706-
snat_v4_nat_handle_icmp_dest_unreach(struct __ctx_buff *ctx, __u64 off,
707-
bool has_l4_header)
706+
snat_v4_nat_handle_icmp_error(struct __ctx_buff *ctx, __u64 off, bool has_l4_header)
708707
{
709708
__u32 inner_l3_off = (__u32)(off + sizeof(struct icmphdr));
710709
struct ipv4_ct_tuple tuple = {};
@@ -853,8 +852,18 @@ snat_v4_nat(struct __ctx_buff *ctx, struct ipv4_ct_tuple *tuple,
853852
if (icmphdr.code > NR_ICMP_UNREACH)
854853
return DROP_UNKNOWN_ICMP_CODE;
855854

856-
return snat_v4_nat_handle_icmp_dest_unreach(ctx, off,
857-
has_l4_header);
855+
goto nat_icmp_v4;
856+
case ICMP_TIME_EXCEEDED:
857+
switch (icmphdr.code) {
858+
case ICMP_EXC_TTL:
859+
case ICMP_EXC_FRAGTIME:
860+
break;
861+
default:
862+
return DROP_UNKNOWN_ICMP_CODE;
863+
}
864+
865+
nat_icmp_v4:
866+
return snat_v4_nat_handle_icmp_error(ctx, off, has_l4_header);
858867
default:
859868
return DROP_NAT_UNSUPP_PROTO;
860869
}
@@ -871,9 +880,9 @@ snat_v4_nat(struct __ctx_buff *ctx, struct ipv4_ct_tuple *tuple,
871880
}
872881

873882
static __always_inline __maybe_unused int
874-
snat_v4_rev_nat_handle_icmp_dest_unreach(struct __ctx_buff *ctx,
875-
__u64 inner_l3_off,
876-
struct ipv4_nat_entry **state)
883+
snat_v4_rev_nat_handle_icmp_error(struct __ctx_buff *ctx,
884+
__u64 inner_l3_off,
885+
struct ipv4_nat_entry **state)
877886
{
878887
struct ipv4_ct_tuple tuple = {};
879888
struct iphdr iphdr;
@@ -995,11 +1004,20 @@ snat_v4_rev_nat(struct __ctx_buff *ctx, const struct ipv4_nat_target *target,
9951004
if (icmphdr.code > NR_ICMP_UNREACH)
9961005
return NAT_PUNT_TO_STACK;
9971006

1007+
goto rev_nat_icmp_v4;
1008+
case ICMP_TIME_EXCEEDED:
1009+
switch (icmphdr.code) {
1010+
case ICMP_EXC_TTL:
1011+
case ICMP_EXC_FRAGTIME:
1012+
break;
1013+
default:
1014+
return NAT_PUNT_TO_STACK;
1015+
}
1016+
1017+
rev_nat_icmp_v4:
9981018
inner_l3_off = off + sizeof(struct icmphdr);
9991019

1000-
ret = snat_v4_rev_nat_handle_icmp_dest_unreach(ctx,
1001-
inner_l3_off,
1002-
&state);
1020+
ret = snat_v4_rev_nat_handle_icmp_error(ctx, inner_l3_off, &state);
10031021
if (IS_ERR(ret))
10041022
return ret;
10051023

0 commit comments

Comments
 (0)