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