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