summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/ipfw/ipfw.816
-rw-r--r--sbin/ipfw/ipfw2.c23
-rw-r--r--sbin/ipfw/ipfw2.h2
-rw-r--r--sys/conf/NOTES3
-rw-r--r--sys/conf/files2
-rw-r--r--sys/conf/options1
-rw-r--r--sys/modules/Makefile2
-rw-r--r--sys/modules/ipfw_pmod/Makefile8
-rw-r--r--sys/netpfil/ipfw/pmod/ip_fw_pmod.c101
-rw-r--r--sys/netpfil/ipfw/pmod/pmod.h36
-rw-r--r--sys/netpfil/ipfw/pmod/tcpmod.c246
11 files changed, 439 insertions, 1 deletions
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index 9f11bbb..27359d4 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 15, 2017
+.Dd April 3, 2017
.Dt IPFW 8
.Os
.Sh NAME
@@ -1118,6 +1118,20 @@ It is also possible to use the
keyword with setdscp.
If the tablearg value is not within the 0..64 range, lower 6 bits of supplied
value are used.
+.It Cm tcp-setmss Ar mss
+Set the Maximum Segment Size (MSS) in the TCP segment to value
+.Ar mss .
+The kernel module
+.Cm ipfw_pmod
+should be loaded or kernel should have
+.Cm options IPFIREWALL_PMOD
+to be able use this action.
+This command does not change a packet if original MSS value is lower than
+specified value.
+Both TCP over IPv4 and over IPv6 are supported.
+Regardless of matched a packet or not by the
+.Cm tcp-setmss
+rule, the search continues with the next rule.
.It Cm reass
Queue and reassemble IP fragments.
If the packet is not fragmented, counters are updated and
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index b954131..2d1d65a 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -36,6 +36,7 @@
#include <pwd.h>
#include <stdio.h>
#include <stdarg.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
@@ -238,6 +239,7 @@ static struct _s_x rule_eactions[] = {
{ "nat64lsn", TOK_NAT64LSN },
{ "nat64stl", TOK_NAT64STL },
{ "nptv6", TOK_NPTV6 },
+ { "tcp-setmss", TOK_TCPSETMSS },
{ NULL, 0 } /* terminator */
};
@@ -272,6 +274,7 @@ static struct _s_x rule_actions[] = {
{ "call", TOK_CALL },
{ "return", TOK_RETURN },
{ "eaction", TOK_EACTION },
+ { "tcp-setmss", TOK_TCPSETMSS },
{ NULL, 0 } /* terminator */
};
@@ -4027,6 +4030,26 @@ chkarg:
fill_cmd(action, O_CALLRETURN, F_NOT, 0);
break;
+ case TOK_TCPSETMSS: {
+ u_long mss;
+ uint16_t idx;
+
+ idx = pack_object(tstate, "tcp-setmss", IPFW_TLV_EACTION);
+ if (idx == 0)
+ errx(EX_DATAERR, "pack_object failed");
+ fill_cmd(action, O_EXTERNAL_ACTION, 0, idx);
+ NEED1("Missing MSS value");
+ action = next_cmd(action, &ablen);
+ action->len = 1;
+ CHECK_ACTLEN;
+ mss = strtoul(*av, NULL, 10);
+ if (mss == 0 || mss > UINT16_MAX)
+ errx(EX_USAGE, "invalid MSS value %s", *av);
+ fill_cmd(action, O_EXTERNAL_DATA, 0, (uint16_t)mss);
+ av++;
+ break;
+ }
+
default:
av--;
if (match_token(rule_eactions, *av) == -1)
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index a311458..0218a4a 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -284,6 +284,8 @@ enum tokens {
TOK_INTPREFIX,
TOK_EXTPREFIX,
TOK_PREFIXLEN,
+
+ TOK_TCPSETMSS,
};
/*
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index fa4202d..a481316 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -969,6 +969,9 @@ device lagg
#
# IPFIREWALL_NPTV6 adds support for in kernel NPTv6 in ipfw.
#
+# IPFIREWALL_PMOD adds support for protocols modification module. Currently
+# it supports only TCP MSS modification.
+#
# IPSTEALTH enables code to support stealth forwarding (i.e., forwarding
# packets without touching the TTL). This can be useful to hide firewalls
# from traceroute and similar tools.
diff --git a/sys/conf/files b/sys/conf/files
index 8478a15..0f47a19 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -3896,6 +3896,8 @@ netpfil/ipfw/nptv6/ip_fw_nptv6.c optional inet inet6 ipfirewall \
ipfirewall_nptv6
netpfil/ipfw/nptv6/nptv6.c optional inet inet6 ipfirewall \
ipfirewall_nptv6
+netpfil/ipfw/pmod/ip_fw_pmod.c optional inet ipfirewall_pmod
+netpfil/ipfw/pmod/tcpmod.c optional inet ipfirewall_pmod
netpfil/pf/if_pflog.c optional pflog pf inet
netpfil/pf/if_pfsync.c optional pfsync pf inet
netpfil/pf/pf.c optional pf inet
diff --git a/sys/conf/options b/sys/conf/options
index b5257a9..3a5d73c 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -422,6 +422,7 @@ IPFIREWALL_NAT64_DIRECT_OUTPUT opt_ipfw.h
IPFIREWALL_NPTV6 opt_ipfw.h
IPFIREWALL_VERBOSE opt_ipfw.h
IPFIREWALL_VERBOSE_LIMIT opt_ipfw.h
+IPFIREWALL_PMOD opt_ipfw.h
IPSEC opt_ipsec.h
IPSEC_DEBUG opt_ipsec.h
IPSEC_FILTERTUNNEL opt_ipsec.h
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 803538f..577f4dc 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -169,6 +169,7 @@ SUBDIR= \
ipfw_nat \
${_ipfw_nat64} \
${_ipfw_nptv6} \
+ ${_ipfw_pmod} \
${_ipmi} \
ip6_mroute_mod \
ip_mroute_mod \
@@ -449,6 +450,7 @@ _toecore= toecore
_if_enc= if_enc
_if_gif= if_gif
_if_gre= if_gre
+_ipfw_pmod= ipfw_pmod
.endif
.if (${MK_INET_SUPPORT} != "no" && ${MK_INET6_SUPPORT} != "no") || \
diff --git a/sys/modules/ipfw_pmod/Makefile b/sys/modules/ipfw_pmod/Makefile
new file mode 100644
index 0000000..5f0ab18
--- /dev/null
+++ b/sys/modules/ipfw_pmod/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/netpfil/ipfw/pmod
+
+KMOD= ipfw_pmod
+SRCS= ip_fw_pmod.c tcpmod.c opt_inet.h opt_inet6.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/netpfil/ipfw/pmod/ip_fw_pmod.c b/sys/netpfil/ipfw/pmod/ip_fw_pmod.c
new file mode 100644
index 0000000..b731c12
--- /dev/null
+++ b/sys/netpfil/ipfw/pmod/ip_fw_pmod.c
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2017 Yandex LLC
+ * Copyright (c) 2017 Andrey V. Elsukov <ae@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/rwlock.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/vnet.h>
+
+#include <netinet/in.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip_fw.h>
+
+#include <netpfil/ipfw/ip_fw_private.h>
+#include <netpfil/ipfw/pmod/pmod.h>
+
+static int
+vnet_ipfw_pmod_init(const void *arg __unused)
+{
+ int error;
+
+ error = tcpmod_init(&V_layer3_chain, IS_DEFAULT_VNET(curvnet));
+ return (error);
+}
+
+static int
+vnet_ipfw_pmod_uninit(const void *arg __unused)
+{
+
+ tcpmod_uninit(&V_layer3_chain, IS_DEFAULT_VNET(curvnet));
+ return (0);
+}
+
+static int
+ipfw_pmod_modevent(module_t mod, int type, void *unused)
+{
+
+ switch (type) {
+ case MOD_LOAD:
+ case MOD_UNLOAD:
+ break;
+ default:
+ return (EOPNOTSUPP);
+ }
+ return (0);
+}
+
+static moduledata_t ipfw_pmod_mod = {
+ "ipfw_pmod",
+ ipfw_pmod_modevent,
+ 0
+};
+
+/* Define startup order. */
+#define IPFW_PMOD_SI_SUB_FIREWALL SI_SUB_PROTO_IFATTACHDOMAIN
+#define IPFW_PMOD_MODEVENT_ORDER (SI_ORDER_ANY - 128) /* after ipfw */
+#define IPFW_PMOD_MODULE_ORDER (IPFW_PMOD_MODEVENT_ORDER + 1)
+#define IPFW_PMOD_VNET_ORDER (IPFW_PMOD_MODEVENT_ORDER + 2)
+
+DECLARE_MODULE(ipfw_pmod, ipfw_pmod_mod, IPFW_PMOD_SI_SUB_FIREWALL,
+ IPFW_PMOD_MODULE_ORDER);
+MODULE_DEPEND(ipfw_pmod, ipfw, 3, 3, 3);
+MODULE_VERSION(ipfw_pmod, 1);
+
+VNET_SYSINIT(vnet_ipfw_pmod_init, IPFW_PMOD_SI_SUB_FIREWALL,
+ IPFW_PMOD_VNET_ORDER, vnet_ipfw_pmod_init, NULL);
+VNET_SYSUNINIT(vnet_ipfw_pmod_uninit, IPFW_PMOD_SI_SUB_FIREWALL,
+ IPFW_PMOD_VNET_ORDER, vnet_ipfw_pmod_uninit, NULL);
diff --git a/sys/netpfil/ipfw/pmod/pmod.h b/sys/netpfil/ipfw/pmod/pmod.h
new file mode 100644
index 0000000..1e9f6ec
--- /dev/null
+++ b/sys/netpfil/ipfw/pmod/pmod.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2017 Yandex LLC
+ * Copyright (c) 2017 Andrey V. Elsukov <ae@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _IP_FW_PMOD_H_
+#define _IP_FW_PMOD_H_
+
+int tcpmod_init(struct ip_fw_chain *ch, int first);
+void tcpmod_uninit(struct ip_fw_chain *ch, int last);
+#endif /* _IP_FW_PMOD_H_ */
+
diff --git a/sys/netpfil/ipfw/pmod/tcpmod.c b/sys/netpfil/ipfw/pmod/tcpmod.c
new file mode 100644
index 0000000..fc2bfb5
--- /dev/null
+++ b/sys/netpfil/ipfw/pmod/tcpmod.c
@@ -0,0 +1,246 @@
+/*-
+ * Copyright (c) 2017 Yandex LLC
+ * Copyright (c) 2017 Andrey V. Elsukov <ae@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/pfil.h>
+#include <net/vnet.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/ip_fw.h>
+#include <netinet/ip6.h>
+
+#include <netpfil/ipfw/ip_fw_private.h>
+#include <netpfil/ipfw/pmod/pmod.h>
+
+#include <machine/in_cksum.h>
+
+static VNET_DEFINE(uint16_t, tcpmod_setmss_eid) = 0;
+#define V_tcpmod_setmss_eid VNET(tcpmod_setmss_eid)
+
+static int
+tcpmod_setmss(struct mbuf **mp, struct tcphdr *tcp, int tlen, uint16_t mss)
+{
+ struct mbuf *m;
+ u_char *cp;
+ int optlen, ret;
+ uint16_t oldmss, csum;
+
+ m = *mp;
+ ret = IP_FW_DENY;
+ if (m->m_len < m->m_pkthdr.len) {
+ /*
+ * We shouldn't have any data, IP packet contains only
+ * TCP header with options.
+ */
+ *mp = m = m_pullup(m, m->m_pkthdr.len);
+ if (m == NULL)
+ return (ret);
+ }
+ /* Parse TCP options. */
+ for (tlen -= sizeof(struct tcphdr), cp = (u_char *)(tcp + 1);
+ tlen > 0; tlen -= optlen, cp += optlen) {
+ if (cp[0] == TCPOPT_EOL)
+ break;
+ if (cp[0] == TCPOPT_NOP) {
+ optlen = 1;
+ continue;
+ }
+ if (tlen < 2)
+ break;
+ optlen = cp[1];
+ if (optlen < 2 || optlen > tlen)
+ break;
+ if (cp[0] == TCPOPT_MAXSEG) {
+ if (optlen != TCPOLEN_MAXSEG)
+ break;
+ ret = 0; /* report success */
+ bcopy(cp + 2, &oldmss, sizeof(oldmss));
+ /* Do not update lower MSS value */
+ if (oldmss <= mss)
+ break;
+ bcopy(&mss, cp + 2, sizeof(mss));
+ /* Update checksum if it is not delayed. */
+ if ((m->m_pkthdr.csum_flags &
+ (CSUM_TCP | CSUM_TCP_IPV6)) == 0) {
+ bcopy(&tcp->th_sum, &csum, sizeof(csum));
+ csum = cksum_adjust(csum, oldmss, mss);
+ bcopy(&csum, &tcp->th_sum, sizeof(csum));
+ }
+ break;
+ }
+ }
+
+ return (ret);
+}
+
+#ifdef INET6
+static int
+tcpmod_ipv6_setmss(struct mbuf **mp, uint16_t mss)
+{
+ struct ip6_hdr *ip6;
+ struct ip6_hbh *hbh;
+ struct tcphdr *tcp;
+ int hlen, plen, proto;
+
+ ip6 = mtod(*mp, struct ip6_hdr *);
+ hlen = sizeof(*ip6);
+ proto = ip6->ip6_nxt;
+ /*
+ * Skip IPv6 extension headers and get the TCP header.
+ * ipfw_chk() has already done this work. So we are sure that
+ * we will not do an access to the out of bounds. For this
+ * reason we skip some checks here.
+ */
+ while (proto == IPPROTO_HOPOPTS || proto == IPPROTO_ROUTING ||
+ proto == IPPROTO_DSTOPTS) {
+ hbh = mtodo(*mp, hlen);
+ proto = hbh->ip6h_nxt;
+ hlen += hbh->ip6h_len << 3;
+ }
+ tcp = mtodo(*mp, hlen);
+ plen = (*mp)->m_pkthdr.len - hlen;
+ hlen = tcp->th_off << 2;
+ /* We must have TCP options and enough data in a packet. */
+ if (hlen <= sizeof(struct tcphdr) || hlen > plen)
+ return (IP_FW_DENY);
+ return (tcpmod_setmss(mp, tcp, hlen, mss));
+}
+#endif /* INET6 */
+
+#ifdef INET
+static int
+tcpmod_ipv4_setmss(struct mbuf **mp, uint16_t mss)
+{
+ struct tcphdr *tcp;
+ struct ip *ip;
+ int hlen, plen;
+
+ ip = mtod(*mp, struct ip *);
+ hlen = ip->ip_hl << 2;
+ tcp = mtodo(*mp, hlen);
+ plen = (*mp)->m_pkthdr.len - hlen;
+ hlen = tcp->th_off << 2;
+ /* We must have TCP options and enough data in a packet. */
+ if (hlen <= sizeof(struct tcphdr) || hlen > plen)
+ return (IP_FW_DENY);
+ return (tcpmod_setmss(mp, tcp, hlen, mss));
+}
+#endif /* INET */
+
+/*
+ * ipfw external action handler.
+ */
+static int
+ipfw_tcpmod(struct ip_fw_chain *chain, struct ip_fw_args *args,
+ ipfw_insn *cmd, int *done)
+{
+ ipfw_insn *icmd;
+ int ret;
+
+ *done = 0; /* try next rule if not matched */
+ ret = IP_FW_DENY;
+ icmd = cmd + 1;
+ if (cmd->opcode != O_EXTERNAL_ACTION ||
+ cmd->arg1 != V_tcpmod_setmss_eid ||
+ icmd->opcode != O_EXTERNAL_DATA ||
+ icmd->len != F_INSN_SIZE(ipfw_insn))
+ return (ret);
+
+ /*
+ * NOTE: ipfw_chk() can set f_id.proto from IPv6 fragment header,
+ * but f_id._flags can be filled only from real TCP header.
+ *
+ * NOTE: ipfw_chk() drops very short packets in the PULLUP_TO()
+ * macro. But we need to check that mbuf is contiguous more than
+ * IP+IP_options/IP_extensions+tcphdr length, because TCP header
+ * must have TCP options, and ipfw_chk() does PULLUP_TO() size of
+ * struct tcphdr.
+ *
+ * NOTE: we require only the presence of SYN flag. User should
+ * properly configure the rule to select the direction of packets,
+ * that should be modified.
+ */
+ if (args->f_id.proto != IPPROTO_TCP ||
+ (args->f_id._flags & TH_SYN) == 0)
+ return (ret);
+
+ switch (args->f_id.addr_type) {
+#ifdef INET
+ case 4:
+ ret = tcpmod_ipv4_setmss(&args->m, htons(icmd->arg1));
+ break;
+#endif
+#ifdef INET6
+ case 6:
+ ret = tcpmod_ipv6_setmss(&args->m, htons(icmd->arg1));
+ break;
+#endif
+ }
+ /*
+ * We return zero in both @ret and @done on success, and ipfw_chk()
+ * will update rule counters. Otherwise a packet will not be matched
+ * by rule.
+ */
+ return (ret);
+}
+
+int
+tcpmod_init(struct ip_fw_chain *ch, int first)
+{
+
+ V_tcpmod_setmss_eid = ipfw_add_eaction(ch, ipfw_tcpmod, "tcp-setmss");
+ if (V_tcpmod_setmss_eid == 0)
+ return (ENXIO);
+ return (0);
+}
+
+void
+tcpmod_uninit(struct ip_fw_chain *ch, int last)
+{
+
+ ipfw_del_eaction(ch, V_tcpmod_setmss_eid);
+ V_tcpmod_setmss_eid = 0;
+}
+
OpenPOWER on IntegriCloud