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.
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.
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
19 * @brief Structures and prototypes for the RADIUS sniffer.
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>
26 RCSIDH(radsniff_h, "$Id$")
28 #include <sys/types.h>
29 #include <netinet/in.h>
31 #include <pcap/pcap.h>
32 #include <freeradius-devel/libradius.h>
33 #include <freeradius-devel/pcap.h>
34 #include <freeradius-devel/event.h>
36 #ifdef HAVE_COLLECTDC_H
37 # include <collectd/client.h>
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.
52 #define DEBUG2(fmt, ...) if (fr_debug_flag > 2) fprintf(fr_log_fp , fmt "\n", ## __VA_ARGS__)
54 #define DEBUG(fmt, ...) if (fr_debug_flag > 1) fprintf(fr_log_fp , fmt "\n", ## __VA_ARGS__)
56 #define INFO(fmt, ...) if (fr_debug_flag > 0) fprintf(fr_log_fp , fmt "\n", ## __VA_ARGS__)
58 #define ERROR(fmt, ...) fr_perror("radsniff: " fmt, ## __VA_ARGS__)
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))
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__)
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);
81 #ifdef HAVE_COLLECTDC_H
82 RS_STATS_OUT_COLLECTD = 1,
87 typedef struct rs rs_t;
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;
94 typedef struct rs_counters {
95 uint64_t type[PW_CODE_MAX];
98 /** Stats for a single interval
100 * And interval is defined as the time between a call to the stats output function.
102 typedef struct rs_latency {
103 int intervals; //!< Number of stats intervals.
105 double latency_smoothed; //!< Smoothed moving average.
106 uint64_t latency_smoothed_count; //!< Number of CMA datapoints processed.
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
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
126 long double latency_total; //!< Total latency between requests/responses in the
128 double latency_average; //!< Average latency (this iteration).
130 double latency_high; //!< Latency high water mark.
131 double latency_low; //!< Latency low water mark.
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;
149 /** One set of statistics
152 typedef struct rs_stats {
153 int intervals; //!< Number of stats intervals.
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.
160 struct timeval quiet; //!< We may need to 'mute' the stats if libpcap starts
161 //!< dropping packets, or we run out of memory.
164 /** Wrapper for RADIUS_PACKET
166 * Allows an event to be associated with a request packet. This is required because we need to disarm
167 * the event timer when a response is received, so we don't erroneously log the response as lost.
169 typedef struct rs_request {
170 uint64_t id; //!< Monotonically increasing packet counter.
171 fr_event_t *event; //!< Event created when we received the original request.
173 struct timeval when; //!< Time when the packet was received, or next time an event
175 fr_pcap_t *in; //!< PCAP handle the original request was received on.
176 RADIUS_PACKET *packet; //!< The original packet.
177 RADIUS_PACKET *expect; //!< Request/response.
178 RADIUS_PACKET *linked; //!< The subsequent response or forwarded request the packet
179 //!< was linked against.
181 uint64_t rt_req; //!< Number of times we saw the same request packet.
182 uint64_t rt_rsp; //!< Number of times we saw a retransmitted response
184 rs_latency_t *stats_req; //!< Latency entry for the request type.
185 rs_latency_t *stats_rsp; //!< Latency entry for the request type.
187 bool silent_cleanup; //!< Cleanup was forced before normal expiry period,
188 //!< ignore stats about packet loss.
190 VALUE_PAIR *link_vps; //!< VALUE_PAIRs used to link retransmissions.
192 bool in_request_tree; //!< Whether the request is currently in the request tree.
193 bool in_link_tree; //!< Whether the request is currently in the linked tree.
196 /** Statistic write/print event
199 typedef struct rs_event {
200 fr_event_list_t *list; //!< The event list.
202 fr_pcap_t *in; //!< PCAP handle event occurred on.
203 fr_pcap_t *out; //!< Where to write output.
205 rs_stats_t *stats; //!< Where to write stats.
208 /** FD data which gets passed to callbacks
211 typedef struct rs_update {
212 fr_event_list_t *list; //!< List to insert new event into.
214 fr_pcap_t *in; //!< Linked list of PCAP handles to check for drops.
215 rs_stats_t *stats; //!< Stats to process.
220 bool from_file; //!< Were reading pcap data from files.
221 bool from_dev; //!< Were reading pcap data from devices.
222 bool from_stdin; //!< Were reading pcap data from stdin.
223 bool to_file; //!< Were writing pcap data to files.
224 bool to_stdout; //!< Were writing pcap data to stdout.
226 bool daemonize; //!< Daemonize and write PID out to file.
227 char const *pidfile; //!< File to write PID to.
229 bool from_auto; //!< From list was auto-generated.
230 bool promiscuous; //!< Capture in promiscuous mode.
231 bool print_packet; //!< Print packet info, disabled with -W
232 bool decode_attrs; //!< Whether we should decode attributes in the request
234 bool verify_udp_checksum; //!< Check UDP checksum in packets.
236 char const *radius_secret; //!< Secret to decode encrypted attributes.
238 char *pcap_filter; //!< PCAP filter string applied to live capture devices.
240 char *list_attributes; //!< Raw attribute filter string.
241 DICT_ATTR const *list_da[RS_MAX_ATTRS]; //!< Output CSV with these attribute values.
244 char *link_attributes; //!< Names of DICT_ATTRs to use for rtx.
245 DICT_ATTR const *link_da[RS_MAX_ATTRS]; //!< DICT_ATTRs to link on.
246 int link_da_num; //!< Number of rtx DICT_ATTRs.
248 char const *filter_request; //!< Raw request filter string.
249 char const *filter_response; //!< Raw response filter string.
251 VALUE_PAIR *filter_request_vps; //!< Sorted filter vps.
252 VALUE_PAIR *filter_response_vps; //!< Sorted filter vps.
253 PW_CODE filter_request_code; //!< Filter request packets by code.
254 PW_CODE filter_response_code; //!< Filter response packets by code.
256 rs_status_t event_flags; //!< Events we log and capture on.
257 rs_packet_logger_t logger; //!< Packet logger
259 int buffer_pkts; //!< Size of the ring buffer to setup for live capture.
260 uint64_t limit; //!< Maximum number of packets to capture
263 int interval; //!< Time between stats updates in seconds.
264 stats_out_t out; //!< Where to write stats.
265 int timeout; //!< Maximum length of time we wait for a response.
267 #ifdef HAVE_COLLECTDC_H
268 char const *collectd; //!< Collectd server/port/unixsocket
269 char const *prefix; //!< Prefix collectd stats with this value.
270 lcc_connection_t *handle; //!< Collectd client handle.
271 rs_stats_tmpl_t *tmpl; //!< The stats templates we created on startup.
276 #ifdef HAVE_COLLECTDC_H
278 /** Callback for processing stats values.
281 typedef void (*rs_stats_cb_t)(rs_t *conf, rs_stats_value_tmpl_t *tmpl);
282 struct rs_stats_value_tmpl {
283 void *src; //!< Pointer to source field in struct. Must be set by
284 //!< stats_collectdc_init caller.
285 int type; //!< Stats type.
286 rs_stats_cb_t cb; //!< Callback used to process stats
287 void *dst; //!< Pointer to dst field in value struct. Must be set
288 //!< by stats_collectdc_init caller.
293 * This gets processed to turn radsniff stats structures into collectd lcc_value_list_t structures.
297 rs_stats_value_tmpl_t *value_tmpl; //!< Value template
298 void *stats; //!< Struct containing the raw stats to process
299 lcc_value_list_t *value; //!< Collectd stats struct to populate
301 rs_stats_tmpl_t *next; //!< Next...
305 * collectd.c - Registration and processing functions
307 rs_stats_tmpl_t *rs_stats_collectd_init_latency(TALLOC_CTX *ctx, rs_stats_tmpl_t **out, rs_t *conf,
308 char const *type, rs_latency_t *stats, PW_CODE code);
309 void rs_stats_collectd_do_stats(rs_t *conf, rs_stats_tmpl_t *tmpls, struct timeval *now);
310 int rs_stats_collectd_open(rs_t *conf);
311 int rs_stats_collectd_close(rs_t *conf);