7dc8ea79f5f109f2f0a594eedbe534d06f3880f8
[freeradius.git] / src / include / radsniff.h
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 if 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$
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$")
27
28 #include <sys/types.h>
29 #include <netinet/in.h>
30
31 #include <pcap/pcap.h>
32 #include <freeradius-devel/libradius.h>
33 #include <freeradius-devel/pcap.h>
34 #include <freeradius-devel/event.h>
35
36 #ifdef HAVE_COLLECTDC_H
37 #  include <collectd/client.h>
38 #endif
39
40 #define RS_DEFAULT_PREFIX       "radsniff"      //!< Default instance
41 #define RS_DEFAULT_SECRET       "testing123"    //!< Default secret
42 #define RS_DEFAULT_TIMEOUT      5200            //!< Standard timeout of 5s + 300ms to cover network latency
43 #define RS_FORCE_YIELD          1000            //!< Service another descriptor every X number of packets
44 #define RS_RETRANSMIT_MAX       5               //!< Maximum number of times we expect to see a packet retransmitted
45 #define RS_MAX_ATTRS            50              //!< Maximum number of attributes we can filter on.
46 #define RS_SOCKET_REOPEN_DELAY  5000            //!< How long we delay re-opening a collectd socket.
47
48 /*
49  *      Logging macros
50  */
51 #undef DEBUG2
52 #define DEBUG2(fmt, ...)        if (fr_debug_flag > 2) fprintf(fr_log_fp , fmt "\n", ## __VA_ARGS__)
53 #undef DEBUG
54 #define DEBUG(fmt, ...)         if (fr_debug_flag > 1) fprintf(fr_log_fp , fmt "\n", ## __VA_ARGS__)
55 #undef INFO
56 #define INFO(fmt, ...)          if (fr_debug_flag > 0) fprintf(fr_log_fp , fmt "\n", ## __VA_ARGS__)
57
58 #define ERROR(fmt, ...)         fr_perror("radsniff: " fmt, ## __VA_ARGS__)
59
60 #define RIDEBUG_ENABLED()       (conf->print_packet && (fr_debug_flag > 0))
61 #define RDEBUG_ENABLED()        (conf->print_packet && (fr_debug_flag > 1))
62 #define RDEBUG_ENABLED2()       (conf->print_packet && (fr_debug_flag > 2))
63
64 #define REDEBUG(fmt, ...)       if (conf->print_packet) fr_perror("%s (%" PRIu64 ") " fmt , timestr, count, ## __VA_ARGS__)
65 #define RIDEBUG(fmt, ...)       if (conf->print_packet && (fr_debug_flag > 0)) fprintf(fr_log_fp , "%s (%" PRIu64 ") " fmt "\n", timestr, count, ## __VA_ARGS__)
66 #define RDEBUG(fmt, ...)        if (conf->print_packet && (fr_debug_flag > 1)) fprintf(fr_log_fp , "%s (%" PRIu64 ") " fmt "\n", timestr, count, ## __VA_ARGS__)
67 #define RDEBUG2(fmt, ...)       if (conf->print_packet && (fr_debug_flag > 2)) fprintf(fr_log_fp , "%s (%" PRIu64 ") " fmt "\n", timestr, count, ## __VA_ARGS__)
68
69 typedef enum {
70         RS_NORMAL       = 0x01,
71         RS_UNLINKED     = 0x02,
72         RS_RTX          = 0x04,
73         RS_REUSED       = 0x08,
74         RS_ERROR        = 0x10,
75         RS_LOST         = 0x20
76 } rs_status_t;
77
78 typedef void (*rs_packet_logger_t)(uint64_t count, rs_status_t status, fr_pcap_t *handle, RADIUS_PACKET *packet,
79                                    struct timeval *elapsed, struct timeval *latency, bool response, bool body);
80 typedef enum {
81 #ifdef HAVE_COLLECTDC_H
82         RS_STATS_OUT_COLLECTD = 1,
83 #endif
84         RS_STATS_OUT_STDIO
85 } stats_out_t;
86
87 typedef struct rs rs_t;
88
89 #ifdef HAVE_COLLECTDC_H
90 typedef struct rs_stats_tmpl rs_stats_tmpl_t;
91 typedef struct rs_stats_value_tmpl rs_stats_value_tmpl_t;
92 #endif
93
94 typedef struct rs_counters {
95         uint64_t type[PW_CODE_MAX];
96 } rs_counters_t;
97
98 /** Stats for a single interval
99  *
100  * And interval is defined as the time between a call to the stats output function.
101  */
102 typedef struct rs_latency {
103         int                     intervals;                      //!< Number of stats intervals.
104
105         double                  latency_smoothed;               //!< Smoothed moving average.
106         uint64_t                latency_smoothed_count;         //!< Number of CMA datapoints processed.
107
108         struct {
109                 uint64_t                received_total;         //!< Total received over interval.
110                 uint64_t                linked_total;           //!< Total request/response pairs over interval.
111                 uint64_t                unlinked_total;         //!< Total unlinked over interval.
112                 uint64_t                reused_total;           //!< Total reused over interval.
113                 uint64_t                lost_total;             //!< Total packets definitely lost in this interval.
114                 uint64_t                rt_total[RS_RETRANSMIT_MAX + 1];        //!< Number of RTX until complete
115                                                                                 //!< over interval.
116
117
118                 double                  received;               //!< Number of this type of packet we've received.
119                 double                  linked;                 //!< Number of request/response pairs
120                 double                  unlinked;               //!< Response with no request.
121                 double                  reused;                 //!< ID re-used too quickly.
122                 double                  lost;                   //!< Never got a response to a request.
123                 double                  rt[RS_RETRANSMIT_MAX + 1];      //!< Number of times we saw the same
124                                                                         //!< request packet.
125
126                 long double             latency_total;          //!< Total latency between requests/responses in the
127                                                                 //!< interval.
128                 double                  latency_average;        //!< Average latency (this iteration).
129
130                 double                  latency_high;           //!< Latency high water mark.
131                 double                  latency_low;            //!< Latency low water mark.
132         } interval;
133 } rs_latency_t;
134
135 typedef struct rs_malformed {
136         uint64_t                min_length_packet;
137         uint64_t                min_length_field;
138         uint64_t                min_length_mimatch;
139         uint64_t                header_overflow;
140         uint64_t                invalid_attribute;
141         uint64_t                attribute_too_short;
142         uint64_t                attribute_overflow;
143         uint64_t                ma_invalid_length;
144         uint64_t                attribute_underflow;
145         uint64_t                too_many_attributes;
146         uint64_t                ma_missing;
147 } rs_malformed_t;
148
149 /** One set of statistics
150  *
151  */
152 typedef struct rs_stats {
153         int                     intervals;              //!< Number of stats intervals.
154
155         rs_latency_t            exchange[PW_CODE_MAX];  //!< We end up allocating ~16K, but memory is cheap so
156                                                         //!< what the hell.  This is required because instances of
157                                                         //!< FreeRADIUS delay Access-Rejects, which would artificially
158                                                         //!< increase latency stats for Access-Requests.
159
160         struct timeval          quiet;                  //!< We may need to 'mute' the stats if libpcap starts
161                                                         //!< dropping packets, or we run out of memory.
162 } rs_stats_t;
163
164 typedef struct rs_capture {
165         struct pcap_pkthdr      *header;                //!< PCAP packet header.
166         uint8_t                 *data;                  //!< PCAP packet data.
167 } rs_capture_t;
168
169 /** Wrapper for RADIUS_PACKET
170  *
171  * Allows an event to be associated with a request packet.  This is required because we need to disarm
172  * the event timer when a response is received, so we don't erroneously log the response as lost.
173  */
174 typedef struct rs_request {
175         uint64_t                id;                     //!< Monotonically increasing packet counter.
176         fr_event_t              *event;                 //!< Event created when we received the original request.
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