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