Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / vsftpd / logging.c
blob2a1ca4530a089c70ecbec91e8c7066720a983d34
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(1);
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_append(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_append(tunable_vsftpd_log_file,
56 0600);
57 if (vsf_sysutil_retval_is_error(retval))
59 die2("failed to open vsftpd log file:", tunable_vsftpd_log_file);
61 p_sess->vsftpd_log_fd = retval;
66 static int
67 vsf_log_type_is_transfer(enum EVSFLogEntryType type)
69 return (type == kVSFLogEntryDownload || type == kVSFLogEntryUpload);
72 void
73 vsf_log_start_entry(struct vsf_session* p_sess, enum EVSFLogEntryType what)
75 if (p_sess->log_type != 0)
77 bug("non null log_type in vsf_log_start_entry");
79 p_sess->log_type = (unsigned long) what;
80 p_sess->log_start_sec = 0;
81 p_sess->log_start_usec = 0;
82 p_sess->transfer_size = 0;
83 str_empty(&p_sess->log_str);
84 if (vsf_log_type_is_transfer(what))
86 p_sess->log_start_sec = vsf_sysutil_get_time_sec();
87 p_sess->log_start_usec = vsf_sysutil_get_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 static struct mystr s_filename_str;
178 long delta_sec;
179 enum EVSFLogEntryType what = (enum EVSFLogEntryType) p_sess->log_type;
180 /* Date - vsf_sysutil_get_current_date updates cached time */
181 str_alloc_text(p_str, vsf_sysutil_get_current_date());
182 str_append_char(p_str, ' ');
183 /* Transfer time (in seconds) */
184 delta_sec = vsf_sysutil_get_time_sec() - p_sess->log_start_sec;
185 if (delta_sec <= 0)
187 delta_sec = 1;
189 str_append_ulong(p_str, (unsigned long) delta_sec);
190 str_append_char(p_str, ' ');
191 /* Remote host name */
192 str_append_str(p_str, &p_sess->remote_ip_str);
193 str_append_char(p_str, ' ');
194 /* Bytes transferred */
195 str_append_filesize_t(p_str, p_sess->transfer_size);
196 str_append_char(p_str, ' ');
197 /* Filename */
198 str_copy(&s_filename_str, &p_sess->log_str);
199 str_replace_char(&s_filename_str, ' ', '_');
200 str_append_str(p_str, &s_filename_str);
201 str_append_char(p_str, ' ');
202 /* Transfer type (ascii/binary) */
203 if (p_sess->is_ascii)
205 str_append_text(p_str, "a ");
207 else
209 str_append_text(p_str, "b ");
211 /* Special action flag - tar, gzip etc. */
212 str_append_text(p_str, "_ ");
213 /* Direction of transfer */
214 if (what == kVSFLogEntryUpload)
216 str_append_text(p_str, "i ");
218 else
220 str_append_text(p_str, "o ");
222 /* Access mode: anonymous/real user, and identity */
223 if (p_sess->is_anonymous && !p_sess->is_guest)
225 str_append_text(p_str, "a ");
226 str_append_str(p_str, &p_sess->anon_pass_str);
228 else
230 if (p_sess->is_guest)
232 str_append_text(p_str, "g ");
234 else
236 str_append_text(p_str, "r ");
238 str_append_str(p_str, &p_sess->user_str);
240 str_append_char(p_str, ' ');
241 /* Service name, authentication method, authentication user id */
242 str_append_text(p_str, "ftp 0 * ");
243 /* Completion status */
244 if (succeeded)
246 str_append_char(p_str, 'c');
248 else
250 str_append_char(p_str, 'i');
254 static void
255 vsf_log_do_log_vsftpd_format(struct vsf_session* p_sess, struct mystr* p_str,
256 int succeeded, enum EVSFLogEntryType what,
257 const struct mystr* p_log_str)
259 str_empty(p_str);
260 if (!tunable_syslog_enable)
262 /* Date - vsf_sysutil_get_current_date updates cached time */
263 str_append_text(p_str, vsf_sysutil_get_current_date());
264 /* Pid */
265 str_append_text(p_str, " [pid ");
266 str_append_ulong(p_str, vsf_sysutil_getpid());
267 str_append_text(p_str, "] ");
269 /* User */
270 if (!str_isempty(&p_sess->user_str))
272 str_append_char(p_str, '[');
273 str_append_str(p_str, &p_sess->user_str);
274 str_append_text(p_str, "] ");
276 /* And the action */
277 if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput &&
278 what != kVSFLogEntryConnection && what != kVSFLogEntryDebug)
280 if (succeeded)
282 str_append_text(p_str, "OK ");
284 else
286 str_append_text(p_str, "FAIL ");
289 switch (what)
291 case kVSFLogEntryDownload:
292 str_append_text(p_str, "DOWNLOAD");
293 break;
294 case kVSFLogEntryUpload:
295 str_append_text(p_str, "UPLOAD");
296 break;
297 case kVSFLogEntryMkdir:
298 str_append_text(p_str, "MKDIR");
299 break;
300 case kVSFLogEntryLogin:
301 str_append_text(p_str, "LOGIN");
302 break;
303 case kVSFLogEntryFTPInput:
304 str_append_text(p_str, "FTP command");
305 break;
306 case kVSFLogEntryFTPOutput:
307 str_append_text(p_str, "FTP response");
308 break;
309 case kVSFLogEntryConnection:
310 str_append_text(p_str, "CONNECT");
311 break;
312 case kVSFLogEntryDelete:
313 str_append_text(p_str, "DELETE");
314 break;
315 case kVSFLogEntryRename:
316 str_append_text(p_str, "RENAME");
317 break;
318 case kVSFLogEntryRmdir:
319 str_append_text(p_str, "RMDIR");
320 break;
321 case kVSFLogEntryChmod:
322 str_append_text(p_str, "CHMOD");
323 break;
324 case kVSFLogEntryDebug:
325 str_append_text(p_str, "DEBUG");
326 break;
327 default:
328 bug("bad entry_type in vsf_log_do_log");
329 break;
331 str_append_text(p_str, ": Client \"");
332 str_append_str(p_str, &p_sess->remote_ip_str);
333 str_append_char(p_str, '"');
334 if (what == kVSFLogEntryLogin && !str_isempty(&p_sess->anon_pass_str))
336 str_append_text(p_str, ", anon password \"");
337 str_append_str(p_str, &p_sess->anon_pass_str);
338 str_append_char(p_str, '"');
340 if (!str_isempty(p_log_str))
342 str_append_text(p_str, ", \"");
343 str_append_str(p_str, p_log_str);
344 str_append_char(p_str, '"');
346 if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput &&
347 what != kVSFLogEntryDebug)
349 if (p_sess->transfer_size)
351 str_append_text(p_str, ", ");
352 str_append_filesize_t(p_str, p_sess->transfer_size);
353 str_append_text(p_str, " bytes");
355 if (vsf_log_type_is_transfer(what))
357 long delta_sec = vsf_sysutil_get_time_sec() - p_sess->log_start_sec;
358 long delta_usec = vsf_sysutil_get_time_usec() - p_sess->log_start_usec;
359 double time_delta = (double) delta_sec + ((double) delta_usec /
360 (double) 1000000);
361 double kbyte_rate;
362 if (time_delta <= 0)
364 time_delta = 0.1;
366 kbyte_rate =
367 ((double) p_sess->transfer_size / time_delta) / (double) 1024;
368 str_append_text(p_str, ", ");
369 str_append_double(p_str, kbyte_rate);
370 str_append_text(p_str, "Kbyte/sec");