OpenVPN
mstats.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/*
24 * Maintain usage stats in a memory-mapped file
25 */
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include "syshead.h"
32
33#if defined(ENABLE_MEMSTATS)
34
35#include <sys/mman.h>
36
37#include "error.h"
38#include "misc.h"
39#include "mstats.h"
40
41#include "memdbg.h"
42
43volatile struct mmap_stats *mmap_stats = NULL; /* GLOBAL */
44static char mmap_fn[128];
45
46void
47mstats_open(const char *fn)
48{
49 void *data;
50 ssize_t stat;
51 int fd;
52 struct mmap_stats ms;
53
54 if (mmap_stats) /* already called? */
55 {
56 return;
57 }
58
59 /* verify that filename is not too long */
60 if (strlen(fn) >= sizeof(mmap_fn))
61 {
62 msg(M_FATAL, "mstats_open: filename too long");
63 }
64
65 /* create file that will be memory mapped */
66 fd = open(fn, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
67 if (fd < 0)
68 {
69 msg(M_ERR, "mstats_open: cannot open: %s", fn);
70 return;
71 }
72
73 /* set the file to the correct size to contain a
74 * struct mmap_stats, and zero it */
75 CLEAR(ms);
76 ms.state = MSTATS_ACTIVE;
77 stat = write(fd, &ms, sizeof(ms));
78 if (stat != sizeof(ms))
79 {
80 msg(M_ERR, "mstats_open: write error: %s", fn);
81 close(fd);
82 return;
83 }
84
85 /* mmap the file */
86 data = mmap(NULL, sizeof(struct mmap_stats), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
87 if (data == MAP_FAILED)
88 {
89 msg(M_ERR, "mstats_open: write error: %s", fn);
90 close(fd);
91 return;
92 }
93
94 /* close the fd (mmap now controls the file) */
95 if (close(fd))
96 {
97 msg(M_ERR, "mstats_open: close error: %s", fn);
98 }
99
100 /* save filename so we can delete it later */
101 strcpy(mmap_fn, fn);
102
103 /* save a global pointer to memory-mapped region */
104 mmap_stats = (struct mmap_stats *)data;
105
106 msg(M_INFO, "memstats data will be written to %s", fn);
107}
108
109void
110mstats_close(void)
111{
112 if (mmap_stats)
113 {
114 mmap_stats->state = MSTATS_EXPIRED;
115 if (munmap((void *)mmap_stats, sizeof(struct mmap_stats)))
116 {
117 msg(M_WARN | M_ERRNO, "mstats_close: munmap error");
118 }
119 platform_unlink(mmap_fn);
120 mmap_stats = NULL;
121 }
122}
123
124#endif /* if defined(ENABLE_MEMSTATS) */
#define M_INFO
Definition errlevel.h:54
@ write
#define CLEAR(x)
Definition basic.h:32
#define M_FATAL
Definition error.h:88
#define M_ERR
Definition error.h:104
#define msg(flags,...)
Definition error.h:150
#define M_WARN
Definition error.h:90
#define M_ERRNO
Definition error.h:93
bool platform_unlink(const char *filename)
Definition platform.c:491