diff --git a/contrib/tcpdump/print-pfsync.c b/contrib/tcpdump/print-pfsync.c --- a/contrib/tcpdump/print-pfsync.c +++ b/contrib/tcpdump/print-pfsync.c @@ -55,7 +55,7 @@ static void print_src_dst(netdissect_options *, const struct pfsync_state_peer *, const struct pfsync_state_peer *, uint8_t); -static void print_state(netdissect_options *, struct pfsync_state *); +static void print_state(netdissect_options *, union pfsync_state_union *, int); u_int pfsync_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, @@ -100,7 +100,8 @@ }; static void pfsync_print_clr(netdissect_options *, const void *); -static void pfsync_print_state(netdissect_options *, const void *); +static void pfsync_print_state_1301(netdissect_options *, const void *); +static void pfsync_print_state_1400(netdissect_options *, const void *); static void pfsync_print_ins_ack(netdissect_options *, const void *); static void pfsync_print_upd_c(netdissect_options *, const void *); static void pfsync_print_upd_req(netdissect_options *, const void *); @@ -110,14 +111,16 @@ struct pfsync_actions actions[] = { { "clear all", sizeof(struct pfsync_clr), pfsync_print_clr }, - { "insert", sizeof(struct pfsync_state), pfsync_print_state }, + { "insert 13.1", sizeof(struct pfsync_state_1301), + pfsync_print_state_1301 }, { "insert ack", sizeof(struct pfsync_ins_ack), pfsync_print_ins_ack }, - { "update", sizeof(struct pfsync_ins_ack), pfsync_print_state }, + { "update 13.1", sizeof(struct pfsync_state_1301), + pfsync_print_state_1301 }, { "update compressed", sizeof(struct pfsync_upd_c), pfsync_print_upd_c }, { "request uncompressed", sizeof(struct pfsync_upd_req), pfsync_print_upd_req }, - { "delete", sizeof(struct pfsync_state), pfsync_print_state }, + { "delete", sizeof(struct pfsync_state_1301), pfsync_print_state_1301 }, { "delete compressed", sizeof(struct pfsync_del_c), pfsync_print_del_c }, { "frag insert", 0, NULL }, @@ -126,6 +129,8 @@ pfsync_print_bus }, { "tdb", 0, pfsync_print_tdb }, { "eof", 0, NULL }, + { "insert", sizeof(struct pfsync_state_1400), pfsync_print_state_1400 }, + { "update", sizeof(struct pfsync_state_1400), pfsync_print_state_1400 }, }; static void @@ -212,12 +217,21 @@ } static void -pfsync_print_state(netdissect_options *ndo, const void *bp) +pfsync_print_state_1301(netdissect_options *ndo, const void *bp) { - struct pfsync_state *st = (struct pfsync_state *)bp; + struct pfsync_state_1301 *st = (struct pfsync_state_1301 *)bp; safeputchar(ndo, '\n'); - print_state(ndo, st); + print_state(ndo, (union pfsync_state_union *)st, PFSYNC_MSG_VERSION_1301); +} + +static void +pfsync_print_state_1400(netdissect_options *ndo, const void *bp) +{ + struct pfsync_state_1301 *st = (struct pfsync_state_1301 *)bp; + + safeputchar(ndo, '\n'); + print_state(ndo, (union pfsync_state_union *)st, PFSYNC_MSG_VERSION_1400); } static void @@ -374,56 +388,56 @@ } static void -print_state(netdissect_options *ndo, struct pfsync_state *s) +print_state(netdissect_options *ndo, union pfsync_state_union *s, int version) { struct pfsync_state_peer *src, *dst; struct pfsync_state_key *sk, *nk; int min, sec; - if (s->direction == PF_OUT) { - src = &s->src; - dst = &s->dst; - sk = &s->key[PF_SK_STACK]; - nk = &s->key[PF_SK_WIRE]; - if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) + if (s->pfs_1301.direction == PF_OUT) { + src = &s->pfs_1301.src; + dst = &s->pfs_1301.dst; + sk = &s->pfs_1301.key[PF_SK_STACK]; + nk = &s->pfs_1301.key[PF_SK_WIRE]; + if (s->pfs_1301.proto == IPPROTO_ICMP || s->pfs_1301.proto == IPPROTO_ICMPV6) sk->port[0] = nk->port[0]; } else { - src = &s->dst; - dst = &s->src; - sk = &s->key[PF_SK_WIRE]; - nk = &s->key[PF_SK_STACK]; - if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) + src = &s->pfs_1301.dst; + dst = &s->pfs_1301.src; + sk = &s->pfs_1301.key[PF_SK_WIRE]; + nk = &s->pfs_1301.key[PF_SK_STACK]; + if (s->pfs_1301.proto == IPPROTO_ICMP || s->pfs_1301.proto == IPPROTO_ICMPV6) sk->port[1] = nk->port[1]; } - ND_PRINT((ndo, "\t%s ", s->ifname)); - ND_PRINT((ndo, "proto %u ", s->proto)); + ND_PRINT((ndo, "\t%s ", s->pfs_1301.ifname)); + ND_PRINT((ndo, "proto %u ", s->pfs_1301.proto)); - print_host(ndo, &nk->addr[1], nk->port[1], s->af, NULL); - if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->af) || + print_host(ndo, &nk->addr[1], nk->port[1], s->pfs_1301.af, NULL); + if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->pfs_1301.af) || nk->port[1] != sk->port[1]) { ND_PRINT((ndo, " (")); - print_host(ndo, &sk->addr[1], sk->port[1], s->af, NULL); + print_host(ndo, &sk->addr[1], sk->port[1], s->pfs_1301.af, NULL); ND_PRINT((ndo, ")")); } - if (s->direction == PF_OUT) + if (s->pfs_1301.direction == PF_OUT) ND_PRINT((ndo, " -> ")); else ND_PRINT((ndo, " <- ")); - print_host(ndo, &nk->addr[0], nk->port[0], s->af, NULL); - if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->af) || + print_host(ndo, &nk->addr[0], nk->port[0], s->pfs_1301.af, NULL); + if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->pfs_1301.af) || nk->port[0] != sk->port[0]) { ND_PRINT((ndo, " (")); - print_host(ndo, &sk->addr[0], sk->port[0], s->af, NULL); + print_host(ndo, &sk->addr[0], sk->port[0], s->pfs_1301.af, NULL); ND_PRINT((ndo, ")")); } - print_src_dst(ndo, src, dst, s->proto); + print_src_dst(ndo, src, dst, s->pfs_1301.proto); if (ndo->ndo_vflag > 1) { uint64_t packets[2]; uint64_t bytes[2]; - uint32_t creation = ntohl(s->creation); - uint32_t expire = ntohl(s->expire); + uint32_t creation = ntohl(s->pfs_1301.creation); + uint32_t expire = ntohl(s->pfs_1301.expire); sec = creation % 60; creation /= 60; @@ -436,23 +450,23 @@ expire /= 60; ND_PRINT((ndo, ", expires in %.2u:%.2u:%.2u", expire, min, sec)); - bcopy(s->packets[0], &packets[0], sizeof(uint64_t)); - bcopy(s->packets[1], &packets[1], sizeof(uint64_t)); - bcopy(s->bytes[0], &bytes[0], sizeof(uint64_t)); - bcopy(s->bytes[1], &bytes[1], sizeof(uint64_t)); + bcopy(s->pfs_1301.packets[0], &packets[0], sizeof(uint64_t)); + bcopy(s->pfs_1301.packets[1], &packets[1], sizeof(uint64_t)); + bcopy(s->pfs_1301.bytes[0], &bytes[0], sizeof(uint64_t)); + bcopy(s->pfs_1301.bytes[1], &bytes[1], sizeof(uint64_t)); ND_PRINT((ndo, ", %ju:%ju pkts, %ju:%ju bytes", be64toh(packets[0]), be64toh(packets[1]), be64toh(bytes[0]), be64toh(bytes[1]))); - if (s->anchor != ntohl(-1)) - ND_PRINT((ndo, ", anchor %u", ntohl(s->anchor))); - if (s->rule != ntohl(-1)) - ND_PRINT((ndo, ", rule %u", ntohl(s->rule))); + if (s->pfs_1301.anchor != ntohl(-1)) + ND_PRINT((ndo, ", anchor %u", ntohl(s->pfs_1301.anchor))); + if (s->pfs_1301.rule != ntohl(-1)) + ND_PRINT((ndo, ", rule %u", ntohl(s->pfs_1301.rule))); } if (ndo->ndo_vflag > 1) { uint64_t id; - bcopy(&s->id, &id, sizeof(uint64_t)); + bcopy(&s->pfs_1301.id, &id, sizeof(uint64_t)); ND_PRINT((ndo, "\n\tid: %016jx creatorid: %08x", - (uintmax_t )be64toh(id), ntohl(s->creatorid))); + (uintmax_t )be64toh(id), ntohl(s->pfs_1301.creatorid))); } } diff --git a/sbin/ifconfig/ifpfsync.c b/sbin/ifconfig/ifpfsync.c --- a/sbin/ifconfig/ifpfsync.c +++ b/sbin/ifconfig/ifpfsync.c @@ -309,6 +309,27 @@ nvlist_destroy(nvl); } +static void +setpfsync_version(if_ctx *ctx, const char *val, int dummy __unused) +{ + int version; + nvlist_t *nvl = nvlist_create(0); + + /* Don't verify, kernel knows which versions are supported.*/ + version = atoi(val); + + if (pfsync_do_ioctl(ctx->io_s, SIOCGETPFSYNCNV, &nvl) == -1) + err(1, "SIOCGETPFSYNCNV"); + + nvlist_free_number(nvl, "version"); + nvlist_add_number(nvl, "version", version); + + if (pfsync_do_ioctl(ctx->io_s, SIOCSETPFSYNCNV, &nvl) == -1) + err(1, "SIOCSETPFSYNCNV"); + + nvlist_destroy(nvl); +} + static void pfsync_status(if_ctx *ctx) { @@ -318,6 +339,7 @@ struct sockaddr_storage syncpeer; int maxupdates = 0; int flags = 0; + int version; int error; nvl = nvlist_create(0); @@ -333,6 +355,8 @@ IFNAMSIZ); if (nvlist_exists_number(nvl, "maxupdates")) maxupdates = nvlist_get_number(nvl, "maxupdates"); + if (nvlist_exists_number(nvl, "version")) + version = nvlist_get_number(nvl, "version"); if (nvlist_exists_number(nvl, "flags")) flags = nvlist_get_number(nvl, "flags"); if (nvlist_exists_nvlist(nvl, "syncpeer")) { @@ -363,7 +387,8 @@ } printf("maxupd: %d ", maxupdates); - printf("defer: %s\n", (flags & PFSYNCF_DEFER) ? "on" : "off"); + printf("defer: %s ", (flags & PFSYNCF_DEFER) ? "on" : "off"); + printf("version: %d\n", version); printf("\tsyncok: %d\n", (flags & PFSYNCF_OK) ? 1 : 0); } @@ -377,6 +402,7 @@ DEF_CMD_ARG("maxupd", setpfsync_maxupd), DEF_CMD("defer", 1, setpfsync_defer), DEF_CMD("-defer", 0, setpfsync_defer), + DEF_CMD_ARG("version", setpfsync_version), }; static struct afswtch af_pfsync = { .af_name = "af_pfsync", diff --git a/sys/net/if_pfsync.h b/sys/net/if_pfsync.h --- a/sys/net/if_pfsync.h +++ b/sys/net/if_pfsync.h @@ -59,10 +59,18 @@ #define PFSYNC_VERSION 5 #define PFSYNC_DFLTTL 255 +enum pfsync_msg_versions { + PFSYNC_MSG_VERSION_UNSPECIFIED = 0, + PFSYNC_MSG_VERSION_1301 = 1301, + PFSYNC_MSG_VERSION_1400 = 1400, +}; + +#define PFSYNC_MSG_VERSION_DEFAULT PFSYNC_MSG_VERSION_1400 + #define PFSYNC_ACT_CLR 0 /* clear all states */ -#define PFSYNC_ACT_INS 1 /* insert state */ +#define PFSYNC_ACT_INS_1301 1 /* insert state */ #define PFSYNC_ACT_INS_ACK 2 /* ack of inserted state */ -#define PFSYNC_ACT_UPD 3 /* update state */ +#define PFSYNC_ACT_UPD_1301 3 /* update state */ #define PFSYNC_ACT_UPD_C 4 /* "compressed" update state */ #define PFSYNC_ACT_UPD_REQ 5 /* request "uncompressed" state */ #define PFSYNC_ACT_DEL 6 /* delete state */ @@ -72,7 +80,9 @@ #define PFSYNC_ACT_BUS 10 /* bulk update status */ #define PFSYNC_ACT_TDB 11 /* TDB replay counter update */ #define PFSYNC_ACT_EOF 12 /* end of frame */ -#define PFSYNC_ACT_MAX 13 +#define PFSYNC_ACT_INS_1400 13 /* insert state */ +#define PFSYNC_ACT_UPD_1400 14 /* update state */ +#define PFSYNC_ACT_MAX 15 /* * A pfsync frame is built from a header followed by several sections which @@ -251,6 +261,7 @@ char syncdev[IFNAMSIZ]; struct sockaddr_storage syncpeer; int maxupdates; + int version; int flags; }; @@ -269,13 +280,13 @@ /* * this shows where a pf state is with respect to the syncing. + * pf_kstate->sync_state */ #define PFSYNC_S_INS 0x00 #define PFSYNC_S_IACK 0x01 #define PFSYNC_S_UPD 0x02 #define PFSYNC_S_UPD_C 0x03 #define PFSYNC_S_DEL_C 0x04 -#define PFSYNC_S_COUNT 0x05 #define PFSYNC_S_DEFER 0xfe #define PFSYNC_S_NONE 0xff diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -641,6 +641,7 @@ uint16_t dnpipe; uint16_t dnrpipe; /* Reverse direction pipe */ uint32_t flags; + uint8_t set_prio[2]; }; union pf_keth_rule_ptr { @@ -1057,12 +1058,14 @@ u_int8_t min_ttl; u_int8_t set_tos; u_int16_t max_mss; + u_int8_t rt; + u_int8_t set_prio[2]; }; /* - * Size <= fits 12 objects per page on LP64. Try to not grow the struct beyond that. + * Size <= fits 11 objects per page on LP64. Try to not grow the struct beyond that. */ -_Static_assert(sizeof(struct pf_kstate) <= 336, "pf_kstate size crosses 336 bytes"); +_Static_assert(sizeof(struct pf_kstate) <= 368, "pf_kstate size crosses 368 bytes"); #endif /* @@ -1094,7 +1097,34 @@ u_int16_t port[2]; }; -struct pfsync_state { +struct pfsync_state_1301 { + u_int64_t id; + char ifname[IFNAMSIZ]; + struct pfsync_state_key key[2]; + struct pfsync_state_peer src; + struct pfsync_state_peer dst; + struct pf_addr rt_addr; + u_int32_t rule; + u_int32_t anchor; + u_int32_t nat_rule; + u_int32_t creation; + u_int32_t expire; + u_int32_t packets[2][2]; + u_int32_t bytes[2][2]; + u_int32_t creatorid; + sa_family_t af; + u_int8_t proto; + u_int8_t direction; + u_int8_t __spare[2]; + u_int8_t log; + u_int8_t state_flags; + u_int8_t timeout; + u_int8_t sync_flags; + u_int8_t updates; +} __packed; + +struct pfsync_state_1400 { + /* The beginning of the struct is compatible with previous versions */ u_int64_t id; char ifname[IFNAMSIZ]; struct pfsync_state_key key[2]; @@ -1114,15 +1144,33 @@ u_int8_t direction; u_int16_t state_flags; u_int8_t log; - u_int8_t state_flags_compat; + u_int8_t __spare; u_int8_t timeout; u_int8_t sync_flags; u_int8_t updates; + /* The rest is not */ + u_int16_t qid; + u_int16_t pqid; + u_int16_t dnpipe; + u_int16_t dnrpipe; + int32_t rtableid; + u_int8_t min_ttl; + u_int8_t set_tos; + u_int16_t max_mss; + u_int8_t set_prio[2]; + u_int8_t rt; + char rt_ifname[IFNAMSIZ]; + +} __packed; + +union pfsync_state_union { + struct pfsync_state_1301 pfs_1301; + struct pfsync_state_1400 pfs_1400; } __packed; #ifdef _KERNEL /* pfsync */ -typedef int pfsync_state_import_t(struct pfsync_state *, int); +typedef int pfsync_state_import_t(union pfsync_state_union *, int, int); typedef void pfsync_insert_state_t(struct pf_kstate *); typedef void pfsync_update_state_t(struct pf_kstate *); typedef void pfsync_delete_state_t(struct pf_kstate *); @@ -1144,8 +1192,8 @@ #define V_pfsync_defer_ptr VNET(pfsync_defer_ptr) extern pfsync_detach_ifnet_t *pfsync_detach_ifnet_ptr; -void pfsync_state_export(struct pfsync_state *, - struct pf_kstate *); +void pfsync_state_export(union pfsync_state_union *, + struct pf_kstate *, int); void pf_state_export(struct pf_state_export *, struct pf_kstate *); @@ -1665,7 +1713,7 @@ }; struct pfioc_state { - struct pfsync_state state; + struct pfsync_state_1301 state; }; struct pfioc_src_node_kill { @@ -1704,8 +1752,8 @@ struct pfioc_states { int ps_len; union { - void *ps_buf; - struct pfsync_state *ps_states; + void *ps_buf; + struct pfsync_state_1301 *ps_states; }; }; diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c --- a/sys/netpfil/pf/if_pfsync.c +++ b/sys/netpfil/pf/if_pfsync.c @@ -122,23 +122,23 @@ static int pfsync_upd_tcp(struct pf_kstate *, struct pfsync_state_peer *, struct pfsync_state_peer *); -static int pfsync_in_clr(struct mbuf *, int, int, int); -static int pfsync_in_ins(struct mbuf *, int, int, int); -static int pfsync_in_iack(struct mbuf *, int, int, int); -static int pfsync_in_upd(struct mbuf *, int, int, int); -static int pfsync_in_upd_c(struct mbuf *, int, int, int); -static int pfsync_in_ureq(struct mbuf *, int, int, int); -static int pfsync_in_del_c(struct mbuf *, int, int, int); -static int pfsync_in_bus(struct mbuf *, int, int, int); -static int pfsync_in_tdb(struct mbuf *, int, int, int); -static int pfsync_in_eof(struct mbuf *, int, int, int); -static int pfsync_in_error(struct mbuf *, int, int, int); - -static int (*pfsync_acts[])(struct mbuf *, int, int, int) = { +static int pfsync_in_clr(struct mbuf *, int, int, int, int); +static int pfsync_in_ins(struct mbuf *, int, int, int, int); +static int pfsync_in_iack(struct mbuf *, int, int, int, int); +static int pfsync_in_upd(struct mbuf *, int, int, int, int); +static int pfsync_in_upd_c(struct mbuf *, int, int, int, int); +static int pfsync_in_ureq(struct mbuf *, int, int, int, int); +static int pfsync_in_del_c(struct mbuf *, int, int, int, int); +static int pfsync_in_bus(struct mbuf *, int, int, int, int); +static int pfsync_in_tdb(struct mbuf *, int, int, int, int); +static int pfsync_in_eof(struct mbuf *, int, int, int, int); +static int pfsync_in_error(struct mbuf *, int, int, int, int); + +static int (*pfsync_acts[])(struct mbuf *, int, int, int, int) = { pfsync_in_clr, /* PFSYNC_ACT_CLR */ - pfsync_in_ins, /* PFSYNC_ACT_INS */ + pfsync_in_ins, /* PFSYNC_ACT_INS_1301 */ pfsync_in_iack, /* PFSYNC_ACT_INS_ACK */ - pfsync_in_upd, /* PFSYNC_ACT_UPD */ + pfsync_in_upd, /* PFSYNC_ACT_UPD_1301 */ pfsync_in_upd_c, /* PFSYNC_ACT_UPD_C */ pfsync_in_ureq, /* PFSYNC_ACT_UPD_REQ */ pfsync_in_error, /* PFSYNC_ACT_DEL */ @@ -147,7 +147,9 @@ pfsync_in_error, /* PFSYNC_ACT_DEL_F */ pfsync_in_bus, /* PFSYNC_ACT_BUS */ pfsync_in_tdb, /* PFSYNC_ACT_TDB */ - pfsync_in_eof /* PFSYNC_ACT_EOF */ + pfsync_in_eof, /* PFSYNC_ACT_EOF */ + pfsync_in_ins, /* PFSYNC_ACT_INS_1400 */ + pfsync_in_upd, /* PFSYNC_ACT_UPD_1400 */ }; struct pfsync_q { @@ -156,21 +158,51 @@ u_int8_t action; }; -/* we have one of these for every PFSYNC_S_ */ -static void pfsync_out_state(struct pf_kstate *, void *); +/* We have the following sync queues */ +enum pfsync_q_id { + PFSYNC_Q_INS_1301, + PFSYNC_Q_INS_1400, + PFSYNC_Q_IACK, + PFSYNC_Q_UPD_1301, + PFSYNC_Q_UPD_1400, + PFSYNC_Q_UPD_C, + PFSYNC_Q_DEL_C, + PFSYNC_Q_COUNT, +}; + +/* Functions for building messages for given queue */ +static void pfsync_out_state_1301(struct pf_kstate *, void *); +static void pfsync_out_state_1400(struct pf_kstate *, void *); static void pfsync_out_iack(struct pf_kstate *, void *); static void pfsync_out_upd_c(struct pf_kstate *, void *); static void pfsync_out_del_c(struct pf_kstate *, void *); +/* Attach those functions to queue */ static struct pfsync_q pfsync_qs[] = { - { pfsync_out_state, sizeof(struct pfsync_state), PFSYNC_ACT_INS }, - { pfsync_out_iack, sizeof(struct pfsync_ins_ack), PFSYNC_ACT_INS_ACK }, - { pfsync_out_state, sizeof(struct pfsync_state), PFSYNC_ACT_UPD }, - { pfsync_out_upd_c, sizeof(struct pfsync_upd_c), PFSYNC_ACT_UPD_C }, - { pfsync_out_del_c, sizeof(struct pfsync_del_c), PFSYNC_ACT_DEL_C } + { pfsync_out_state_1301, sizeof(struct pfsync_state_1301), PFSYNC_ACT_INS_1301 }, + { pfsync_out_state_1400, sizeof(struct pfsync_state_1400), PFSYNC_ACT_INS_1400 }, + { pfsync_out_iack, sizeof(struct pfsync_ins_ack), PFSYNC_ACT_INS_ACK }, + { pfsync_out_state_1301, sizeof(struct pfsync_state_1301), PFSYNC_ACT_UPD_1301 }, + { pfsync_out_state_1400, sizeof(struct pfsync_state_1400), PFSYNC_ACT_UPD_1400 }, + { pfsync_out_upd_c, sizeof(struct pfsync_upd_c), PFSYNC_ACT_UPD_C }, + { pfsync_out_del_c, sizeof(struct pfsync_del_c), PFSYNC_ACT_DEL_C } +}; + +/* Map queue to pf_kstate->sync_state */ +static u_int8_t pfsync_qid_sstate[] = { + PFSYNC_S_INS, /* PFSYNC_Q_INS_1301 */ + PFSYNC_S_INS, /* PFSYNC_Q_INS_1400 */ + PFSYNC_S_IACK, /* PFSYNC_Q_IACK */ + PFSYNC_S_UPD, /* PFSYNC_Q_UPD_1301 */ + PFSYNC_S_UPD, /* PFSYNC_Q_UPD_1400 */ + PFSYNC_S_UPD_C, /* PFSYNC_Q_UPD_C */ + PFSYNC_S_DEL_C, /* PFSYNC_Q_DEL_C */ }; -static void pfsync_q_ins(struct pf_kstate *, int, bool); +/* Map pf_kstate->sync_state to queue */ +static enum pfsync_q_id pfsync_sstate_to_qid(u_int8_t); + +static void pfsync_q_ins(struct pf_kstate *, int sync_state, bool); static void pfsync_q_del(struct pf_kstate *, bool, struct pfsync_bucket *); static void pfsync_update_state(struct pf_kstate *); @@ -200,7 +232,7 @@ #define PFSYNCF_BUCKET_PUSH 0x00000001 size_t b_len; - TAILQ_HEAD(, pf_kstate) b_qs[PFSYNC_S_COUNT]; + TAILQ_HEAD(, pf_kstate) b_qs[PFSYNC_Q_COUNT]; TAILQ_HEAD(, pfsync_upd_req_item) b_upd_req_list; TAILQ_HEAD(, pfsync_deferral) b_deferrals; u_int b_deferred; @@ -220,6 +252,7 @@ uint8_t sc_maxupdates; union inet_template sc_template; struct mtx sc_mtx; + uint32_t sc_version; /* Queued data */ struct pfsync_bucket *sc_buckets; @@ -336,7 +369,8 @@ struct pfsync_softc *sc; struct ifnet *ifp; struct pfsync_bucket *b; - int c, q; + int c; + enum pfsync_q_id q; if (unit != 0) return (EINVAL); @@ -347,6 +381,7 @@ sc = malloc(sizeof(struct pfsync_softc), M_PFSYNC, M_WAITOK | M_ZERO); sc->sc_flags |= PFSYNCF_OK; sc->sc_maxupdates = 128; + sc->sc_version = PFSYNC_MSG_VERSION_DEFAULT; ifp = sc->sc_ifp = if_alloc(IFT_PFSYNC); if (ifp == NULL) { @@ -379,7 +414,7 @@ b->b_sc = sc; b->b_len = PFSYNC_MINPKT; - for (q = 0; q < PFSYNC_S_COUNT; q++) + for (q = 0; q < PFSYNC_Q_COUNT; q++) TAILQ_INIT(&b->b_qs[q]); TAILQ_INIT(&b->b_upd_req_list); @@ -465,7 +500,7 @@ } static int -pfsync_state_import(struct pfsync_state *sp, int flags) +pfsync_state_import(union pfsync_state_union *sp, int flags, int msg_version) { struct pfsync_softc *sc = V_pfsyncif; #ifndef __NO_STRICT_ALIGNMENT @@ -480,17 +515,17 @@ PF_RULES_RASSERT(); - if (sp->creatorid == 0) { + if (sp->pfs_1301.creatorid == 0) { if (V_pf_status.debug >= PF_DEBUG_MISC) printf("%s: invalid creator id: %08x\n", __func__, - ntohl(sp->creatorid)); + ntohl(sp->pfs_1301.creatorid)); return (EINVAL); } - if ((kif = pfi_kkif_find(sp->ifname)) == NULL) { + if ((kif = pfi_kkif_find(sp->pfs_1301.ifname)) == NULL) { if (V_pf_status.debug >= PF_DEBUG_MISC) printf("%s: unknown interface: %s\n", __func__, - sp->ifname); + sp->pfs_1301.ifname); if (flags & PFSYNC_SI_IOCTL) return (EINVAL); return (0); /* skip this state */ @@ -500,11 +535,11 @@ * If the ruleset checksums match or the state is coming from the ioctl, * it's safe to associate the state with the rule of that number. */ - if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) && - (flags & (PFSYNC_SI_IOCTL | PFSYNC_SI_CKSUM)) && ntohl(sp->rule) < + if (sp->pfs_1301.rule != htonl(-1) && sp->pfs_1301.anchor == htonl(-1) && + (flags & (PFSYNC_SI_IOCTL | PFSYNC_SI_CKSUM)) && ntohl(sp->pfs_1301.rule) < pf_main_ruleset.rules[PF_RULESET_FILTER].active.rcount) r = pf_main_ruleset.rules[ - PF_RULESET_FILTER].active.ptr_array[ntohl(sp->rule)]; + PF_RULESET_FILTER].active.ptr_array[ntohl(sp->pfs_1301.rule)]; else r = &V_pf_default_rule; @@ -523,16 +558,16 @@ goto cleanup; #ifndef __NO_STRICT_ALIGNMENT - bcopy(&sp->key, key, sizeof(struct pfsync_state_key) * 2); + bcopy(&sp->pfs_1301.key, key, sizeof(struct pfsync_state_key) * 2); kw = &key[PF_SK_WIRE]; ks = &key[PF_SK_STACK]; #else - kw = &sp->key[PF_SK_WIRE]; - ks = &sp->key[PF_SK_STACK]; + kw = &sp->pfs_1301.key[PF_SK_WIRE]; + ks = &sp->pfs_1301.key[PF_SK_STACK]; #endif - if (PF_ANEQ(&kw->addr[0], &ks->addr[0], sp->af) || - PF_ANEQ(&kw->addr[1], &ks->addr[1], sp->af) || + if (PF_ANEQ(&kw->addr[0], &ks->addr[0], sp->pfs_1301.af) || + PF_ANEQ(&kw->addr[1], &ks->addr[1], sp->pfs_1301.af) || kw->port[0] != ks->port[0] || kw->port[1] != ks->port[1]) { sks = uma_zalloc(V_pf_state_key_z, M_NOWAIT); @@ -542,8 +577,8 @@ sks = skw; /* allocate memory for scrub info */ - if (pfsync_alloc_scrub_memory(&sp->src, &st->src) || - pfsync_alloc_scrub_memory(&sp->dst, &st->dst)) + if (pfsync_alloc_scrub_memory(&sp->pfs_1301.src, &st->src) || + pfsync_alloc_scrub_memory(&sp->pfs_1301.dst, &st->dst)) goto cleanup; /* Copy to state key(s). */ @@ -551,69 +586,110 @@ skw->addr[1] = kw->addr[1]; skw->port[0] = kw->port[0]; skw->port[1] = kw->port[1]; - skw->proto = sp->proto; - skw->af = sp->af; + skw->proto = sp->pfs_1301.proto; + skw->af = sp->pfs_1301.af; if (sks != skw) { sks->addr[0] = ks->addr[0]; sks->addr[1] = ks->addr[1]; sks->port[0] = ks->port[0]; sks->port[1] = ks->port[1]; - sks->proto = sp->proto; - sks->af = sp->af; + sks->proto = sp->pfs_1301.proto; + sks->af = sp->pfs_1301.af; } /* copy to state */ - bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr)); - st->creation = time_uptime - ntohl(sp->creation); + bcopy(&sp->pfs_1301.rt_addr, &st->rt_addr, sizeof(st->rt_addr)); + st->creation = time_uptime - ntohl(sp->pfs_1301.creation); st->expire = time_uptime; - if (sp->expire) { + if (sp->pfs_1301.expire) { uint32_t timeout; - timeout = r->timeout[sp->timeout]; + timeout = r->timeout[sp->pfs_1301.timeout]; if (!timeout) - timeout = V_pf_default_rule.timeout[sp->timeout]; + timeout = V_pf_default_rule.timeout[sp->pfs_1301.timeout]; /* sp->expire may have been adaptively scaled by export. */ - st->expire -= timeout - ntohl(sp->expire); + st->expire -= timeout - ntohl(sp->pfs_1301.expire); } - st->direction = sp->direction; - st->log = sp->log; - st->timeout = sp->timeout; - /* 8 from old peers, 16 bits from new peers */ - st->state_flags = sp->state_flags_compat | ntohs(sp->state_flags); + st->direction = sp->pfs_1301.direction; + st->log = sp->pfs_1301.log; + st->timeout = sp->pfs_1301.timeout; - if (r == &V_pf_default_rule) { - /* ToS and Prio are not sent over struct pfsync_state */ - st->state_flags &= ~PFSTATE_SETMASK; - } else { - /* Most actions are applied form state, not from rule. Until - * pfsync can forward all those actions and their parameters we - * must relay on restoring them from the found rule. - * It's a copy of pf_rule_to_actions() */ - st->qid = r->qid; - st->pqid = r->pqid; - st->rtableid = r->rtableid; - if (r->scrub_flags & PFSTATE_SETTOS) - st->set_tos = r->set_tos; - st->min_ttl = r->min_ttl; - st->max_mss = r->max_mss; - st->state_flags |= (r->scrub_flags & (PFSTATE_NODF|PFSTATE_RANDOMID| - PFSTATE_SETTOS|PFSTATE_SCRUB_TCP|PFSTATE_SETPRIO)); - st->dnpipe = r->dnpipe; - st->dnrpipe = r->dnrpipe; - /* FIXME: dnflags are not part of state, can't update them */ - } - - st->id = sp->id; - st->creatorid = sp->creatorid; - pf_state_peer_ntoh(&sp->src, &st->src); - pf_state_peer_ntoh(&sp->dst, &st->dst); + switch (msg_version) { + case PFSYNC_MSG_VERSION_1301: + st->state_flags = sp->pfs_1301.state_flags; + /* + * In FreeBSD 13 pfsync lacks many attributes. Copy them + * from the rule if possible. If rule can't be matched + * clear any set options as we can't recover their + * parameters. + */ + if (r == &V_pf_default_rule) { + st->state_flags &= ~PFSTATE_SETMASK; + } else { + /* + * Similar to pf_rule_to_actions(). This code + * won't set the actions properly if they come + * from multiple "match" rules as only rule + * creating the state is send over pfsync. + */ + st->qid = r->qid; + st->pqid = r->pqid; + st->rtableid = r->rtableid; + if (r->scrub_flags & PFSTATE_SETTOS) + st->set_tos = r->set_tos; + st->min_ttl = r->min_ttl; + st->max_mss = r->max_mss; + st->state_flags |= (r->scrub_flags & + (PFSTATE_NODF|PFSTATE_RANDOMID| + PFSTATE_SETTOS|PFSTATE_SCRUB_TCP| + PFSTATE_SETPRIO)); + if (r->dnpipe || r->dnrpipe) { + if (r->free_flags & PFRULE_DN_IS_PIPE) + st->state_flags |= PFSTATE_DN_IS_PIPE; + else + st->state_flags &= ~PFSTATE_DN_IS_PIPE; + } + st->dnpipe = r->dnpipe; + st->dnrpipe = r->dnrpipe; + } + break; + case PFSYNC_MSG_VERSION_1400: + st->state_flags = ntohs(sp->pfs_1400.state_flags); + st->qid = ntohs(sp->pfs_1400.qid); + st->pqid = ntohs(sp->pfs_1400.pqid); + st->dnpipe = ntohs(sp->pfs_1400.dnpipe); + st->dnrpipe = ntohs(sp->pfs_1400.dnrpipe); + st->rtableid = ntohl(sp->pfs_1400.rtableid); + st->min_ttl = sp->pfs_1400.min_ttl; + st->set_tos = sp->pfs_1400.set_tos; + st->max_mss = ntohs(sp->pfs_1400.max_mss); + st->set_prio[0] = sp->pfs_1400.set_prio[0]; + st->set_prio[1] = sp->pfs_1400.set_prio[1]; + st->rt = sp->pfs_1400.rt; + if (st->rt && (st->rt_kif = pfi_kkif_find(sp->pfs_1400.rt_ifname)) == NULL) { + if (V_pf_status.debug >= PF_DEBUG_MISC) + printf("%s: unknown route interface: %s\n", + __func__, sp->pfs_1400.rt_ifname); + if (flags & PFSYNC_SI_IOCTL) + return (EINVAL); + return (0); /* skip this state */ + } + break; + default: + panic("%s: Unsupported pfsync_msg_version %d", + __func__, msg_version); + } + + st->id = sp->pfs_1301.id; + st->creatorid = sp->pfs_1301.creatorid; + pf_state_peer_ntoh(&sp->pfs_1301.src, &st->src); + pf_state_peer_ntoh(&sp->pfs_1301.dst, &st->dst); st->rule.ptr = r; st->nat_rule.ptr = NULL; st->anchor.ptr = NULL; - st->rt_kif = NULL; st->pfsync_time = time_uptime; st->sync_state = PFSYNC_S_NONE; @@ -745,7 +821,7 @@ count = ntohs(subh.count); V_pfsyncstats.pfsyncs_iacts[subh.action] += count; - rv = (*pfsync_acts[subh.action])(m, offset, count, flags); + rv = (*pfsync_acts[subh.action])(m, offset, count, flags, subh.action); if (rv == -1) { PF_RULES_RUNLOCK(); return (IPPROTO_DONE); @@ -762,7 +838,7 @@ #endif static int -pfsync_in_clr(struct mbuf *m, int offset, int count, int flags) +pfsync_in_clr(struct mbuf *m, int offset, int count, int flags, int action) { struct pfsync_clr *clr; struct mbuf *mp; @@ -804,36 +880,50 @@ } static int -pfsync_in_ins(struct mbuf *m, int offset, int count, int flags) +pfsync_in_ins(struct mbuf *m, int offset, int count, int flags, int action) { struct mbuf *mp; - struct pfsync_state *sa, *sp; - int len = sizeof(*sp) * count; - int i, offp; + union pfsync_state_union *sa, *sp; + int i, offp, len, msg_version; + + switch (action) { + case PFSYNC_ACT_INS_1301: + len = sizeof(struct pfsync_state_1301) * count; + msg_version = PFSYNC_MSG_VERSION_1301; + break; + case PFSYNC_ACT_INS_1400: + len = sizeof(struct pfsync_state_1400) * count; + msg_version = PFSYNC_MSG_VERSION_1400; + break; + default: + V_pfsyncstats.pfsyncs_badact++; + return (-1); + } mp = m_pulldown(m, offset, len, &offp); if (mp == NULL) { V_pfsyncstats.pfsyncs_badlen++; return (-1); } - sa = (struct pfsync_state *)(mp->m_data + offp); + sa = (union pfsync_state_union *)(mp->m_data + offp); for (i = 0; i < count; i++) { sp = &sa[i]; /* Check for invalid values. */ - if (sp->timeout >= PFTM_MAX || - sp->src.state > PF_TCPS_PROXY_DST || - sp->dst.state > PF_TCPS_PROXY_DST || - sp->direction > PF_OUT || - (sp->af != AF_INET && sp->af != AF_INET6)) { + if (sp->pfs_1301.timeout >= PFTM_MAX || + sp->pfs_1301.src.state > PF_TCPS_PROXY_DST || + sp->pfs_1301.dst.state > PF_TCPS_PROXY_DST || + sp->pfs_1301.direction > PF_OUT || + (sp->pfs_1301.af != AF_INET && + sp->pfs_1301.af != AF_INET6)) { if (V_pf_status.debug >= PF_DEBUG_MISC) printf("%s: invalid value\n", __func__); V_pfsyncstats.pfsyncs_badval++; continue; } - if (pfsync_state_import(sp, flags) == ENOMEM) + if (pfsync_state_import(sp, flags, msg_version) == ENOMEM) /* Drop out, but process the rest of the actions. */ break; } @@ -842,7 +932,7 @@ } static int -pfsync_in_iack(struct mbuf *m, int offset, int count, int flags) +pfsync_in_iack(struct mbuf *m, int offset, int count, int flags, int action) { struct pfsync_ins_ack *ia, *iaa; struct pf_kstate *st; @@ -913,31 +1003,42 @@ } static int -pfsync_in_upd(struct mbuf *m, int offset, int count, int flags) +pfsync_in_upd(struct mbuf *m, int offset, int count, int flags, int action) { struct pfsync_softc *sc = V_pfsyncif; - struct pfsync_state *sa, *sp; + union pfsync_state_union *sa, *sp; struct pf_kstate *st; - int sync; - struct mbuf *mp; - int len = count * sizeof(*sp); - int offp, i; + int sync, offp, i, len, msg_version; + + switch (action) { + case PFSYNC_ACT_UPD_1301: + len = sizeof(struct pfsync_state_1301) * count; + msg_version = PFSYNC_MSG_VERSION_1301; + break; + case PFSYNC_ACT_UPD_1400: + len = sizeof(struct pfsync_state_1400) * count; + msg_version = PFSYNC_MSG_VERSION_1400; + break; + default: + V_pfsyncstats.pfsyncs_badact++; + return (-1); + } mp = m_pulldown(m, offset, len, &offp); if (mp == NULL) { V_pfsyncstats.pfsyncs_badlen++; return (-1); } - sa = (struct pfsync_state *)(mp->m_data + offp); + sa = (union pfsync_state_union *)(mp->m_data + offp); for (i = 0; i < count; i++) { sp = &sa[i]; /* check for invalid values */ - if (sp->timeout >= PFTM_MAX || - sp->src.state > PF_TCPS_PROXY_DST || - sp->dst.state > PF_TCPS_PROXY_DST) { + if (sp->pfs_1301.timeout >= PFTM_MAX || + sp->pfs_1301.src.state > PF_TCPS_PROXY_DST || + sp->pfs_1301.dst.state > PF_TCPS_PROXY_DST) { if (V_pf_status.debug >= PF_DEBUG_MISC) { printf("pfsync_input: PFSYNC_ACT_UPD: " "invalid value\n"); @@ -946,10 +1047,10 @@ continue; } - st = pf_find_state_byid(sp->id, sp->creatorid); + st = pf_find_state_byid(sp->pfs_1301.id, sp->pfs_1301.creatorid); if (st == NULL) { /* insert the update */ - if (pfsync_state_import(sp, flags)) + if (pfsync_state_import(sp, flags, msg_version)) V_pfsyncstats.pfsyncs_badstate++; continue; } @@ -959,7 +1060,7 @@ } if (st->key[PF_SK_WIRE]->proto == IPPROTO_TCP) - sync = pfsync_upd_tcp(st, &sp->src, &sp->dst); + sync = pfsync_upd_tcp(st, &sp->pfs_1301.src, &sp->pfs_1301.dst); else { sync = 0; @@ -967,20 +1068,20 @@ * Non-TCP protocol state machine always go * forwards */ - if (st->src.state > sp->src.state) + if (st->src.state > sp->pfs_1301.src.state) sync++; else - pf_state_peer_ntoh(&sp->src, &st->src); - if (st->dst.state > sp->dst.state) + pf_state_peer_ntoh(&sp->pfs_1301.src, &st->src); + if (st->dst.state > sp->pfs_1301.dst.state) sync++; else - pf_state_peer_ntoh(&sp->dst, &st->dst); + pf_state_peer_ntoh(&sp->pfs_1301.dst, &st->dst); } if (sync < 2) { - pfsync_alloc_scrub_memory(&sp->dst, &st->dst); - pf_state_peer_ntoh(&sp->dst, &st->dst); + pfsync_alloc_scrub_memory(&sp->pfs_1301.dst, &st->dst); + pf_state_peer_ntoh(&sp->pfs_1301.dst, &st->dst); st->expire = time_uptime; - st->timeout = sp->timeout; + st->timeout = sp->pfs_1301.timeout; } st->pfsync_time = time_uptime; @@ -999,7 +1100,7 @@ } static int -pfsync_in_upd_c(struct mbuf *m, int offset, int count, int flags) +pfsync_in_upd_c(struct mbuf *m, int offset, int count, int flags, int action) { struct pfsync_softc *sc = V_pfsyncif; struct pfsync_upd_c *ua, *up; @@ -1086,7 +1187,7 @@ } static int -pfsync_in_ureq(struct mbuf *m, int offset, int count, int flags) +pfsync_in_ureq(struct mbuf *m, int offset, int count, int flags, int action) { struct pfsync_upd_req *ur, *ura; struct mbuf *mp; @@ -1127,7 +1228,7 @@ } static int -pfsync_in_del_c(struct mbuf *m, int offset, int count, int flags) +pfsync_in_del_c(struct mbuf *m, int offset, int count, int flags, int action) { struct mbuf *mp; struct pfsync_del_c *sa, *sp; @@ -1159,7 +1260,7 @@ } static int -pfsync_in_bus(struct mbuf *m, int offset, int count, int flags) +pfsync_in_bus(struct mbuf *m, int offset, int count, int flags, int action) { struct pfsync_softc *sc = V_pfsyncif; struct pfsync_bus *bus; @@ -1188,7 +1289,7 @@ callout_reset(&sc->sc_bulkfail_tmo, 4 * hz + V_pf_limits[PF_LIMIT_STATES].limit / ((sc->sc_ifp->if_mtu - PFSYNC_MINPKT) / - sizeof(struct pfsync_state)), + sizeof(union pfsync_state_union)), pfsync_bulk_fail, sc); if (V_pf_status.debug >= PF_DEBUG_MISC) printf("pfsync: received bulk update start\n"); @@ -1221,7 +1322,7 @@ } static int -pfsync_in_tdb(struct mbuf *m, int offset, int count, int flags) +pfsync_in_tdb(struct mbuf *m, int offset, int count, int flags, int action) { int len = count * sizeof(struct pfsync_tdb); @@ -1286,7 +1387,7 @@ #endif static int -pfsync_in_eof(struct mbuf *m, int offset, int count, int flags) +pfsync_in_eof(struct mbuf *m, int offset, int count, int flags, int action) { /* check if we are at the right place in the packet */ if (offset != m->m_pkthdr.len) @@ -1298,7 +1399,7 @@ } static int -pfsync_in_error(struct mbuf *m, int offset, int count, int flags) +pfsync_in_error(struct mbuf *m, int offset, int count, int flags, int action) { V_pfsyncstats.pfsyncs_badact++; @@ -1379,6 +1480,7 @@ nvlist_add_string(nvl, "syncdev", sc->sc_sync_if->if_xname); nvlist_add_number(nvl, "maxupdates", sc->sc_maxupdates); nvlist_add_number(nvl, "flags", sc->sc_flags); + nvlist_add_number(nvl, "version", sc->sc_version); if ((nvl_syncpeer = pfsync_sockaddr_to_syncpeer_nvlist(&sc->sc_sync_peer)) != NULL) nvlist_add_nvlist(nvl, "syncpeer", nvl_syncpeer); @@ -1464,11 +1566,19 @@ } static void -pfsync_out_state(struct pf_kstate *st, void *buf) +pfsync_out_state_1301(struct pf_kstate *st, void *buf) +{ + union pfsync_state_union *sp = buf; + + pfsync_state_export(sp, st, PFSYNC_MSG_VERSION_1301); +} + +static void +pfsync_out_state_1400(struct pf_kstate *st, void *buf) { - struct pfsync_state *sp = buf; + union pfsync_state_union *sp = buf; - pfsync_state_export(sp, st); + pfsync_state_export(sp, st, PFSYNC_MSG_VERSION_1400); } static void @@ -1509,16 +1619,17 @@ struct pf_kstate *st, *next; struct pfsync_upd_req_item *ur; struct pfsync_bucket *b; - int c, q; + int c; + enum pfsync_q_id q; for (c = 0; c < pfsync_buckets; c++) { b = &sc->sc_buckets[c]; - for (q = 0; q < PFSYNC_S_COUNT; q++) { + for (q = 0; q < PFSYNC_Q_COUNT; q++) { if (TAILQ_EMPTY(&b->b_qs[q])) continue; TAILQ_FOREACH_SAFE(st, &b->b_qs[q], sync_list, next) { - KASSERT(st->sync_state == q, + KASSERT(st->sync_state == pfsync_qid_sstate[q], ("%s: st->sync_state == q", __func__)); st->sync_state = PFSYNC_S_NONE; @@ -1548,8 +1659,8 @@ struct pf_kstate *st, *st_next; struct pfsync_upd_req_item *ur; struct pfsync_bucket *b = &sc->sc_buckets[c]; - int aflen, offset; - int q, count = 0; + int aflen, offset, count = 0; + enum pfsync_q_id q; KASSERT(sc != NULL, ("%s: null sc", __func__)); KASSERT(b->b_len > PFSYNC_MINPKT, @@ -1591,7 +1702,6 @@ return; } - /* build the pfsync header */ ph = (struct pfsync_header *)(m->m_data + offset); bzero(ph, sizeof(*ph)); @@ -1602,7 +1712,7 @@ bcopy(V_pf_status.pf_chksum, ph->pfcksum, PF_MD5_DIGEST_LENGTH); /* walk the queues */ - for (q = 0; q < PFSYNC_S_COUNT; q++) { + for (q = 0; q < PFSYNC_Q_COUNT; q++) { if (TAILQ_EMPTY(&b->b_qs[q])) continue; @@ -1611,7 +1721,7 @@ count = 0; TAILQ_FOREACH_SAFE(st, &b->b_qs[q], sync_list, st_next) { - KASSERT(st->sync_state == q, + KASSERT(st->sync_state == pfsync_qid_sstate[q], ("%s: st->sync_state == q", __func__)); /* @@ -2015,7 +2125,7 @@ panic("%s: unexpected sync state %d", __func__, st->sync_state); } - if ((sc->sc_ifp->if_mtu - b->b_len) < sizeof(struct pfsync_state)) + if ((sc->sc_ifp->if_mtu - b->b_len) < sizeof(union pfsync_state_union)) full = true; PFSYNC_BUCKET_UNLOCK(b); @@ -2087,9 +2197,47 @@ pfsync_send_plus(&r, sizeof(r)); } +static enum pfsync_q_id +pfsync_sstate_to_qid(u_int8_t sync_state) +{ + struct pfsync_softc *sc = V_pfsyncif; + + switch (sync_state) { + case PFSYNC_S_INS: + switch (sc->sc_version) { + case PFSYNC_MSG_VERSION_1301: + return PFSYNC_Q_INS_1301; + case PFSYNC_MSG_VERSION_1400: + return PFSYNC_Q_INS_1400; + } + break; + case PFSYNC_S_IACK: + return PFSYNC_Q_IACK; + case PFSYNC_S_UPD: + switch (sc->sc_version) { + case PFSYNC_MSG_VERSION_1301: + return PFSYNC_Q_UPD_1301; + case PFSYNC_MSG_VERSION_1400: + return PFSYNC_Q_UPD_1400; + } + break; + case PFSYNC_S_UPD_C: + return PFSYNC_Q_UPD_C; + case PFSYNC_S_DEL_C: + return PFSYNC_Q_DEL_C; + default: + panic("%s: Unsupported st->sync_state 0x%02x", + __func__, sync_state); + } + + panic("%s: Unsupported pfsync_msg_version %d", + __func__, sc->sc_version); +} + static void -pfsync_q_ins(struct pf_kstate *st, int q, bool ref) +pfsync_q_ins(struct pf_kstate *st, int sync_state, bool ref) { + enum pfsync_q_id q = pfsync_sstate_to_qid(sync_state); struct pfsync_softc *sc = V_pfsyncif; size_t nlen = pfsync_qs[q].len; struct pfsync_bucket *b = pfsync_get_bucket(sc, st); @@ -2112,7 +2260,7 @@ b->b_len += nlen; TAILQ_INSERT_TAIL(&b->b_qs[q], st, sync_list); - st->sync_state = q; + st->sync_state = pfsync_qid_sstate[q]; if (ref) pf_ref_state(st); } @@ -2120,12 +2268,13 @@ static void pfsync_q_del(struct pf_kstate *st, bool unref, struct pfsync_bucket *b) { - int q = st->sync_state; + enum pfsync_q_id q; PFSYNC_BUCKET_LOCK_ASSERT(b); KASSERT(st->sync_state != PFSYNC_S_NONE, ("%s: st->sync_state != PFSYNC_S_NONE", __func__)); + q = pfsync_sstate_to_qid(st->sync_state); b->b_len -= pfsync_qs[q].len; TAILQ_REMOVE(&b->b_qs[q], st, sync_list); st->sync_state = PFSYNC_S_NONE; @@ -2522,6 +2671,20 @@ imf = ip_mfilter_alloc(M_WAITOK, 0, 0); PFSYNC_LOCK(sc); + + switch (status->version) { + case PFSYNC_MSG_VERSION_UNSPECIFIED: + sc->sc_version = PFSYNC_MSG_VERSION_DEFAULT; + break; + case PFSYNC_MSG_VERSION_1301: + case PFSYNC_MSG_VERSION_1400: + sc->sc_version = status->version; + break; + default: + PFSYNC_UNLOCK(sc); + return (EINVAL); + } + struct sockaddr_in *sc_sin = (struct sockaddr_in *)&sc->sc_sync_peer; sc_sin->sin_family = AF_INET; sc_sin->sin_len = sizeof(*sc_sin); diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -3592,6 +3592,8 @@ void pf_rule_to_actions(struct pf_krule *r, struct pf_rule_actions *a) { + a->flags |= (r->scrub_flags & (PFSTATE_NODF|PFSTATE_RANDOMID| + PFSTATE_SETTOS|PFSTATE_SCRUB_TCP|PFSTATE_SETPRIO)); if (r->qid) a->qid = r->qid; if (r->pqid) @@ -3599,14 +3601,12 @@ if (r->rtableid >= 0) a->rtableid = r->rtableid; a->log |= r->log; - if (r->scrub_flags & PFSTATE_SETTOS) + if (a->flags & PFSTATE_SETTOS) a->set_tos = r->set_tos; if (r->min_ttl) a->min_ttl = r->min_ttl; if (r->max_mss) a->max_mss = r->max_mss; - a->flags |= (r->scrub_flags & (PFSTATE_NODF|PFSTATE_RANDOMID| - PFSTATE_SETTOS|PFSTATE_SCRUB_TCP|PFSTATE_SETPRIO)); if (r->dnpipe) a->dnpipe = r->dnpipe; if (r->dnrpipe) @@ -3617,6 +3617,10 @@ else a->flags &= ~PFSTATE_DN_IS_PIPE; } + if (a->flags & PFSTATE_SETPRIO) { + a->set_prio[0] = r->set_prio[0]; + a->set_prio[1] = r->set_prio[1]; + } } int @@ -4638,6 +4642,8 @@ s->pqid = pd->act.pqid; s->dnpipe = pd->act.dnpipe; s->dnrpipe = pd->act.dnrpipe; + s->set_prio[0] = pd->act.set_prio[0]; + s->set_prio[1] = pd->act.set_prio[1]; s->state_flags |= pd->act.flags; if (nr != NULL) s->log |= nr->log & PF_LOG_ALL; @@ -4706,6 +4712,7 @@ goto csfailed; } s->rt_kif = r->rpool.cur->kif; + s->rt = r->rt; } s->creation = time_uptime; @@ -6441,9 +6448,20 @@ struct pf_ksrc_node *sn = NULL; int error = 0; uint16_t ip_len, ip_off; + int r_rt, r_dir; KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__)); - KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: invalid direction", + + if (s) { + r_rt = s->rt; + r_dir = s->direction; + } else { + r_rt = r->rt; + r_dir = r->direction; + } + + KASSERT(dir == PF_IN || dir == PF_OUT || + r_dir == PF_IN || r_dir == PF_OUT, ("%s: invalid direction", __func__)); if ((pd->pf_mtag == NULL && @@ -6454,7 +6472,7 @@ goto bad_locked; } - if (r->rt == PF_DUPTO) { + if (r_rt == PF_DUPTO) { if ((pd->pf_mtag->flags & PF_DUPLICATED)) { if (s == NULL) { ifp = r->rpool.cur->kif ? @@ -6484,7 +6502,7 @@ } } } else { - if ((r->rt == PF_REPLYTO) == (r->direction == dir)) { + if ((r_rt == PF_REPLYTO) == (r_dir == dir)) { pf_dummynet(pd, dir, s, r, m); if (s) PF_STATE_UNLOCK(s); @@ -6583,7 +6601,7 @@ if ((ip_off & IP_DF) || (m0->m_pkthdr.csum_flags & CSUM_TSO)) { error = EMSGSIZE; KMOD_IPSTAT_INC(ips_cantfrag); - if (r->rt != PF_DUPTO) { + if (r_rt != PF_DUPTO) { if (s && pd->nat_rule != NULL) PACKET_UNDO_NAT(m0, pd, (ip->ip_hl << 2) + (ip_off & IP_OFFMASK), @@ -6619,7 +6637,7 @@ KMOD_IPSTAT_INC(ips_fragmented); done: - if (r->rt != PF_DUPTO) + if (r_rt != PF_DUPTO) *m = NULL; return; @@ -6643,9 +6661,20 @@ struct ifnet *ifp = NULL; struct pf_addr naddr; struct pf_ksrc_node *sn = NULL; + int r_rt, r_dir; KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__)); - KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: invalid direction", + + if (s) { + r_rt = s->rt; + r_dir = s->direction; + } else { + r_rt = r->rt; + r_dir = r->direction; + } + + KASSERT(dir == PF_IN || dir == PF_OUT || + r_dir == PF_IN || r_dir == PF_OUT, ("%s: invalid direction", __func__)); if ((pd->pf_mtag == NULL && @@ -6656,7 +6685,7 @@ goto bad_locked; } - if (r->rt == PF_DUPTO) { + if (r_rt == PF_DUPTO) { if ((pd->pf_mtag->flags & PF_DUPLICATED)) { if (s == NULL) { ifp = r->rpool.cur->kif ? @@ -6686,7 +6715,7 @@ } } } else { - if ((r->rt == PF_REPLYTO) == (r->direction == dir)) { + if ((r_rt == PF_REPLYTO) == (r_dir == dir)) { pf_dummynet(pd, dir, s, r, m); if (s) PF_STATE_UNLOCK(s); @@ -6770,7 +6799,7 @@ } else { in6_ifstat_inc(ifp, ifs6_in_toobig); - if (r->rt != PF_DUPTO) { + if (r_rt != PF_DUPTO) { if (s && pd->nat_rule != NULL) PACKET_UNDO_NAT(m0, pd, ((caddr_t)ip6 - m0->m_data) + @@ -6782,7 +6811,7 @@ } done: - if (r->rt != PF_DUPTO) + if (r_rt != PF_DUPTO) *m = NULL; return; @@ -7102,7 +7131,18 @@ struct pf_kstate *s = NULL; struct pf_kruleset *ruleset = NULL; struct pf_pdesc pd; - int off, dirndx, pqid = 0; + int off, dirndx; + uint16_t scrub_flags; +#ifdef ALTQ + uint16_t qid; +#endif + uint16_t pqid; + uint16_t tag; + int32_t rtableid; + uint8_t min_ttl; + uint8_t set_tos; + uint8_t rt; + uint8_t set_prio[2]; PF_RULES_RLOCK_TRACKER; KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: bad direction %d\n", __func__, dir)); @@ -7394,36 +7434,47 @@ } if (s) { - pf_scrub_ip(&m, s->state_flags, s->min_ttl, s->set_tos); - if (s->rtableid >= 0) - M_SETFIB(m, s->rtableid); + scrub_flags = s->state_flags; + min_ttl = s->min_ttl; + set_tos = s->set_tos; + rtableid = s->rtableid; + pqid = s->pqid; #ifdef ALTQ - if (s->qid) { - pd.act.pqid = s->pqid; - pd.act.qid = s->qid; - } + qid = s->qid; #endif + tag = s->tag; + rt = s->rt; + set_prio[0] = s->set_prio[0]; + set_prio[1] = s->set_prio[1]; } else { - pf_scrub_ip(&m, r->scrub_flags, r->min_ttl, r->set_tos); - if (r->rtableid >= 0) - M_SETFIB(m, r->rtableid); + scrub_flags = r->scrub_flags; + min_ttl = r->min_ttl; + set_tos = r->set_tos; + rtableid = r->rtableid; + pqid = r->pqid; #ifdef ALTQ - if (r->qid) { - pd.act.pqid = r->pqid; - pd.act.qid = r->qid; - } + qid = r->qid; #endif + tag = r->tag; + rt = r->rt; + set_prio[0] = r->set_prio[0]; + set_prio[1] = r->set_prio[1]; } - if (s && s->tag > 0 && pf_tag_packet(m, &pd, s->tag)) { + if (tag > 0 && pf_tag_packet(m, &pd, tag)) { action = PF_DROP; REASON_SET(&reason, PFRES_MEMORY); } - if (r->scrub_flags & PFSTATE_SETPRIO) { + pf_scrub_ip(&m, scrub_flags, min_ttl, set_tos); + + if (rtableid >= 0) + M_SETFIB(m, rtableid); + + if (scrub_flags & PFSTATE_SETPRIO) { if (pd.tos & IPTOS_LOWDELAY) pqid = 1; - if (vlan_set_pcp(m, r->set_prio[pqid])) { + if (vlan_set_pcp(m, set_prio[pqid])) { action = PF_DROP; REASON_SET(&reason, PFRES_MEMORY); log = PF_LOG_FORCE; @@ -7433,6 +7484,11 @@ } #ifdef ALTQ + if (qid) { + pd.act.pqid = pqid; + pd.act.qid = qid; + } + if (action == PF_PASS && pd.act.qid) { if (pd.pf_mtag == NULL && ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) { @@ -7604,7 +7660,7 @@ break; default: /* pf_route() returns unlocked. */ - if (r->rt) { + if (rt) { pf_route(m0, r, dir, kif->pfik_ifp, s, &pd, inp); return (action); } @@ -7637,7 +7693,18 @@ struct pf_kstate *s = NULL; struct pf_kruleset *ruleset = NULL; struct pf_pdesc pd; - int off, terminal = 0, dirndx, rh_cnt = 0, pqid = 0; + int off, terminal = 0, dirndx, rh_cnt = 0; + uint16_t scrub_flags; +#ifdef ALTQ + uint16_t qid; +#endif + uint16_t pqid; + uint16_t tag; + int32_t rtableid; + uint8_t min_ttl; + uint8_t set_tos; + uint8_t rt; + uint8_t set_prio[2]; PF_RULES_RLOCK_TRACKER; KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: bad direction %d\n", __func__, dir)); @@ -7925,37 +7992,48 @@ ("pf: dropping packet with dangerous v6 headers\n")); } - if (s && s->tag > 0 && pf_tag_packet(m, &pd, s->tag)) { - action = PF_DROP; - REASON_SET(&reason, PFRES_MEMORY); - } - if (s) { - pf_scrub_ip6(&m, s->state_flags, s->min_ttl, s->set_tos); - if (s->rtableid >= 0) - M_SETFIB(m, s->rtableid); + scrub_flags = s->state_flags; + min_ttl = s->min_ttl; + set_tos = s->set_tos; + rtableid = s->rtableid; + pqid = s->pqid; #ifdef ALTQ - if (s->qid) { - pd.act.pqid = s->pqid; - pd.act.qid = s->qid; - } + qid = s->qid; #endif + tag = s->tag; + rt = s->rt; + set_prio[0] = s->set_prio[0]; + set_prio[1] = s->set_prio[1]; } else { - pf_scrub_ip6(&m, r->scrub_flags, r->min_ttl, r->set_tos); - if (r->rtableid >= 0) - M_SETFIB(m, r->rtableid); + scrub_flags = r->scrub_flags; + min_ttl = r->min_ttl; + set_tos = r->set_tos; + rtableid = r->rtableid; + pqid = r->pqid; #ifdef ALTQ - if (r->qid) { - pd.act.pqid = r->pqid; - pd.act.qid = r->qid; - } + qid = r->qid; #endif + tag = r->tag; + rt = r->rt; + set_prio[0] = r->set_prio[0]; + set_prio[1] = r->set_prio[1]; } - if (r->scrub_flags & PFSTATE_SETPRIO) { + if (tag > 0 && pf_tag_packet(m, &pd, tag)) { + action = PF_DROP; + REASON_SET(&reason, PFRES_MEMORY); + } + + pf_scrub_ip6(&m, scrub_flags, min_ttl, set_tos); + + if (rtableid >= 0) + M_SETFIB(m, rtableid); + + if (scrub_flags & PFSTATE_SETPRIO) { if (pd.tos & IPTOS_LOWDELAY) pqid = 1; - if (vlan_set_pcp(m, r->set_prio[pqid])) { + if (vlan_set_pcp(m, set_prio[pqid])) { action = PF_DROP; REASON_SET(&reason, PFRES_MEMORY); log = PF_LOG_FORCE; @@ -7965,6 +8043,11 @@ } #ifdef ALTQ + if (qid) { + pd.act.pqid = pqid; + pd.act.qid = qid; + } + if (action == PF_PASS && pd.act.qid) { if (pd.pf_mtag == NULL && ((pd.pf_mtag = pf_get_mtag(m)) == NULL)) { @@ -8084,7 +8167,7 @@ break; default: /* pf_route6() returns unlocked. */ - if (r->rt) { + if (rt) { pf_route6(m0, r, dir, kif->pfik_ifp, s, &pd, inp); return (action); } diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -3720,8 +3720,8 @@ } case DIOCADDSTATE: { - struct pfioc_state *ps = (struct pfioc_state *)addr; - struct pfsync_state *sp = &ps->state; + struct pfioc_state *ps = (struct pfioc_state *)addr; + struct pfsync_state_1301 *sp = &ps->state; if (sp->timeout >= PFTM_MAX) { error = EINVAL; @@ -3729,7 +3729,9 @@ } if (V_pfsync_state_import_ptr != NULL) { PF_RULES_RLOCK(); - error = V_pfsync_state_import_ptr(sp, PFSYNC_SI_IOCTL); + error = V_pfsync_state_import_ptr( + (union pfsync_state_union *)sp, PFSYNC_SI_IOCTL, + PFSYNC_MSG_VERSION_1301); PF_RULES_RUNLOCK(); } else error = EOPNOTSUPP; @@ -3746,7 +3748,8 @@ break; } - pfsync_state_export(&ps->state, s); + pfsync_state_export((union pfsync_state_union*)&ps->state, + s, PFSYNC_MSG_VERSION_1301); PF_STATE_UNLOCK(s); break; } @@ -3759,20 +3762,20 @@ case DIOCGETSTATES: { struct pfioc_states *ps = (struct pfioc_states *)addr; struct pf_kstate *s; - struct pfsync_state *pstore, *p; + struct pfsync_state_1301 *pstore, *p; int i, nr; size_t slice_count = 16, count; void *out; if (ps->ps_len <= 0) { nr = uma_zone_get_cur(V_pf_state_z); - ps->ps_len = sizeof(struct pfsync_state) * nr; + ps->ps_len = sizeof(struct pfsync_state_1301) * nr; break; } out = ps->ps_states; pstore = mallocarray(slice_count, - sizeof(struct pfsync_state), M_TEMP, M_WAITOK | M_ZERO); + sizeof(struct pfsync_state_1301), M_TEMP, M_WAITOK | M_ZERO); nr = 0; for (i = 0; i <= pf_hashmask; i++) { @@ -3797,7 +3800,7 @@ free(pstore, M_TEMP); slice_count = count * 2; pstore = mallocarray(slice_count, - sizeof(struct pfsync_state), M_TEMP, + sizeof(struct pfsync_state_1301), M_TEMP, M_WAITOK | M_ZERO); goto DIOCGETSTATES_retry; } @@ -3811,19 +3814,20 @@ if (s->timeout == PFTM_UNLINKED) continue; - pfsync_state_export(p, s); + pfsync_state_export((union pfsync_state_union*)p, + s, PFSYNC_MSG_VERSION_1301); p++; nr++; } PF_HASHROW_UNLOCK(ih); error = copyout(pstore, out, - sizeof(struct pfsync_state) * count); + sizeof(struct pfsync_state_1301) * count); if (error) break; out = ps->ps_states + nr; } DIOCGETSTATES_full: - ps->ps_len = sizeof(struct pfsync_state) * nr; + ps->ps_len = sizeof(struct pfsync_state_1301) * nr; free(pstore, M_TEMP); break; @@ -5663,64 +5667,90 @@ } void -pfsync_state_export(struct pfsync_state *sp, struct pf_kstate *st) +pfsync_state_export(union pfsync_state_union *sp, struct pf_kstate *st, int msg_version) { - bzero(sp, sizeof(struct pfsync_state)); + bzero(sp, sizeof(union pfsync_state_union)); /* 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; + sp->pfs_1301.key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0]; + sp->pfs_1301.key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1]; + sp->pfs_1301.key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0]; + sp->pfs_1301.key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1]; + sp->pfs_1301.key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0]; + sp->pfs_1301.key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1]; + sp->pfs_1301.key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0]; + sp->pfs_1301.key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1]; + sp->pfs_1301.proto = st->key[PF_SK_WIRE]->proto; + sp->pfs_1301.af = st->key[PF_SK_WIRE]->af; /* copy from state */ - strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->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); + strlcpy(sp->pfs_1301.ifname, st->kif->pfik_name, sizeof(sp->pfs_1301.ifname)); + bcopy(&st->rt_addr, &sp->pfs_1301.rt_addr, sizeof(sp->pfs_1301.rt_addr)); + sp->pfs_1301.creation = htonl(time_uptime - st->creation); + sp->pfs_1301.expire = pf_state_expires(st); + if (sp->pfs_1301.expire <= time_uptime) + sp->pfs_1301.expire = htonl(0); else - sp->expire = htonl(sp->expire - time_uptime); + sp->pfs_1301.expire = htonl(sp->pfs_1301.expire - time_uptime); + + sp->pfs_1301.direction = st->direction; + sp->pfs_1301.log = st->log; + sp->pfs_1301.timeout = st->timeout; + + switch (msg_version) { + case PFSYNC_MSG_VERSION_1301: + sp->pfs_1301.state_flags = st->state_flags; + break; + case PFSYNC_MSG_VERSION_1400: + sp->pfs_1400.state_flags = htons(st->state_flags); + sp->pfs_1400.qid = htons(st->qid); + sp->pfs_1400.pqid = htons(st->pqid); + sp->pfs_1400.dnpipe = htons(st->dnpipe); + sp->pfs_1400.dnrpipe = htons(st->dnrpipe); + sp->pfs_1400.rtableid = htonl(st->rtableid); + sp->pfs_1400.min_ttl = st->min_ttl; + sp->pfs_1400.set_tos = st->set_tos; + sp->pfs_1400.max_mss = htons(st->max_mss); + sp->pfs_1400.set_prio[0] = st->set_prio[0]; + sp->pfs_1400.set_prio[1] = st->set_prio[1]; + sp->pfs_1400.rt = st->rt; + if (st->rt_kif) + strlcpy(sp->pfs_1400.rt_ifname, + st->rt_kif->pfik_name, + sizeof(sp->pfs_1400.rt_ifname)); + break; + default: + panic("%s: Unsupported pfsync_msg_version %d", + __func__, msg_version); + } - sp->direction = st->direction; - sp->log = st->log; - sp->timeout = st->timeout; - sp->state_flags_compat = st->state_flags; - sp->state_flags = htons(st->state_flags); if (st->src_node) - sp->sync_flags |= PFSYNC_FLAG_SRCNODE; + sp->pfs_1301.sync_flags |= PFSYNC_FLAG_SRCNODE; if (st->nat_src_node) - sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE; + sp->pfs_1301.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); + sp->pfs_1301.id = st->id; + sp->pfs_1301.creatorid = st->creatorid; + pf_state_peer_hton(&st->src, &sp->pfs_1301.src); + pf_state_peer_hton(&st->dst, &sp->pfs_1301.dst); if (st->rule.ptr == NULL) - sp->rule = htonl(-1); + sp->pfs_1301.rule = htonl(-1); else - sp->rule = htonl(st->rule.ptr->nr); + sp->pfs_1301.rule = htonl(st->rule.ptr->nr); if (st->anchor.ptr == NULL) - sp->anchor = htonl(-1); + sp->pfs_1301.anchor = htonl(-1); else - sp->anchor = htonl(st->anchor.ptr->nr); + sp->pfs_1301.anchor = htonl(st->anchor.ptr->nr); if (st->nat_rule.ptr == NULL) - sp->nat_rule = htonl(-1); + sp->pfs_1301.nat_rule = htonl(-1); else - sp->nat_rule = htonl(st->nat_rule.ptr->nr); + sp->pfs_1301.nat_rule = htonl(st->nat_rule.ptr->nr); - pf_state_counter_hton(st->packets[0], sp->packets[0]); - 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]); + pf_state_counter_hton(st->packets[0], sp->pfs_1301.packets[0]); + pf_state_counter_hton(st->packets[1], sp->pfs_1301.packets[1]); + pf_state_counter_hton(st->bytes[0], sp->pfs_1301.bytes[0]); + pf_state_counter_hton(st->bytes[1], sp->pfs_1301.bytes[1]); } void diff --git a/sys/netpfil/pf/pfsync_nv.c b/sys/netpfil/pf/pfsync_nv.c --- a/sys/netpfil/pf/pfsync_nv.c +++ b/sys/netpfil/pf/pfsync_nv.c @@ -130,6 +130,7 @@ return (EINVAL); status->maxupdates = nvlist_get_number(nvl, "maxupdates"); + status->version = nvlist_get_number(nvl, "version"); status->flags = nvlist_get_number(nvl, "flags"); if (nvlist_exists_string(nvl, "syncdev")) diff --git a/usr.bin/netstat/if.c b/usr.bin/netstat/if.c --- a/usr.bin/netstat/if.c +++ b/usr.bin/netstat/if.c @@ -81,9 +81,9 @@ #ifdef PF static const char* pfsyncacts[] = { /* PFSYNC_ACT_CLR */ "clear all request", - /* PFSYNC_ACT_INS */ "state insert", + /* PFSYNC_ACT_INS_1301 */ "13.1 state insert", /* PFSYNC_ACT_INS_ACK */ "state inserted ack", - /* PFSYNC_ACT_UPD */ "state update", + /* PFSYNC_ACT_UPD_1301 */ "13.1 state update", /* PFSYNC_ACT_UPD_C */ "compressed state update", /* PFSYNC_ACT_UPD_REQ */ "uncompressed state request", /* PFSYNC_ACT_DEL */ "state delete", @@ -93,13 +93,15 @@ /* PFSYNC_ACT_BUS */ "bulk update mark", /* PFSYNC_ACT_TDB */ "TDB replay counter update", /* PFSYNC_ACT_EOF */ "end of frame mark", + /* PFSYNC_ACT_INS_1400 */ "state insert", + /* PFSYNC_ACT_UPD_1400 */ "state update", }; static const char* pfsyncacts_name[] = { /* PFSYNC_ACT_CLR */ "clear-all-request", - /* PFSYNC_ACT_INS */ "state-insert", + /* PFSYNC_ACT_INS_1301 */ "state-insert-1301", /* PFSYNC_ACT_INS_ACK */ "state-inserted-ack", - /* PFSYNC_ACT_UPD */ "state-update", + /* PFSYNC_ACT_UPD_1301 */ "state-update-1301", /* PFSYNC_ACT_UPD_C */ "compressed-state-update", /* PFSYNC_ACT_UPD_REQ */ "uncompressed-state-request", /* PFSYNC_ACT_DEL */ "state-delete", @@ -109,6 +111,8 @@ /* PFSYNC_ACT_BUS */ "bulk-update-mark", /* PFSYNC_ACT_TDB */ "TDB-replay-counter-update", /* PFSYNC_ACT_EOF */ "end-of-frame-mark", + /* PFSYNC_ACT_INS_1400 */ "state-insert", + /* PFSYNC_ACT_UPD_1400 */ "state-update", }; static void