1 /* $OpenBSD: if_pfsync.h,v 1.30 2006/10/31 14:49:01 henning 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 struct pfsync_state_scrub { 52 u_int16_t pfss_flags; 53 u_int8_t pfss_ttl; /* stashed TTL */ 54 #define PFSYNC_SCRUB_FLAG_VALID 0x01 55 u_int8_t scrub_flag; 56 u_int32_t pfss_ts_mod; /* timestamp modulation */ 57 } __packed; 58 59 struct pfsync_state_host { 60 struct pf_addr addr; 61 u_int16_t port; 62 u_int16_t pad[3]; 63 } __packed; 64 65 struct pfsync_state_peer { 66 struct pfsync_state_scrub scrub; /* state is scrubbed */ 67 u_int32_t seqlo; /* Max sequence number sent */ 68 u_int32_t seqhi; /* Max the other end ACKd + win */ 69 u_int32_t seqdiff; /* Sequence number modulator */ 70 u_int16_t max_win; /* largest window (pre scaling) */ 71 u_int16_t mss; /* Maximum segment size option */ 72 u_int8_t state; /* active state level */ 73 u_int8_t wscale; /* window scaling factor */ 74 u_int8_t pad[6]; 75 } __packed; 76 77 struct pfsync_state { 78 u_int32_t id[2]; 79 char ifname[IFNAMSIZ]; 80 struct pfsync_state_host lan; 81 struct pfsync_state_host gwy; 82 struct pfsync_state_host ext; 83 struct pfsync_state_peer src; 84 struct pfsync_state_peer dst; 85 struct pf_addr rt_addr; 86 u_int32_t rule; 87 u_int32_t anchor; 88 u_int32_t nat_rule; 89 u_int32_t creation; 90 u_int32_t expire; 91 u_int32_t packets[2][2]; 92 u_int32_t bytes[2][2]; 93 u_int32_t creatorid; 94 sa_family_t af; 95 u_int8_t proto; 96 u_int8_t direction; 97 u_int8_t log; 98 u_int8_t allow_opts; 99 u_int8_t timeout; 100 u_int8_t sync_flags; 101 u_int8_t updates; 102 } __packed; 103 104 #define PFSYNC_FLAG_COMPRESS 0x01 105 #define PFSYNC_FLAG_STALE 0x02 106 107 struct pfsync_state_upd { 108 u_int32_t id[2]; 109 struct pfsync_state_peer src; 110 struct pfsync_state_peer dst; 111 u_int32_t creatorid; 112 u_int32_t expire; 113 u_int8_t timeout; 114 u_int8_t updates; 115 u_int8_t pad[6]; 116 } __packed; 117 118 struct pfsync_state_del { 119 u_int32_t id[2]; 120 u_int32_t creatorid; 121 struct { 122 u_int8_t state; 123 } src; 124 struct { 125 u_int8_t state; 126 } dst; 127 u_int8_t pad[2]; 128 } __packed; 129 130 struct pfsync_state_upd_req { 131 u_int32_t id[2]; 132 u_int32_t creatorid; 133 u_int32_t pad; 134 } __packed; 135 136 struct pfsync_state_clr { 137 char ifname[IFNAMSIZ]; 138 u_int32_t creatorid; 139 u_int32_t pad; 140 } __packed; 141 142 struct pfsync_state_bus { 143 u_int32_t creatorid; 144 u_int32_t endtime; 145 u_int8_t status; 146 #define PFSYNC_BUS_START 1 147 #define PFSYNC_BUS_END 2 148 u_int8_t pad[7]; 149 } __packed; 150 151 #ifdef _KERNEL 152 153 union sc_statep { 154 struct pfsync_state *s; 155 struct pfsync_state_upd *u; 156 struct pfsync_state_del *d; 157 struct pfsync_state_clr *c; 158 struct pfsync_state_bus *b; 159 struct pfsync_state_upd_req *r; 160 }; 161 162 union sc_tdb_statep { 163 struct pfsync_tdb *t; 164 }; 165 166 extern int pfsync_sync_ok; 167 168 struct pfsync_softc { 169 struct ifnet sc_if; 170 struct ifnet *sc_sync_ifp; 171 172 struct ip_moptions sc_imo; 173 struct callout sc_tmo; 174 struct callout sc_tdb_tmo; 175 struct callout sc_bulk_tmo; 176 struct callout sc_bulkfail_tmo; 177 struct in_addr sc_sync_peer; 178 struct in_addr sc_sendaddr; 179 struct mbuf *sc_mbuf; /* current cumulative mbuf */ 180 struct mbuf *sc_mbuf_net; /* current cumulative mbuf */ 181 struct mbuf *sc_mbuf_tdb; /* dito for TDB updates */ 182 union sc_statep sc_statep; 183 union sc_statep sc_statep_net; 184 union sc_tdb_statep sc_statep_tdb; 185 u_int32_t sc_ureq_received; 186 u_int32_t sc_ureq_sent; 187 struct pf_state *sc_bulk_send_next; 188 struct pf_state *sc_bulk_terminator; 189 int sc_bulk_tries; 190 int sc_maxcount; /* number of states in mtu */ 191 int sc_maxupdates; /* number of updates/state */ 192 LIST_ENTRY(pfsync_softc) sc_next; 193 }; 194 195 extern struct pfsync_softc *pfsyncif; 196 #endif 197 198 199 struct pfsync_header { 200 u_int8_t version; 201 #define PFSYNC_VERSION 3 202 u_int8_t af; 203 u_int8_t action; 204 #define PFSYNC_ACT_CLR 0 /* clear all states */ 205 #define PFSYNC_ACT_INS 1 /* insert state */ 206 #define PFSYNC_ACT_UPD 2 /* update state */ 207 #define PFSYNC_ACT_DEL 3 /* delete state */ 208 #define PFSYNC_ACT_UPD_C 4 /* "compressed" state update */ 209 #define PFSYNC_ACT_DEL_C 5 /* "compressed" state delete */ 210 #define PFSYNC_ACT_INS_F 6 /* insert fragment */ 211 #define PFSYNC_ACT_DEL_F 7 /* delete fragments */ 212 #define PFSYNC_ACT_UREQ 8 /* request "uncompressed" state */ 213 #define PFSYNC_ACT_BUS 9 /* Bulk Update Status */ 214 #define PFSYNC_ACT_TDB_UPD 10 /* TDB replay counter update */ 215 #define PFSYNC_ACT_MAX 11 216 u_int8_t count; 217 u_int8_t pf_chksum[PF_MD5_DIGEST_LENGTH]; 218 } __packed; 219 220 #define PFSYNC_BULKPACKETS 1 /* # of packets per timeout */ 221 #define PFSYNC_MAX_BULKTRIES 12 222 #define PFSYNC_HDRLEN sizeof(struct pfsync_header) 223 #define PFSYNC_ACTIONS \ 224 "CLR ST", "INS ST", "UPD ST", "DEL ST", \ 225 "UPD ST COMP", "DEL ST COMP", "INS FR", "DEL FR", \ 226 "UPD REQ", "BLK UPD STAT", "TDB UPD" 227 228 #define PFSYNC_DFLTTL 255 229 230 struct pfsyncstats { 231 u_int64_t pfsyncs_ipackets; /* total input packets, IPv4 */ 232 u_int64_t pfsyncs_ipackets6; /* total input packets, IPv6 */ 233 u_int64_t pfsyncs_badif; /* not the right interface */ 234 u_int64_t pfsyncs_badttl; /* TTL is not PFSYNC_DFLTTL */ 235 u_int64_t pfsyncs_hdrops; /* packets shorter than hdr */ 236 u_int64_t pfsyncs_badver; /* bad (incl unsupp) version */ 237 u_int64_t pfsyncs_badact; /* bad action */ 238 u_int64_t pfsyncs_badlen; /* data length does not match */ 239 u_int64_t pfsyncs_badauth; /* bad authentication */ 240 u_int64_t pfsyncs_stale; /* stale state */ 241 u_int64_t pfsyncs_badval; /* bad values */ 242 u_int64_t pfsyncs_badstate; /* insert/lookup failed */ 243 244 u_int64_t pfsyncs_opackets; /* total output packets, IPv4 */ 245 u_int64_t pfsyncs_opackets6; /* total output packets, IPv6 */ 246 u_int64_t pfsyncs_onomem; /* no memory for an mbuf */ 247 u_int64_t pfsyncs_oerrors; /* ip output error */ 248 }; 249 250 /* 251 * Configuration structure for SIOCSETPFSYNC SIOCGETPFSYNC 252 */ 253 struct pfsyncreq { 254 char pfsyncr_syncdev[IFNAMSIZ]; 255 struct in_addr pfsyncr_syncpeer; 256 int pfsyncr_maxupdates; 257 int pfsyncr_authlevel; 258 }; 259 #define SIOCSETPFSYNC _IOW('i', 247, struct ifreq) 260 #define SIOCGETPFSYNC _IOWR('i', 248, struct ifreq) 261 262 263 #define pf_state_peer_hton(s,d) do { \ 264 (d)->seqlo = htonl((s)->seqlo); \ 265 (d)->seqhi = htonl((s)->seqhi); \ 266 (d)->seqdiff = htonl((s)->seqdiff); \ 267 (d)->max_win = htons((s)->max_win); \ 268 (d)->mss = htons((s)->mss); \ 269 (d)->state = (s)->state; \ 270 (d)->wscale = (s)->wscale; \ 271 if ((s)->scrub) { \ 272 (d)->scrub.pfss_flags = \ 273 htons((s)->scrub->pfss_flags & PFSS_TIMESTAMP); \ 274 (d)->scrub.pfss_ttl = (s)->scrub->pfss_ttl; \ 275 (d)->scrub.pfss_ts_mod = htonl((s)->scrub->pfss_ts_mod);\ 276 (d)->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID; \ 277 } \ 278 } while (0) 279 280 #define pf_state_peer_ntoh(s,d) do { \ 281 (d)->seqlo = ntohl((s)->seqlo); \ 282 (d)->seqhi = ntohl((s)->seqhi); \ 283 (d)->seqdiff = ntohl((s)->seqdiff); \ 284 (d)->max_win = ntohs((s)->max_win); \ 285 (d)->mss = ntohs((s)->mss); \ 286 (d)->state = (s)->state; \ 287 (d)->wscale = (s)->wscale; \ 288 if ((s)->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && \ 289 (d)->scrub != NULL) { \ 290 (d)->scrub->pfss_flags = \ 291 ntohs((s)->scrub.pfss_flags) & PFSS_TIMESTAMP; \ 292 (d)->scrub->pfss_ttl = (s)->scrub.pfss_ttl; \ 293 (d)->scrub->pfss_ts_mod = ntohl((s)->scrub.pfss_ts_mod);\ 294 } \ 295 } while (0) 296 297 #define pf_state_host_hton(s,d) do { \ 298 bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \ 299 (d)->port = (s)->port; \ 300 } while (0) 301 302 #define pf_state_host_ntoh(s,d) do { \ 303 bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \ 304 (d)->port = (s)->port; \ 305 } while (0) 306 307 #define pf_state_counter_hton(s,d) do { \ 308 d[0] = htonl((s>>32)&0xffffffff); \ 309 d[1] = htonl(s&0xffffffff); \ 310 } while (0) 311 312 #define pf_state_counter_ntoh(s,d) do { \ 313 d = ntohl(s[0]); \ 314 d = d<<32; \ 315 d += ntohl(s[1]); \ 316 } while (0) 317 318 #ifdef _KERNEL 319 void pfsync_input(struct mbuf *, ...); 320 int pfsync_clear_states(u_int32_t, char *); 321 int pfsync_pack_state(u_int8_t, struct pf_state *, int); 322 #define pfsync_insert_state(st) do { \ 323 if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) || \ 324 (st->proto == IPPROTO_PFSYNC)) \ 325 st->sync_flags |= PFSTATE_NOSYNC; \ 326 else if (!st->sync_flags) \ 327 pfsync_pack_state(PFSYNC_ACT_INS, (st), \ 328 PFSYNC_FLAG_COMPRESS); \ 329 st->sync_flags &= ~PFSTATE_FROMSYNC; \ 330 } while (0) 331 #define pfsync_update_state(st) do { \ 332 if (!st->sync_flags) \ 333 pfsync_pack_state(PFSYNC_ACT_UPD, (st), \ 334 PFSYNC_FLAG_COMPRESS); \ 335 st->sync_flags &= ~PFSTATE_FROMSYNC; \ 336 } while (0) 337 #define pfsync_delete_state(st) do { \ 338 if (!st->sync_flags) \ 339 pfsync_pack_state(PFSYNC_ACT_DEL, (st), \ 340 PFSYNC_FLAG_COMPRESS); \ 341 } while (0) 342 #endif 343 344 #endif /* _NET_IF_PFSYNC_H_ */ 345