Benno and me were looking into why pflow is sending flows with starttime after endtime. We believe this was introduced with this commit:
------------------------------------------------------------------------ CVSROOT: /cvs Module name: src Changes by: [email protected] 2011/11/25 05:52:10 Modified files: sys/net : if_pflow.c if_pfsync.c pf.c pf_ioctl.c pf_norm.c Log message: use time_uptime to set state creation values as time_second can be skewed at runtime by things like date(1) and ntpd. time_uptime is monotonic and therefore more useful to compare against. ok deraadt@ mikeb@ ------------------------------------------------------------------------ So the startime comes from time_uptime while the expiration time depends on time_second: in pf_purge_expired_states(u_int32_t maxcheck): } else if (pf_state_expires(cur) <= time_second) { The following patch changes the state timeouts to time_uptime. There are two additional patches for fragmentation and src track timeouts. I believe the remaining usages of time_second are for display purpose (in pf_ioctl.c, pf_table.c, pf_if.c and one in pf.c) Index: sys/net/if_pfsync.c =================================================================== RCS file: /opt/OpenBSD-CVS/src/sys/net/if_pfsync.c,v retrieving revision 1.189 diff -u -p -r1.189 if_pfsync.c --- sys/net/if_pfsync.c 26 Jul 2012 12:25:31 -0000 1.189 +++ sys/net/if_pfsync.c 28 Jul 2012 17:16:08 -0000 @@ -574,7 +574,7 @@ pfsync_state_import(struct pfsync_state /* copy to state */ bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr)); st->creation = time_uptime - ntohl(sp->creation); - st->expire = time_second; + st->expire = time_uptime; if (sp->expire) { u_int32_t timeout; @@ -948,7 +948,7 @@ pfsync_in_upd(caddr_t buf, int len, int if (sync < 2) { pfsync_alloc_scrub_memory(&sp->dst, &st->dst); pf_state_peer_ntoh(&sp->dst, &st->dst); - st->expire = time_second; + st->expire = time_uptime; st->timeout = sp->timeout; } st->pfsync_time = time_uptime; @@ -1022,7 +1022,7 @@ pfsync_in_upd_c(caddr_t buf, int len, in if (sync < 2) { pfsync_alloc_scrub_memory(&up->dst, &st->dst); pf_state_peer_ntoh(&up->dst, &st->dst); - st->expire = time_second; + st->expire = time_uptime; st->timeout = up->timeout; } st->pfsync_time = time_uptime; Index: sys/net/pf.c =================================================================== RCS file: /opt/OpenBSD-CVS/src/sys/net/pf.c,v retrieving revision 1.809 diff -u -p -r1.809 pf.c --- sys/net/pf.c 26 Jul 2012 12:25:31 -0000 1.809 +++ sys/net/pf.c 28 Jul 2012 17:16:08 -0000 @@ -1105,10 +1105,10 @@ pf_state_export(struct pfsync_state *sp, bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr)); sp->creation = htonl(time_uptime - st->creation); sp->expire = pf_state_expires(st); - if (sp->expire <= time_second) + if (sp->expire <= time_uptime) sp->expire = htonl(0); else - sp->expire = htonl(sp->expire - time_second); + sp->expire = htonl(sp->expire - time_uptime); sp->direction = st->direction; sp->log = st->log; @@ -1179,7 +1179,7 @@ pf_state_expires(const struct pf_state * /* handle all PFTM_* > PFTM_MAX here */ if (state->timeout == PFTM_PURGE) - return (time_second); + return (time_uptime); KASSERT(state->timeout != PFTM_UNLINKED); KASSERT(state->timeout < PFTM_MAX); timeout = state->rule.ptr->timeout[state->timeout]; @@ -1199,7 +1199,7 @@ pf_state_expires(const struct pf_state * return (state->expire + timeout * (end - states) / (end - start)); else - return (time_second); + return (time_uptime); } return (state->expire + timeout); } @@ -1343,7 +1343,7 @@ pf_purge_expired_states(u_int32_t maxche locked = 1; } pf_free_state(cur); - } else if (pf_state_expires(cur) <= time_second) { + } else if (pf_state_expires(cur) <= time_uptime) { /* unlink and free expired state */ pf_unlink_state(cur); if (! locked) { @@ -3761,7 +3761,7 @@ pf_create_state(struct pf_pdesc *pd, str } s->creation = time_uptime; - s->expire = time_second; + s->expire = time_uptime; if (pd->proto == IPPROTO_TCP) { if (s->state_flags & PFSTATE_SCRUB_TCP && @@ -4198,7 +4198,7 @@ pf_tcp_track_full(struct pf_pdesc *pd, s src->state = dst->state = TCPS_TIME_WAIT; /* update expire time */ - (*state)->expire = time_second; + (*state)->expire = time_uptime; if (src->state >= TCPS_FIN_WAIT_2 && dst->state >= TCPS_FIN_WAIT_2) (*state)->timeout = PFTM_TCP_CLOSED; @@ -4375,7 +4375,7 @@ pf_tcp_track_sloppy(struct pf_pdesc *pd, src->state = dst->state = TCPS_TIME_WAIT; /* update expire time */ - (*state)->expire = time_second; + (*state)->expire = time_uptime; if (src->state >= TCPS_FIN_WAIT_2 && dst->state >= TCPS_FIN_WAIT_2) (*state)->timeout = PFTM_TCP_CLOSED; @@ -4620,7 +4620,7 @@ pf_test_state_udp(struct pf_pdesc *pd, s dst->state = PFUDPS_MULTIPLE; /* update expire time */ - (*state)->expire = time_second; + (*state)->expire = time_uptime; if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE) (*state)->timeout = PFTM_UDP_MULTIPLE; else @@ -4762,7 +4762,7 @@ pf_test_state_icmp(struct pf_pdesc *pd, return (ret); } - (*state)->expire = time_second; + (*state)->expire = time_uptime; (*state)->timeout = PFTM_ICMP_ERROR_REPLY; /* translate source/destination address, if necessary */ @@ -5570,7 +5570,7 @@ pf_test_state_other(struct pf_pdesc *pd, dst->state = PFOTHERS_MULTIPLE; /* update expire time */ - (*state)->expire = time_second; + (*state)->expire = time_uptime; if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE) (*state)->timeout = PFTM_OTHER_MULTIPLE; else ------------------------------------------------------------------------ fragmentation timeouts: Index: sys/net/pf_norm.c =================================================================== RCS file: /opt/OpenBSD-CVS/src/sys/net/pf_norm.c,v retrieving revision 1.154 diff -u -p -r1.154 pf_norm.c --- sys/net/pf_norm.c 12 May 2012 13:08:48 -0000 1.154 +++ sys/net/pf_norm.c 28 Jul 2012 17:12:48 -0000 @@ -173,7 +173,7 @@ void pf_purge_expired_fragments(void) { struct pf_fragment *frag; - u_int32_t expire = time_second - + u_int32_t expire = time_uptime - pf_default_rule.timeout[PFTM_FRAG]; while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) { @@ -238,7 +238,7 @@ pf_find_fragment(struct pf_fragment_cmp frag = RB_FIND(pf_frag_tree, tree, (struct pf_fragment *)key); if (frag != NULL) { /* XXX Are we sure we want to update the timeout? */ - frag->fr_timeout = time_second; + frag->fr_timeout = time_uptime; TAILQ_REMOVE(&pf_fragqueue, frag, frag_next); TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next); } @@ -314,7 +314,7 @@ pf_fillup_fragment(struct pf_fragment_cm *(struct pf_fragment_cmp *)frag = *key; TAILQ_INIT(&frag->fr_queue); - frag->fr_timeout = time_second; + frag->fr_timeout = time_uptime; frag->fr_maxlen = frent->fe_len; RB_INSERT(pf_frag_tree, &pf_frag_tree, frag); ------------------------------------------------------------------------ source tracking timeouts: Index: sys/net/pf.c =================================================================== RCS file: /opt/OpenBSD-CVS/src/sys/net/pf.c,v retrieving revision 1.809 diff -u -p -r1.809 pf.c --- sys/net/pf.c 26 Jul 2012 12:25:31 -0000 1.809 +++ sys/net/pf.c 28 Jul 2012 17:19:58 -0000 @@ -389,13 +389,13 @@ pf_init_threshold(struct pf_threshold *t threshold->limit = limit * PF_THRESHOLD_MULT; threshold->seconds = seconds; threshold->count = 0; - threshold->last = time_second; + threshold->last = time_uptime; } void pf_add_threshold(struct pf_threshold *threshold) { - u_int32_t t = time_second, diff = t - threshold->last; + u_int32_t t = time_uptime, diff = t - threshold->last; if (diff >= threshold->seconds) threshold->count = 0; @@ -582,7 +582,7 @@ pf_insert_src_node(struct pf_src_node ** void pf_remove_src_node(struct pf_src_node *sn) { - if (sn->states > 0 || sn->expire > time_second) + if (sn->states > 0 || sn->expire > time_uptime) return; if (sn->rule.ptr != NULL) { @@ -1213,7 +1213,7 @@ pf_purge_expired_src_nodes(int waslocked for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) { next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur); - if (cur->states <= 0 && cur->expire <= time_second) { + if (cur->states <= 0 && cur->expire <= time_uptime) { if (! locked) { rw_enter_write(&pf_consistency_lock); next = RB_NEXT(pf_src_tree, @@ -1243,7 +1243,7 @@ pf_src_tree_remove_state(struct pf_state if (!timeout) timeout = pf_default_rule.timeout[PFTM_SRC_NODE]; - sni->sn->expire = time_second + timeout; + sni->sn->expire = time_uptime + timeout; } pool_put(&pf_sn_item_pl, sni); } Index: sys/net/pf_ioctl.c =================================================================== RCS file: /opt/OpenBSD-CVS/src/sys/net/pf_ioctl.c,v retrieving revision 1.253 diff -u -p -r1.253 pf_ioctl.c --- sys/net/pf_ioctl.c 8 Jul 2012 07:58:09 -0000 1.253 +++ sys/net/pf_ioctl.c 28 Jul 2012 17:19:58 -0000 @@ -2333,7 +2333,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a p = psn->psn_src_nodes; RB_FOREACH(n, pf_src_tree, &tree_src_tracking) { - int secs = time_second, diff; + int secs = time_uptime, diff; if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len) break; -- I'm not entirely sure you are real.
