27RCSID(
"$Id: 3ceab13e63dfd2a996b1245223ead0e8cc683535 $")
 
   33#include <freeradius-devel/autoconf.h> 
   34#include <freeradius-devel/radius/list.h> 
   35#include <freeradius-devel/util/conf.h> 
   36#include <freeradius-devel/util/event.h> 
   37#include <freeradius-devel/util/file.h> 
   38#include <freeradius-devel/util/syserror.h> 
   39#include <freeradius-devel/util/atexit.h> 
   40#include <freeradius-devel/util/pair_legacy.h> 
   41#include <freeradius-devel/util/base16.h> 
   42#include <freeradius-devel/util/pcap.h> 
   43#include <freeradius-devel/util/timeval.h> 
   45#ifdef HAVE_COLLECTDC_H 
   46#  include <collectd/client.h> 
   51#define RS_ASSERT(_x) if (!(_x) && !fr_cond_assert(_x)) exit(1) 
  150        if ((chdir(
"/")) < 0) {
 
  158        fp = fopen(pidfile, 
"w");
 
  160                fprintf(fp, 
"%d\n", (
int) sid);
 
  170        if (isatty(fileno(stdout))) {
 
  171                if (!freopen(
"/dev/null", 
"w", stdout)) {
 
  176        if (isatty(fileno(stderr))) {
 
  177                if (!freopen(
"/dev/null", 
"w", stderr)) {
 
 
  183static void rs_tv_add_ms(
struct timeval 
const *start, 
unsigned long interval, 
struct timeval *result) {
 
  184    result->tv_sec = start->tv_sec + (interval / 1000);
 
  185    result->tv_usec = start->tv_usec + ((interval % 1000) * 1000);
 
  187    if (result->tv_usec > 
USEC) {
 
  188        result->tv_usec -= 
USEC;
 
 
  205        ret = strftime(
out, len, 
"%Y-%m-%d %H:%M:%S", 
localtime_r(&t->tv_sec, &result));
 
  213                while (usec < 100000) usec *= 10;
 
 
  222        char const      *start = 
out;
 
  237        while ((
inlen > 0) && (outlen > 2)) {
 
  249                if ((*str == 
'\r') || (*str == 
'\n') || ((*str >= 
'\x20') && (*str <= 
'\x7E'))) {
 
 
  276        len = 
strlcpy(p, 
"\"Status\",\"Count\",\"Time\",\"Latency\",\"Type\",\"Interface\"," 
  277                      "\"Src IP\",\"Src Port\",\"Dst IP\",\"Dst Port\",\"ID\",", s);
 
  306        fprintf(stdout , 
"%s\n", 
buffer);
 
 
  311                                UNUSED struct timeval *elapsed, 
struct timeval *latency, 
UNUSED bool response,
 
  314        char const      *status_str;
 
  318        char src[INET6_ADDRSTRLEN];
 
  319        char dst[INET6_ADDRSTRLEN];
 
  331                                        (
unsigned int) latency->tv_sec,
 
  332                                        ((
unsigned int) latency->tv_usec / 1000)) < 0) 
return;
 
  341                                        src, packet->
socket.inet.src_port, dst, packet->
socket.inet.dst_port, packet->
id) < 0) 
return;
 
  343                if (
fr_sbuff_in_sprintf(&sbuff, 
"%u,%s,%s,%i,%s,%i,%i,", packet->
code, handle->name,
 
  344                                        src, packet->
socket.inet.src_port, dst, packet->
socket.inet.dst_port, packet->
id) < 0) 
return;
 
  353                        if (
vp && (
vp->vp_length > 0)) {
 
  360                                                              vp->vp_strvalue, 
vp->vp_length);
 
  361                                        if (slen < 0) 
return;
 
  377                fr_sbuff_terminate(&sbuff);
 
  380        fprintf(stdout , 
"%s\n", 
buffer);
 
 
  385                                  struct timeval *elapsed, 
struct timeval *latency, 
bool response, 
bool body)
 
  390        char src[INET6_ADDRSTRLEN];
 
  391        char dst[INET6_ADDRSTRLEN];
 
  400                char const *status_str;
 
  405                len = 
snprintf(p, s, 
"** %s ** ", status_str);
 
  412                len = 
snprintf(p, s, 
"%s Id %i %s:%s:%d %s %s:%i ",
 
  416                               response ? dst : src,
 
  417                               response ? packet->
socket.inet.dst_port : packet->
socket.inet.src_port,
 
  418                               response ? 
"<-" : 
"->",
 
  419                               response ? src : dst ,
 
  420                               response ? packet->
socket.inet.src_port : packet->
socket.inet.dst_port);
 
  422                len = 
snprintf(p, s, 
"%u Id %i %s:%s:%i %s %s:%i ",
 
  426                               response ? dst : src,
 
  427                               response ? packet->
socket.inet.dst_port : packet->
socket.inet.src_port,
 
  428                               response ? 
"<-" : 
"->",
 
  429                               response ? src : dst ,
 
  430                               response ? packet->
socket.inet.src_port : packet->
socket.inet.dst_port);
 
  438                               (
unsigned int) elapsed->tv_sec, ((
unsigned int) elapsed->tv_usec / 1000));
 
  446                               (
unsigned int) latency->tv_sec, ((
unsigned int) latency->tv_usec / 1000));
 
 
  480                                  UNUSED struct timeval *elapsed, 
UNUSED struct timeval *latency, 
bool response, 
bool body)
 
  485        char const *packet_type = response ? 
"reply" : 
"request";
 
  493                DEBUG2(
"Saving %s in %s", packet_type, filename);
 
  500                ERROR(
"Failed opening %s output file.", filename);
 
  518                ERROR(
"Failed closing %s output file.", filename);
 
 
  531                                   struct timeval *elapsed, 
struct timeval *latency,
 
  532                                   bool response, 
bool body)
 
  536        if (request) request->
