- feature: remote TCP logging facility
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
|
||||
|
||||
#include "config.h"
|
||||
//#include "log.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
@@ -30,19 +30,35 @@
|
||||
#include <time.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
//#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
static char const ident[]="$Id$";
|
||||
|
||||
static int log_to_stdout=0;
|
||||
/* module local variables */
|
||||
static int log_to_stderr=0;
|
||||
static int debug_pattern=0;
|
||||
|
||||
static int debug_listen_port=0;
|
||||
static int debug_listen_fd=0;
|
||||
static int debug_fd=0;
|
||||
static char outbuf[512];
|
||||
/*
|
||||
* What shall I log to syslog?
|
||||
* 0 - DEBUGs, INFOs, WARNINGs and ERRORs (this is the default)
|
||||
* 1 - INFOs, WARNINGs and ERRORs
|
||||
* 0 - DEBUGs, INFOs, WARNINGs and ERRORs
|
||||
* 1 - INFOs, WARNINGs and ERRORs (this is the default)
|
||||
* 2 - WARNINGs and ERRORs
|
||||
* 3 - only ERRORs
|
||||
* 4 - absolutely nothing
|
||||
*/
|
||||
static int silence_level=0;
|
||||
static int silence_level=1;
|
||||
|
||||
/*
|
||||
* Mutex for threat synchronization when writing log data
|
||||
@@ -53,18 +69,137 @@ static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void log_set_pattern(int pattern) {
|
||||
debug_pattern=pattern;
|
||||
return;
|
||||
}
|
||||
|
||||
int log_get_pattern(void) {
|
||||
return debug_pattern;
|
||||
}
|
||||
|
||||
void log_set_stdout(int tostdout) {
|
||||
log_to_stdout=tostdout;
|
||||
void log_set_stderr(int tostdout) {
|
||||
log_to_stderr=tostdout;
|
||||
return;
|
||||
}
|
||||
|
||||
void log_set_silence(int level) {
|
||||
silence_level=level;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* TCP logging
|
||||
*/
|
||||
void log_set_listen_port(int port){
|
||||
debug_listen_port = port;
|
||||
log_tcp_listen();
|
||||
return;
|
||||
}
|
||||
|
||||
void log_tcp_listen(void) {
|
||||
struct sockaddr_in my_addr;
|
||||
int sts, on=1;
|
||||
int flags;
|
||||
|
||||
/* disabled in configuration? */
|
||||
if (debug_listen_port == 0) {
|
||||
debug_listen_fd=-1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* ignore SIGPIPE of lost TCP connection */
|
||||
signal (SIGPIPE, SIG_IGN);
|
||||
|
||||
memset(&my_addr, 0, sizeof(my_addr));
|
||||
my_addr.sin_family = AF_INET;
|
||||
my_addr.sin_port = htons(debug_listen_port);
|
||||
|
||||
debug_listen_fd=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
INFO("DEBUG listener on TCP port %i",debug_listen_port);
|
||||
if (debug_listen_fd < 0) {
|
||||
ERROR("socket returned error [%i:%s]",errno, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (setsockopt(debug_listen_fd, SOL_SOCKET, SO_REUSEADDR, &on , sizeof(on)) < 0) {
|
||||
ERROR("socket returned error [%i:%s]",errno, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
sts=bind(debug_listen_fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
|
||||
if (sts != 0) {
|
||||
ERROR("bind returned error [%i:%s]",errno, strerror(errno));
|
||||
close(debug_listen_fd);
|
||||
debug_listen_fd=-1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* set non-blocking */
|
||||
flags = fcntl(debug_listen_fd, F_GETFL);
|
||||
if (flags < 0) {
|
||||
ERROR("fcntl returned error [%i:%s]",errno, strerror(errno));
|
||||
close(debug_listen_fd);
|
||||
debug_listen_fd=-1;
|
||||
return;
|
||||
}
|
||||
if (fcntl(debug_listen_fd, F_SETFL, (long) flags | O_NONBLOCK) < 0) {
|
||||
ERROR("fcntl returned error [%i:%s]",errno, strerror(errno));
|
||||
close(debug_listen_fd);
|
||||
debug_listen_fd=-1;
|
||||
return;
|
||||
}
|
||||
|
||||
listen (debug_listen_fd, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
void log_tcp_connect(void) {
|
||||
int sts;
|
||||
fd_set fdset;
|
||||
struct timeval timeout;
|
||||
int tmpfd;
|
||||
|
||||
if (debug_listen_fd <= 0) return;
|
||||
|
||||
timeout.tv_sec=0;
|
||||
timeout.tv_usec=0;
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET (debug_listen_fd, &fdset);
|
||||
|
||||
sts=select(debug_listen_fd+1, &fdset, NULL, NULL, &timeout);
|
||||
if (sts > 0) {
|
||||
if (debug_fd != 0) {
|
||||
tmpfd=accept(debug_listen_fd, NULL, NULL);
|
||||
close(tmpfd);
|
||||
INFO("Rejected DEBUG TCP connection");
|
||||
} else {
|
||||
debug_fd=accept(debug_listen_fd, NULL, NULL);
|
||||
INFO("Accepted DEBUG TCP connection [fd=%i]", debug_fd);
|
||||
}
|
||||
}
|
||||
|
||||
/* check the TCP connection */
|
||||
if (debug_fd > 0) {
|
||||
timeout.tv_sec=0;
|
||||
timeout.tv_usec=0;
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET (debug_fd, &fdset);
|
||||
|
||||
sts=select(debug_fd+1, &fdset, NULL, NULL, &timeout);
|
||||
if (sts > 0) {
|
||||
char buf[32];
|
||||
sts = recv(debug_fd, buf, sizeof(buf), 0);
|
||||
/* got disconnected? */
|
||||
if (sts == 0) {
|
||||
close(debug_fd);
|
||||
INFO("Disconnected DEBUG TCP connection [fd=%i]", debug_fd);
|
||||
debug_fd=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +215,6 @@ void log_debug(int class, char *file, int line, const char *format, ...) {
|
||||
struct tm *tim;
|
||||
char string[128];
|
||||
|
||||
|
||||
if ((debug_pattern & class) == 0) return;
|
||||
|
||||
va_start(ap, format);
|
||||
@@ -89,7 +223,7 @@ void log_debug(int class, char *file, int line, const char *format, ...) {
|
||||
/*
|
||||
* DEBUG output is either STDOUT or SYSLOG, but not both
|
||||
*/
|
||||
if (log_to_stdout) {
|
||||
if (log_to_stderr) {
|
||||
/* not running as daemon - log to STDERR */
|
||||
time(&t);
|
||||
tim=localtime(&t);
|
||||
@@ -103,6 +237,21 @@ void log_debug(int class, char *file, int line, const char *format, ...) {
|
||||
vsnprintf(string, sizeof(string), format, ap);
|
||||
syslog(LOG_USER|LOG_DEBUG, "%s:%i %s", file, line, string);
|
||||
}
|
||||
/*
|
||||
* Log to TCP
|
||||
*/
|
||||
if (debug_fd > 0) {
|
||||
/* log to TCP socket */
|
||||
time(&t);
|
||||
tim=localtime(&t);
|
||||
snprintf(outbuf, sizeof(outbuf) ,"%2.2i:%2.2i:%2.2i %s:%i ",
|
||||
tim->tm_hour, tim->tm_min, tim->tm_sec, file, line);
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
vsnprintf(outbuf, sizeof(outbuf) , format, ap);
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
snprintf(outbuf, sizeof(outbuf) ,"\n");
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
}
|
||||
pthread_mutex_unlock(&log_mutex);
|
||||
|
||||
va_end(ap);
|
||||
@@ -124,7 +273,7 @@ void log_error(char *file, int line, const char *format, ...) {
|
||||
* INFO, WARN, ERROR output is always to syslog and if not daemonized
|
||||
* st STDOUT as well.
|
||||
*/
|
||||
if (log_to_stdout) {
|
||||
if (log_to_stderr) {
|
||||
/* not running as daemon - log to STDERR */
|
||||
time(&t);
|
||||
tim=localtime(&t);
|
||||
@@ -139,6 +288,21 @@ void log_error(char *file, int line, const char *format, ...) {
|
||||
vsnprintf(string, sizeof(string), format, ap);
|
||||
syslog(LOG_USER|LOG_WARNING, "%s:%i ERROR:%s", file, line, string);
|
||||
}
|
||||
/*
|
||||
* Log to TCP
|
||||
*/
|
||||
if (debug_fd > 0) {
|
||||
/* log to TCP socket */
|
||||
time(&t);
|
||||
tim=localtime(&t);
|
||||
snprintf(outbuf, sizeof(outbuf) ,"%2.2i:%2.2i:%2.2i ERROR:%s:%i ",
|
||||
tim->tm_hour, tim->tm_min, tim->tm_sec, file, line);
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
vsnprintf(outbuf, sizeof(outbuf) , format, ap);
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
snprintf(outbuf, sizeof(outbuf) ,"\n");
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
}
|
||||
pthread_mutex_unlock(&log_mutex);
|
||||
|
||||
va_end(ap);
|
||||
@@ -160,7 +324,7 @@ void log_warn(char *file, int line, const char *format, ...) {
|
||||
* INFO, WARN, ERROR output is always to syslog and if not daemonized
|
||||
* st STDOUT as well.
|
||||
*/
|
||||
if (log_to_stdout) {
|
||||
if (log_to_stderr) {
|
||||
/* not running as daemon - log to STDERR */
|
||||
time(&t);
|
||||
tim=localtime(&t);
|
||||
@@ -175,6 +339,21 @@ void log_warn(char *file, int line, const char *format, ...) {
|
||||
vsnprintf(string, sizeof(string), format, ap);
|
||||
syslog(LOG_USER|LOG_NOTICE, "%s:%i WARNING:%s", file, line, string);
|
||||
}
|
||||
/*
|
||||
* Log to TCP
|
||||
*/
|
||||
if (debug_fd > 0) {
|
||||
/* log to TCP socket */
|
||||
time(&t);
|
||||
tim=localtime(&t);
|
||||
snprintf(outbuf, sizeof(outbuf) ,"%2.2i:%2.2i:%2.2i WARNING:%s:%i ",
|
||||
tim->tm_hour, tim->tm_min, tim->tm_sec, file, line);
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
vsnprintf(outbuf, sizeof(outbuf) , format, ap);
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
snprintf(outbuf, sizeof(outbuf) ,"\n");
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
}
|
||||
pthread_mutex_unlock(&log_mutex);
|
||||
|
||||
va_end(ap);
|
||||
@@ -196,7 +375,7 @@ void log_info(char *file, int line, const char *format, ...) {
|
||||
* INFO, WARN, ERROR output is always to syslog and if not daemonized
|
||||
* st STDOUT as well.
|
||||
*/
|
||||
if (log_to_stdout) {
|
||||
if (log_to_stderr) {
|
||||
/* not running as daemon - log to STDERR */
|
||||
time(&t);
|
||||
tim=localtime(&t);
|
||||
@@ -211,6 +390,21 @@ void log_info(char *file, int line, const char *format, ...) {
|
||||
vsnprintf(string, sizeof(string), format, ap);
|
||||
syslog(LOG_USER|LOG_NOTICE, "%s:%i INFO:%s", file, line, string);
|
||||
}
|
||||
/*
|
||||
* Log to TCP
|
||||
*/
|
||||
if (debug_fd > 0) {
|
||||
/* log to TCP socket */
|
||||
time(&t);
|
||||
tim=localtime(&t);
|
||||
snprintf(outbuf, sizeof(outbuf) ,"%2.2i:%2.2i:%2.2i INFO:%s:%i ",
|
||||
tim->tm_hour, tim->tm_min, tim->tm_sec, file, line);
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
vsnprintf(outbuf, sizeof(outbuf) , format, ap);
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
snprintf(outbuf, sizeof(outbuf) ,"\n");
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
}
|
||||
pthread_mutex_unlock(&log_mutex);
|
||||
|
||||
va_end(ap);
|
||||
@@ -225,10 +419,14 @@ void log_dump_buffer(int class, char *file, int line,
|
||||
char tmp[8], tmplin1[80], tmplin2[80];
|
||||
|
||||
if ((debug_pattern & class) == 0) return;
|
||||
if (!log_to_stdout) return;
|
||||
if ((!log_to_stderr) && (debug_fd <= 0)) return;
|
||||
|
||||
pthread_mutex_lock(&log_mutex);
|
||||
fprintf(stderr,"---BUFFER DUMP follows---\n");
|
||||
if (log_to_stderr) fprintf(stderr, "---BUFFER DUMP follows---\n");
|
||||
if (debug_fd > 0) {
|
||||
snprintf(outbuf, sizeof(outbuf) ,"---BUFFER DUMP follows---\n");
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
}
|
||||
|
||||
for (i=0; i<length; i+=16) {
|
||||
strcpy(tmplin1,"");
|
||||
@@ -239,12 +437,26 @@ void log_dump_buffer(int class, char *file, int line,
|
||||
sprintf(tmp, "%c",(isprint((int)buffer[i+j]))? buffer[i+j]: '.');
|
||||
strcat(tmplin2, tmp);
|
||||
}
|
||||
fprintf(stderr, " %-47.47s %-16.16s\n",tmplin1, tmplin2);
|
||||
if (log_to_stderr) {
|
||||
fprintf(stderr, " %-47.47s %-16.16s\n",tmplin1, tmplin2);
|
||||
}
|
||||
if (debug_fd > 0) {
|
||||
snprintf(outbuf, sizeof(outbuf) ," %-47.47s %-16.16s\n",
|
||||
tmplin1, tmplin2);
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr,"\n---end of BUFFER DUMP---\n");
|
||||
fflush(stderr);
|
||||
if (log_to_stderr) {
|
||||
fprintf(stderr,"\n---end of BUFFER DUMP---\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
if (debug_fd > 0) {
|
||||
snprintf(outbuf, sizeof(outbuf) ,"---end of BUFFER DUMP---\n");
|
||||
write(debug_fd, outbuf, strlen(outbuf));
|
||||
}
|
||||
pthread_mutex_unlock(&log_mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,11 @@
|
||||
|
||||
void log_set_pattern(int pattern);
|
||||
int log_get_pattern(void);
|
||||
void log_set_stdout(int tostdout);
|
||||
void log_set_stderr(int tostdout);
|
||||
void log_set_silence(int level);
|
||||
void log_set_listen_port(int port);
|
||||
void log_tcp_listen(void);
|
||||
void log_tcp_connect(void);
|
||||
|
||||
#undef DEBUG
|
||||
#define DEBUG(F...) log_debug(1,__FILE__, __LINE__,F)
|
||||
|
||||
@@ -144,6 +144,7 @@ static int parse_config (FILE *configfile) {
|
||||
void *dest;
|
||||
} configoptions[] = {
|
||||
{ "debug_level", TYP_INT4, &configuration.debuglevel },
|
||||
{ "debug_port", TYP_INT4, &configuration.debugport },
|
||||
{ "sip_listen_port", TYP_INT4, &configuration.sip_listen_port },
|
||||
{ "daemonize", TYP_INT4, &configuration.daemonize },
|
||||
{ "silence_log", TYP_INT4, &configuration.silence_log },
|
||||
|
||||
+8
-4
@@ -88,7 +88,7 @@ int main (int argc, char *argv[])
|
||||
char *pidfilename=NULL;
|
||||
struct sigaction act;
|
||||
|
||||
log_set_stdout(1);
|
||||
log_set_stderr(1);
|
||||
|
||||
/*
|
||||
* setup signal handlers
|
||||
@@ -191,6 +191,7 @@ int main (int argc, char *argv[])
|
||||
|
||||
/* set debug level as desired */
|
||||
log_set_pattern(configuration.debuglevel);
|
||||
log_set_listen_port(configuration.debugport);
|
||||
|
||||
/* change user and group IDs */
|
||||
secure_enviroment();
|
||||
@@ -202,7 +203,7 @@ int main (int argc, char *argv[])
|
||||
setsid();
|
||||
if (fork()!=0) exit(0);
|
||||
|
||||
log_set_stdout(0);
|
||||
log_set_stderr(0);
|
||||
INFO("daemonized, pid=%i", getpid());
|
||||
}
|
||||
|
||||
@@ -255,11 +256,14 @@ int main (int argc, char *argv[])
|
||||
*/
|
||||
while (!exit_program) {
|
||||
|
||||
DEBUGC(DBCLASS_BABBLE,"going into sip_wait\n");
|
||||
DEBUGC(DBCLASS_BABBLE,"going into sipsock_wait\n");
|
||||
while (sipsock_wait()<=0) {
|
||||
/* got no input, here by timeout. do aging */
|
||||
register_agemap();
|
||||
|
||||
/* TCP log: check for a connection */
|
||||
log_tcp_connect();
|
||||
|
||||
/* dump memory stats if requested to do so */
|
||||
if (dmalloc_dump) {
|
||||
dmalloc_dump=0;
|
||||
@@ -276,7 +280,7 @@ int main (int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* got input, process */
|
||||
DEBUGC(DBCLASS_BABBLE,"back from sip_wait");
|
||||
DEBUGC(DBCLASS_BABBLE,"back from sipsock_wait");
|
||||
|
||||
i=sipsock_read(&buff, sizeof(buff)-1, &ticket.from, &ticket.protocol);
|
||||
buff[i]='\0';
|
||||
|
||||
@@ -57,6 +57,7 @@ typedef struct {
|
||||
*/
|
||||
struct siproxd_config {
|
||||
int debuglevel;
|
||||
int debugport;
|
||||
char *inbound_if;
|
||||
char *outbound_if;
|
||||
int sip_listen_port;
|
||||
|
||||
+2
-2
@@ -68,7 +68,7 @@ int sipsock_listen (void) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for incoming SIP message. After a 5 sec timeout
|
||||
* Wait for incoming SIP message. After a 2 sec timeout
|
||||
* this function returns with sts=0
|
||||
*
|
||||
* RETURNS >0 if data received, =0 if nothing received /T/O), -1 on error
|
||||
@@ -78,7 +78,7 @@ int sipsock_wait(void) {
|
||||
fd_set fdset;
|
||||
struct timeval timeout;
|
||||
|
||||
timeout.tv_sec=5;
|
||||
timeout.tv_sec=2;
|
||||
timeout.tv_usec=0;
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
|
||||
Reference in New Issue
Block a user