1 /*-
2  * Copyright (c) 2004-2005 Gleb Smirnoff <glebius@FreeBSD.org>
3  * Copyright (c) 2001-2003 Roman V. Palagin <romanp@unshadow.net>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *	 $SourceForge: ng_netflow.h,v 1.26 2004/09/04 15:44:55 glebius Exp $
28  *	 $FreeBSD: src/sys/netgraph/netflow/ng_netflow.h,v 1.10 2007/03/28 13:59:13 glebius Exp $
29  */
30 
31 #ifndef	_NG_NETFLOW_H_
32 #define	_NG_NETFLOW_H_
33 
34 #define NG_NETFLOW_NODE_TYPE	"netflow"
35 #define NGM_NETFLOW_COOKIE	1137078102
36 
37 #define	NG_NETFLOW_MAXIFACES	USHRT_MAX
38 
39 /* Hook names */
40 
41 #define	NG_NETFLOW_HOOK_DATA	"iface"
42 #define	NG_NETFLOW_HOOK_OUT	"out"
43 #define NG_NETFLOW_HOOK_EXPORT	"export"
44 
45 /* Netgraph commands understood by netflow node */
46 enum {
47     NGM_NETFLOW_INFO = 1|NGM_READONLY|NGM_HASREPLY,	/* get node info */
48     NGM_NETFLOW_IFINFO = 2|NGM_READONLY|NGM_HASREPLY,	/* get iface info */
49     NGM_NETFLOW_SHOW = 3|NGM_READONLY|NGM_HASREPLY,	/* show ip cache flow */
50     NGM_NETFLOW_SETDLT		= 4,	/* set data-link type */
51     NGM_NETFLOW_SETIFINDEX	= 5, 	/* set interface index */
52     NGM_NETFLOW_SETTIMEOUTS	= 6, 	/* set active/inactive flow timeouts */
53 };
54 
55 /* This structure is returned by the NGM_NETFLOW_INFO message */
56 struct ng_netflow_info {
57 	uint64_t	nfinfo_bytes;		/* accounted bytes */
58 	uint32_t	nfinfo_packets;		/* accounted packets */
59 	uint32_t	nfinfo_used;		/* used cache records */
60 	uint32_t	nfinfo_alloc_failed;	/* failed allocations */
61 	uint32_t	nfinfo_export_failed;	/* failed exports */
62 	uint32_t	nfinfo_act_exp;		/* active expiries */
63 	uint32_t	nfinfo_inact_exp;	/* inactive expiries */
64 	uint32_t	nfinfo_inact_t;		/* flow inactive timeout */
65 	uint32_t	nfinfo_act_t;		/* flow active timeout */
66 };
67 
68 /* This structure is returned by the NGM_NETFLOW_IFINFO message */
69 struct ng_netflow_ifinfo {
70 	uint32_t	ifinfo_packets;	/* number of packets for this iface */
71 	uint8_t		ifinfo_dlt;	/* Data Link Type, DLT_XXX */
72 #define	MAXDLTNAMELEN	20
73 	u_int16_t	ifinfo_index;	/* connected iface index */
74 };
75 
76 
77 /* This structure is passed to NGM_NETFLOW_SETDLT message */
78 struct ng_netflow_setdlt {
79 	uint16_t iface;		/* which iface dlt change */
80 	uint8_t  dlt;			/* DLT_XXX from bpf.h */
81 };
82 
83 /* This structure is passed to NGM_NETFLOW_SETIFINDEX */
84 struct ng_netflow_setifindex {
85 	u_int16_t iface;		/* which iface index change */
86 	u_int16_t index;		/* new index */
87 };
88 
89 /* This structure is passed to NGM_NETFLOW_SETTIMEOUTS */
90 struct ng_netflow_settimeouts {
91 	uint32_t	inactive_timeout;	/* flow inactive timeout */
92 	uint32_t	active_timeout;		/* flow active timeout */
93 };
94 
95 /* This is unique data, which identifies flow */
96 struct flow_rec {
97 	struct in_addr	r_src;
98 	struct in_addr	r_dst;
99 	union {
100 		struct {
101 			uint16_t	s_port;	/* source TCP/UDP port */
102 			uint16_t	d_port; /* destination TCP/UDP port */
103 		} dir;
104 		uint32_t both;
105 	} ports;
106 	union {
107 		struct {
108 			u_char		prot;	/* IP protocol */
109 			u_char		tos;	/* IP TOS */
110 			uint16_t	i_ifx;	/* input interface index */
111 		} i;
112 		uint32_t all;
113 	} misc;
114 };
115 
116 #define	r_ip_p	misc.i.prot
117 #define	r_tos	misc.i.tos
118 #define	r_i_ifx	misc.i.i_ifx
119 #define r_misc	misc.all
120 #define r_ports	ports.both
121 #define r_sport	ports.dir.s_port
122 #define r_dport	ports.dir.d_port
123 
124 /* A flow entry which accumulates statistics */
125 struct flow_entry_data {
126 	struct flow_rec		r;
127 	struct in_addr		next_hop;
128 	uint16_t		fle_o_ifx;	/* output interface index */
129 #define				fle_i_ifx	r.misc.i.i_ifx
130 	uint8_t		dst_mask;	/* destination route mask bits */
131 	uint8_t		src_mask;	/* source route mask bits */
132 	u_long			packets;
133 	u_long			bytes;
134 	long			first;	/* uptime on first packet */
135 	long			last;	/* uptime on last packet */
136 	u_char			tcp_flags;	/* cumulative OR */
137 };
138 
139 /*
140  * How many flow records we will transfer at once
141  * without overflowing socket receive buffer
142  */
143 #define NREC_AT_ONCE		1000
144 #define NGRESP_SIZE		(sizeof(struct ngnf_flows) + (NREC_AT_ONCE * \
145 				sizeof(struct flow_entry_data)))
146 #define SORCVBUF_SIZE		(NGRESP_SIZE + 2 * sizeof(struct ng_mesg))
147 
148 /* This struct is returned to userland, when "show cache ip flow" */
149 struct ngnf_flows {
150 	uint32_t		nentries;
151 	uint32_t		last;
152 	struct flow_entry_data	entries[0];
153 };
154 
155 /* Everything below is for kernel */
156 
157 #ifdef _KERNEL
158 
159 struct flow_entry {
160 	struct flow_entry_data	f;
161 	TAILQ_ENTRY(flow_entry)	fle_hash;	/* entries in hash slot */
162 };
163 
164 /* Parsing declarations */
165 
166 /* Parse the info structure */
167 #define	NG_NETFLOW_INFO_TYPE	{			\
168 	{ "Bytes",	&ng_parse_uint64_type },	\
169 	{ "Packets",	&ng_parse_uint32_type },	\
170 	{ "Records used",	&ng_parse_uint32_type },\
171 	{ "Failed allocations",	&ng_parse_uint32_type },\
172 	{ "Failed exports",	&ng_parse_uint32_type },\
173 	{ "Active expiries",	&ng_parse_uint32_type },\
174 	{ "Inactive expiries",	&ng_parse_uint32_type },\
175 	{ "Inactive timeout",	&ng_parse_uint32_type },\
176 	{ "Active timeout",	&ng_parse_uint32_type },\
177 	{ NULL }					\
178 }
179 
180 /* Parse the ifinfo structure */
181 #define NG_NETFLOW_IFINFO_TYPE	{			\
182 	{ "packets",	&ng_parse_uint32_type },	\
183 	{ "data link type", &ng_parse_uint8_type },	\
184 	{ "index", &ng_parse_uint16_type },		\
185 	{ NULL }					\
186 }
187 
188 /* Parse the setdlt structure */
189 #define	NG_NETFLOW_SETDLT_TYPE {			\
190 	{ "iface",	&ng_parse_uint16_type },	\
191 	{ "dlt",	&ng_parse_uint8_type  },	\
192 	{ NULL }					\
193 }
194 
195 /* Parse the setifindex structure */
196 #define	NG_NETFLOW_SETIFINDEX_TYPE {			\
197 	{ "iface",	&ng_parse_uint16_type },	\
198 	{ "index",	&ng_parse_uint16_type },	\
199 	{ NULL }					\
200 }
201 
202 /* Parse the settimeouts structure */
203 #define NG_NETFLOW_SETTIMEOUTS_TYPE {			\
204 	{ "inactive",	&ng_parse_uint32_type },	\
205 	{ "active",	&ng_parse_uint32_type },	\
206 	{ NULL }					\
207 }
208 
209 /* Private hook data */
210 struct ng_netflow_iface {
211 	hook_p		hook;		/* NULL when disconnected */
212 	hook_p		out;		/* NULL when no bypass hook */
213 	struct ng_netflow_ifinfo	info;
214 };
215 
216 typedef struct ng_netflow_iface *iface_p;
217 typedef struct ng_netflow_ifinfo *ifinfo_p;
218 
219 /* Structure describing our flow engine */
220 struct netflow {
221 	node_p			node;		/* link to the node itself */
222 	hook_p			export;		/* export data goes there */
223 
224 	struct ng_netflow_info	info;
225 	struct callout		exp_callout;	/* expiry periodic job */
226 
227 	/*
228 	 * Flow entries are allocated in uma(9) zone zone. They are
229 	 * indexed by hash hash. Each hash element consist of tailqueue
230 	 * head and mutex to protect this element.
231 	 */
232 #define	CACHESIZE			(65536*4)
233 #define	CACHELOWAT			(CACHESIZE * 3/4)
234 #define	CACHEHIGHWAT			(CACHESIZE * 9/10)
235 	uma_zone_t		zone;
236 	struct flow_hash_entry	*hash;
237 
238 	/*
239 	 * NetFlow data export
240 	 *
241 	 * export_item is a data item, it has an mbuf with cluster
242 	 * attached to it. A thread detaches export_item from priv
243 	 * and works with it. If the export is full it is sent, and
244 	 * a new one is allocated. Before exiting thread re-attaches
245 	 * its current item back to priv. If there is item already,
246 	 * current incomplete datagram is sent.
247 	 * export_mtx is used for attaching/detaching.
248 	 */
249 	item_p			export_item;
250 	struct mtx		export_mtx;
251 	uint32_t		flow_seq;	/* current flow sequence */
252 
253 	struct ng_netflow_iface	ifaces[NG_NETFLOW_MAXIFACES];
254 };
255 
256 typedef struct netflow *priv_p;
257 
258 /* Header of a small list in hash cell */
259 struct flow_hash_entry {
260 	struct mtx		mtx;
261 	TAILQ_HEAD(fhead, flow_entry) head;
262 };
263 
264 #define	ERROUT(x)	{ error = (x); goto done; }
265 
266 /* Prototypes for netflow.c */
267 int	ng_netflow_cache_init(priv_p);
268 void	ng_netflow_cache_flush(priv_p);
269 void	ng_netflow_copyinfo(priv_p, struct ng_netflow_info *);
270 timeout_t ng_netflow_expire;
271 int	ng_netflow_flow_add(priv_p, struct ip *, iface_p, struct ifnet *);
272 int	ng_netflow_flow_show(priv_p, uint32_t last, struct ng_mesg *);
273 
274 #endif	/* _KERNEL */
275 #endif	/* _NG_NETFLOW_H_ */
276