Update to OpenVPN 2.1rc17
[tomato.git] / release / src / router / openvpn / status.c
blob9834f1e24967fb82cea153fb4f999ef4f7694e3c
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-2009 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 #include "syshead.h"
27 #include "status.h"
28 #include "perf.h"
30 #include "memdbg.h"
33 * printf-style interface for outputting status info
36 static const char *
37 print_status_mode (unsigned int flags)
39 switch (flags)
41 case STATUS_OUTPUT_WRITE:
42 return "WRITE";
43 case STATUS_OUTPUT_READ:
44 return "READ";
45 case STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE:
46 return "READ/WRITE";
47 default:
48 return "UNDEF";
52 struct status_output *
53 status_open (const char *filename,
54 const int refresh_freq,
55 const int msglevel,
56 const struct virtual_output *vout,
57 const unsigned int flags)
59 struct status_output *so = NULL;
60 if (filename || msglevel >= 0 || vout)
62 ALLOC_OBJ_CLEAR (so, struct status_output);
63 so->flags = flags;
64 so->msglevel = msglevel;
65 so->vout = vout;
66 so->fd = -1;
67 buf_reset (&so->read_buf);
68 event_timeout_clear (&so->et);
69 if (filename)
71 switch (so->flags)
73 #ifdef _MSC_VER
74 case STATUS_OUTPUT_WRITE:
75 so->fd = open (filename,
76 O_CREAT | O_TRUNC | O_WRONLY,
77 _S_IREAD | _S_IWRITE);
78 break;
79 case STATUS_OUTPUT_READ:
80 so->fd = open (filename,
81 O_RDONLY,
82 _S_IREAD | _S_IWRITE);
83 break;
84 case STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE:
85 so->fd = open (filename,
86 O_CREAT | O_RDWR,
87 _S_IREAD | _S_IWRITE);
88 break;
89 #else
90 case STATUS_OUTPUT_WRITE:
91 so->fd = open (filename,
92 O_CREAT | O_TRUNC | O_WRONLY,
93 S_IRUSR | S_IWUSR);
94 break;
95 case STATUS_OUTPUT_READ:
96 so->fd = open (filename,
97 O_RDONLY,
98 S_IRUSR | S_IWUSR);
99 break;
100 case STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE:
101 so->fd = open (filename,
102 O_CREAT | O_RDWR,
103 S_IRUSR | S_IWUSR);
104 break;
105 #endif
106 default:
107 ASSERT (0);
109 if (so->fd >= 0)
111 so->filename = string_alloc (filename, NULL);
113 /* allocate read buffer */
114 if (so->flags & STATUS_OUTPUT_READ)
115 so->read_buf = alloc_buf (512);
117 else
119 msg (M_WARN, "Note: cannot open %s for %s", filename, print_status_mode (so->flags));
120 so->errors = true;
123 else
124 so->flags = STATUS_OUTPUT_WRITE;
126 if ((so->flags & STATUS_OUTPUT_WRITE) && refresh_freq > 0)
128 event_timeout_init (&so->et, refresh_freq, 0);
131 return so;
134 bool
135 status_trigger (struct status_output *so)
137 if (so)
139 struct timeval null;
140 CLEAR (null);
141 return event_timeout_trigger (&so->et, &null, ETT_DEFAULT);
143 else
144 return false;
147 bool
148 status_trigger_tv (struct status_output *so, struct timeval *tv)
150 if (so)
151 return event_timeout_trigger (&so->et, tv, ETT_DEFAULT);
152 else
153 return false;
156 void
157 status_reset (struct status_output *so)
159 if (so && so->fd >= 0)
160 lseek (so->fd, (off_t)0, SEEK_SET);
163 void
164 status_flush (struct status_output *so)
166 if (so && so->fd >= 0 && (so->flags & STATUS_OUTPUT_WRITE))
168 #if defined(HAVE_FTRUNCATE)
170 const off_t off = lseek (so->fd, (off_t)0, SEEK_CUR);
171 ftruncate (so->fd, off);
173 #elif defined(HAVE_CHSIZE)
175 const long off = (long) lseek (so->fd, (off_t)0, SEEK_CUR);
176 chsize (so->fd, off);
178 #else
179 #warning both ftruncate and chsize functions appear to be missing from this OS
180 #endif
182 /* clear read buffer */
183 if (buf_defined (&so->read_buf))
185 ASSERT (buf_init (&so->read_buf, 0));
190 /* return false if error occurred */
191 bool
192 status_close (struct status_output *so)
194 bool ret = true;
195 if (so)
197 if (so->errors)
198 ret = false;
199 if (so->fd >= 0)
201 if (close (so->fd) < 0)
202 ret = false;
204 if (so->filename)
205 free (so->filename);
206 if (buf_defined (&so->read_buf))
207 free_buf (&so->read_buf);
208 free (so);
210 else
211 ret = false;
212 return ret;
215 #define STATUS_PRINTF_MAXLEN 512
217 void
218 status_printf (struct status_output *so, const char *format, ...)
220 if (so && (so->flags & STATUS_OUTPUT_WRITE))
222 char buf[STATUS_PRINTF_MAXLEN+2]; /* leave extra bytes for CR, LF */
223 va_list arglist;
224 int stat;
226 va_start (arglist, format);
227 stat = vsnprintf (buf, STATUS_PRINTF_MAXLEN, format, arglist);
228 va_end (arglist);
229 buf[STATUS_PRINTF_MAXLEN - 1] = 0;
231 if (stat < 0 || stat >= STATUS_PRINTF_MAXLEN)
232 so->errors = true;
234 if (so->msglevel >= 0 && !so->errors)
235 msg (so->msglevel, "%s", buf);
237 if (so->fd >= 0 && !so->errors)
239 int len;
240 strcat (buf, "\n");
241 len = strlen (buf);
242 if (len > 0)
244 if (write (so->fd, buf, len) != len)
245 so->errors = true;
249 if (so->vout && !so->errors)
251 chomp (buf);
252 (*so->vout->func) (so->vout->arg, so->vout->flags_default, buf);
257 bool
258 status_read (struct status_output *so, struct buffer *buf)
260 bool ret = false;
262 if (so && so->fd >= 0 && (so->flags & STATUS_OUTPUT_READ))
264 ASSERT (buf_defined (&so->read_buf));
265 ASSERT (buf_defined (buf));
266 while (true)
268 const int c = buf_read_u8 (&so->read_buf);
270 /* read more of file into buffer */
271 if (c == -1)
273 int len;
275 ASSERT (buf_init (&so->read_buf, 0));
276 len = read (so->fd, BPTR (&so->read_buf), BCAP (&so->read_buf));
277 if (len <= 0)
278 break;
280 ASSERT (buf_inc_len (&so->read_buf, len));
281 continue;
284 ret = true;
286 if (c == '\r')
287 continue;
289 if (c == '\n')
290 break;
292 buf_write_u8 (buf, c);
295 buf_null_terminate (buf);
298 return ret;