OpenVPN
mbuf.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2025 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "syshead.h"
28
29#include "buffer.h"
30#include "error.h"
31#include "integer.h"
32#include "misc.h"
33#include "mbuf.h"
34
35#include "memdbg.h"
36
37#if defined(__GNUC__) || defined(__clang__)
38#pragma GCC diagnostic push
39#pragma GCC diagnostic ignored "-Wconversion"
40#endif
41
42struct mbuf_set *
43mbuf_init(unsigned int size)
44{
45 struct mbuf_set *ret;
46 ALLOC_OBJ_CLEAR(ret, struct mbuf_set);
47 ret->capacity = adjust_power_of_2(size);
48 ALLOC_ARRAY(ret->array, struct mbuf_item, ret->capacity);
49 return ret;
50}
51
52#if defined(__GNUC__) || defined(__clang__)
53#pragma GCC diagnostic pop
54#endif
55
56void
58{
59 if (ms)
60 {
61 int i;
62 for (i = 0; i < (int)ms->len; ++i)
63 {
64 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
65 mbuf_free_buf(item->buffer);
66 }
67 free(ms->array);
68 free(ms);
69 }
70}
71
72struct mbuf_buffer *
74{
75 struct mbuf_buffer *ret;
76 ALLOC_OBJ(ret, struct mbuf_buffer);
77 ret->buf = clone_buf(buf);
78 ret->refcount = 1;
79 ret->flags = 0;
80 return ret;
81}
82
83void
85{
86 if (mb)
87 {
88 if (--mb->refcount <= 0)
89 {
90 free_buf(&mb->buf);
91 free(mb);
92 }
93 }
94}
95
96void
97mbuf_add_item(struct mbuf_set *ms, const struct mbuf_item *item)
98{
99 ASSERT(ms);
100 if (ms->len == ms->capacity)
101 {
102 struct mbuf_item rm;
103 ASSERT(mbuf_extract_item(ms, &rm));
105 msg(D_MULTI_DROPPED, "MBUF: mbuf packet dropped");
106 }
107
108 ASSERT(ms->len < ms->capacity);
109
110 ms->array[MBUF_INDEX(ms->head, ms->len, ms->capacity)] = *item;
111 if (++ms->len > ms->max_queued)
112 {
113 ms->max_queued = ms->len;
114 }
115 ++item->buffer->refcount;
116}
117
118bool
119mbuf_extract_item(struct mbuf_set *ms, struct mbuf_item *item)
120{
121 bool ret = false;
122 if (ms)
123 {
124 while (ms->len)
125 {
126 *item = ms->array[ms->head];
127 ms->head = MBUF_INDEX(ms->head, 1, ms->capacity);
128 --ms->len;
129 if (item->instance) /* ignore dereferenced instances */
130 {
131 ret = true;
132 break;
133 }
134 }
135 }
136 return ret;
137}
138
139struct multi_instance *
141{
142 struct multi_instance *ret = NULL;
143 if (ms)
144 {
145 int i;
146 for (i = 0; i < (int)ms->len; ++i)
147 {
148 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
149 if (item->instance)
150 {
151 ret = item->instance;
152 break;
153 }
154 }
155 }
156 return ret;
157}
158
159void
161{
162 if (ms)
163 {
164 int i;
165 for (i = 0; i < (int)ms->len; ++i)
166 {
167 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
168 if (item->instance == mi)
169 {
170 mbuf_free_buf(item->buffer);
171 item->buffer = NULL;
172 item->instance = NULL;
173 msg(D_MBUF, "MBUF: dereferenced queued packet");
174 }
175 }
176 }
177}
void free_buf(struct buffer *buf)
Definition buffer.c:184
struct buffer clone_buf(const struct buffer *buf)
Definition buffer.c:116
#define ALLOC_OBJ(dptr, type)
Definition buffer.h:1037
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition buffer.h:1042
#define ALLOC_ARRAY(dptr, type, n)
Definition buffer.h:1048
#define D_MBUF
Definition errlevel.h:98
#define D_MULTI_DROPPED
Definition errlevel.h:100
static size_t adjust_power_of_2(size_t u)
Definition integer.h:205
void mbuf_add_item(struct mbuf_set *ms, const struct mbuf_item *item)
Definition mbuf.c:97
struct mbuf_buffer * mbuf_alloc_buf(const struct buffer *buf)
Definition mbuf.c:73
void mbuf_free_buf(struct mbuf_buffer *mb)
Definition mbuf.c:84
void mbuf_dereference_instance(struct mbuf_set *ms, struct multi_instance *mi)
Definition mbuf.c:160
bool mbuf_extract_item(struct mbuf_set *ms, struct mbuf_item *item)
Definition mbuf.c:119
void mbuf_free(struct mbuf_set *ms)
Definition mbuf.c:57
struct multi_instance * mbuf_peek_dowork(struct mbuf_set *ms)
Definition mbuf.c:140
struct mbuf_set * mbuf_init(unsigned int size)
Definition mbuf.c:43
#define MBUF_INDEX(head, offset, size)
Definition mbuf.h:38
#define msg(flags,...)
Definition error.h:152
#define ASSERT(x)
Definition error.h:219
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
unsigned int flags
Definition mbuf.h:46
struct buffer buf
Definition mbuf.h:42
int refcount
Definition mbuf.h:43
struct mbuf_buffer * buffer
Definition mbuf.h:51
struct multi_instance * instance
Definition mbuf.h:52
struct mbuf_item * array
Definition mbuf.h:61
unsigned int max_queued
Definition mbuf.h:60
unsigned int head
Definition mbuf.h:57
unsigned int len
Definition mbuf.h:58
unsigned int capacity
Definition mbuf.h:59
Server-mode state structure for one single VPN tunnel.
Definition multi.h:103