From 526c2b65984520c2f0878d4707d4e98a8c39de2d Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Mon, 16 Feb 2009 00:31:26 +0000 Subject: pfsync v5, mostly written at n2k9, but based on work done at n2k8. WARNING: THIS BREAKS COMPATIBILITY WITH THE PREVIOUS VERSION OF PFSYNC this is a new variant of the protocol and a large reworking of the pfsync code to address some performance issues. the single largest benefit comes from having multiple pfsync messages of different types handled in a single packet. pfsyncs handling of pf states is highly optimised now, along with packet parsing and construction. huggz for beck@ for testing. huge thanks to mcbride@ for his help during development and for finding all the bugs during the initial tests. thanks to peter sutton for letting me get credit for this work. ok beck@ mcbride@ "good." deraadt@ --- sys/net/if_pfsync.h | 355 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 211 insertions(+), 144 deletions(-) (limited to 'sys/net/if_pfsync.h') diff --git a/sys/net/if_pfsync.h b/sys/net/if_pfsync.h index 1fa562c9590..fae33616dc7 100644 --- a/sys/net/if_pfsync.h +++ b/sys/net/if_pfsync.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pfsync.h,v 1.35 2008/06/29 08:42:15 mcbride Exp $ */ +/* $OpenBSD: if_pfsync.h,v 1.36 2009/02/16 00:31:25 dlg Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -26,154 +26,217 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * Copyright (c) 2008 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + #ifndef _NET_IF_PFSYNC_H_ #define _NET_IF_PFSYNC_H_ +#define PFSYNC_VERSION 5 +#define PFSYNC_DFLTTL 255 + +#define PFSYNC_ACT_CLR 0 /* clear all states */ +#define PFSYNC_ACT_INS 1 /* insert state */ +#define PFSYNC_ACT_INS_ACK 2 /* ack of insterted state */ +#define PFSYNC_ACT_UPD 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_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_ID_LEN sizeof(u_int64_t) +#define PFSYNC_ACTIONS "CLR ST", \ + "INS ST", \ + "INS ST ACK", \ + "UPD ST", \ + "UPD ST COMP", \ + "UPD ST REQ", \ + "DEL ST", \ + "DEL ST COMP", \ + "INS FR", \ + "DEL FR", \ + "BULK UPD STAT", \ + "TDB UPD", \ + "EOF" -struct pfsync_tdb { - u_int32_t spi; - union sockaddr_union dst; - u_int32_t rpl; - u_int64_t cur_bytes; - u_int8_t sproto; - u_int8_t updates; - u_int8_t pad[2]; +#define PFSYNC_HMAC_LEN 20 + +/* + * A pfsync frame is built from a header followed by several sections which + * are all prefixed with their own subheaders. Frames must be terminated with + * an EOF subheader. + * + * | ... | + * | IP header | + * +============================+ + * | pfsync_header | + * +----------------------------+ + * | pfsync_subheader | + * +----------------------------+ + * | first action fields | + * | ... | + * +----------------------------+ + * | pfsync_subheader | + * +----------------------------+ + * | second action fields | + * | ... | + * +----------------------------+ + * | EOF pfsync_subheader | + * +----------------------------+ + * | HMAC | + * +============================+ + */ + +/* + * Frame header + */ + +struct pfsync_header { + u_int8_t version; + u_int8_t _pad; + u_int16_t len; + u_int8_t pfcksum[PF_MD5_DIGEST_LENGTH]; } __packed; -struct pfsync_state_upd { - u_int32_t id[2]; - struct pfsync_state_peer src; - struct pfsync_state_peer dst; - u_int32_t creatorid; - u_int32_t expire; - u_int8_t timeout; - u_int8_t updates; - u_int8_t pad[6]; +/* + * Frame region subheader + */ + +struct pfsync_subheader { + u_int8_t action; + u_int8_t _pad; + u_int16_t count; } __packed; -struct pfsync_state_del { - u_int32_t id[2]; - u_int32_t creatorid; - struct { - u_int8_t state; - } src; - struct { - u_int8_t state; - } dst; - u_int8_t pad[2]; +/* + * CLR + */ + +struct pfsync_clr { + char ifname[IFNAMSIZ]; + u_int32_t creatorid; } __packed; -struct pfsync_state_upd_req { - u_int32_t id[2]; - u_int32_t creatorid; - u_int32_t pad; +/* + * INS, UPD, DEL + */ + +/* these use struct pfsync_state in pfvar.h */ + +/* + * INS_ACK + */ + +struct pfsync_ins_ack { + u_int64_t id; + u_int32_t creatorid; } __packed; -struct pfsync_state_clr { - char ifname[IFNAMSIZ]; - u_int32_t creatorid; - u_int32_t pad; +/* + * UPD_C + */ + +struct pfsync_upd_c { + u_int64_t id; + struct pfsync_state_peer src; + struct pfsync_state_peer dst; + u_int32_t creatorid; + u_int32_t expire; + u_int8_t timeout; + u_int8_t _pad[3]; } __packed; -struct pfsync_state_bus { - u_int32_t creatorid; - u_int32_t endtime; - u_int8_t status; -#define PFSYNC_BUS_START 1 -#define PFSYNC_BUS_END 2 - u_int8_t pad[7]; +/* + * UPD_REQ + */ + +struct pfsync_upd_req { + u_int64_t id; + u_int32_t creatorid; } __packed; /* - * Names for PFSYNC sysctl objects + * DEL_C */ -#define PFSYNCCTL_STATS 1 /* PFSYNC stats */ -#define PFSYNCCTL_MAXID 2 -#define PFSYNCCTL_NAMES { \ - { 0, 0 }, \ - { "stats", CTLTYPE_STRUCT }, \ -} +struct pfsync_del_c { + u_int64_t id; + u_int32_t creatorid; +} __packed; -#ifdef _KERNEL +/* + * INS_F, DEL_F + */ -union sc_statep { - struct pfsync_state *s; - struct pfsync_state_upd *u; - struct pfsync_state_del *d; - struct pfsync_state_clr *c; - struct pfsync_state_bus *b; - struct pfsync_state_upd_req *r; -}; +/* not implemented (yet) */ -union sc_tdb_statep { - struct pfsync_tdb *t; -}; +/* + * BUS + */ -extern int pfsync_sync_ok; - -struct pfsync_softc { - struct ifnet sc_if; - struct ifnet *sc_sync_ifp; - - struct ip_moptions sc_imo; - struct timeout sc_tmo; - struct timeout sc_tdb_tmo; - struct timeout sc_bulk_tmo; - struct timeout sc_bulkfail_tmo; - struct in_addr sc_sync_peer; - struct in_addr sc_sendaddr; - struct mbuf *sc_mbuf; /* current cumulative mbuf */ - struct mbuf *sc_mbuf_net; /* current cumulative mbuf */ - struct mbuf *sc_mbuf_tdb; /* dito for TDB updates */ - union sc_statep sc_statep; - union sc_statep sc_statep_net; - union sc_tdb_statep sc_statep_tdb; - u_int32_t sc_ureq_received; - u_int32_t sc_ureq_sent; - struct pf_state *sc_bulk_send_next; - struct pf_state *sc_bulk_terminator; - int sc_bulk_tries; - int sc_maxcount; /* number of states in mtu */ - int sc_maxupdates; /* number of updates/state */ -}; +struct pfsync_bus { + u_int32_t creatorid; + u_int32_t endtime; + u_int8_t status; +#define PFSYNC_BUS_START 1 +#define PFSYNC_BUS_END 2 + u_int8_t _pad[3]; +} __packed; -extern struct pfsync_softc *pfsyncif; -#endif +/* + * TDB + */ +struct pfsync_tdb { + u_int32_t spi; + union sockaddr_union dst; + u_int32_t rpl; + u_int64_t cur_bytes; + u_int8_t sproto; + u_int8_t updates; + u_int8_t _pad[2]; +} __packed; -struct pfsync_header { - u_int8_t version; -#define PFSYNC_VERSION 4 - u_int8_t af; - u_int8_t action; -#define PFSYNC_ACT_CLR 0 /* clear all states */ -#define PFSYNC_ACT_INS 1 /* insert state */ -#define PFSYNC_ACT_UPD 2 /* update state */ -#define PFSYNC_ACT_DEL 3 /* delete state */ -#define PFSYNC_ACT_UPD_C 4 /* "compressed" state update */ -#define PFSYNC_ACT_DEL_C 5 /* "compressed" state delete */ -#define PFSYNC_ACT_INS_F 6 /* insert fragment */ -#define PFSYNC_ACT_DEL_F 7 /* delete fragments */ -#define PFSYNC_ACT_UREQ 8 /* request "uncompressed" state */ -#define PFSYNC_ACT_BUS 9 /* Bulk Update Status */ -#define PFSYNC_ACT_TDB_UPD 10 /* TDB replay counter update */ -#define PFSYNC_ACT_MAX 11 - u_int8_t count; - u_int8_t pf_chksum[PF_MD5_DIGEST_LENGTH]; +/* + * EOF + */ + +struct pfsync_eof { + u_int8_t hmac[PFSYNC_HMAC_LEN]; } __packed; -#define PFSYNC_BULKPACKETS 1 /* # of packets per timeout */ -#define PFSYNC_MAX_BULKTRIES 12 -#define PFSYNC_HDRLEN sizeof(struct pfsync_header) -#define PFSYNC_ACTIONS \ - "CLR ST", "INS ST", "UPD ST", "DEL ST", \ - "UPD ST COMP", "DEL ST COMP", "INS FR", "DEL FR", \ - "UPD REQ", "BLK UPD STAT", "TDB UPD" +#define PFSYNC_HDRLEN sizeof(struct pfsync_header) -#define PFSYNC_DFLTTL 255 + + +/* + * Names for PFSYNC sysctl objects + */ +#define PFSYNCCTL_STATS 1 /* PFSYNC stats */ +#define PFSYNCCTL_MAXID 2 + +#define PFSYNCCTL_NAMES { \ + { 0, 0 }, \ + { "stats", CTLTYPE_STRUCT }, \ +} struct pfsyncstats { u_int64_t pfsyncs_ipackets; /* total input packets, IPv4 */ @@ -206,39 +269,43 @@ struct pfsyncreq { }; #ifdef _KERNEL + +/* + * this shows where a pf state is with respect to the syncing. + */ +#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 + void pfsync_input(struct mbuf *, ...); -int pfsync_clear_states(u_int32_t, char *); -int pfsync_pack_state(u_int8_t, struct pf_state *, int); int pfsync_sysctl(int *, u_int, void *, size_t *, void *, size_t); -void pfsync_state_export(struct pfsync_state *, - struct pf_state *); #define PFSYNC_SI_IOCTL 0x01 #define PFSYNC_SI_CKSUM 0x02 +#define PFSYNC_SI_ACK 0x04 int pfsync_state_import(struct pfsync_state *, u_int8_t); +void pfsync_state_export(struct pfsync_state *, + struct pf_state *); + +void pfsync_insert_state(struct pf_state *); +void pfsync_update_state(struct pf_state *); +void pfsync_delete_state(struct pf_state *); +void pfsync_clear_states(u_int32_t, const char *); + +void pfsync_update_tdb(struct tdb *, int); +void pfsync_delete_tdb(struct tdb *); + +int pfsync_defer(struct pf_state *, struct mbuf *); -#define pfsync_insert_state(st) do { \ - if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) || \ - (st->key[PF_SK_WIRE]->proto == IPPROTO_PFSYNC)) \ - st->sync_flags |= PFSTATE_NOSYNC; \ - else if (!st->sync_flags) \ - pfsync_pack_state(PFSYNC_ACT_INS, (st), \ - PFSYNC_FLAG_COMPRESS); \ - st->sync_flags &= ~PFSTATE_FROMSYNC; \ -} while (0) -#define pfsync_update_state(st) do { \ - if (!st->sync_flags) \ - pfsync_pack_state(PFSYNC_ACT_UPD, (st), \ - PFSYNC_FLAG_COMPRESS); \ - st->sync_flags &= ~PFSTATE_FROMSYNC; \ -} while (0) -#define pfsync_delete_state(st) do { \ - if (!st->sync_flags) \ - pfsync_pack_state(PFSYNC_ACT_DEL, (st), \ - PFSYNC_FLAG_COMPRESS); \ -} while (0) -int pfsync_update_tdb(struct tdb *, int); +int pfsync_up(void); +int pfsync_state_in_use(struct pf_state *); #endif #endif /* _NET_IF_PFSYNC_H_ */ -- cgit v1.2.3