diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index b3eec6c9a088..c070b2a92826 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -289,6 +289,12 @@ and the length of the port list is limited to .Pa /usr/src/sys/netinet/ip_fw.h ) ports. .Pp +Fragmented packets which have a non-zero offset (i.e. not the first +fragment) will never match a rule which has one or more port +specifications. See the +.Ar frag +option for details on matching fragmented packets. +.Pp Rules can apply to packets when they are incoming, or outgoing, or both. The .Ar in @@ -360,6 +366,10 @@ Additional .It frag Matches if the packet is a fragment and this is not the first fragment of the datagram. +.Ar frag +may not be used in conjunction with either +.Ar tcpflags +or TCP/UDP port specifications. .It in Matches if this packet was on the way in. .It out @@ -399,6 +409,12 @@ and .Ar urg . The absence of a particular flag may be denoted with a ``!''. +A rule which contains a +.Ar tcpflags +specification can never match a fragmented packet which has +a non-zero offset. See the +.Ar frag +option for details on matching fragmented packets. .It icmptypes Ar types Matches if the ICMP type is in the list .Ar types . diff --git a/sbin/ipfw/ipfw.c b/sbin/ipfw/ipfw.c index 29300d108054..5663ed7d637b 100644 --- a/sbin/ipfw/ipfw.c +++ b/sbin/ipfw/ipfw.c @@ -16,7 +16,7 @@ * * NEW command line interface for IP firewall facility * - * $Id: ipfw.c,v 1.52 1998/01/08 00:27:31 alex Exp $ + * $Id: ipfw.c,v 1.53 1998/01/08 03:03:50 alex Exp $ * */ @@ -502,7 +502,7 @@ show_usage(const char *fmt, ...) " src: from [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n" " dst: to [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n" " extras:\n" -" fragment\n" +" fragment (may not be used with ports or tcpflags)\n" " in\n" " out\n" " {xmit|recv|via} {iface|ip|any}\n" @@ -1108,6 +1108,15 @@ add(ac,av) } else if ((rule.fw_flg & IP_FW_F_OIFACE) && (rule.fw_flg & IP_FW_F_IN)) show_usage("can't check xmit interface of incoming packets"); + /* frag may not be used in conjunction with ports or TCP flags */ + if (rule.fw_flg & IP_FW_F_FRAG) { + if (rule.fw_tcpf || rule.fw_tcpnf) + show_usage(EX_USAGE, "can't mix 'frag' and tcpflags"); + + if (rule.fw_nports) + show_usage(EX_USAGE, "can't mix 'frag' and port specifications"); + } + if (!do_quiet) show_ipfw(&rule, 10, 10); i = setsockopt(s, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule); diff --git a/sys/netinet/ip_fw.c b/sys/netinet/ip_fw.c index 21011c2217f6..854879a19e08 100644 --- a/sys/netinet/ip_fw.c +++ b/sys/netinet/ip_fw.c @@ -12,7 +12,7 @@ * * This software is provided ``AS IS'' without any warranties of any kind. * - * $Id: ip_fw.c,v 1.76 1998/02/06 12:13:51 eivind Exp $ + * $Id: ip_fw.c,v 1.77 1998/02/09 06:10:10 eivind Exp $ */ /* @@ -459,8 +459,18 @@ ip_fw_chk(struct ip **pip, int hlen, if (offset == 1) /* cf. RFC 1858 */ goto bogusfrag; - if (offset != 0) /* Flags, ports aren't valid */ + if (offset != 0) { + /* + * TCP flags and ports aren't available in this + * packet -- if this rule specified either one, + * we consider the rule a non-match. + */ + if (f->fw_nports != 0 || + f->fw_tcpf != f->fw_tcpnf) + continue; + break; + } PULLUP_TO(hlen + 14); tcp = (struct tcphdr *) ((u_long *)ip + ip->ip_hl); if (f->fw_tcpf != f->fw_tcpnf && !tcpflg_match(tcp, f)) @@ -474,8 +484,17 @@ ip_fw_chk(struct ip **pip, int hlen, { struct udphdr *udp; - if (offset != 0) /* Ports aren't valid */ + if (offset != 0) { + /* + * Port specification is unavailable -- if this + * rule specifies a port, we consider the rule + * a non-match. + */ + if (f->fw_nports != 0) + continue; + break; + } PULLUP_TO(hlen + 4); udp = (struct udphdr *) ((u_long *)ip + ip->ip_hl); src_port = ntohs(udp->uh_sport); @@ -868,6 +887,19 @@ check_ipfw_struct(struct ip_fw *frwl) return(NULL); } + if ((frwl->fw_flg & IP_FW_F_FRAG) && + (frwl->fw_prot == IPPROTO_UDP || frwl->fw_prot == IPPROTO_TCP)) { + if (frwl->fw_nports) { + dprintf(("%s cannot mix 'frag' and ports\n", err_prefix)); + return(NULL); + } + if (frwl->fw_prot == IPPROTO_TCP && + frwl->fw_tcpf != frwl->fw_tcpnf) { + dprintf(("%s cannot mix 'frag' and TCP flags\n", err_prefix)); + return(NULL); + } + } + /* Check command specific stuff */ switch (frwl->fw_flg & IP_FW_F_COMMAND) {