summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorpiso <piso@FreeBSD.org>2009-04-01 20:23:47 +0000
committerpiso <piso@FreeBSD.org>2009-04-01 20:23:47 +0000
commitc9b4c109954a4dd9052f62f379febea366d11a07 (patch)
tree12380d32edc71a17a6bfe18bb48510a54c10f4f3 /sys/netinet
parente965f0a26dd194aa82e93f27e2493e7c4d0afea2 (diff)
downloadFreeBSD-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.h4
-rw-r--r--sys/netinet/ip_fw2.c53
-rw-r--r--sys/netinet/ip_fw_pfil.c6
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__));
}
OpenPOWER on IntegriCloud