summaryrefslogtreecommitdiff
path: root/sys/net/if_pfsync.h
blob: 70d6e1811a0a6c6e468c661fe127d237a5361ef6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*	$OpenBSD: if_pfsync.h,v 1.7 2003/12/28 17:18:58 mcbride Exp $	*/

/*
 * Copyright (c) 2001 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _NET_IF_PFSYNC_H_
#define _NET_IF_PFSYNC_H_

struct pfsync_state_scrub {
	u_int16_t	pfss_flags;
	u_int8_t	pfss_ttl;	/* stashed TTL		*/
	u_int8_t	scrub_flag;
	u_int32_t	pfss_ts_mod;	/* timestamp modulation	*/
} __packed;

struct pfsync_state_host {
	struct pf_addr	addr;
	u_int16_t	port;
	u_int16_t	pad[3];
} __packed;

struct pfsync_state_peer {
	struct pfsync_state_scrub scrub;	/* state is scrubbed	*/
	u_int32_t	seqlo;		/* Max sequence number sent	*/
	u_int32_t	seqhi;		/* Max the other end ACKd + win	*/
	u_int32_t	seqdiff;	/* Sequence number modulator	*/
	u_int16_t	max_win;	/* largest window (pre scaling)	*/
	u_int16_t	mss;		/* Maximum segment size option	*/
	u_int8_t	state;		/* active state level		*/
	u_int8_t	wscale;		/* window scaling factor	*/
	u_int8_t	scrub_flag;
	u_int8_t	pad[5];
} __packed;

struct pfsync_state {
	u_int64_t	 id;
	struct pfsync_state_host lan;
	struct pfsync_state_host gwy;
	struct pfsync_state_host ext;
	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];
	u_int32_t	 bytes[2];
	u_int32_t	 creatorid;
	sa_family_t	 af;
	u_int8_t	 proto;
	u_int8_t	 direction;
	u_int8_t	 log;
	u_int8_t	 allow_opts;
	u_int8_t	 timeout;
	u_int8_t	 sync_flags;
	u_int8_t	 updates;
} __packed;

struct pfsync_state_upd {
	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		updates;
	u_int8_t		pad[7];
} __packed;

struct pfsync_state_del {
	u_int64_t		id;
	u_int32_t		creatorid;
	struct {
		u_int8_t	state;
	} src;
	struct {
		u_int8_t	state;
	} dst;
	u_int8_t		pad[2];
} __packed;

struct pfsync_state_upd_req {
	u_int64_t		id;
	u_int32_t		creatorid;
	u_int32_t		pad;
} __packed;

struct pfsync_state_clr {
	u_int32_t		creatorid;
	u_int32_t		pad;
} __packed;

#ifdef _KERNEL

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_upd_req	*r;
};

struct pfsync_softc {
	struct ifnet		 sc_if;
	struct ifnet		*sc_sync_ifp;

	struct ip_moptions	 sc_imo;
	struct timeout		 sc_tmo;
	struct in_addr		 sc_sendaddr;
	struct mbuf		*sc_mbuf;	/* current cummulative mbuf */
	struct mbuf		*sc_mbuf_net;	/* current cummulative mbuf */
	union sc_statep		 sc_statep;
	union sc_statep		 sc_statep_net;
	int			 sc_maxcount;	/* number of states in mtu */
	int			 sc_maxupdates;	/* number of updates/state */
};
#endif


struct pfsync_header {
	u_int8_t version;
#define	PFSYNC_VERSION	1
	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_MAX		9
	u_int8_t count;
} __packed;

#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"

#define PFSYNC_DFLTTL		255

struct pfsyncstats {
	u_long	pfsyncs_ipackets;	/* total input packets, IPv4 */
	u_long	pfsyncs_ipackets6;	/* total input packets, IPv6 */
	u_long	pfsyncs_badif;		/* not the right interface */
	u_long	pfsyncs_badttl;		/* TTL is not PFSYNC_DFLTTL */
	u_long	pfsyncs_hdrops;		/* packets shorter than header */
	u_long	pfsyncs_badver;		/* bad (incl unsupp) version */
	u_long	pfsyncs_badact;		/* bad action */
	u_long	pfsyncs_badlen;		/* data length does not match */
	u_long	pfsyncs_badauth;	/* bad authentication */
	u_long	pfsyncs_badstate;	/* insert/lookup failed */

	u_long	pfsyncs_opackets;	/* total output packets, IPv4 */
	u_long	pfsyncs_opackets6;	/* total output packets, IPv6 */
	u_long	pfsyncs_onomem;		/* no memory for an mbuf for a send */
	u_long	pfsyncs_oerrors;	/* ip output error */
};

/*
 * Configuration structure for SIOCSETPFSYNC SIOCGETPFSYNC
 */
struct pfsyncreq {
	char	pfsyncr_syncif[IFNAMSIZ];
	int	pfsyncr_maxupdates;
	int	pfsyncr_authlevel;
};
#define SIOCSETPFSYNC	_IOW('i', 247, struct ifreq)
#define SIOCGETPFSYNC	_IOWR('i', 248, struct ifreq)


#define pf_state_peer_hton(s,d) do {		\
	(d)->seqlo = htonl((s)->seqlo);		\
	(d)->seqhi = htonl((s)->seqhi);		\
	(d)->seqdiff = htonl((s)->seqdiff);	\
	(d)->max_win = htons((s)->max_win);	\
	(d)->mss = htons((s)->mss);		\
	(d)->state = (s)->state;		\
	(d)->wscale = (s)->wscale;		\
} while (0)

#define pf_state_peer_ntoh(s,d) do {		\
	(d)->seqlo = ntohl((s)->seqlo);		\
	(d)->seqhi = ntohl((s)->seqhi);		\
	(d)->seqdiff = ntohl((s)->seqdiff);	\
	(d)->max_win = ntohs((s)->max_win);	\
	(d)->mss = ntohs((s)->mss);		\
	(d)->state = (s)->state;		\
	(d)->wscale = (s)->wscale;		\
} while (0)

#define pf_state_host_hton(s,d) do {				\
	bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr));	\
	(d)->port = htons((s)->port);				\
} while (0)

#define pf_state_host_ntoh(s,d) do {				\
	bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr));	\
	(d)->port = ntohs((s)->port);				\
} while (0)

#ifdef _KERNEL
void pfsync_input(struct mbuf *, ...);
int pfsync_clear_states(u_int32_t);
int pfsync_pack_state(u_int8_t, struct pf_state *, int);
#define pfsync_insert_state(st)	do {				\
	if (st->rule.ptr->rule_flag & PFRULE_NOSYNC)		\
		st->sync_flags |= PFSTATE_NOSYNC;		\
	else if (!st->sync_flags)				\
		pfsync_pack_state(PFSYNC_ACT_INS, (st), 1);	\
	st->sync_flags &= ~PFSTATE_FROMSYNC;			\
} while (0)
#define pfsync_update_state(st) do {				\
	if (!st->sync_flags)					\
		pfsync_pack_state(PFSYNC_ACT_UPD, (st), 1);	\
	st->sync_flags &= ~PFSTATE_FROMSYNC;			\
} while (0)
#define pfsync_delete_state(st) do {				\
	if (!st->sync_flags)					\
		pfsync_pack_state(PFSYNC_ACT_DEL, (st), 1);	\
	st->sync_flags &= ~PFSTATE_FROMSYNC;			\
} while (0)
#endif

#endif /* _NET_IF_PFSYNC_H_ */