summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authordan <dan@FreeBSD.org>2000-06-08 15:34:51 +0000
committerdan <dan@FreeBSD.org>2000-06-08 15:34:51 +0000
commitc3897dad80cc844b7f75b8cfa53825c031d02605 (patch)
treea156e91e6ecec2e7ac6b722fecb49d451eb5515b /sbin
parent31f827d91f8e4147518f8d6192a98d5196ef935a (diff)
downloadFreeBSD-src-c3897dad80cc844b7f75b8cfa53825c031d02605.zip
FreeBSD-src-c3897dad80cc844b7f75b8cfa53825c031d02605.tar.gz
Add tcpoptions to ipfw. This works much in the same way as ipoptions do.
It also squashes 99% of packet kiddie synflood orgies. For example, to rate syn packets without MSS, ipfw pipe 10 config 56Kbit/s queue 10Packets ipfw add pipe 10 tcp from any to any in setup tcpoptions !mss Submitted by: Richard A. Steenbergen <ras@e-gerbil.net>
Diffstat (limited to 'sbin')
-rw-r--r--sbin/ipfw/ipfw.819
-rw-r--r--sbin/ipfw/ipfw.c74
2 files changed, 88 insertions, 5 deletions
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index b7104a8..13dde53 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -650,6 +650,25 @@ The supported IP options are:
The absence of a particular option may be denoted
with a
.Ql ! .
+.It Cm tcpoptions Ar spec
+Match if the TCP header contains the comma separated list of
+options specified in
+.Ar spec .
+The supported TCP options are:
+.Pp
+.Cm mss
+(maximum segment size),
+.Cm window
+(tcp window advertisement),
+.Cm sack
+(selective ack),
+.Cm ts
+(rfc1323 timestamp) and
+.Cm cc
+(rfc1644 t/tcp connection count).
+The absence of a particular option may be denoted
+with a
+.Ql ! .
.It Cm established
TCP packets only.
Match packets that have the RST or ACK bits set.
diff --git a/sbin/ipfw/ipfw.c b/sbin/ipfw/ipfw.c
index 0c43203..75cb893 100644
--- a/sbin/ipfw/ipfw.c
+++ b/sbin/ipfw/ipfw.c
@@ -437,7 +437,7 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth)
#define PRINTFLG(x) {if (_flg_printed) printf(",");\
printf(x); _flg_printed = 1;}
- printf(" tcpflg ");
+ printf(" tcpflags ");
if (chain->fw_tcpf & IP_FW_TCPF_FIN) PRINTFLG("fin");
if (chain->fw_tcpnf & IP_FW_TCPF_FIN) PRINTFLG("!fin");
if (chain->fw_tcpf & IP_FW_TCPF_SYN) PRINTFLG("syn");
@@ -451,6 +451,24 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth)
if (chain->fw_tcpf & IP_FW_TCPF_URG) PRINTFLG("urg");
if (chain->fw_tcpnf & IP_FW_TCPF_URG) PRINTFLG("!urg");
}
+ if (chain->fw_tcpopt || chain->fw_tcpnopt) {
+ int _opt_printed = 0;
+#define PRINTTOPT(x) {if (_opt_printed) printf(",");\
+ printf(x); _opt_printed = 1;}
+
+ printf(" tcpoptions ");
+ if (chain->fw_tcpopt & IP_FW_TCPOPT_MSS) PRINTTOPT("mss");
+ if (chain->fw_tcpnopt & IP_FW_TCPOPT_MSS) PRINTTOPT("!mss");
+ if (chain->fw_tcpopt & IP_FW_TCPOPT_WINDOW) PRINTTOPT("window");
+ if (chain->fw_tcpnopt & IP_FW_TCPOPT_WINDOW) PRINTTOPT("!window");
+ if (chain->fw_tcpopt & IP_FW_TCPOPT_SACK) PRINTTOPT("sack");
+ if (chain->fw_tcpnopt & IP_FW_TCPOPT_SACK) PRINTTOPT("!sack");
+ if (chain->fw_tcpopt & IP_FW_TCPOPT_TS) PRINTTOPT("ts");
+ if (chain->fw_tcpnopt & IP_FW_TCPOPT_TS) PRINTTOPT("!ts");
+ if (chain->fw_tcpopt & IP_FW_TCPOPT_CC) PRINTTOPT("cc");
+ if (chain->fw_tcpnopt & IP_FW_TCPOPT_CC) PRINTTOPT("!cc");
+ }
+
if (chain->fw_flg & IP_FW_F_ICMPBIT) {
int type_index;
int first = 1;
@@ -818,6 +836,7 @@ show_usage(const char *fmt, ...)
" {established|setup}\n"
" tcpflags [!]{syn|fin|rst|ack|psh|urg},...\n"
" ipoptions [!]{ssrr|lsrr|rr|ts},...\n"
+" tcpoptions [!]{mss|window|sack|ts|cc},...\n"
" icmptypes {type[,type]}...\n"
" pipeconfig:\n"
" {bw|bandwidth} <number>{bit/s|Kbit/s|Mbit/s|Bytes/s|KBytes/s|MBytes/s}\n"
@@ -1025,9 +1044,7 @@ fill_port(cnt, ptr, off, arg)
}
static void
-fill_tcpflag(set, reset, vp)
- u_char *set, *reset;
- char **vp;
+fill_tcpflag(u_char *set, u_char *reset, char **vp)
{
char *p = *vp,*q;
u_char *d;
@@ -1067,6 +1084,45 @@ fill_tcpflag(set, reset, vp)
}
static void
+fill_tcpopts(u_char *set, u_char *reset, char **vp)
+{
+ char *p = *vp,*q;
+ u_char *d;
+
+ while (p && *p) {
+ struct tpcopts {
+ char * name;
+ u_char value;
+ } opts[] = {
+ { "mss", IP_FW_TCPOPT_MSS },
+ { "window", IP_FW_TCPOPT_WINDOW },
+ { "sack", IP_FW_TCPOPT_SACK },
+ { "ts", IP_FW_TCPOPT_TS },
+ { "cc", IP_FW_TCPOPT_CC },
+ };
+ int i;
+
+ if (*p == '!') {
+ p++;
+ d = reset;
+ } else {
+ d = set;
+ }
+ q = strchr(p, ',');
+ if (q)
+ *q++ = '\0';
+ for (i = 0; i < sizeof(opts) / sizeof(opts[0]); ++i)
+ if (!strncmp(p, opts[i].name, strlen(p))) {
+ *d |= opts[i].value;
+ break;
+ }
+ if (i == sizeof(opts) / sizeof(opts[0]))
+ show_usage("invalid tcp option ``%s''", p);
+ p = q;
+ }
+}
+
+static void
fill_ipopt(u_char *set, u_char *reset, char **vp)
{
char *p = *vp,*q;
@@ -1839,7 +1895,7 @@ badviacombo:
rule.fw_tcpnf |= IP_FW_TCPF_ACK;
av++; ac--; continue;
}
- if (!strncmp(*av,"tcpflags",strlen(*av))) {
+ if (!strncmp(*av,"tcpflags",strlen(*av)) || !strncmp(*av,"tcpflgs",strlen(*av))) {
av++; ac--;
if (!ac)
show_usage("missing argument"
@@ -1847,6 +1903,14 @@ badviacombo:
fill_tcpflag(&rule.fw_tcpf, &rule.fw_tcpnf, av);
av++; ac--; continue;
}
+ if (!strncmp(*av,"tcpoptions",strlen(*av)) || !strncmp(*av, "tcpopts",strlen(*av))) {
+ av++; ac--;
+ if (!ac)
+ show_usage("missing argument"
+ " for ``tcpflags''");
+ fill_tcpopts(&rule.fw_tcpopt, &rule.fw_tcpnopt, av);
+ av++; ac--; continue;
+ }
}
if (rule.fw_prot == IPPROTO_ICMP) {
if (!strncmp(*av,"icmptypes",strlen(*av))) {
OpenPOWER on IntegriCloud