OpenVPN: Update to version 2.3.2. Solves TLS security bug.
[tomato.git] / release / src / router / openvpn / src / openvpn / status.c
blobb7ff484346b47b32b9dc8e8bce082db265e42fa0
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.
8 * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
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.
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.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #elif defined(_MSC_VER)
28 #include "config-msvc.h"
29 #endif
31 #include "syshead.h"
33 #include "status.h"
34 #include "perf.h"
35 #include "misc.h"
36 #include "fdmisc.h"
38 #include "memdbg.h"
41 * printf-style interface for outputting status info
44 static const char *
45 print_status_mode (unsigned int flags)
47 switch (flags)
49 case STATUS_OUTPUT_WRITE:
50 return "WRITE";
51 case STATUS_OUTPUT_READ:
52 return "READ";
53 case STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE:
54 return "READ/WRITE";
55 default:
56 return "UNDEF";
60 struct status_output *
61 status_open (const char *filename,
62 const int refresh_freq,
63 const int msglevel,
64 const struct virtual_output *vout,
65 const unsigned int flags)
67 struct status_output *so = NULL;
68 if (filename || msglevel >= 0 || vout)
70 ALLOC_OBJ_CLEAR (so, struct status_output);
71 so->flags = flags;
72 so->msglevel = msglevel;
73 so->vout = vout;
74 so->fd = -1;
75 buf_reset (&so->read_buf);
76 event_timeout_clear (&so->et);
77 if (filename)
79 switch (so->flags)
81 case STATUS_OUTPUT_WRITE:
82 so->fd = platform_open (filename,
83 O_CREAT | O_TRUNC | O_WRONLY,
84 S_IRUSR | S_IWUSR);
85 break;
86 case STATUS_OUTPUT_READ:
87 so->fd = platform_open (filename,
88 O_RDONLY,
89 S_IRUSR | S_IWUSR);
90 break;
91 case STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE:
92 so->fd = platform_open (filename,
93 O_CREAT | O_RDWR,
94 S_IRUSR | S_IWUSR);
95 break;
96 default:
97 ASSERT (0);
99 if (so->fd >= 0)
101 so->filename = string_alloc (filename, NULL);
102 set_cloexec (so->fd);
104 /* allocate read buffer */
105 if (so->flags & STATUS_OUTPUT_READ)
106 so->read_buf = alloc_buf (512);
108 else
110 msg (M_WARN, "Note: cannot open %s for %s", filename, print_status_mode (so->flags));
111 so->errors = true;
114 else
115 so->flags = STATUS_OUTPUT_WRITE;
117 if ((so->flags & STATUS_OUTPUT_WRITE) && refresh_freq > 0)
119 event_timeout_init (&so->et, refresh_freq, 0);
122 return so;
125 bool
126 status_trigger (struct status_output *so)
128 if (so)
130 struct timeval null;
131 CLEAR (null);
132 return event_timeout_trigger (&so->et, &null, ETT_DEFAULT);
134 else
135 return false;
138 bool
139 status_trigger_tv (struct status_output *so, struct timeval *tv)
141 if (so)
142 return event_timeout_trigger (&so->et, tv, ETT_DEFAULT);
143 else
144 return false;
147 void
148 status_reset (struct status_output *so)
150 if (so && so->fd >= 0)
151 lseek (so->fd, (off_t)0, SEEK_SET);
154 void
155 status_flush (struct status_output *so)
157 if (so && so->fd >= 0 && (so->flags & STATUS_OUTPUT_WRITE))
159 #if defined(HAVE_FTRUNCATE)
161 const off_t off = lseek (so->fd, (off_t)0, SEEK_CUR);
162 if (ftruncate (so->fd, off) != 0) {
163 msg (M_WARN, "Failed to truncate status file: %s", strerror(errno));
166 #elif defined(HAVE_CHSIZE)
168 const long off = (long) lseek (so->fd, (off_t)0, SEEK_CUR);
169 chsize (so->fd, off);
171 #else
172 #warning both ftruncate and chsize functions appear to be missing from this OS
173 #endif
175 /* clear read buffer */
176 if (buf_defined (&so->read_buf))
178 ASSERT (buf_init (&so->read_buf, 0));
183 /* return false if error occurred */
184 bool
185 status_close (struct status_output *so)
187 bool ret = true;
188 if (so)
190 if (so->errors)
191 ret = false;
192 if (so->fd >= 0)
194 if (close (so->fd) < 0)
195 ret = false;
197 if (so->filename)
198 free (so->filename);
199 if (buf_defined (&so->read_buf))
200 free_buf (&so->read_buf);
201 free (so);
203 else
204 ret = false;
205 return ret;
208 #define STATUS_PRINTF_MAXLEN 512
210 void
211 status_printf (struct status_output *so, const char *format, ...)
213 if (so && (so->flags & STATUS_OUTPUT_WRITE))
215 char buf[STATUS_PRINTF_MAXLEN+2]; /* leave extra bytes for CR, LF */
216 va_list arglist;
217 int stat;
219 va_start (arglist, format);
220 stat = vsnprintf (buf, STATUS_PRINTF_MAXLEN, format, arglist);
221 va_end (arglist);
222 buf[STATUS_PRINTF_MAXLEN - 1] = 0;
224 if (stat < 0 || stat >= STATUS_PRINTF_MAXLEN)
225 so->errors = true;
227 if (so->msglevel >= 0 && !so->errors)
228 msg (so->msglevel, "%s", buf);
230 if (so->fd >= 0 && !so->errors)
232 int len;
233 strcat (buf, "\n");
234 len = strlen (buf);
235 if (len > 0)
237 if (write (so->fd, buf, len) != len)
238 so->errors = true;
242 if (so->vout && !so->errors)
244 chomp (buf);
245 (*so->vout->func) (so->vout->arg, so->vout->flags_default, buf);
250 bool
251 status_read (struct status_output *so, struct buffer *buf)
253 bool ret = false;
255 if (so && so->fd >= 0 && (so->flags & STATUS_OUTPUT_READ))
257 ASSERT (buf_defined (&so->read_buf));
258 ASSERT (buf_defined (buf));
259 while (true)
261 const int c = buf_read_u8 (&so->read_buf);
263 /* read more of file into buffer */
264 if (c == -1)
266 int len;
268 ASSERT (buf_init (&so->read_buf, 0));
269 len = read (so->fd, BPTR (&so->read_buf), BCAP (&so->read_buf));
270 if (len <= 0)
271 break;
273 ASSERT (buf_inc_len (&so->read_buf, len));
274 continue;
277 ret = true;
279 if (c == '\r')
280 continue;
282 if (c == '\n')
283 break;
285 buf_write_u8 (buf, c);
288 buf_null_terminate (buf);
291 return ret;