The FreeRADIUS server
$Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
|
Transport-specific functions. More...
#include <freeradius-devel/io/channel.h>
#include <freeradius-devel/server/request.h>
#include <freeradius-devel/util/socket.h>
#include <freeradius-devel/util/time.h>
#include <freeradius-devel/util/talloc.h>
Go to the source code of this file.
Data Structures | |
struct | fr_io_address_t |
struct | fr_io_stats_t |
Typedefs | |
typedef struct fr_channel_s | fr_channel_t |
typedef struct fr_client_s | fr_client_t |
typedef fr_client_t *(* | fr_io_client_find_t) (fr_listen_t *li, fr_ipaddr_t const *ipaddr, int ipproto) |
typedef int(* | fr_io_close_t) (fr_listen_t *li) |
Handle a close on the socket. More... | |
typedef int(* | fr_io_connection_set_t) (fr_listen_t *li, fr_io_address_t *connection) |
typedef int(* | fr_io_data_inject_t) (fr_listen_t *li, uint8_t const *buffer, size_t buffer_len, fr_time_t recv_time) |
Inject data into a socket. More... | |
typedef ssize_t(* | fr_io_data_read_t) (fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time, uint8_t *buffer, size_t buffer_len, size_t *leftover) |
Read from a socket. More... | |
typedef void(* | fr_io_data_vnode_t) (fr_listen_t *li, uint32_t fflags) |
Tell the IO handler that a VNODE has changed. More... | |
typedef ssize_t(* | fr_io_data_write_t) (fr_listen_t *li, void *packet_ctx, fr_time_t request_time, uint8_t *buffer, size_t buffer_len, size_t written) |
Write a socket. More... | |
typedef int(* | fr_io_decode_t) (void const *instance, request_t *request, uint8_t *const data, size_t data_len) |
Decode a raw packet and convert it into a request. More... | |
typedef ssize_t(* | fr_io_encode_t) (void const *instance, request_t *request, uint8_t *buffer, size_t buffer_len) |
Encode data from a request_t into a raw packet. More... | |
typedef int(* | fr_io_get_fd_t) (fr_listen_t const *li) |
Return a selectable file descriptor for this I/O path. More... | |
typedef size_t(* | fr_io_nak_t) (fr_listen_t *li, void *packet_ctx, uint8_t *const packet, size_t packet_len, uint8_t *reply, size_t reply_len) |
NAK a packet. More... | |
typedef char const *(* | fr_io_name_t) (fr_listen_t *li) |
typedef void(* | fr_io_network_get_t) (int *ipproto, bool *dynamic_clients, fr_trie_t const **trie, void *instance) |
Callback to return network properties. More... | |
typedef int(* | fr_io_open_t) (fr_listen_t *li) |
Open an I/O path. More... | |
typedef int(* | fr_io_set_fd_t) (fr_listen_t *li, int fd) |
Set a selectable file descriptor for this I/O path. More... | |
typedef int(* | fr_io_signal_t) (fr_listen_t *li) |
Handle an error on the socket. More... | |
typedef int(* | fr_io_track_cmp_t) (void const *instance, void *thread_instance, fr_client_t *client, void const *one, void const *two) |
Compare two tracking structures for storing in a duplicate detection tree. More... | |
typedef void *(* | fr_io_track_create_t) (void const *instance, void *thread_instance, fr_client_t *client, fr_io_track_t *track, uint8_t const *packet, size_t packet_len) |
Convert a raw packet to a tracking structure. More... | |
typedef struct fr_io_track_s | fr_io_track_t |
typedef struct fr_listen | fr_listen_t |
typedef struct fr_trie_s | fr_trie_t |
Transport-specific functions.
Definition in file base.h.
struct fr_io_address_t |
Data Fields | ||
---|---|---|
fr_client_t const * | radclient | old-style client definition |
fr_socket_t | socket | src/dst ip and port. |
struct fr_io_stats_t |
typedef struct fr_channel_s fr_channel_t |
typedef struct fr_client_s fr_client_t |
typedef fr_client_t*(* fr_io_client_find_t) (fr_listen_t *li, fr_ipaddr_t const *ipaddr, int ipproto) |
typedef int(* fr_io_close_t) (fr_listen_t *li) |
Handle a close on the socket.
In general, the only thing to do on errors is to close the transport. But on error, the "error" function will be called before "close". On normal finish, the "close" function will be called.
[in] | li | the listener for this socket |
typedef int(* fr_io_connection_set_t) (fr_listen_t *li, fr_io_address_t *connection) |
typedef int(* fr_io_data_inject_t) (fr_listen_t *li, uint8_t const *buffer, size_t buffer_len, fr_time_t recv_time) |
Inject data into a socket.
This function allows callers to inject data into a socket, just as if the data was read from a socket.
Note that this function is NOT an analog to fr_io_data_read_t. That is, the called function MUST copy the packet pointer into an internal list, so that subsequent calls to read() will return this packet.
The network side ensures that the packet buffer remains available to the called function for the duration of an inject() and read() call. i.e. the packet contents do NOT have to be saved, and the code can instead save the pointer to the buffer.
However, this buffer MUST be immediately returned on a subsequent call to read(). If it is not returned, the memory is still freed, and the pointer becomes invalid. Subsequent access to the buffer will result in crashes.
[in] | li | the listener for this socket |
[in] | buffer | the buffer where the raw packet to be injected |
[in] | buffer_len | the length of the buffer |
[in] | recv_time | when the packet was received |
typedef ssize_t(* fr_io_data_read_t) (fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time, uint8_t *buffer, size_t buffer_len, size_t *leftover) |
Read from a socket.
The network side guarantees that the read routine can leave partial data in the buffer. That data will be there on the next call to read. However, the data MAY have moved, so please do not keep a pointer to 'buffer' around.
datagram sockets should always set '*leftover = 0'.
stream sockets can read one packet, and set '*leftover' to how many bytes are left in the buffer. The read routine will be called again, with a (possibly new) buffer, but with 'leftover' bytes left in the buffer. The value in 'leftover'' will be the same as from the previous call, so the reader does not need to track it.
[in] | li | the listener for this socket |
[out] | packet_ctx | Where to write a newly allocated packet_ctx struct containing request specific data. |
[out] | recv_time | A pointer to a time when the packet was received |
[in,out] | buffer | the buffer where the raw packet will be written to (or read from) |
[in] | buffer_len | the length of the buffer |
[out] | leftover | bytes left in the buffer after reading a full packet. |
typedef void(* fr_io_data_vnode_t) (fr_listen_t *li, uint32_t fflags) |
typedef ssize_t(* fr_io_data_write_t) (fr_listen_t *li, void *packet_ctx, fr_time_t request_time, uint8_t *buffer, size_t buffer_len, size_t written) |
Write a socket.
If the socket is a datagram socket, then the function can read or write directly into the buffer. Stream sockets are a bit more complicated.
A stream reader can read data into the buffer, and be guaranteed that the data will not change in between subsequent calls to the read routine.
A stream writer MUST be prepared for the caller to delete the data immediately after calling the write routine. This means that if the socket is not ready, the writer MUST copy the data to an internal buffer, usually in instance. It MUST then have a write callback on the socket, which is called when the socket is ready for writing. That callback can then write the internal buffer to the socket.
i.e. this write() function is a way for the network thread to write packets to the transport context. The data may or may not go out to the network right away.
If the write function does a partial write, it should return a value smaller than buffer_len to indicate this. The network functions will then pass that value to a subsequent write call, in the "written" argument.
The reason for this odd API is that read/write should be writing packets, not raw streams of bytes. This API allows the "buffer" parameter to always contain a full packet.
[in] | li | the listener for this socket |
[in] | packet_ctx | Request specific data. |
[in] | request_time | when the original request was received |
[in] | buffer | the buffer where the raw packet will be written from |
[in] | buffer_len | the length of the buffer |
[in] | written | total number of bytes written in previous calls for this packet. |
typedef int(* fr_io_decode_t) (void const *instance, request_t *request, uint8_t *const data, size_t data_len) |
Decode a raw packet and convert it into a request.
This function is the opposite of fr_io_encode_t.
The "decode" function is ONLY for decoding data. It should be aware of the protocol (e.g. RADIUS), but it MUST NOT know anything about the underlying network transport (e.g. UDP), and it MUST NOT know anything about how the data will be used (e.g. authorize, authenticate, etc. for Access-Request)
[in] | instance | of the fr_app_t or fr_app_io_t. |
[in] | data | the raw packet data |
[in] | data_len | the length of the raw data |
[in] | request | where the decoded VPs should be placed. |
typedef ssize_t(* fr_io_encode_t) (void const *instance, request_t *request, uint8_t *buffer, size_t buffer_len) |
Encode data from a request_t into a raw packet.
This function is the opposite of fr_io_decode_t.
The "encode" function is ONLY for encoding data. It should be aware of the protocol (e.g. RADIUS), but it MUST NOT know anything about the underlying network transport (e.g. UDP), and it MUST NOT know anything about how the data will be used (e.g. reject delay on Access-Reject)
[in] | instance | of the fr_app_t or fr_app_io_t. |
[in] | request | request where the VPs to be encoded are located |
[out] | buffer | the buffer where the raw packet will be written |
[in] | buffer_len | the length of the buffer |
typedef int(* fr_io_get_fd_t) (fr_listen_t const *li) |
typedef size_t(* fr_io_nak_t) (fr_listen_t *li, void *packet_ctx, uint8_t *const packet, size_t packet_len, uint8_t *reply, size_t reply_len) |
NAK a packet.
When a worker receives a packet, it sometimes is unable to process that request. In order for the channels to work correctly, every request MUST be met with a response. This function allows a worker to NAK a request, but NOT send a response packet on the network.
This function MUST NOT fail. It must always return some data.
When the NAK packet is received by the network side, the transport portion of the network side MUST be able to recognize the NAK and take the appropriate action. e.g. for RADIUS, mark a request as "do not respond", even if duplicates come in.
[in] | li | the listener for this socket |
[out] | packet_ctx | the packet_ctx struct containing request specific data. |
[in] | packet | the packet to NAK |
[in] | packet_len | length of the packet to NAK |
[in] | reply | the NAK reply |
[in] | reply_len | length of the buffer where the reply should be placed. |
typedef char const*(* fr_io_name_t) (fr_listen_t *li) |
typedef int(* fr_io_open_t) (fr_listen_t *li) |
Open an I/O path.
Open a socket, file, or anything else that can be referenced by a file descriptor.
The file descriptor should be made available to the event loop via the selectable_fd callback. It will only be used to determine if the socket is readable/writable/has errored.
No data will be read from or written to the fd, except by the io_data callbacks here.
[in] | li | the listener for this socket |
typedef int(* fr_io_set_fd_t) (fr_listen_t *li, int fd) |
typedef int(* fr_io_signal_t) (fr_listen_t *li) |
Handle an error on the socket.
In general, the only thing to do on errors is to close the transport. But on error, the "error" function will be called before "close". On normal finish, the "close" function will be called.
[in] | li | the listener for this socket |
typedef int(* fr_io_track_cmp_t) (void const *instance, void *thread_instance, fr_client_t *client, void const *one, void const *two) |
Compare two tracking structures for storing in a duplicate detection tree.
We presume that the packets are well formed.
The comparison should be stable. i.e. compare the packets a field at a time. If the field is different, return the result from that field.
The comparison order of the fields should be "very different" to "much the same". The packets are put into an rbtree, so having a large fanout at the top is useful.
Note that this function should not check if the packets are completely identical. Instead, it checks particular fields in the packet so that we can distinguish packets without checking the entire packet.
[in] | instance | the context for this function |
[in] | thread_instance | the thread instance for this function |
[in] | client | the client associated with this packet |
[in] | one | packet tracking structure one |
[in] | two | packet tracking structure two |
typedef void*(* fr_io_track_create_t) (void const *instance, void *thread_instance, fr_client_t *client, fr_io_track_t *track, uint8_t const *packet, size_t packet_len) |
Convert a raw packet to a tracking structure.
For passing to fr_io_track_cmp_t
[in] | instance | the context for this function |
[in] | thread_instance | the thread instance for this function |
[in] | client | the client associated with this packet |
[in] | track | The parent tracking structure |
[in] | packet | The packet being summarized |
[in] | packet_len | Length of the packet being summarized |
typedef struct fr_io_track_s fr_io_track_t |
typedef struct fr_listen fr_listen_t |