27RCSID(
"$Id: 73344aa0c2d37c5c1dc43ad69d57031f9714cc4f $")
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++) {
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);
983 ERROR(
"Failed inserting stats event");
1005 for (i = 0; i < num; i++) {
1046 if (request->
event) {
1105 if ((request->
in->type == PCAP_INTERFACE_IN) && request->
logged) {
1136 request->
event = NULL;
1154 if (!event->
out)
return 0;
1196 pcap_dump((
void *)event->
out->dumper, header,
data);
1204 if (!event->
out)
return 0;
1216 if (!(request->
capture_p->
header = talloc(request,
struct pcap_pkthdr)))
return -1;
1221 memcpy(request->
capture_p->
header, header,
sizeof(
struct pcap_pkthdr));
1233 pcap_dump((
void *)event->
out->dumper, header,
data);
1239#define RS_CLEANUP_NOW(_x, _s)\
1241 _x->silent_cleanup = _s;\
1242 _x->when = header->ts;\
1243 rs_packet_cleanup(_x);\
1266 struct timeval elapsed = {0, 0};
1267 struct timeval latency;
1282 static uint64_t captured = 0;
1293 memset(&search, 0,
sizeof(search));
1306 len = fr_pcap_link_layer_offset(
data, header->caplen, event->
in->link_layer);
1308 REDEBUG(
"Failed determining link layer header offset");
1313 version = (p[0] & 0xf0) >> 4;
1317 len = (0x0f & ip->
ip_vhl) * 4;
1328 REDEBUG(
"IP version invalid %i", version);
1336 if ((
size_t) len > header->caplen) {
1337 REDEBUG(
"Packet too small, we require at least %zu bytes, captured %i bytes",
1338 (
size_t) len, header->caplen);
1350 udp_len = ntohs(udp->
len);
1351 actual_len = header->caplen - (p -
data);
1353 if (udp_len > actual_len) {
1354 REDEBUG(
"Packet too small by %zi bytes, UDP header + Payload should be %hu bytes",
1355 udp_len - actual_len, udp_len);
1368 else if (udp_len < actual_len) {
1369 REDEBUG(
"Packet too big by %zi bytes, UDP header + Payload should be %hu bytes",
1370 actual_len - udp_len, udp_len);
1379 if (udp->checksum != expected) {
1380 REDEBUG(
"UDP checksum invalid, packet: 0x%04hx calculated: 0x%04hx",
1381 ntohs(udp->checksum), ntohs(expected));
1395 REDEBUG(
"Failed allocating memory to hold decoded packet");
1402 memcpy(&packet->
data, &p,
sizeof(packet->
data));
1410 packet->
socket.inet.src_ipaddr.
af = AF_INET;
1411 packet->
socket.inet.src_ipaddr.addr.v4.s_addr = ip->ip_src.s_addr;
1413 packet->
socket.inet.dst_ipaddr.
af = AF_INET;
1414 packet->
socket.inet.dst_ipaddr.addr.v4.s_addr = ip->
ip_dst.s_addr;
1416 packet->
socket.inet.src_ipaddr.
af = AF_INET6;
1417 memcpy(packet->
socket.inet.src_ipaddr.addr.v6.s6_addr, ip6->ip_src.s6_addr,
1418 sizeof(packet->
socket.inet.src_ipaddr.addr.v6.s6_addr));
1420 packet->
socket.inet.dst_ipaddr.
af = AF_INET6;
1421 memcpy(packet->
socket.inet.dst_ipaddr.addr.v6.s6_addr, ip6->
ip_dst.s6_addr,
1422 sizeof(packet->
socket.inet.dst_ipaddr.addr.v6.s6_addr));
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);
1549 REDEBUG(
"Failed inserting new event");
1568 RDEBUG2(
"Original request dropped by filter");
1593 RDEBUG2(
"Request dropped by filter");
1600 switch (packet->
code) {
1613 fr_perror(
"Failed verifying packet ID %d", packet->
id);
1654 REDEBUG(
"Failed allocating memory to hold expected reply");
1668 ERROR(
"Failed extracting RTX linking pairs from request");
1688 if (tuple && (original != tuple)) {
1740 original->
packet = talloc_steal(original, packet);
1751 original->
expect = talloc_steal(original, search.
expect);
1762 original->
in =
event->in;
1768 original->
packet = talloc_steal(original, packet);
1771 original->
expect = talloc_steal(original, search.
expect);
1818 REDEBUG(
"Failed inserting new event");
1845 if (original && original->
linked) {
1864 struct timeval ts_tv;
1879 &elapsed, &latency, response,
true);
1892 print_id = original->
id;
1898 print_pair_list = &decoded;
1903 &elapsed, NULL, response,
true);
1912 if (response && !original) {
1921 INFO(
"Captured %" PRIu64
" packets, exiting...", captured);
1928 static uint64_t
count = 0;
1932 pcap_t *handle =
event->in->handle;
1937 struct pcap_pkthdr *header;
1948 last_sync = now_real;
1954 if ((event->in->type == PCAP_FILE_IN) || (event->in->type == PCAP_STDIO_IN)) {
1955 bool stats_started =
false;
1960 ret = pcap_next_ex(handle, &header, &
data);
1966 DEBUG(
"Done reading packets (%s)", event->in->name);
1976 ERROR(
"Error requesting next packet, got (%i): %s", ret, pcap_geterr(handle));
1984 if (
conf->
stats.interval && !stats_started) {
1986 stats_started =
true;
2004 ret = pcap_next_ex(handle, &header, &
data);
2010 ERROR(
"Error requesting next packet, got (%i): %s", ret, pcap_geterr(handle));
2021 struct timeval wake;
2025 if ((wake.tv_sec != 0) || (wake.tv_usec >= 100000)) {
2026 DEBUG2(
"Waking up in %d.%01u seconds", (
int) wake.tv_sec, (
unsigned int) wake.tv_usec / 100000);
2052 if (ret != 0)
return ret;
2055 if (ret != 0)
return ret;
2067 while ((tok =
strsep(&p,
"\t ,")) != NULL) {
2069 if ((*tok ==
'\t') || (*tok ==
' ') || (*tok ==
'\0')) {
2074 ERROR(
"Too many attributes, maximum allowed is %zu", len);
2081 ERROR(
"Error parsing attribute name \"%s\"", tok);
2105 .allow_compare =
true,
2110 fr_perror(
"Invalid RADIUS filter \"%s\"", filter);
2115 ERROR(
"Empty RADIUS filter '%s'", filter);
2133 while ((tok =
strsep(&p,
"\t ,")) != NULL) {
2136 if ((*tok ==
'\t') || (*tok ==
' ') || (*tok ==
'\0')) {
2142 ERROR(
"Invalid flag \"%s\"", tok);
2159 this->in_request_tree =
false;
2169 this->in_link_tree =
false;
2181#ifdef HAVE_COLLECTDC_H
2189 if (rs_stats_collectd_open(
conf) == 0) {
2190 DEBUG2(
"Stats output socket (re)opened");
2198 rs_collectd_reopen,
el) < 0) {
2199 ERROR(
"Failed inserting re-open event");
2211 if (write(
self_pipe[1], &sig,
sizeof(sig)) < 0) {
2212 ERROR(
"Failed writing signal %s to pipe: %s", strsignal(sig),
fr_syserror(errno));
2221#ifndef HAVE_COLLECTDC_H
2229 ret = read(fd, &sig,
sizeof(sig));
2235 if (ret !=
sizeof(sig)) {
2236 ERROR(
"Failed reading signal from pipe: "
2237 "Expected signal to be %zu bytes but only read %zu byes",
sizeof(sig), ret);
2242#ifdef HAVE_COLLECTDC_H
2244 rs_collectd_reopen(list,
fr_time(), list);
2253 DEBUG2(
"Signalling event loop to exit");
2258 ERROR(
"Unhandled signal %s", strsignal(sig));
2265 FILE *output = status ? stderr : stdout;
2266 fprintf(output,
"Usage: radsniff [options][stats options] -- [pcap files]\n");
2267 fprintf(output,
"options:\n");
2268 fprintf(output,
" -a List all interfaces available for capture.\n");
2269 fprintf(output,
" -c <count> Number of packets to capture.\n");
2270 fprintf(output,
" -C <checksum_type> Enable checksum validation. (Specify 'udp' or 'radius')\n");
2271 fprintf(output,
" -d <raddb> Set configuration directory (defaults to " RADDBDIR
").\n");
2272 fprintf(output,
" -D <dictdir> Set main dictionary directory (defaults to " DICTDIR
").\n");
2273 fprintf(output,
" -e <event>[,<event>] Only log requests with these event flags.\n");
2274 fprintf(output,
" Event may be one of the following:\n");
2275 fprintf(output,
" - received - a request or response.\n");
2276 fprintf(output,
" - norsp - seen for a request.\n");
2277 fprintf(output,
" - rtx - of a request that we've seen before.\n");
2278 fprintf(output,
" - noreq - could be matched with the response.\n");
2279 fprintf(output,
" - reused - ID too soon.\n");
2280 fprintf(output,
" - error - decoding the packet.\n");
2281 fprintf(output,
" -f <filter> PCAP filter (default is 'udp port <port> or <port + 1> or %i'\n",
2283 fprintf(output,
" with extra rules to allow .1Q tagged packets)\n");
2284 fprintf(output,
" -h This help message.\n");
2285 fprintf(output,
" -i <interface> Capture packets from interface (defaults to all if supported).\n");
2286 fprintf(output,
" -I <file> Read packets from <file>\n");
2287 fprintf(output,
" -l <attr>[,<attr>] Output packet sig and a list of attributes.\n");
2288 fprintf(output,
" -L <attr>[,<attr>] Detect retransmissions using these attributes to link requests.\n");
2289 fprintf(output,
" -m Don't put interface(s) into promiscuous mode.\n");
2290 fprintf(output,
" -p <port> Filter packets by port (default is %i).\n",
FR_AUTH_UDP_PORT);
2291 fprintf(output,
" -P <pidfile> Daemonize and write out <pidfile>.\n");
2292 fprintf(output,
" -q Print less debugging information.\n");
2293 fprintf(output,
" -r <filter> RADIUS attribute request filter.\n");
2294 fprintf(output,
" -R <filter> RADIUS attribute response filter.\n");
2295 fprintf(output,
" -s <secret> RADIUS secret.\n");
2296 fprintf(output,
" -S Write PCAP data to stdout.\n");
2297 fprintf(output,
" -t <timeout> Stop after <timeout> seconds.\n");
2298 fprintf(output,
" -v Show program version information and exit.\n");
2299 fprintf(output,
" -w <file> Write output packets to file.\n");
2300 fprintf(output,
" -x Print more debugging information.\n");
2301 fprintf(output,
"stats options:\n");
2302 fprintf(output,
" -W <interval> Periodically write out statistics every <interval> seconds.\n");
2303 fprintf(output,
" -E Print stats in CSV format.\n");
2304 fprintf(output,
" -T <timeout> How many milliseconds before the request is counted as lost "
2306#ifdef HAVE_COLLECTDC_H
2307 fprintf(output,
" -N <prefix> The instance name passed to the collectd plugin.\n");
2308 fprintf(output,
" -O <server> Write statistics to this collectd server.\n");
2310 fprintf(output,
" -Z <output_dir> Dump the packets in <output_dir>/{requests,reply}.${count}.txt\n");
2320 fr_pcap_t *
in = NULL, *in_p;
2321 fr_pcap_t **in_head = &
in;
2322 fr_pcap_t *
out = NULL;
2324 int ret = EXIT_SUCCESS;
2326 char errbuf[PCAP_ERRBUF_SIZE];
2330 unsigned int timeout = 0;
2332 char const *raddb_dir = RADDBDIR;
2333 char const *dict_dir = DICTDIR;
2358 talloc_set_log_stderr();
2373#ifdef HAVE_COLLECTDC_H
2379#ifdef HAVE_COLLECTDC_H
2386 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) {
2390 pcap_if_t *all_devices = NULL;
2394 if (pcap_findalldevs(&all_devices, errbuf) < 0) {
2395 ERROR(
"Error getting available capture devices: %s", errbuf);
2400 for (dev_p = all_devices;
2402 dev_p = dev_p->next) {
2403 INFO(
"%i.%s", i++, dev_p->name);
2406 pcap_freealldevs(all_devices);
2414 ERROR(
"Invalid buffer length \"%s\"", optarg);
2422 ERROR(
"Invalid number of packets \"%s\"", optarg);
2429 if (strcmp(optarg,
"udp") == 0) {
2432 }
else if (strcmp(optarg,
"radius") == 0) {
2436 ERROR(
"Must specify 'udp' or 'radius' for -C, not %s", optarg);
2466 *in_head = fr_pcap_init(
conf, optarg, PCAP_INTERFACE_IN);
2467 if (!*in_head)
goto finish;
2468 in_head = &(*in_head)->next;
2473 *in_head = fr_pcap_init(
conf, optarg, PCAP_FILE_IN);
2477 in_head = &(*in_head)->next;
2494 port = atoi(optarg);
2522 timeout = atoi(optarg);
2530#ifdef HAVE_COLLECTDC_H
2532 lcc_version_string());
2539 out = fr_pcap_init(
conf, optarg, PCAP_FILE_OUT);
2541 ERROR(
"Failed creating pcap file \"%s\"", optarg);
2556 ERROR(
"Stats interval must be > 0");
2564 size_t len = strlen(p);
2569 if (p[len-1] ==
'/') p[len-1] =
'\0';
2583 ERROR(
"Timeout value must be > 0");
2588#ifdef HAVE_COLLECTDC_H
2595 conf->
stats.out = RS_STATS_OUT_COLLECTD;
2612 while (optind < argc) {
2613 *in_head = fr_pcap_init(
conf, argv[optind], PCAP_FILE_IN);
2617 in_head = &(*in_head)->next;
2623 if (!isatty(fileno(stdin))) {
2634 ERROR(
"Can't read from both a file and a device");
2640 ERROR(
"CSV output requires a statistics interval (-W)");
2655 out = fr_pcap_init(
conf,
"stdout", PCAP_STDIO_OUT);
2662 *in_head = fr_pcap_init(
conf,
"stdin", PCAP_STDIO_IN);
2666 in_head = &(*in_head)->next;
2694#if !defined(HAVE_PCAP_FOPEN_OFFLINE) || !defined(HAVE_PCAP_DUMP_FOPEN)
2696 ERROR(
"PCAP streams not supported");
2762 ERROR(
"Failed creating RTX tree");
2799 DEBUG(
"Logging all events");
2820 ERROR(
"Failed creating request tree");
2828 pcap_if_t *all_devices;
2831 if (pcap_findalldevs(&all_devices, errbuf) < 0) {
2832 ERROR(
"Error getting available capture devices: %s", errbuf);
2837 ERROR(
"No capture files specified and no live interfaces available");
2839 pcap_freealldevs(all_devices);
2843 for (dev_p = all_devices;
2845 dev_p = dev_p->next) {
2849 if (!strcmp(dev_p->name,
"any"))
continue;
2852 if (!strncmp(dev_p->name,
"pktap", 5))
continue;
2854 link_layer = fr_pcap_if_link_layer(dev_p);
2855 if (link_layer < 0) {
2860 if (!fr_pcap_link_layer_supported(link_layer)) {
2861 DEBUG2(
"Skipping %s: datalink type %s not supported",
2862 dev_p->name, pcap_datalink_val_to_name(link_layer));
2866 *in_head = fr_pcap_init(
conf, dev_p->name, PCAP_INTERFACE_IN);
2867 in_head = &(*in_head)->next;
2869 pcap_freealldevs(all_devices);
2873 INFO(
"Defaulting to capture on all interfaces");
2880 DEBUG2(
"Sniffing with options:");
2882 char *
buff = fr_pcap_device_names(
conf,
in,
' ');
2887 DEBUG2(
" Writing to : [%s]",
out->name);
2900 DEBUG2(
" RADIUS request filter :");
2913 DEBUG2(
" RADIUS response filter :");
2921#ifdef HAVE_COLLECTDC_H
2922 if (
conf->
stats.out == RS_STATS_OUT_COLLECTD) {
2924 rs_stats_tmpl_t *tmpl, **next;
2926 if (rs_stats_collectd_open(
conf) < 0) {
2933 tmpl = rs_stats_collectd_init_latency(
conf, next,
conf,
"exchanged",
2937 ERROR(
"Error allocating memory for stats template");
2940 next = &(tmpl->next);
2950 fr_pcap_t **tmp_p = &tmp;
2954 in_p = in_p->next) {
2957 if (fr_pcap_open(in_p) < 0) {
2958 fr_perror(
"Failed opening pcap handle (%s)", in_p->name);
2966 if (!fr_pcap_link_layer_supported(in_p->link_layer)) {
2967 ERROR(
"Failed opening pcap handle (%s): Datalink type %s not supported",
2968 in_p->name, pcap_datalink_val_to_name(in_p->link_layer));
2987 tmp_p = &(in_p->next);
2993 ERROR(
"No PCAP sources available");
3005 out->link_layer = -1;
3009 in_p = in_p->next) {
3010 if (
out->link_layer < 0) {
3011 out->link_layer = in_p->link_layer;
3015 if (
out->link_layer != in_p->link_layer) {
3016 ERROR(
"Asked to write to output file, but inputs do not have the same link type");
3024 if (fr_pcap_open(
out) < 0) {
3025 fr_perror(
"Failed opening pcap output (%s)",
out->name);
3062 fr_perror(
"Failed inserting signal pipe descriptor");
3082 in_p = in_p->next) {
3089 event->stats = stats;
3102 if (event->
in->type == PCAP_FILE_IN) {
3109 ERROR(
"Failed inserting file descriptor");
3117 ERROR(
"Failed inserting timeout event");
3144 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/.
#define fr_event_timer_at(...)
#define fr_event_timer_in(...)
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.
int fr_event_timer_delete(fr_event_timer_t const **ev_p)
Delete a timer event from the event list.
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.
int fr_event_timer_run(fr_event_list_t *el, fr_time_t *when)
Run a single scheduled timer event.
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 void rs_stats_process(fr_event_list_t *el, fr_time_t now_t, void *ctx)
Process stats for a single interval.
static int rs_request_to_pcap(rs_event_t *event, rs_request_t *request, struct pcap_pkthdr const *header, uint8_t const *data)
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 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 _rs_event(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *ctx)
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 timeout_event(fr_event_list_t *el, UNUSED fr_time_t now_t, UNUSED void *ctx)
Exit the event loop after a given timeout.
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.
fr_event_timer_t const * event
Event created when we received the original request.
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.
@ 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.
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.
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