The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
mem.c
Go to the documentation of this file.
1/*
2 * This program is is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 56376e138f574bfe04b8de04605fc00aaf039902 $
19 * @file lib/bio/mem.c
20 * @brief BIO abstractions for memory buffers
21 *
22 * @copyright 2024 Network RADIUS SAS (legal@networkradius.com)
23 */
24
25#include <freeradius-devel/bio/bio_priv.h>
26#include <freeradius-devel/bio/null.h>
27#include <freeradius-devel/bio/buf.h>
28
29#include <freeradius-devel/bio/mem.h>
30
31typedef enum {
33 FR_BIO_MEM_SOURCE, /* the application writes to it, something else reads */
34 FR_BIO_MEM_SINK, /* something else writes to it, the application reads */
35 FR_BIO_MEM_VERIFY, /* verification only, with no buffers */
36 FR_BIO_MEM_BUFFER, /* we manage local buffers */
38
39/** The memory buffer bio
40 *
41 * It is used to buffer reads / writes to a streaming socket.
42 */
43typedef struct fr_bio_mem_s {
45
46 fr_bio_mem_type_t type; //!< source, sink, etc.
47
48 fr_bio_verify_t verify; //!< verify data to see if we have a packet.
49 void *verify_ctx; //!< verify context
50
51 fr_bio_buf_t read_buffer; //!< buffering for reads
52 fr_bio_buf_t write_buffer; //!< buffering for writes
54
55static ssize_t fr_bio_mem_write_buffer(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size);
56
57static int fr_bio_mem_call_verify(fr_bio_t *bio, void *packet_ctx, size_t *size) CC_HINT(nonnull(1,3));
58
59/** At EOF, read data from the buffer until it is empty.
60 *
61 * When "next" bio returns EOF, there may still be pending data in the memory buffer. Return that until it's
62 * empty, and then EOF from then on.
63 */
64static ssize_t fr_bio_mem_read_eof(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
65{
66 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
67
68 /*
69 * No more data: return EOF from now on.
70 */
71 if (fr_bio_buf_used(&my->read_buffer) == 0) {
72
73 /*
74 * Don't call our EOF function. But do tell the other BIOs that we're at EOF.
75 */
76 my->priv_cb.eof = NULL;
77 fr_bio_eof(&my->bio);
78 return 0;
79 }
80
81 /*
82 * Return whatever data we have available. One the buffer is empty, the next read will get EOF.
83 */
84 return fr_bio_buf_read(&my->read_buffer, buffer, size);
85}
86
87static int fr_bio_mem_eof(fr_bio_t *bio)
88{
89 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
90
91 /*
92 * Nothing more for us to read, tell fr_bio_eof() that it can continue with poking other BIOs.
93 */
94 if (fr_bio_buf_used(&my->read_buffer) == 0) {
95 return 1;
96 }
97
98 my->bio.read = fr_bio_mem_read_eof;
99
100 return 0;
101}
102
103/** Read from a memory BIO
104 *
105 * This bio reads as much data as possible into the memory buffer. On the theory that a few memcpy() or
106 * memmove() calls are much cheaper than a system call.
107 *
108 * If the read buffer has enough data to satisfy the read, then it is returned.
109 *
110 * Otherwise the next bio is called to re-fill the buffer. The next read call will try to get as much data
111 * as possible into the buffer, even if that results in reading more than "size" bytes.
112 *
113 * Once the next read has been done, then the data from the buffer is returned, even if it is less than
114 * "size".
115 */
116static ssize_t fr_bio_mem_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
117{
118 ssize_t rcode;
119 size_t used, room;
120 uint8_t *p;
121 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
122 fr_bio_t *next;
123
124 /*
125 * We can satisfy the read from the memory buffer: do so.
126 */
127 used = fr_bio_buf_used(&my->read_buffer);
128 if (size <= used) {
129 return fr_bio_buf_read(&my->read_buffer, buffer, size);
130 }
131
132 /*
133 * There must be a next bio.
134 */
135 next = fr_bio_next(&my->bio);
136 fr_assert(next != NULL);
137
138 /*
139 * If there's no room to store more data in the buffer. Just return whatever data we have in the
140 * buffer.
141 */
142 room = fr_bio_buf_write_room(&my->read_buffer);
143 if (!room) return fr_bio_buf_read(&my->read_buffer, buffer, size);
144
145 /*
146 * We try to fill the buffer as much as possible from the network, even if that means reading
147 * more than "size" amount of data.
148 */
149 p = fr_bio_buf_write_reserve(&my->read_buffer, room);
150 fr_assert(p != NULL); /* otherwise room would be zero */
151
152 rcode = next->read(next, packet_ctx, p, room);
153
154 /*
155 * Ensure that whatever data we have read is marked as "used" in the buffer, and then return
156 * whatever data is available back to the caller.
157 */
158 if (rcode >= 0) {
159 if (rcode > 0) (void) fr_bio_buf_write_alloc(&my->read_buffer, (size_t) rcode);
160
161 return fr_bio_buf_read(&my->read_buffer, buffer, size);
162 }
163
164 /*
165 * The next bio returned an error. Whatever it is, it's fatal. We can read from the memory
166 * buffer until it's empty, but we can no longer write to the memory buffer. Any data written to
167 * the buffer is lost.
168 */
171 return rcode;
172}
173
174/** Return data only if we have a complete packet.
175 *
176 */
177static ssize_t fr_bio_mem_read_verify_stream(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
178{
179 ssize_t rcode;
180 size_t used, room, want;
181 uint8_t *p;
182 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
183 fr_bio_t *next;
184
185 /*
186 * We may be able to satisfy the read from the memory buffer.
187 */
188 used = fr_bio_buf_used(&my->read_buffer);
189 if (used) {
190 /*
191 * See if there are valid packets in the buffer.
192 */
193 rcode = fr_bio_mem_call_verify(bio, packet_ctx, &want);
194 if (rcode < 0) return fr_bio_error(VERIFY);
195
196 /*
197 * There's at least one valid packet, return it.
198 */
199 if (rcode == 1) {
200 /*
201 * This isn't a fatal error. The caller should check how much room is needed by calling
202 * fr_bio_mem_call_verify(), and retry.
203 *
204 * But in general, the caller should make sure that the output buffer has enough
205 * room for at least one packet. The verify() function should also ensure that
206 * the packet is no larger than our application maximum, even if the protocol
207 * allows for it to be larger.
208 */
209 if (want > size) return fr_bio_error(BUFFER_TOO_SMALL);
210
211 return fr_bio_buf_read(&my->read_buffer, buffer, want);
212 }
213
214 /*
215 * Else we need to read more data to have a complete packet.
216 */
217 }
218
219 /*
220 * There must be a next bio.
221 */
222 next = fr_bio_next(&my->bio);
223 fr_assert(next != NULL);
224
225 /*
226 * If there's no room to store more data in the buffer, try to make some room.
227 */
228 room = fr_bio_buf_write_room(&my->read_buffer);
229 if (!room) {
230 room = fr_bio_buf_make_room(&my->read_buffer);
231
232 /*
233 * We've tried to make room and failed. Which means that the buffer is full, AND there
234 * still isn't a complete packet in the buffer. This is therefore an error. The
235 * application has not supplied us with enough read_buffer space to store a complete
236 * packet.
237 *
238 * @todo - allow the application to increase the size of the buffer.
239 */
240 if (!room) return fr_bio_error(BUFFER_FULL);
241 }
242
243 /*
244 * We try to fill the buffer as much as possible from the network. The theory is that a few
245 * extra memcpy() or memmove()s are cheaper than a system call for reading each packet.
246 */
247 p = fr_bio_buf_write_reserve(&my->read_buffer, room);
248 fr_assert(p != NULL); /* otherwise room would be zero */
249
250 rcode = next->read(next, packet_ctx, p, room);
251
252 /*
253 * No data was read from the next bio, we still don't have a packet. Return nothing.
254 */
255 if (rcode == 0) return 0;
256
257 /*
258 * The next bio returned some data. See if it's a valid packet.
259 */
260 if (rcode > 0) {
261 (void) fr_bio_buf_write_alloc(&my->read_buffer, (size_t) rcode);
262
263 want = fr_bio_buf_used(&my->read_buffer);
264 if (size <= want) want = size;
265
266 /*
267 * See if there are valid packets in the buffer.
268 */
269 rcode = fr_bio_mem_call_verify(bio, packet_ctx, &want);
270 if (rcode < 0) return fr_bio_error(VERIFY);
271
272 /*
273 * There's at least one valid packet, return it.
274 */
275 if (rcode == 1) return fr_bio_buf_read(&my->read_buffer, buffer, want);
276
277 /*
278 * No valid packets. The next call to read will call verify again, which will return a
279 * partial packet. And then it will try to fill the buffer from the next bio.
280 */
281 return 0;
282 }
283
284 /*
285 * The other BIO returned an error. It could be transient or permanent. Return that to the
286 * application. If the error is permanent, then the other BIO is responsible for shutting down
287 * the BIO chain.
288 */
289 return rcode;
290}
291
292/** Return data only if we have a complete packet.
293 *
294 */
295static ssize_t fr_bio_mem_read_verify_datagram(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
296{
297 ssize_t rcode;
298 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
299 fr_bio_t *next;
300
301 /*
302 * There must be a next bio.
303 */
304 next = fr_bio_next(&my->bio);
305 fr_assert(next != NULL);
306
307 rcode = next->read(next, packet_ctx, buffer, size);
308
309 /*
310 * No data was read from the next bio, we still don't have a packet. Return nothing.
311 */
312 if (rcode == 0) return 0;
313
314 /*
315 * We have some data.
316 */
317 if (rcode > 0) {
318 size_t want = rcode;
319
320 /*
321 * It's a datagram socket, there can only be one packet in the buffer.
322 *
323 * @todo - if we're allowed more than one packet in the buffer, we should just call
324 * fr_bio_mem_read_verify(), or this function should call fr_bio_mem_call_verify().
325 */
326 switch (my->verify((fr_bio_t *) my, my->verify_ctx, packet_ctx, buffer, &want)) {
327 /*
328 * The data in the buffer is exactly a packet. Return that.
329 *
330 * @todo - if there are multiple packets, return the total size of packets?
331 */
332 case FR_BIO_VERIFY_OK:
333 fr_assert(want <= (size_t) rcode);
334 return want;
335
336 /*
337 * The data in the buffer doesn't make up a complete packet, discard it. The
338 * called verify function should take care of logging.
339 */
341 return 0;
342
344 return 0;
345
346 /*
347 * Some kind of fatal validation error.
348 */
350 break;
351 }
352
353 fr_bio_shutdown(bio);
354 return fr_bio_error(VERIFY);
355 }
356
357 /*
358 * The other BIO returned an error. It could be transient or permanent. Return that to the
359 * application. If the error is permanent, then the other BIO is responsible for shutting down
360 * the BIO chain.
361 */
362 return rcode;
363}
364
365
366/** Pass writes to the next BIO
367 *
368 * For speed, we try to bypass the memory buffer and write directly to the next bio. However, if the next
369 * bio returns EWOULDBLOCK, we write the data to the memory buffer, even if it is partial data.
370 */
371static ssize_t fr_bio_mem_write_next(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
372{
373 int error;
374 ssize_t rcode;
375 size_t room, leftover;
376 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
377 fr_bio_t *next;
378
379 /*
380 * We can't call the next bio if there's still cached data to flush.
381 *
382 * There must be a next bio.
383 */
384 fr_assert(fr_bio_buf_used(&my->write_buffer) == 0);
385
386 next = fr_bio_next(&my->bio);
387 fr_assert(next != NULL);
388
389 /*
390 * The next bio may write all of the data. If so, we return that,
391 */
392 rcode = next->write(next, packet_ctx, buffer, size);
393 if ((size_t) rcode == size) return rcode;
394
395 /*
396 * The next bio returned an error. Anything other than WOULD BLOCK is fatal. We can read from
397 * the memory buffer until it's empty, but we can no longer write to the memory buffer.
398 */
399 if ((rcode < 0) && (rcode != fr_bio_error(IO_WOULD_BLOCK))) {
402 return rcode;
403 }
404
405 /*
406 * We were flushing the BIO, return however much data we managed to write.
407 *
408 * Note that flushes should never block.
409 */
410 if (!buffer) {
411 fr_assert(rcode != fr_bio_error(IO_WOULD_BLOCK));
412 return rcode;
413 }
414
415 /*
416 * Tell previous BIOs in the chain that they are blocked.
417 */
418 error = fr_bio_write_blocked(bio);
419 if (error < 0) return error;
420
421 fr_assert(error != 0); /* what to do? */
422
423 /*
424 * We had WOULD BLOCK, or wrote partial bytes. Save the data to the memory buffer, and ensure
425 * that future writes are ordered. i.e. they write to the memory buffer before writing to the
426 * next bio.
427 */
429
430 /*
431 * Clamp the write to however much data is available in the buffer.
432 */
433 leftover = size - rcode;
434 room = fr_bio_buf_write_room(&my->write_buffer);
435
436 /*
437 * If we have "used == 0" above, then we must also have "room > 0".
438 */
439 fr_assert(room > 0);
440
441 if (room < leftover) leftover = room;
442
443 /*
444 * Since we've clamped the write, this call can never fail.
445 */
446 (void) fr_bio_buf_write(&my->write_buffer, ((uint8_t const *) buffer) + rcode, leftover);
447
448 /*
449 * Some of the data base been written to the next bio, and some to our cache. The caller has to
450 * ensure that the first subsequent write will send over the rest of the data.
451 *
452 * However, we tell the caller that we wrote the entire packet. Because we are now responsible
453 * for writing the remaining bytes.
454 */
455 return size;
456}
457
458/** Flush the memory buffer.
459 *
460 */
462{
463 int rcode;
464 size_t used;
465 fr_bio_t *next;
466
467 /*
468 * Nothing to flush, don't do any writes.
469 *
470 * Instead, set the write function to write next, where data will be sent directly to the next
471 * bio, and will bypass the write buffer.
472 */
473 used = fr_bio_buf_used(&my->write_buffer);
474 if (!used) {
475 my->bio.write = fr_bio_mem_write_next;
476 return 0;
477 }
478
479 next = fr_bio_next(&my->bio);
480 fr_assert(next != NULL);
481
482 /*
483 * Clamp the amount of data written. If the caller wants to write everything, it should
484 * pass SIZE_MAX.
485 */
486 if (used < size) used = size;
487
488 /*
489 * Flush the buffer to the next bio in line. That function will write as much data as possible,
490 * but may return a partial write.
491 */
492 rcode = next->write(next, NULL, my->write_buffer.write, used);
493
494 /*
495 * We didn't write anything, the bio is blocked.
496 */
497 if ((rcode == 0) || (rcode == fr_bio_error(IO_WOULD_BLOCK))) return fr_bio_error(IO_WOULD_BLOCK);
498
499 /*
500 * All other errors are fatal. We can read from the memory buffer until it's empty, but we can
501 * no longer write to the memory buffer.
502 */
503 if (rcode < 0) return rcode;
504
505 /*
506 * Tell the buffer that we've read a certain amount of data from it.
507 */
508 (void) fr_bio_buf_read(&my->write_buffer, NULL, (size_t) rcode);
509
510 /*
511 * We haven't emptied the buffer, any further IO is blocked.
512 */
513 if ((size_t) rcode < used) return fr_bio_error(IO_WOULD_BLOCK);
514
515 /*
516 * We've flushed all of the buffer. Revert back to "pass through" writing.
517 */
518 fr_assert(fr_bio_buf_used(&my->write_buffer) == 0);
519 my->bio.write = fr_bio_mem_write_next;
520 return rcode;
521}
522
523/** Write to the memory buffer.
524 *
525 * The special buffer pointer of NULL means flush(). On flush, we call next->read(), and if that succeeds,
526 * go back to "pass through" mode for the buffers.
527 */
528static ssize_t fr_bio_mem_write_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void const *buffer, size_t size)
529{
530 size_t room;
531 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
532
533 /*
534 * Flush the output buffer.
535 */
536 if (unlikely(!buffer)) return fr_bio_mem_write_flush(my, size);
537
538 /*
539 * Clamp the write to however much data is available in the buffer.
540 */
541 room = fr_bio_buf_write_room(&my->write_buffer);
542
543 /*
544 * The buffer is full, we can't write anything.
545 */
546 if (!room) return fr_bio_error(IO_WOULD_BLOCK);
547
548 /*
549 * If we're asked to write more bytes than are available in the buffer, then tell the caller that
550 * writes are now blocked, and we can't write any more data.
551 *
552 * Return an WOULD_BLOCK error instead of breaking our promise by writing part of the data,
553 * instead of accepting a full application write.
554 */
555 if (room < size) {
556 int rcode;
557
558 rcode = fr_bio_write_blocked(bio);
559 if (rcode < 0) return rcode;
560
561 return fr_bio_error(IO_WOULD_BLOCK);
562 }
563
564 /*
565 * As we have clamped the write, we know that this call must succeed.
566 */
567 (void) fr_bio_buf_write(&my->write_buffer, buffer, size);
568
569 /*
570 * If we've filled the buffer, tell the caller that writes are now blocked, and we can't write
571 * any more data. However, we still return the amount of data we wrote.
572 */
573 if (room == size) {
574 int rcode;
575
576 rcode = fr_bio_write_blocked(bio);
577 if (rcode < 0) return rcode;
578 }
579
580 return size;
581}
582
583/** Peek at the data in the read buffer
584 *
585 * Peeking at the data allows us to avoid many memory copies.
586 */
587uint8_t const *fr_bio_mem_read_peek(fr_bio_t *bio, size_t *size)
588{
589 size_t used;
590 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
591
592 used = fr_bio_buf_used(&my->read_buffer);
593
594 if (!used) return NULL;
595
596 *size = used;
597 return my->read_buffer.read;
598}
599
600/** Discard data from the read buffer.
601 *
602 * Discarding allows the caller to silently omit packets, so that
603 * they are not passed up to previous bios.
604 */
605void fr_bio_mem_read_discard(fr_bio_t *bio, size_t size)
606{
607 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
608
609 (void) fr_bio_buf_read(&my->read_buffer, NULL, size);
610}
611
612/** Verify that a packet is OK.
613 *
614 * @todo - have this as a parameter to the read routines, so that they only return complete packets?
615 *
616 * @param bio the #fr_bio_mem_t
617 * @param packet_ctx the packet ctx
618 * @param[out] size how big the verified packet is
619 * @return
620 * - <0 for FR_BIO_VERIFY_ERROR_CLOSE, the caller should close the bio.
621 * - 0 for "we have a partial packet", the size to read is in *size
622 * - 1 for "we have at least one good packet", the size of it is in *size
623 */
624static int fr_bio_mem_call_verify(fr_bio_t *bio, void *packet_ctx, size_t *size)
625{
626 uint8_t *packet, *end;
627 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
628
629 packet = my->read_buffer.read;
630 end = my->read_buffer.write;
631
632 while (packet < end) {
633 size_t want;
634#ifndef NDEBUG
635 size_t used;
636
637 used = end - packet;
638#endif
639
640 want = end - packet;
641
642 switch (my->verify((fr_bio_t *) my, my->verify_ctx, packet_ctx, packet, &want)) {
643 /*
644 * The data in the buffer is exactly a packet. Return that.
645 *
646 * @todo - if there are multiple packets, return the total size of packets?
647 */
648 case FR_BIO_VERIFY_OK:
649 fr_assert(want <= used);
650 *size = want;
651 return 1;
652
653 /*
654 * The packet needs more data. Return how much data we need for one packet.
655 */
657 fr_assert(want > used);
658 *size = want;
659 return 0;
660
662 /*
663 * We don't call fr_bio_buf_read(), because that will move the memory around, and
664 * we want to avoid that if at all possible.
665 */
666 fr_assert(want <= used);
667 fr_assert(packet == my->read_buffer.read);
668 my->read_buffer.read += want;
669 continue;
670
671 /*
672 * Some kind of fatal validation error.
673 */
675 break;
676 }
677 }
678
679 /*
680 * A fatal error. Shut down the entire BIO chain.
681 */
682 fr_bio_shutdown(bio);
683 return -1;
684}
685
686/*
687 * The application can read from the BIO until EOF, but cannot write to it.
688 */
690{
693}
694
695/** Allocate a memory buffer bio for either reading or writing.
696 */
697static bool fr_bio_mem_buf_alloc(fr_bio_mem_t *my, fr_bio_buf_t *buf, size_t size)
698{
699 if (size < 1024) size = 1024;
700 if (size > (1 << 20)) size = 1 << 20;
701
702 if (fr_bio_buf_alloc(my, buf, size) < 0) {
704 return false;
705 }
706
707 return true;
708}
709
710/** Allocate a memory buffer bio
711 *
712 * The "read buffer" will cache reads from the next bio in the chain. If the next bio returns more data than
713 * the caller asked for, the extra data is cached in the read buffer.
714 *
715 * The "write buffer" will buffer writes to the next bio in the chain. If the caller writes more data than
716 * the next bio can process, the extra data is cached in the write buffer.
717 *
718 * When the bio is closed (or freed) any pending data in the buffers is lost. The same happens if the next
719 * bio returns a fatal error.
720 *
721 * At some point during a read, the next bio may return EOF. When that happens, the caller should not rely
722 * on the next FD being readable or writable. Instead, it should keep reading from the memory bio until it
723 * returns EOF. See fr_bio_fd_eof() for details.
724 *
725 * @param ctx the talloc ctx
726 * @param read_size size of the read buffer. Must be 1024..1^20
727 * @param write_size size of the write buffer. Can be zero. If non-zero, must be 1024..1^20
728 * @param next the next bio which will perform the underlying reads and writes.
729 * - NULL on error, memory allocation failed
730 * - !NULL the bio
731 */
732fr_bio_t *fr_bio_mem_alloc(TALLOC_CTX *ctx, size_t read_size, size_t write_size, fr_bio_t *next)
733{
735
736 my = talloc_zero(ctx, fr_bio_mem_t);
737 if (!my) return NULL;
738
739 /*
740 * We can do 0-sized buffers for read, and the application should then set the verify function.
741 */
742 if (!read_size) {
743 my->type = FR_BIO_MEM_VERIFY;
744 my->bio.read = fr_bio_null_read; /* can't read anything until the verify routine is put in place */
745 my->bio.write = fr_bio_next_write;
746
747 if (write_size > 0) {
749 fr_strerror_const("Invalid write size. If read size is zero, then write size must also be zero");
750 return NULL;
751 }
752
753 } else {
754 /*
755 * We have a read buffer, and potentially a write buffer.
756 */
757 my->type = FR_BIO_MEM_BUFFER;
758
759 if (!fr_bio_mem_buf_alloc(my, &my->read_buffer, read_size)) {
760 oom:
761 fr_strerror_const("Out of memory");
762 return NULL;
763 }
764 my->bio.read = fr_bio_mem_read;
765
766 if (write_size) {
767 if (!fr_bio_mem_buf_alloc(my, &my->write_buffer, write_size)) goto oom;
768
769 /*
770 * Default to passing writes straight through, but buffer them locally if the
771 * write blocks.
772 *
773 * We also only need to resume writes if we're buffering data.
774 */
775 my->bio.write = fr_bio_mem_write_next;
776 my->priv_cb.write_resume = fr_bio_mem_write_resume;
777
778 } else {
779 my->bio.write = fr_bio_next_write;
780 }
781
782 /*
783 * EOF and shutdown are needed if there's a read buffer, but not when the memory bio is
784 * just doing packet verification/
785 */
786 my->priv_cb.eof = fr_bio_mem_eof;
787 my->priv_cb.shutdown = fr_bio_mem_shutdown;
788 }
789
790 fr_bio_chain(&my->bio, next);
791
792 talloc_set_destructor((fr_bio_t *) my, fr_bio_destructor);
793 return (fr_bio_t *) my;
794}
795
796
797/** Allocate a memory buffer which sources data from the callers application into the bio system.
798 *
799 * The caller writes data to the buffer, but never reads from it. This bio will call the "next" bio to write
800 * the data. somewhere.
801 */
802fr_bio_t *fr_bio_mem_source_alloc(TALLOC_CTX *ctx, size_t write_size, fr_bio_t *next)
803{
805
806 /*
807 * The caller has to state that the API is caching data.
808 */
809 if (!write_size) return NULL;
810
811 my = talloc_zero(ctx, fr_bio_mem_t);
812 if (!my) return NULL;
813
814 if (!fr_bio_mem_buf_alloc(my, &my->write_buffer, write_size)) {
816 return NULL;
817 }
818
819 my->type = FR_BIO_MEM_SOURCE;
820 my->bio.read = fr_bio_null_read; /* reading FROM this bio is not possible */
821 my->bio.write = fr_bio_mem_write_next;
822
823 /*
824 * @todo - have write pause / write resume callbacks?
825 */
826 my->priv_cb.shutdown = fr_bio_mem_shutdown;
827
828 fr_bio_chain(&my->bio, next);
829
830 talloc_set_destructor((fr_bio_t *) my, fr_bio_destructor);
831 return (fr_bio_t *) my;
832}
833
834/** Read from a buffer which a previous bio has filled.
835 *
836 * This function is called by the application which wants to read from a sink.
837 */
838static ssize_t fr_bio_mem_read_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
839{
840 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
841
842 return fr_bio_buf_read(&my->read_buffer, buffer, size);
843}
844
845/** Write to the read buffer.
846 *
847 * This function is called by an upstream function which writes into our local buffer.
848 */
849static ssize_t fr_bio_mem_write_read_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void const *buffer, size_t size)
850{
851 size_t room;
852 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
853
854 /*
855 * Clamp the write to however much data is available in the buffer.
856 */
857 room = fr_bio_buf_write_room(&my->read_buffer);
858
859 /*
860 * The buffer is full. We're now blocked.
861 */
862 if (!room) return fr_bio_error(IO_WOULD_BLOCK);
863
864 if (room < size) size = room;
865
866 /*
867 * As we have clamped the write, we know that this call must succeed.
868 */
869 return fr_bio_buf_write(&my->read_buffer, buffer, size);
870}
871
872/** Allocate a memory buffer which sinks data from a bio system into the callers application.
873 *
874 * The caller reads data from this bio, but never writes to it. Upstream BIOs will source the data.
875 */
876fr_bio_t *fr_bio_mem_sink_alloc(TALLOC_CTX *ctx, size_t read_size)
877{
879
880 /*
881 * The caller has to state that the API is caching data.
882 */
883 if (!read_size) return NULL;
884
885 my = talloc_zero(ctx, fr_bio_mem_t);
886 if (!my) return NULL;
887
888 if (!fr_bio_mem_buf_alloc(my, &my->read_buffer, read_size)) {
890 return NULL;
891 }
892
893 my->type = FR_BIO_MEM_SINK;
894 my->bio.read = fr_bio_mem_read_buffer;
895 my->bio.write = fr_bio_mem_write_read_buffer; /* the upstream will write to our read buffer */
896
897 talloc_set_destructor((fr_bio_t *) my, fr_bio_destructor);
898 return (fr_bio_t *) my;
899}
900
901/** Set the verification function for memory bios.
902 *
903 * It is possible to add a verification function. It is not currently possible to remove one.
904 *
905 * @param bio the binary IO handler
906 * @param verify the verification function
907 * @param datagram whether or not this bio is a datagram one.
908 * @return
909 * - <0 on error
910 * - 0 on success
911 */
912int fr_bio_mem_set_verify(fr_bio_t *bio, fr_bio_verify_t verify, void *verify_ctx, bool datagram)
913{
914 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
915
916 switch (my->type) {
918 fr_assert(0);
919 return -1;
920
922 case FR_BIO_MEM_SINK:
923 fr_strerror_const("Cannot add verify to this memory BIO");
924 return fr_bio_error(GENERIC);
925
927 fr_assert(my->bio.write == fr_bio_next_write);
928 if (!datagram) {
929 fr_strerror_const("Invalid memory BIO - we need a read buffer for verifying packets from a stream socket");
930 return -1;
931 }
933
935 break;
936 }
937
938 my->verify = verify;
939 my->verify_ctx = verify_ctx;
940
941 /*
942 * For reading datagrams, we just verify the packet in place. This works both when we have local
943 * buffers, and when we are verifying packets in the application-supplied buffer.
944 *
945 * For writing datagrams, then we cannot buffer individual datagrams. We must write
946 * either all of the datagram out, or none of it.
947 */
948 if (datagram) {
950 my->bio.write = fr_bio_next_write;
951
952 /*
953 * Might as well free the memory for the write buffer. It won't be used.
954 */
955 if (my->write_buffer.start) {
956 talloc_free(my->write_buffer.start);
957 my->write_buffer = (fr_bio_buf_t) {};
958 }
959 } else {
961 /* don't touch the write function or the write buffer. */
962 }
963
964 return 0;
965}
966
967/*
968 * There's no fr_bio_mem_write_blocked()
969 */
970
971/** See if we can resume writes to the memory bio.
972 *
973 * Note that there is no equivalent fr_bio_mem_write_blocked(), as that function wouldn't do anything.
974 * Perhaps it could swap the write function to fr_bio_mem_write_buffer(), but the fr_bio_mem_write_next()
975 * function should automatically do that when the write to the next bio only writes part of the data,
976 * or if it returns fr_bio_error(IO_WOULD_BLOCK)
977 */
979{
980 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
981 ssize_t rcode;
982
983 if (bio->write != fr_bio_mem_write_buffer) return 1;
984
986
987 /*
988 * Flush the buffer, and then reset the write routine if we were successful.
989 */
990 rcode = fr_bio_mem_write_flush(my, SIZE_MAX);
991 if (rcode <= 0) return rcode;
992
993 if (fr_bio_buf_used(&my->write_buffer) > 0) return 0;
994
995 /*
996 * Check for an application hook to check if we can resume writes.
997 */
998 if (!my->cb.write_resume) return 1;
999
1000 return my->cb.write_resume(bio);
1001}
1002
1003/** Pause writes.
1004 *
1005 * Calls to fr_bio_write() will write to the memory buffer, and not
1006 * to the next bio. You MUST call fr_bio_mem_write_resume() after
1007 * this to flush any data.
1008 */
1010{
1011 fr_bio_mem_t *my = talloc_get_type_abort(bio, fr_bio_mem_t);
1012
1013 if (my->bio.write == fr_bio_mem_write_buffer) return 0;
1014
1015 if (my->bio.write != fr_bio_mem_write_buffer) return -1;
1016
1017 my->bio.write = fr_bio_mem_write_buffer;
1018
1019 return 0;
1020}
static int const char char buffer[256]
Definition acutest.h:576
fr_bio_write_t _CONST write
write to the underlying bio
Definition base.h:117
fr_bio_read_t _CONST read
read from the underlying bio
Definition base.h:116
static fr_bio_t * fr_bio_next(fr_bio_t *bio)
Definition base.h:131
#define fr_bio_error(_x)
Definition base.h:193
static void fr_bio_chain(fr_bio_t *first, fr_bio_t *second)
Chain one bio after another.
Definition bio_priv.h:69
size_t fr_bio_buf_make_room(fr_bio_buf_t *bio_buf)
Definition buf.c:28
size_t fr_bio_buf_read(fr_bio_buf_t *bio_buf, void *buffer, size_t size)
Definition buf.c:45
int fr_bio_buf_alloc(TALLOC_CTX *ctx, fr_bio_buf_t *bio_buf, size_t size)
Definition buf.c:114
ssize_t fr_bio_buf_write(fr_bio_buf_t *bio_buf, const void *buffer, size_t size)
Definition buf.c:81
static size_t fr_bio_buf_write_room(fr_bio_buf_t const *bio_buf)
Definition buf.h:82
static size_t fr_bio_buf_used(fr_bio_buf_t const *bio_buf)
Definition buf.h:73
static uint8_t * fr_bio_buf_write_reserve(fr_bio_buf_t *bio_buf, size_t size)
Definition buf.h:89
static int fr_bio_buf_write_alloc(fr_bio_buf_t *bio_buf, size_t size)
Definition buf.h:98
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:324
#define unlikely(_x)
Definition build.h:383
#define UNUSED
Definition build.h:317
fr_bio_shutdown & my
Definition fd_errno.h:70
int fr_bio_write_blocked(fr_bio_t *bio)
Internal BIO function to tell all BIOs that it's blocked.
Definition base.c:307
void fr_bio_eof(fr_bio_t *bio)
Internal BIO function to run EOF callbacks.
Definition base.c:258
int fr_bio_destructor(fr_bio_t *bio)
Free this bio.
Definition base.c:34
ssize_t fr_bio_next_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Internal bio function which just writes to the "next" bio.
Definition base.c:74
int fr_bio_shutdown(fr_bio_t *bio)
Shut down a set of BIOs.
Definition base.c:151
fr_bio_t * fr_bio_mem_alloc(TALLOC_CTX *ctx, size_t read_size, size_t write_size, fr_bio_t *next)
Allocate a memory buffer bio.
Definition mem.c:732
static ssize_t fr_bio_mem_write_read_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void const *buffer, size_t size)
Write to the read buffer.
Definition mem.c:849
static ssize_t fr_bio_mem_read_verify_stream(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Return data only if we have a complete packet.
Definition mem.c:177
void * verify_ctx
verify context
Definition mem.c:49
void fr_bio_mem_read_discard(fr_bio_t *bio, size_t size)
Discard data from the read buffer.
Definition mem.c:605
fr_bio_t * fr_bio_mem_sink_alloc(TALLOC_CTX *ctx, size_t read_size)
Allocate a memory buffer which sinks data from a bio system into the callers application.
Definition mem.c:876
fr_bio_mem_type_t
Definition mem.c:31
@ FR_BIO_MEM_SINK
Definition mem.c:34
@ FR_BIO_MEM_INVALID
Definition mem.c:32
@ FR_BIO_MEM_SOURCE
Definition mem.c:33
@ FR_BIO_MEM_BUFFER
Definition mem.c:36
@ FR_BIO_MEM_VERIFY
Definition mem.c:35
fr_bio_buf_t read_buffer
buffering for reads
Definition mem.c:51
static int fr_bio_mem_eof(fr_bio_t *bio)
Definition mem.c:87
struct fr_bio_mem_s fr_bio_mem_t
The memory buffer bio.
static ssize_t fr_bio_mem_write_next(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Pass writes to the next BIO.
Definition mem.c:371
static ssize_t fr_bio_mem_read_verify_datagram(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Return data only if we have a complete packet.
Definition mem.c:295
fr_bio_t * fr_bio_mem_source_alloc(TALLOC_CTX *ctx, size_t write_size, fr_bio_t *next)
Allocate a memory buffer which sources data from the callers application into the bio system.
Definition mem.c:802
static ssize_t fr_bio_mem_read_buffer(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Read from a buffer which a previous bio has filled.
Definition mem.c:838
int fr_bio_mem_write_resume(fr_bio_t *bio)
See if we can resume writes to the memory bio.
Definition mem.c:978
fr_bio_buf_t write_buffer
buffering for writes
Definition mem.c:52
fr_bio_verify_t verify
verify data to see if we have a packet.
Definition mem.c:48
FR_BIO_COMMON
Definition mem.c:44
static ssize_t fr_bio_mem_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Read from a memory BIO.
Definition mem.c:116
int fr_bio_mem_set_verify(fr_bio_t *bio, fr_bio_verify_t verify, void *verify_ctx, bool datagram)
Set the verification function for memory bios.
Definition mem.c:912
static void fr_bio_mem_shutdown(fr_bio_t *bio)
Definition mem.c:689
fr_bio_mem_type_t type
source, sink, etc.
Definition mem.c:46
static ssize_t fr_bio_mem_read_eof(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
At EOF, read data from the buffer until it is empty.
Definition mem.c:64
static bool fr_bio_mem_buf_alloc(fr_bio_mem_t *my, fr_bio_buf_t *buf, size_t size)
Allocate a memory buffer bio for either reading or writing.
Definition mem.c:697
static ssize_t fr_bio_mem_write_flush(fr_bio_mem_t *my, size_t size)
Flush the memory buffer.
Definition mem.c:461
static int fr_bio_mem_call_verify(fr_bio_t *bio, void *packet_ctx, size_t *size))
Verify that a packet is OK.
Definition mem.c:624
int fr_bio_mem_write_pause(fr_bio_t *bio)
Pause writes.
Definition mem.c:1009
uint8_t const * fr_bio_mem_read_peek(fr_bio_t *bio, size_t *size)
Peek at the data in the read buffer.
Definition mem.c:587
static ssize_t fr_bio_mem_write_buffer(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
The memory buffer bio.
Definition mem.c:43
talloc_free(reap)
@ FR_BIO_VERIFY_ERROR_CLOSE
fatal error, the bio should be closed.
Definition mem.h:36
@ FR_BIO_VERIFY_DISCARD
the packet should be discarded
Definition mem.h:34
@ FR_BIO_VERIFY_OK
packet is OK
Definition mem.h:33
@ FR_BIO_VERIFY_WANT_MORE
not enough data for one packet
Definition mem.h:35
fr_bio_verify_action_t(* fr_bio_verify_t)(fr_bio_t *bio, void *verify_ctx, void *packet_ctx, const void *buffer, size_t *size)
Verifies the packet.
Definition mem.h:51
long int ssize_t
unsigned char uint8_t
static size_t used
ssize_t fr_bio_null_write(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
Always return 0 on write.
Definition null.c:39
ssize_t fr_bio_null_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
Always return 0 on read.
Definition null.c:31
#define fr_assert(_expr)
Definition rad_assert.h:38
#define VERIFY(_x)
Definition trie.c:130
#define fr_strerror_const(_msg)
Definition strerror.h:223
int nonnull(2, 5))