# FILE: ipfw.patch # PATCHES: /usr/src/sys/netinet/ip_fw.h # /usr/src/sys/netinet/ip_fw.h # /usr/src/sbin/ipfw/ipfw.c # /usr/src/sbin/ipfw/ipfw.8 # WRITTEN BY: Aaron D. Gifford - http://www.adg.us/ # PURPOSE: Patch the FreeBSD kernel's ipfw system to support per-rule # dynamic rule lifetime overriding. This patch set patches # the kernel, the ipfw command line utility, and the ipfw # utility's man page. # --- /usr/src/sys/netinet/ip_fw.h.orig Tue Jul 9 03:11:42 2002 +++ /usr/src/sys/netinet/ip_fw.h Thu Aug 1 09:59:33 2002 @@ -125,6 +125,7 @@ u_short fu_skipto_rule; /* SKIPTO command rule number */ u_short fu_reject_code; /* REJECT response code */ struct sockaddr_in fu_fwd_ip; + u_int32_t fu_dyn_lifetime; /* Explicit dynamic rule lifetime */ } fw_un; /* @@ -166,6 +167,7 @@ #define fw_reject_code fw_un.fu_reject_code #define fw_pipe_nr fw_un.fu_pipe_nr #define fw_fwd_ip fw_un.fu_fwd_ip +#define fw_dyn_lifetime fw_un.fu_dyn_lifetime /* * @@ -197,6 +199,7 @@ struct ipfw_flow_id id; /* (masked) flow id */ struct ip_fw *rule; /* pointer to rule */ struct ipfw_dyn_rule *parent; /* pointer to parent rule */ + u_int32_t lifetime; /* per-rule lifetime */ u_int32_t expire; /* expire time */ u_int64_t pcnt; /* packet match counters */ u_int64_t bcnt; /* byte match counters */ --- /usr/src/sys/netinet/ip_fw.c.orig Sun Jul 28 20:04:25 2002 +++ /usr/src/sys/netinet/ip_fw.c Thu Aug 1 09:59:33 2002 @@ -783,7 +783,7 @@ break ; case TH_SYN | (TH_SYN << 8) : /* move to established */ - q->expire = time_second + dyn_ack_lifetime ; + q->expire = time_second + q->lifetime ; break ; case TH_SYN | (TH_SYN << 8) | TH_FIN : case TH_SYN | (TH_SYN << 8) | (TH_FIN << 8) : @@ -806,11 +806,16 @@ q->expire = time_second + dyn_rst_lifetime ; break ; } - } else if (pkt->proto == IPPROTO_UDP) { - q->expire = time_second + dyn_udp_lifetime ; } else { - /* other protocols */ - q->expire = time_second + dyn_short_lifetime ; + /* + * UDP and other protocols: + * NOTE: The value of q->lifetime, if not explicitly set in + * the ruleset, has already been set earlier, at the time + * that this specific dynamic rule was created by an initial + * packet match, set to the value of dyn_udp_lifetime (for + * UDP rules), or to dyn_short_lifetime (for non-UDP rules). + */ + q->expire = time_second + q->lifetime ; } if (match_direction) *match_direction = dir ; @@ -871,7 +876,20 @@ } r->id = *id ; - r->expire = time_second + dyn_syn_lifetime ; + r->lifetime = rule->fw_dyn_lifetime ; + if (r->id.proto == IPPROTO_TCP) { + r->lifetime = r->lifetime ? r->lifetime : dyn_ack_lifetime ; + r->expire = time_second + dyn_syn_lifetime ; + } else { + if (r->lifetime == 0) { + if (r->id.proto == IPPROTO_UDP) { + r->lifetime = dyn_udp_lifetime ; + } else { + r->lifetime = dyn_short_lifetime ; + } + } + r->expire = time_second + r->lifetime ; + } r->rule = rule ; r->dyn_type = dyn_type ; r->pcnt = r->bcnt = 0 ; --- /usr/src/sbin/ipfw/ipfw.c.orig Mon May 13 04:14:59 2002 +++ /usr/src/sbin/ipfw/ipfw.c Thu Aug 1 09:59:33 2002 @@ -393,6 +393,9 @@ break ; case DYN_KEEP_STATE: printf(" keep-state"); + if (chain->fw_dyn_lifetime) + printf(" lifetime %lu", (unsigned long) + chain->fw_dyn_lifetime); break; case DYN_LIMIT: printf(" limit"); @@ -889,7 +892,7 @@ " ipoptions [!]{ssrr|lsrr|rr|ts}, ...\n" " tcpoptions [!]{mss|window|sack|ts|cc}, ...\n" " icmptypes {type[, type]}...\n" -" keep-state [method]\n" +" keep-state [method] [lifetime ]\n" " pipeconfig:\n" " {bw|bandwidth} {bit/s|Kbit/s|Mbit/s|Bytes/s|KBytes/s|MBytes/s}\n" " {bw|bandwidth} interface_name\n" @@ -1955,6 +1958,15 @@ if (ac > 0 && (type = atoi(*av)) != 0) { rule.dyn_type = type; av++; ac--; + } + if (ac > 0 && !strncmp(*av, "lifetime", strlen(*av))) { + u_long lifetime; + + av++; ac--; + if (ac > 0 && (lifetime = atoi(*av)) != 0) { + rule.fw_dyn_lifetime = lifetime; + av++; ac--; + } } } else if (!strncmp(*av, "bridged", strlen(*av))) { rule.fw_flg |= IP_FW_BRIDGED; --- /usr/src/sbin/ipfw/ipfw.8.orig Wed May 1 15:29:59 2002 +++ /usr/src/sbin/ipfw/ipfw.8 Thu Aug 1 09:59:33 2002 @@ -616,14 +616,35 @@ interface. .It Ar options : .Bl -tag -width indent -.It Cm keep-state +.It Xo Cm keep-state +.Op Cm lifetime Ar number +.Xc Upon a match, the firewall will create a dynamic rule, whose -default behaviour is to matching bidirectional traffic between +default behaviour is to match bidirectional traffic between source and destination IP/port using the same protocol. -The rule has a limited lifetime (controlled by a set of +The rule has a limited lifetime controlled by a set of .Xr sysctl 8 -variables), and the lifetime is refreshed every time a matching +variables, and the lifetime is refreshed each time a matching packet is found. +.Pp +The default limited rule lifetime behavior may be modified +for a specific rule by appending +.Cm lifetime Ar number +immediately after +.Cm keep-state . +Doing so will explicitly set the dynamic rule lifetime to the +specified number of seconds, overriding the default lifetime +behavior for the specified rule. +.Pp +For TCP rules, explicitly setting a rule lifetime overrides the +default setting stored in the +.Xr sysctl 8 +variable +.Em net.inet.ip.fw.dyn_ack_lifetime . +For UDP rules, it overrides +.Em net.inet.ip.fw.dyn_udp_lifetime . +For all other rules, it overrides +.Em net.inet.ip.fw.dyn_short_lifetime . .It Cm limit Bro Cm src-addr | src-port | dst-addr | dst-port Brc Ar N The firewall will only allow .Ar N