1 /*
2 * Copyright 2022-2026 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdio.h>
11 #include <errno.h>
12 #include "bio_local.h"
13 #include "internal/cryptlib.h"
14 #include "internal/safe_math.h"
15
16 #if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
17
18 OSSL_SAFE_MATH_UNSIGNED(size_t, size_t)
19
20 /* ===========================================================================
21 * Byte-wise ring buffer which supports pushing and popping blocks of multiple
22 * bytes at a time.
23 */
24 struct ring_buf {
25 unsigned char *start; /* start of buffer */
26 size_t len; /* size of buffer allocation in bytes */
27 size_t count; /* number of bytes currently pushed */
28 /*
29 * These index into start. Where idx[0] == idx[1], the buffer is full
30 * (if count is nonzero) and empty otherwise.
31 */
32 size_t idx[2]; /* 0: head, 1: tail */
33 };
34
ring_buf_init(struct ring_buf * r,size_t nbytes)35 static int ring_buf_init(struct ring_buf *r, size_t nbytes)
36 {
37 r->start = OPENSSL_malloc(nbytes);
38 if (r->start == NULL)
39 return 0;
40
41 r->len = nbytes;
42 r->idx[0] = r->idx[1] = r->count = 0;
43 return 1;
44 }
45
ring_buf_destroy(struct ring_buf * r)46 static void ring_buf_destroy(struct ring_buf *r)
47 {
48 OPENSSL_free(r->start);
49 r->start = NULL;
50 r->len = 0;
51 r->count = 0;
52 }
53
54 /*
55 * Get a pointer to the next place to write data to be pushed to the ring buffer
56 * (idx=0), or the next data to be popped from the ring buffer (idx=1). The
57 * pointer is written to *buf and the maximum number of bytes which can be
58 * read/written are written to *len. After writing data to the buffer, call
59 * ring_buf_push/pop() with the number of bytes actually read/written, which
60 * must not exceed the returned length.
61 */
ring_buf_head_tail(struct ring_buf * r,int idx,uint8_t ** buf,size_t * len)62 static void ring_buf_head_tail(struct ring_buf *r, int idx, uint8_t **buf, size_t *len)
63 {
64 size_t max_len = r->len - r->idx[idx];
65
66 if (idx == 0 && max_len > r->len - r->count)
67 max_len = r->len - r->count;
68 if (idx == 1 && max_len > r->count)
69 max_len = r->count;
70
71 *buf = (uint8_t *)r->start + r->idx[idx];
72 *len = max_len;
73 }
74
75 #define ring_buf_head(r, buf, len) ring_buf_head_tail((r), 0, (buf), (len))
76 #define ring_buf_tail(r, buf, len) ring_buf_head_tail((r), 1, (buf), (len))
77
78 /*
79 * Commit bytes to the ring buffer previously filled after a call to
80 * ring_buf_head().
81 */
ring_buf_push_pop(struct ring_buf * r,int idx,size_t num_bytes)82 static void ring_buf_push_pop(struct ring_buf *r, int idx, size_t num_bytes)
83 {
84 size_t new_idx;
85
86 /* A single push/pop op cannot wrap around, though it can reach the end.
87 * If the caller adheres to the convention of using the length returned
88 * by ring_buf_head/tail(), this cannot happen.
89 */
90 if (!ossl_assert(num_bytes <= r->len - r->idx[idx]))
91 return;
92
93 /*
94 * Must not overfill the buffer, or pop more than is in the buffer either.
95 */
96 if (!ossl_assert(idx != 0 ? num_bytes <= r->count
97 : num_bytes + r->count <= r->len))
98 return;
99
100 /* Update the index. */
101 new_idx = r->idx[idx] + num_bytes;
102 if (new_idx == r->len)
103 new_idx = 0;
104
105 r->idx[idx] = new_idx;
106 if (idx != 0)
107 r->count -= num_bytes;
108 else
109 r->count += num_bytes;
110 }
111
112 #define ring_buf_push(r, num_bytes) ring_buf_push_pop((r), 0, (num_bytes))
113 #define ring_buf_pop(r, num_bytes) ring_buf_push_pop((r), 1, (num_bytes))
114
ring_buf_clear(struct ring_buf * r)115 static void ring_buf_clear(struct ring_buf *r)
116 {
117 r->idx[0] = r->idx[1] = r->count = 0;
118 }
119
ring_buf_resize(struct ring_buf * r,size_t nbytes)120 static int ring_buf_resize(struct ring_buf *r, size_t nbytes)
121 {
122 unsigned char *new_start;
123
124 if (r->start == NULL)
125 return ring_buf_init(r, nbytes);
126
127 if (nbytes == r->len)
128 return 1;
129
130 if (r->count > 0 && nbytes < r->len)
131 /* fail shrinking the ring buffer when there is any data in it */
132 return 0;
133
134 new_start = OPENSSL_realloc(r->start, nbytes);
135 if (new_start == NULL)
136 return 0;
137
138 /* Moving tail if it is after (or equal to) head */
139 if (r->count > 0) {
140 if (r->idx[0] <= r->idx[1]) {
141 size_t offset = nbytes - r->len;
142
143 memmove(new_start + r->idx[1] + offset, new_start + r->idx[1],
144 r->len - r->idx[1]);
145 r->idx[1] += offset;
146 }
147 } else {
148 /* just reset the head/tail because it might be pointing outside */
149 r->idx[0] = r->idx[1] = 0;
150 }
151
152 r->start = new_start;
153 r->len = nbytes;
154
155 return 1;
156 }
157
158 /* ===========================================================================
159 * BIO_s_dgram_pair is documented in BIO_s_dgram_pair(3).
160 *
161 * INTERNAL DATA STRUCTURE
162 *
163 * This is managed internally by using a bytewise ring buffer which supports
164 * pushing and popping spans of multiple bytes at once. The ring buffer stores
165 * internal packets which look like this:
166 *
167 * struct dgram_hdr hdr;
168 * uint8_t data[];
169 *
170 * The header contains the length of the data and metadata such as
171 * source/destination addresses.
172 *
173 * The datagram pair BIO is designed to support both traditional
174 * BIO_read/BIO_write (likely to be used by applications) as well as
175 * BIO_recvmmsg/BIO_sendmmsg.
176 */
177 struct bio_dgram_pair_st;
178 static int dgram_pair_write(BIO *bio, const char *buf, int sz_);
179 static int dgram_pair_read(BIO *bio, char *buf, int sz_);
180 static int dgram_mem_read(BIO *bio, char *buf, int sz_);
181 static long dgram_pair_ctrl(BIO *bio, int cmd, long num, void *ptr);
182 static long dgram_mem_ctrl(BIO *bio, int cmd, long num, void *ptr);
183 static int dgram_pair_init(BIO *bio);
184 static int dgram_mem_init(BIO *bio);
185 static int dgram_pair_free(BIO *bio);
186 static int dgram_pair_sendmmsg(BIO *b, BIO_MSG *msg, size_t stride,
187 size_t num_msg, uint64_t flags,
188 size_t *num_processed);
189 static int dgram_pair_recvmmsg(BIO *b, BIO_MSG *msg, size_t stride,
190 size_t num_msg, uint64_t flags,
191 size_t *num_processed);
192
193 static int dgram_pair_ctrl_destroy_bio_pair(BIO *bio1);
194 static size_t dgram_pair_read_inner(struct bio_dgram_pair_st *b, uint8_t *buf,
195 size_t sz);
196
197 #define BIO_MSG_N(array, n) (*(BIO_MSG *)((char *)(array) + (n) * stride))
198
199 static const BIO_METHOD dgram_pair_method = {
200 BIO_TYPE_DGRAM_PAIR,
201 "BIO dgram pair",
202 bwrite_conv,
203 dgram_pair_write,
204 bread_conv,
205 dgram_pair_read,
206 NULL, /* dgram_pair_puts */
207 NULL, /* dgram_pair_gets */
208 dgram_pair_ctrl,
209 dgram_pair_init,
210 dgram_pair_free,
211 NULL, /* dgram_pair_callback_ctrl */
212 dgram_pair_sendmmsg,
213 dgram_pair_recvmmsg,
214 };
215
216 static const BIO_METHOD dgram_mem_method = {
217 BIO_TYPE_DGRAM_MEM,
218 "BIO dgram mem",
219 bwrite_conv,
220 dgram_pair_write,
221 bread_conv,
222 dgram_mem_read,
223 NULL, /* dgram_pair_puts */
224 NULL, /* dgram_pair_gets */
225 dgram_mem_ctrl,
226 dgram_mem_init,
227 dgram_pair_free,
228 NULL, /* dgram_pair_callback_ctrl */
229 dgram_pair_sendmmsg,
230 dgram_pair_recvmmsg,
231 };
232
BIO_s_dgram_pair(void)233 const BIO_METHOD *BIO_s_dgram_pair(void)
234 {
235 return &dgram_pair_method;
236 }
237
BIO_s_dgram_mem(void)238 const BIO_METHOD *BIO_s_dgram_mem(void)
239 {
240 return &dgram_mem_method;
241 }
242
243 struct dgram_hdr {
244 size_t len; /* payload length in bytes, not including this struct */
245 BIO_ADDR src_addr, dst_addr; /* family == 0: not present */
246 };
247
248 struct bio_dgram_pair_st {
249 /* The other half of the BIO pair. NULL for dgram_mem. */
250 BIO *peer;
251 /* Writes are directed to our own ringbuf and reads to our peer. */
252 struct ring_buf rbuf;
253 /* Requested size of rbuf buffer in bytes once we initialize. */
254 size_t req_buf_len;
255 /* Largest possible datagram size */
256 size_t mtu;
257 /* Capability flags. */
258 uint32_t cap;
259 /* The local address to use (if set) */
260 BIO_ADDR *local_addr;
261 /*
262 * This lock protects updates to our rbuf. Since writes are directed to our
263 * own rbuf, this means we use this lock for writes and our peer's lock for
264 * reads.
265 */
266 CRYPTO_RWLOCK *lock;
267 unsigned int no_trunc : 1; /* Reads fail if they would truncate */
268 unsigned int local_addr_enable : 1; /* Can use BIO_MSG->local? */
269 unsigned int role : 1; /* Determines lock order */
270 unsigned int grows_on_write : 1; /* Set for BIO_s_dgram_mem only */
271 };
272
273 #define MIN_BUF_LEN (1024)
274
275 #define is_dgram_pair(b) (b->peer != NULL)
276
dgram_pair_init(BIO * bio)277 static int dgram_pair_init(BIO *bio)
278 {
279 struct bio_dgram_pair_st *b = OPENSSL_zalloc(sizeof(*b));
280
281 if (b == NULL)
282 return 0;
283
284 b->mtu = 1472; /* conservative default MTU */
285 /* default buffer size */
286 b->req_buf_len = 9 * (sizeof(struct dgram_hdr) + b->mtu);
287
288 b->lock = CRYPTO_THREAD_lock_new();
289 if (b->lock == NULL) {
290 OPENSSL_free(b);
291 return 0;
292 }
293
294 bio->ptr = b;
295 return 1;
296 }
297
dgram_mem_init(BIO * bio)298 static int dgram_mem_init(BIO *bio)
299 {
300 struct bio_dgram_pair_st *b;
301
302 if (!dgram_pair_init(bio))
303 return 0;
304
305 b = bio->ptr;
306
307 if (ring_buf_init(&b->rbuf, b->req_buf_len) == 0) {
308 dgram_pair_free(bio);
309 ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
310 return 0;
311 }
312
313 b->grows_on_write = 1;
314
315 bio->init = 1;
316 return 1;
317 }
318
dgram_pair_free(BIO * bio)319 static int dgram_pair_free(BIO *bio)
320 {
321 struct bio_dgram_pair_st *b;
322
323 if (bio == NULL)
324 return 0;
325
326 b = bio->ptr;
327 if (!ossl_assert(b != NULL))
328 return 0;
329
330 /* We are being freed. Disconnect any peer and destroy buffers. */
331 dgram_pair_ctrl_destroy_bio_pair(bio);
332
333 CRYPTO_THREAD_lock_free(b->lock);
334 OPENSSL_free(b);
335 return 1;
336 }
337
338 /* BIO_make_bio_pair (BIO_C_MAKE_BIO_PAIR) */
dgram_pair_ctrl_make_bio_pair(BIO * bio1,BIO * bio2)339 static int dgram_pair_ctrl_make_bio_pair(BIO *bio1, BIO *bio2)
340 {
341 struct bio_dgram_pair_st *b1, *b2;
342
343 /* peer must be non-NULL. */
344 if (bio1 == NULL || bio2 == NULL) {
345 ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
346 return 0;
347 }
348
349 /* Ensure the BIO we have been passed is actually a dgram pair BIO. */
350 if (bio1->method != &dgram_pair_method || bio2->method != &dgram_pair_method) {
351 ERR_raise_data(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT,
352 "both BIOs must be BIO_dgram_pair");
353 return 0;
354 }
355
356 b1 = bio1->ptr;
357 b2 = bio2->ptr;
358
359 if (!ossl_assert(b1 != NULL && b2 != NULL)) {
360 ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
361 return 0;
362 }
363
364 /*
365 * This ctrl cannot be used to associate a BIO pair half which is already
366 * associated.
367 */
368 if (b1->peer != NULL || b2->peer != NULL) {
369 ERR_raise_data(ERR_LIB_BIO, BIO_R_IN_USE,
370 "cannot associate a BIO_dgram_pair which is already in use");
371 return 0;
372 }
373
374 if (!ossl_assert(b1->req_buf_len >= MIN_BUF_LEN
375 && b2->req_buf_len >= MIN_BUF_LEN)) {
376 ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED);
377 return 0;
378 }
379
380 if (b1->rbuf.len != b1->req_buf_len)
381 if (ring_buf_init(&b1->rbuf, b1->req_buf_len) == 0) {
382 ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
383 return 0;
384 }
385
386 if (b2->rbuf.len != b2->req_buf_len)
387 if (ring_buf_init(&b2->rbuf, b2->req_buf_len) == 0) {
388 ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB);
389 ring_buf_destroy(&b1->rbuf);
390 return 0;
391 }
392
393 b1->peer = bio2;
394 b2->peer = bio1;
395 b1->role = 0;
396 b2->role = 1;
397 bio1->init = 1;
398 bio2->init = 1;
399 return 1;
400 }
401
402 /* BIO_destroy_bio_pair (BIO_C_DESTROY_BIO_PAIR) */
dgram_pair_ctrl_destroy_bio_pair(BIO * bio1)403 static int dgram_pair_ctrl_destroy_bio_pair(BIO *bio1)
404 {
405 BIO *bio2;
406 struct bio_dgram_pair_st *b1 = bio1->ptr, *b2;
407
408 ring_buf_destroy(&b1->rbuf);
409 bio1->init = 0;
410
411 BIO_ADDR_free(b1->local_addr);
412
413 /* Early return if we don't have a peer. */
414 if (b1->peer == NULL)
415 return 1;
416
417 bio2 = b1->peer;
418 b2 = bio2->ptr;
419
420 /* Invariant. */
421 if (!ossl_assert(b2->peer == bio1))
422 return 0;
423
424 /* Free buffers. */
425 ring_buf_destroy(&b2->rbuf);
426
427 bio2->init = 0;
428 b1->peer = NULL;
429 b2->peer = NULL;
430 return 1;
431 }
432
433 /* BIO_eof (BIO_CTRL_EOF) */
dgram_pair_ctrl_eof(BIO * bio)434 static int dgram_pair_ctrl_eof(BIO *bio)
435 {
436 struct bio_dgram_pair_st *b = bio->ptr, *peerb;
437
438 if (!ossl_assert(b != NULL))
439 return -1;
440
441 /* If we aren't initialized, we can never read anything */
442 if (!bio->init)
443 return 1;
444 if (!is_dgram_pair(b))
445 return 0;
446
447 peerb = b->peer->ptr;
448 if (!ossl_assert(peerb != NULL))
449 return -1;
450
451 /*
452 * Since we are emulating datagram semantics, never indicate EOF so long as
453 * we have a peer.
454 */
455 return 0;
456 }
457
458 /* BIO_set_write_buf_size (BIO_C_SET_WRITE_BUF_SIZE) */
dgram_pair_ctrl_set_write_buf_size(BIO * bio,size_t len)459 static int dgram_pair_ctrl_set_write_buf_size(BIO *bio, size_t len)
460 {
461 struct bio_dgram_pair_st *b = bio->ptr;
462
463 /* Changing buffer sizes is not permitted while a peer is connected. */
464 if (b->peer != NULL) {
465 ERR_raise(ERR_LIB_BIO, BIO_R_IN_USE);
466 return 0;
467 }
468
469 /* Enforce minimum size. */
470 if (len < MIN_BUF_LEN)
471 len = MIN_BUF_LEN;
472
473 if (b->rbuf.start != NULL) {
474 if (!ring_buf_resize(&b->rbuf, len))
475 return 0;
476 }
477
478 b->req_buf_len = len;
479 b->grows_on_write = 0;
480 return 1;
481 }
482
483 /* BIO_reset (BIO_CTRL_RESET) */
dgram_pair_ctrl_reset(BIO * bio)484 static int dgram_pair_ctrl_reset(BIO *bio)
485 {
486 struct bio_dgram_pair_st *b = bio->ptr;
487
488 ring_buf_clear(&b->rbuf);
489 return 1;
490 }
491
492 /* BIO_pending (BIO_CTRL_PENDING) (Threadsafe) */
dgram_pair_ctrl_pending(BIO * bio)493 static size_t dgram_pair_ctrl_pending(BIO *bio)
494 {
495 size_t saved_idx, saved_count;
496 struct bio_dgram_pair_st *b = bio->ptr, *readb;
497 struct dgram_hdr hdr;
498 size_t l;
499
500 /* Safe to check; init may not change during this call */
501 if (!bio->init)
502 return 0;
503 if (is_dgram_pair(b))
504 readb = b->peer->ptr;
505 else
506 readb = b;
507
508 if (CRYPTO_THREAD_write_lock(readb->lock) == 0)
509 return 0;
510
511 saved_idx = readb->rbuf.idx[1];
512 saved_count = readb->rbuf.count;
513
514 l = dgram_pair_read_inner(readb, (uint8_t *)&hdr, sizeof(hdr));
515
516 readb->rbuf.idx[1] = saved_idx;
517 readb->rbuf.count = saved_count;
518
519 CRYPTO_THREAD_unlock(readb->lock);
520
521 if (!ossl_assert(l == 0 || l == sizeof(hdr)))
522 return 0;
523
524 return l > 0 ? hdr.len : 0;
525 }
526
527 /* BIO_get_write_guarantee (BIO_C_GET_WRITE_GUARANTEE) (Threadsafe) */
dgram_pair_ctrl_get_write_guarantee(BIO * bio)528 static size_t dgram_pair_ctrl_get_write_guarantee(BIO *bio)
529 {
530 size_t l;
531 struct bio_dgram_pair_st *b = bio->ptr;
532
533 if (CRYPTO_THREAD_read_lock(b->lock) == 0)
534 return 0;
535
536 l = b->rbuf.len - b->rbuf.count;
537 if (l >= sizeof(struct dgram_hdr))
538 l -= sizeof(struct dgram_hdr);
539
540 /*
541 * If the amount of buffer space would not be enough to accommodate the
542 * worst-case size of a datagram, report no space available.
543 */
544 if (l < b->mtu)
545 l = 0;
546
547 CRYPTO_THREAD_unlock(b->lock);
548 return l;
549 }
550
551 /* BIO_dgram_get_local_addr_cap (BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP) */
dgram_pair_ctrl_get_local_addr_cap(BIO * bio)552 static int dgram_pair_ctrl_get_local_addr_cap(BIO *bio)
553 {
554 struct bio_dgram_pair_st *b = bio->ptr, *readb;
555
556 if (!bio->init)
557 return 0;
558
559 if (is_dgram_pair(b))
560 readb = b->peer->ptr;
561 else
562 readb = b;
563
564 return (~readb->cap & (BIO_DGRAM_CAP_HANDLES_SRC_ADDR | BIO_DGRAM_CAP_PROVIDES_DST_ADDR)) == 0;
565 }
566
567 /* BIO_dgram_get_effective_caps (BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS) */
dgram_pair_ctrl_get_effective_caps(BIO * bio)568 static int dgram_pair_ctrl_get_effective_caps(BIO *bio)
569 {
570 struct bio_dgram_pair_st *b = bio->ptr, *peerb;
571
572 if (b->peer == NULL)
573 return 0;
574
575 peerb = b->peer->ptr;
576
577 return peerb->cap;
578 }
579
580 /* BIO_dgram_get_caps (BIO_CTRL_DGRAM_GET_CAPS) */
dgram_pair_ctrl_get_caps(BIO * bio)581 static uint32_t dgram_pair_ctrl_get_caps(BIO *bio)
582 {
583 struct bio_dgram_pair_st *b = bio->ptr;
584
585 return b->cap;
586 }
587
588 /* BIO_dgram_set_caps (BIO_CTRL_DGRAM_SET_CAPS) */
dgram_pair_ctrl_set_caps(BIO * bio,uint32_t caps)589 static int dgram_pair_ctrl_set_caps(BIO *bio, uint32_t caps)
590 {
591 struct bio_dgram_pair_st *b = bio->ptr;
592
593 b->cap = caps;
594 return 1;
595 }
596
597 /* BIO_dgram_get_local_addr_enable (BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE) */
dgram_pair_ctrl_get_local_addr_enable(BIO * bio)598 static int dgram_pair_ctrl_get_local_addr_enable(BIO *bio)
599 {
600 struct bio_dgram_pair_st *b = bio->ptr;
601
602 return b->local_addr_enable;
603 }
604
605 /* BIO_dgram_set_local_addr_enable (BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE) */
dgram_pair_ctrl_set_local_addr_enable(BIO * bio,int enable)606 static int dgram_pair_ctrl_set_local_addr_enable(BIO *bio, int enable)
607 {
608 struct bio_dgram_pair_st *b = bio->ptr;
609
610 if (dgram_pair_ctrl_get_local_addr_cap(bio) == 0)
611 return 0;
612
613 b->local_addr_enable = (enable != 0 ? 1 : 0);
614 return 1;
615 }
616
617 /* BIO_dgram_get_mtu (BIO_CTRL_DGRAM_GET_MTU) */
dgram_pair_ctrl_get_mtu(BIO * bio)618 static int dgram_pair_ctrl_get_mtu(BIO *bio)
619 {
620 struct bio_dgram_pair_st *b = bio->ptr;
621
622 return b->mtu;
623 }
624
625 /* BIO_dgram_set_mtu (BIO_CTRL_DGRAM_SET_MTU) */
dgram_pair_ctrl_set_mtu(BIO * bio,size_t mtu)626 static int dgram_pair_ctrl_set_mtu(BIO *bio, size_t mtu)
627 {
628 struct bio_dgram_pair_st *b = bio->ptr, *peerb;
629
630 b->mtu = mtu;
631
632 if (b->peer != NULL) {
633 peerb = b->peer->ptr;
634 peerb->mtu = mtu;
635 }
636
637 return 1;
638 }
639
640 /* BIO_dgram_set0_local_addr (BIO_CTRL_DGRAM_SET0_LOCAL_ADDR) */
dgram_pair_ctrl_set0_local_addr(BIO * bio,BIO_ADDR * addr)641 static int dgram_pair_ctrl_set0_local_addr(BIO *bio, BIO_ADDR *addr)
642 {
643 struct bio_dgram_pair_st *b = bio->ptr;
644
645 BIO_ADDR_free(b->local_addr);
646 b->local_addr = addr;
647 return 1;
648 }
649
650 /* Partially threadsafe (some commands) */
dgram_mem_ctrl(BIO * bio,int cmd,long num,void * ptr)651 static long dgram_mem_ctrl(BIO *bio, int cmd, long num, void *ptr)
652 {
653 long ret = 1;
654 struct bio_dgram_pair_st *b = bio->ptr;
655
656 if (!ossl_assert(b != NULL))
657 return 0;
658
659 switch (cmd) {
660 /*
661 * BIO_set_write_buf_size: Set the size of the ring buffer used for storing
662 * datagrams. No more writes can be performed once the buffer is filled up,
663 * until reads are performed. This cannot be used after a peer is connected.
664 */
665 case BIO_C_SET_WRITE_BUF_SIZE: /* Non-threadsafe */
666 ret = (long)dgram_pair_ctrl_set_write_buf_size(bio, (size_t)num);
667 break;
668
669 /*
670 * BIO_get_write_buf_size: Get ring buffer size.
671 */
672 case BIO_C_GET_WRITE_BUF_SIZE: /* Non-threadsafe */
673 ret = (long)b->req_buf_len;
674 break;
675
676 /*
677 * BIO_reset: Clear all data which was written to this side of the pair.
678 */
679 case BIO_CTRL_RESET: /* Non-threadsafe */
680 dgram_pair_ctrl_reset(bio);
681 break;
682
683 /*
684 * BIO_get_write_guarantee: Any BIO_write providing a buffer less than or
685 * equal to this value is guaranteed to succeed.
686 */
687 case BIO_C_GET_WRITE_GUARANTEE: /* Threadsafe */
688 ret = (long)dgram_pair_ctrl_get_write_guarantee(bio);
689 break;
690
691 /* BIO_pending: Bytes available to read. */
692 case BIO_CTRL_PENDING: /* Threadsafe */
693 ret = (long)dgram_pair_ctrl_pending(bio);
694 break;
695
696 /* BIO_flush: No-op. */
697 case BIO_CTRL_FLUSH: /* Threadsafe */
698 break;
699
700 /* BIO_dgram_get_no_trunc */
701 case BIO_CTRL_DGRAM_GET_NO_TRUNC: /* Non-threadsafe */
702 ret = (long)b->no_trunc;
703 break;
704
705 /* BIO_dgram_set_no_trunc */
706 case BIO_CTRL_DGRAM_SET_NO_TRUNC: /* Non-threadsafe */
707 b->no_trunc = (num > 0);
708 break;
709
710 /* BIO_dgram_get_local_addr_enable */
711 case BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE: /* Non-threadsafe */
712 *(int *)ptr = (int)dgram_pair_ctrl_get_local_addr_enable(bio);
713 break;
714
715 /* BIO_dgram_set_local_addr_enable */
716 case BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE: /* Non-threadsafe */
717 ret = (long)dgram_pair_ctrl_set_local_addr_enable(bio, num);
718 break;
719
720 /* BIO_dgram_get_local_addr_cap: Can local addresses be supported? */
721 case BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP: /* Non-threadsafe */
722 ret = (long)dgram_pair_ctrl_get_local_addr_cap(bio);
723 break;
724
725 /* BIO_dgram_get_effective_caps */
726 case BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS: /* Non-threadsafe */
727 /* BIO_dgram_get_caps */
728 case BIO_CTRL_DGRAM_GET_CAPS: /* Non-threadsafe */
729 ret = (long)dgram_pair_ctrl_get_caps(bio);
730 break;
731
732 /* BIO_dgram_set_caps */
733 case BIO_CTRL_DGRAM_SET_CAPS: /* Non-threadsafe */
734 ret = (long)dgram_pair_ctrl_set_caps(bio, (uint32_t)num);
735 break;
736
737 /* BIO_dgram_get_mtu */
738 case BIO_CTRL_DGRAM_GET_MTU: /* Non-threadsafe */
739 ret = (long)dgram_pair_ctrl_get_mtu(bio);
740 break;
741
742 /* BIO_dgram_set_mtu */
743 case BIO_CTRL_DGRAM_SET_MTU: /* Non-threadsafe */
744 ret = (long)dgram_pair_ctrl_set_mtu(bio, (uint32_t)num);
745 break;
746
747 case BIO_CTRL_DGRAM_SET0_LOCAL_ADDR:
748 ret = (long)dgram_pair_ctrl_set0_local_addr(bio, (BIO_ADDR *)ptr);
749 break;
750
751 /*
752 * BIO_eof: Returns whether this half of the BIO pair is empty of data to
753 * read.
754 */
755 case BIO_CTRL_EOF: /* Non-threadsafe */
756 ret = (long)dgram_pair_ctrl_eof(bio);
757 break;
758
759 default:
760 ret = 0;
761 break;
762 }
763
764 return ret;
765 }
766
dgram_pair_ctrl(BIO * bio,int cmd,long num,void * ptr)767 static long dgram_pair_ctrl(BIO *bio, int cmd, long num, void *ptr)
768 {
769 long ret = 1;
770
771 switch (cmd) {
772 /*
773 * BIO_make_bio_pair: this is usually used by BIO_new_dgram_pair, though it
774 * may be used manually after manually creating each half of a BIO pair
775 * using BIO_new. This only needs to be called on one of the BIOs.
776 */
777 case BIO_C_MAKE_BIO_PAIR: /* Non-threadsafe */
778 ret = (long)dgram_pair_ctrl_make_bio_pair(bio, (BIO *)ptr);
779 break;
780
781 /*
782 * BIO_destroy_bio_pair: Manually disconnect two halves of a BIO pair so
783 * that they are no longer peers.
784 */
785 case BIO_C_DESTROY_BIO_PAIR: /* Non-threadsafe */
786 dgram_pair_ctrl_destroy_bio_pair(bio);
787 break;
788
789 /* BIO_dgram_get_effective_caps */
790 case BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS: /* Non-threadsafe */
791 ret = (long)dgram_pair_ctrl_get_effective_caps(bio);
792 break;
793
794 default:
795 ret = dgram_mem_ctrl(bio, cmd, num, ptr);
796 break;
797 }
798
799 return ret;
800 }
801
BIO_new_bio_dgram_pair(BIO ** pbio1,size_t writebuf1,BIO ** pbio2,size_t writebuf2)802 int BIO_new_bio_dgram_pair(BIO **pbio1, size_t writebuf1,
803 BIO **pbio2, size_t writebuf2)
804 {
805 int ret = 0;
806 long r;
807 BIO *bio1 = NULL, *bio2 = NULL;
808
809 bio1 = BIO_new(BIO_s_dgram_pair());
810 if (bio1 == NULL)
811 goto err;
812
813 bio2 = BIO_new(BIO_s_dgram_pair());
814 if (bio2 == NULL)
815 goto err;
816
817 if (writebuf1 > 0) {
818 r = BIO_set_write_buf_size(bio1, writebuf1);
819 if (r == 0)
820 goto err;
821 }
822
823 if (writebuf2 > 0) {
824 r = BIO_set_write_buf_size(bio2, writebuf2);
825 if (r == 0)
826 goto err;
827 }
828
829 r = BIO_make_bio_pair(bio1, bio2);
830 if (r == 0)
831 goto err;
832
833 ret = 1;
834 err:
835 if (ret == 0) {
836 BIO_free(bio1);
837 bio1 = NULL;
838 BIO_free(bio2);
839 bio2 = NULL;
840 }
841
842 *pbio1 = bio1;
843 *pbio2 = bio2;
844 return ret;
845 }
846
847 /* Must hold peer write lock */
dgram_pair_read_inner(struct bio_dgram_pair_st * b,uint8_t * buf,size_t sz)848 static size_t dgram_pair_read_inner(struct bio_dgram_pair_st *b, uint8_t *buf, size_t sz)
849 {
850 size_t total_read = 0;
851
852 /*
853 * We repeat pops from the ring buffer for as long as we have more
854 * application *buffer to fill until we fail. We may not be able to pop
855 * enough data to fill the buffer in one operation if the ring buffer wraps
856 * around, but there may still be more data available.
857 */
858 while (sz > 0) {
859 uint8_t *src_buf = NULL;
860 size_t src_len = 0;
861
862 /*
863 * There are two BIO instances, each with a ringbuf. We read from the
864 * peer ringbuf and write to our own ringbuf.
865 */
866 ring_buf_tail(&b->rbuf, &src_buf, &src_len);
867 if (src_len == 0)
868 break;
869
870 if (src_len > sz)
871 src_len = sz;
872
873 if (buf != NULL)
874 memcpy(buf, src_buf, src_len);
875
876 ring_buf_pop(&b->rbuf, src_len);
877
878 if (buf != NULL)
879 buf += src_len;
880 total_read += src_len;
881 sz -= src_len;
882 }
883
884 return total_read;
885 }
886
887 /*
888 * Must hold peer write lock. Returns number of bytes processed or negated BIO
889 * response code.
890 */
dgram_pair_read_actual(BIO * bio,char * buf,size_t sz,BIO_ADDR * local,BIO_ADDR * peer,int is_multi)891 static ossl_ssize_t dgram_pair_read_actual(BIO *bio, char *buf, size_t sz,
892 BIO_ADDR *local, BIO_ADDR *peer,
893 int is_multi)
894 {
895 size_t l, trunc = 0, saved_idx, saved_count;
896 struct bio_dgram_pair_st *b = bio->ptr, *readb;
897 struct dgram_hdr hdr;
898
899 if (!is_multi)
900 BIO_clear_retry_flags(bio);
901
902 if (!bio->init)
903 return -BIO_R_UNINITIALIZED;
904
905 if (!ossl_assert(b != NULL))
906 return -BIO_R_TRANSFER_ERROR;
907
908 if (is_dgram_pair(b))
909 readb = b->peer->ptr;
910 else
911 readb = b;
912 if (!ossl_assert(readb != NULL && readb->rbuf.start != NULL))
913 return -BIO_R_TRANSFER_ERROR;
914
915 if (sz > 0 && buf == NULL)
916 return -BIO_R_INVALID_ARGUMENT;
917
918 /* If the caller wants to know the local address, it must be enabled */
919 if (local != NULL && b->local_addr_enable == 0)
920 return -BIO_R_LOCAL_ADDR_NOT_AVAILABLE;
921
922 /* Read the header. */
923 saved_idx = readb->rbuf.idx[1];
924 saved_count = readb->rbuf.count;
925 l = dgram_pair_read_inner(readb, (uint8_t *)&hdr, sizeof(hdr));
926 if (l == 0) {
927 /* Buffer was empty. */
928 if (!is_multi)
929 BIO_set_retry_read(bio);
930 return -BIO_R_NON_FATAL;
931 }
932
933 if (!ossl_assert(l == sizeof(hdr)))
934 /*
935 * This should not be possible as headers (and their following payloads)
936 * should always be written atomically.
937 */
938 return -BIO_R_BROKEN_PIPE;
939
940 if (sz > hdr.len) {
941 sz = hdr.len;
942 } else if (sz < hdr.len) {
943 /* Truncation is occurring. */
944 trunc = hdr.len - sz;
945 if (b->no_trunc) {
946 /* Restore original state. */
947 readb->rbuf.idx[1] = saved_idx;
948 readb->rbuf.count = saved_count;
949 return -BIO_R_NON_FATAL;
950 }
951 }
952
953 l = dgram_pair_read_inner(readb, (uint8_t *)buf, sz);
954 if (!ossl_assert(l == sz))
955 /* We were somehow not able to read the entire datagram. */
956 return -BIO_R_TRANSFER_ERROR;
957
958 /*
959 * If the datagram was truncated due to an inadequate buffer, discard the
960 * remainder.
961 */
962 if (trunc > 0 && !ossl_assert(dgram_pair_read_inner(readb, NULL, trunc) == trunc))
963 /* We were somehow not able to read/skip the entire datagram. */
964 return -BIO_R_TRANSFER_ERROR;
965
966 if (local != NULL)
967 *local = hdr.dst_addr;
968 if (peer != NULL)
969 *peer = hdr.src_addr;
970
971 return (ossl_ssize_t)l;
972 }
973
974 /* Threadsafe */
dgram_pair_lock_both_write(struct bio_dgram_pair_st * a,struct bio_dgram_pair_st * b)975 static int dgram_pair_lock_both_write(struct bio_dgram_pair_st *a,
976 struct bio_dgram_pair_st *b)
977 {
978 struct bio_dgram_pair_st *x, *y;
979
980 x = (a->role == 1) ? a : b;
981 y = (a->role == 1) ? b : a;
982
983 if (!ossl_assert(a->role != b->role))
984 return 0;
985
986 if (!ossl_assert(a != b && x != y))
987 return 0;
988
989 if (CRYPTO_THREAD_write_lock(x->lock) == 0)
990 return 0;
991
992 if (CRYPTO_THREAD_write_lock(y->lock) == 0) {
993 CRYPTO_THREAD_unlock(x->lock);
994 return 0;
995 }
996
997 return 1;
998 }
999
dgram_pair_unlock_both(struct bio_dgram_pair_st * a,struct bio_dgram_pair_st * b)1000 static void dgram_pair_unlock_both(struct bio_dgram_pair_st *a,
1001 struct bio_dgram_pair_st *b)
1002 {
1003 CRYPTO_THREAD_unlock(a->lock);
1004 CRYPTO_THREAD_unlock(b->lock);
1005 }
1006
1007 /* Threadsafe */
dgram_pair_read(BIO * bio,char * buf,int sz_)1008 static int dgram_pair_read(BIO *bio, char *buf, int sz_)
1009 {
1010 int ret;
1011 ossl_ssize_t l;
1012 struct bio_dgram_pair_st *b = bio->ptr, *peerb;
1013
1014 if (sz_ < 0) {
1015 ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
1016 return -1;
1017 }
1018
1019 if (b->peer == NULL) {
1020 ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE);
1021 return -1;
1022 }
1023
1024 peerb = b->peer->ptr;
1025
1026 /*
1027 * For BIO_read we have to acquire both locks because we touch the retry
1028 * flags on the local bio. (This is avoided in the recvmmsg case as it does
1029 * not touch the retry flags.)
1030 */
1031 if (dgram_pair_lock_both_write(peerb, b) == 0) {
1032 ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1033 return -1;
1034 }
1035
1036 l = dgram_pair_read_actual(bio, buf, (size_t)sz_, NULL, NULL, 0);
1037 if (l < 0) {
1038 if (l != -BIO_R_NON_FATAL)
1039 ERR_raise(ERR_LIB_BIO, -l);
1040 ret = -1;
1041 } else {
1042 ret = (int)l;
1043 }
1044
1045 dgram_pair_unlock_both(peerb, b);
1046 return ret;
1047 }
1048
1049 /* Threadsafe */
dgram_pair_recvmmsg(BIO * bio,BIO_MSG * msg,size_t stride,size_t num_msg,uint64_t flags,size_t * num_processed)1050 static int dgram_pair_recvmmsg(BIO *bio, BIO_MSG *msg,
1051 size_t stride, size_t num_msg,
1052 uint64_t flags,
1053 size_t *num_processed)
1054 {
1055 int ret;
1056 ossl_ssize_t l;
1057 BIO_MSG *m;
1058 size_t i;
1059 struct bio_dgram_pair_st *b = bio->ptr, *readb;
1060
1061 if (num_msg == 0) {
1062 *num_processed = 0;
1063 return 1;
1064 }
1065
1066 if (!bio->init) {
1067 ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE);
1068 *num_processed = 0;
1069 return 0;
1070 }
1071
1072 if (is_dgram_pair(b))
1073 readb = b->peer->ptr;
1074 else
1075 readb = b;
1076
1077 if (CRYPTO_THREAD_write_lock(readb->lock) == 0) {
1078 ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1079 *num_processed = 0;
1080 return 0;
1081 }
1082
1083 for (i = 0; i < num_msg; ++i) {
1084 m = &BIO_MSG_N(msg, i);
1085 l = dgram_pair_read_actual(bio, m->data, m->data_len,
1086 m->local, m->peer, 1);
1087 if (l < 0) {
1088 *num_processed = i;
1089 if (i > 0) {
1090 ret = 1;
1091 } else {
1092 ERR_raise(ERR_LIB_BIO, -l);
1093 ret = 0;
1094 }
1095 goto out;
1096 }
1097
1098 m->data_len = l;
1099 m->flags = 0;
1100 }
1101
1102 *num_processed = i;
1103 ret = 1;
1104 out:
1105 CRYPTO_THREAD_unlock(readb->lock);
1106 return ret;
1107 }
1108
1109 /* Threadsafe */
dgram_mem_read(BIO * bio,char * buf,int sz_)1110 static int dgram_mem_read(BIO *bio, char *buf, int sz_)
1111 {
1112 int ret;
1113 ossl_ssize_t l;
1114 struct bio_dgram_pair_st *b = bio->ptr;
1115
1116 if (sz_ < 0) {
1117 ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
1118 return -1;
1119 }
1120
1121 if (CRYPTO_THREAD_write_lock(b->lock) == 0) {
1122 ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1123 return -1;
1124 }
1125
1126 l = dgram_pair_read_actual(bio, buf, (size_t)sz_, NULL, NULL, 0);
1127 if (l < 0) {
1128 if (l != -BIO_R_NON_FATAL)
1129 ERR_raise(ERR_LIB_BIO, -l);
1130 ret = -1;
1131 } else {
1132 ret = (int)l;
1133 }
1134
1135 CRYPTO_THREAD_unlock(b->lock);
1136 return ret;
1137 }
1138
1139 /*
1140 * Calculate the array growth based on the target size.
1141 *
1142 * The growth factor is a rational number and is defined by a numerator
1143 * and a denominator. According to Andrew Koenig in his paper "Why Are
1144 * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less
1145 * than the golden ratio (1.618...).
1146 *
1147 * We use an expansion factor of 8 / 5 = 1.6
1148 */
1149 static const size_t max_rbuf_size = SIZE_MAX / 2; /* unlimited in practice */
compute_rbuf_growth(size_t target,size_t current)1150 static ossl_inline size_t compute_rbuf_growth(size_t target, size_t current)
1151 {
1152 int err = 0;
1153
1154 while (current < target) {
1155 if (current >= max_rbuf_size)
1156 return 0;
1157
1158 current = safe_muldiv_size_t(current, 8, 5, &err);
1159 if (err)
1160 return 0;
1161 if (current >= max_rbuf_size)
1162 current = max_rbuf_size;
1163 }
1164 return current;
1165 }
1166
1167 /* Must hold local write lock */
dgram_pair_write_inner(struct bio_dgram_pair_st * b,const uint8_t * buf,size_t sz)1168 static size_t dgram_pair_write_inner(struct bio_dgram_pair_st *b,
1169 const uint8_t *buf, size_t sz)
1170 {
1171 size_t total_written = 0;
1172
1173 /*
1174 * We repeat pushes to the ring buffer for as long as we have data until we
1175 * fail. We may not be able to push in one operation if the ring buffer
1176 * wraps around, but there may still be more room for data.
1177 */
1178 while (sz > 0) {
1179 size_t dst_len;
1180 uint8_t *dst_buf;
1181
1182 /*
1183 * There are two BIO instances, each with a ringbuf. We write to our own
1184 * ringbuf and read from the peer ringbuf.
1185 */
1186 ring_buf_head(&b->rbuf, &dst_buf, &dst_len);
1187 if (dst_len == 0) {
1188 size_t new_len;
1189
1190 if (!b->grows_on_write) /* resize only if size not set explicitly */
1191 break;
1192 /* increase the size */
1193 new_len = compute_rbuf_growth(b->req_buf_len + sz, b->req_buf_len);
1194 if (new_len == 0 || !ring_buf_resize(&b->rbuf, new_len))
1195 break;
1196 b->req_buf_len = new_len;
1197 }
1198
1199 if (dst_len > sz)
1200 dst_len = sz;
1201
1202 memcpy(dst_buf, buf, dst_len);
1203 ring_buf_push(&b->rbuf, dst_len);
1204
1205 buf += dst_len;
1206 sz -= dst_len;
1207 total_written += dst_len;
1208 }
1209
1210 return total_written;
1211 }
1212
1213 /*
1214 * Must hold local write lock. Returns number of bytes processed or negated BIO
1215 * response code.
1216 */
dgram_pair_write_actual(BIO * bio,const char * buf,size_t sz,const BIO_ADDR * local,const BIO_ADDR * peer,int is_multi)1217 static ossl_ssize_t dgram_pair_write_actual(BIO *bio, const char *buf, size_t sz,
1218 const BIO_ADDR *local, const BIO_ADDR *peer,
1219 int is_multi)
1220 {
1221 static const BIO_ADDR zero_addr;
1222 size_t saved_idx, saved_count;
1223 struct bio_dgram_pair_st *b = bio->ptr, *readb;
1224 struct dgram_hdr hdr = { 0 };
1225
1226 if (!is_multi)
1227 BIO_clear_retry_flags(bio);
1228
1229 if (!bio->init)
1230 return -BIO_R_UNINITIALIZED;
1231
1232 if (!ossl_assert(b != NULL && b->rbuf.start != NULL))
1233 return -BIO_R_TRANSFER_ERROR;
1234
1235 if (sz > 0 && buf == NULL)
1236 return -BIO_R_INVALID_ARGUMENT;
1237
1238 if (local != NULL && b->local_addr_enable == 0)
1239 return -BIO_R_LOCAL_ADDR_NOT_AVAILABLE;
1240
1241 if (is_dgram_pair(b))
1242 readb = b->peer->ptr;
1243 else
1244 readb = b;
1245 if (peer != NULL && (readb->cap & BIO_DGRAM_CAP_HANDLES_DST_ADDR) == 0)
1246 return -BIO_R_PEER_ADDR_NOT_AVAILABLE;
1247
1248 hdr.len = sz;
1249 hdr.dst_addr = (peer != NULL ? *peer : zero_addr);
1250 if (local == NULL)
1251 local = b->local_addr;
1252 hdr.src_addr = (local != NULL ? *local : zero_addr);
1253
1254 saved_idx = b->rbuf.idx[0];
1255 saved_count = b->rbuf.count;
1256 if (dgram_pair_write_inner(b, (const uint8_t *)&hdr, sizeof(hdr)) != sizeof(hdr)
1257 || dgram_pair_write_inner(b, (const uint8_t *)buf, sz) != sz) {
1258 /*
1259 * We were not able to push the header and the entirety of the payload
1260 * onto the ring buffer, so abort and roll back the ring buffer state.
1261 */
1262 b->rbuf.idx[0] = saved_idx;
1263 b->rbuf.count = saved_count;
1264 if (!is_multi)
1265 BIO_set_retry_write(bio);
1266 return -BIO_R_NON_FATAL;
1267 }
1268
1269 return sz;
1270 }
1271
1272 /* Threadsafe */
dgram_pair_write(BIO * bio,const char * buf,int sz_)1273 static int dgram_pair_write(BIO *bio, const char *buf, int sz_)
1274 {
1275 int ret;
1276 ossl_ssize_t l;
1277 struct bio_dgram_pair_st *b = bio->ptr;
1278
1279 if (sz_ < 0) {
1280 ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT);
1281 return -1;
1282 }
1283
1284 if (CRYPTO_THREAD_write_lock(b->lock) == 0) {
1285 ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1286 return -1;
1287 }
1288
1289 l = dgram_pair_write_actual(bio, buf, (size_t)sz_, NULL, NULL, 0);
1290 if (l < 0) {
1291 ERR_raise(ERR_LIB_BIO, -l);
1292 ret = -1;
1293 } else {
1294 ret = (int)l;
1295 }
1296
1297 CRYPTO_THREAD_unlock(b->lock);
1298 return ret;
1299 }
1300
1301 /* Threadsafe */
dgram_pair_sendmmsg(BIO * bio,BIO_MSG * msg,size_t stride,size_t num_msg,uint64_t flags,size_t * num_processed)1302 static int dgram_pair_sendmmsg(BIO *bio, BIO_MSG *msg,
1303 size_t stride, size_t num_msg,
1304 uint64_t flags, size_t *num_processed)
1305 {
1306 ossl_ssize_t ret, l;
1307 BIO_MSG *m;
1308 size_t i;
1309 struct bio_dgram_pair_st *b = bio->ptr;
1310
1311 if (num_msg == 0) {
1312 *num_processed = 0;
1313 return 1;
1314 }
1315
1316 if (CRYPTO_THREAD_write_lock(b->lock) == 0) {
1317 ERR_raise(ERR_LIB_BIO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
1318 *num_processed = 0;
1319 return 0;
1320 }
1321
1322 for (i = 0; i < num_msg; ++i) {
1323 m = &BIO_MSG_N(msg, i);
1324 l = dgram_pair_write_actual(bio, m->data, m->data_len,
1325 m->local, m->peer, 1);
1326 if (l < 0) {
1327 *num_processed = i;
1328 if (i > 0) {
1329 ret = 1;
1330 } else {
1331 ERR_raise(ERR_LIB_BIO, -l);
1332 ret = 0;
1333 }
1334 goto out;
1335 }
1336
1337 m->flags = 0;
1338 }
1339
1340 *num_processed = i;
1341 ret = 1;
1342 out:
1343 CRYPTO_THREAD_unlock(b->lock);
1344 return ret;
1345 }
1346
1347 #endif
1348