The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: 77c38e85bb98bbe1d24bed9c618d67ad62962955 $
20  *
21  * @file lib/io/base.h
22  * @brief Transport-specific functions.
23  *
24  * @copyright 2016 Alan DeKok (aland@freeradius.org)
25  */
26 RCSIDH(io_h, "$Id: 77c38e85bb98bbe1d24bed9c618d67ad62962955 $")
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
35 extern "C" {
36 #endif
37 
38 typedef struct fr_listen fr_listen_t;
39 typedef struct fr_trie_s fr_trie_t;
40 
41 typedef struct {
42  uint64_t in;
43  uint64_t out;
44  uint64_t dup;
45  uint64_t dropped;
47 
48 
49 typedef struct fr_channel_s fr_channel_t;
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  */
67 typedef 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  */
75 typedef 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  */
83 typedef 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  */
103 typedef 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  */
123 typedef 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  */
148 typedef 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  */
176 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);
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  */
218 typedef 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  */
249 typedef 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  */
256 typedef void (*fr_io_data_vnode_t)(fr_listen_t *li, uint32_t fflags);
257 
258 typedef 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  */
274 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);
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  */
302 typedef 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  */
316 typedef 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  */
330 typedef int (*fr_io_close_t)(fr_listen_t *li);
331 
332 /*
333  * Structures and definitions for the master IO handler.
334  */
335 typedef struct {
336  fr_socket_t socket; //!< src/dst ip and port.
337 
338  fr_client_t const *radclient; //!< old-style client definition
340 
341 typedef int (*fr_io_connection_set_t)(fr_listen_t *li, fr_io_address_t *connection);
342 
343 typedef struct fr_client_s fr_client_t;
344 
345 typedef fr_client_t *(*fr_io_client_find_t)(fr_listen_t *li, fr_ipaddr_t const *ipaddr, int ipproto);
346 
347 typedef void (*fr_io_network_get_t)(void *instance, int *ipproto, bool *dynamic_clients, fr_trie_t const **trie);
348 
349 typedef char const *(*fr_io_name_t)(fr_listen_t *li);
350 
351 
352 #ifdef __cplusplus
353 }
354 #endif
static int const char char buffer[256]
Definition: acutest.h:574
#define RCSIDH(h, id)
Definition: build.h:445
A full channel, which consists of two ends.
Definition: channel.c:144
IPv4/6 prefix.
Definition: merged_model.c:272
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
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
void(* fr_io_network_get_t)(void *instance, int *ipproto, bool *dynamic_clients, fr_trie_t const **trie)
Definition: base.h:347
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
Definition: client.h:80
Describes a host allowed to send packets to the server.
Definition: client.h:77
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
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
unsigned long int size_t
Definition: merged_model.c:25
static int ipproto
Definition: radclient-ng.c:94
"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:1259