1 /*
2  *   This program is is free software; you can redistribute it and/or modify
3  *   it under the terms of the GNU General Public License, version 2 of the
4  *   License as published by the Free Software Foundation.
5  *
6  *   This program is distributed in the hope that it will be useful,
7  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
8  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  *   GNU General Public License for more details.
10  *
11  *   You should have received a copy of the GNU General Public License
12  *   along with this program; if not, write to the Free Software
13  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
14  */
15 
16 /**
17  * $Id: c909ecdf0733173ce62b08bbfad3043323e4dd12 $
18  * @file radsniff.h
19  * @brief Structures and prototypes for the RADIUS sniffer.
20  *
21  * @copyright 2013 Arran Cudbard-Bell <arran.cudbardb@freeradius.org>
22  * @copyright 2006 The FreeRADIUS server project
23  * @copyright 2006 Nicolas Baradakis <nicolas.baradakis@cegetel.net>
24  */
25 
26 RCSIDH(radsniff_h, "$Id: c909ecdf0733173ce62b08bbfad3043323e4dd12 $")
27 
28 #include <sys/types.h>
29 
30 #include <freeradius-devel/libradius.h>
31 #include <freeradius-devel/pcap.h>
32 #include <freeradius-devel/event.h>
33 
34 #ifdef HAVE_COLLECTDC_H
35 #  include <collectd/client.h>
36 #endif
37 
38 #define RS_DEFAULT_PREFIX	"radsniff"	//!< Default instance
39 #define RS_DEFAULT_SECRET	"testing123"	//!< Default secret
40 #define RS_DEFAULT_TIMEOUT	5200		//!< Standard timeout of 5s + 300ms to cover network latency
41 #define RS_FORCE_YIELD		1000		//!< Service another descriptor every X number of packets
42 #define RS_RETRANSMIT_MAX	5		//!< Maximum number of times we expect to see a packet retransmitted
43 #define RS_MAX_ATTRS		50		//!< Maximum number of attributes we can filter on.
44 #define RS_SOCKET_REOPEN_DELAY  5000		//!< How long we delay re-opening a collectd socket.
45 
46 /*
47  *	Logging macros
48  */
49 #undef DEBUG2
50 #define DEBUG2(fmt, ...)	if (fr_debug_lvl > 2) fprintf(fr_log_fp , fmt "\n", ## __VA_ARGS__)
51 #undef DEBUG
52 #define DEBUG(fmt, ...)		if (fr_debug_lvl > 1) fprintf(fr_log_fp , fmt "\n", ## __VA_ARGS__)
53 #undef INFO
54 #define INFO(fmt, ...)		if (fr_debug_lvl > 0) fprintf(fr_log_fp , fmt "\n", ## __VA_ARGS__)
55 
56 #define ERROR(fmt, ...)		fr_perror("radsniff: " fmt, ## __VA_ARGS__)
57 
58 #define RIDEBUG_ENABLED()	(conf->print_packet && (fr_debug_lvl > 0))
59 #define RDEBUG_ENABLED()	(conf->print_packet && (fr_debug_lvl > 1))
60 #define RDEBUG_ENABLED2()	(conf->print_packet && (fr_debug_lvl > 2))
61 
62 #define REDEBUG(fmt, ...)	if (conf->print_packet) fr_perror("%s (%" PRIu64 ") " fmt , timestr, count, ## __VA_ARGS__)
63 #define RIDEBUG(fmt, ...)	if (conf->print_packet && (fr_debug_lvl > 0)) fprintf(fr_log_fp , "%s (%" PRIu64 ") " fmt "\n", timestr, count, ## __VA_ARGS__)
64 #define RDEBUG(fmt, ...)	if (conf->print_packet && (fr_debug_lvl > 1)) fprintf(fr_log_fp , "%s (%" PRIu64 ") " fmt "\n", timestr, count, ## __VA_ARGS__)
65 #define RDEBUG2(fmt, ...)	if (conf->print_packet && (fr_debug_lvl > 2)) fprintf(fr_log_fp , "%s (%" PRIu64 ") " fmt "\n", timestr, count, ## __VA_ARGS__)
66 
67 typedef enum {
68 	RS_NORMAL	= 0x01,
69 	RS_UNLINKED	= 0x02,
70 	RS_RTX		= 0x04,
71 	RS_REUSED	= 0x08,
72 	RS_ERROR	= 0x10,
73 	RS_LOST		= 0x20
74 } rs_status_t;
75 
76 typedef void (*rs_packet_logger_t)(uint64_t count, rs_status_t status, fr_pcap_t *handle, RADIUS_PACKET *packet,
77 				   struct timeval *elapsed, struct timeval *latency, bool response, bool body);
78 typedef enum {
79 #ifdef HAVE_COLLECTDC_H
80 	RS_STATS_OUT_COLLECTD = 1,
81 #endif
82 	RS_STATS_OUT_STDIO
83 } stats_out_t;
84 
85 typedef struct rs rs_t;
86 
87 #ifdef HAVE_COLLECTDC_H
88 typedef struct rs_stats_tmpl rs_stats_tmpl_t;
89 typedef struct rs_stats_value_tmpl rs_stats_value_tmpl_t;
90 #endif
91 
92 typedef struct rs_counters {
93 	uint64_t type[PW_CODE_MAX];
94 } rs_counters_t;
95 
96 /** Stats for a single interval
97  *
98  * And interval is defined as the time between a call to the stats output function.
99  */
100 typedef struct rs_latency {
101 	int			intervals;			//!< Number of stats intervals.
102 
103 	double			latency_smoothed;		//!< Smoothed moving average.
104 	uint64_t		latency_smoothed_count;		//!< Number of CMA datapoints processed.
105 
106 	struct {
107 		uint64_t		received_total;		//!< Total received over interval.
108 		uint64_t		linked_total;		//!< Total request/response pairs over interval.
109 		uint64_t		unlinked_total;		//!< Total unlinked over interval.
110 		uint64_t		reused_total;		//!< Total reused over interval.
111 		uint64_t		lost_total;		//!< Total packets definitely lost in this interval.
112 		uint64_t		rt_total[RS_RETRANSMIT_MAX + 1];	//!< Number of RTX until complete
113 										//!< over interval.
114 
115 
116 		double			received;		//!< Number of this type of packet we've received.
117 		double			linked;			//!< Number of request/response pairs
118 		double			unlinked;		//!< Response with no request.
119 		double			reused;			//!< ID re-used too quickly.
120 		double			lost;			//!< Never got a response to a request.
121 		double			rt[RS_RETRANSMIT_MAX + 1];	//!< Number of times we saw the same
122 									//!< request packet.
123 
124 		long double		latency_total;		//!< Total latency between requests/responses in the
125 								//!< interval.
126 		double			latency_average;	//!< Average latency (this iteration).
127 
128 		double			latency_high;		//!< Latency high water mark.
129 		double			latency_low;		//!< Latency low water mark.
130 	} interval;
131 } rs_latency_t;
132 
133 typedef struct rs_malformed {
134 	uint64_t		min_length_packet;
135 	uint64_t		min_length_field;
136 	uint64_t		min_length_mimatch;
137 	uint64_t		header_overflow;
138 	uint64_t		invalid_attribute;
139 	uint64_t		attribute_too_short;
140 	uint64_t		attribute_overflow;
141 	uint64_t		ma_invalid_length;
142 	uint64_t		attribute_underflow;
143 	uint64_t		too_many_attributes;
144 	uint64_t		ma_missing;
145 } rs_malformed_t;
146 
147 /** One set of statistics
148  *
149  */
150 typedef struct rs_stats {
151 	int			intervals;		//!< Number of stats intervals.
152 
153 	rs_latency_t		exchange[PW_CODE_MAX];  //!< We end up allocating ~16K, but memory is cheap so
154 							//!< what the hell.  This is required because instances of
155 							//!< FreeRADIUS delay Access-Rejects, which would artificially
156 							//!< increase latency stats for Access-Requests.
157 
158 	struct timeval		quiet;			//!< We may need to 'mute' the stats if libpcap starts
159 							//!< dropping packets, or we run out of memory.
160 } rs_stats_t;
161 
162 typedef struct rs_capture {
163 	struct pcap_pkthdr	*header;		//!< PCAP packet header.
164 	uint8_t			*data;			//!< PCAP packet data.
165 } rs_capture_t;
166 
167 /** Wrapper for RADIUS_PACKET
168  *
169  * Allows an event to be associated with a request packet.  This is required because we need to disarm
170  * the event timer when a response is received, so we don't erroneously log the response as lost.
171  */
172 typedef struct rs_request {
173 	uint64_t		id;			//!< Monotonically increasing packet counter.
174 	fr_event_t		*event;			//!< Event created when we received the original request.
175 
176 	bool			logged;			//!< Whether any messages regarding this request were logged.
177 
178 	struct timeval		when;			//!< Time when the packet was received, or next time an event
179 							//!< is scheduled.
180 	fr_pcap_t		*in;			//!< PCAP handle the original request was received on.
181 	RADIUS_PACKET		*packet;		//!< The original packet.
182 	RADIUS_PACKET		*expect;		//!< Request/response.
183 	RADIUS_PACKET		*linked;		//!< The subsequent response or forwarded request the packet
184 							//!< was linked against.
185 
186 
187 	rs_capture_t		capture[RS_RETRANSMIT_MAX];	//!< Buffered request packets (if a response filter
188 								//!< has been applied).
189 	rs_capture_t		*capture_p;			//!< Next packet slot.
190 
191 	uint64_t		rt_req;			//!< Number of times we saw the same request packet.
192 	uint64_t		rt_rsp;			//!< Number of times we saw a retransmitted response
193 							//!< packet.
194 	rs_latency_t		*stats_req;		//!< Latency entry for the request type.
195 	rs_latency_t		*stats_rsp;		//!< Latency entry for the request type.
196 
197 	bool			silent_cleanup;		//!< Cleanup was forced before normal expiry period,
198 							//!< ignore stats about packet loss.
199 
200 	VALUE_PAIR		*link_vps;		//!< VALUE_PAIRs used to link retransmissions.
201 
202 	bool			in_request_tree;	//!< Whether the request is currently in the request tree.
203 	bool			in_link_tree;		//!< Whether the request is currently in the linked tree.
204 } rs_request_t;
205 
206 /** Statistic write/print event
207  *
208  */
209 typedef struct rs_event {
210 	fr_event_list_t		*list;			//!< The event list.
211 
212 	fr_pcap_t		*in;			//!< PCAP handle event occurred on.
213 	fr_pcap_t		*out;			//!< Where to write output.
214 
215 	rs_stats_t		*stats;			//!< Where to write stats.
216 } rs_event_t;
217 
218 /** FD data which gets passed to callbacks
219  *
220  */
221 typedef struct rs_update {
222 	fr_event_list_t		*list;			//!< List to insert new event into.
223 
224 	fr_pcap_t		*in;			//!< Linked list of PCAP handles to check for drops.
225 	rs_stats_t		*stats;			//!< Stats to process.
226 } rs_update_t;
227 
228 
229 struct rs {
230 	bool			from_file;		//!< Were reading pcap data from files.
231 	bool			from_dev;		//!< Were reading pcap data from devices.
232 	bool			from_stdin;		//!< Were reading pcap data from stdin.
233 	bool			to_file;		//!< Were writing pcap data to files.
234 	bool			to_stdout;		//!< Were writing pcap data to stdout.
235 
236 	bool			daemonize;		//!< Daemonize and write PID out to file.
237 	char const		*pidfile;		//!< File to write PID to.
238 
239 	bool			from_auto;		//!< From list was auto-generated.
240 	bool			promiscuous;		//!< Capture in promiscuous mode.
241 	bool			print_packet;		//!< Print packet info, disabled with -W
242 	bool			decode_attrs;		//!< Whether we should decode attributes in the request
243 							//!< and response.
244 	bool			verify_udp_checksum;	//!< Check UDP checksum in packets.
245 
246 	char const		*radius_secret;		//!< Secret to decode encrypted attributes.
247 
248 	char			*pcap_filter;		//!< PCAP filter string applied to live capture devices.
249 
250 	char			*list_attributes;	//!< Raw attribute filter string.
251 	DICT_ATTR const 	*list_da[RS_MAX_ATTRS]; //!< Output CSV with these attribute values.
252 	int			list_da_num;
253 
254 	char			*link_attributes;	//!< Names of DICT_ATTRs to use for rtx.
255 	DICT_ATTR const		*link_da[RS_MAX_ATTRS];	//!< DICT_ATTRs to link on.
256 	int			link_da_num;		//!< Number of rtx DICT_ATTRs.
257 
258 	char const		*filter_request;	//!< Raw request filter string.
259 	char const		*filter_response;	//!< Raw response filter string.
260 
261 	VALUE_PAIR 		*filter_request_vps;	//!< Sorted filter vps.
262 	VALUE_PAIR 		*filter_response_vps;	//!< Sorted filter vps.
263 	PW_CODE			filter_request_code;	//!< Filter request packets by code.
264 	PW_CODE			filter_response_code;	//!< Filter response packets by code.
265 
266 	rs_status_t		event_flags;		//!< Events we log and capture on.
267 	rs_packet_logger_t	logger;			//!< Packet logger
268 
269 	int			buffer_pkts;		//!< Size of the ring buffer to setup for live capture.
270 	uint64_t		limit;			//!< Maximum number of packets to capture
271 
272 	struct {
273 		int			interval;		//!< Time between stats updates in seconds.
274 		stats_out_t		out;			//!< Where to write stats.
275 		int			timeout;		//!< Maximum length of time we wait for a response.
276 
277 #ifdef HAVE_COLLECTDC_H
278 		char const		*collectd;		//!< Collectd server/port/unixsocket
279 		char const		*prefix;		//!< Prefix collectd stats with this value.
280 		lcc_connection_t	*handle;		//!< Collectd client handle.
281 		rs_stats_tmpl_t		*tmpl;			//!< The stats templates we created on startup.
282 #endif
283 	} stats;
284 };
285 
286 #ifdef HAVE_COLLECTDC_H
287 
288 /** Callback for processing stats values.
289  *
290  */
291 typedef void (*rs_stats_cb_t)(rs_t *conf, rs_stats_value_tmpl_t *tmpl);
292 struct rs_stats_value_tmpl {
293 	void			*src;			//!< Pointer to source field in struct. Must be set by
294 							//!< stats_collectdc_init caller.
295 	int			type;			//!< Stats type.
296 	rs_stats_cb_t		cb;			//!< Callback used to process stats
297 	void			*dst;			//!< Pointer to dst field in value struct. Must be set
298 							//!< by stats_collectdc_init caller.
299 };
300 
301 /** Stats templates
302  *
303  * This gets processed to turn radsniff stats structures into collectd lcc_value_list_t structures.
304  */
305 struct rs_stats_tmpl
306 {
307 	rs_stats_value_tmpl_t	*value_tmpl;		//!< Value template
308 	void			*stats;			//!< Struct containing the raw stats to process
309 	lcc_value_list_t	*value;			//!< Collectd stats struct to populate
310 
311 	rs_stats_tmpl_t		*next;			//!< Next...
312 };
313 
314 /*
315  *	collectd.c - Registration and processing functions
316  */
317 rs_stats_tmpl_t *rs_stats_collectd_init_latency(TALLOC_CTX *ctx, rs_stats_tmpl_t **out, rs_t *conf,
318 						char const *type, rs_latency_t *stats, PW_CODE code);
319 void rs_stats_collectd_do_stats(rs_t *conf, rs_stats_tmpl_t *tmpls, struct timeval *now);
320 int rs_stats_collectd_open(rs_t *conf);
321 int rs_stats_collectd_close(rs_t *conf);
322 
323 #endif
324