27RCSID(
"$Id: d9f74306fb7d86bfa34d98c543b382e621de1004 $")
33#include <freeradius-devel/autoconf.h>
34#include <freeradius-devel/radius/list.h>
35#include <freeradius-devel/util/conf.h>
36#include <freeradius-devel/util/event.h>
37#include <freeradius-devel/util/file.h>
38#include <freeradius-devel/util/syserror.h>
39#include <freeradius-devel/util/atexit.h>
40#include <freeradius-devel/util/pair_legacy.h>
41#include <freeradius-devel/util/base16.h>
42#include <freeradius-devel/util/pcap.h>
43#include <freeradius-devel/util/timeval.h>
45#ifdef HAVE_COLLECTDC_H
46# include <collectd/client.h>
51#define RS_ASSERT(_x) if (!(_x) && !fr_cond_assert(_x)) exit(1)
150 if ((chdir(
"/")) < 0) {
158 fp = fopen(pidfile,
"w");
160 fprintf(fp,
"%d\n", (
int) sid);
170 if (isatty(fileno(stdout))) {
171 if (!freopen(
"/dev/null",
"w", stdout)) {
176 if (isatty(fileno(stderr))) {
177 if (!freopen(
"/dev/null",
"w", stderr)) {
183static void rs_tv_add_ms(
struct timeval
const *start,
unsigned long interval,
struct timeval *result) {
184 result->tv_sec = start->tv_sec + (interval / 1000);
185 result->tv_usec = start->tv_usec + ((interval % 1000) * 1000);
187 if (result->tv_usec >
USEC) {
188 result->tv_usec -=
USEC;
205 ret = strftime(
out, len,
"%Y-%m-%d %H:%M:%S",
localtime_r(&t->tv_sec, &result));
213 while (usec < 100000) usec *= 10;
222 char const *start =
out;
237 while ((
inlen > 0) && (outlen > 2)) {
249 if ((*str ==
'\r') || (*str ==
'\n') || ((*str >=
'\x20') && (*str <=
'\x7E'))) {
276 len =
strlcpy(p,
"\"Status\",\"Count\",\"Time\",\"Latency\",\"Type\",\"Interface\","
277 "\"Src IP\",\"Src Port\",\"Dst IP\",\"Dst Port\",\"ID\",", s);
306 fprintf(stdout ,
"%s\n",
buffer);
311 UNUSED struct timeval *elapsed,
struct timeval *latency,
UNUSED bool response,
314 char const *status_str;
318 char src[INET6_ADDRSTRLEN];
319 char dst[INET6_ADDRSTRLEN];
331 (
unsigned int) latency->tv_sec,
332 ((
unsigned int) latency->tv_usec / 1000)) < 0)
return;
341 src, packet->
socket.inet.src_port, dst, packet->
socket.inet.dst_port, packet->
id) < 0)
return;
343 if (
fr_sbuff_in_sprintf(&sbuff,
"%u,%s,%s,%i,%s,%i,%i,", packet->
code, handle->name,
344 src, packet->
socket.inet.src_port, dst, packet->
socket.inet.dst_port, packet->
id) < 0)
return;
353 if (
vp && (
vp->vp_length > 0)) {
360 vp->vp_strvalue,
vp->vp_length);
361 if (slen < 0)
return;
377 fr_sbuff_terminate(&sbuff);
380 fprintf(stdout ,
"%s\n",
buffer);
385 struct timeval *elapsed,
struct timeval *latency,
bool response,
bool body)
390 char src[INET6_ADDRSTRLEN];
391 char dst[INET6_ADDRSTRLEN];
400 char const *status_str;
405 len =
snprintf(p, s,
"** %s ** ", status_str);
412 len =
snprintf(p, s,
"%s Id %i %s:%s:%d %s %s:%i ",
416 response ? dst : src,
417 response ? packet->
socket.inet.dst_port : packet->
socket.inet.src_port,
418 response ?
"<-" :
"->",
419 response ? src : dst ,
420 response ? packet->
socket.inet.src_port : packet->
socket.inet.dst_port);
422 len =
snprintf(p, s,
"%u Id %i %s:%s:%i %s %s:%i ",
426 response ? dst : src,
427 response ? packet->
socket.inet.dst_port : packet->
socket.inet.src_port,
428 response ?
"<-" :
"->",
429 response ? src : dst ,
430 response ? packet->
socket.inet.src_port : packet->
socket.inet.dst_port);
438 (
unsigned int) elapsed->tv_sec, ((
unsigned int) elapsed->tv_usec / 1000));
446 (
unsigned int) latency->tv_sec, ((
unsigned int) latency->tv_usec / 1000));
480 UNUSED struct timeval *elapsed,
UNUSED struct timeval *latency,
bool response,
bool body)
485 char const *packet_type = response ?
"reply" :
"request";
493 DEBUG2(
"Saving %s in %s", packet_type, filename);
500 ERROR(
"Failed opening %s output file.", filename);
518 ERROR(
"Failed closing %s output file.", filename);
531 struct timeval *elapsed,
struct timeval *latency,
532 bool response,
bool body)
536 if (request) request->
logged =
true;
537 conf->
logger(
count, status, handle, packet, list, elapsed, latency, response, body);
555 struct pcap_stat pstats;
557 if (pcap_stats(
in->handle, &pstats) != 0) {
558 ERROR(
"%s failed retrieving pcap stats: %s",
in->name, pcap_geterr(
in->handle));
562 if (pstats.ps_drop -
in->pstats.ps_drop > 0) {
563 ERROR(
"%s dropped %i packets: Buffer exhaustion",
in->name, pstats.ps_drop -
in->pstats.ps_drop);
567 if (pstats.ps_ifdrop -
in->pstats.ps_ifdrop > 0) {
568 ERROR(
"%s dropped %i packets: Interface",
in->name, pstats.ps_ifdrop -
in->pstats.ps_ifdrop);
590 if (stats->
interval.linked_total == 0) {
591 double unk = strtod(
"NAN()", (
char **) NULL);
593 stats->
interval.latency_average = unk;
613 if (stats->
interval.latency_average > 0) {
638 bool have_rt =
false;
642 if (!stats->
interval.received && !have_rt && !stats->
interval.reused)
return;
657 INFO(
"\tAverage : %.3lfms", stats->
interval.latency_average);
668 if (!stats->
interval.rt[i])
continue;
691 if ((stats->
quiet.tv_sec + (stats->
quiet.tv_usec / 1000000.0)) -
692 (now->tv_sec + (now->tv_usec / 1000000.0)) > 0) {
693 INFO(
"Stats muted because of warmup, or previous error");
697 INFO(
"######### Stats Iteration %i #########", stats->
intervals);
699 if (this->
in)
INFO(
"Interface capture rate:");
700 for (in_p = this->
in;
703 struct pcap_stat pstats;
705 if (pcap_stats(in_p->handle, &pstats) != 0) {
706 ERROR(
"%s failed retrieving pcap stats: %s", in_p->name, pcap_geterr(in_p->handle));
710 INFO(
"\t%s%*s: %.3lf/s", in_p->name, (
int) (10 - strlen(in_p->name)),
"",
711 ((
double) (pstats.ps_recv - in_p->pstats.ps_recv)) /
conf->
stats.interval);
719 for (i = 0; i < rs_codes_len; i++) {
733 fprintf(stdout,
"\"Iteration\"");
735 for (in_p = this->
in; in_p; in_p = in_p->next) {
736 fprintf(stdout,
",\"%s PPS\"", in_p->name);
739 for (i = 0; i < rs_codes_len; i++) {
746 ",\"%s lat high (ms)\""
747 ",\"%s lat low (ms)\""
748 ",\"%s lat avg (ms)\""
749 ",\"%s lat ma (ms)\""
764 fprintf(stdout,
",\"%s rtx (%i)\"",
name, j);
766 fprintf(stdout,
",\"%s rtx (%i+)\"",
name, j);
771 fprintf(stdout ,
"\n");
777 char *p =
out, *end =
out + outlen;
779 p +=
snprintf(
out, outlen,
",%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf",
789 if (p >= end)
return -1;
793 if (p >= end)
return -1;
809 ERROR(
"Exceeded line buffer size");
813 for (in_p = this->
in;
816 struct pcap_stat pstats;
818 if (pcap_stats(in_p->handle, &pstats) != 0) {
819 ERROR(
"%s failed retrieving pcap stats: %s", in_p->name, pcap_geterr(in_p->handle));
824 ((
double) (pstats.ps_recv - in_p->pstats.ps_recv)) /
conf->
stats.interval);
825 if (p >= end)
goto oob;
828 for (i = 0; i < rs_codes_len; i++) {
832 if (slen < 0)
goto oob;
835 if (p >= end)
goto oob;
838 fprintf(stdout ,
"%s\n",
buffer);
855 if (!this->done_header) {
857 this->done_header =
true;
862 for (in_p = this->
in;
866 ERROR(
"Muting stats for the next %i milliseconds",
conf->
stats.timeout);
876 if ((stats->
quiet.tv_sec + (stats->
quiet.tv_usec / 1000000.0)) -
877 (now.tv_sec + (now.tv_usec / 1000000.0)) > 0)
goto clear;
879 for (i = 0; i < rs_codes_len; i++) {
884 if (this->body) this->body(
this, stats, &now);
886#ifdef HAVE_COLLECTDC_H
900 for (i = 0; i < rs_codes_len; i++) {
914 ERROR(
"Failed inserting stats interval event");
929 lint = (latency->tv_sec + (latency->tv_usec / 1000000.0)) * 1000;
930 if (lint > stats->
interval.latency_high) {
931 stats->
interval.latency_high = lint;
933 if (!stats->
interval.latency_low || (lint < stats->interval.latency_low)) {
936 stats->
interval.latency_total += (
long double) lint;
941 fr_pcap_t *
in,
struct timeval *now,
bool live)
946 memset(&update, 0,
sizeof(update));
949 update.
stats = stats;
964#ifdef HAVE_COLLECTDC_H
965 case RS_STATS_OUT_COLLECTD:
978 INFO(
"Muting stats for the next %i milliseconds (warmup)",
conf->
stats.timeout);
985 ERROR(
"Failed inserting stats event");
1007 for (i = 0; i < num; i++) {
1103 if ((request->
in->type == PCAP_INTERFACE_IN) && request->
logged) {
1151 if (!event->
out)
return 0;
1193 pcap_dump((
void *)event->
out->dumper, header,
data);
1201 if (!event->
out)
return 0;
1213 if (!(request->
capture_p->
header = talloc(request,
struct pcap_pkthdr)))
return -1;
1218 memcpy(request->
capture_p->
header, header,
sizeof(
struct pcap_pkthdr));
1230 pcap_dump((
void *)event->
out->dumper, header,
data);
1236#define RS_CLEANUP_NOW(_x, _s)\
1238 _x->silent_cleanup = _s;\
1239 _x->when = header->ts;\
1240 rs_packet_cleanup(_x);\
1263 struct timeval elapsed = {0, 0};
1264 struct timeval latency;
1279 static uint64_t captured = 0;
1290 memset(&search, 0,
sizeof(search));
1303 len = fr_pcap_link_layer_offset(
data, header->caplen, event->
in->link_layer);
1305 REDEBUG(
"Failed determining link layer header offset");
1310 version = (p[0] & 0xf0) >> 4;
1314 len = (0x0f & ip->
ip_vhl) * 4;
1325 REDEBUG(
"IP version invalid %i", version);
1333 if ((
size_t) len > header->caplen) {
1334 REDEBUG(
"Packet too small, we require at least %zu bytes, captured %i bytes",
1335 (
size_t) len, header->caplen);
1347 udp_len = ntohs(udp->
len);
1348 actual_len = header->caplen - (p -
data);
1350 if (udp_len > actual_len) {
1351 REDEBUG(
"Packet too small by %zi bytes, UDP header + Payload should be %hu bytes",
1352 udp_len - actual_len, udp_len);
1365 else if (udp_len < actual_len) {
1366 REDEBUG(
"Packet too big by %zi bytes, UDP header + Payload should be %hu bytes",
1367 actual_len - udp_len, udp_len);
1376 if (udp->checksum != expected) {
1377 REDEBUG(
"UDP checksum invalid, packet: 0x%04hx calculated: 0x%04hx",
1378 ntohs(udp->checksum), ntohs(expected));
1392 REDEBUG(
"Failed allocating memory to hold decoded packet");
1399 memcpy(&packet->
data, &p,
sizeof(packet->
data));
1407 packet->
socket.inet.src_ipaddr.
af = AF_INET;
1408 packet->
socket.inet.src_ipaddr.addr.v4.s_addr = ip->ip_src.s_addr;
1410 packet->
socket.inet.dst_ipaddr.
af = AF_INET;
1411 packet->
socket.inet.dst_ipaddr.addr.v4.s_addr = ip->
ip_dst.s_addr;
1413 packet->
socket.inet.src_ipaddr.
af = AF_INET6;
1414 memcpy(packet->
socket.inet.src_ipaddr.addr.v6.s6_addr, ip6->ip_src.s6_addr,
1415 sizeof(packet->
socket.inet.src_ipaddr.addr.v6.s6_addr));
1417 packet->
socket.inet.dst_ipaddr.
af = AF_INET6;
1418 memcpy(packet->
socket.inet.dst_ipaddr.addr.v6.s6_addr, ip6->
ip_dst.s6_addr,
1419 sizeof(packet->
socket.inet.dst_ipaddr.addr.v6.s6_addr));
1422 packet->
socket.inet.src_port = ntohs(udp->
src);
1423 packet->
socket.inet.dst_port = ntohs(udp->
dst);
1429 packet, &decoded, &elapsed, NULL,
false,
false);
1436 switch (packet->
code) {
1455 RDEBUG2(
"Response dropped by filter");
1473 fr_perror(
"Failed verifying packet ID %d", packet->
id);
1541 original->
linked = talloc_steal(original, packet);
1547 REDEBUG(
"Failed inserting new event");
1566 RDEBUG2(
"Original request dropped by filter");
1591 RDEBUG2(
"Request dropped by filter");
1598 switch (packet->
code) {
1611 fr_perror(
"Failed verifying packet ID %d", packet->
id);
1652 REDEBUG(
"Failed allocating memory to hold expected reply");
1666 ERROR(
"Failed extracting RTX linking pairs from request");
1686 if (tuple && (original != tuple)) {
1738 original->
packet = talloc_steal(original, packet);
1749 original->
expect = talloc_steal(original, search.
expect);
1760 original->
in =
event->in;
1766 original->
packet = talloc_steal(original, packet);
1769 original->
expect = talloc_steal(original, search.
expect);
1817 REDEBUG(
"Failed inserting new event");
1844 if (original && original->
linked) {
1863 struct timeval ts_tv;
1878 &elapsed, &latency, response,
true);
1891 print_id = original->
id;
1897 print_pair_list = &decoded;
1902 &elapsed, NULL, response,
true);
1911 if (response && !original) {
1920 INFO(
"Captured %" PRIu64
" packets, exiting...", captured);
1927 static uint64_t
count = 0;
1931 pcap_t *handle =
event->in->handle;
1936 struct pcap_pkthdr *header;
1947 last_sync = now_real;
1953 if ((event->in->type == PCAP_FILE_IN) || (event->in->type == PCAP_STDIO_IN)) {
1954 bool stats_started =
false;
1959 ret = pcap_next_ex(handle, &header, &
data);
1965 DEBUG(
"Done reading packets (%s)", event->in->name);
1975 ERROR(
"Error requesting next packet, got (%i): %s", ret, pcap_geterr(handle));
1983 if (
conf->
stats.interval && !stats_started) {
1985 stats_started =
true;
2003 ret = pcap_next_ex(handle, &header, &
data);
2009 ERROR(
"Error requesting next packet, got (%i): %s", ret, pcap_geterr(handle));
2020 struct timeval wake;
2024 if ((wake.tv_sec != 0) || (wake.tv_usec >= 100000)) {
2025 DEBUG2(
"Waking up in %d.%01u seconds", (
int) wake.tv_sec, (
unsigned int) wake.tv_usec / 100000);
2051 if (ret != 0)
return ret;
2054 if (ret != 0)
return ret;
2066 while ((tok =
strsep(&p,
"\t ,")) != NULL) {
2068 if ((*tok ==
'\t') || (*tok ==
' ') || (*tok ==
'\0')) {
2073 ERROR(
"Too many attributes, maximum allowed is %zu", len);
2080 ERROR(
"Error parsing attribute name \"%s\"", tok);
2104 .allow_compare =
true,
2109 fr_perror(
"Invalid RADIUS filter \"%s\"", filter);
2114 ERROR(
"Empty RADIUS filter '%s'", filter);
2132 while ((tok =
strsep(&p,
"\t ,")) != NULL) {
2135 if ((*tok ==
'\t') || (*tok ==
' ') || (*tok ==
'\0')) {
2141 ERROR(
"Invalid flag \"%s\"", tok);
2158 this->in_request_tree =
false;
2168 this->in_link_tree =
false;
2180#ifdef HAVE_COLLECTDC_H
2188 if (rs_stats_collectd_open(
conf) == 0) {
2189 DEBUG2(
"Stats output socket (re)opened");
2197 false, rs_collectd_reopen, NULL) < 0) {
2198 ERROR(
"Failed inserting re-open event");
2210 if (write(
self_pipe[1], &sig,
sizeof(sig)) < 0) {
2211 ERROR(
"Failed writing signal %s to pipe: %s", strsignal(sig),
fr_syserror(errno));
2220#ifndef HAVE_COLLECTDC_H
2228 ret = read(fd, &sig,
sizeof(sig));
2234 if (ret !=
sizeof(sig)) {
2235 ERROR(
"Failed reading signal from pipe: "
2236 "Expected signal to be %zu bytes but only read %zu byes",
sizeof(sig), ret);
2241#ifdef HAVE_COLLECTDC_H
2243 rs_collectd_reopen(list->tl,
fr_time(), list);
2252 DEBUG2(
"Signalling event loop to exit");
2257 ERROR(
"Unhandled signal %s", strsignal(sig));
2264 FILE *output = status ? stderr : stdout;
2265 fprintf(output,
"Usage: radsniff [options][stats options] -- [pcap files]\n");
2266 fprintf(output,
"options:\n");
2267 fprintf(output,
" -a List all interfaces available for capture.\n");
2268 fprintf(output,
" -c <count> Number of packets to capture.\n");
2269 fprintf(output,
" -C <checksum_type> Enable checksum validation. (Specify 'udp' or 'radius')\n");
2270 fprintf(output,
" -d <raddb> Set configuration directory (defaults to " RADDBDIR
").\n");
2271 fprintf(output,
" -D <dictdir> Set main dictionary directory (defaults to " DICTDIR
").\n");
2272 fprintf(output,
" -e <event>[,<event>] Only log requests with these event flags.\n");
2273 fprintf(output,
" Event may be one of the following:\n");
2274 fprintf(output,
" - received - a request or response.\n");
2275 fprintf(output,
" - norsp - seen for a request.\n");
2276 fprintf(output,
" - rtx - of a request that we've seen before.\n");
2277 fprintf(output,
" - noreq - could be matched with the response.\n");
2278 fprintf(output,
" - reused - ID too soon.\n");
2279 fprintf(output,
" - error - decoding the packet.\n");
2280 fprintf(output,
" -f <filter> PCAP filter (default is 'udp port <port> or <port + 1> or %i'\n",
2282 fprintf(output,
" with extra rules to allow .1Q tagged packets)\n");
2283 fprintf(output,
" -h This help message.\n");
2284 fprintf(output,
" -i <interface> Capture packets from interface (defaults to all if supported).\n");
2285 fprintf(output,
" -I <file> Read packets from <file>\n");
2286 fprintf(output,
" -l <attr>[,<attr>] Output packet sig and a list of attributes.\n");
2287 fprintf(output,
" -L <attr>[,<attr>] Detect retransmissions using these attributes to link requests.\n");
2288 fprintf(output,
" -m Don't put interface(s) into promiscuous mode.\n");
2289 fprintf(output,
" -p <port> Filter packets by port (default is %i).\n",
FR_AUTH_UDP_PORT);
2290 fprintf(output,
" -P <pidfile> Daemonize and write out <pidfile>.\n");
2291 fprintf(output,
" -q Print less debugging information.\n");
2292 fprintf(output,
" -r <filter> RADIUS attribute request filter.\n");
2293 fprintf(output,
" -R <filter> RADIUS attribute response filter.\n");
2294 fprintf(output,
" -s <secret> RADIUS secret.\n");
2295 fprintf(output,
" -S Write PCAP data to stdout.\n");
2296 fprintf(output,
" -t <timeout> Stop after <timeout> seconds.\n");
2297 fprintf(output,
" -v Show program version information and exit.\n");
2298 fprintf(output,
" -w <file> Write output packets to file.\n");
2299 fprintf(output,
" -x Print more debugging information.\n");
2300 fprintf(output,
"stats options:\n");
2301 fprintf(output,
" -W <interval> Periodically write out statistics every <interval> seconds.\n");
2302 fprintf(output,
" -E Print stats in CSV format.\n");
2303 fprintf(output,
" -T <timeout> How many milliseconds before the request is counted as lost "
2305#ifdef HAVE_COLLECTDC_H
2306 fprintf(output,
" -N <prefix> The instance name passed to the collectd plugin.\n");
2307 fprintf(output,
" -O <server> Write statistics to this collectd server.\n");
2309 fprintf(output,
" -Z <output_dir> Dump the packets in <output_dir>/{requests,reply}.${count}.txt\n");
2319 fr_pcap_t *
in = NULL, *in_p;
2320 fr_pcap_t **in_head = &
in;
2321 fr_pcap_t *
out = NULL;
2323 int ret = EXIT_SUCCESS;
2325 char errbuf[PCAP_ERRBUF_SIZE];
2329 unsigned int timeout = 0;
2331 char const *raddb_dir = RADDBDIR;
2332 char const *dict_dir = DICTDIR;
2357 talloc_set_log_stderr();
2372#ifdef HAVE_COLLECTDC_H
2378#ifdef HAVE_COLLECTDC_H
2385 while ((c = getopt(argc, argv,
"ab:c:C:d:D:e:Ef:hi:I:l:L:mp:P:qr:R:s:St:vw:xXW:T:P:N:O:Z:")) != -1) {
2389 pcap_if_t *all_devices = NULL;
2393 if (pcap_findalldevs(&all_devices, errbuf) < 0) {
2394 ERROR(
"Error getting available capture devices: %s", errbuf);
2399 for (dev_p = all_devices;
2401 dev_p = dev_p->next) {
2402 INFO(
"%i.%s", i++, dev_p->name);
2405 pcap_freealldevs(all_devices);
2413 ERROR(
"Invalid buffer length \"%s\"", optarg);
2421 ERROR(
"Invalid number of packets \"%s\"", optarg);
2428 if (strcmp(optarg,
"udp") == 0) {
2431 }
else if (strcmp(optarg,
"radius") == 0) {
2435 ERROR(
"Must specify 'udp' or 'radius' for -C, not %s", optarg);
2465 *in_head = fr_pcap_init(
conf, optarg, PCAP_INTERFACE_IN);
2466 if (!*in_head)
goto finish;
2467 in_head = &(*in_head)->next;
2472 *in_head = fr_pcap_init(
conf, optarg, PCAP_FILE_IN);
2476 in_head = &(*in_head)->next;
2493 port = atoi(optarg);
2521 timeout = atoi(optarg);
2529#ifdef HAVE_COLLECTDC_H
2531 lcc_version_string());
2538 out = fr_pcap_init(
conf, optarg, PCAP_FILE_OUT);
2540 ERROR(
"Failed creating pcap file \"%s\"", optarg);
2555 ERROR(
"Stats interval must be > 0");
2563 size_t len = strlen(p);
2568 if (p[len-1] ==
'/') p[len-1] =
'\0';
2582 ERROR(
"Timeout value must be > 0");
2587#ifdef HAVE_COLLECTDC_H
2594 conf->
stats.out = RS_STATS_OUT_COLLECTD;
2611 while (optind < argc) {
2612 *in_head = fr_pcap_init(
conf, argv[optind], PCAP_FILE_IN);
2616 in_head = &(*in_head)->next;
2622 if (!isatty(fileno(stdin))) {
2633 ERROR(
"Can't read from both a file and a device");
2639 ERROR(
"CSV output requires a statistics interval (-W)");
2654 out = fr_pcap_init(
conf,
"stdout", PCAP_STDIO_OUT);
2661 *in_head = fr_pcap_init(
conf,
"stdin", PCAP_STDIO_IN);
2665 in_head = &(*in_head)->next;
2693#if !defined(HAVE_PCAP_FOPEN_OFFLINE) || !defined(HAVE_PCAP_DUMP_FOPEN)
2695 ERROR(
"PCAP streams not supported");
2761 ERROR(
"Failed creating RTX tree");
2798 DEBUG(
"Logging all events");
2819 ERROR(
"Failed creating request tree");
2827 pcap_if_t *all_devices;
2830 if (pcap_findalldevs(&all_devices, errbuf) < 0) {
2831 ERROR(
"Error getting available capture devices: %s", errbuf);
2836 ERROR(
"No capture files specified and no live interfaces available");
2838 pcap_freealldevs(all_devices);
2842 for (dev_p = all_devices;
2844 dev_p = dev_p->next) {
2848 if (!strcmp(dev_p->name,
"any"))
continue;
2851 if (!strncmp(dev_p->name,
"pktap", 5))
continue;
2853 link_layer = fr_pcap_if_link_layer(dev_p);
2854 if (link_layer < 0) {
2859 if (!fr_pcap_link_layer_supported(link_layer)) {
2860 DEBUG2(
"Skipping %s: datalink type %s not supported",
2861 dev_p->name, pcap_datalink_val_to_name(link_layer));
2865 *in_head = fr_pcap_init(
conf, dev_p->name, PCAP_INTERFACE_IN);
2866 in_head = &(*in_head)->next;
2868 pcap_freealldevs(all_devices);
2872 INFO(
"Defaulting to capture on all interfaces");
2879 DEBUG2(
"Sniffing with options:");
2881 char *
buff = fr_pcap_device_names(
conf,
in,
' ');
2886 DEBUG2(
" Writing to : [%s]",
out->name);
2899 DEBUG2(
" RADIUS request filter :");
2912 DEBUG2(
" RADIUS response filter :");
2920#ifdef HAVE_COLLECTDC_H
2921 if (
conf->
stats.out == RS_STATS_OUT_COLLECTD) {
2923 rs_stats_tmpl_t *tmpl, **next;
2925 if (rs_stats_collectd_open(
conf) < 0) {
2932 tmpl = rs_stats_collectd_init_latency(
conf, next,
conf,
"exchanged",
2936 ERROR(
"Error allocating memory for stats template");
2939 next = &(tmpl->next);
2949 fr_pcap_t **tmp_p = &tmp;
2953 in_p = in_p->next) {
2956 if (fr_pcap_open(in_p) < 0) {
2957 fr_perror(
"Failed opening pcap handle (%s)", in_p->name);
2965 if (!fr_pcap_link_layer_supported(in_p->link_layer)) {
2966 ERROR(
"Failed opening pcap handle (%s): Datalink type %s not supported",
2967 in_p->name, pcap_datalink_val_to_name(in_p->link_layer));
2986 tmp_p = &(in_p->next);
2992 ERROR(
"No PCAP sources available");
3004 out->link_layer = -1;
3008 in_p = in_p->next) {
3009 if (
out->link_layer < 0) {
3010 out->link_layer = in_p->link_layer;
3014 if (
out->link_layer != in_p->link_layer) {
3015 ERROR(
"Asked to write to output file, but inputs do not have the same link type");
3023 if (fr_pcap_open(
out) < 0) {
3024 fr_perror(
"Failed opening pcap output (%s)",
out->name);
3061 fr_perror(
"Failed inserting signal pipe descriptor");
3081 in_p = in_p->next) {
3088 event->stats = stats;
3101 if (event->
in->type == PCAP_FILE_IN) {
3108 ERROR(
"Failed inserting file descriptor");
3116 ERROR(
"Failed inserting timeout event");
3143 DEBUG2(
"Entering event loop");
static int const char char buffer[256]
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
#define fr_base16_encode(_out, _in)
#define NEVER_RETURNS
Should be placed before the function return type.
#define L(_str)
Helper for initialising arrays of string literals.
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
static void * fr_dcursor_set_current(fr_dcursor_t *cursor, void *item)
Set the cursor to a specified item.
static void * fr_dcursor_filter_next(fr_dcursor_t *cursor, fr_dcursor_eval_t eval, void const *uctx)
Return the next item, skipping the current item, that satisfies an evaluation function.
static void * fr_dcursor_remove(fr_dcursor_t *cursor)
Remove the current item.
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
fr_radius_packet_code_t
RADIUS packet codes.
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
@ FR_RADIUS_CODE_DISCONNECT_REQUEST
RFC3575/RFC5176 - Disconnect-Request.
@ FR_RADIUS_CODE_DISCONNECT_ACK
RFC3575/RFC5176 - Disconnect-Ack (positive)
@ FR_RADIUS_CODE_STATUS_SERVER
RFC2865/RFC5997 - Status Server (request)
@ FR_RADIUS_CODE_COA_REQUEST
RFC3575/RFC5176 - CoA-Request.
@ FR_RADIUS_CODE_ACCESS_ACCEPT
RFC2865 - Access-Accept.
@ FR_RADIUS_CODE_ACCOUNTING_RESPONSE
RFC2866 - Accounting-Response.
@ FR_RADIUS_CODE_COA_NAK
RFC3575/RFC5176 - CoA-Nak (not willing to perform)
@ FR_RADIUS_CODE_COA_ACK
RFC3575/RFC5176 - CoA-Ack (positive)
@ FR_RADIUS_CODE_DISCONNECT_NAK
RFC3575/RFC5176 - Disconnect-Nak (not willing to perform)
@ FR_RADIUS_CODE_ACCOUNTING_REQUEST
RFC2866 - Accounting-Request.
@ FR_RADIUS_CODE_ACCESS_REJECT
RFC2865 - Access-Reject.
static NEVER_RETURNS void usage(void)
fr_dict_gctx_t * fr_dict_global_ctx_init(TALLOC_CTX *ctx, bool free_at_exit, char const *dict_dir)
Initialise the global protocol hashes.
fr_dict_t * fr_dict_unconst(fr_dict_t const *dict)
Coerce to non-const.
#define fr_dict_autofree(_to_free)
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
#define fr_dict_autoload(_to_load)
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename)
Read supplementary attribute definitions into an existing dictionary.
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
#define fr_event_fd_insert(...)
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
ssize_t fr_mkdir(int *fd_out, char const *path, ssize_t len, mode_t mode, fr_mkdir_func_t func, void *uctx)
Create directories that are missing in the specified path.
int fr_unlink(char const *filename)
Remove a regular file from the filesystem.
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
uint64_t fr_event_list_num_fds(fr_event_list_t *el)
Return the number of file descriptors is_registered with this event loop.
fr_event_list_t * fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t status, void *status_uctx)
Initialise a new event list.
bool fr_event_loop_exiting(fr_event_list_t *el)
Check to see whether the event loop is in the process of exiting.
void fr_event_loop_exit(fr_event_list_t *el, int code)
Signal an event loop exit with the specified code.
int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Remove a file descriptor from the event loop.
int fr_event_loop(fr_event_list_t *el)
Run an event loop.
Stores all information relating to an event list.
int fr_log_init_file(fr_log_t *log, char const *file)
Initialise a file logging destination.
int fr_log_close(fr_log_t *log)
Universal close function for all logging destinations.
@ L_TIMESTAMP_OFF
Never log timestamps.
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
@ L_DBG_LVL_4
4th highest priority debug messages (-xxxx | -Xxx).
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
fr_packet_t * fr_packet_alloc_reply(TALLOC_CTX *ctx, fr_packet_t *packet)
Allocate a new fr_packet_t response.
void fr_packet_free(fr_packet_t **packet_p)
Free a fr_packet_t.
int8_t fr_packet_cmp(void const *a_v, void const *b_v)
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
void fr_quick_sort(void const *to_sort[], int start, int end, fr_cmp_t cmp)
Quick sort an array of pointers using a comparator.
int fr_set_signal(int sig, sig_t func)
Sets a signal handler using sigaction if available, else signal.
int8_t fr_pointer_cmp(void const *a, void const *b)
Compares two pointers.
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
char * strsep(char **stringp, char const *delim)
struct tm * localtime_r(time_t const *l_clock, struct tm *result)
uint16_t fr_udp_checksum(uint8_t const *data, uint16_t len, uint16_t checksum, struct in_addr const src_addr, struct in_addr const dst_addr)
Calculate UDP checksum.
struct in6_addr ip_src ip_dst
Src and Dst address.
#define RADIUS_AUTH_VECTOR_LENGTH
uint16_t dst
Destination port.
uint16_t checksum
UDP checksum.
struct in_addr ip_src ip_dst
Src and Dst address.
uint8_t ip_vhl
Header length, version.
bool fr_pair_matches_da(void const *item, void const *uctx)
Evaluation function for matching if vp matches a given da.
int fr_pair_list_cmp(fr_pair_list_t const *a, fr_pair_list_t const *b)
Determine equality of two lists.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
int fr_pair_steal(TALLOC_CTX *ctx, fr_pair_t *vp)
Steal one VP.
bool fr_pair_validate_relaxed(fr_pair_t const *failed[2], fr_pair_list_t *filter, fr_pair_list_t *list)
Uses fr_pair_cmp to verify all fr_pair_ts in list match the filter defined by check.
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
int8_t fr_pair_cmp_by_da(void const *a, void const *b)
Order attributes by their da, and tag.
fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t *relative, fr_sbuff_t *in)
Parse a fr_pair_list_t from a substring.
struct fr_pair_parse_s fr_pair_parse_t
int fr_radius_global_init(void)
ssize_t fr_radius_decode_simple(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t *packet, size_t packet_len, uint8_t const *vector, char const *secret)
Simple wrapper for callers who just need a shared secret.
void fr_radius_global_free(void)
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
int fr_packet_verify(fr_packet_t *packet, fr_packet_t *original, char const *secret)
Verify the Request/Response Authenticator (and Message-Authenticator if present) of a packet.
bool fr_packet_ok(fr_packet_t *packet, uint32_t max_attributes, bool require_message_authenticator, fr_radius_decode_fail_t *reason)
See if the data pointed to by PTR is a valid RADIUS packet.
static TALLOC_CTX * autofree
fr_radius_decode_fail_t
Failure reasons.
#define RADIUS_MAX_ATTRIBUTES
#define fr_packet_log_hex(_log, _packet)
#define FR_RADIUS_PACKET_CODE_VALID(_x)
fr_dict_attr_autoload_t radsniff_dict_attr[]
static int rs_request_to_pcap(rs_event_t *event, rs_request_t *request, struct pcap_pkthdr const *header, uint8_t const *data)
static void timeout_event(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now_t, void *ctx)
Exit the event loop after a given timeout.
static struct timeval start_pcap
static size_t rs_snprint_csv(char *out, size_t outlen, char const *in, size_t inlen)
static fr_rb_tree_t * link_tree
static void rs_packet_print(rs_request_t *request, uint64_t count, rs_status_t status, fr_pcap_t *handle, fr_packet_t *packet, fr_pair_list_t *list, struct timeval *elapsed, struct timeval *latency, bool response, bool body)
static int self_pipe[2]
Signals from sig handlers.
int main(int argc, char *argv[])
static fr_dict_attr_t const * attr_packet_type
static void rs_stats_process_latency(rs_latency_t *stats)
Update smoothed average.
static ssize_t rs_stats_print_code_csv(char *out, size_t outlen, rs_latency_t *stats)
static void rs_stats_print_code_fancy(rs_latency_t *stats, fr_radius_packet_code_t code)
static void rs_daemonize(char const *pidfile)
Fork and kill the parent process, writing out our PID.
static void rs_stats_process(fr_timer_list_t *tl, fr_time_t now_t, void *ctx)
Process stats for a single interval.
static int rs_install_stats_processor(rs_stats_t *stats, fr_event_list_t *el, fr_pcap_t *in, struct timeval *now, bool live)
static fr_event_list_t * events
static const uint8_t zeros[RADIUS_AUTH_VECTOR_LENGTH]
static void rs_packet_save_in_output_dir(uint64_t count, UNUSED rs_status_t status, UNUSED fr_pcap_t *handle, fr_packet_t *packet, fr_pair_list_t *list, UNUSED struct timeval *elapsed, UNUSED struct timeval *latency, bool response, bool body)
static void rs_packet_print_csv_header(void)
static fr_dict_t const * dict_freeradius
static int rs_response_to_pcap(rs_event_t *event, rs_request_t *request, struct pcap_pkthdr const *header, uint8_t const *data)
static fr_rb_tree_t * request_tree
static fr_dict_t const * dict_radius
static rs_request_t * rs_request_alloc(TALLOC_CTX *ctx)
static int _rs_event_status(UNUSED fr_time_t now, fr_time_delta_t wake_t, UNUSED void *uctx)
static char const * radsniff_version
static void _unmark_request(void *request)
Callback for when the request is removed from the request tree.
static int rs_build_event_flags(int *flags, fr_table_num_sorted_t const *map, size_t map_len, char *list)
static int8_t rs_rtx_cmp(void const *one, void const *two)
Compare requests using packet info and lists of attributes.
static void rs_stats_print_csv(rs_update_t *this, rs_stats_t *stats, UNUSED struct timeval *now)
static int rs_check_pcap_drop(fr_pcap_t *in)
Query libpcap to see if it dropped any packets.
static void rs_stats_print_fancy(rs_update_t *this, rs_stats_t *stats, struct timeval *now)
static size_t rs_events_len
static int rs_build_dict_list(fr_dict_attr_t const **out, size_t len, char *list)
fr_dict_autoload_t radsniff_dict[]
static void rs_tv_add_ms(struct timeval const *start, unsigned long interval, struct timeval *result)
static void rs_time_print(char *out, size_t len, struct timeval const *t)
static void rs_signal_self(int sig)
Write the last signal to the signal pipe.
static void rs_packet_cleanup(rs_request_t *request)
static void _unmark_link(void *request)
Callback for when the request is removed from the link tree.
static void rs_stats_print_csv_header(rs_update_t *this)
#define RS_CLEANUP_NOW(_x, _s)
static void rs_got_packet(fr_event_list_t *el, int fd, UNUSED int flags, void *ctx)
static void rs_packet_print_fancy(uint64_t count, rs_status_t status, fr_pcap_t *handle, fr_packet_t *packet, fr_pair_list_t *list, struct timeval *elapsed, struct timeval *latency, bool response, bool body)
static void rs_packet_process(uint64_t count, rs_event_t *event, struct pcap_pkthdr const *header, uint8_t const *data)
static int8_t rs_packet_cmp(void const *one, void const *two)
Wrapper around fr_packet_cmp to strip off the outer request struct.
static int rs_get_pairs(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_pair_list_t *vps, fr_dict_attr_t const *da[], int num)
Copy a subset of attributes from one list into the other.
static void rs_signal_action(UNUSED fr_event_list_t *list, int fd, int UNUSED flags, UNUSED void *ctx)
Read the last signal from the signal pipe.
static void rs_packet_print_csv(uint64_t count, rs_status_t status, fr_pcap_t *handle, fr_packet_t *packet, fr_pair_list_t *list, UNUSED struct timeval *elapsed, struct timeval *latency, UNUSED bool response, bool body)
static void rs_stats_process_counters(rs_latency_t *stats)
static int rs_useful_codes[]
static int _request_free(rs_request_t *request)
static void rs_stats_update_latency(rs_latency_t *stats, struct timeval *latency)
Update latency statistics for request/response and forwarded packets.
static int rs_build_filter(fr_pair_list_t *out, char const *filter)
static void _rs_event(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *ctx)
static fr_table_num_sorted_t const rs_events[]
Structures and prototypes for the RADIUS sniffer.
fr_radius_packet_code_t filter_response_code
Filter response packets by code.
fr_pcap_t * in
PCAP handle event occurred on.
fr_packet_t * expect
Request/response.
bool to_output_dir
Were writing attributes into directory.
rs_stats_print_cb_t body
Print body.
bool print_packet
Print packet info, disabled with -W.
uint8_t * data
PCAP packet data.
fr_dict_attr_t const * list_da[RS_MAX_ATTRS]
Output CSV with these attribute values.
char const * output_dir
Where we should save the files $PATH/requests.txt and $PATH/reply.txt.
fr_timer_t * event
Event created when we received the original request.
@ RS_STATS_OUT_STDIO_FANCY
#define RS_DEFAULT_SECRET
Default secret.
bool in_request_tree
Whether the request is currently in the request tree.
rs_status_t event_flags
Events we log and capture on.
fr_dict_attr_t const * link_da[RS_MAX_ATTRS]
fr_dict_attr_ts to link on.
uint64_t latency_smoothed_count
Number of CMA datapoints processed.
int link_da_num
Number of rtx fr_dict_attr_ts.
fr_radius_packet_code_t filter_request_code
Filter request packets by code.
rs_stats_t * stats
Stats to process.
int buffer_pkts
Size of the ring buffer to setup for live capture.
char const * filter_response
Raw response filter string.
fr_event_list_t * list
List to insert new event into.
struct timeval when
Time when the packet was received, or next time an event is scheduled.
bool from_dev
Were reading pcap data from devices.
#define RS_FORCE_YIELD
Service another descriptor every X number of packets.
#define RS_DEFAULT_TIMEOUT
Standard timeout of 5s + 300ms to cover network latency.
rs_packet_logger_t logger
Packet logger.
char * pcap_filter_vlan
Variant of the normal filter to apply to devices which support VLAN tags.
char * pcap_filter
PCAP filter string applied to live capture devices.
rs_capture_t capture[RS_RETRANSMIT_MAX]
Buffered request packets (if a response filter has been applied).
bool from_auto
From list was auto-generated.
rs_latency_t * stats_req
Latency entry for the request type.
bool decode_attrs
Whether we should decode attributes in the request and response.
uint64_t id
Monotonically increasing packet counter.
rs_latency_t * stats_rsp
Latency entry for the request type.
bool to_file
Were writing pcap data to files.
fr_pair_list_t link_vps
fr_pair_ts used to link retransmissions.
fr_packet_t * packet
The original packet.
#define RS_RETRANSMIT_MAX
Maximum number of times we expect to see a packet retransmitted.
rs_stats_print_header_cb_t head
Print header.
char * list_attributes
Raw attribute filter string.
char * radius_secret
Secret to decode encrypted attributes.
bool from_file
Were reading pcap data from files.
fr_pcap_t * out
Where to write output.
#define RS_DEFAULT_PREFIX
Default instance.
fr_pcap_t * in
PCAP handle the original request was received on.
fr_pcap_t * in
Linked list of PCAP handles to check for drops.
rs_capture_t * capture_p
Next packet slot.
bool in_link_tree
Whether the request is currently in the linked tree.
struct timeval quiet
We may need to 'mute' the stats if libpcap starts dropping packets, or we run out of memory.
#define RIDEBUG_ENABLED()
int intervals
Number of stats intervals.
fr_event_list_t * list
The event list.
fr_packet_t * linked
The subsequent response or forwarded request the packet was linked against.
bool verify_radius_authenticator
Check RADIUS authenticator in packets.
uint64_t limit
Maximum number of packets to capture.
char const * pidfile
File to write PID to.
uint64_t rt_rsp
Number of times we saw a retransmitted response packet.
bool from_stdin
Were reading pcap data from stdin.
bool daemonize
Daemonize and write PID out to file.
double latency_smoothed
Smoothed moving average.
uint64_t rt_req
Number of times we saw the same request packet.
rs_latency_t exchange[FR_RADIUS_CODE_MAX+1]
We end up allocating ~16K, but memory is cheap so.
fr_pair_list_t filter_response_vps
Sorted filter vps.
bool promiscuous
Capture in promiscuous mode.
fr_pair_list_t expect_vps
fr_pair_list_t packet_vps
bool logged
Whether any messages regarding this request were logged.
char * link_attributes
Names of fr_dict_attr_ts to use for rtx.
bool silent_cleanup
Cleanup was forced before normal expiry period, ignore stats about packet loss.
char const * filter_request
Raw request filter string.
struct pcap_pkthdr * header
PCAP packet header.
#define RS_SOCKET_REOPEN_DELAY
How long we delay re-opening a collectd socket.
bool verify_udp_checksum
Check UDP checksum in packets.
bool to_stdout
Were writing pcap data to stdout.
struct rs_latency_t::@0 interval
fr_pair_list_t filter_request_vps
Sorted filter vps.
Statistic write/print event.
Stats for a single interval.
FD data which gets passed to callbacks.
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
#define fr_rb_inline_talloc_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
The main red black tree structure.
ssize_t fr_sbuff_in_sprintf(fr_sbuff_t *sbuff, char const *fmt,...)
Print using a fmt string to an sbuff.
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_current(_sbuff_or_marker)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_remaining(_sbuff_or_marker)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define fr_sbuff_in_char(_sbuff,...)
static char buff[sizeof("18446744073709551615")+3]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
fr_aka_sim_id_type_t type
#define fr_time()
Allow us to arbitrarily manipulate time.
size_t strlcpy(char *dst, char const *src, size_t siz)
fr_log_timestamp_t timestamp
Prefix log messages with timestamps.
bool print_level
sometimes we don't want log levels printed
FILE * handle
Path to log file.
Stores an attribute, a value and various bits of other data.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in a lexicographically sorted array of name to num mappings.
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
int fr_time_sync(void)
Get a new fr_time_monotonic_to_realtime value.
int fr_time_start(void)
Initialize the local time.
static fr_time_t fr_time_from_timeval(struct timeval const *when_tv)
Convert a timeval (wallclock time) to a fr_time_t (internal time)
static fr_time_delta_t fr_time_delta_from_msec(int64_t msec)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_wrap(_time)
#define fr_time_delta_to_timeval(_delta)
Convert a delta to a timeval.
#define fr_time_add(_a, _b)
Add a time/time delta together.
#define fr_time_to_timeval(_when)
Convert server epoch time to unix epoch time.
#define fr_time_sub(_a, _b)
Subtract one time from another.
#define fr_time_delta_gt(_a, _b)
A time delta, a difference in time measured in nanoseconds.
int fr_timer_list_run(fr_timer_list_t *tl, fr_time_t *when)
Execute any pending events in the event loop.
#define fr_timer_armed(_ev)
#define FR_TIMER_DELETE(_ev_p)
void fr_timeval_subtract(struct timeval *out, struct timeval const *end, struct timeval const *start)
Subtract one timeval from another.
static fr_event_list_t * el
static void print_packet(FILE *fp, fr_packet_t *packet, fr_pair_list_t *list)
#define FR_DICTIONARY_FILE
unsigned int code
Packet code (type).
fr_socket_t socket
This packet was received on.
int id
Packet ID (used to link requests/responses).
uint8_t * data
Packet data (body).
size_t data_len
Length of packet data.
uint8_t vector[RADIUS_AUTH_VECTOR_LENGTH]
RADIUS authentication vector.
fr_time_t timestamp
When we received the packet.
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
void fr_pair_list_sort(fr_pair_list_t *list, fr_cmp_t cmp)
Sort a doubly linked list of fr_pair_ts using merge sort.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
ssize_t fr_pair_print_value_quoted(fr_sbuff_t *out, fr_pair_t const *vp, fr_token_t quote)
Print the value of an attribute to a string.
#define fr_pair_list_log(_log, _lvl, _list)
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
int af
AF_INET, AF_INET6, or AF_UNIX.
int type
SOCK_STREAM, SOCK_DGRAM, etc.
char const * fr_strerror(void)
Get the last library error.
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
#define RADIUSD_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
#define RADIUSD_MAGIC_NUMBER
static size_t char fr_sbuff_t size_t inlen
static size_t char ** out