Index: sbin/ipfw/ipfw.8 =================================================================== RCS file: /export/ncvs/src/sbin/ipfw/ipfw.8,v retrieving revision 1.93 diff -u -r1.93 ipfw.8 --- sbin/ipfw/ipfw.8 2001/10/14 22:46:05 1.93 +++ sbin/ipfw/ipfw.8 2001/11/02 02:58:16 @@ -631,13 +640,37 @@ 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 that may be overridden on a per-rule basis. +The lifetime is refreshed each time a matching packet is +found. +.Pp +The actual behaviour can be modified by specifying a different +.Ar method , +although at the moment only the default one is specified. +.Pp +The default rule lifetime may be overridden for a specific +rule by appending +.Cm lifetime Ar number +to explicitly set the number of seconds for the dynamic rule +lifetime. +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 non-TCP rules, it overrides the .Xr sysctl 8 -variables), and the lifetime is refreshed every time a matching +variable +.Em net.inet.ip.fw.dyn_short_lifetime . +The lifetime is refreshed every time a matching packet is found. .It Cm limit Bro Cm src-addr | src-port | dst-addr | dst-port Brc Ar N The firewall will only allow Index: sbin/ipfw/ipfw.c =================================================================== RCS file: /export/ncvs/src/sbin/ipfw/ipfw.c,v retrieving revision 1.117 diff -u -r1.117 ipfw.c --- sbin/ipfw/ipfw.c 2001/11/01 08:45:02 1.117 +++ sbin/ipfw/ipfw.c 2001/11/02 07:33:46 @@ -394,13 +394,16 @@ break ; case DYN_KEEP_STATE: printf(" keep-state"); + if (chain->fw_dyn_lifetime) + printf(" lifetime %d", + (int)chain->fw_dyn_lifetime); break; case DYN_LIMIT: printf(" limit"); for ( ; p->s != NULL ; p++) if (chain->limit_mask & p->x) printf(" %s", p->s); - printf(" %d", chain->conn_limit); + printf(" %d", chain->conn_limit); break ; } } @@ -938,7 +941,7 @@ " tcpack {acknowledgement number}\n" " tcpwin {window size}\n" " icmptypes {type[, type]}...\n" -" keep-state [method]\n" +" keep-state [lifetime ]\n" " pipeconfig:\n" " {bw|bandwidth} {bit/s|Kbit/s|Mbit/s|Bytes/s|KBytes/s|MBytes/s}\n" " {bw|bandwidth} interface_name\n" @@ -2030,6 +2033,19 @@ 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 + errx(EX_USAGE, "``lifetime'' requires" + " integer argument"); + } else + /* sysctl(8) default is used when zeroed. */ + rule.fw_dyn_lifetime = 0; } else if (!strncmp(*av, "bridged", strlen(*av))) { rule.fw_flg |= IP_FW_BRIDGED; av++; ac--; Index: sys/netinet/ip_fw.c =================================================================== RCS file: /export/ncvs/src/sys/netinet/ip_fw.c,v retrieving revision 1.173 diff -u -r1.173 ip_fw.c --- sys/netinet/ip_fw.c 2001/10/05 07:06:31 1.173 +++ sys/netinet/ip_fw.c 2001/11/02 08:52:23 @@ -815,7 +838,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) : @@ -838,12 +861,9 @@ 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 ; - } + } else + /* should do something for UDP and others... */ + q->expire = time_second + q->lifetime ; if (match_direction) *match_direction = dir ; return q ; @@ -903,7 +923,21 @@ } r->id = *id ; - r->expire = time_second + dyn_syn_lifetime ; + r->lifetime = rule->fw_dyn_lifetime ; + switch (r->id.proto) { + case IPPROTO_TCP: + r->lifetime = r->lifetime ? r->lifetime : dyn_ack_lifetime; + r->expire = time_second + dyn_syn_lifetime; + break; + case IPPROTO_UDP: + r->lifetime = r->lifetime ? r->lifetime : dyn_udp_lifetime; + r->expire = time_second + r->lifetime; + break; + default: + r->lifetime = r->lifetime ? r->lifetime : dyn_short_lifetime; + r->expire = time_second + r->lifetime; + break; + } r->rule = rule ; r->dyn_type = dyn_type ; r->pcnt = r->bcnt = 0 ; Index: sys/netinet/ip_fw.h =================================================================== RCS file: /export/ncvs/src/sys/netinet/ip_fw.h,v retrieving revision 1.62 diff -u -r1.62 ip_fw.h --- sys/netinet/ip_fw.h 2001/10/29 15:09:07 1.62 +++ sys/netinet/ip_fw.h 2001/11/01 23:27:28 @@ -116,6 +116,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; void *pipe_ptr; /* flow_set ptr for dummynet pipe */ void *next_rule_ptr; /* next rule in case of match */ @@ -150,6 +151,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 /* * @@ -181,6 +183,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 specified lifetime */ u_int32_t expire; /* expire time */ u_int64_t pcnt; /* packet match counters */ u_int64_t bcnt; /* byte match counters */