27RCSID(
"$Id: a9ee65e91eb107a164d8514e83d8da6d60e95542 $")
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/pair_legacy.h>
40#include <freeradius-devel/util/base16.h>
41#include <freeradius-devel/util/pcap.h>
42#include <freeradius-devel/util/timeval.h>
44#ifdef HAVE_COLLECTDC_H
45# include <collectd/client.h>
50#define RS_ASSERT(_x) if (!(_x) && !fr_cond_assert(_x)) exit(1)
149 if ((chdir(
"/")) < 0) {
157 fp = fopen(pidfile,
"w");
159 fprintf(fp,
"%d\n", (
int) sid);
169 if (isatty(fileno(stdout))) {
170 if (!freopen(
"/dev/null",
"w", stdout)) {
175 if (isatty(fileno(stderr))) {
176 if (!freopen(
"/dev/null",
"w", stderr)) {
182static void rs_tv_add_ms(
struct timeval
const *start,
unsigned long interval,
struct timeval *result) {
183 result->tv_sec = start->tv_sec + (interval / 1000);
184 result->tv_usec = start->tv_usec + ((interval % 1000) * 1000);
186 if (result->tv_usec >
USEC) {
187 result->tv_usec -=
USEC;
204 ret = strftime(
out, len,
"%Y-%m-%d %H:%M:%S",
localtime_r(&t->tv_sec, &result));
212 while (usec < 100000) usec *= 10;
221 char const *start =
out;
236 while ((
inlen > 0) && (outlen > 2)) {
248 if ((*str ==
'\r') || (*str ==
'\n') || ((*str >=
'\x20') && (*str <=
'\x7E'))) {
275 len =
strlcpy(p,
"\"Status\",\"Count\",\"Time\",\"Latency\",\"Type\",\"Interface\","
276 "\"Src IP\",\"Src Port\",\"Dst IP\",\"Dst Port\",\"ID\",", s);
305 fprintf(stdout ,
"%s\n",
buffer);
310 UNUSED struct timeval *elapsed,
struct timeval *latency,
UNUSED bool response,
313 char const *status_str;
317 char src[INET6_ADDRSTRLEN];
318 char dst[INET6_ADDRSTRLEN];
330 (
unsigned int) latency->tv_sec,
331 ((
unsigned int) latency->tv_usec / 1000)) < 0)
return;
340 src, packet->
socket.inet.src_port, dst, packet->
socket.inet.dst_port, packet->
id) < 0)
return;
342 if (
fr_sbuff_in_sprintf(&sbuff,
"%u,%s,%s,%i,%s,%i,%i,", packet->
code, handle->name,
343 src, packet->
socket.inet.src_port, dst, packet->
socket.inet.dst_port, packet->
id) < 0)
return;
352 if (
vp && (
vp->vp_length > 0)) {
359 vp->vp_strvalue,
vp->vp_length);
360 if (slen < 0)
return;
376 fr_sbuff_terminate(&sbuff);
379 fprintf(stdout ,
"%s\n",
buffer);
384 struct timeval *elapsed,
struct timeval *latency,
bool response,
bool body)
389 char src[INET6_ADDRSTRLEN];
390 char dst[INET6_ADDRSTRLEN];
399 char const *status_str;
404 len =
snprintf(p, s,
"** %s ** ", status_str);
411 len =
snprintf(p, s,
"%s Id %i %s:%s:%d %s %s:%i ",
415 response ? dst : src,
416 response ? packet->
socket.inet.dst_port : packet->
socket.inet.src_port,
417 response ?
"<-" :
"->",
418 response ? src : dst ,
419 response ? packet->
socket.inet.src_port : packet->
socket.inet.dst_port);
421 len =
snprintf(p, s,
"%u Id %i %s:%s:%i %s %s:%i ",
425 response ? dst : src,
426 response ? packet->
socket.inet.dst_port : packet->
socket.inet.src_port,
427 response ?
"<-" :
"->",
428 response ? src : dst ,
429 response ? packet->
socket.inet.src_port : packet->
socket.inet.dst_port);
437 (
unsigned int) elapsed->tv_sec, ((
unsigned int) elapsed->tv_usec / 1000));
445 (
unsigned int) latency->tv_sec, ((
unsigned int) latency->tv_usec / 1000));
479 UNUSED struct timeval *elapsed,
UNUSED struct timeval *latency,
bool response,
bool body)
484 char const *packet_type = response ?
"reply" :
"request";
492 DEBUG2(
"Saving %s in %s", packet_type, filename);
499 ERROR(
"Failed opening %s output file.", filename);
517 ERROR(
"Failed closing %s output file.", filename);
530 struct timeval *elapsed,
struct timeval *latency,
531 bool response,
bool body)
535 if (request) request->
logged =
true;
536 conf->
logger(
count, status, handle, packet, list, elapsed, latency, response, body);
554 struct pcap_stat pstats;
556 if (pcap_stats(
in->handle, &pstats) != 0) {
557 ERROR(
"%s failed retrieving pcap stats: %s",
in->name, pcap_geterr(
in->handle));
561 if (pstats.ps_drop -
in->pstats.ps_drop > 0) {
562 ERROR(
"%s dropped %i packets: Buffer exhaustion",
in->name, pstats.ps_drop -
in->pstats.ps_drop);
566 if (pstats.ps_ifdrop -
in->pstats.ps_ifdrop > 0) {
567 ERROR(
"%s dropped %i packets: Interface",
in->name, pstats.ps_ifdrop -
in->pstats.ps_ifdrop);
589 if (stats->
interval.linked_total == 0) {
590 double unk = strtod(
"NAN()", (
char **) NULL);
592 stats->
interval.latency_average = unk;
612 if (stats->
interval.latency_average > 0) {
637 bool have_rt =
false;
641 if (!stats->
interval.received && !have_rt && !stats->
interval.reused)
return;
656 INFO(
"\tAverage : %.3lfms", stats->
interval.latency_average);
667 if (!stats->
interval.rt[i])
continue;
690 if ((stats->
quiet.tv_sec + (stats->
quiet.tv_usec / 1000000.0)) -
691 (now->tv_sec + (now->tv_usec / 1000000.0)) > 0) {
692 INFO(
"Stats muted because of warmup, or previous error");
696 INFO(
"######### Stats Iteration %i #########", stats->
intervals);
698 if (this->
in)
INFO(
"Interface capture rate:");
699 for (in_p = this->
in;
702 struct pcap_stat pstats;
704 if (pcap_stats(in_p->handle, &pstats) != 0) {
705 ERROR(
"%s failed retrieving pcap stats: %s", in_p->name, pcap_geterr(in_p->handle));
709 INFO(
"\t%s%*s: %.3lf/s", in_p->name, (
int) (10 - strlen(in_p->name)),
"",
710 ((
double) (pstats.ps_recv - in_p->pstats.ps_recv)) /
conf->
stats.interval);
718 for (i = 0; i < rs_codes_len; i++) {
732 fprintf(stdout,
"\"Iteration\"");
734 for (in_p = this->
in; in_p; in_p = in_p->next) {
735 fprintf(stdout,
",\"%s PPS\"", in_p->name);
738 for (i = 0; i < rs_codes_len; i++) {
745 ",\"%s lat high (ms)\""
746 ",\"%s lat low (ms)\""
747 ",\"%s lat avg (ms)\""
748 ",\"%s lat ma (ms)\""
763 fprintf(stdout,
",\"%s rtx (%i)\"",
name, j);
765 fprintf(stdout,
",\"%s rtx (%i+)\"",
name, j);
770 fprintf(stdout ,
"\n");
776 char *p =
out, *end =
out + outlen;
778 p +=
snprintf(
out, outlen,
",%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf",
788 if (p >= end)
return -1;
792 if (p >= end)
return -1;
808 ERROR(
"Exceeded line buffer size");
812 for (in_p = this->
in;
815 struct pcap_stat pstats;
817 if (pcap_stats(in_p->handle, &pstats) != 0) {
818 ERROR(
"%s failed retrieving pcap stats: %s", in_p->name, pcap_geterr(in_p->handle));
823 ((
double) (pstats.ps_recv - in_p->pstats.ps_recv)) /
conf->
stats.interval);
824 if (p >= end)
goto oob;
827 for (i = 0; i < rs_codes_len; i++) {
831 if (slen < 0)
goto oob;
834 if (p >= end)
goto oob;
837 fprintf(stdout ,
"%s\n",
buffer);
854 if (!this->done_header) {
856 this->done_header =
true;
861 for (in_p = this->
in;
865 ERROR(
"Muting stats for the next %i milliseconds",
conf->
stats.timeout);
875 if ((stats->
quiet.tv_sec + (stats->
quiet.tv_usec / 1000000.0)) -
876 (now.tv_sec + (now.tv_usec / 1000000.0)) > 0)
goto clear;
878 for (i = 0; i < rs_codes_len; i++) {
883 if (this->body) this->body(
this, stats, &now);
885#ifdef HAVE_COLLECTDC_H
899 for (i = 0; i < rs_codes_len; i++) {
913 ERROR(
"Failed inserting stats interval event");
928 lint = (latency->tv_sec + (latency->tv_usec / 1000000.0)) * 1000;
929 if (lint > stats->
interval.latency_high) {
930 stats->
interval.latency_high = lint;
932 if (!stats->
interval.latency_low || (lint < stats->interval.latency_low)) {
935 stats->
interval.latency_total += (
long double) lint;
940 fr_pcap_t *
in,
struct timeval *now,
bool live)
945 memset(&update, 0,
sizeof(update));
948 update.
stats = stats;
963#ifdef HAVE_COLLECTDC_H
964 case RS_STATS_OUT_COLLECTD:
977 INFO(
"Muting stats for the next %i milliseconds (warmup)",
conf->
stats.timeout);
984 ERROR(
"Failed inserting stats event");
1006 for (i = 0; i < num; i++) {
1102 if ((request->
in->type == PCAP_INTERFACE_IN) && request->
logged) {
1150 if (!event->
out)
return 0;
1192 pcap_dump((
void *)event->
out->dumper, header,
data);
1200 if (!event->
out)
return 0;
1212 if (!(request->
capture_p->
header = talloc(request,
struct pcap_pkthdr)))
return -1;
1217 memcpy(request->
capture_p->
header, header,
sizeof(
struct pcap_pkthdr));
1229 pcap_dump((
void *)event->
out->dumper, header,
data);
1235#define RS_CLEANUP_NOW(_x, _s)\
1237 _x->silent_cleanup = _s;\
1238 _x->when = header->ts;\
1239 rs_packet_cleanup(_x);\
1262 struct timeval elapsed = {0, 0};
1263 struct timeval latency;
1278 static uint64_t captured = 0;
1289 memset(&search, 0,
sizeof(search));
1302 len = fr_pcap_link_layer_offset(
data, header->caplen, event->
in->link_layer);
1304 REDEBUG(
"Failed determining link layer header offset");
1309 version = (p[0] & 0xf0) >> 4;
1313 len = (0x0f & ip->
ip_vhl) * 4;
1324 REDEBUG(
"IP version invalid %i", version);
1332 if ((
size_t) len > header->caplen) {
1333 REDEBUG(
"Packet too small, we require at least %zu bytes, captured %i bytes",
1334 (
size_t) len, header->caplen);
1346 udp_len = ntohs(udp->
len);
1347 actual_len = header->caplen - (p -
data);
1349 if (udp_len > actual_len) {
1350 REDEBUG(
"Packet too small by %zi bytes, UDP header + Payload should be %hu bytes",
1351 udp_len - actual_len, udp_len);
1364 else if (udp_len < actual_len) {
1365 REDEBUG(
"Packet too big by %zi bytes, UDP header + Payload should be %hu bytes",
1366 actual_len - udp_len, udp_len);
1375 if (udp->checksum != expected) {
1376 REDEBUG(
"UDP checksum invalid, packet: 0x%04hx calculated: 0x%04hx",
1377 ntohs(udp->checksum), ntohs(expected));
1391 REDEBUG(
"Failed allocating memory to hold decoded packet");
1398 memcpy(&packet->
data, &p,
sizeof(packet->
data));
1406 packet->
socket.inet.src_ipaddr.
af = AF_INET;
1407 packet->
socket.inet.src_ipaddr.addr.v4.s_addr = ip->ip_src.s_addr;
1408 packet->
socket.inet.src_ipaddr.prefix = 32;
1410 packet->
socket.inet.dst_ipaddr.
af = AF_INET;
1411 packet->
socket.inet.dst_ipaddr.addr.v4.s_addr = ip->
ip_dst.s_addr;
1412 packet->
socket.inet.dst_ipaddr.prefix = 32;
1414 packet->
socket.inet.src_ipaddr.
af = AF_INET6;
1415 memcpy(packet->
socket.inet.src_ipaddr.addr.v6.s6_addr, ip6->ip_src.s6_addr,
1416 sizeof(packet->
socket.inet.src_ipaddr.addr.v6.s6_addr));
1417 packet->
socket.inet.src_ipaddr.prefix = 128;
1419 packet->
socket.inet.dst_ipaddr.
af = AF_INET6;
1420 memcpy(packet->
socket.inet.dst_ipaddr.addr.v6.s6_addr, ip6->
ip_dst.s6_addr,
1421 sizeof(packet->
socket.inet.dst_ipaddr.addr.v6.s6_addr));
1422 packet->
socket.inet.dst_ipaddr.prefix = 128;
1425 packet->
socket.inet.src_port = ntohs(udp->
src);
1426 packet->
socket.inet.dst_port = ntohs(udp->
dst);
1432 packet, &decoded, &elapsed, NULL,
false,
false);
1439 switch (packet->
code) {
1458 RDEBUG2(
"Response dropped by filter");
1476 fr_perror(
"Failed verifying packet ID %d", packet->
id);
1544 original->
linked = talloc_steal(original, packet);
1550 REDEBUG(
"Failed inserting new event");
1569 RDEBUG2(
"Original request dropped by filter");
1594 RDEBUG2(
"Request dropped by filter");
1601 switch (packet->
code) {
1614 fr_perror(
"Failed verifying packet ID %d", packet->
id);
1655 REDEBUG(
"Failed allocating memory to hold expected reply");
1669 ERROR(
"Failed extracting RTX linking pairs from request");
1689 if (tuple && (original != tuple)) {
1741 original->
packet = talloc_steal(original, packet);
1752 original->
expect = talloc_steal(original, search.
expect);
1763 original->
in =
event->in;
1769 original->
packet = talloc_steal(original, packet);
1772 original->
expect = talloc_steal(original, search.
expect);
1820 REDEBUG(
"Failed inserting new event");
1847 if (original && original->
linked) {
1866 struct timeval ts_tv;
1881 &elapsed, &latency, response,
true);
1894 print_id = original->
id;
1900 print_pair_list = &decoded;
1905 &elapsed, NULL, response,
true);
1914 if (response && !original) {
1923 INFO(
"Captured %" PRIu64
" packets, exiting...", captured);
1930 static uint64_t
count = 0;
1934 pcap_t *handle =
event->in->handle;
1939 struct pcap_pkthdr *header;
1950 last_sync = now_real;
1956 if ((event->in->type == PCAP_FILE_IN) || (event->in->type == PCAP_STDIO_IN)) {
1957 bool stats_started =
false;
1962 ret = pcap_next_ex(handle, &header, &
data);
1968 DEBUG(
"Done reading packets (%s)", event->in->name);
1978 ERROR(
"Error requesting next packet, got (%i): %s", ret, pcap_geterr(handle));
1986 if (
conf->
stats.interval && !stats_started) {
1988 stats_started =
true;
2006 ret = pcap_next_ex(handle, &header, &
data);
2012 ERROR(
"Error requesting next packet, got (%i): %s", ret, pcap_geterr(handle));
2023 struct timeval wake;
2027 if ((wake.tv_sec != 0) || (wake.tv_usec >= 100000)) {
2028 DEBUG2(
"Waking up in %d.%01u seconds", (
int) wake.tv_sec, (
unsigned int) wake.tv_usec / 100000);
2054 if (ret != 0)
return ret;
2057 if (ret != 0)
return ret;
2069 while ((tok =
strsep(&p,
"\t ,")) != NULL) {
2071 if ((*tok ==
'\t') || (*tok ==
' ') || (*tok ==
'\0')) {
2076 ERROR(
"Too many attributes, maximum allowed is %zu", len);
2083 ERROR(
"Error parsing attribute name \"%s\"", tok);
2109 .allow_compare =
true,
2115 fr_perror(
"Invalid RADIUS filter \"%s\"", filter);
2120 ERROR(
"Empty RADIUS filter '%s'", filter);
2138 while ((tok =
strsep(&p,
"\t ,")) != NULL) {
2141 if ((*tok ==
'\t') || (*tok ==
' ') || (*tok ==
'\0')) {
2147 ERROR(
"Invalid flag \"%s\"", tok);
2164 this->in_request_tree =
false;
2174 this->in_link_tree =
false;
2186#ifdef HAVE_COLLECTDC_H
2194 if (rs_stats_collectd_open(
conf) == 0) {
2195 DEBUG2(
"Stats output socket (re)opened");
2203 false, rs_collectd_reopen, NULL) < 0) {
2204 ERROR(
"Failed inserting re-open event");
2216 if (write(
self_pipe[1], &sig,
sizeof(sig)) < 0) {
2217 ERROR(
"Failed writing signal %s to pipe: %s", strsignal(sig),
fr_syserror(errno));
2226#ifndef HAVE_COLLECTDC_H
2234 ret = read(fd, &sig,
sizeof(sig));
2240 if (ret !=
sizeof(sig)) {
2241 ERROR(
"Failed reading signal from pipe: "
2242 "Expected signal to be %zu bytes but only read %zu byes",
sizeof(sig), ret);
2247#ifdef HAVE_COLLECTDC_H
2249 rs_collectd_reopen(list->tl,
fr_time(), list);
2258 DEBUG2(
"Signalling event loop to exit");
2263 ERROR(
"Unhandled signal %s", strsignal(sig));
2270 FILE *output = status ? stderr : stdout;
2271 fprintf(output,
"Usage: radsniff [options][stats options] -- [pcap files]\n");
2272 fprintf(output,
"options:\n");
2273 fprintf(output,
" -a List all interfaces available for capture.\n");
2274 fprintf(output,
" -c <count> Number of packets to capture.\n");
2275 fprintf(output,
" -C <checksum_type> Enable checksum validation. (Specify 'udp' or 'radius')\n");
2276 fprintf(output,
" -d <confdir> Set configuration directory (defaults to " CONFDIR
").\n");
2277 fprintf(output,
" -D <dictdir> Set main dictionary directory (defaults to " DICTDIR
").\n");
2278 fprintf(output,
" -e <event>[,<event>] Only log requests with these event flags.\n");
2279 fprintf(output,
" Event may be one of the following:\n");
2280 fprintf(output,
" - received - a request or response.\n");
2281 fprintf(output,
" - norsp - seen for a request.\n");
2282 fprintf(output,
" - rtx - of a request that we've seen before.\n");
2283 fprintf(output,
" - noreq - could be matched with the response.\n");
2284 fprintf(output,
" - reused - ID too soon.\n");
2285 fprintf(output,
" - error - decoding the packet.\n");
2286 fprintf(output,
" -f <filter> PCAP filter (default is 'udp port <port> or <port + 1> or %i'\n",
2288 fprintf(output,
" with extra rules to allow .1Q tagged packets)\n");
2289 fprintf(output,
" -h This help message.\n");
2290 fprintf(output,
" -i <interface> Capture packets from interface (defaults to all if supported).\n");
2291 fprintf(output,
" -I <file> Read packets from <file>\n");
2292 fprintf(output,
" -l <attr>[,<attr>] Output packet sig and a list of attributes.\n");
2293 fprintf(output,
" -L <attr>[,<attr>] Detect retransmissions using these attributes to link requests.\n");
2294 fprintf(output,
" -m Don't put interface(s) into promiscuous mode.\n");
2295 fprintf(output,
" -p <port> Filter packets by port (default is %i).\n",
FR_AUTH_UDP_PORT);
2296 fprintf(output,
" -P <pidfile> Daemonize and write out <pidfile>.\n");
2297 fprintf(output,
" -q Print less debugging information.\n");
2298 fprintf(output,
" -r <filter> RADIUS attribute request filter.\n");
2299 fprintf(output,
" -R <filter> RADIUS attribute response filter.\n");
2300 fprintf(output,
" -s <secret> RADIUS secret.\n");
2301 fprintf(output,
" -S Write PCAP data to stdout.\n");
2302 fprintf(output,
" -t <timeout> Stop after <timeout> seconds.\n");
2303 fprintf(output,
" -v Show program version information and exit.\n");
2304 fprintf(output,
" -w <file> Write output packets to file.\n");
2305 fprintf(output,
" -x Print more debugging information.\n");
2306 fprintf(output,
"stats options:\n");
2307 fprintf(output,
" -W <interval> Periodically write out statistics every <interval> seconds.\n");
2308 fprintf(output,
" -E Print stats in CSV format.\n");
2309 fprintf(output,
" -T <timeout> How many milliseconds before the request is counted as lost "
2311#ifdef HAVE_COLLECTDC_H
2312 fprintf(output,
" -N <prefix> The instance name passed to the collectd plugin.\n");
2313 fprintf(output,
" -O <server> Write statistics to this collectd server.\n");
2315 fprintf(output,
" -Z <output_dir> Dump the packets in <output_dir>/{requests,reply}.${count}.txt\n");
2325 fr_pcap_t *
in = NULL, *in_p;
2326 fr_pcap_t **in_head = &
in;
2327 fr_pcap_t *
out = NULL;
2329 int ret = EXIT_SUCCESS;
2331 char errbuf[PCAP_ERRBUF_SIZE];
2335 unsigned int timeout = 0;
2337 char const *confdir = CONFDIR;
2338 char const *dict_dir = DICTDIR;
2363 talloc_set_log_stderr();
2378#ifdef HAVE_COLLECTDC_H
2384#ifdef HAVE_COLLECTDC_H
2391 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) {
2395 pcap_if_t *all_devices = NULL;
2399 if (pcap_findalldevs(&all_devices, errbuf) < 0) {
2400 ERROR(
"Error getting available capture devices: %s", errbuf);
2405 for (dev_p = all_devices;
2407 dev_p = dev_p->next) {
2408 INFO(
"%i.%s", i++, dev_p->name);
2411 pcap_freealldevs(all_devices);
2419 ERROR(
"Invalid buffer length \"%s\"", optarg);
2427 ERROR(
"Invalid number of packets \"%s\"", optarg);
2434 if (strcmp(optarg,
"udp") == 0) {
2437 }
else if (strcmp(optarg,
"radius") == 0) {
2441 ERROR(
"Must specify 'udp' or 'radius' for -C, not %s", optarg);
2471 *in_head = fr_pcap_init(
conf, optarg, PCAP_INTERFACE_IN);
2472 if (!*in_head)
goto finish;
2473 in_head = &(*in_head)->next;
2478 *in_head = fr_pcap_init(
conf, optarg, PCAP_FILE_IN);
2482 in_head = &(*in_head)->next;
2499 port = atoi(optarg);
2527 timeout = atoi(optarg);
2535#ifdef HAVE_COLLECTDC_H
2537 lcc_version_string());
2544 out = fr_pcap_init(
conf, optarg, PCAP_FILE_OUT);
2546 ERROR(
"Failed creating pcap file \"%s\"", optarg);
2561 ERROR(
"Stats interval must be > 0");
2569 size_t len = strlen(p);
2574 if (p[len-1] ==
'/') p[len-1] =
'\0';
2588 ERROR(
"Timeout value must be > 0");
2593#ifdef HAVE_COLLECTDC_H
2600 conf->
stats.out = RS_STATS_OUT_COLLECTD;
2617 while (optind < argc) {
2618 *in_head = fr_pcap_init(
conf, argv[optind], PCAP_FILE_IN);
2622 in_head = &(*in_head)->next;
2628 if (!isatty(fileno(stdin))) {
2639 ERROR(
"Can't read from both a file and a device");
2645 ERROR(
"CSV output requires a statistics interval (-W)");
2660 out = fr_pcap_init(
conf,
"stdout", PCAP_STDIO_OUT);
2667 *in_head = fr_pcap_init(
conf,
"stdin", PCAP_STDIO_IN);
2671 in_head = &(*in_head)->next;
2699#if !defined(HAVE_PCAP_FOPEN_OFFLINE) || !defined(HAVE_PCAP_DUMP_FOPEN)
2701 ERROR(
"PCAP streams not supported");
2767 ERROR(
"Failed creating RTX tree");
2804 DEBUG(
"Logging all events");
2825 ERROR(
"Failed creating request tree");
2833 pcap_if_t *all_devices;
2836 if (pcap_findalldevs(&all_devices, errbuf) < 0) {
2837 ERROR(
"Error getting available capture devices: %s", errbuf);
2842 ERROR(
"No capture files specified and no live interfaces available");
2844 pcap_freealldevs(all_devices);
2848 for (dev_p = all_devices;
2850 dev_p = dev_p->next) {
2854 if (!strcmp(dev_p->name,
"any"))
continue;
2857 if (!strncmp(dev_p->name,
"pktap", 5))
continue;
2859 link_layer = fr_pcap_if_link_layer(dev_p);
2860 if (link_layer < 0) {
2865 if (!fr_pcap_link_layer_supported(link_layer)) {
2866 DEBUG2(
"Skipping %s: datalink type %s not supported",
2867 dev_p->name, pcap_datalink_val_to_name(link_layer));
2871 *in_head = fr_pcap_init(
conf, dev_p->name, PCAP_INTERFACE_IN);
2872 in_head = &(*in_head)->next;
2874 pcap_freealldevs(all_devices);
2878 INFO(
"Defaulting to capture on all interfaces");
2885 DEBUG2(
"Sniffing with options:");
2887 char *
buff = fr_pcap_device_names(
conf,
in,
' ');
2892 DEBUG2(
" Writing to : [%s]",
out->name);
2905 DEBUG2(
" RADIUS request filter :");
2918 DEBUG2(
" RADIUS response filter :");
2926#ifdef HAVE_COLLECTDC_H
2927 if (
conf->
stats.out == RS_STATS_OUT_COLLECTD) {
2929 rs_stats_tmpl_t *tmpl, **next;
2931 if (rs_stats_collectd_open(
conf) < 0) {
2938 tmpl = rs_stats_collectd_init_latency(
conf, next,
conf,
"exchanged",
2942 ERROR(
"Error allocating memory for stats template");
2945 next = &(tmpl->next);
2955 fr_pcap_t **tmp_p = &tmp;
2959 in_p = in_p->next) {
2962 if (fr_pcap_open(in_p) < 0) {
2963 fr_perror(
"Failed opening pcap handle (%s)", in_p->name);
2971 if (!fr_pcap_link_layer_supported(in_p->link_layer)) {
2972 ERROR(
"Failed opening pcap handle (%s): Datalink type %s not supported",
2973 in_p->name, pcap_datalink_val_to_name(in_p->link_layer));
2992 tmp_p = &(in_p->next);
2998 ERROR(
"No PCAP sources available");
3010 out->link_layer = -1;
3014 in_p = in_p->next) {
3015 if (
out->link_layer < 0) {
3016 out->link_layer = in_p->link_layer;
3020 if (
out->link_layer != in_p->link_layer) {
3021 ERROR(
"Asked to write to output file, but inputs do not have the same link type");
3029 if (fr_pcap_open(
out) < 0) {
3030 fr_perror(
"Failed opening pcap output (%s)",
out->name);
3067 fr_perror(
"Failed inserting signal pipe descriptor");
3087 in_p = in_p->next) {
3094 event->stats = stats;
3107 if (event->
in->type == PCAP_FILE_IN) {
3114 ERROR(
"Failed inserting file descriptor");
3122 ERROR(
"Failed inserting timeout event");
3149 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)
static TALLOC_CTX * autofree
#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_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_read(fr_dict_t *dict, char const *dict_dir, char const *filename))
Read supplementary attribute definitions into an existing dictionary.
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.
fr_dict_t const * fr_dict_internal(void)
#define fr_dict_autoload(_to_load)
#define DICT_AUTOLOAD_TERMINATOR
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.
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/.
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.
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.
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.
#define RADIUS_HEADER_LENGTH
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.
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.
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_current(_sbuff_or_marker)
#define FR_SBUFF_IN_STR(_start)
#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
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.
#define talloc_strdup(_ctx, _str)
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_DELETE(_ev_p)
static bool fr_timer_armed(fr_timer_t *ev)
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