1 /*
2 * log.c - logging and debugging functions
3 *
4 * This file is part of the SSH Library
5 *
6 * Copyright (c) 2008-2013 by Aris Adamantiadis
7 *
8 * The SSH Library is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or (at your
11 * option) any later version.
12 *
13 * The SSH Library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 * License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with the SSH Library; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21 * MA 02111-1307, USA.
22 */
23
24 #include "config.h"
25
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #ifdef HAVE_SYS_TIME_H
30 #include <sys/time.h>
31 #endif /* HAVE_SYS_TIME_H */
32 #ifdef HAVE_SYS_UTIME_H
33 #include <sys/utime.h>
34 #endif /* HAVE_SYS_UTIME_H */
35 #include <time.h>
36
37 #include "libssh/priv.h"
38 #include "libssh/misc.h"
39 #include "libssh/session.h"
40
41 static LIBSSH_THREAD int ssh_log_level;
42 static LIBSSH_THREAD ssh_logging_callback ssh_log_cb;
43 static LIBSSH_THREAD void *ssh_log_userdata;
44
45 /**
46 * @defgroup libssh_log The SSH logging functions.
47 * @ingroup libssh
48 *
49 * Logging functions for debugging and problem resolving.
50 *
51 * @{
52 */
53
current_timestring(int hires,char * buf,size_t len)54 static int current_timestring(int hires, char *buf, size_t len)
55 {
56 char tbuf[64];
57 struct timeval tv;
58 struct tm *tm;
59 time_t t;
60
61 gettimeofday(&tv, NULL);
62 t = (time_t) tv.tv_sec;
63
64 tm = localtime(&t);
65 if (tm == NULL) {
66 return -1;
67 }
68
69 if (hires) {
70 strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
71 snprintf(buf, len, "%s.%06ld", tbuf, (long)tv.tv_usec);
72 } else {
73 strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
74 snprintf(buf, len, "%s", tbuf);
75 }
76
77 return 0;
78 }
79
ssh_log_stderr(int verbosity,const char * function,const char * buffer)80 static void ssh_log_stderr(int verbosity,
81 const char *function,
82 const char *buffer)
83 {
84 char date[128] = {0};
85 int rc;
86
87 rc = current_timestring(1, date, sizeof(date));
88 if (rc == 0) {
89 fprintf(stderr, "[%s, %d] %s:", date, verbosity, function);
90 } else {
91 fprintf(stderr, "[%d] %s", verbosity, function);
92 }
93
94 fprintf(stderr, " %s\n", buffer);
95 }
96
ssh_log_function(int verbosity,const char * function,const char * buffer)97 void ssh_log_function(int verbosity,
98 const char *function,
99 const char *buffer)
100 {
101 ssh_logging_callback log_fn = ssh_get_log_callback();
102 if (log_fn) {
103 char buf[1024];
104
105 snprintf(buf, sizeof(buf), "%s: %s", function, buffer);
106
107 log_fn(verbosity,
108 function,
109 buf,
110 ssh_get_log_userdata());
111 return;
112 }
113
114 ssh_log_stderr(verbosity, function, buffer);
115 }
116
_ssh_log(int verbosity,const char * function,const char * format,...)117 void _ssh_log(int verbosity,
118 const char *function,
119 const char *format, ...)
120 {
121 char buffer[1024];
122 va_list va;
123
124 if (verbosity <= ssh_get_log_level()) {
125 va_start(va, format);
126 vsnprintf(buffer, sizeof(buffer), format, va);
127 va_end(va);
128 ssh_log_function(verbosity, function, buffer);
129 }
130 }
131
132 /* LEGACY */
133
ssh_log(ssh_session session,int verbosity,const char * format,...)134 void ssh_log(ssh_session session,
135 int verbosity,
136 const char *format, ...)
137 {
138 char buffer[1024];
139 va_list va;
140
141 if (verbosity <= session->common.log_verbosity) {
142 va_start(va, format);
143 vsnprintf(buffer, sizeof(buffer), format, va);
144 va_end(va);
145 ssh_log_function(verbosity, "", buffer);
146 }
147 }
148
149 /** @internal
150 * @brief log a SSH event with a common pointer
151 * @param common The SSH/bind session.
152 * @param verbosity The verbosity of the event.
153 * @param format The format string of the log entry.
154 */
ssh_log_common(struct ssh_common_struct * common,int verbosity,const char * function,const char * format,...)155 void ssh_log_common(struct ssh_common_struct *common,
156 int verbosity,
157 const char *function,
158 const char *format, ...)
159 {
160 char buffer[1024];
161 va_list va;
162
163 if (verbosity <= common->log_verbosity) {
164 va_start(va, format);
165 vsnprintf(buffer, sizeof(buffer), format, va);
166 va_end(va);
167 ssh_log_function(verbosity, function, buffer);
168 }
169 }
170
171
172 /* PUBLIC */
173
174 /**
175 * @brief Set the log level of the library.
176 *
177 * @param[in] level The level to set.
178 *
179 * @return SSH_OK on success, SSH_ERROR on error.
180 */
ssh_set_log_level(int level)181 int ssh_set_log_level(int level) {
182 if (level < 0) {
183 return SSH_ERROR;
184 }
185
186 ssh_log_level = level;
187
188 return SSH_OK;
189 }
190
191 /**
192 * @brief Get the log level of the library.
193 *
194 * @return The value of the log level.
195 */
ssh_get_log_level(void)196 int ssh_get_log_level(void) {
197 return ssh_log_level;
198 }
199
ssh_set_log_callback(ssh_logging_callback cb)200 int ssh_set_log_callback(ssh_logging_callback cb) {
201 if (cb == NULL) {
202 return SSH_ERROR;
203 }
204
205 ssh_log_cb = cb;
206
207 return SSH_OK;
208 }
209
ssh_get_log_callback(void)210 ssh_logging_callback ssh_get_log_callback(void) {
211 return ssh_log_cb;
212 }
213
214 /**
215 * @brief Get the userdata of the logging function.
216 *
217 * @return The userdata if set or NULL.
218 */
ssh_get_log_userdata(void)219 void *ssh_get_log_userdata(void)
220 {
221 if (ssh_log_userdata == NULL) {
222 return NULL;
223 }
224
225 return ssh_log_userdata;
226 }
227
228 /**
229 * @brief Set the userdata for the logging function.
230 *
231 * @param[in] data The userdata to set.
232 *
233 * @return SSH_OK on success.
234 */
ssh_set_log_userdata(void * data)235 int ssh_set_log_userdata(void *data)
236 {
237 ssh_log_userdata = data;
238
239 return 0;
240 }
241
242 /** @} */
243