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