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 
44 volatile struct mmap_stats *mmap_stats = NULL; /* GLOBAL */
45 static char mmap_fn[128];
46 
47 void
48 mstats_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 
110 void
111 mstats_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) */
M_INFO
#define M_INFO
Definition: errlevel.h:55
M_ERRNO
#define M_ERRNO
Definition: error.h:94
M_FATAL
#define M_FATAL
Definition: error.h:89
CLEAR
#define CLEAR(x)
Definition: basic.h:33
write
@ write
Definition: interactive.c:219
misc.h
M_WARN
#define M_WARN
Definition: error.h:91
M_ERR
#define M_ERR
Definition: error.h:105
platform_unlink
bool platform_unlink(const char *filename)
Definition: platform.c:501
syshead.h
mstats.h
config.h
memdbg.h
msg
#define msg(flags,...)
Definition: error.h:144