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 typedef struct rs_capture {
165 struct pcap_pkthdr *header; //!< PCAP packet header.
166 uint8_t *data; //!< PCAP packet data.
169 /** Wrapper for RADIUS_PACKET
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.
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.
178 struct timeval when; //!< Time when the packet was received, or next time an event
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.
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.
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
194 rs_latency_t *stats_req; //!< Latency entry for the request type.
195 rs_latency_t *stats_rsp; //!< Latency entry for the request type.
197 bool silent_cleanup; //!< Cleanup was forced before normal expiry period,
198 //!< ignore stats about packet loss.
200 VALUE_PAIR *link_vps; //!< VALUE_PAIRs used to link retransmissions.
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.
206 /** Statistic write/print event
209 typedef struct rs_event {
210 fr_event_list_t *list; //!< The event list.
212 fr_pcap_t *in; //!< PCAP handle event occurred on.
213 fr_pcap_t *out; //!< Where to write output.
215 rs_stats_t *stats; //!< Where to write stats.
218 /** FD data which gets passed to callbacks
221 typedef struct rs_update {
222 fr_event_list_t *list; //!< List to insert new event into.
224 fr_pcap_t *in; //!< Linked list of PCAP handles to check for drops.
225 rs_stats_t *stats; //!< Stats to process.
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.
236 bool daemonize; //!< Daemonize and write PID out to file.
237 char const *pidfile; //!< File to write PID to.
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
244 bool verify_udp_checksum; //!< Check UDP checksum in packets.
246 char const *radius_secret; //!< Secret to decode encrypted attributes.
248 char *pcap_filter; //!< PCAP filter string applied to live capture devices.
250 char *list_attributes; //!< Raw attribute filter string.
251 DICT_ATTR const *list_da[RS_MAX_ATTRS]; //!< Output CSV with these attribute values.
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.
258 char const *filter_request; //!< Raw request filter string.
259 char const *filter_response; //!< Raw response filter string.
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.
266 rs_status_t event_flags; //!< Events we log and capture on.
267 rs_packet_logger_t logger; //!< Packet logger
269 int buffer_pkts; //!< Size of the ring buffer to setup for live capture.
270 uint64_t limit; //!< Maximum number of packets to capture
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.
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.
286 #ifdef HAVE_COLLECTDC_H
288 /** Callback for processing stats values.
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.
303 * This gets processed to turn radsniff stats structures into collectd lcc_value_list_t structures.
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
311 rs_stats_tmpl_t *next; //!< Next...
315 * collectd.c - Registration and processing functions
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);