50601419f66c5b40717d9a08a74d66978c22e378
[dragonfly.git] / sys / net / pf / if_pfsync.h
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_ */