27RCSID(
"$Id: bd045ff53ab4d5a253211451fabd349046eae5e6 $")
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++) {
1048 if (request->
event) {
1107 if ((request->
in->type == PCAP_INTERFACE_IN) && request->
logged) {
1155 if (!event->
out)
return 0;
1197 pcap_dump((
void *)event->
out->dumper, header,
data);
1205 if (!event->
out)
return 0;
1217 if (!(request->
capture_p->
header = talloc(request,
struct pcap_pkthdr)))
return -1;
1222 memcpy(request->
capture_p->
header, header,
sizeof(
struct pcap_pkthdr));
1234 pcap_dump((
void *)event->
out->dumper, header,
data);
1240#define RS_CLEANUP_NOW(_x, _s)\
1242 _x->silent_cleanup = _s;\
1243 _x->when = header->ts;\
1244 rs_packet_cleanup(_x);\
1267 struct timeval elapsed = {0, 0};
1268 struct timeval latency;
1283 static uint64_t captured = 0;
1294 memset(&search, 0,
sizeof(search));
1307 len = fr_pcap_link_layer_offset(
data, header->caplen, event->
in->link_layer);
1309 REDEBUG(
"Failed determining link layer header offset");
1314 version = (p[0] & 0xf0) >> 4;
1318 len = (0x0f & ip->
ip_vhl) * 4;
1329 REDEBUG(
"IP version invalid %i", version);
1337 if ((
size_t) len > header->caplen) {
1338 REDEBUG(
"Packet too small, we require at least %zu bytes, captured %i bytes",
1339 (
size_t) len, header->caplen);
1351 udp_len = ntohs(udp->
len);
1352 actual_len = header->caplen - (p -
data);
1354 if (udp_len > actual_len) {
1355 REDEBUG(
"Packet too small by %zi bytes, UDP header + Payload should be %hu bytes",
1356 udp_len - actual_len, udp_len);
1369 else if (udp_len < actual_len) {
1370 REDEBUG(
"Packet too big by %zi bytes, UDP header + Payload should be %hu bytes",
1371 actual_len - udp_len, udp_len);
1380 if (udp->checksum != expected) {
1381 REDEBUG(
"UDP checksum invalid, packet: 0x%04hx calculated: 0x%04hx",
1382 ntohs(udp->checksum), ntohs(expected));
1396 REDEBUG(
"Failed allocating memory to hold decoded packet");
1403 memcpy(&packet->
data, &p,
sizeof(packet->
data));
1411 packet->
socket.inet.src_ipaddr.
af = AF_INET;
1412 packet->
socket.inet.src_ipaddr.addr.v4.s_addr = ip->ip_src.s_addr;
1414 packet->
socket.inet.dst_ipaddr.
af = AF_INET;
1415 packet->
socket.inet.dst_ipaddr.addr.v4.s_addr = ip->
ip_dst.s_addr;
1417 packet->
socket.inet.src_ipaddr.
af = AF_INET6;
1418 memcpy(packet->
socket.inet.src_ipaddr.addr.v6.s6_addr, ip6->ip_src.s6_addr,
1419 sizeof(packet->
socket.inet.src_ipaddr.addr.v6.s6_addr));
1421 packet->
socket.inet.dst_ipaddr.
af = AF_INET6;
1422 memcpy(packet->
socket.inet.dst_ipaddr.addr.v6.s6_addr, ip6->
ip_dst.s6_addr,
1423 sizeof(packet->
socket.inet.dst_ipaddr.addr.v6.s6_addr));
1426 packet->
socket.inet.src_port = ntohs(udp->
src);
1427 packet->
socket.inet.dst_port = ntohs(udp->
dst);
1433 packet, &decoded, &elapsed, NULL,
false,
false);
1440 switch (packet->
code) {
1459 RDEBUG2(
"Response dropped by filter");
1477 fr_perror(
"Failed verifying packet ID %d", packet->
id);
1545 original->
linked = talloc_steal(original, packet);
1551 REDEBUG(
"Failed inserting new event");
1570 RDEBUG2(
"Original request dropped by filter");
1595 RDEBUG2(
"Request dropped by filter");
1602 switch (packet->
code) {
1615 fr_perror(
"Failed verifying packet ID %d", packet->
id);
1656 REDEBUG(
"Failed allocating memory to hold expected reply");
1670 ERROR(
"Failed extracting RTX linking pairs from request");
1690 if (tuple && (original != tuple)) {
1742 original->
packet = talloc_steal(original, packet);
1753 original->
expect = talloc_steal(original, search.
expect);
1764 original->
in =
event->in;
1770 original->
packet = talloc_steal(original, packet);
1773 original->
expect = talloc_steal(original, search.
expect);
1821 REDEBUG(
"Failed inserting new event");
1848 if (original && original->
linked) {
1867 struct timeval ts_tv;
1882 &elapsed, &latency, response,
true);
1895 print_id = original->
id;
1901 print_pair_list = &decoded;
1906 &elapsed, NULL, response,
true);
1915 if (response && !original) {
1924 INFO(
"Captured %" PRIu64
" packets, exiting...", captured);
1931 static uint64_t
count = 0;
1935 pcap_t *handle =
event->in->handle;
1940 struct pcap_pkthdr *header;
1951 last_sync = now_real;
1957 if ((event->in->type == PCAP_FILE_IN) || (event->in->type == PCAP_STDIO_IN)) {
1958 bool stats_started =
false;
1963 ret = pcap_next_ex(handle, &header, &
data);
1969 DEBUG(
"Done reading packets (%s)", event->in->name);
1979 ERROR(
"Error requesting next packet, got (%i): %s", ret, pcap_geterr(handle));
1987 if (
conf->
stats.interval && !stats_started) {
1989 stats_started =
true;
2007 ret = pcap_next_ex(handle, &header, &
data);
2013 ERROR(
"Error requesting next packet, got (%i): %s", ret, pcap_geterr(handle));
2024 struct timeval wake;
2028 if ((wake.tv_sec != 0) || (wake.tv_usec >= 100000)) {
2029 DEBUG2(
"Waking up in %d.%01u seconds", (
int) wake.tv_sec, (
unsigned int) wake.tv_usec / 100000);
2055 if (ret != 0)
return ret;
2058 if (ret != 0)
return ret;
2070 while ((tok =
strsep(&p,
"\t ,")) != NULL) {
2072 if ((*tok ==
'\t') || (*tok ==
' ') || (*tok ==
'\0')) {
2077 ERROR(
"Too many attributes, maximum allowed is %zu", len);
2084 ERROR(
"Error parsing attribute name \"%s\"", tok);
2108 .allow_compare =
true,
2113 fr_perror(
"Invalid RADIUS filter \"%s\"", filter);
2118 ERROR(
"Empty RADIUS filter '%s'", filter);
2136 while ((tok =
strsep(&p,
"\t ,")) != NULL) {
2139 if ((*tok ==
'\t') || (*tok ==
' ') || (*tok ==
'\0')) {
2145 ERROR(
"Invalid flag \"%s\"", tok);
2162 this->in_request_tree =
false;
2172 this->in_link_tree =
false;
2184#ifdef HAVE_COLLECTDC_H
2192 if (rs_stats_collectd_open(
conf) == 0) {
2193 DEBUG2(
"Stats output socket (re)opened");
2201 false, rs_collectd_reopen, NULL) < 0) {
2202 ERROR(
"Failed inserting re-open event");
2214 if (write(
self_pipe[1], &sig,
sizeof(sig)) < 0) {
2215 ERROR(
"Failed writing signal %s to pipe: %s", strsignal(sig),
fr_syserror(errno));
2224#ifndef HAVE_COLLECTDC_H
2232 ret = read(fd, &sig,
sizeof(sig));
2238 if (ret !=
sizeof(sig)) {
2239 ERROR(
"Failed reading signal from pipe: "
2240 "Expected signal to be %zu bytes but only read %zu byes",
sizeof(sig), ret);
2245#ifdef HAVE_COLLECTDC_H
2247 rs_collectd_reopen(list->tl,
fr_time(), list);
2256 DEBUG2(
"Signalling event loop to exit");
2261 ERROR(
"Unhandled signal %s", strsignal(sig));
2268 FILE *output = status ? stderr : stdout;
2269 fprintf(output,
"Usage: radsniff [options][stats options] -- [pcap files]\n");
2270 fprintf(output,
"options:\n");
2271 fprintf(output,
" -a List all interfaces available for capture.\n");
2272 fprintf(output,
" -c <count> Number of packets to capture.\n");
2273 fprintf(output,
" -C <checksum_type> Enable checksum validation. (Specify 'udp' or 'radius')\n");
2274 fprintf(output,
" -d <raddb> Set configuration directory (defaults to " RADDBDIR
").\n");
2275 fprintf(output,
" -D <dictdir> Set main dictionary directory (defaults to " DICTDIR
").\n");
2276 fprintf(output,
" -e <event>[,<event>] Only log requests with these event flags.\n");
2277 fprintf(output,
" Event may be one of the following:\n");
2278 fprintf(output,
" - received - a request or response.\n");
2279 fprintf(output,
" - norsp - seen for a request.\n");
2280 fprintf(output,
" - rtx - of a request that we've seen before.\n");
2281 fprintf(output,
" - noreq - could be matched with the response.\n");
2282 fprintf(output,
" - reused - ID too soon.\n");
2283 fprintf(output,
" - error - decoding the packet.\n");
2284 fprintf(output,
" -f <filter> PCAP filter (default is 'udp port <port> or <port + 1> or %i'\n",
2286 fprintf(output,
" with extra rules to allow .1Q tagged packets)\n");
2287 fprintf(output,
" -h This help message.\n");
2288 fprintf(output,
" -i <interface> Capture packets from interface (defaults to all if supported).\n");
2289 fprintf(output,
" -I <file> Read packets from <file>\n");
2290 fprintf(output,
" -l <attr>[,<attr>] Output packet sig and a list of attributes.\n");
2291 fprintf(output,
" -L <attr>[,<attr>] Detect retransmissions using these attributes to link requests.\n");
2292 fprintf(output,
" -m Don't put interface(s) into promiscuous mode.\n");
2293 fprintf(output,
" -p <port> Filter packets by port (default is %i).\n",
FR_AUTH_UDP_PORT);
2294 fprintf(output,
" -P <pidfile> Daemonize and write out <pidfile>.\n");
2295 fprintf(output,
" -q Print less debugging information.\n");
2296 fprintf(output,
" -r <filter> RADIUS attribute request filter.\n");
2297 fprintf(output,
" -R <filter> RADIUS attribute response filter.\n");
2298 fprintf(output,
" -s <secret> RADIUS secret.\n");
2299 fprintf(output,
" -S Write PCAP data to stdout.\n");
2300 fprintf(output,
" -t <timeout> Stop after <timeout> seconds.\n");
2301 fprintf(output,
" -v Show program version information and exit.\n");
2302 fprintf(output,
" -w <file> Write output packets to file.\n");
2303 fprintf(output,
" -x Print more debugging information.\n");
2304 fprintf(output,
"stats options:\n");
2305 fprintf(output,
" -W <interval> Periodically write out statistics every <interval> seconds.\n");
2306 fprintf(output,
" -E Print stats in CSV format.\n");
2307 fprintf(output,
" -T <timeout> How many milliseconds before the request is counted as lost "
2309#ifdef HAVE_COLLECTDC_H
2310 fprintf(output,
" -N <prefix> The instance name passed to the collectd plugin.\n");
2311 fprintf(output,
" -O <server> Write statistics to this collectd server.\n");
2313 fprintf(output,
" -Z <output_dir> Dump the packets in <output_dir>/{requests,reply}.${count}.txt\n");
2323 fr_pcap_t *
in = NULL, *in_p;
2324 fr_pcap_t **in_head = &
in;
2325 fr_pcap_t *
out = NULL;
2327 int ret = EXIT_SUCCESS;
2329 char errbuf[PCAP_ERRBUF_SIZE];
2333 unsigned int timeout = 0;
2335 char const *raddb_dir = RADDBDIR;
2336 char const *dict_dir = DICTDIR;
2361 talloc_set_log_stderr();
2376#ifdef HAVE_COLLECTDC_H
2382#ifdef HAVE_COLLECTDC_H
2389 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) {
2393 pcap_if_t *all_devices = NULL;
2397 if (pcap_findalldevs(&all_devices, errbuf) < 0) {
2398 ERROR(
"Error getting available capture devices: %s", errbuf);
2403 for (dev_p = all_devices;
2405 dev_p = dev_p->next) {
2406 INFO(
"%i.%s", i++, dev_p->name);
2409 pcap_freealldevs(all_devices);
2417 ERROR(
"Invalid buffer length \"%s\"", optarg);
2425 ERROR(
"Invalid number of packets \"%s\"", optarg);
2432 if (strcmp(optarg,
"udp") == 0) {
2435 }
else if (strcmp(optarg,
"radius") == 0) {
2439 ERROR(
"Must specify 'udp' or 'radius' for -C, not %s", optarg);
2469 *in_head = fr_pcap_init(
conf, optarg, PCAP_INTERFACE_IN);
2470 if (!*in_head)
goto finish;
2471 in_head = &(*in_head)->next;
2476 *in_head = fr_pcap_init(
conf, optarg, PCAP_FILE_IN);
2480 in_head = &(*in_head)->next;
2497 port = atoi(optarg);
2525 timeout = atoi(optarg);
2533#ifdef HAVE_COLLECTDC_H
2535 lcc_version_string());
2542 out = fr_pcap_init(
conf, optarg, PCAP_FILE_OUT);
2544 ERROR(
"Failed creating pcap file \"%s\"", optarg);
2559 ERROR(
"Stats interval must be > 0");
2567 size_t len = strlen(p);
2572 if (p[len-1] ==
'/') p[len-1] =
'\0';
2586 ERROR(
"Timeout value must be > 0");
2591#ifdef HAVE_COLLECTDC_H
2598 conf->
stats.out = RS_STATS_OUT_COLLECTD;
2615 while (optind < argc) {
2616 *in_head = fr_pcap_init(
conf, argv[optind], PCAP_FILE_IN);
2620 in_head = &(*in_head)->next;
2626 if (!isatty(fileno(stdin))) {
2637 ERROR(
"Can't read from both a file and a device");
2643 ERROR(
"CSV output requires a statistics interval (-W)");
2658 out = fr_pcap_init(
conf,
"stdout", PCAP_STDIO_OUT);
2665 *in_head = fr_pcap_init(
conf,
"stdin", PCAP_STDIO_IN);
2669 in_head = &(*in_head)->next;
2697#if !defined(HAVE_PCAP_FOPEN_OFFLINE) || !defined(HAVE_PCAP_DUMP_FOPEN)
2699 ERROR(
"PCAP streams not supported");
2765 ERROR(
"Failed creating RTX tree");
2802 DEBUG(
"Logging all events");
2823 ERROR(
"Failed creating request tree");
2831 pcap_if_t *all_devices;
2834 if (pcap_findalldevs(&all_devices, errbuf) < 0) {
2835 ERROR(
"Error getting available capture devices: %s", errbuf);
2840 ERROR(
"No capture files specified and no live interfaces available");
2842 pcap_freealldevs(all_devices);
2846 for (dev_p = all_devices;
2848 dev_p = dev_p->next) {
2852 if (!strcmp(dev_p->name,
"any"))
continue;
2855 if (!strncmp(dev_p->name,
"pktap", 5))
continue;
2857 link_layer = fr_pcap_if_link_layer(dev_p);
2858 if (link_layer < 0) {
2863 if (!fr_pcap_link_layer_supported(link_layer)) {
2864 DEBUG2(
"Skipping %s: datalink type %s not supported",
2865 dev_p->name, pcap_datalink_val_to_name(link_layer));
2869 *in_head = fr_pcap_init(
conf, dev_p->name, PCAP_INTERFACE_IN);
2870 in_head = &(*in_head)->next;
2872 pcap_freealldevs(all_devices);
2876 INFO(
"Defaulting to capture on all interfaces");
2883 DEBUG2(
"Sniffing with options:");
2885 char *
buff = fr_pcap_device_names(
conf,
in,
' ');
2890 DEBUG2(
" Writing to : [%s]",
out->name);
2903 DEBUG2(
" RADIUS request filter :");
2916 DEBUG2(
" RADIUS response filter :");
2924#ifdef HAVE_COLLECTDC_H
2925 if (
conf->
stats.out == RS_STATS_OUT_COLLECTD) {
2927 rs_stats_tmpl_t *tmpl, **next;
2929 if (rs_stats_collectd_open(
conf) < 0) {
2936 tmpl = rs_stats_collectd_init_latency(
conf, next,
conf,
"exchanged",
2940 ERROR(
"Error allocating memory for stats template");
2943 next = &(tmpl->next);
2953 fr_pcap_t **tmp_p = &tmp;
2957 in_p = in_p->next) {
2960 if (fr_pcap_open(in_p) < 0) {
2961 fr_perror(
"Failed opening pcap handle (%s)", in_p->name);
2969 if (!fr_pcap_link_layer_supported(in_p->link_layer)) {
2970 ERROR(
"Failed opening pcap handle (%s): Datalink type %s not supported",
2971 in_p->name, pcap_datalink_val_to_name(in_p->link_layer));
2990 tmp_p = &(in_p->next);
2996 ERROR(
"No PCAP sources available");
3008 out->link_layer = -1;
3012 in_p = in_p->next) {
3013 if (
out->link_layer < 0) {
3014 out->link_layer = in_p->link_layer;
3018 if (
out->link_layer != in_p->link_layer) {
3019 ERROR(
"Asked to write to output file, but inputs do not have the same link type");
3027 if (fr_pcap_open(
out) < 0) {
3028 fr_perror(
"Failed opening pcap output (%s)",
out->name);
3065 fr_perror(
"Failed inserting signal pipe descriptor");
3085 in_p = in_p->next) {
3092 event->stats = stats;
3105 if (event->
in->type == PCAP_FILE_IN) {
3112 ERROR(
"Failed inserting file descriptor");
3120 ERROR(
"Failed inserting timeout event");
3147 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.
int fr_timer_delete(fr_timer_t **ev_p)
Delete a timer event and free its memory.
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