26#include <freeradius-devel/server/protocol.h> 
   27#include <freeradius-devel/server/pair.h> 
   28#include <freeradius-devel/server/main_loop.h> 
   29#include <freeradius-devel/io/application.h> 
   30#include <freeradius-devel/io/listen.h> 
   31#include <freeradius-devel/util/syserror.h> 
   49#define MPRINT(_x, ...) 
  122        request->client = 
inst->client;
 
  124        request->packet->id = track->
id;
 
  125        request->reply->id = track->
id;
 
 
  152        uint8_t                         *partial, *end, *next, *p, *record_end;
 
  234        partial = 
buffer + *leftover;
 
  236        MPRINT(
"READ leftover %zd", *leftover);
 
  244                room = buffer_len - *leftover;
 
  246                data_size = read(thread->
fd, partial, room);
 
  248                        ERROR(
"proto_detail (%s): Failed reading file %s: %s",
 
  253                MPRINT(
"GOT %zd bytes", data_size);
 
  265                        MPRINT(
"Set EOF data_size %ld vs room %ld", data_size, room);
 
  268                end = partial + data_size;
 
  282        stopped_search = end;
 
  301                if ((p + 1) == end) {
 
  315                        stopped_search = next;
 
  325                        ERROR(
"proto_detail (%s): Missing tab indent at %s[%u], offset from start of file %zu",
 
  341                if ((p + 2) >= end) {
 
  351                while ((p < end) && !isspace((
uint8_t) *p)) p++;
 
  367                if (memcmp(p, 
" = ", 3) != 0) {
 
  368                        ERROR(
"proto_detail (%s): Missing pair assignment operator at %s[%u], offset from start of file %zu: %.*s",
 
  389                packet_len = next - 
buffer;
 
  390                *leftover = end - next;
 
  392                MPRINT(
"FOUND next at %zd, leftover is %zd", packet_len, *leftover);
 
  394        } 
else if (!thread->
eof) {
 
  395                if ((
size_t) (end - 
buffer) == buffer_len) {
 
  396                        ERROR(
"proto_detail (%s): Too large entry (>%d bytes) found at offset %zu: %.*s of file %s",
 
  397                              thread->
name, (
int) buffer_len,
 
  410                MPRINT(
"Not at EOF, and no next.  Leftover is %zd", *leftover);
 
  419                packet_len = end - 
buffer;
 
  422                MPRINT(
"NO end of record, but at EOF, found %zd leftover is 0", packet_len);
 
  430        if (packet_len > 
inst->parent->max_packet_size) {
 
  431                DEBUG(
"Ignoring 'too large' entry at offset %zu of %s",
 
  433                DEBUG(
"Entry size %lu is greater than allowed maximum %u",
 
  434                      packet_len, 
inst->parent->max_packet_size);
 
  436                MPRINT(
"Skipping record");
 
  438                        memmove(
buffer, next, (end - next));
 
  439                        data_size = (end - next);
 
  447                        if (end == 
buffer) 
return 0;
 
  459        record_end = 
buffer + packet_len;
 
  463        while (p < record_end) {
 
  470                if (p == record_end) 
break;
 
  472                if (((record_end - p) >= 5) &&
 
  473                    (memcmp(p, 
"\tDone", 5) == 0)) {
 
  477                if (((record_end - p) > 10) &&
 
  478                    (memcmp(p, 
"\tTimestamp", 10) == 0)) {
 
  493        if (
inst->retransmit) {
 
  512                thread->
closing = (*leftover == 0);
 
  528                if (*leftover) (void) lseek(thread->
fd, thread->
read_offset - 1, SEEK_SET);
 
 
  547        DEBUG(
"%s - retransmitting packet %d", thread->
name, track->
id);
 
  565        (void) lseek(thread->
fd, 0, SEEK_SET);
 
 
  579        if (buffer_len < 1) 
return -1;
 
  585                if (!
inst->retransmit) 
goto mark_done;
 
  594                                DEBUG(
"%s - packet %d failed after %u retransmissions",
 
  601                                DEBUG(
"%s - packet %d failed after %u seconds",
 
  608                DEBUG(
"%s - packet %d failed during processing.  Will retransmit in %.6fs",
 
  613                        ERROR(
"%s - Failed inserting retransmission timeout", thread->
name);
 
  633                if (write(thread->
fd, 
"Done", 4) < 0) {
 
  654                (void) lseek(thread->
fd, 0, SEEK_SET);
 
  667                MPRINT(
"WRITE ASKED TO CLOSE");
 
  671        MPRINT(
"WRITE RETURN B %ld", buffer_len);
 
 
  688        if (thread->
fd < 0) {
 
  692                if (thread->
fd < 0) {
 
  701        if (
inst->track_progress) {
 
  704                if (fstat(thread->
fd, &buf) < 0) {
 
 
  752        DEBUG(
"Closing %sdetail worker file %s", thread->
outstanding == 0 ? 
"and deleting " : 
"", thread->
name);
 
  764        if (
inst->parent->exit_when_done) {
 
  765                INFO(
"Done reading detail files, process will now exit");
 
 
  798        DEBUG(
"Detail worker %s had file system unmounted.  Stopping.", thread->
name);
 
  817        memset(&funcs, 0, 
sizeof(funcs));
 
  818        funcs.revoke = mod_revoke;
 
  821                WARN(
"Failed to add event watching for unmounted file system");
 
 
  847        if (
inst->track_progress) {
 
  850                inst->mode = O_RDONLY;
 
  853        if (
inst->retransmit) {
 
  873        if (!
inst->client) 
return 0;
 
  876        client->
ipaddr.
addr.v4.s_addr = htonl(INADDR_NONE);
 
  880        client->
nas_type = talloc_strdup(client, 
"other");
 
 
  892                .name                   = 
"detail_work",
 
  898        .default_message_size   = 65536,
 
  899        .default_reply_size     = 32,
 
 
static int const char char buffer[256]
module_t common
Common fields to all loadable modules.
Public structure describing an I/O path for a protocol.
#define CONF_PARSER_TERMINATOR
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Defines a CONF_PAIR to C data type mapping.
A section grouping multiple CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
static int max_outstanding
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.
#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 MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Entry in a doubly linked list.
@ FR_EVENT_FILTER_VNODE
Filter for vnode subfilters.
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
#define fr_event_filter_update(...)
#define fr_event_filter_insert(...)
#define FR_EVENT_RESUME(_s, _f)
Re-add the filter for a func from kevent.
#define FR_EVENT_SUSPEND(_s, _f)
Temporarily remove the filter for a func from kevent.
Callbacks for the FR_EVENT_FILTER_IO filter.
Structure describing a modification to a filter's state.
Callbacks for the FR_EVENT_FILTER_VNODE filter.
union fr_ipaddr_t::@138 addr
void const  * app_io_instance
I/O path configuration context.
void * thread_instance
thread / socket context
bool no_write_callback
sometimes we don't need to do writes
int fd
file descriptor for this socket - set by open
void fr_network_listen_read(fr_network_t *nr, fr_listen_t *li)
Signal the network to read from a listener.
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
char const  * secret
Secret PSK.
fr_ipaddr_t src_ipaddr
IPv4/IPv6 address to send responses from (family must match ipaddr).
char const  * nas_type
Type of client (arbitrary).
char const  * longname
Client identifier.
char const  * shortname
Client nickname.
Describes a host allowed to send packets to the server.
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.
Stores all information relating to an event list.
void main_loop_signal_raise(int flag)
@ RADIUS_SIGNAL_SELF_TERM
@ FR_TYPE_UINT32
32 Bit unsigned integer.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for instantiation calls.
Detail master protocol handler.
struct proto_detail_work_s proto_detail_work_t
size_t last_search
where we last searched in the buffer MUST be offset, as the buffers can change.
proto_detail_work_thread_t * file_parent
thread instance of the directory reader that spawned us
bool paused
Is reading paused?
int count
number of packets we read from this file.
unsigned int last_line
line number of the last record read.
bool eof
are we at EOF on reading?
fr_listen_t * listen
talloc_parent() is slow
char const  * name
debug name for printing
int num_workers
number of workers
uint16_t max_outstanding
number of packets to run in parallel
fr_event_list_t * el
for various timers
off_t file_size
size of the file
uint8_t * leftover_buffer
pthread_mutex_t worker_mutex
for the workers
char const  * filename_work
work file name
off_t header_offset
offset of the current header we're reading
proto_detail_work_t const  * inst
instance data
fr_dlist_head_t list
for retransmissions
bool closing
we should be closing the file
off_t read_offset
where we're reading from in filename_work
uint32_t outstanding
number of currently outstanding records;
fr_network_t * nr
for Linux-specific callbacks
fr_dict_attr_autoload_t proto_detail_work_dict_attr[]
static const conf_parser_t file_listen_config[]
static ssize_t mod_read(fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time_p, uint8_t *buffer, size_t buffer_len, size_t *leftover)
static int mod_decode(void const *instance, request_t *request, UNUSED uint8_t *const data, UNUSED size_t data_len)
static fr_dict_t const  * dict_freeradius
static void work_retransmit(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *uctx)
proto_detail_work_thread_t * parent
talloc_parent is SLOW!
fr_dlist_t entry
for the retransmission list
static void mod_event_list_set(fr_listen_t *li, fr_event_list_t *el, void *nr)
Set the event list for a new IO instance.
static int mod_open(fr_listen_t *li)
Open a detail listener.
size_t packet_len
for retransmissions
fr_retry_t retry
our retry timers
uint8_t * packet
for retransmissions
fr_time_t timestamp
when we read the entry.
fr_dict_autoload_t proto_detail_work_dict[]
static fr_event_update_t pause_read[]
static conf_parser_t limit_config[]
fr_timer_t * ev
retransmission timer
fr_app_io_t proto_detail_work
Private interface for use by proto_detail_file.
static int mod_close_internal(proto_detail_work_thread_t *thread)
static char const * mod_name(fr_listen_t *li)
int id
for retransmission counters
static int mod_close(fr_listen_t *li)
Close a detail listener.
off_t done_offset
where we're tracking the status
static fr_dict_attr_t const  * attr_packet_transmit_counter
static ssize_t mod_write(fr_listen_t *li, void *packet_ctx, UNUSED fr_time_t request_time, uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
static int mod_instantiate(module_inst_ctx_t const *mctx)
static fr_event_update_t resume_read[]
#define pair_update_request(_attr, _da)
#define REQUEST_VERIFY(_x)
static conf_parser_t retry_config[]
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
module_instance_t const  * parent
Parent module's instance (if any).
conf_parser_t const  * config
How to convert a CONF_SECTION to a module instance.
eap_aka_sim_process_conf_t * inst
#define fr_time()
Allow us to arbitrarily manipulate time.
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.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
#define talloc_get_type_abort_const
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_wrap(_time)
#define fr_time_eq(_a, _b)
static int64_t fr_time_delta_to_sec(fr_time_delta_t delta)
static fr_event_list_t * el
fr_retry_state_t fr_retry_next(fr_retry_t *r, fr_time_t now)
Initialize a retransmission counter.
void fr_retry_init(fr_retry_t *r, fr_time_t now, fr_retry_config_t const *config)
Initialize a retransmission counter.
fr_time_t start
when we started the retransmission
fr_time_delta_t rt
retransmit interval
@ FR_RETRY_MRC
reached maximum retransmission count
@ FR_RETRY_MRD
reached maximum retransmission duration
uint32_t count
number of sent packets
fr_time_t next
when the next timer should be set