1 /* $OpenBSD: if_pfsync.h,v 1.31 2007/05/31 04:11:42 mcbride Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef _NET_IF_PFSYNC_H_ 30 #define _NET_IF_PFSYNC_H_ 31 32 #include <sys/ioccom.h> 33 34 /* 35 * pfvar.h is required to get struct pf_addr. Also kdump and other utilities 36 * blindly include header files to try to get all the ioctl constants and 37 * buildworld will fail without this. We need a better way XXX 38 */ 39 #ifndef _NET_PFVAR_H_ 40 #include "pfvar.h" 41 #endif 42 43 /* Reserved SPI numbers */ 44 #define SPI_LOCAL_USE 0 45 #define SPI_RESERVED_MIN 1 46 #define SPI_RESERVED_MAX 255 47 48 49 #define PFSYNC_ID_LEN sizeof(u_int64_t) 50 51 #define PFSYNC_FLAG_COMPRESS 0x01 52 #define PFSYNC_FLAG_STALE 0x02 53 54 struct pfsync_tdb { 55 u_int32_t spi; 56 union sockaddr_union dst; 57 u_int32_t rpl; 58 u_int64_t cur_bytes; 59 u_int8_t sproto; 60 u_int8_t updates; 61 u_int8_t pad[2]; 62 } __packed; 63 64 struct pfsync_state_upd { 65 u_int32_t id[2]; 66 struct pfsync_state_peer src; 67 struct pfsync_state_peer dst; 68 u_int32_t creatorid; 69 u_int32_t expire; 70 u_int8_t timeout; 71 u_int8_t updates; 72 u_int8_t pad[6]; 73 } __packed; 74 75 struct pfsync_state_del { 76 u_int32_t id[2]; 77 u_int32_t creatorid; 78 struct { 79 u_int8_t state; 80 } src; 81 struct { 82 u_int8_t state; 83 } dst; 84 u_int8_t pad[2]; 85 } __packed; 86 87 struct pfsync_state_upd_req { 88 u_int32_t id[2]; 89 u_int32_t creatorid; 90 u_int32_t pad; 91 } __packed; 92 93 struct pfsync_state_clr { 94 char ifname[IFNAMSIZ]; 95 u_int32_t creatorid; 96 u_int32_t pad; 97 } __packed; 98 99 struct pfsync_state_bus { 100 u_int32_t creatorid; 101 u_int32_t endtime; 102 u_int8_t status; 103 #define PFSYNC_BUS_START 1 104 #define PFSYNC_BUS_END 2 105 u_int8_t pad[7]; 106 } __packed; 107 108 #ifdef _KERNEL 109 110 union sc_statep { 111 struct pfsync_state *s; 112 struct pfsync_state_upd *u; 113 struct pfsync_state_del *d; 114 struct pfsync_state_clr *c; 115 struct pfsync_state_bus *b; 116 struct pfsync_state_upd_req *r; 117 }; 118 119 union sc_tdb_statep { 120 struct pfsync_tdb *t; 121 }; 122 123 extern int pfsync_sync_ok; 124 125 struct pfsync_softc { 126 struct ifnet sc_if; 127 struct ifnet *sc_sync_ifp; 128 129 struct ip_moptions sc_imo; 130 struct callout sc_tmo; 131 struct callout sc_tdb_tmo; 132 struct callout sc_bulk_tmo; 133 struct callout sc_bulkfail_tmo; 134 struct in_addr sc_sync_peer; 135 struct in_addr sc_sendaddr; 136 struct mbuf *sc_mbuf; /* current cumulative mbuf */ 137 struct mbuf *sc_mbuf_net; /* current cumulative mbuf */ 138 struct mbuf *sc_mbuf_tdb; /* dito for TDB updates */ 139 union sc_statep sc_statep; 140 union sc_statep sc_statep_net; 141 union sc_tdb_statep sc_statep_tdb; 142 u_int32_t sc_ureq_received; 143 u_int32_t sc_ureq_sent; 144 struct pf_state *sc_bulk_send_next; 145 struct pf_state *sc_bulk_terminator; 146 int sc_bulk_tries; 147 int sc_maxcount; /* number of states in mtu */ 148 int sc_maxupdates; /* number of updates/state */ 149 LIST_ENTRY(pfsync_softc) sc_next; 150 }; 151 152 extern struct pfsync_softc *pfsyncif; 153 #endif 154 155 156 struct pfsync_header { 157 u_int8_t version; 158 #define PFSYNC_VERSION 3 159 u_int8_t af; 160 u_int8_t action; 161 #define PFSYNC_ACT_CLR 0 /* clear all states */ 162 #define PFSYNC_ACT_INS 1 /* insert state */ 163 #define PFSYNC_ACT_UPD 2 /* update state */ 164 #define PFSYNC_ACT_DEL 3 /* delete state */ 165 #define PFSYNC_ACT_UPD_C 4 /* "compressed" state update */ 166 #define PFSYNC_ACT_DEL_C 5 /* "compressed" state delete */ 167 #define PFSYNC_ACT_INS_F 6 /* insert fragment */ 168 #define PFSYNC_ACT_DEL_F 7 /* delete fragments */ 169 #define PFSYNC_ACT_UREQ 8 /* request "uncompressed" state */ 170 #define PFSYNC_ACT_BUS 9 /* Bulk Update Status */ 171 #define PFSYNC_ACT_TDB_UPD 10 /* TDB replay counter update */ 172 #define PFSYNC_ACT_MAX 11 173 u_int8_t count; 174 u_int8_t pf_chksum[PF_MD5_DIGEST_LENGTH]; 175 } __packed; 176 177 #define PFSYNC_BULKPACKETS 1 /* # of packets per timeout */ 178 #define PFSYNC_MAX_BULKTRIES 12 179 #define PFSYNC_HDRLEN sizeof(struct pfsync_header) 180 #define PFSYNC_ACTIONS \ 181 "CLR ST", "INS ST", "UPD ST", "DEL ST", \ 182 "UPD ST COMP", "DEL ST COMP", "INS FR", "DEL FR", \ 183 "UPD REQ", "BLK UPD STAT", "TDB UPD" 184 185 #define PFSYNC_DFLTTL 255 186 187 struct pfsyncstats { 188 u_int64_t pfsyncs_ipackets; /* total input packets, IPv4 */ 189 u_int64_t pfsyncs_ipackets6; /* total input packets, IPv6 */ 190 u_int64_t pfsyncs_badif; /* not the right interface */ 191 u_int64_t pfsyncs_badttl; /* TTL is not PFSYNC_DFLTTL */ 192 u_int64_t pfsyncs_hdrops; /* packets shorter than hdr */ 193 u_int64_t pfsyncs_badver; /* bad (incl unsupp) version */ 194 u_int64_t pfsyncs_badact; /* bad action */ 195 u_int64_t pfsyncs_badlen; /* data length does not match */ 196 u_int64_t pfsyncs_badauth; /* bad authentication */ 197 u_int64_t pfsyncs_stale; /* stale state */ 198 u_int64_t pfsyncs_badval; /* bad values */ 199 u_int64_t pfsyncs_badstate; /* insert/lookup failed */ 200 201 u_int64_t pfsyncs_opackets; /* total output packets, IPv4 */ 202 u_int64_t pfsyncs_opackets6; /* total output packets, IPv6 */ 203 u_int64_t pfsyncs_onomem; /* no memory for an mbuf */ 204 u_int64_t pfsyncs_oerrors; /* ip output error */ 205 }; 206 207 /* 208 * Configuration structure for SIOCSETPFSYNC SIOCGETPFSYNC 209 */ 210 struct pfsyncreq { 211 char pfsyncr_syncdev[IFNAMSIZ]; 212 struct in_addr pfsyncr_syncpeer; 213 int pfsyncr_maxupdates; 214 int pfsyncr_authlevel; 215 }; 216 #define SIOCSETPFSYNC _IOW('i', 247, struct ifreq) 217 #define SIOCGETPFSYNC _IOWR('i', 248, struct ifreq) 218 219 /* for copies to/from network */ 220 #define pf_state_peer_hton(s,d) do { \ 221 (d)->seqlo = htonl((s)->seqlo); \ 222 (d)->seqhi = htonl((s)->seqhi); \ 223 (d)->seqdiff = htonl((s)->seqdiff); \ 224 (d)->max_win = htons((s)->max_win); \ 225 (d)->mss = htons((s)->mss); \ 226 (d)->state = (s)->state; \ 227 (d)->wscale = (s)->wscale; \ 228 if ((s)->scrub) { \ 229 (d)->scrub.pfss_flags = \ 230 htons((s)->scrub->pfss_flags & PFSS_TIMESTAMP); \ 231 (d)->scrub.pfss_ttl = (s)->scrub->pfss_ttl; \ 232 (d)->scrub.pfss_ts_mod = htonl((s)->scrub->pfss_ts_mod);\ 233 (d)->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID; \ 234 } \ 235 } while (0) 236 237 #define pf_state_peer_ntoh(s,d) do { \ 238 (d)->seqlo = ntohl((s)->seqlo); \ 239 (d)->seqhi = ntohl((s)->seqhi); \ 240 (d)->seqdiff = ntohl((s)->seqdiff); \ 241 (d)->max_win = ntohs((s)->max_win); \ 242 (d)->mss = ntohs((s)->mss); \ 243 (d)->state = (s)->state; \ 244 (d)->wscale = (s)->wscale; \ 245 if ((s)->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && \ 246 (d)->scrub != NULL) { \ 247 (d)->scrub->pfss_flags = \ 248 ntohs((s)->scrub.pfss_flags) & PFSS_TIMESTAMP; \ 249 (d)->scrub->pfss_ttl = (s)->scrub.pfss_ttl; \ 250 (d)->scrub->pfss_ts_mod = ntohl((s)->scrub.pfss_ts_mod);\ 251 } \ 252 } while (0) 253 254 #define pf_state_host_hton(s,d) do { \ 255 bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \ 256 (d)->port = (s)->port; \ 257 } while (0) 258 259 #define pf_state_host_ntoh(s,d) do { \ 260 bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \ 261 (d)->port = (s)->port; \ 262 } while (0) 263 264 #define pf_state_counter_hton(s,d) do { \ 265 d[0] = htonl((s>>32)&0xffffffff); \ 266 d[1] = htonl(s&0xffffffff); \ 267 } while (0) 268 269 #define pf_state_counter_ntoh(s,d) do { \ 270 d = ntohl(s[0]); \ 271 d = d<<32; \ 272 d += ntohl(s[1]); \ 273 } while (0) 274 275 #ifdef _KERNEL 276 void pfsync_input(struct mbuf *, ...); 277 int pfsync_clear_states(u_int32_t, char *); 278 int pfsync_pack_state(u_int8_t, struct pf_state *, int); 279 #define pfsync_insert_state(st) do { \ 280 if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) || \ 281 (st->state_key->proto == IPPROTO_PFSYNC)) \ 282 st->sync_flags |= PFSTATE_NOSYNC; \ 283 else if (!st->sync_flags) \ 284 pfsync_pack_state(PFSYNC_ACT_INS, (st), \ 285 PFSYNC_FLAG_COMPRESS); \ 286 st->sync_flags &= ~PFSTATE_FROMSYNC; \ 287 } while (0) 288 #define pfsync_update_state(st) do { \ 289 if (!st->sync_flags) \ 290 pfsync_pack_state(PFSYNC_ACT_UPD, (st), \ 291 PFSYNC_FLAG_COMPRESS); \ 292 st->sync_flags &= ~PFSTATE_FROMSYNC; \ 293 } while (0) 294 #define pfsync_delete_state(st) do { \ 295 if (!st->sync_flags) \ 296 pfsync_pack_state(PFSYNC_ACT_DEL, (st), \ 297 PFSYNC_FLAG_COMPRESS); \ 298 } while (0) 299 #endif 300 301 #endif /* _NET_IF_PFSYNC_H_ */ 302