/* * Internal wrapper function which must be called for _all_ output * to the log file. It takes care of opening the log file if it * isn't open, buffering data if it's in the process of being * opened asynchronously, etc. */ static void logwrite(struct LogContext *ctx, void *data, int len) { /* * In state L_CLOSED, we call logfopen, which will set the state * to one of L_OPENING, L_OPEN or L_ERROR. Hence we process all of * those three _after_ processing L_CLOSED. */ if (ctx->state == L_CLOSED) logfopen(ctx); if (ctx->state == L_OPENING) { bufchain_add(&ctx->queue, data, len); } else if (ctx->state == L_OPEN) { assert(ctx->lgfp); #ifdef PERSOPORT if( !get_param("PUTTY") ) { if( timestamp_switch ) { log_writetimestamp( ctx ) ; timestamp_switch = 0 ; } char * c = (char*)(data+len-1) ; if( c[0]=='\n' ) timestamp_switch = 1 ; } #endif if (fwrite(data, 1, len, ctx->lgfp) < (size_t)len) { logfclose(ctx); ctx->state = L_ERROR; /* Log state is L_ERROR so this won't cause a loop */ logevent(ctx->frontend, "Disabled writing session log due to error while writing"); } } /* else L_ERROR, so ignore the write */ }
/* * Log an SSH packet. */ void log_packet(void *handle, int direction, int type, char *texttype, void *data, int len) { struct LogContext *ctx = (struct LogContext *)handle; int i, j; char dumpdata[80], smalldata[5]; if (ctx->cfg.logtype != LGTYP_PACKETS) return; if (!ctx->lgfp) logfopen(ctx); if (ctx->lgfp) { fprintf(ctx->lgfp, "%s packet type %d / 0x%02x (%s)\r\n", direction == PKT_INCOMING ? "Incoming" : "Outgoing", type, type, texttype); for (i = 0; i < len; i += 16) { sprintf(dumpdata, " %08x%*s\r\n", i, 1+3*16+2+16, ""); for (j = 0; j < 16 && i+j < len; j++) { int c = ((unsigned char *)data)[i+j]; sprintf(smalldata, "%02x", c); dumpdata[10+2+3*j] = smalldata[0]; dumpdata[10+2+3*j+1] = smalldata[1]; dumpdata[10+1+3*16+2+j] = (isprint(c) ? c : '.'); } strcpy(dumpdata + 10+1+3*16+2+j, "\r\n"); fputs(dumpdata, ctx->lgfp); } fflush(ctx->lgfp); } }
void log_restart(void *handle, Config *cfg) { struct LogContext *ctx = (struct LogContext *)handle; logfclose(ctx); ctx->cfg = *cfg; /* STRUCTURE COPY */ ctx->cfg.logtype = LGTYP_ASCII; logfopen(ctx); }
/* * Log session traffic. */ void logtraffic(void *handle, unsigned char c, int logmode) { struct LogContext *ctx = (struct LogContext *)handle; if (ctx->cfg.logtype > 0) { if (ctx->cfg.logtype == logmode) { /* deferred open file from pgm start? */ if (!ctx->lgfp) logfopen(ctx); if (ctx->lgfp) fputc(c, ctx->lgfp); } } }
/* * Log an Event Log entry. Used in SSH packet logging mode; this is * also as convenient a place as any to put the output of Event Log * entries to stderr when a command-line tool is in verbose mode. * (In particular, this is a better place to put it than in the * front ends, because it only has to be done once for all * platforms. Platforms which don't have a meaningful stderr can * just avoid defining FLAG_STDERR. */ void log_eventlog(void *handle, const char *event) { struct LogContext *ctx = (struct LogContext *)handle; if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) { fprintf(stderr, "%s\n", event); fflush(stderr); } if (ctx->cfg.logtype != LGTYP_PACKETS) return; if (!ctx->lgfp) logfopen(ctx); if (ctx->lgfp) fprintf(ctx->lgfp, "Event Log: %s\r\n", event); }
/* * Internal wrapper function which must be called for _all_ output * to the log file. It takes care of opening the log file if it * isn't open, buffering data if it's in the process of being * opened asynchronously, etc. */ static void logwrite(struct LogContext *ctx, void *data, int len) { /* * In state L_CLOSED, we call logfopen, which will set the state * to one of L_OPENING, L_OPEN or L_ERROR. Hence we process all of * those three _after_ processing L_CLOSED. */ if (ctx->state == L_CLOSED) logfopen(ctx); if (ctx->state == L_OPENING) { bufchain_add(&ctx->queue, data, len); } else if (ctx->state == L_OPEN) { assert(ctx->lgfp); fwrite(data, 1, len, ctx->lgfp); } /* else L_ERROR, so ignore the write */ }
void log_reconfig(void *handle, Config *cfg) { struct LogContext *ctx = (struct LogContext *)handle; int reset_logging; if (!filename_equal(ctx->cfg.logfilename, cfg->logfilename) || ctx->cfg.logtype != cfg->logtype) reset_logging = TRUE; else reset_logging = FALSE; if (reset_logging) logfclose(ctx); ctx->cfg = *cfg; /* STRUCTURE COPY */ if (reset_logging) logfopen(ctx); }
/* * Internal wrapper function which must be called for _all_ output * to the log file. It takes care of opening the log file if it * isn't open, buffering data if it's in the process of being * opened asynchronously, etc. */ static void logwrite(struct LogContext *ctx, void *data, int len) { /* * In state L_CLOSED, we call logfopen, which will set the state * to one of L_OPENING, L_OPEN or L_ERROR. Hence we process all of * those three _after_ processing L_CLOSED. */ if (ctx->state == L_CLOSED) logfopen(ctx); if (ctx->state == L_OPENING) { bufchain_add(&ctx->queue, data, len); } else if (ctx->state == L_OPEN) { assert(ctx->lgfp); if (fwrite(data, 1, len, ctx->lgfp) < len) { logfclose(ctx); ctx->state = L_ERROR; /* Log state is L_ERROR so this won't cause a loop */ logevent(ctx->frontend, "Disabled writing session log due to error while writing"); } } /* else L_ERROR, so ignore the write */ }
void log_reconfig(void *handle, Conf *conf) { struct LogContext *ctx = (struct LogContext *)handle; int reset_logging; if (!filename_equal(conf_get_filename(ctx->conf, CONF_logfilename), conf_get_filename(conf, CONF_logfilename)) || conf_get_int(ctx->conf, CONF_logtype) != conf_get_int(conf, CONF_logtype)) reset_logging = TRUE; else reset_logging = FALSE; if (reset_logging) logfclose(ctx); conf_free(ctx->conf); ctx->conf = conf_copy(conf); ctx->logtype = conf_get_int(ctx->conf, CONF_logtype); if (reset_logging) logfopen(ctx); }