diff options
-rw-r--r-- | sbin/ipfw/ipfw.c | 175 | ||||
-rw-r--r-- | sys/netinet/ip_fw.h | 29 |
2 files changed, 197 insertions, 7 deletions
diff --git a/sbin/ipfw/ipfw.c b/sbin/ipfw/ipfw.c index 1caf288..f3b1ea3 100644 --- a/sbin/ipfw/ipfw.c +++ b/sbin/ipfw/ipfw.c @@ -412,7 +412,7 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth) if (chain->fw_flg & IP_FW_F_FRAG) printf(" frag"); - if (chain->fw_ipopt || chain->fw_ipnopt) { + if (chain->fw_ipflg & IP_FW_IF_IPOPT) { int _opt_printed = 0; #define PRINTOPT(x) {if (_opt_printed) printf(",");\ printf(x); _opt_printed = 1;} @@ -428,12 +428,39 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth) if (chain->fw_ipnopt & IP_FW_IPOPT_TS) PRINTOPT("!ts"); } + if (chain->fw_ipflg & IP_FW_IF_IPLEN) + printf(" iplen %u", chain->fw_iplen); + if (chain->fw_ipflg & IP_FW_IF_IPID) + printf(" ipid 0x%04x", chain->fw_ipid); + + if (chain->fw_ipflg & IP_FW_IF_IPTOS) { + int _opt_printed = 0; + + printf(" iptos "); + if (chain->fw_iptos & IPTOS_LOWDELAY) PRINTOPT("lowdelay"); + if (chain->fw_ipntos & IPTOS_LOWDELAY) PRINTOPT("!lowdelay"); + if (chain->fw_iptos & IPTOS_THROUGHPUT) PRINTOPT("throughput"); + if (chain->fw_ipntos & IPTOS_THROUGHPUT) PRINTOPT("!throughput"); + if (chain->fw_iptos & IPTOS_RELIABILITY) PRINTOPT("reliability"); + if (chain->fw_ipntos & IPTOS_RELIABILITY) PRINTOPT("!reliability"); + if (chain->fw_iptos & IPTOS_MINCOST) PRINTOPT("mincost"); + if (chain->fw_ipntos & IPTOS_MINCOST) PRINTOPT("!mincost"); + if (chain->fw_iptos & IPTOS_CE) PRINTOPT("congestion"); + if (chain->fw_ipntos & IPTOS_CE) PRINTOPT("!congestion"); + } + + if (chain->fw_ipflg & IP_FW_IF_IPTTL) + printf(" ipttl %u", chain->fw_ipttl); + + if (chain->fw_ipflg & IP_FW_IF_IPVER) + printf(" ipversion %u", chain->fw_ipver); + if (chain->fw_tcpf & IP_FW_TCPF_ESTAB) printf(" established"); else if (chain->fw_tcpf == IP_FW_TCPF_SYN && chain->fw_tcpnf == IP_FW_TCPF_ACK) printf(" setup"); - else if (chain->fw_tcpf || chain->fw_tcpnf) { + else if (chain->fw_ipflg & IP_FW_IF_TCPOPT) { int _flg_printed = 0; #define PRINTFLG(x) {if (_flg_printed) printf(",");\ printf(x); _flg_printed = 1;} @@ -452,7 +479,7 @@ 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) { + if (chain->fw_ipflg & IP_FW_IF_TCPOPT) { int _opt_printed = 0; #define PRINTTOPT(x) {if (_opt_printed) printf(",");\ printf(x); _opt_printed = 1;} @@ -470,6 +497,13 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth) if (chain->fw_tcpnopt & IP_FW_TCPOPT_CC) PRINTTOPT("!cc"); } + if (chain->fw_ipflg & IP_FW_IF_TCPSEQ) + printf(" tcpseq %lu", ntohl(chain->fw_tcpseq)); + if (chain->fw_ipflg & IP_FW_IF_TCPACK) + printf(" tcpack %lu", ntohl(chain->fw_tcpack)); + if (chain->fw_ipflg & IP_FW_IF_TCPWIN) + printf(" tcpwin %hu", ntohs(chain->fw_tcpwin)); + if (chain->fw_flg & IP_FW_F_ICMPBIT) { int type_index; int first = 1; @@ -837,7 +871,15 @@ show_usage(const char *fmt, ...) " {established|setup}\n" " tcpflags [!]{syn|fin|rst|ack|psh|urg},...\n" " ipoptions [!]{ssrr|lsrr|rr|ts},...\n" +" iplen {length}\n" +" ipid {identification number (in hex)}\n" +" iptos [!]{lowdelay|throughput|reliability|mincost|congestion}\n" +" ipttl {time to live}\n" +" ipversion {version number}\n" " tcpoptions [!]{mss|window|sack|ts|cc},...\n" +" tcpseq {sequence number}\n" +" tcpack {acknowledgement number}\n" +" tcpwin {window size}\n" " icmptypes {type[,type]}...\n" " pipeconfig:\n" " {bw|bandwidth} <number>{bit/s|Kbit/s|Mbit/s|Bytes/s|KBytes/s|MBytes/s}\n" @@ -1148,6 +1190,40 @@ fill_ipopt(u_char *set, u_char *reset, char **vp) } static void +fill_iptos(u_char *set, u_char *reset, char **vp) +{ + char *p = *vp,*q; + u_char *d; + + while (p && *p) { + if (*p == '!') { + p++; + d = reset; + } else { + d = set; + } + q = strchr(p, ','); + if (q) + *q++ = '\0'; + if (!strncmp(p,"lowdelay",strlen(p))) + *d |= IPTOS_LOWDELAY; + if (!strncmp(p,"throughput",strlen(p))) + *d |= IPTOS_THROUGHPUT; + if (!strncmp(p,"reliability",strlen(p))) + *d |= IPTOS_RELIABILITY; + if (!strncmp(p,"mincost",strlen(p))) + *d |= IPTOS_MINCOST; + if (!strncmp(p,"congestion",strlen(p))) + *d |= IPTOS_CE; +#if 0 /* conflicting! */ + if (!strncmp(p,"ecntransport",strlen(p))) + *d |= IPTOS_ECT; +#endif + p = q; + } +} + +static void fill_icmptypes(types, vp, fw_flg) u_long *types; char **vp; @@ -1878,40 +1954,127 @@ badviacombo: rule.fw_flg |= IP_FW_F_FRAG; av++; ac--; continue; } - if (!strncmp(*av,"ipoptions",strlen(*av))) { + if (!strncmp(*av,"ipoptions",strlen(*av)) || + !strncmp(*av,"ipopts",strlen(*av))) { av++; ac--; if (!ac) show_usage("missing argument" " for ``ipoptions''"); + rule.fw_ipflg |= IP_FW_IF_IPOPT; fill_ipopt(&rule.fw_ipopt, &rule.fw_ipnopt, av); av++; ac--; continue; } + if (!strncmp(*av,"iplen",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``iplen''"); + rule.fw_ipflg |= IP_FW_IF_IPLEN; + rule.fw_iplen = (u_short)strtoul(*av, NULL, 0); + av++; ac--; continue; + } + if (!strncmp(*av,"ipid",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``ipid''"); + rule.fw_ipflg |= IP_FW_IF_IPID; + if (strlen(*av) != 6 || (*av)[0] != '0' || (*av)[1] != 'x' || + isxdigit((*av)[2]) == 0 || + isxdigit((*av)[3]) == 0 || + isxdigit((*av)[4]) == 0 || + isxdigit((*av)[5]) == 0) + show_usage("argument to ipid must be in hex"); + rule.fw_ipid = (u_short)strtoul(*av, NULL, 0); + av++; ac--; continue; + } + if (!strncmp(*av,"iptos",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``iptos''"); + rule.fw_ipflg |= IP_FW_IF_IPTOS; + fill_iptos(&rule.fw_iptos, &rule.fw_ipntos, av); + av++; ac--; continue; + } + if (!strncmp(*av,"ipttl",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``ipttl''"); + rule.fw_ipflg |= IP_FW_IF_IPTTL; + rule.fw_ipttl = (u_short)strtoul(*av, NULL, 0); + av++; ac--; continue; + } + if (!strncmp(*av,"ipversion",strlen(*av)) || + !strncmp(*av,"ipver",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``ipversion''"); + rule.fw_ipflg |= IP_FW_IF_IPVER; + rule.fw_ipver = (u_short)strtoul(*av, NULL, 0); + av++; ac--; continue; + } if (rule.fw_prot == IPPROTO_TCP) { if (!strncmp(*av,"established",strlen(*av))) { rule.fw_tcpf |= IP_FW_TCPF_ESTAB; + rule.fw_ipflg |= IP_FW_IF_TCPFLG; av++; ac--; continue; } if (!strncmp(*av,"setup",strlen(*av))) { rule.fw_tcpf |= IP_FW_TCPF_SYN; rule.fw_tcpnf |= IP_FW_TCPF_ACK; + rule.fw_ipflg |= IP_FW_IF_TCPFLG; av++; ac--; continue; } - if (!strncmp(*av,"tcpflags",strlen(*av)) || !strncmp(*av,"tcpflgs",strlen(*av))) { + if (!strncmp(*av,"tcpflags",strlen(*av)) || + !strncmp(*av,"tcpflgs",strlen(*av))) { av++; ac--; if (!ac) show_usage("missing argument" " for ``tcpflags''"); + rule.fw_ipflg |= IP_FW_IF_TCPFLG; fill_tcpflag(&rule.fw_tcpf, &rule.fw_tcpnf, av); av++; ac--; continue; } - if (!strncmp(*av,"tcpoptions",strlen(*av)) || !strncmp(*av, "tcpopts",strlen(*av))) { + if (!strncmp(*av,"tcpoptions",strlen(*av)) || + !strncmp(*av, "tcpopts",strlen(*av))) { av++; ac--; if (!ac) show_usage("missing argument" " for ``tcpoptions''"); + rule.fw_ipflg |= IP_FW_IF_TCPOPT; fill_tcpopts(&rule.fw_tcpopt, &rule.fw_tcpnopt, av); av++; ac--; continue; } + if (!strncmp(*av,"tcpseq",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``tcpseq''"); + rule.fw_ipflg |= IP_FW_IF_TCPSEQ; + rule.fw_tcpseq = htonl((u_int32_t)strtoul(*av, NULL, 0)); + av++; ac--; continue; + } + if (!strncmp(*av,"tcpack",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``tcpack''"); + rule.fw_ipflg |= IP_FW_IF_TCPACK; + rule.fw_tcpack = htonl((u_int32_t)strtoul(*av, NULL, 0)); + av++; ac--; continue; + } + if (!strncmp(*av,"tcpwin",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``tcpwin''"); + rule.fw_ipflg |= IP_FW_IF_TCPWIN; + rule.fw_tcpwin = htons((u_short)strtoul(*av, NULL, 0)); + av++; ac--; continue; + } } if (rule.fw_prot == IPPROTO_ICMP) { if (!strncmp(*av,"icmptypes",strlen(*av))) { diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index 86b2bce..f61abd1 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -54,7 +54,7 @@ struct ip_fw { struct in_addr fw_src, fw_dst; /* Source and destination IP addr */ struct in_addr fw_smsk, fw_dmsk; /* Mask for src and dest IP addr */ u_short fw_number; /* Rule number */ - u_int fw_flg; /* Flags word */ + u_int fw_flg; /* Operational Flags word */ #define IP_FW_MAX_PORTS 10 /* A reasonable maximum */ union { u_short fw_pts[IP_FW_MAX_PORTS]; /* Array of port numbers to match */ @@ -62,9 +62,16 @@ struct ip_fw { #define IP_FW_ICMPTYPES_DIM (IP_FW_ICMPTYPES_MAX / (sizeof(unsigned) * 8)) unsigned fw_icmptypes[IP_FW_ICMPTYPES_DIM]; /* ICMP types bitmap */ } fw_uar; + u_int fw_ipflg; /* IP flags word */ u_char fw_ipopt,fw_ipnopt; /* IP options set/unset */ + u_short fw_iplen, fw_ipid; /* IP length, identification */ + u_char fw_iptos, fw_ipntos; /* IP type of service set/unset */ + u_char fw_ipttl; /* IP time to live */ + u_int fw_ipver:4; /* IP version */ u_char fw_tcpopt,fw_tcpnopt; /* TCP options set/unset */ u_char fw_tcpf,fw_tcpnf; /* TCP flags set/unset */ + u_int32_t fw_tcpseq, fw_tcpack; /* TCP sequence and acknowledgement */ + u_short fw_tcpwin; /* TCP window size */ long timestamp; /* timestamp (tv_sec) of last match */ union ip_fw_if fw_in_if, fw_out_if; /* Incoming and outgoing interfaces */ union { @@ -207,6 +214,26 @@ struct ipfw_dyn_rule { #define IP_FW_F_MASK 0x1FFFFFFF /* All possible flag bits mask */ +/* + * Flags for the 'fw_ipflg' field, for comparing values of ip and its protocols. + */ +#define IP_FW_IF_TCPOPT 0x00000001 /* tcp options */ +#define IP_FW_IF_TCPFLG 0x00000002 /* tcp flags */ +#define IP_FW_IF_TCPSEQ 0x00000004 /* tcp sequence number */ +#define IP_FW_IF_TCPACK 0x00000008 /* tcp acknowledgement number */ +#define IP_FW_IF_TCPWIN 0x00000010 /* tcp window size */ +#define IP_FW_IF_TCPMSK 0x0000001f /* mask of all tcp values */ + +#define IP_FW_IF_IPOPT 0x00000100 /* ip options */ +#define IP_FW_IF_IPLEN 0x00000200 /* ip length */ +#define IP_FW_IF_IPID 0x00000400 /* ip identification */ +#define IP_FW_IF_IPTOS 0x00000800 /* ip type of service */ +#define IP_FW_IF_IPTTL 0x00001000 /* ip time to live */ +#define IP_FW_IF_IPVER 0x00002000 /* ip version */ +#define IP_FW_IF_IPMSK 0x00003f00 /* mask of all ip values */ + +#define IP_FW_IF_MSK 0x0000ffff /* All possible bits mask */ + /* * For backwards compatibility with rules specifying "via iface" but * not restricted to only "in" or "out" packets, we define this combination |