svn commit: r366892 - stable/12/sys/netpfil/ipfw/nat64
Andrey V. Elsukov
ae at FreeBSD.org
Tue Oct 20 11:40:38 UTC 2020
Author: ae
Date: Tue Oct 20 11:40:37 2020
New Revision: 366892
URL: https://svnweb.freebsd.org/changeset/base/366892
Log:
MFC r366681:
Add IPv4 fragments reassembling to NAT64LSN.
NAT64LSN requires the presence of upper level protocol header
in a IPv4 datagram to find corresponding state to make translation.
Now it will be handled automatically by nat64lsn instance.
Obtained from: Yandex LLC
Sponsored by: Yandex LLC
Modified:
stable/12/sys/netpfil/ipfw/nat64/nat64lsn.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sys/netpfil/ipfw/nat64/nat64lsn.c
==============================================================================
--- stable/12/sys/netpfil/ipfw/nat64/nat64lsn.c Tue Oct 20 09:51:41 2020 (r366891)
+++ stable/12/sys/netpfil/ipfw/nat64/nat64lsn.c Tue Oct 20 11:40:37 2020 (r366892)
@@ -548,6 +548,57 @@ nat64lsn_get_state4to6(struct nat64lsn_cfg *cfg, struc
return (NULL);
}
+/*
+ * Reassemble IPv4 fragments, make PULLUP if needed, get some ULP fields
+ * that might be unknown until reassembling is completed.
+ */
+static struct mbuf*
+nat64lsn_reassemble4(struct nat64lsn_cfg *cfg, struct mbuf *m,
+ uint16_t *port)
+{
+ struct ip *ip;
+ int len;
+
+ m = ip_reass(m);
+ if (m == NULL)
+ return (NULL);
+ /* IP header must be contigious after ip_reass() */
+ ip = mtod(m, struct ip *);
+ len = ip->ip_hl << 2;
+ switch (ip->ip_p) {
+ case IPPROTO_ICMP:
+ len += ICMP_MINLEN; /* Enough to get icmp_id */
+ break;
+ case IPPROTO_TCP:
+ len += sizeof(struct tcphdr);
+ break;
+ case IPPROTO_UDP:
+ len += sizeof(struct udphdr);
+ break;
+ default:
+ m_freem(m);
+ NAT64STAT_INC(&cfg->base.stats, noproto);
+ return (NULL);
+ }
+ if (m->m_len < len) {
+ m = m_pullup(m, len);
+ if (m == NULL) {
+ NAT64STAT_INC(&cfg->base.stats, nomem);
+ return (NULL);
+ }
+ ip = mtod(m, struct ip *);
+ }
+ switch (ip->ip_p) {
+ case IPPROTO_TCP:
+ *port = ntohs(L3HDR(ip, struct tcphdr *)->th_dport);
+ break;
+ case IPPROTO_UDP:
+ *port = ntohs(L3HDR(ip, struct udphdr *)->uh_dport);
+ break;
+ }
+ return (m);
+}
+
static int
nat64lsn_translate4(struct nat64lsn_cfg *cfg,
const struct ipfw_flow_id *f_id, struct mbuf **mp)
@@ -567,6 +618,14 @@ nat64lsn_translate4(struct nat64lsn_cfg *cfg,
if (addr < cfg->prefix4 || addr > cfg->pmask4) {
NAT64STAT_INC(&cfg->base.stats, nomatch4);
return (cfg->nomatch_verdict);
+ }
+
+ /* Reassemble fragments if needed */
+ ret = ntohs(mtod(*mp, struct ip *)->ip_off);
+ if ((ret & (IP_MF | IP_OFFMASK)) != 0) {
+ *mp = nat64lsn_reassemble4(cfg, *mp, &port);
+ if (*mp == NULL)
+ return (IP_FW_DENY);
}
/* Check if protocol is supported */
More information about the svn-src-stable-12
mailing list