Skip to content

Commit

Permalink
Add IPv4 fragments reassembling to NAT64LSN.
Browse files Browse the repository at this point in the history
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.

Reviewed by:	melifaro
Obtained from:	Yandex LLC
MFC after:	1 week
Sponsored by:	Yandex LLC
Differential Revision:	https://reviews.freebsd.org/D26758
  • Loading branch information
bu7cher committed Oct 13, 2020
1 parent b867b32 commit f909db0
Showing 1 changed file with 59 additions and 0 deletions.
59 changes: 59 additions & 0 deletions sys/netpfil/ipfw/nat64/nat64lsn.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,57 @@ nat64lsn_get_state4to6(struct nat64lsn_cfg *cfg, struct nat64lsn_alias *alias,
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)
Expand All @@ -568,6 +619,14 @@ nat64lsn_translate4(struct nat64lsn_cfg *cfg,
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 */
switch (proto) {
case IPPROTO_ICMP:
Expand Down

0 comments on commit f909db0

Please sign in to comment.