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,14 @@ struct pfsync_actions actions[] = { { "clear all", sizeof(struct pfsync_clr), pfsync_print_clr }, - { "insert", sizeof(struct pfsync_state), pfsync_print_state }, + { "insert", 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", 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 +127,9 @@ 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 }, + { "delete", sizeof(struct pfsync_state_1400), pfsync_print_state_1400 }, }; static void @@ -212,12 +216,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 +387,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 +449,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 @@ -57,6 +57,7 @@ void setpfsync_syncpeer(const char *, int, int, const struct afswtch *); void setpfsync_maxupd(const char *, int, int, const struct afswtch *); void setpfsync_defer(const char *, int, int, const struct afswtch *); +void setpfsync_version(const char *, int, int, const struct afswtch *); void pfsync_status(int); static int @@ -323,6 +324,28 @@ nvlist_destroy(nvl); } +/* ARGSUSED */ +void +setpfsync_version(const char *val, int d, int s, const struct afswtch *rafp) +{ + int version; + nvlist_t *nvl = nvlist_create(0); + + /* Don't verify, kernel knows which versions are supported.*/ + version = atoi(val); + + if (pfsync_do_ioctl(s, SIOCGETPFSYNCNV, &nvl) == -1) + err(1, "SIOCGETPFSYNCNV"); + + nvlist_free_number(nvl, "version"); + nvlist_add_number(nvl, "version", version); + + if (pfsync_do_ioctl(s, SIOCSETPFSYNCNV, &nvl) == -1) + err(1, "SIOCSETPFSYNCNV"); + + nvlist_destroy(nvl); +} + void pfsync_status(int s) { @@ -331,6 +354,7 @@ char syncpeer_str[NI_MAXHOST]; struct sockaddr_storage syncpeer; int maxupdates; + int version; int flags; int error; @@ -347,6 +371,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")) { @@ -377,7 +403,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); } @@ -391,6 +418,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,20 +59,31 @@ #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 */ +#define PFSYNC_ACT_DEL_1301 6 /* delete state */ #define PFSYNC_ACT_DEL_C 7 /* "compressed" delete state */ #define PFSYNC_ACT_INS_F 8 /* insert fragment */ #define PFSYNC_ACT_DEL_F 9 /* delete fragments */ #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_DEL_1400 15 /* delete state */ +#define PFSYNC_ACT_MAX 16 /* * A pfsync frame is built from a header followed by several sections which @@ -251,6 +262,7 @@ char syncdev[IFNAMSIZ]; struct sockaddr_storage syncpeer; int maxupdates; + int version; int flags; }; @@ -269,13 +281,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 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 @@ -1043,7 +1043,7 @@ 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]; @@ -1069,9 +1069,49 @@ 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]; + 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_int16_t state_flags; + u_int8_t log; + u_int8_t __spare; + u_int8_t timeout; + u_int8_t sync_flags; + u_int8_t updates; + /* The rest is not */ + u_int8_t rt; + u_int16_t max_mss; + u_int8_t min_ttl; + u_int8_t set_tos; + u_int8_t set_prio[2]; + int32_t rtableid; + +} __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 *); @@ -1093,8 +1133,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 *); @@ -1613,7 +1653,7 @@ }; struct pfioc_state { - struct pfsync_state state; + struct pfsync_state_1301 state; }; struct pfioc_src_node_kill { @@ -1653,7 +1693,7 @@ int ps_len; union { caddr_t psu_buf; - struct pfsync_state *psu_states; + struct pfsync_state_1301 *psu_states; } ps_u; #define ps_buf ps_u.psu_buf #define ps_states ps_u.psu_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,33 +122,36 @@ 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(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_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(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) = { +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_del, /* PFSYNC_ACT_DEL */ + pfsync_in_del, /* PFSYNC_ACT_DEL_1301 */ pfsync_in_del_c, /* PFSYNC_ACT_DEL_C */ pfsync_in_error, /* PFSYNC_ACT_INS_F */ 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 */ + pfsync_in_del, /* PFSYNC_ACT_DEL_1400 */ }; struct pfsync_q { @@ -157,18 +160,45 @@ 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, + 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(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, 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, 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, /* PFSYNC_Q_DEL */ }; static void pfsync_q_ins(struct pf_kstate *, int, bool); @@ -201,7 +231,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; @@ -221,6 +251,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; @@ -348,6 +379,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) { @@ -380,7 +412,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); @@ -466,7 +498,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 @@ -481,17 +513,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 */ @@ -501,11 +533,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; @@ -524,16 +556,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); @@ -543,8 +575,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). */ @@ -552,41 +584,64 @@ 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; - st->state_flags = sp->state_flags; + st->direction = sp->pfs_1301.direction; + st->log = sp->pfs_1301.log; + st->timeout = sp->pfs_1301.timeout; - st->id = sp->id; - st->creatorid = sp->creatorid; - pf_state_peer_ntoh(&sp->src, &st->src); - pf_state_peer_ntoh(&sp->dst, &st->dst); + 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); + + switch (msg_version) { + case PFSYNC_MSG_VERSION_1301: + st->state_flags = sp->pfs_1301.state_flags; + break; + case PFSYNC_MSG_VERSION_1400: + st->state_flags = ntohs(sp->pfs_1400.state_flags); + /* + * TODO: modify pf.c to store those values in states. + * This is already partially done in D38025. + * Add export for DIOCGETSTATESV2 too. + * + * st->rt = sp->pfs_1400.rt; + * st->max_mss = sp->pfs_1400.max_mss; + * st->min_ttl = sp->pfs_1400.min_ttl; + * st->set_prio[0] = sp->pfs_1400->set_prio[0]; + * st->set_prio[1] = sp->pfs_1400->set_prio[1]; + * st->rtableid = sp->pfs_1400->rtableid; + */ + break; + default: + panic("%s: Unsupported pfsync_msg_version %d", + __func__, msg_version); + } st->rule.ptr = r; st->nat_rule.ptr = NULL; @@ -611,7 +666,7 @@ if (st->state_flags & PFSTATE_ACK) { struct pfsync_bucket *b = pfsync_get_bucket(sc, st); PFSYNC_BUCKET_LOCK(b); - pfsync_q_ins(st, PFSYNC_S_IACK, true); + pfsync_q_ins(st, PFSYNC_Q_IACK, true); PFSYNC_BUCKET_UNLOCK(b); pfsync_push_all(sc); @@ -725,7 +780,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); @@ -742,7 +797,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; @@ -784,36 +839,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; } @@ -822,7 +891,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; @@ -893,31 +962,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"); @@ -926,10 +1006,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; } @@ -939,7 +1019,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; @@ -947,20 +1027,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; @@ -979,7 +1059,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; @@ -1066,7 +1146,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; @@ -1107,25 +1187,36 @@ } static int -pfsync_in_del(struct mbuf *m, int offset, int count, int flags) +pfsync_in_del(struct mbuf *m, int offset, int count, int flags, int action) { struct mbuf *mp; - struct pfsync_state *sa, *sp; + union pfsync_state_union *sa, *sp; struct pf_kstate *st; - int len = count * sizeof(*sp); - int offp, i; + int len, offp, i; + + switch (action) { + case PFSYNC_ACT_DEL_1301: + len = sizeof(struct pfsync_state_1301) * count; + break; + case PFSYNC_ACT_DEL_1400: + len = sizeof(struct pfsync_state_1400) * count; + 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]; - 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) { V_pfsyncstats.pfsyncs_badstate++; continue; @@ -1138,7 +1229,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; @@ -1170,7 +1261,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; @@ -1199,7 +1290,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"); @@ -1232,7 +1323,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); @@ -1297,7 +1388,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) @@ -1309,7 +1400,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++; @@ -1390,6 +1481,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); @@ -1475,11 +1567,19 @@ } static void -pfsync_out_state(struct pf_kstate *st, void *buf) +pfsync_out_state_1301(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_1301); +} + +static void +pfsync_out_state_1400(struct pf_kstate *st, void *buf) +{ + union pfsync_state_union *sp = buf; + + pfsync_state_export(sp, st, PFSYNC_MSG_VERSION_1400); } static void @@ -1524,12 +1624,12 @@ 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; @@ -1602,7 +1702,6 @@ return; } - /* build the pfsync header */ ph = (struct pfsync_header *)(m->m_data + offset); bzero(ph, sizeof(*ph)); @@ -1613,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; @@ -1622,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__)); /* @@ -1731,7 +1830,18 @@ if (b->b_len == PFSYNC_MINPKT) callout_reset(&b->b_tmo, 1 * hz, pfsync_timeout, b); - pfsync_q_ins(st, PFSYNC_S_INS, true); + switch (sc->sc_version) { + case PFSYNC_MSG_VERSION_1301: + pfsync_q_ins(st, PFSYNC_Q_INS_1301, true); + break; + case PFSYNC_MSG_VERSION_1400: + pfsync_q_ins(st, PFSYNC_Q_INS_1400, true); + break; + default: + panic("%s: Unsupported pfsync_msg_version %d", + __func__, sc->sc_version); + } + PFSYNC_BUCKET_UNLOCK(b); st->sync_updates = 0; @@ -1930,7 +2040,7 @@ /* FALLTHROUGH */ case PFSYNC_S_NONE: - pfsync_q_ins(st, PFSYNC_S_UPD_C, ref); + pfsync_q_ins(st, PFSYNC_Q_UPD_C, ref); st->sync_updates = 0; break; @@ -2012,7 +2122,17 @@ /* FALLTHROUGH */ case PFSYNC_S_NONE: - pfsync_q_ins(st, PFSYNC_S_UPD, ref); + switch (sc->sc_version) { + case PFSYNC_MSG_VERSION_1301: + pfsync_q_ins(st, PFSYNC_Q_UPD_1301, ref); + break; + case PFSYNC_MSG_VERSION_1400: + pfsync_q_ins(st, PFSYNC_Q_UPD_1400, ref); + break; + default: + panic("%s: Unsupported pfsync_msg_version %d", + __func__, sc->sc_version); + } pfsync_push(b); break; @@ -2026,7 +2146,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); @@ -2068,7 +2188,7 @@ /* FALLTHROUGH */ case PFSYNC_S_NONE: - pfsync_q_ins(st, PFSYNC_S_DEL, ref); + pfsync_q_ins(st, PFSYNC_Q_DEL, ref); break; default: @@ -2123,7 +2243,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); } @@ -2131,20 +2251,25 @@ 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__)); - b->b_len -= pfsync_qs[q].len; - TAILQ_REMOVE(&b->b_qs[q], st, sync_list); - st->sync_state = PFSYNC_S_NONE; - if (unref) - pf_release_state(st); + for (q=0; qsync_state) + continue; - if (TAILQ_EMPTY(&b->b_qs[q])) - b->b_len -= sizeof(struct pfsync_subheader); + b->b_len -= pfsync_qs[q].len; + TAILQ_REMOVE(&b->b_qs[q], st, sync_list); + st->sync_state = PFSYNC_S_NONE; + if (unref) + pf_release_state(st); + + if (TAILQ_EMPTY(&b->b_qs[q])) + b->b_len -= sizeof(struct pfsync_subheader); + } } static void @@ -2533,6 +2658,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 @@ -2011,6 +2011,8 @@ { struct pf_idhash *ih = &V_pf_idhash[PF_IDHASH(s)]; + printf("%s: creator: %08x, id: %016lx ss: %d\n", __func__, s->creatorid, s->id, s->sync_state); + PF_HASHROW_ASSERT(ih); if (s->timeout == PFTM_UNLINKED) { 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 @@ -3708,8 +3708,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; @@ -3717,7 +3717,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; @@ -3734,7 +3736,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; } @@ -3747,20 +3750,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++) { @@ -3785,7 +3788,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; } @@ -3799,19 +3802,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; @@ -5640,63 +5644,75 @@ } 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); + 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 = 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"))