The branch main has been updated by kp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=c6bf20a2a46dc36bf881ac594454f71379828a9a

commit c6bf20a2a46dc36bf881ac594454f71379828a9a
Author:     Kristof Provost <k...@freebsd.org>
AuthorDate: 2021-07-06 10:12:12 +0000
Commit:     Kristof Provost <k...@freebsd.org>
CommitDate: 2021-07-09 08:29:53 +0000

    pf: add DIOCGETSTATESV2
    
    Add a new version of the DIOCGETSTATES call, which extends the struct to
    include the original interface information.
    
    MFC after:      1 week
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D31097
---
 sys/net/pfvar.h           |  73 ++++++++++++++++++++++++++++
 sys/netpfil/pf/pf_ioctl.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 192 insertions(+)

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 7bbb585106c7..17af5d46a183 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -520,6 +520,65 @@ struct pf_state_cmp {
 #define        PFSTATE_SETPRIO         0x0200
 #define        PFSTATE_SETMASK   (PFSTATE_SETPRIO)
 
+struct pf_state_scrub_export {
+       uint16_t        pfss_flags;
+       uint8_t         pfss_ttl;       /* stashed TTL          */
+#define PF_SCRUB_FLAG_VALID            0x01
+       uint8_t         scrub_flag;
+       uint32_t        pfss_ts_mod;    /* timestamp modulation */
+};
+
+struct pf_state_key_export {
+       struct pf_addr   addr[2];
+       uint16_t         port[2];
+};
+
+struct pf_state_peer_export {
+       struct pf_state_scrub_export    scrub;  /* state is scrubbed    */
+       uint32_t        seqlo;          /* Max sequence number sent     */
+       uint32_t        seqhi;          /* Max the other end ACKd + win */
+       uint32_t        seqdiff;        /* Sequence number modulator    */
+       uint16_t        max_win;        /* largest window (pre scaling) */
+       uint16_t        mss;            /* Maximum segment size option  */
+       uint8_t         state;          /* active state level           */
+       uint8_t         wscale;         /* window scaling factor        */
+       uint8_t         dummy[6];
+};
+_Static_assert(sizeof(struct pf_state_peer_export) == 32, "size incorrect");
+
+struct pf_state_export {
+       uint64_t         version;
+#define        PF_STATE_VERSION        20210706
+       uint64_t         id;
+       char             ifname[IFNAMSIZ];
+       char             orig_ifname[IFNAMSIZ];
+       struct pf_state_key_export       key[2];
+       struct pf_state_peer_export      src;
+       struct pf_state_peer_export      dst;
+       struct pf_addr   rt_addr;
+       uint32_t         rule;
+       uint32_t         anchor;
+       uint32_t         nat_rule;
+       uint32_t         creation;
+       uint32_t         expire;
+       uint32_t         spare0;
+       uint64_t         packets[2];
+       uint64_t         bytes[2];
+       uint32_t         creatorid;
+       uint32_t         spare1;
+       sa_family_t      af;
+       uint8_t          proto;
+       uint8_t          direction;
+       uint8_t          log;
+       uint8_t          state_flags;
+       uint8_t          timeout;
+       uint8_t          sync_flags;
+       uint8_t          updates;
+
+       uint8_t          spare[112];
+};
+_Static_assert(sizeof(struct pf_state_export) == 384, "size incorrect");
+
 #ifdef _KERNEL
 struct pf_kstate {
        u_int64_t                id;
@@ -646,6 +705,8 @@ extern pfsync_detach_ifnet_t        
*pfsync_detach_ifnet_ptr;
 
 void                   pfsync_state_export(struct pfsync_state *,
                            struct pf_kstate *);
+void                   pf_state_export(struct pf_state_export *,
+                           struct pf_kstate *);
 
 /* pflog */
 struct pf_kruleset;
@@ -1187,6 +1248,17 @@ struct pfioc_states {
 #define ps_states      ps_u.psu_states
 };
 
+struct pfioc_states_v2 {
+       int             ps_len;
+       uint64_t        ps_req_version;
+       union {
+               caddr_t                  psu_buf;
+               struct pf_state_export  *psu_states;
+       } ps_u;
+#define ps_buf         ps_u.psu_buf
+#define ps_states      ps_u.psu_states
+};
+
 struct pfioc_src_nodes {
        int     psn_len;
        union {
@@ -1402,6 +1474,7 @@ struct pfioc_iface {
 #define        DIOCCLRIFFLAG   _IOWR('D', 90, struct pfioc_iface)
 #define        DIOCKILLSRCNODES        _IOWR('D', 91, struct 
pfioc_src_node_kill)
 #define        DIOCKEEPCOUNTERS        _IOWR('D', 92, struct pfioc_nv)
+#define DIOCGETSTATESV2        _IOWR('D', 93, struct pfioc_states_v2)
 
 struct pf_ifspeed_v0 {
        char                    ifname[IFNAMSIZ];
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 33eb0e15ea57..e4017f48a8ca 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -2108,6 +2108,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int 
flags, struct thread *td
                case DIOCNATLOOK:
                case DIOCSETDEBUG:
                case DIOCGETSTATES:
+               case DIOCGETSTATESV2:
                case DIOCGETSTATESNV:
                case DIOCGETTIMEOUT:
                case DIOCCLRRULECTRS:
@@ -2161,6 +2162,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int 
flags, struct thread *td
                case DIOCGETSTATENV:
                case DIOCGETSTATUS:
                case DIOCGETSTATES:
+               case DIOCGETSTATESV2:
                case DIOCGETSTATESNV:
                case DIOCGETTIMEOUT:
                case DIOCGETLIMIT:
@@ -2871,6 +2873,60 @@ DIOCGETSTATES_full:
                break;
        }
 
+       case DIOCGETSTATESV2: {
+               struct pfioc_states_v2  *ps = (struct pfioc_states_v2 *)addr;
+               struct pf_kstate        *s;
+               struct pf_state_export  *pstore, *p;
+               int i, nr;
+
+               if (ps->ps_req_version > PF_STATE_VERSION) {
+                       error = ENOTSUP;
+                       break;
+               }
+
+               if (ps->ps_len <= 0) {
+                       nr = uma_zone_get_cur(V_pf_state_z);
+                       ps->ps_len = sizeof(struct pf_state_export) * nr;
+                       break;
+               }
+
+               p = pstore = malloc(ps->ps_len, M_TEMP, M_WAITOK | M_ZERO);
+               nr = 0;
+
+               for (i = 0; i <= pf_hashmask; i++) {
+                       struct pf_idhash *ih = &V_pf_idhash[i];
+
+                       if (LIST_EMPTY(&ih->states))
+                               continue;
+
+                       PF_HASHROW_LOCK(ih);
+                       LIST_FOREACH(s, &ih->states, entry) {
+                               if (s->timeout == PFTM_UNLINKED)
+                                       continue;
+
+                               if ((nr+1) * sizeof(*p) > ps->ps_len) {
+                                       PF_HASHROW_UNLOCK(ih);
+                                       goto DIOCGETSTATESV2_full;
+                               }
+                               pf_state_export(p, s);
+                               p++;
+                               nr++;
+                       }
+                       PF_HASHROW_UNLOCK(ih);
+               }
+DIOCGETSTATESV2_full:
+               error = copyout(pstore, ps->ps_states,
+                   sizeof(struct pf_state_export) * nr);
+               if (error) {
+                       free(pstore, M_TEMP);
+                       break;
+               }
+               ps->ps_len = sizeof(struct pf_state_export) * nr;
+               free(pstore, M_TEMP);
+
+               break;
+       }
+
        case DIOCGETSTATESNV: {
                error = pf_getstates((struct pfioc_nv *)addr);
                break;
@@ -4594,7 +4650,70 @@ pfsync_state_export(struct pfsync_state *sp, struct 
pf_kstate *st)
        pf_state_counter_hton(st->packets[1], sp->packets[1]);
        pf_state_counter_hton(st->bytes[0], sp->bytes[0]);
        pf_state_counter_hton(st->bytes[1], sp->bytes[1]);
+}
+
+void
+pf_state_export(struct pf_state_export *sp, struct pf_kstate *st)
+{
+       bzero(sp, sizeof(*sp));
+
+       sp->version = PF_STATE_VERSION;
+
+       /* copy from state key */
+       sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
+       sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
+       sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
+       sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
+       sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
+       sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
+       sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
+       sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
+       sp->proto = st->key[PF_SK_WIRE]->proto;
+       sp->af = st->key[PF_SK_WIRE]->af;
+
+       /* copy from state */
+       strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
+       strlcpy(sp->orig_ifname, st->orig_kif->pfik_name,
+           sizeof(sp->orig_ifname));
+       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_uptime)
+               sp->expire = htonl(0);
+       else
+               sp->expire = htonl(sp->expire - time_uptime);
+
+       sp->direction = st->direction;
+       sp->log = st->log;
+       sp->timeout = st->timeout;
+       sp->state_flags = st->state_flags;
+       if (st->src_node)
+               sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
+       if (st->nat_src_node)
+               sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
+
+       sp->id = st->id;
+       sp->creatorid = st->creatorid;
+       pf_state_peer_hton(&st->src, &sp->src);
+       pf_state_peer_hton(&st->dst, &sp->dst);
+
+       if (st->rule.ptr == NULL)
+               sp->rule = htonl(-1);
+       else
+               sp->rule = htonl(st->rule.ptr->nr);
+       if (st->anchor.ptr == NULL)
+               sp->anchor = htonl(-1);
+       else
+               sp->anchor = htonl(st->anchor.ptr->nr);
+       if (st->nat_rule.ptr == NULL)
+               sp->nat_rule = htonl(-1);
+       else
+               sp->nat_rule = htonl(st->nat_rule.ptr->nr);
 
+       sp->packets[0] = st->packets[0];
+       sp->packets[1] = st->packets[1];
+       sp->bytes[0] = st->bytes[0];
+       sp->bytes[1] = st->bytes[1];
 }
 
 static void
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to