diff options
author | piso <piso@FreeBSD.org> | 2009-04-01 20:23:47 +0000 |
---|---|---|
committer | piso <piso@FreeBSD.org> | 2009-04-01 20:23:47 +0000 |
commit | c9b4c109954a4dd9052f62f379febea366d11a07 (patch) | |
tree | 12380d32edc71a17a6bfe18bb48510a54c10f4f3 /sys/netinet | |
parent | e965f0a26dd194aa82e93f27e2493e7c4d0afea2 (diff) | |
download | FreeBSD-src-c9b4c109954a4dd9052f62f379febea366d11a07.zip FreeBSD-src-c9b4c109954a4dd9052f62f379febea366d11a07.tar.gz |
Implement an ipfw action to reassemble ip packets: reass.
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_fw.h | 4 | ||||
-rw-r--r-- | sys/netinet/ip_fw2.c | 53 | ||||
-rw-r--r-- | sys/netinet/ip_fw_pfil.c | 6 |
3 files changed, 62 insertions, 1 deletions
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index 0cf1a52..35e7e12 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -139,7 +139,8 @@ enum ipfw_opcodes { /* arguments (4 byte each) */ O_FORWARD_IP, /* fwd sockaddr */ O_FORWARD_MAC, /* fwd mac */ O_NAT, /* nope */ - + O_REASS, /* none */ + /* * More opcodes. */ @@ -574,6 +575,7 @@ enum { IP_FW_NETGRAPH, IP_FW_NGTEE, IP_FW_NAT, + IP_FW_REASS, }; /* flags for divert mtag */ diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index 1405a27..fa6e6f1 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -898,6 +898,9 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, case O_NAT: action = "Nat"; break; + case O_REASS: + action = "Reass"; + break; default: action = "UNKNOWN"; break; @@ -3375,6 +3378,55 @@ check_body: goto done; } + case O_REASS: { + int ip_off; + + f->pcnt++; + f->bcnt += pktlen; + ip_off = (args->eh != NULL) ? ntohs(ip->ip_off) : ip->ip_off; + if (ip_off & (IP_MF | IP_OFFMASK)) { + /* + * ip_reass() expects len & off in host + * byte order: fix them in case we come + * from layer2. + */ + if (args->eh != NULL) { + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); + } + + m = ip_reass(m); + args->m = m; + + /* + * IP header checksum fixup after + * reassembly and leave header + * in network byte order. + */ + if (m != NULL) { + int hlen; + + ip = mtod(m, struct ip *); + hlen = ip->ip_hl << 2; + /* revert len & off for layer2 pkts */ + if (args->eh != NULL) + ip->ip_len = htons(ip->ip_len); + ip->ip_sum = 0; + if (hlen == sizeof(struct ip)) + ip->ip_sum = in_cksum_hdr(ip); + else + ip->ip_sum = in_cksum(m, hlen); + retval = IP_FW_REASS; + args->rule = f; + goto done; + } else { + retval = IP_FW_DENY; + goto done; + } + } + goto next_rule; + } + default: panic("-- unknown opcode %d\n", cmd->opcode); } /* end of switch() on opcodes */ @@ -4024,6 +4076,7 @@ check_ipfw_struct(struct ip_fw *rule, int size) case O_UNREACH6: #endif case O_SKIPTO: + case O_REASS: check_size: if (cmdlen != F_INSN_SIZE(ipfw_insn)) goto bad_size; diff --git a/sys/netinet/ip_fw_pfil.c b/sys/netinet/ip_fw_pfil.c index 1e6d2b0..11560a7 100644 --- a/sys/netinet/ip_fw_pfil.c +++ b/sys/netinet/ip_fw_pfil.c @@ -200,6 +200,9 @@ again: case IP_FW_NAT: goto again; /* continue with packet */ + case IP_FW_REASS: + goto again; + default: KASSERT(0, ("%s: unknown retval", __func__)); } @@ -329,6 +332,9 @@ again: case IP_FW_NAT: goto again; /* continue with packet */ + case IP_FW_REASS: + goto again; + default: KASSERT(0, ("%s: unknown retval", __func__)); } |