logged = 
true;
 
  537        conf->
logger(
count, status, handle, packet, list, elapsed, latency, response, body);
 
 
  555        struct pcap_stat pstats;
 
  557        if (pcap_stats(
in->handle, &pstats) != 0) {
 
  558                ERROR(
"%s failed retrieving pcap stats: %s", 
in->name, pcap_geterr(
in->handle));
 
  562        if (pstats.ps_drop - 
in->pstats.ps_drop > 0) {
 
  563                ERROR(
"%s dropped %i packets: Buffer exhaustion", 
in->name, pstats.ps_drop - 
in->pstats.ps_drop);
 
  567        if (pstats.ps_ifdrop - 
in->pstats.ps_ifdrop > 0) {
 
  568                ERROR(
"%s dropped %i packets: Interface", 
in->name, pstats.ps_ifdrop - 
in->pstats.ps_ifdrop);
 
 
  590        if (stats->
interval.linked_total == 0) {
 
  591                double unk = strtod(
"NAN()", (
char **) NULL);
 
  593                stats->
interval.latency_average = unk;
 
  613        if (stats->
interval.latency_average > 0) {
 
 
  638        bool have_rt = 
false;
 
  642        if (!stats->
interval.received && !have_rt && !stats->
interval.reused) 
return;
 
  657                INFO(
"\tAverage   : %.3lfms", stats->
interval.latency_average);
 
  668                        if (!stats->
interval.rt[i]) 
continue;
 
 
  691        if ((stats->
quiet.tv_sec + (stats->
quiet.tv_usec / 1000000.0)) -
 
  692            (now->tv_sec + (now->tv_usec / 1000000.0)) > 0) {
 
  693                INFO(
"Stats muted because of warmup, or previous error");
 
  697        INFO(
"######### Stats Iteration %i #########", stats->
intervals);
 
  699        if (this->
in) 
INFO(
"Interface capture rate:");
 
  700        for (in_p = this->
in;
 
  703                struct pcap_stat pstats;
 
  705                if (pcap_stats(in_p->handle, &pstats) != 0) {
 
  706                        ERROR(
"%s failed retrieving pcap stats: %s", in_p->name, pcap_geterr(in_p->handle));
 
  710                INFO(
"\t%s%*s: %.3lf/s", in_p->name, (
int) (10 - strlen(in_p->name)), 
"",
 
  711                     ((
double) (pstats.ps_recv - in_p->pstats.ps_recv)) / 
conf->
stats.interval);
 
  719        for (i = 0; i < rs_codes_len; i++) {
 
 
  733        fprintf(stdout, 
"\"Iteration\"");
 
  735        for (in_p = this->
in; in_p; in_p = in_p->next) {
 
  736                fprintf(stdout, 
",\"%s PPS\"", in_p->name);
 
  739        for (i = 0; i < rs_codes_len; i++) {
 
  746                        ",\"%s lat high (ms)\"" 
  747                        ",\"%s lat low (ms)\"" 
  748                        ",\"%s lat avg (ms)\"" 
  749                        ",\"%s lat ma (ms)\"" 
  764                                fprintf(stdout, 
",\"%s rtx (%i)\"", 
name, j);
 
  766                                fprintf(stdout, 
",\"%s rtx (%i+)\"", 
name, j);
 
  771        fprintf(stdout , 
"\n");
 
 
  777        char    *p = 
out, *end = 
out + outlen;
 
  779        p += 
snprintf(
out, outlen, 
",%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf,%.3lf",
 
  789        if (p >= end) 
return -1;
 
  793                if (p >= end) 
return -1;
 
 
  809                ERROR(
"Exceeded line buffer size");
 
  813        for (in_p = this->
in;
 
  816                struct pcap_stat pstats;
 
  818                if (pcap_stats(in_p->handle, &pstats) != 0) {
 
  819                        ERROR(
"%s failed retrieving pcap stats: %s", in_p->name, pcap_geterr(in_p->handle));
 
  824                              ((
double) (pstats.ps_recv - in_p->pstats.ps_recv)) / 
conf->
stats.interval);
 
  825                if (p >= end) 
goto oob;
 
  828        for (i = 0; i < rs_codes_len; i++) {
 
  832                if (slen < 0) 
goto oob;
 
  835                if (p >= end) 
goto oob;
 
  838        fprintf(stdout , 
"%s\n", 
buffer);
 
 
  855        if (!this->done_header) {
 
  857                this->done_header = 
true;
 
  862        for (in_p = this->
in;
 
  866                        ERROR(
"Muting stats for the next %i milliseconds", 
conf->
stats.timeout);
 
  876        if ((stats->
quiet.tv_sec + (stats->
quiet.tv_usec / 1000000.0)) -
 
  877            (now.tv_sec + (now.tv_usec / 1000000.0)) > 0) 
goto clear;
 
  879        for (i = 0; i < rs_codes_len; i++) {
 
  884        if (this->body) this->body(
this, stats, &now);
 
  886#ifdef HAVE_COLLECTDC_H 
  900        for (i = 0; i < rs_codes_len; i++) {
 
  914                        ERROR(
"Failed inserting stats interval event");
 
 
  929        lint = (latency->tv_sec + (latency->tv_usec / 1000000.0)) * 1000;
 
  930        if (lint > stats->
interval.latency_high) {
 
  931                stats->
interval.latency_high = lint;
 
  933        if (!stats->
interval.latency_low || (lint < stats->interval.latency_low)) {
 
  936        stats->
interval.latency_total += (
long double) lint;
 
 
  941                                      fr_pcap_t *
in, 
struct timeval *now, 
bool live)
 
  946        memset(&update, 0, 
sizeof(update));
 
  949        update.
stats = stats;
 
  964#ifdef HAVE_COLLECTDC_H 
  965        case RS_STATS_OUT_COLLECTD:
 
  978                INFO(
"Muting stats for the next %i milliseconds (warmup)", 
conf->
stats.timeout);
 
  985                ERROR(
"Failed inserting stats event");
 
 
 1007        for (i = 0; i < num; i++) {
 
 
 1103                if ((request->
in->type == PCAP_INTERFACE_IN) && request->
logged) {
 
 
 1151        if (!event->
out) 
return 0;
 
 1193        pcap_dump((
void *)event->
out->dumper, header, 
data);
 
 
 1201        if (!event->
out) 
return 0;
 
 1213                if (!(request->
capture_p->
header = talloc(request, 
struct pcap_pkthdr))) 
return -1;
 
 1218                memcpy(request->
capture_p->
header, header, 
sizeof(
struct pcap_pkthdr));
 
 1230        pcap_dump((
void *)event->
out->dumper, header, 
data);
 
 
 1236#define RS_CLEANUP_NOW(_x, _s)\ 
 1238                _x->silent_cleanup = _s;\ 
 1239                _x->when = header->ts;\ 
 1240                rs_packet_cleanup(_x);\ 
 
 1263        struct timeval          elapsed = {0, 0};
 
 1264        struct timeval          latency;
 
 1279        static uint64_t         captured = 0;
 
 1290        memset(&search, 0, 
sizeof(search));
 
 1303        len = fr_pcap_link_layer_offset(
data, header->caplen, event->
in->link_layer);
 
 1305                REDEBUG(
"Failed determining link layer header offset");
 
 1310        version = (p[0] & 0xf0) >> 4;
 
 1314                len = (0x0f & ip->
ip_vhl) * 4;  
 
 1325                REDEBUG(
"IP version invalid %i", version);
 
 1333        if ((
size_t) len > header->caplen) {
 
 1334                REDEBUG(
"Packet too small, we require at least %zu bytes, captured %i bytes",
 
 1335                        (
size_t) len, header->caplen);
 
 1347                udp_len = ntohs(udp->
len);
 
 1348                actual_len = header->caplen - (p - 
data);
 
 1350                if (udp_len > actual_len) {
 
 1351                        REDEBUG(
"Packet too small by %zi bytes, UDP header + Payload should be %hu bytes",
 
 1352                                udp_len - actual_len, udp_len);
 
 1365                else if (udp_len < actual_len) {
 
 1366                        REDEBUG(
"Packet too big by %zi bytes, UDP header + Payload should be %hu bytes",
 
 1367                                actual_len - udp_len, udp_len);
 
 1376                        if (udp->checksum != expected) {
 
 1377                                REDEBUG(
"UDP checksum invalid, packet: 0x%04hx calculated: 0x%04hx",
 
 1378                                        ntohs(udp->checksum), ntohs(expected));
 
 1392                REDEBUG(
"Failed allocating memory to hold decoded packet");
 
 1399        memcpy(&packet->
data, &p, 
sizeof(packet->
data));
 
 1407                packet->
socket.inet.src_ipaddr.
af = AF_INET;
 
 1408                packet->
socket.inet.src_ipaddr.addr.v4.s_addr = ip->ip_src.s_addr;
 
 1409                packet->
socket.inet.src_ipaddr.prefix = 32;
 
 1411                packet->
socket.inet.dst_ipaddr.
af = AF_INET;
 
 1412                packet->
socket.inet.dst_ipaddr.addr.v4.s_addr = ip->
ip_dst.s_addr;
 
 1413                packet->
socket.inet.dst_ipaddr.prefix = 32;
 
 1415                packet->
socket.inet.src_ipaddr.
af = AF_INET6;
 
 1416                memcpy(packet->
socket.inet.src_ipaddr.addr.v6.s6_addr, ip6->ip_src.s6_addr,
 
 1417                       sizeof(packet->
socket.inet.src_ipaddr.addr.v6.s6_addr));
 
 1418                packet->
socket.inet.src_ipaddr.prefix = 128;
 
 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));
 
 1423                packet->
socket.inet.dst_ipaddr.prefix = 128;
 
 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)
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_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.
#define DICT_AUTOLOAD_TERMINATOR
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.
#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.
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.
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
#define fr_time()
Allow us to arbitrarily manipulate time.
size_t strlcpy(char *dst, char const *src, size_t siz)
fr_log_timestamp_t timestamp
Prefix log messages with timestamps.
bool print_level
sometimes we don't want log levels printed
FILE * handle
Path to log file.
Stores an attribute, a value and various bits of other data.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in a lexicographically sorted array of name to num mappings.
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
int fr_time_sync(void)
Get a new fr_time_monotonic_to_realtime value.
int fr_time_start(void)
Initialize the local time.
static fr_time_t fr_time_from_timeval(struct timeval const *when_tv)
Convert a timeval (wallclock time) to a fr_time_t (internal time)
static fr_time_delta_t fr_time_delta_from_msec(int64_t msec)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_wrap(_time)
#define fr_time_delta_to_timeval(_delta)
Convert a delta to a timeval.
#define fr_time_add(_a, _b)
Add a time/time delta together.
#define fr_time_to_timeval(_when)
Convert server epoch time to unix epoch time.
#define fr_time_sub(_a, _b)
Subtract one time from another.
#define fr_time_delta_gt(_a, _b)
A time delta, a difference in time measured in nanoseconds.
int fr_timer_list_run(fr_timer_list_t *tl, fr_time_t *when)
Execute any pending events in the event loop.
#define FR_TIMER_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