Add OpenVPN 2.1rc12 source (unconfigured)
[tomato.git] / release / src / router / openvpn / manage.c
blob12ed97ec52c7cd7dbde67a3b4ad0473770069aac
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-2008 Telethra, 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 #ifdef ENABLE_MANAGEMENT
29 #include "error.h"
30 #include "fdmisc.h"
31 #include "options.h"
32 #include "sig.h"
33 #include "event.h"
34 #include "otime.h"
35 #include "integer.h"
36 #include "misc.h"
37 #include "ssl.h"
38 #include "manage.h"
40 #include "memdbg.h"
42 #ifdef ENABLE_PKCS11
43 #include "pkcs11.h"
44 #endif
46 #define MANAGEMENT_ECHO_PULL_INFO 0
48 #if MANAGEMENT_ECHO_PULL_INFO
49 #define MANAGEMENT_ECHO_FLAGS LOG_PRINT_INTVAL
50 #else
51 #define MANAGEMENT_ECHO_FLAGS 0
52 #endif
54 /* tag for blank username/password */
55 static const char blank_up[] = "[[BLANK]]";
57 struct management *management; /* GLOBAL */
59 /* static forward declarations */
60 static void man_output_standalone (struct management *man, volatile int *signal_received);
61 static void man_reset_client_socket (struct management *man, const bool exiting);
63 static void
64 man_help ()
66 msg (M_CLIENT, "Management Interface for %s", title_string);
67 msg (M_CLIENT, "Commands:");
68 msg (M_CLIENT, "auth-retry t : Auth failure retry mode (none,interact,nointeract).");
69 msg (M_CLIENT, "bytecount n : Show bytes in/out, update every n secs (0=off).");
70 msg (M_CLIENT, "echo [on|off] [N|all] : Like log, but only show messages in echo buffer.");
71 msg (M_CLIENT, "exit|quit : Close management session.");
72 msg (M_CLIENT, "forget-passwords : Forget passwords entered so far.");
73 msg (M_CLIENT, "help : Print this message.");
74 msg (M_CLIENT, "hold [on|off|release] : Set/show hold flag to on/off state, or");
75 msg (M_CLIENT, " release current hold and start tunnel.");
76 msg (M_CLIENT, "kill cn : Kill the client instance(s) having common name cn.");
77 msg (M_CLIENT, "kill IP:port : Kill the client instance connecting from IP:port.");
78 msg (M_CLIENT, "log [on|off] [N|all] : Turn on/off realtime log display");
79 msg (M_CLIENT, " + show last N lines or 'all' for entire history.");
80 msg (M_CLIENT, "mute [n] : Set log mute level to n, or show level if n is absent.");
81 msg (M_CLIENT, "needok type action : Enter confirmation for NEED-OK request of 'type',");
82 msg (M_CLIENT, " where action = 'ok' or 'cancel'.");
83 msg (M_CLIENT, "needstr type action : Enter confirmation for NEED-STR request of 'type',");
84 msg (M_CLIENT, " where action is reply string.");
85 msg (M_CLIENT, "net : (Windows only) Show network info and routing table.");
86 msg (M_CLIENT, "password type p : Enter password p for a queried OpenVPN password.");
87 #ifdef ENABLE_PKCS11
88 msg (M_CLIENT, "pkcs11-id-count : Get number of available PKCS#11 identities.");
89 msg (M_CLIENT, "pkcs11-id-get index : Get PKCS#11 identity at index.");
90 #endif
91 #ifdef MANAGEMENT_DEF_AUTH
92 msg (M_CLIENT, "client-auth CID KID : Authenticate client-id/key-id CID/KID (MULTILINE)");
93 msg (M_CLIENT, "client-auth-nt CID KID : Authenticate client-id/key-id CID/KID");
94 msg (M_CLIENT, "client-deny CID KID R : Deny auth client-id/key-id CID/KID with reason text R");
95 msg (M_CLIENT, "client-kill CID : Kill client instance CID");
96 #ifdef MANAGEMENT_PF
97 msg (M_CLIENT, "client-pf CID : Define packet filter for client CID (MULTILINE)");
98 #endif
99 #endif
100 msg (M_CLIENT, "signal s : Send signal s to daemon,");
101 msg (M_CLIENT, " s = SIGHUP|SIGTERM|SIGUSR1|SIGUSR2.");
102 msg (M_CLIENT, "state [on|off] [N|all] : Like log, but show state history.");
103 msg (M_CLIENT, "status [n] : Show current daemon status info using format #n.");
104 msg (M_CLIENT, "test n : Produce n lines of output for testing/debugging.");
105 msg (M_CLIENT, "username type u : Enter username u for a queried OpenVPN username.");
106 msg (M_CLIENT, "verb [n] : Set log verbosity level to n, or show if n is absent.");
107 msg (M_CLIENT, "version : Show current version number.");
108 msg (M_CLIENT, "END");
111 static const char *
112 man_state_name (const int state)
114 switch (state)
116 case OPENVPN_STATE_INITIAL:
117 return "INITIAL";
118 case OPENVPN_STATE_CONNECTING:
119 return "CONNECTING";
120 case OPENVPN_STATE_WAIT:
121 return "WAIT";
122 case OPENVPN_STATE_AUTH:
123 return "AUTH";
124 case OPENVPN_STATE_GET_CONFIG:
125 return "GET_CONFIG";
126 case OPENVPN_STATE_ASSIGN_IP:
127 return "ASSIGN_IP";
128 case OPENVPN_STATE_ADD_ROUTES:
129 return "ADD_ROUTES";
130 case OPENVPN_STATE_CONNECTED:
131 return "CONNECTED";
132 case OPENVPN_STATE_RECONNECTING:
133 return "RECONNECTING";
134 case OPENVPN_STATE_EXITING:
135 return "EXITING";
136 case OPENVPN_STATE_RESOLVE:
137 return "RESOLVE";
138 case OPENVPN_STATE_TCP_CONNECT:
139 return "TCP_CONNECT";
140 default:
141 return "?";
145 static void
146 man_welcome (struct management *man)
148 msg (M_CLIENT, ">INFO:OpenVPN Management Interface Version %d -- type 'help' for more info",
149 MANAGEMENT_VERSION);
150 if (man->persist.special_state_msg)
151 msg (M_CLIENT, "%s", man->persist.special_state_msg);
154 static inline bool
155 man_password_needed (struct management *man)
157 return man->settings.up.defined && !man->connection.password_verified;
160 static void
161 man_check_password (struct management *man, const char *line)
163 if (man_password_needed (man))
165 if (streq (line, man->settings.up.password))
167 man->connection.password_verified = true;
168 msg (M_CLIENT, "SUCCESS: password is correct");
169 man_welcome (man);
171 else
173 man->connection.password_verified = false;
174 msg (M_CLIENT, "ERROR: bad password");
175 if (++man->connection.password_tries >= MANAGEMENT_N_PASSWORD_RETRIES)
177 msg (M_WARN, "MAN: client connection rejected after %d failed password attempts",
178 MANAGEMENT_N_PASSWORD_RETRIES);
179 man->connection.halt = true;
185 static void
186 man_update_io_state (struct management *man)
188 if (socket_defined (man->connection.sd_cli))
190 if (buffer_list_defined (man->connection.out))
192 man->connection.state = MS_CC_WAIT_WRITE;
194 else
196 man->connection.state = MS_CC_WAIT_READ;
201 static void
202 man_output_list_push (struct management *man, const char *str)
204 if (management_connected (man))
206 if (str)
207 buffer_list_push (man->connection.out, (const unsigned char *) str);
208 man_update_io_state (man);
209 if (!man->persist.standalone_disabled)
211 volatile int signal_received = 0;
212 man_output_standalone (man, &signal_received);
217 static void
218 man_prompt (struct management *man)
220 if (man_password_needed (man))
221 man_output_list_push (man, "ENTER PASSWORD:");
222 #if 0 /* should we use prompt? */
223 else
224 man_output_list_push (man, PACKAGE_NAME ">");
225 #endif
228 static void
229 man_close_socket (struct management *man, const socket_descriptor_t sd)
231 #ifndef WIN32
233 * Windows doesn't need this because the ne32 event is permanently
234 * enabled at struct management scope.
236 if (man->persist.callback.delete_event)
237 (*man->persist.callback.delete_event) (man->persist.callback.arg, sd);
238 #endif
239 openvpn_close_socket (sd);
242 static void
243 virtual_output_callback_func (void *arg, const unsigned int flags, const char *str)
245 static int recursive_level = 0; /* GLOBAL */
247 if (!recursive_level) /* don't allow recursion */
249 struct gc_arena gc = gc_new ();
250 struct management *man = (struct management *) arg;
251 struct log_entry e;
252 const char *out = NULL;
254 ++recursive_level;
256 CLEAR (e);
257 update_time ();
258 e.timestamp = now;
259 e.u.msg_flags = flags;
260 e.string = str;
262 if (flags & M_FATAL)
263 man->persist.standalone_disabled = false;
265 if (flags != M_CLIENT)
266 log_history_add (man->persist.log, &e);
268 if (!man_password_needed (man))
270 if (flags == M_CLIENT)
271 out = log_entry_print (&e, LOG_PRINT_CRLF, &gc);
272 else if (man->connection.log_realtime)
273 out = log_entry_print (&e, LOG_PRINT_INT_DATE
274 | LOG_PRINT_MSG_FLAGS
275 | LOG_PRINT_LOG_PREFIX
276 | LOG_PRINT_CRLF, &gc);
277 if (out)
278 man_output_list_push (man, out);
279 if (flags & M_FATAL)
281 out = log_entry_print (&e, LOG_FATAL_NOTIFY|LOG_PRINT_CRLF, &gc);
282 if (out)
284 man_output_list_push (man, out);
285 man_reset_client_socket (man, true);
290 --recursive_level;
291 gc_free (&gc);
296 * Given a signal, return the signal with possible remapping applied,
297 * or -1 if the signal should be ignored.
299 static int
300 man_mod_signal (const struct management *man, const int signum)
302 const unsigned int flags = man->settings.mansig;
303 int s = signum;
304 if (s == SIGUSR1)
306 if (flags & MANSIG_MAP_USR1_TO_HUP)
307 s = SIGHUP;
308 if (flags & MANSIG_MAP_USR1_TO_TERM)
309 s = SIGTERM;
311 if (flags & MANSIG_IGNORE_USR1_HUP)
313 if (s == SIGHUP || s == SIGUSR1)
314 s = -1;
316 return s;
319 static void
320 man_signal (struct management *man, const char *name)
322 const int sig = parse_signal (name);
323 if (sig >= 0)
325 const int sig_mod = man_mod_signal (man, sig);
326 if (sig_mod >= 0)
328 throw_signal (sig_mod);
329 msg (M_CLIENT, "SUCCESS: signal %s thrown", signal_name (sig_mod, true));
331 else
333 if (man->persist.special_state_msg)
334 msg (M_CLIENT, "%s", man->persist.special_state_msg);
335 else
336 msg (M_CLIENT, "ERROR: signal '%s' is currently ignored", name);
339 else
341 msg (M_CLIENT, "ERROR: signal '%s' is not a known signal type", name);
345 static void
346 man_status (struct management *man, const int version, struct status_output *so)
348 if (man->persist.callback.status)
350 (*man->persist.callback.status) (man->persist.callback.arg, version, so);
352 else
354 msg (M_CLIENT, "ERROR: The 'status' command is not supported by the current daemon mode");
358 static void
359 man_bytecount (struct management *man, const int update_seconds)
361 man->connection.bytecount_update_seconds = update_seconds;
364 void
365 man_bytecount_output (struct management *man)
367 char in[32];
368 char out[32];
369 /* do in a roundabout way to work around possible mingw or mingw-glibc bug */
370 openvpn_snprintf (in, sizeof (in), counter_format, man->persist.bytes_in);
371 openvpn_snprintf (out, sizeof (out), counter_format, man->persist.bytes_out);
372 msg (M_CLIENT, ">BYTECOUNT:%s,%s", in, out);
373 man->connection.bytecount_last_update = now;
376 static void
377 man_kill (struct management *man, const char *victim)
379 struct gc_arena gc = gc_new ();
381 if (man->persist.callback.kill_by_cn && man->persist.callback.kill_by_addr)
383 struct buffer buf;
384 char p1[128];
385 char p2[128];
386 int n_killed;
388 buf_set_read (&buf, (uint8_t*) victim, strlen (victim) + 1);
389 buf_parse (&buf, ':', p1, sizeof (p1));
390 buf_parse (&buf, ':', p2, sizeof (p2));
392 if (strlen (p1) && strlen (p2))
394 /* IP:port specified */
395 bool status;
396 const in_addr_t addr = getaddr (GETADDR_HOST_ORDER|GETADDR_MSG_VIRT_OUT, p1, 0, &status, NULL);
397 if (status)
399 const int port = atoi (p2);
400 if (port > 0 && port < 65536)
402 n_killed = (*man->persist.callback.kill_by_addr) (man->persist.callback.arg, addr, port);
403 if (n_killed > 0)
405 msg (M_CLIENT, "SUCCESS: %d client(s) at address %s:%d killed",
406 n_killed,
407 print_in_addr_t (addr, 0, &gc),
408 port);
410 else
412 msg (M_CLIENT, "ERROR: client at address %s:%d not found",
413 print_in_addr_t (addr, 0, &gc),
414 port);
417 else
419 msg (M_CLIENT, "ERROR: port number is out of range: %s", p2);
422 else
424 msg (M_CLIENT, "ERROR: error parsing IP address: %s", p1);
427 else if (strlen (p1))
429 /* common name specified */
430 n_killed = (*man->persist.callback.kill_by_cn) (man->persist.callback.arg, p1);
431 if (n_killed > 0)
433 msg (M_CLIENT, "SUCCESS: common name '%s' found, %d client(s) killed", p1, n_killed);
435 else
437 msg (M_CLIENT, "ERROR: common name '%s' not found", p1);
440 else
442 msg (M_CLIENT, "ERROR: kill parse");
445 else
447 msg (M_CLIENT, "ERROR: The 'kill' command is not supported by the current daemon mode");
450 gc_free (&gc);
454 * General-purpose history command handler
455 * for the log and echo commands.
457 static void
458 man_history (struct management *man,
459 const char *parm,
460 const char *type,
461 struct log_history *log,
462 bool *realtime,
463 const unsigned int lep_flags)
465 struct gc_arena gc = gc_new ();
466 int n = 0;
468 if (streq (parm, "on"))
470 *realtime = true;
471 msg (M_CLIENT, "SUCCESS: real-time %s notification set to ON", type);
473 else if (streq (parm, "off"))
475 *realtime = false;
476 msg (M_CLIENT, "SUCCESS: real-time %s notification set to OFF", type);
478 else if (streq (parm, "all") || (n = atoi (parm)) > 0)
480 const int size = log_history_size (log);
481 const int start = (n ? n : size) - 1;
482 int i;
484 for (i = start; i >= 0; --i)
486 const struct log_entry *e = log_history_ref (log, i);
487 if (e)
489 const char *out = log_entry_print (e, lep_flags, &gc);
490 virtual_output_callback_func (man, M_CLIENT, out);
493 msg (M_CLIENT, "END");
495 else
497 msg (M_CLIENT, "ERROR: %s parameter must be 'on' or 'off' or some number n or 'all'", type);
500 gc_free (&gc);
503 static void
504 man_log (struct management *man, const char *parm)
506 man_history (man,
507 parm,
508 "log",
509 man->persist.log,
510 &man->connection.log_realtime,
511 LOG_PRINT_INT_DATE|LOG_PRINT_MSG_FLAGS);
514 static void
515 man_echo (struct management *man, const char *parm)
517 man_history (man,
518 parm,
519 "echo",
520 man->persist.echo,
521 &man->connection.echo_realtime,
522 LOG_PRINT_INT_DATE|MANAGEMENT_ECHO_FLAGS);
525 static void
526 man_state (struct management *man, const char *parm)
528 man_history (man,
529 parm,
530 "state",
531 man->persist.state,
532 &man->connection.state_realtime,
533 LOG_PRINT_INT_DATE|LOG_PRINT_STATE|
534 LOG_PRINT_LOCAL_IP|LOG_PRINT_REMOTE_IP);
537 static void
538 man_up_finalize (struct management *man)
540 switch (man->connection.up_query_mode)
542 case UP_QUERY_DISABLED:
543 man->connection.up_query.defined = false;
544 break;
545 case UP_QUERY_USER_PASS:
546 if (strlen (man->connection.up_query.username) && strlen (man->connection.up_query.password))
547 man->connection.up_query.defined = true;
548 break;
549 case UP_QUERY_PASS:
550 if (strlen (man->connection.up_query.password))
551 man->connection.up_query.defined = true;
552 break;
553 case UP_QUERY_NEED_OK:
554 if (strlen (man->connection.up_query.password))
555 man->connection.up_query.defined = true;
556 break;
557 case UP_QUERY_NEED_STR:
558 if (strlen (man->connection.up_query.password))
559 man->connection.up_query.defined = true;
560 break;
561 default:
562 ASSERT (0);
566 static void
567 man_query_user_pass (struct management *man,
568 const char *type,
569 const char *string,
570 const bool needed,
571 const char *prompt,
572 char *dest,
573 int len)
575 if (needed)
577 ASSERT (man->connection.up_query_type);
578 if (streq (man->connection.up_query_type, type))
580 strncpynt (dest, string, len);
581 man_up_finalize (man);
582 msg (M_CLIENT, "SUCCESS: '%s' %s entered, but not yet verified",
583 type,
584 prompt);
586 else
587 msg (M_CLIENT, "ERROR: %s of type '%s' entered, but we need one of type '%s'",
588 prompt,
589 type,
590 man->connection.up_query_type);
592 else
594 msg (M_CLIENT, "ERROR: no %s is currently needed at this time", prompt);
598 static void
599 man_query_username (struct management *man, const char *type, const char *string)
601 const bool needed = (man->connection.up_query_mode == UP_QUERY_USER_PASS && man->connection.up_query_type);
602 man_query_user_pass (man, type, string, needed, "username", man->connection.up_query.username, USER_PASS_LEN);
605 static void
606 man_query_password (struct management *man, const char *type, const char *string)
608 const bool needed = ((man->connection.up_query_mode == UP_QUERY_USER_PASS
609 || man->connection.up_query_mode == UP_QUERY_PASS)
610 && man->connection.up_query_type);
611 if (!string[0]) /* allow blank passwords to be passed through using the blank_up tag */
612 string = blank_up;
613 man_query_user_pass (man, type, string, needed, "password", man->connection.up_query.password, USER_PASS_LEN);
616 static void
617 man_query_need_ok (struct management *man, const char *type, const char *action)
619 const bool needed = ((man->connection.up_query_mode == UP_QUERY_NEED_OK) && man->connection.up_query_type);
620 man_query_user_pass (man, type, action, needed, "needok-confirmation", man->connection.up_query.password, USER_PASS_LEN);
623 static void
624 man_query_need_str (struct management *man, const char *type, const char *action)
626 const bool needed = ((man->connection.up_query_mode == UP_QUERY_NEED_STR) && man->connection.up_query_type);
627 man_query_user_pass (man, type, action, needed, "needstr-string", man->connection.up_query.password, USER_PASS_LEN);
630 static void
631 man_forget_passwords (struct management *man)
633 #if defined(USE_CRYPTO) && defined(USE_SSL)
634 ssl_purge_auth ();
635 msg (M_CLIENT, "SUCCESS: Passwords were forgotten");
636 #endif
639 static void
640 man_net (struct management *man)
642 if (man->persist.callback.show_net)
644 (*man->persist.callback.show_net) (man->persist.callback.arg, M_CLIENT);
646 else
648 msg (M_CLIENT, "ERROR: The 'net' command is not supported by the current daemon mode");
652 #ifdef ENABLE_PKCS11
654 static void
655 man_pkcs11_id_count (struct management *man)
657 msg (M_CLIENT, ">PKCS11ID-COUNT:%d", pkcs11_management_id_count ());
660 static void
661 man_pkcs11_id_get (struct management *man, const int index)
663 char *id = NULL;
664 char *base64 = NULL;
666 if (pkcs11_management_id_get (index, &id, &base64))
667 msg (M_CLIENT, ">PKCS11ID-ENTRY:'%d', ID:'%s', BLOB:'%s'", index, id, base64);
668 else
669 msg (M_CLIENT, ">PKCS11ID-ENTRY:'%d'", index);
671 if (id != NULL)
672 free (id);
673 if (base64 != NULL)
674 free (base64);
677 #endif
679 static void
680 man_hold (struct management *man, const char *cmd)
682 if (cmd)
684 if (streq (cmd, "on"))
686 man->settings.flags |= MF_HOLD;
687 msg (M_CLIENT, "SUCCESS: hold flag set to ON");
689 else if (streq (cmd, "off"))
691 man->settings.flags &= ~MF_HOLD;
692 msg (M_CLIENT, "SUCCESS: hold flag set to OFF");
694 else if (streq (cmd, "release"))
696 man->persist.hold_release = true;
697 msg (M_CLIENT, "SUCCESS: hold release succeeded");
699 else
701 msg (M_CLIENT, "ERROR: bad hold command parameter");
704 else
705 msg (M_CLIENT, "SUCCESS: hold=%d", BOOL_CAST(man->settings.flags & MF_HOLD));
708 #ifdef MANAGEMENT_DEF_AUTH
710 static bool
711 parse_cid (const char *str, unsigned long *cid)
713 if (sscanf (str, "%lu", cid) == 1)
714 return true;
715 else
717 msg (M_CLIENT, "ERROR: cannot parse CID");
718 return false;
722 static bool
723 parse_kid (const char *str, unsigned int *kid)
725 if (sscanf (str, "%u", kid) == 1)
726 return true;
727 else
729 msg (M_CLIENT, "ERROR: cannot parse KID");
730 return false;
734 static void
735 in_extra_reset (struct man_connection *mc, const bool new)
737 if (mc)
739 if (!new)
741 mc->in_extra_cmd = IEC_UNDEF;
742 mc->in_extra_cid = 0;
743 mc->in_extra_kid = 0;
745 if (mc->in_extra)
747 buffer_list_free (mc->in_extra);
748 mc->in_extra = NULL;
750 if (new)
751 mc->in_extra = buffer_list_new (0);
755 static void
756 in_extra_dispatch (struct management *man)
758 switch (man->connection.in_extra_cmd)
760 case IEC_CLIENT_AUTH:
761 if (man->persist.callback.client_auth)
763 const bool status = (*man->persist.callback.client_auth)
764 (man->persist.callback.arg,
765 man->connection.in_extra_cid,
766 man->connection.in_extra_kid,
767 true,
768 NULL,
769 man->connection.in_extra);
770 man->connection.in_extra = NULL;
771 if (status)
773 msg (M_CLIENT, "SUCCESS: client-auth command succeeded");
775 else
777 msg (M_CLIENT, "ERROR: client-auth command failed");
780 else
782 msg (M_CLIENT, "ERROR: The client-auth command is not supported by the current daemon mode");
784 break;
785 #ifdef MANAGEMENT_PF
786 case IEC_CLIENT_PF:
787 if (man->persist.callback.client_pf)
789 const bool status = (*man->persist.callback.client_pf)
790 (man->persist.callback.arg,
791 man->connection.in_extra_cid,
792 man->connection.in_extra);
793 man->connection.in_extra = NULL;
794 if (status)
796 msg (M_CLIENT, "SUCCESS: client-pf command succeeded");
798 else
800 msg (M_CLIENT, "ERROR: client-pf command failed");
803 else
805 msg (M_CLIENT, "ERROR: The client-pf command is not supported by the current daemon mode");
807 break;
808 #endif
810 in_extra_reset (&man->connection, false);
813 static void
814 man_client_auth (struct management *man, const char *cid_str, const char *kid_str, const bool extra)
816 struct man_connection *mc = &man->connection;
817 mc->in_extra_cid = 0;
818 mc->in_extra_kid = 0;
819 if (parse_cid (cid_str, &mc->in_extra_cid)
820 && parse_kid (kid_str, &mc->in_extra_kid))
822 mc->in_extra_cmd = IEC_CLIENT_AUTH;
823 in_extra_reset (mc, true);
824 if (!extra)
825 in_extra_dispatch (man);
829 static void
830 man_client_deny (struct management *man, const char *cid_str, const char *kid_str, const char *reason)
832 unsigned long cid = 0;
833 unsigned int kid = 0;
834 if (parse_cid (cid_str, &cid) && parse_kid (kid_str, &kid))
836 if (man->persist.callback.client_auth)
838 const bool status = (*man->persist.callback.client_auth)
839 (man->persist.callback.arg,
840 cid,
841 kid,
842 false,
843 reason,
844 NULL);
845 if (status)
847 msg (M_CLIENT, "SUCCESS: client-deny command succeeded");
849 else
851 msg (M_CLIENT, "ERROR: client-deny command failed");
854 else
856 msg (M_CLIENT, "ERROR: The client-deny command is not supported by the current daemon mode");
861 static void
862 man_client_kill (struct management *man, const char *cid_str)
864 unsigned long cid = 0;
865 if (parse_cid (cid_str, &cid))
867 if (man->persist.callback.kill_by_cid)
869 const bool status = (*man->persist.callback.kill_by_cid) (man->persist.callback.arg, cid);
870 if (status)
872 msg (M_CLIENT, "SUCCESS: client-kill command succeeded");
874 else
876 msg (M_CLIENT, "ERROR: client-kill command failed");
879 else
881 msg (M_CLIENT, "ERROR: The client-kill command is not supported by the current daemon mode");
886 #ifdef MANAGEMENT_PF
888 static void
889 man_client_pf (struct management *man, const char *cid_str)
891 struct man_connection *mc = &man->connection;
892 mc->in_extra_cid = 0;
893 mc->in_extra_kid = 0;
894 if (parse_cid (cid_str, &mc->in_extra_cid))
896 mc->in_extra_cmd = IEC_CLIENT_PF;
897 in_extra_reset (mc, true);
901 #endif
902 #endif
904 #define MN_AT_LEAST (1<<0)
906 static bool
907 man_need (struct management *man, const char **p, const int n, unsigned int flags)
909 int i;
910 ASSERT (p[0]);
911 for (i = 1; i <= n; ++i)
913 if (!p[i])
915 msg (M_CLIENT, "ERROR: the '%s' command requires %s%d parameter%s",
916 p[0],
917 (flags & MN_AT_LEAST) ? "at least " : "",
919 n > 1 ? "s" : "");
920 return false;
923 return true;
926 static void
927 man_dispatch_command (struct management *man, struct status_output *so, const char **p, const int nparms)
929 struct gc_arena gc = gc_new ();
931 ASSERT (p[0]);
932 if (streq (p[0], "exit") || streq (p[0], "quit"))
934 man->connection.halt = true;
935 goto done;
937 else if (streq (p[0], "help"))
939 man_help ();
941 else if (streq (p[0], "version"))
943 msg (M_CLIENT, "OpenVPN Version: %s", title_string);
944 msg (M_CLIENT, "Management Version: %d", MANAGEMENT_VERSION);
945 msg (M_CLIENT, "END");
947 else if (streq (p[0], "signal"))
949 if (man_need (man, p, 1, 0))
950 man_signal (man, p[1]);
952 else if (streq (p[0], "status"))
954 int version = 0;
955 if (p[1])
956 version = atoi (p[1]);
957 man_status (man, version, so);
959 else if (streq (p[0], "kill"))
961 if (man_need (man, p, 1, 0))
962 man_kill (man, p[1]);
964 else if (streq (p[0], "verb"))
966 if (p[1])
968 const int level = atoi(p[1]);
969 if (set_debug_level (level, 0))
970 msg (M_CLIENT, "SUCCESS: verb level changed");
971 else
972 msg (M_CLIENT, "ERROR: verb level is out of range");
974 else
975 msg (M_CLIENT, "SUCCESS: verb=%d", get_debug_level ());
977 else if (streq (p[0], "mute"))
979 if (p[1])
981 const int level = atoi(p[1]);
982 if (set_mute_cutoff (level))
983 msg (M_CLIENT, "SUCCESS: mute level changed");
984 else
985 msg (M_CLIENT, "ERROR: mute level is out of range");
987 else
988 msg (M_CLIENT, "SUCCESS: mute=%d", get_mute_cutoff ());
990 else if (streq (p[0], "auth-retry"))
992 #if P2MP
993 if (p[1])
995 if (auth_retry_set (M_CLIENT, p[1]))
996 msg (M_CLIENT, "SUCCESS: auth-retry parameter changed");
997 else
998 msg (M_CLIENT, "ERROR: bad auth-retry parameter");
1000 else
1001 msg (M_CLIENT, "SUCCESS: auth-retry=%s", auth_retry_print ());
1002 #else
1003 msg (M_CLIENT, "ERROR: auth-retry feature is unavailable");
1004 #endif
1006 else if (streq (p[0], "state"))
1008 if (!p[1])
1010 man_state (man, "1");
1012 else
1014 if (p[1])
1015 man_state (man, p[1]);
1016 if (p[2])
1017 man_state (man, p[2]);
1020 else if (streq (p[0], "log"))
1022 if (man_need (man, p, 1, MN_AT_LEAST))
1024 if (p[1])
1025 man_log (man, p[1]);
1026 if (p[2])
1027 man_log (man, p[2]);
1030 else if (streq (p[0], "echo"))
1032 if (man_need (man, p, 1, MN_AT_LEAST))
1034 if (p[1])
1035 man_echo (man, p[1]);
1036 if (p[2])
1037 man_echo (man, p[2]);
1040 else if (streq (p[0], "username"))
1042 if (man_need (man, p, 2, 0))
1043 man_query_username (man, p[1], p[2]);
1045 else if (streq (p[0], "password"))
1047 if (man_need (man, p, 2, 0))
1048 man_query_password (man, p[1], p[2]);
1050 else if (streq (p[0], "forget-passwords"))
1052 man_forget_passwords (man);
1054 else if (streq (p[0], "needok"))
1056 if (man_need (man, p, 2, 0))
1057 man_query_need_ok (man, p[1], p[2]);
1059 else if (streq (p[0], "needstr"))
1061 if (man_need (man, p, 2, 0))
1062 man_query_need_str (man, p[1], p[2]);
1064 else if (streq (p[0], "net"))
1066 man_net (man);
1068 else if (streq (p[0], "hold"))
1070 man_hold (man, p[1]);
1072 else if (streq (p[0], "bytecount"))
1074 if (man_need (man, p, 1, 0))
1075 man_bytecount (man, atoi(p[1]));
1077 #ifdef MANAGEMENT_DEF_AUTH
1078 else if (streq (p[0], "client-kill"))
1080 if (man_need (man, p, 1, 0))
1081 man_client_kill (man, p[1]);
1083 else if (streq (p[0], "client-deny"))
1085 if (man_need (man, p, 3, 0))
1086 man_client_deny (man, p[1], p[2], p[3]);
1088 else if (streq (p[0], "client-auth-nt"))
1090 if (man_need (man, p, 2, 0))
1091 man_client_auth (man, p[1], p[2], false);
1093 else if (streq (p[0], "client-auth"))
1095 if (man_need (man, p, 2, 0))
1096 man_client_auth (man, p[1], p[2], true);
1098 #ifdef MANAGEMENT_PF
1099 else if (streq (p[0], "client-pf"))
1101 if (man_need (man, p, 1, 0))
1102 man_client_pf (man, p[1]);
1104 #endif
1105 #endif
1106 #ifdef ENABLE_PKCS11
1107 else if (streq (p[0], "pkcs11-id-count"))
1109 man_pkcs11_id_count (man);
1111 else if (streq (p[0], "pkcs11-id-get"))
1113 if (man_need (man, p, 1, 0))
1114 man_pkcs11_id_get (man, atoi(p[1]));
1116 #endif
1117 #if 1
1118 else if (streq (p[0], "test"))
1120 if (man_need (man, p, 1, 0))
1122 int i;
1123 const int n = atoi (p[1]);
1124 for (i = 0; i < n; ++i)
1126 msg (M_CLIENT, "[%d] The purpose of this command is to generate large amounts of output.", i);
1130 #endif
1131 else
1133 msg (M_CLIENT, "ERROR: unknown command, enter 'help' for more options");
1136 done:
1137 gc_free (&gc);
1140 #ifdef WIN32
1142 static void
1143 man_start_ne32 (struct management *man)
1145 switch (man->connection.state)
1147 case MS_LISTEN:
1148 net_event_win32_start (&man->connection.ne32, FD_ACCEPT, man->connection.sd_top);
1149 break;
1150 case MS_CC_WAIT_READ:
1151 case MS_CC_WAIT_WRITE:
1152 net_event_win32_start (&man->connection.ne32, FD_READ|FD_WRITE|FD_CLOSE, man->connection.sd_cli);
1153 break;
1154 default:
1155 ASSERT (0);
1159 static void
1160 man_stop_ne32 (struct management *man)
1162 net_event_win32_stop (&man->connection.ne32);
1165 #endif
1167 static void
1168 man_record_peer_info (struct management *man)
1170 struct gc_arena gc = gc_new ();
1171 if (man->settings.write_peer_info_file)
1173 bool success = false;
1174 #ifdef HAVE_GETSOCKNAME
1175 if (socket_defined (man->connection.sd_cli))
1177 struct sockaddr_in addr;
1178 socklen_t addrlen = sizeof (addr);
1179 int status;
1181 CLEAR (addr);
1182 status = getsockname (man->connection.sd_cli, (struct sockaddr *)&addr, &addrlen);
1183 if (!status && addrlen == sizeof (addr))
1185 const in_addr_t a = ntohl (addr.sin_addr.s_addr);
1186 const int p = ntohs (addr.sin_port);
1187 FILE *fp = fopen (man->settings.write_peer_info_file, "w");
1188 if (fp)
1190 fprintf (fp, "%s\n%d\n", print_in_addr_t (a, 0, &gc), p);
1191 if (!fclose (fp))
1192 success = true;
1196 #endif
1197 if (!success)
1199 msg (D_MANAGEMENT, "MANAGEMENT: failed to write peer info to file %s",
1200 man->settings.write_peer_info_file);
1201 throw_signal_soft (SIGTERM, "management-connect-failed");
1204 gc_free (&gc);
1207 static void
1208 man_connection_settings_reset (struct management *man)
1210 man->connection.state_realtime = false;
1211 man->connection.log_realtime = false;
1212 man->connection.echo_realtime = false;
1213 man->connection.bytecount_update_seconds = 0;
1214 man->connection.password_verified = false;
1215 man->connection.password_tries = 0;
1216 man->connection.halt = false;
1217 man->connection.state = MS_CC_WAIT_WRITE;
1220 static void
1221 man_new_connection_post (struct management *man, const char *description)
1223 struct gc_arena gc = gc_new ();
1225 set_nonblock (man->connection.sd_cli);
1226 set_cloexec (man->connection.sd_cli);
1228 man_connection_settings_reset (man);
1230 #ifdef WIN32
1231 man_start_ne32 (man);
1232 #endif
1234 msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
1235 description,
1236 print_sockaddr (&man->settings.local, &gc));
1238 buffer_list_reset (man->connection.out);
1240 if (!man_password_needed (man))
1241 man_welcome (man);
1242 man_prompt (man);
1243 man_update_io_state (man);
1245 gc_free (&gc);
1248 static void
1249 man_accept (struct management *man)
1251 struct link_socket_actual act;
1254 * Accept the TCP client.
1256 man->connection.sd_cli = socket_do_accept (man->connection.sd_top, &act, false);
1257 if (socket_defined (man->connection.sd_cli))
1259 man->connection.remote = act.dest;
1261 if (socket_defined (man->connection.sd_top))
1263 #ifdef WIN32
1264 man_stop_ne32 (man);
1265 #endif
1268 man_new_connection_post (man, "Client connected from");
1272 static void
1273 man_listen (struct management *man)
1275 struct gc_arena gc = gc_new ();
1278 * Initialize state
1280 man->connection.state = MS_LISTEN;
1281 man->connection.sd_cli = SOCKET_UNDEFINED;
1284 * Initialize listening socket
1286 if (man->connection.sd_top == SOCKET_UNDEFINED)
1288 man->connection.sd_top = create_socket_tcp ();
1291 * Bind socket
1293 socket_bind (man->connection.sd_top, &man->settings.local, "MANAGEMENT");
1296 * Listen for connection
1298 if (listen (man->connection.sd_top, 1))
1299 msg (M_SOCKERR, "MANAGEMENT: listen() failed");
1302 * Set misc socket properties
1304 set_nonblock (man->connection.sd_top);
1305 set_cloexec (man->connection.sd_top);
1307 msg (D_MANAGEMENT, "MANAGEMENT: TCP Socket listening on %s",
1308 print_sockaddr (&man->settings.local, &gc));
1311 #ifdef WIN32
1312 man_start_ne32 (man);
1313 #endif
1315 gc_free (&gc);
1318 static void
1319 man_connect (struct management *man)
1321 struct gc_arena gc = gc_new ();
1322 int status;
1323 int signal_received = 0;
1326 * Initialize state
1328 man->connection.state = MS_INITIAL;
1329 man->connection.sd_top = SOCKET_UNDEFINED;
1331 man->connection.sd_cli = create_socket_tcp ();
1333 status = openvpn_connect (man->connection.sd_cli,
1334 &man->settings.local,
1336 &signal_received);
1338 if (signal_received)
1340 throw_signal (signal_received);
1341 goto done;
1344 if (status)
1346 msg (D_LINK_ERRORS,
1347 "MANAGEMENT: connect to %s failed: %s",
1348 print_sockaddr (&man->settings.local, &gc),
1349 strerror_ts (status, &gc));
1350 throw_signal_soft (SIGTERM, "management-connect-failed");
1351 goto done;
1354 man_record_peer_info (man);
1355 man_new_connection_post (man, "Connected to management server at");
1357 done:
1358 gc_free (&gc);
1361 static void
1362 man_reset_client_socket (struct management *man, const bool exiting)
1364 if (socket_defined (man->connection.sd_cli))
1366 msg (D_MANAGEMENT, "MANAGEMENT: Client disconnected");
1367 #ifdef WIN32
1368 man_stop_ne32 (man);
1369 #endif
1370 man_close_socket (man, man->connection.sd_cli);
1371 man->connection.sd_cli = SOCKET_UNDEFINED;
1372 command_line_reset (man->connection.in);
1373 buffer_list_reset (man->connection.out);
1374 #ifdef MANAGEMENT_DEF_AUTH
1375 in_extra_reset (&man->connection, false);
1376 #endif
1378 if (!exiting)
1380 #if defined(USE_CRYPTO) && defined(USE_SSL)
1381 if (man->settings.flags & MF_FORGET_DISCONNECT)
1382 ssl_purge_auth ();
1383 #endif
1384 if (man->settings.flags & MF_SIGNAL) {
1385 int mysig = man_mod_signal (man, SIGUSR1);
1386 if (mysig >= 0)
1388 msg (D_MANAGEMENT, "MANAGEMENT: Triggering management signal");
1389 throw_signal_soft (mysig, "management-disconnect");
1393 if (man->settings.flags & MF_CONNECT_AS_CLIENT)
1395 msg (D_MANAGEMENT, "MANAGEMENT: Triggering management exit");
1396 throw_signal_soft (SIGTERM, "management-exit");
1398 else
1399 man_listen (man);
1403 static void
1404 man_process_command (struct management *man, const char *line)
1406 struct gc_arena gc = gc_new ();
1407 struct status_output *so;
1408 int nparms;
1409 char *parms[MAX_PARMS+1];
1411 CLEAR (parms);
1412 so = status_open (NULL, 0, -1, &man->persist.vout, 0);
1413 #ifdef MANAGEMENT_DEF_AUTH
1414 in_extra_reset (&man->connection, false);
1415 #endif
1417 if (man_password_needed (man))
1419 man_check_password (man, line);
1421 else
1423 nparms = parse_line (line, parms, MAX_PARMS, "TCP", 0, M_CLIENT, &gc);
1424 if (parms[0] && streq (parms[0], "password"))
1425 msg (D_MANAGEMENT_DEBUG, "MANAGEMENT: CMD 'password [...]'");
1426 else
1427 msg (D_MANAGEMENT_DEBUG, "MANAGEMENT: CMD '%s'", line);
1429 #if 0
1430 /* DEBUGGING -- print args */
1432 int i;
1433 for (i = 0; i < nparms; ++i)
1434 msg (M_INFO, "[%d] '%s'", i, parms[i]);
1436 #endif
1438 if (nparms > 0)
1439 man_dispatch_command (man, so, (const char **)parms, nparms);
1442 CLEAR (parms);
1443 status_close (so);
1444 gc_free (&gc);
1447 static bool
1448 man_io_error (struct management *man, const char *prefix)
1450 const int err = openvpn_errno_socket ();
1452 if (!ignore_sys_error (err))
1454 struct gc_arena gc = gc_new ();
1455 msg (D_MANAGEMENT, "MANAGEMENT: TCP %s error: %s",
1456 prefix,
1457 strerror_ts (err, &gc));
1458 gc_free (&gc);
1459 return true;
1461 else
1462 return false;
1465 static int
1466 man_read (struct management *man)
1469 * read command line from socket
1471 unsigned char buf[256];
1472 int len = 0;
1474 len = recv (man->connection.sd_cli, buf, sizeof (buf), MSG_NOSIGNAL);
1475 if (len == 0)
1477 man_reset_client_socket (man, false);
1479 else if (len > 0)
1481 bool processed_command = false;
1483 ASSERT (len <= (int) sizeof (buf));
1484 command_line_add (man->connection.in, buf, len);
1487 * Reset output object
1489 buffer_list_reset (man->connection.out);
1492 * process command line if complete
1495 const unsigned char *line;
1496 while ((line = command_line_get (man->connection.in)))
1498 #ifdef MANAGEMENT_DEF_AUTH
1499 if (man->connection.in_extra)
1501 if (!strcmp ((char *)line, "END"))
1503 in_extra_dispatch (man);
1504 in_extra_reset (&man->connection, false);
1506 else
1508 buffer_list_push (man->connection.in_extra, line);
1511 else
1512 #endif
1513 man_process_command (man, (char *) line);
1514 if (man->connection.halt)
1515 break;
1516 command_line_next (man->connection.in);
1517 processed_command = true;
1522 * Reset output state to MS_CC_WAIT_(READ|WRITE)
1524 if (man->connection.halt)
1526 man_reset_client_socket (man, false);
1527 len = 0;
1529 else
1531 if (processed_command)
1532 man_prompt (man);
1533 man_update_io_state (man);
1536 else /* len < 0 */
1538 if (man_io_error (man, "recv"))
1539 man_reset_client_socket (man, false);
1541 return len;
1544 static int
1545 man_write (struct management *man)
1547 const int max_send = 256;
1548 int sent = 0;
1550 const struct buffer *buf = buffer_list_peek (man->connection.out);
1551 if (buf && BLEN (buf))
1553 const int len = min_int (max_send, BLEN (buf));
1554 sent = send (man->connection.sd_cli, BPTR (buf), len, MSG_NOSIGNAL);
1555 if (sent >= 0)
1557 buffer_list_advance (man->connection.out, sent);
1559 else if (sent < 0)
1561 if (man_io_error (man, "send"))
1562 man_reset_client_socket (man, false);
1567 * Reset output state to MS_CC_WAIT_(READ|WRITE)
1569 man_update_io_state (man);
1571 return sent;
1574 static void
1575 man_connection_clear (struct man_connection *mc)
1577 CLEAR (*mc);
1579 /* set initial state */
1580 mc->state = MS_INITIAL;
1582 /* clear socket descriptors */
1583 mc->sd_top = SOCKET_UNDEFINED;
1584 mc->sd_cli = SOCKET_UNDEFINED;
1587 static void
1588 man_persist_init (struct management *man,
1589 const int log_history_cache,
1590 const int echo_buffer_size,
1591 const int state_buffer_size)
1593 struct man_persist *mp = &man->persist;
1594 if (!mp->defined)
1596 CLEAR (*mp);
1598 /* initialize log history store */
1599 mp->log = log_history_init (log_history_cache);
1602 * Initialize virtual output object, so that functions
1603 * which write to a virtual_output object can be redirected
1604 * here to the management object.
1606 mp->vout.func = virtual_output_callback_func;
1607 mp->vout.arg = man;
1608 mp->vout.flags_default = M_CLIENT;
1609 msg_set_virtual_output (&mp->vout);
1612 * Initialize --echo list
1614 man->persist.echo = log_history_init (echo_buffer_size);
1617 * Initialize --state list
1619 man->persist.state = log_history_init (state_buffer_size);
1621 mp->defined = true;
1625 static void
1626 man_persist_close (struct man_persist *mp)
1628 if (mp->log)
1630 msg_set_virtual_output (NULL);
1631 log_history_close (mp->log);
1634 if (mp->echo)
1635 log_history_close (mp->echo);
1637 if (mp->state)
1638 log_history_close (mp->state);
1640 CLEAR (*mp);
1643 static void
1644 man_settings_init (struct man_settings *ms,
1645 const char *addr,
1646 const int port,
1647 const char *pass_file,
1648 const int log_history_cache,
1649 const int echo_buffer_size,
1650 const int state_buffer_size,
1651 const char *write_peer_info_file,
1652 const int remap_sigusr1,
1653 const unsigned int flags)
1655 if (!ms->defined)
1657 CLEAR (*ms);
1659 ms->flags = flags;
1662 * Get username/password
1664 if (pass_file)
1665 get_user_pass (&ms->up, pass_file, "Management", GET_USER_PASS_PASSWORD_ONLY);
1667 ms->write_peer_info_file = string_alloc (write_peer_info_file, NULL);
1670 * Initialize socket address
1672 ms->local.sa.sin_family = AF_INET;
1673 ms->local.sa.sin_addr.s_addr = 0;
1674 ms->local.sa.sin_port = htons (port);
1677 * Run management over tunnel, or
1678 * separate channel?
1680 if (streq (addr, "tunnel") && !(flags & MF_CONNECT_AS_CLIENT))
1682 ms->management_over_tunnel = true;
1684 else
1686 ms->local.sa.sin_addr.s_addr = getaddr
1687 (GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, addr, 0, NULL, NULL);
1691 * Log history and echo buffer may need to be resized
1693 ms->log_history_cache = log_history_cache;
1694 ms->echo_buffer_size = echo_buffer_size;
1695 ms->state_buffer_size = state_buffer_size;
1698 * Set remap sigusr1 flags
1700 if (remap_sigusr1 == SIGHUP)
1701 ms->mansig |= MANSIG_MAP_USR1_TO_HUP;
1702 else if (remap_sigusr1 == SIGTERM)
1703 ms->mansig |= MANSIG_MAP_USR1_TO_TERM;
1705 ms->defined = true;
1709 static void
1710 man_settings_close (struct man_settings *ms)
1712 free (ms->write_peer_info_file);
1713 CLEAR (*ms);
1717 static void
1718 man_connection_init (struct management *man)
1720 if (man->connection.state == MS_INITIAL)
1722 #ifdef WIN32
1724 * This object is a sort of TCP/IP helper
1725 * for Windows.
1727 net_event_win32_init (&man->connection.ne32);
1728 #endif
1731 * Allocate helper objects for command line input and
1732 * command output from/to the socket.
1734 man->connection.in = command_line_new (256);
1735 man->connection.out = buffer_list_new (0);
1738 * Initialize event set for standalone usage, when we are
1739 * running outside of the primary event loop.
1742 int maxevents = 1;
1743 man->connection.es = event_set_init (&maxevents, EVENT_METHOD_FAST);
1747 * Listen/connect socket
1749 if (man->settings.flags & MF_CONNECT_AS_CLIENT)
1750 man_connect (man);
1751 else
1752 man_listen (man);
1756 static void
1757 man_connection_close (struct management *man)
1759 struct man_connection *mc = &man->connection;
1761 if (mc->es)
1762 event_free (mc->es);
1763 #ifdef WIN32
1764 net_event_win32_close (&mc->ne32);
1765 #endif
1766 if (socket_defined (mc->sd_top))
1767 man_close_socket (man, mc->sd_top);
1768 if (socket_defined (mc->sd_cli))
1769 man_close_socket (man, mc->sd_cli);
1770 if (mc->in)
1771 command_line_free (mc->in);
1772 if (mc->out)
1773 buffer_list_free (mc->out);
1774 #ifdef MANAGEMENT_DEF_AUTH
1775 in_extra_reset (&man->connection, false);
1776 #endif
1777 man_connection_clear (mc);
1780 struct management *
1781 management_init (void)
1783 struct management *man;
1784 ALLOC_OBJ_CLEAR (man, struct management);
1786 man_persist_init (man,
1787 MANAGEMENT_LOG_HISTORY_INITIAL_SIZE,
1788 MANAGEMENT_ECHO_BUFFER_SIZE,
1789 MANAGEMENT_STATE_BUFFER_SIZE);
1791 man_connection_clear (&man->connection);
1793 return man;
1796 bool
1797 management_open (struct management *man,
1798 const char *addr,
1799 const int port,
1800 const char *pass_file,
1801 const int log_history_cache,
1802 const int echo_buffer_size,
1803 const int state_buffer_size,
1804 const char *write_peer_info_file,
1805 const int remap_sigusr1,
1806 const unsigned int flags)
1808 bool ret = false;
1811 * Save the settings only if they have not
1812 * been saved before.
1814 man_settings_init (&man->settings,
1815 addr,
1816 port,
1817 pass_file,
1818 log_history_cache,
1819 echo_buffer_size,
1820 state_buffer_size,
1821 write_peer_info_file,
1822 remap_sigusr1,
1823 flags);
1826 * The log is initially sized to MANAGEMENT_LOG_HISTORY_INITIAL_SIZE,
1827 * but may be changed here. Ditto for echo and state buffers.
1829 log_history_resize (man->persist.log, man->settings.log_history_cache);
1830 log_history_resize (man->persist.echo, man->settings.echo_buffer_size);
1831 log_history_resize (man->persist.state, man->settings.state_buffer_size);
1834 * If connection object is uninitialized and we are not doing
1835 * over-the-tunnel management, then open (listening) connection.
1837 if (man->connection.state == MS_INITIAL)
1839 if (!man->settings.management_over_tunnel)
1841 man_connection_init (man);
1842 ret = true;
1846 return ret;
1849 void
1850 management_close (struct management *man)
1852 man_connection_close (man);
1853 man_settings_close (&man->settings);
1854 man_persist_close (&man->persist);
1855 free (man);
1858 void
1859 management_set_callback (struct management *man,
1860 const struct management_callback *cb)
1862 man->persist.standalone_disabled = true;
1863 man->persist.callback = *cb;
1866 void
1867 management_clear_callback (struct management *man)
1869 man->persist.standalone_disabled = false;
1870 man->persist.hold_release = false;
1871 CLEAR (man->persist.callback);
1872 man_output_list_push (man, NULL); /* flush output queue */
1875 void
1876 management_set_state (struct management *man,
1877 const int state,
1878 const char *detail,
1879 const in_addr_t tun_local_ip,
1880 const in_addr_t tun_remote_ip)
1882 if (man->persist.state && (!(man->settings.flags & MF_SERVER) || state < OPENVPN_STATE_CLIENT_BASE))
1884 struct gc_arena gc = gc_new ();
1885 struct log_entry e;
1886 const char *out = NULL;
1888 update_time ();
1889 CLEAR (e);
1890 e.timestamp = now;
1891 e.u.state = state;
1892 e.string = detail;
1893 e.local_ip = tun_local_ip;
1894 e.remote_ip = tun_remote_ip;
1896 log_history_add (man->persist.state, &e);
1898 if (man->connection.state_realtime)
1899 out = log_entry_print (&e, LOG_PRINT_STATE_PREFIX
1900 | LOG_PRINT_INT_DATE
1901 | LOG_PRINT_STATE
1902 | LOG_PRINT_LOCAL_IP
1903 | LOG_PRINT_REMOTE_IP
1904 | LOG_PRINT_CRLF
1905 | LOG_ECHO_TO_LOG, &gc);
1907 if (out)
1908 man_output_list_push (man, out);
1910 gc_free (&gc);
1914 #ifdef MANAGEMENT_DEF_AUTH
1916 static void
1917 man_output_env (const struct env_set *es)
1919 if (es)
1921 struct env_item *e;
1922 for (e = es->list; e != NULL; e = e->next)
1924 if (e->string)
1925 msg (M_CLIENT, ">CLIENT:ENV,%s", e->string);
1928 msg (M_CLIENT, ">CLIENT:ENV,END");
1931 void
1932 management_notify_client_needing_auth (struct management *management,
1933 const unsigned int mda_key_id,
1934 struct man_def_auth_context *mdac,
1935 const struct env_set *es)
1937 if (!(mdac->flags & DAF_CONNECTION_CLOSED))
1939 const char *mode = "CONNECT";
1940 if (mdac->flags & DAF_CONNECTION_ESTABLISHED)
1941 mode = "REAUTH";
1942 msg (M_CLIENT, ">CLIENT:%s,%lu,%u", mode, mdac->cid, mda_key_id);
1943 man_output_env (es);
1944 mdac->flags |= DAF_INITIAL_AUTH;
1948 void
1949 management_connection_established (struct management *management,
1950 struct man_def_auth_context *mdac)
1952 mdac->flags |= DAF_CONNECTION_ESTABLISHED;
1955 void
1956 management_notify_client_close (struct management *management,
1957 struct man_def_auth_context *mdac,
1958 const struct env_set *es)
1960 if ((mdac->flags & DAF_INITIAL_AUTH) && !(mdac->flags & DAF_CONNECTION_CLOSED))
1962 msg (M_CLIENT, ">CLIENT:DISCONNECT,%lu", mdac->cid);
1963 man_output_env (es);
1964 mdac->flags |= DAF_CONNECTION_CLOSED;
1968 void
1969 management_learn_addr (struct management *management,
1970 struct man_def_auth_context *mdac,
1971 const struct mroute_addr *addr,
1972 const bool primary)
1974 struct gc_arena gc = gc_new ();
1975 if ((mdac->flags & DAF_INITIAL_AUTH) && !(mdac->flags & DAF_CONNECTION_CLOSED))
1977 msg (M_CLIENT, ">CLIENT:ADDRESS,%lu,%s,%d",
1978 mdac->cid,
1979 mroute_addr_print_ex (addr, MAPF_SUBNET, &gc),
1980 BOOL_CAST (primary));
1982 gc_free (&gc);
1985 #endif
1987 void
1988 management_echo (struct management *man, const char *string, const bool pull)
1990 if (man->persist.echo)
1992 struct gc_arena gc = gc_new ();
1993 struct log_entry e;
1994 const char *out = NULL;
1996 update_time ();
1997 CLEAR (e);
1998 e.timestamp = now;
1999 e.string = string;
2000 e.u.intval = BOOL_CAST (pull);
2002 log_history_add (man->persist.echo, &e);
2004 if (man->connection.echo_realtime)
2005 out = log_entry_print (&e, LOG_PRINT_INT_DATE|LOG_PRINT_ECHO_PREFIX|LOG_PRINT_CRLF|MANAGEMENT_ECHO_FLAGS, &gc);
2007 if (out)
2008 man_output_list_push (man, out);
2010 gc_free (&gc);
2014 void
2015 management_post_tunnel_open (struct management *man, const in_addr_t tun_local_ip)
2018 * If we are running management over the tunnel,
2019 * this is the place to initialize the connection.
2021 if (man->settings.management_over_tunnel
2022 && man->connection.state == MS_INITIAL)
2024 /* listen on our local TUN/TAP IP address */
2025 man->settings.local.sa.sin_addr.s_addr = htonl (tun_local_ip);
2026 man_connection_init (man);
2031 void
2032 management_pre_tunnel_close (struct management *man)
2034 if (man->settings.management_over_tunnel)
2035 man_connection_close (man);
2038 void
2039 management_auth_failure (struct management *man, const char *type)
2041 msg (M_CLIENT, ">PASSWORD:Verification Failed: '%s'", type);
2044 static inline bool
2045 man_persist_state (unsigned int *persistent, const int n)
2047 if (persistent)
2049 if (*persistent == (unsigned int)n)
2050 return false;
2051 *persistent = n;
2053 return true;
2056 #ifdef WIN32
2058 void
2059 management_socket_set (struct management *man,
2060 struct event_set *es,
2061 void *arg,
2062 unsigned int *persistent)
2064 if (man->connection.state != MS_INITIAL)
2066 event_t ev = net_event_win32_get_event (&man->connection.ne32);
2067 net_event_win32_reset_write (&man->connection.ne32);
2069 switch (man->connection.state)
2071 case MS_LISTEN:
2072 if (man_persist_state (persistent, 1))
2073 event_ctl (es, ev, EVENT_READ, arg);
2074 break;
2075 case MS_CC_WAIT_READ:
2076 if (man_persist_state (persistent, 2))
2077 event_ctl (es, ev, EVENT_READ, arg);
2078 break;
2079 case MS_CC_WAIT_WRITE:
2080 if (man_persist_state (persistent, 3))
2081 event_ctl (es, ev, EVENT_READ|EVENT_WRITE, arg);
2082 break;
2083 default:
2084 ASSERT (0);
2089 void
2090 management_io (struct management *man)
2092 if (man->connection.state != MS_INITIAL)
2094 long net_events;
2095 net_event_win32_reset (&man->connection.ne32);
2096 net_events = net_event_win32_get_event_mask (&man->connection.ne32);
2098 if (net_events & FD_CLOSE)
2100 man_reset_client_socket (man, false);
2102 else
2104 if (man->connection.state == MS_LISTEN)
2106 if (net_events & FD_ACCEPT)
2108 man_accept (man);
2109 net_event_win32_clear_selected_events (&man->connection.ne32, FD_ACCEPT);
2112 else if (man->connection.state == MS_CC_WAIT_READ)
2114 if (net_events & FD_READ)
2116 man_read (man);
2117 net_event_win32_clear_selected_events (&man->connection.ne32, FD_READ);
2121 if (man->connection.state == MS_CC_WAIT_WRITE)
2123 if (net_events & FD_WRITE)
2125 int status;
2126 /* dmsg (M_INFO, "FD_WRITE set"); */
2127 status = man_write (man);
2128 if (status < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
2130 /* dmsg (M_INFO, "FD_WRITE cleared"); */
2131 net_event_win32_clear_selected_events (&man->connection.ne32, FD_WRITE);
2139 #else
2141 void
2142 management_socket_set (struct management *man,
2143 struct event_set *es,
2144 void *arg,
2145 unsigned int *persistent)
2147 switch (man->connection.state)
2149 case MS_LISTEN:
2150 if (man_persist_state (persistent, 1))
2151 event_ctl (es, man->connection.sd_top, EVENT_READ, arg);
2152 break;
2153 case MS_CC_WAIT_READ:
2154 if (man_persist_state (persistent, 2))
2155 event_ctl (es, man->connection.sd_cli, EVENT_READ, arg);
2156 break;
2157 case MS_CC_WAIT_WRITE:
2158 if (man_persist_state (persistent, 3))
2159 event_ctl (es, man->connection.sd_cli, EVENT_WRITE, arg);
2160 break;
2161 case MS_INITIAL:
2162 break;
2163 default:
2164 ASSERT (0);
2168 void
2169 management_io (struct management *man)
2171 switch (man->connection.state)
2173 case MS_LISTEN:
2174 man_accept (man);
2175 break;
2176 case MS_CC_WAIT_READ:
2177 man_read (man);
2178 break;
2179 case MS_CC_WAIT_WRITE:
2180 man_write (man);
2181 break;
2182 case MS_INITIAL:
2183 break;
2184 default:
2185 ASSERT (0);
2189 #endif
2191 static inline bool
2192 man_standalone_ok (const struct management *man)
2194 return !man->settings.management_over_tunnel && man->connection.state != MS_INITIAL;
2197 static bool
2198 man_check_for_signals (volatile int *signal_received)
2200 if (signal_received)
2202 get_signal (signal_received);
2203 if (*signal_received)
2204 return true;
2206 return false;
2210 * Wait for socket I/O when outside primary event loop
2212 static int
2213 man_block (struct management *man, volatile int *signal_received, const time_t expire)
2215 struct timeval tv;
2216 struct event_set_return esr;
2217 int status = -1;
2219 if (man_standalone_ok (man))
2223 event_reset (man->connection.es);
2224 management_socket_set (man, man->connection.es, NULL, NULL);
2225 tv.tv_usec = 0;
2226 tv.tv_sec = 1;
2227 if (man_check_for_signals (signal_received))
2229 status = -1;
2230 break;
2232 status = event_wait (man->connection.es, &tv, &esr, 1);
2233 update_time ();
2234 if (man_check_for_signals (signal_received))
2236 status = -1;
2237 break;
2239 /* set SIGINT signal if expiration time exceeded */
2240 if (expire && now >= expire)
2242 status = 0;
2243 if (signal_received)
2244 *signal_received = SIGINT;
2245 break;
2247 } while (status != 1);
2249 return status;
2253 * Perform management socket output outside primary event loop
2255 static void
2256 man_output_standalone (struct management *man, volatile int *signal_received)
2258 if (man_standalone_ok (man))
2260 while (man->connection.state == MS_CC_WAIT_WRITE)
2262 management_io (man);
2263 if (man->connection.state == MS_CC_WAIT_WRITE)
2264 man_block (man, signal_received, 0);
2265 if (signal_received && *signal_received)
2266 break;
2272 * Process management event loop outside primary event loop
2274 static int
2275 man_standalone_event_loop (struct management *man, volatile int *signal_received, const time_t expire)
2277 int status;
2278 ASSERT (man_standalone_ok (man));
2279 status = man_block (man, signal_received, expire);
2280 if (status > 0)
2281 management_io (man);
2282 return status;
2285 #define MWCC_PASSWORD_WAIT (1<<0)
2286 #define MWCC_HOLD_WAIT (1<<1)
2289 * Block until client connects
2291 static void
2292 man_wait_for_client_connection (struct management *man,
2293 volatile int *signal_received,
2294 const time_t expire,
2295 unsigned int flags)
2297 ASSERT (man_standalone_ok (man));
2298 if (man->connection.state == MS_LISTEN)
2300 if (flags & MWCC_PASSWORD_WAIT)
2301 msg (D_MANAGEMENT, "Need password(s) from management interface, waiting...");
2302 if (flags & MWCC_HOLD_WAIT)
2303 msg (D_MANAGEMENT, "Need hold release from management interface, waiting...");
2304 do {
2305 man_standalone_event_loop (man, signal_received, expire);
2306 if (signal_received && *signal_received)
2307 break;
2308 } while (man->connection.state == MS_LISTEN || man_password_needed (man));
2313 * Process the management event loop for sec seconds
2315 void
2316 management_event_loop_n_seconds (struct management *man, int sec)
2318 if (man_standalone_ok (man))
2320 volatile int signal_received = 0;
2321 const bool standalone_disabled_save = man->persist.standalone_disabled;
2322 time_t expire;
2324 man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
2326 /* set expire time */
2327 update_time ();
2328 expire = now + sec;
2330 /* if no client connection, wait for one */
2331 man_wait_for_client_connection (man, &signal_received, expire, 0);
2332 if (signal_received)
2333 return;
2335 /* run command processing event loop until we get our username/password */
2336 while (true)
2338 man_standalone_event_loop (man, &signal_received, expire);
2339 if (signal_received)
2340 return;
2343 /* revert state */
2344 man->persist.standalone_disabled = standalone_disabled_save;
2346 else
2348 sleep (sec);
2353 * Get a username/password from management channel in standalone mode.
2355 bool
2356 management_query_user_pass (struct management *man,
2357 struct user_pass *up,
2358 const char *type,
2359 const unsigned int flags)
2361 struct gc_arena gc = gc_new ();
2362 bool ret = false;
2364 if (man_standalone_ok (man))
2366 volatile int signal_received = 0;
2367 const bool standalone_disabled_save = man->persist.standalone_disabled;
2368 struct buffer alert_msg = alloc_buf_gc (128, &gc);
2369 const char *alert_type = NULL;
2370 const char *prefix = NULL;
2371 unsigned int up_query_mode = 0;
2373 ret = true;
2374 man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
2375 man->persist.special_state_msg = NULL;
2377 CLEAR (man->connection.up_query);
2379 if (flags & GET_USER_PASS_NEED_OK)
2381 up_query_mode = UP_QUERY_NEED_OK;
2382 prefix= "NEED-OK";
2383 alert_type = "confirmation";
2385 else if (flags & GET_USER_PASS_NEED_STR)
2387 up_query_mode = UP_QUERY_NEED_STR;
2388 prefix= "NEED-STR";
2389 alert_type = "string";
2391 else if (flags & GET_USER_PASS_PASSWORD_ONLY)
2393 up_query_mode = UP_QUERY_PASS;
2394 prefix = "PASSWORD";
2395 alert_type = "password";
2397 else
2399 up_query_mode = UP_QUERY_USER_PASS;
2400 prefix = "PASSWORD";
2401 alert_type = "username/password";
2403 buf_printf (&alert_msg, ">%s:Need '%s' %s",
2404 prefix,
2405 type,
2406 alert_type);
2408 if (flags & (GET_USER_PASS_NEED_OK | GET_USER_PASS_NEED_STR))
2409 buf_printf (&alert_msg, " MSG:%s", up->username);
2411 man_wait_for_client_connection (man, &signal_received, 0, MWCC_PASSWORD_WAIT);
2412 if (signal_received)
2413 ret = false;
2415 if (ret)
2417 man->persist.special_state_msg = BSTR (&alert_msg);
2418 msg (M_CLIENT, "%s", man->persist.special_state_msg);
2420 /* tell command line parser which info we need */
2421 man->connection.up_query_mode = up_query_mode;
2422 man->connection.up_query_type = type;
2424 /* run command processing event loop until we get our username/password */
2427 man_standalone_event_loop (man, &signal_received, 0);
2428 if (signal_received)
2430 ret = false;
2431 break;
2433 } while (!man->connection.up_query.defined);
2436 /* revert state */
2437 man->connection.up_query_mode = UP_QUERY_DISABLED;
2438 man->connection.up_query_type = NULL;
2439 man->persist.standalone_disabled = standalone_disabled_save;
2440 man->persist.special_state_msg = NULL;
2442 /* pass through blank passwords */
2443 if (!strcmp (man->connection.up_query.password, blank_up))
2444 CLEAR (man->connection.up_query.password);
2447 * Transfer u/p to return object, zero any record
2448 * we hold in the management object.
2450 if (ret)
2452 man->connection.up_query.nocache = up->nocache; /* preserve caller's nocache setting */
2453 *up = man->connection.up_query;
2455 CLEAR (man->connection.up_query);
2458 gc_free (&gc);
2459 return ret;
2463 * Return true if management_hold() would block
2465 bool
2466 management_would_hold (struct management *man)
2468 return (man->settings.flags & MF_HOLD) && !man->persist.hold_release && man_standalone_ok (man);
2472 * Return true if (from the management interface's perspective) OpenVPN should
2473 * daemonize.
2475 bool
2476 management_should_daemonize (struct management *man)
2478 return management_would_hold (man) || (man->settings.flags & MF_QUERY_PASSWORDS);
2482 * If the hold flag is enabled, hibernate until a management client releases the hold.
2483 * Return true if the caller should not sleep for an additional time interval.
2485 bool
2486 management_hold (struct management *man)
2488 if (management_would_hold (man))
2490 volatile int signal_received = 0;
2491 const bool standalone_disabled_save = man->persist.standalone_disabled;
2493 man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
2494 man->persist.special_state_msg = NULL;
2495 man->settings.mansig |= MANSIG_IGNORE_USR1_HUP;
2497 man_wait_for_client_connection (man, &signal_received, 0, MWCC_HOLD_WAIT);
2499 if (!signal_received)
2501 man->persist.special_state_msg = ">HOLD:Waiting for hold release";
2502 msg (M_CLIENT, "%s", man->persist.special_state_msg);
2504 /* run command processing event loop until we get our username/password */
2507 man_standalone_event_loop (man, &signal_received, 0);
2508 if (signal_received)
2509 break;
2510 } while (!man->persist.hold_release);
2513 /* revert state */
2514 man->persist.standalone_disabled = standalone_disabled_save;
2515 man->persist.special_state_msg = NULL;
2516 man->settings.mansig &= ~MANSIG_IGNORE_USR1_HUP;
2518 return true;
2520 return false;
2524 * struct command_line
2527 struct command_line *
2528 command_line_new (const int buf_len)
2530 struct command_line *cl;
2531 ALLOC_OBJ_CLEAR (cl, struct command_line);
2532 cl->buf = alloc_buf (buf_len);
2533 cl->residual = alloc_buf (buf_len);
2534 return cl;
2537 void
2538 command_line_reset (struct command_line *cl)
2540 buf_clear (&cl->buf);
2541 buf_clear (&cl->residual);
2544 void
2545 command_line_free (struct command_line *cl)
2547 command_line_reset (cl);
2548 free_buf (&cl->buf);
2549 free_buf (&cl->residual);
2550 free (cl);
2553 void
2554 command_line_add (struct command_line *cl, const unsigned char *buf, const int len)
2556 int i;
2557 for (i = 0; i < len; ++i)
2559 if (buf[i] && (isprint(buf[i]) || buf[i] == '\n'))
2561 if (!buf_write_u8 (&cl->buf, buf[i]))
2562 buf_clear (&cl->buf);
2567 const unsigned char *
2568 command_line_get (struct command_line *cl)
2570 int i;
2571 const unsigned char *ret = NULL;
2573 i = buf_substring_len (&cl->buf, '\n');
2574 if (i >= 0)
2576 buf_copy_excess (&cl->residual, &cl->buf, i);
2577 buf_chomp (&cl->buf);
2578 ret = (const unsigned char *) BSTR (&cl->buf);
2580 return ret;
2583 void
2584 command_line_next (struct command_line *cl)
2586 buf_clear (&cl->buf);
2587 buf_copy (&cl->buf, &cl->residual);
2588 buf_clear (&cl->residual);
2592 * struct log_entry
2595 const char *
2596 log_entry_print (const struct log_entry *e, unsigned int flags, struct gc_arena *gc)
2598 struct buffer out = alloc_buf_gc (ERR_BUF_SIZE, gc);
2599 if (flags & LOG_FATAL_NOTIFY)
2600 buf_printf (&out, ">FATAL:");
2601 if (flags & LOG_PRINT_LOG_PREFIX)
2602 buf_printf (&out, ">LOG:");
2603 if (flags & LOG_PRINT_ECHO_PREFIX)
2604 buf_printf (&out, ">ECHO:");
2605 if (flags & LOG_PRINT_STATE_PREFIX)
2606 buf_printf (&out, ">STATE:");
2607 if (flags & LOG_PRINT_INT_DATE)
2608 buf_printf (&out, "%u,", (unsigned int)e->timestamp);
2609 if (flags & LOG_PRINT_MSG_FLAGS)
2610 buf_printf (&out, "%s,", msg_flags_string (e->u.msg_flags, gc));
2611 if (flags & LOG_PRINT_STATE)
2612 buf_printf (&out, "%s,", man_state_name (e->u.state));
2613 if (flags & LOG_PRINT_INTVAL)
2614 buf_printf (&out, "%d,", e->u.intval);
2615 if (e->string)
2616 buf_printf (&out, "%s", e->string);
2617 if (flags & LOG_PRINT_LOCAL_IP)
2618 buf_printf (&out, ",%s", print_in_addr_t (e->local_ip, IA_EMPTY_IF_UNDEF, gc));
2619 if (flags & LOG_PRINT_REMOTE_IP)
2620 buf_printf (&out, ",%s", print_in_addr_t (e->remote_ip, IA_EMPTY_IF_UNDEF, gc));
2621 if (flags & LOG_ECHO_TO_LOG)
2622 msg (D_MANAGEMENT, "MANAGEMENT: %s", BSTR (&out));
2623 if (flags & LOG_PRINT_CRLF)
2624 buf_printf (&out, "\r\n");
2625 return BSTR (&out);
2628 static void
2629 log_entry_free_contents (struct log_entry *e)
2631 if (e->string)
2632 free ((char *)e->string);
2633 CLEAR (*e);
2637 * struct log_history
2640 static inline int
2641 log_index (const struct log_history *h, int i)
2643 return modulo_add (h->base, i, h->capacity);
2646 static void
2647 log_history_obj_init (struct log_history *h, int capacity)
2649 CLEAR (*h);
2650 h->capacity = capacity;
2651 ALLOC_ARRAY_CLEAR (h->array, struct log_entry, capacity);
2654 struct log_history *
2655 log_history_init (const int capacity)
2657 struct log_history *h;
2658 ASSERT (capacity > 0);
2659 ALLOC_OBJ (h, struct log_history);
2660 log_history_obj_init (h, capacity);
2661 return h;
2664 static void
2665 log_history_free_contents (struct log_history *h)
2667 int i;
2668 for (i = 0; i < h->size; ++i)
2669 log_entry_free_contents (&h->array[log_index(h, i)]);
2670 free (h->array);
2673 void
2674 log_history_close (struct log_history *h)
2676 log_history_free_contents (h);
2677 free (h);
2680 void
2681 log_history_add (struct log_history *h, const struct log_entry *le)
2683 struct log_entry *e;
2684 ASSERT (h->size >= 0 && h->size <= h->capacity);
2685 if (h->size == h->capacity)
2687 e = &h->array[h->base];
2688 log_entry_free_contents (e);
2689 h->base = log_index (h, 1);
2691 else
2693 e = &h->array[log_index(h, h->size)];
2694 ++h->size;
2697 *e = *le;
2698 e->string = string_alloc (le->string, NULL);
2701 void
2702 log_history_resize (struct log_history *h, const int capacity)
2704 if (capacity != h->capacity)
2706 struct log_history newlog;
2707 int i;
2709 ASSERT (capacity > 0);
2710 log_history_obj_init (&newlog, capacity);
2712 for (i = 0; i < h->size; ++i)
2713 log_history_add (&newlog, &h->array[log_index(h, i)]);
2715 log_history_free_contents (h);
2716 *h = newlog;
2720 const struct log_entry *
2721 log_history_ref (const struct log_history *h, const int index)
2723 if (index >= 0 && index < h->size)
2724 return &h->array[log_index(h, (h->size - 1) - index)];
2725 else
2726 return NULL;
2729 #else
2730 static void dummy(void) {}
2731 #endif /* ENABLE_MANAGEMENT */