vsftpd 2.0.7 - initial checkin.
[tomato.git] / release / src / router / vsftpd / logging.c
blob368eb7dc6984635b5ef7622b49cc674e0238eb11
1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
6 * logging.c
7 */
9 #include "logging.h"
10 #include "tunables.h"
11 #include "utility.h"
12 #include "str.h"
13 #include "sysutil.h"
14 #include "sysstr.h"
15 #include "session.h"
17 /* File local functions */
18 static int vsf_log_type_is_transfer(enum EVSFLogEntryType type);
19 static void vsf_log_common(struct vsf_session* p_sess, int succeeded,
20 enum EVSFLogEntryType what,
21 const struct mystr* p_str);
22 static void vsf_log_do_log_vsftpd_format(struct vsf_session* p_sess,
23 struct mystr* p_str, int succeeded,
24 enum EVSFLogEntryType what,
25 const struct mystr* p_log_str);
26 static void vsf_log_do_log_wuftpd_format(struct vsf_session* p_sess,
27 struct mystr* p_str, int succeeded);
28 static void vsf_log_do_log_to_file(int fd, struct mystr* p_str);
30 void
31 vsf_log_init(struct vsf_session* p_sess)
33 int retval;
34 if (tunable_syslog_enable || tunable_tcp_wrappers)
36 vsf_sysutil_openlog();
38 if (!tunable_xferlog_enable && !tunable_dual_log_enable)
40 return;
42 if (tunable_dual_log_enable || tunable_xferlog_std_format)
44 retval = vsf_sysutil_create_or_open_file(tunable_xferlog_file, 0600);
45 if (vsf_sysutil_retval_is_error(retval))
47 die2("failed to open xferlog log file:", tunable_xferlog_file);
49 p_sess->xferlog_fd = retval;
51 if (tunable_dual_log_enable || !tunable_xferlog_std_format)
53 if (!tunable_syslog_enable)
55 retval = vsf_sysutil_create_or_open_file(tunable_vsftpd_log_file, 0600);
56 if (vsf_sysutil_retval_is_error(retval))
58 die2("failed to open vsftpd log file:", tunable_vsftpd_log_file);
60 p_sess->vsftpd_log_fd = retval;
65 static int
66 vsf_log_type_is_transfer(enum EVSFLogEntryType type)
68 return (type == kVSFLogEntryDownload || type == kVSFLogEntryUpload);
71 void
72 vsf_log_start_entry(struct vsf_session* p_sess, enum EVSFLogEntryType what)
74 if (p_sess->log_type != 0)
76 bug("non null log_type in vsf_log_start_entry");
78 p_sess->log_type = (unsigned long) what;
79 p_sess->log_start_sec = 0;
80 p_sess->log_start_usec = 0;
81 p_sess->transfer_size = 0;
82 str_empty(&p_sess->log_str);
83 if (vsf_log_type_is_transfer(what))
85 vsf_sysutil_update_cached_time();
86 p_sess->log_start_sec = vsf_sysutil_get_cached_time_sec();
87 p_sess->log_start_usec = vsf_sysutil_get_cached_time_usec();
91 void
92 vsf_log_line(struct vsf_session* p_sess, enum EVSFLogEntryType what,
93 struct mystr* p_str)
95 vsf_log_common(p_sess, 1, what, p_str);
98 int
99 vsf_log_entry_pending(struct vsf_session* p_sess)
101 if (p_sess->log_type == 0)
103 return 0;
105 return 1;
108 void
109 vsf_log_clear_entry(struct vsf_session* p_sess)
111 p_sess->log_type = 0;
114 void
115 vsf_log_do_log(struct vsf_session* p_sess, int succeeded)
117 vsf_log_common(p_sess, succeeded, (enum EVSFLogEntryType) p_sess->log_type,
118 &p_sess->log_str);
119 p_sess->log_type = 0;
122 static void
123 vsf_log_common(struct vsf_session* p_sess, int succeeded,
124 enum EVSFLogEntryType what, const struct mystr* p_str)
126 static struct mystr s_log_str;
127 /* Handle xferlog line if appropriate */
128 if (p_sess->xferlog_fd != -1 && vsf_log_type_is_transfer(what))
130 vsf_log_do_log_wuftpd_format(p_sess, &s_log_str, succeeded);
131 vsf_log_do_log_to_file(p_sess->xferlog_fd, &s_log_str);
133 /* Handle vsftpd.log line if appropriate */
134 if (p_sess->vsftpd_log_fd != -1)
136 vsf_log_do_log_vsftpd_format(p_sess, &s_log_str, succeeded, what, p_str);
137 vsf_log_do_log_to_file(p_sess->vsftpd_log_fd, &s_log_str);
139 /* Handle syslog() line if appropriate */
140 if (tunable_syslog_enable)
142 int severe = 0;
143 vsf_log_do_log_vsftpd_format(p_sess, &s_log_str, succeeded, what, p_str);
144 if (what == kVSFLogEntryLogin && !succeeded)
146 severe = 1;
148 str_syslog(&s_log_str, severe);
152 static void
153 vsf_log_do_log_to_file(int fd, struct mystr* p_str)
155 if (!tunable_no_log_lock)
157 int retval = vsf_sysutil_lock_file_write(fd);
158 if (vsf_sysutil_retval_is_error(retval))
160 return;
163 str_replace_unprintable(p_str, '?');
164 str_append_char(p_str, '\n');
165 /* Ignore write failure; maybe the disk filled etc. */
166 (void) str_write_loop(p_str, fd);
167 if (!tunable_no_log_lock)
169 vsf_sysutil_unlock_file(fd);
173 static void
174 vsf_log_do_log_wuftpd_format(struct vsf_session* p_sess, struct mystr* p_str,
175 int succeeded)
177 long delta_sec;
178 enum EVSFLogEntryType what = (enum EVSFLogEntryType) p_sess->log_type;
179 /* Date - vsf_sysutil_get_current_date updates cached time */
180 str_alloc_text(p_str, vsf_sysutil_get_current_date());
181 str_append_char(p_str, ' ');
182 /* Transfer time (in seconds) */
183 delta_sec = vsf_sysutil_get_cached_time_sec() - p_sess->log_start_sec;
184 if (delta_sec <= 0)
186 delta_sec = 1;
188 str_append_ulong(p_str, (unsigned long) delta_sec);
189 str_append_char(p_str, ' ');
190 /* Remote host name */
191 str_append_str(p_str, &p_sess->remote_ip_str);
192 str_append_char(p_str, ' ');
193 /* Bytes transferred */
194 str_append_filesize_t(p_str, p_sess->transfer_size);
195 str_append_char(p_str, ' ');
196 /* Filename */
197 str_append_str(p_str, &p_sess->log_str);
198 str_append_char(p_str, ' ');
199 /* Transfer type (ascii/binary) */
200 if (p_sess->is_ascii)
202 str_append_text(p_str, "a ");
204 else
206 str_append_text(p_str, "b ");
208 /* Special action flag - tar, gzip etc. */
209 str_append_text(p_str, "_ ");
210 /* Direction of transfer */
211 if (what == kVSFLogEntryUpload)
213 str_append_text(p_str, "i ");
215 else
217 str_append_text(p_str, "o ");
219 /* Access mode: anonymous/real user, and identity */
220 if (p_sess->is_anonymous && !p_sess->is_guest)
222 str_append_text(p_str, "a ");
223 str_append_str(p_str, &p_sess->anon_pass_str);
225 else
227 if (p_sess->is_guest)
229 str_append_text(p_str, "g ");
231 else
233 str_append_text(p_str, "r ");
235 str_append_str(p_str, &p_sess->user_str);
237 str_append_char(p_str, ' ');
238 /* Service name, authentication method, authentication user id */
239 str_append_text(p_str, "ftp 0 * ");
240 /* Completion status */
241 if (succeeded)
243 str_append_char(p_str, 'c');
245 else
247 str_append_char(p_str, 'i');
251 static void
252 vsf_log_do_log_vsftpd_format(struct vsf_session* p_sess, struct mystr* p_str,
253 int succeeded, enum EVSFLogEntryType what,
254 const struct mystr* p_log_str)
256 /* Date - vsf_sysutil_get_current_date updates cached time */
257 str_alloc_text(p_str, vsf_sysutil_get_current_date());
258 /* Pid */
259 str_append_text(p_str, " [pid ");
260 str_append_ulong(p_str, vsf_sysutil_getpid());
261 str_append_text(p_str, "] ");
262 /* User */
263 if (!str_isempty(&p_sess->user_str))
265 str_append_char(p_str, '[');
266 str_append_str(p_str, &p_sess->user_str);
267 str_append_text(p_str, "] ");
269 /* And the action */
270 if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput &&
271 what != kVSFLogEntryConnection && what != kVSFLogEntryDebug)
273 if (succeeded)
275 str_append_text(p_str, "OK ");
277 else
279 str_append_text(p_str, "FAIL ");
282 switch (what)
284 case kVSFLogEntryDownload:
285 str_append_text(p_str, "DOWNLOAD");
286 break;
287 case kVSFLogEntryUpload:
288 str_append_text(p_str, "UPLOAD");
289 break;
290 case kVSFLogEntryMkdir:
291 str_append_text(p_str, "MKDIR");
292 break;
293 case kVSFLogEntryLogin:
294 str_append_text(p_str, "LOGIN");
295 break;
296 case kVSFLogEntryFTPInput:
297 str_append_text(p_str, "FTP command");
298 break;
299 case kVSFLogEntryFTPOutput:
300 str_append_text(p_str, "FTP response");
301 break;
302 case kVSFLogEntryConnection:
303 str_append_text(p_str, "CONNECT");
304 break;
305 case kVSFLogEntryDelete:
306 str_append_text(p_str, "DELETE");
307 break;
308 case kVSFLogEntryRename:
309 str_append_text(p_str, "RENAME");
310 break;
311 case kVSFLogEntryRmdir:
312 str_append_text(p_str, "RMDIR");
313 break;
314 case kVSFLogEntryChmod:
315 str_append_text(p_str, "CHMOD");
316 break;
317 case kVSFLogEntryDebug:
318 str_append_text(p_str, "DEBUG");
319 break;
320 default:
321 bug("bad entry_type in vsf_log_do_log");
322 break;
324 str_append_text(p_str, ": Client \"");
325 str_append_str(p_str, &p_sess->remote_ip_str);
326 str_append_char(p_str, '"');
327 if (what == kVSFLogEntryLogin && !str_isempty(&p_sess->anon_pass_str))
329 str_append_text(p_str, ", anon password \"");
330 str_append_str(p_str, &p_sess->anon_pass_str);
331 str_append_char(p_str, '"');
333 if (!str_isempty(p_log_str))
335 str_append_text(p_str, ", \"");
336 str_append_str(p_str, p_log_str);
337 str_append_char(p_str, '"');
339 if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput &&
340 what != kVSFLogEntryDebug)
342 if (p_sess->transfer_size)
344 str_append_text(p_str, ", ");
345 str_append_filesize_t(p_str, p_sess->transfer_size);
346 str_append_text(p_str, " bytes");
348 if (vsf_log_type_is_transfer(what))
350 long delta_sec = vsf_sysutil_get_cached_time_sec() -
351 p_sess->log_start_sec;
352 long delta_usec = vsf_sysutil_get_cached_time_usec() -
353 p_sess->log_start_usec;
354 double time_delta = (double) delta_sec + ((double) delta_usec /
355 (double) 1000000);
356 double kbyte_rate;
357 if (time_delta <= 0)
359 time_delta = 0.1;
361 kbyte_rate =
362 ((double) p_sess->transfer_size / time_delta) / (double) 1024;
363 str_append_text(p_str, ", ");
364 str_append_double(p_str, kbyte_rate);
365 str_append_text(p_str, "Kbyte/sec");