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 ASSERT(size <= MBUF_SIZE_MAX);
46
47 struct mbuf_set *ret;
48 ALLOC_OBJ_CLEAR(ret, struct mbuf_set);
49 ret->capacity = adjust_power_of_2(size);
50 ALLOC_ARRAY(ret->array, struct mbuf_item, ret->capacity);
51 return ret;
52}
53
54#if defined(__GNUC__) || defined(__clang__)
55#pragma GCC diagnostic pop
56#endif
57
58void
60{
61 if (ms)
62 {
63 int i;
64 for (i = 0; i < (int)ms->len; ++i)
65 {
66 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
67 mbuf_free_buf(item->buffer);
68 }
69 free(ms->array);
70 free(ms);
71 }
72}
73
74struct mbuf_buffer *
76{
77 struct mbuf_buffer *ret;
78 ALLOC_OBJ(ret, struct mbuf_buffer);
79 ret->buf = clone_buf(buf);
80 ret->refcount = 1;
81 ret->flags = 0;
82 return ret;
83}
84
85void
87{
88 if (mb)
89 {
90 if (--mb->refcount <= 0)
91 {
92 free_buf(&mb->buf);
93 free(mb);
94 }
95 }
96}
97
98void
99mbuf_add_item(struct mbuf_set *ms, const struct mbuf_item *item)
100{
101 ASSERT(ms);
102 if (ms->len == ms->capacity)
103 {
104 struct mbuf_item rm;
105 ASSERT(mbuf_extract_item(ms, &rm));
107 msg(D_MULTI_DROPPED, "MBUF: mbuf packet dropped");
108 }
109
110 ASSERT(ms->len < ms->capacity);
111
112 ms->array[MBUF_INDEX(ms->head, ms->len, ms->capacity)] = *item;
113 if (++ms->len > ms->max_queued)
114 {
115 ms->max_queued = ms->len;
116 }
117 ++item->buffer->refcount;
118}
119
120bool
121mbuf_extract_item(struct mbuf_set *ms, struct mbuf_item *item)
122{
123 bool ret = false;
124 if (ms)
125 {
126 ASSERT(item);
127 while (ms->len)
128 {
129 *item = ms->array[ms->head];
130 ms->head = MBUF_INDEX(ms->head, 1, ms->capacity);
131 --ms->len;
132 if (item->instance) /* ignore dereferenced instances */
133 {
134 ret = true;
135 break;
136 }
137 }
138 }
139 return ret;
140}
141
142struct multi_instance *
144{
145 struct multi_instance *ret = NULL;
146 if (ms)
147 {
148 int i;
149 for (i = 0; i < (int)ms->len; ++i)
150 {
151 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
152 if (item->instance)
153 {
154 ret = item->instance;
155 break;
156 }
157 }
158 }
159 return ret;
160}
161
162void
164{
165 if (ms)
166 {
167 int i;
168 for (i = 0; i < (int)ms->len; ++i)
169 {
170 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
171 if (item->instance == mi)
172 {
173 mbuf_free_buf(item->buffer);
174 item->buffer = NULL;
175 item->instance = NULL;
176 msg(D_MBUF, "MBUF: dereferenced queued packet");
177 }
178 }
179 }
180}
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:1059
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition buffer.h:1064
#define ALLOC_ARRAY(dptr, type, n)
Definition buffer.h:1070
#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:99
struct mbuf_buffer * mbuf_alloc_buf(const struct buffer *buf)
Definition mbuf.c:75
void mbuf_free_buf(struct mbuf_buffer *mb)
Definition mbuf.c:86
void mbuf_dereference_instance(struct mbuf_set *ms, struct multi_instance *mi)
Definition mbuf.c:163
bool mbuf_extract_item(struct mbuf_set *ms, struct mbuf_item *item)
Definition mbuf.c:121
void mbuf_free(struct mbuf_set *ms)
Definition mbuf.c:59
struct multi_instance * mbuf_peek_dowork(struct mbuf_set *ms)
Definition mbuf.c:143
struct mbuf_set * mbuf_init(unsigned int size)
Definition mbuf.c:43
#define MBUF_SIZE_MAX
Definition mbuf.h:40
#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:48
struct buffer buf
Definition mbuf.h:44
int refcount
Definition mbuf.h:45
struct mbuf_buffer * buffer
Definition mbuf.h:53
struct multi_instance * instance
Definition mbuf.h:54
struct mbuf_item * array
Definition mbuf.h:63
unsigned int max_queued
Definition mbuf.h:62
unsigned int head
Definition mbuf.h:59
unsigned int len
Definition mbuf.h:60
unsigned int capacity
Definition mbuf.h:61
Server-mode state structure for one single VPN tunnel.
Definition multi.h:102