The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
base.h
Go to the documentation of this file.
1#pragma once
2/*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16 */
17
18/**
19 * $Id: 3f474654c8765c470f1a7e26ce285ef2033e0472 $
20 *
21 * @file lib/io/base.h
22 * @brief Transport-specific functions.
23 *
24 * @copyright 2016 Alan DeKok (aland@freeradius.org)
25 */
26RCSIDH(io_h, "$Id: 3f474654c8765c470f1a7e26ce285ef2033e0472 $")
27
28#include <freeradius-devel/io/channel.h>
29#include <freeradius-devel/server/request.h>
30#include <freeradius-devel/util/socket.h>
31#include <freeradius-devel/util/time.h>
32#include <freeradius-devel/util/talloc.h>
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37
38typedef struct fr_listen fr_listen_t;
39typedef struct fr_trie_s fr_trie_t;
40
41typedef struct {
42 uint64_t in;
43 uint64_t out;
44 uint64_t dup;
45 uint64_t dropped;
47
48
50
51/** Open an I/O path
52 *
53 * Open a socket, file, or anything else that can be referenced
54 * by a file descriptor.
55 *
56 * The file descriptor should be made available to the event loop
57 * via the selectable_fd callback. It will only be used to determine if the
58 * socket is readable/writable/has errored.
59 *
60 * No data will be read from or written to the fd, except by the io_data callbacks here.
61 *
62 * @param[in] li the listener for this socket
63 * @return
64 * - 0 on success
65 * - <0 on error
66 */
67typedef int (*fr_io_open_t)(fr_listen_t *li);
68
69/** Return a selectable file descriptor for this I/O path
70 *
71 * Return the file descriptor associated with this I/O path.
72 *
73 * @param[in] li the listener for this socket
74 */
75typedef int (*fr_io_get_fd_t)(fr_listen_t const *li);
76
77/** Set a selectable file descriptor for this I/O path
78 *
79 *
80 * @param[in] li the listener for this socket
81 * @param[in] fd the FD to set
82 */
83typedef int (*fr_io_set_fd_t)(fr_listen_t *li, int fd);
84
85/** Decode a raw packet and convert it into a request.
86 *
87 * This function is the opposite of fr_io_encode_t.
88 *
89 * The "decode" function is ONLY for decoding data. It should be
90 * aware of the protocol (e.g. RADIUS), but it MUST NOT know anything
91 * about the underlying network transport (e.g. UDP), and it MUST NOT
92 * know anything about how the data will be used (e.g. authorize,
93 * authenticate, etc. for Access-Request)
94 *
95 * @param[in] instance of the #fr_app_t or #fr_app_io_t.
96 * @param[in] data the raw packet data
97 * @param[in] data_len the length of the raw data
98 * @param[in] request where the decoded VPs should be placed.
99 * @return
100 * - <0 on error
101 * - 0 on success
102 */
103typedef int (*fr_io_decode_t)(void const *instance, request_t *request, uint8_t *const data, size_t data_len);
104
105/** Encode data from a request_t into a raw packet.
106 *
107 * This function is the opposite of fr_io_decode_t.
108 *
109 * The "encode" function is ONLY for encoding data. It should be
110 * aware of the protocol (e.g. RADIUS), but it MUST NOT know anything
111 * about the underlying network transport (e.g. UDP), and it MUST NOT
112 * know anything about how the data will be used (e.g. reject delay
113 * on Access-Reject)
114 *
115 * @param[in] instance of the #fr_app_t or #fr_app_io_t.
116 * @param[in] request request where the VPs to be encoded are located
117 * @param[out] buffer the buffer where the raw packet will be written
118 * @param[in] buffer_len the length of the buffer
119 * @return
120 * - <0 on error
121 * - >=0 length of the encoded data in the buffer, will be <=buffer_len
122 */
123typedef ssize_t (*fr_io_encode_t)(void const *instance, request_t *request, uint8_t *buffer, size_t buffer_len);
124
125/** NAK a packet.
126 *
127 * When a worker receives a packet, it sometimes is unable to process
128 * that request. In order for the channels to work correctly, every
129 * request MUST be met with a response. This function allows a
130 * worker to NAK a request, but NOT send a response packet on the
131 * network.
132 *
133 * This function MUST NOT fail. It must always return some data.
134 *
135 * When the NAK packet is received by the network side, the transport
136 * portion of the network side MUST be able to recognize the NAK and
137 * take the appropriate action. e.g. for RADIUS, mark a request as
138 * "do not respond", even if duplicates come in.
139 *
140 * @param[in] li the listener for this socket
141 * @param[out] packet_ctx the packet_ctx struct containing request specific data.
142 * @param[in] packet the packet to NAK
143 * @param[in] packet_len length of the packet to NAK
144 * @param[in] reply the NAK reply
145 * @param[in] reply_len length of the buffer where the reply should be placed.
146 * @return length of the data in the reply buffer.
147 */
148typedef size_t (*fr_io_nak_t)(fr_listen_t *li, void *packet_ctx, uint8_t *const packet, size_t packet_len,
149 uint8_t *reply, size_t reply_len);
150
151/** Read from a socket.
152 *
153 * The network side guarantees that the read routine can leave partial
154 * data in the buffer. That data will be there on the next call to
155 * read. However, the data MAY have moved, so please do not keep a
156 * pointer to 'buffer' around.
157 *
158 * datagram sockets should always set '*leftover = 0'.
159 *
160 * stream sockets can read one packet, and set '*leftover' to how many
161 * bytes are left in the buffer. The read routine will be called
162 * again, with a (possibly new) buffer, but with 'leftover' bytes left
163 * in the buffer. The value in 'leftover'' will be the same as from
164 * the previous call, so the reader does not need to track it.
165 *
166 * @param[in] li the listener for this socket
167 * @param[out] packet_ctx Where to write a newly allocated packet_ctx struct containing request specific data.
168 * @param[out] recv_time A pointer to a time when the packet was received
169 * @param[in,out] buffer the buffer where the raw packet will be written to (or read from)
170 * @param[in] buffer_len the length of the buffer
171 * @param[out] leftover bytes left in the buffer after reading a full packet.
172 * @return
173 * - <0 on error
174 * - >=0 length of the data read or written.
175 */
176typedef 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);
177
178/** Write a socket.
179 *
180 * If the socket is a datagram socket, then the function can read or
181 * write directly into the buffer. Stream sockets are a bit more complicated.
182 *
183 * A stream reader can read data into the buffer, and be guaranteed
184 * that the data will not change in between subsequent calls to the
185 * read routine.
186 *
187 * A stream writer MUST be prepared for the caller to delete the data
188 * immediately after calling the write routine. This means that if
189 * the socket is not ready, the writer MUST copy the data to an
190 * internal buffer, usually in instance. It MUST then have a
191 * write callback on the socket, which is called when the socket is
192 * ready for writing. That callback can then write the internal
193 * buffer to the socket.
194 *
195 * i.e. this write() function is a way for the network thread to
196 * write packets to the transport context. The data may or may not
197 * go out to the network right away.
198 *
199 * If the write function does a partial write, it should return a
200 * value smaller than buffer_len to indicate this. The network
201 * functions will then pass that value to a subsequent write call, in
202 * the "written" argument.
203 *
204 * The reason for this odd API is that read/write should be writing
205 * *packets*, not raw streams of bytes. This API allows the "buffer"
206 * parameter to always contain a full packet.
207 *
208 * @param[in] li the listener for this socket
209 * @param[in] packet_ctx Request specific data.
210 * @param[in] request_time when the original request was received
211 * @param[in] buffer the buffer where the raw packet will be written from
212 * @param[in] buffer_len the length of the buffer
213 * @param[in] written total number of bytes written in previous calls for this packet.
214 * @return
215 * - <0 on error
216 * - >=0 length of the data read or written.
217 */
218typedef ssize_t (*fr_io_data_write_t)(fr_listen_t *li, void *packet_ctx, fr_time_t request_time,
219 uint8_t *buffer, size_t buffer_len, size_t written);
220
221/** Inject data into a socket.
222 *
223 * This function allows callers to inject data into a socket, just as if the data
224 * was read from a socket.
225 *
226 * Note that this function is NOT an analog to fr_io_data_read_t.
227 * That is, the called function MUST copy the packet pointer into an
228 * internal list, so that subsequent calls to read() will return this
229 * packet.
230 *
231 * The network side ensures that the packet buffer remains available
232 * to the called function for the duration of an inject() and read()
233 * call. i.e. the packet contents do NOT have to be saved, and the
234 * code can instead save the pointer to the buffer.
235 *
236 * However, this buffer MUST be immediately returned on a subsequent
237 * call to read(). If it is not returned, the memory is still freed,
238 * and the pointer becomes invalid. Subsequent access to the buffer
239 * will result in crashes.
240 *
241 * @param[in] li the listener for this socket
242 * @param[in] buffer the buffer where the raw packet to be injected
243 * @param[in] buffer_len the length of the buffer
244 * @param[in] recv_time when the packet was received
245 * @return
246 * - <0 on error
247 * - 0 on success
248 */
249typedef int (*fr_io_data_inject_t)(fr_listen_t *li,uint8_t const *buffer, size_t buffer_len, fr_time_t recv_time);
250
251/** Tell the IO handler that a VNODE has changed
252 *
253 * @param[in] li the listener for this socket
254 * @param[in] fflags from kevent. Usually just NOTE_EXEND
255 */
256typedef void (*fr_io_data_vnode_t)(fr_listen_t *li, uint32_t fflags);
257
258typedef struct fr_io_track_s fr_io_track_t; /* in master.h */
259
260/** Convert a raw packet to a tracking structure
261 *
262 * For passing to fr_io_track_cmp_t
263 *
264 * @param[in] instance the context for this function
265 * @param[in] thread_instance the thread instance for this function
266 * @param[in] client the client associated with this packet
267 * @param[in] track The parent tracking structure
268 * @param[in] packet The packet being summarized
269 * @param[in] packet_len Length of the packet being summarized
270 * @return
271 * - NULL on error
272 * - !NULL the packet tracking structure
273 */
274typedef 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);
275
276/** Compare two tracking structures for storing in a duplicate detection tree.
277 *
278 * We presume that the packets are well formed.
279 *
280 * The comparison should be stable. i.e. compare the packets a field
281 * at a time. If the field is different, return the result from that
282 * field.
283 *
284 * The comparison order of the fields should be "very different" to
285 * "much the same". The packets are put into an rbtree, so having a
286 * large fanout at the top is useful.
287 *
288 * Note that this function should not check if the packets are
289 * completely identical. Instead, it checks particular fields in the
290 * packet so that we can distinguish packets without checking the entire packet.
291 *
292 * @param[in] instance the context for this function
293 * @param[in] thread_instance the thread instance for this function
294 * @param[in] client the client associated with this packet
295 * @param[in] one packet tracking structure one
296 * @param[in] two packet tracking structure two
297 * @return
298 * - <0 on packet one "smaller" than packet two
299 * - >0 on packet two "larger" than packet one
300 * - =0 on the two packets being identical
301 */
302typedef int (*fr_io_track_cmp_t)(void const *instance, void *thread_instance, fr_client_t *client, void const *one, void const *two);
303
304/** Handle an error on the socket.
305 *
306 * In general, the only thing to do on errors is to close the
307 * transport. But on error, the "error" function will be called
308 * before "close". On normal finish, the "close" function will be
309 * called.
310 *
311 * @param[in] li the listener for this socket
312 * @return
313 * - 0 on success
314 * - <0 on error
315 */
316typedef int (*fr_io_signal_t)(fr_listen_t *li);
317
318/** Handle a close on the socket.
319 *
320 * In general, the only thing to do on errors is to close the
321 * transport. But on error, the "error" function will be called
322 * before "close". On normal finish, the "close" function will be
323 * called.
324 *
325 * @param[in] li the listener for this socket
326 * @return
327 * - 0 on success
328 * - <0 on error
329 */
330typedef int (*fr_io_close_t)(fr_listen_t *li);
331
332/*
333 * Structures and definitions for the master IO handler.
334 */
335typedef struct {
336 fr_socket_t socket; //!< src/dst ip and port.
337
338 fr_client_t const *radclient; //!< old-style client definition
340
341typedef int (*fr_io_connection_set_t)(fr_listen_t *li, fr_io_address_t *connection);
342
344
345typedef fr_client_t *(*fr_io_client_find_t)(fr_listen_t *li, fr_ipaddr_t const *ipaddr, int ipproto);
346
347/** Callback to return network properties
348 *
349 * @param[out] ipproto IP protocol (AF_INET or AF_INET6).
350 * @param[out] dynamic_clients Whether clients are dynamic.
351 * @param[out] trie Trie of clients.
352 * @param[in] instance Instance data.
353 */
354typedef void (*fr_io_network_get_t)(int *ipproto, bool *dynamic_clients, fr_trie_t const **trie, void *instance);
355
356typedef char const *(*fr_io_name_t)(fr_listen_t *li);
357
358
359#ifdef __cplusplus
360}
361#endif
static int const char char buffer[256]
Definition acutest.h:576
#define RCSIDH(h, id)
Definition build.h:484
A full channel, which consists of two ends.
Definition channel.c:144
IPv4/6 prefix.
int(* fr_io_open_t)(fr_listen_t *li)
Open an I/O path.
Definition base.h:67
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.
Definition base.h:176
fr_socket_t socket
src/dst ip and port.
Definition base.h:336
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.
Definition base.h:302
void(* fr_io_data_vnode_t)(fr_listen_t *li, uint32_t fflags)
Tell the IO handler that a VNODE has changed.
Definition base.h:256
uint64_t out
Definition base.h:43
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.
Definition base.h:103
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.
Definition base.h:218
int(* fr_io_set_fd_t)(fr_listen_t *li, int fd)
Set a selectable file descriptor for this I/O path.
Definition base.h:83
int(* fr_io_connection_set_t)(fr_listen_t *li, fr_io_address_t *connection)
Definition base.h:341
int(* fr_io_get_fd_t)(fr_listen_t const *li)
Return a selectable file descriptor for this I/O path.
Definition base.h:75
uint64_t dup
Definition base.h:44
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.
Definition base.h:148
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.
Definition base.h:123
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.
Definition base.h:249
uint64_t dropped
Definition base.h:45
void(* fr_io_network_get_t)(int *ipproto, bool *dynamic_clients, fr_trie_t const **trie, void *instance)
Callback to return network properties.
Definition base.h:354
int(* fr_io_close_t)(fr_listen_t *li)
Handle a close on the socket.
Definition base.h:330
int(* fr_io_signal_t)(fr_listen_t *li)
Handle an error on the socket.
Definition base.h:316
fr_client_t const * radclient
old-style client definition
Definition base.h:338
uint64_t in
Definition base.h:42
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
Definition client.h:83
Describes a host allowed to send packets to the server.
Definition client.h:80
uint8_t * packet
really a tracking structure, not a packet
Definition master.h:56
fr_io_client_t * client
client handling this packet.
Definition master.h:55
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
unsigned long int size_t
static int ipproto
"server local" time.
Definition time.h:69
Holds information necessary for binding or connecting to a socket.
Definition socket.h:63
static fr_slen_t data
Definition value.h:1265