--- zzzz-none-000/linux-4.4.271/net/netfilter/nf_nat_ftp.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/net/netfilter/nf_nat_ftp.c 2023-04-19 10:22:30.000000000 +0000 @@ -24,8 +24,39 @@ MODULE_DESCRIPTION("ftp NAT helper"); MODULE_ALIAS("ip_nat_ftp"); +static ushort psid = 0; +module_param(psid, ushort, 0644); +MODULE_PARM_DESC(psid, "MAP_E devices's psid"); + +static uint psid_len = 0; +module_param(psid_len, uint, 0644); +MODULE_PARM_DESC(psid_len, "MAP_E devices's psid length"); + +static uint offset = 0; +module_param(offset, uint, 0644); +MODULE_PARM_DESC(offset, "MAP_E devices's psid offset"); + /* FIXME: Time out? --RR */ +/** + * nf_nat_port_valid_check - check the port is in the range of psid + * @skb the packets to be translated + * @port the port to be checked. + **/ +static int nf_nat_port_valid_check(struct sk_buff *skb, u16 port) +{ + if (psid == 0 || psid_len == 0 || offset == 0) + return 1; + + if ((psid_len + offset) > 16) + return 1; + + if ((((port >> (16 - psid_len - offset)) & ((1 << psid_len) - 1))) == psid) + return 1; + + return 0; +} + static int nf_nat_ftp_fmt_cmd(struct nf_conn *ct, enum nf_ct_ftp_type type, char *buffer, size_t buflen, union nf_inet_addr *addr, u16 port) @@ -65,7 +96,7 @@ struct nf_conntrack_expect *exp) { union nf_inet_addr newaddr; - u_int16_t port; + u16 port; int dir = CTINFO2DIR(ctinfo); struct nf_conn *ct = exp->master; char buffer[sizeof("|1||65535|") + INET6_ADDRSTRLEN]; @@ -82,10 +113,16 @@ * this one. */ exp->expectfn = nf_nat_follow_master; - /* Try to get same port: if not, try to change it. */ + /* In the case of MAP-E, the outbound FTP ALG source port number must use its own + * PSID. Otherwise the returned packets from ftp server will use other + * than its own IPv6 address. + * so let the check hook to validate the port*/ for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) { int ret; + if ((type == NF_CT_FTP_EPRT || type == NF_CT_FTP_PORT) && !nf_nat_port_valid_check(skb, port)) + continue; + exp->tuple.dst.u.tcp.port = htons(port); ret = nf_ct_expect_related(exp); if (ret == 0)