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.

Reply via email to