While I read through the code for ipfw I found out that it check the packets before the TCP/IP stack:
For IP fragmentation it require that the first fragment contain an entire L4 header:
Have I misunderstood the code or it's the a feature of ipfw? Is it required that the first fragment must contain the entire L4 header (I haven't seen that in the protocol stack code)? Or it's just a feature of ipfw?
It seems pf in FreeBSD try resolve IP fragmentation by itself:
In Linux, netfilter will process input packets after ip_defrag(), and before ip_fragment() for output packets.
ether_input -> ether_demux -> ether_ipfw_chk -> ip_fw_chk_ptr [ipfw_chk]
For IP fragmentation it require that the first fragment contain an entire L4 header:
Code:
if (offset == 0) {
switch (proto) {
case IPPROTO_TCP:
[color="Red"][B]PULLUP_TO(hlen, ulp, struct tcphdr);[/B][/color]
dst_port = TCP(ulp)->th_dport;
src_port = TCP(ulp)->th_sport;
args->f_id.flags = TCP(ulp)->th_flags;
break;
Code:
#define PULLUP_TO(len, p, T) \
do { \
int x = (len) + sizeof(T); \
if ((m)->m_len < x) { \
args->m = m = m_pullup(m, x); \
if (m == NULL) \
goto pullup_failed; \
} \
p = (mtod(m, char *) + (len)); \
} while (0)
Have I misunderstood the code or it's the a feature of ipfw? Is it required that the first fragment must contain the entire L4 header (I haven't seen that in the protocol stack code)? Or it's just a feature of ipfw?
It seems pf in FreeBSD try resolve IP fragmentation by itself:
Code:
/* We do IP header normalization and packet reassembly here */
if (pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) {
action = PF_DROP;
goto done;
}
m = *m0;
h = mtod(m, struct ip *);
off = h->ip_hl << 2;
if (off < (int)sizeof(*h)) {
action = PF_DROP;
REASON_SET(&reason, PFRES_SHORT);
log = 1;
goto done;
}
pd.src = (struct pf_addr *)&h->ip_src;
pd.dst = (struct pf_addr *)&h->ip_dst;
PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET);
pd.ip_sum = &h->ip_sum;
pd.proto = h->ip_p;
pd.af = AF_INET;
pd.tos = h->ip_tos;
pd.tot_len = ntohs(h->ip_len);
pd.eh = eh;
/* handle fragments that didn't get reassembled by normalization */
if (h->ip_off & htons(IP_MF | IP_OFFMASK)) {
action = pf_test_fragment(&r, dir, kif, m, h,
&pd, &a, &ruleset);
goto done;
}
switch (h->ip_p) {
case IPPROTO_TCP: {
In Linux, netfilter will process input packets after ip_defrag(), and before ip_fragment() for output packets.