/**************************************************************************
* vhsyslogd.c
**************************************************************************
* $Date: 2001/04/17 16:36:24 $
* $Revision: 1.1 $
**************************************************************************
*
* vhsyslogd daemon.
*
* reads the following sources:
*
* a TCP listen/accept socket.
* a static list of UDP ports (up to MAX_UDP).
* a static list of AF_LOCAL sockets. (up to MAX_UNIX).
*
* writes to the following consumers:
*
* VHLOGFILE.
*
* VHLOGFILE rolls over after MAX_LOGFILE_SIZE.
* This code supports a remote monitor via TCP.
*
* Here is the current calling tree for each source
* (note: '>' means fork() ):
*
* main()
* ---------
* |
* |
vhsyslogd()
*
>----------
* | |
* | | service_tcp_accepts()
* exit fg |
>--------------------
* ---------
|
|
*
|
| accept()
*
|
----------
*
|
|
*
|
| handle_tcp_input()
*
|
--------------------
*
| handle_udp_input()
*
>------------------
*
|
*
| handle_unix_input()
*
----------------------
*
*
* Revision History
*
who
when
what
*
---
----
----
*
martinj991@home.com
19/04/01 chmod
/dev/log after opening.
*
martinj991@home.com
26/02/01 started.
*
* $Log: vhsyslogd.c,v $
* Revision 1.1
2001/04/17 16:36:24 root
* Initial revision
*
*************************************************************************/
#include "version.cpp"
#include "vhsyslog.h"
#include <paths.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/un.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define _GNU_SOURCE
#include <getopt.h>
/* log file sources
*/
#define INTERNAL 2
#define SYSLOG 1
#define REMOTE 0
int
debug = 0;
int
do_fork = 1;
/* defined in getopt
*/
extern char *optarg;
extern int optind, opterr, optopt;
/* list of active tcp buffers */
tcp_buffer_t *TcpBuffers = (tcp_buffer_t *) NULL;
/* VHheader
*/
vhsyslog_msg_t *VHmsg;
/* UNIX sockets to listen on */
char
*UNIX_SOCKNAMES[MAX_UNIX*PATH_FILENAME_MAX];
int UNIX_DESCRIPTORS[MAX_UNIX];
struct sockaddr_un UNIX_SOCKETS[MAX_UNIX];
/* TCP port to listen on */
int TCP_PORT;
int iVHsyslogTCP = -1;
struct sockaddr_in sVHsyslogTCP;
int
sndrcv_buffers = SNDRCV_BUFFERS;
char
xlen[LEN_TAG+1];
int
MAX_TCP_HANDLERS = 1; /* -T switch */
int
MAX_UDP_HANDLERS = 1; /* -U switch */
int
I_AM_TCP = 0; /* handler
*/
int
I_AM_UDP = 0; /* type */
/* UDP ports to listen on */
int
UDP_PORTS[MAX_UDP];
int
UDP_DESCRIPTORS[MAX_UDP];
struct sockaddr_in UDP_SOCKETS[MAX_UDP];
int
active_UDP_fds = 0;
/* run time stats
*/
vhsyslogd_stats_t *rtStats;
int shmkey = vhsyslogSHM;
int
shmid = -1;
void
*rtShmem = (void *)0;
/* local system info
*/
struct utsname MyUTSname;
struct hostent *host;
char
MyIP[TINYSTRING];
char
sSource[PATH_FILENAME_MAX];
char
*proc_name;
/* TCP remote peer info
*/
char
peerIP[TINYSTRING];
char
peerPort[TINYSTRING];
/* used to log local messages */
char
INT_MSG[MSGSIZE];
char
StartupMsg[MEDIUMSTRING];
/* files
*/
int fpLogFileOut = -1;
FILE *fpLastWrite;
struct stat stbuf;
char
BufferFile[PATH_FILENAME_MAX];
char
BaseName[PATH_FILENAME_MAX];
/* BufferFIle LOCK token */
char
LOCKtoken[PATH_FILENAME_MAX];
int
fdLOCK = -1;
int
lock_timeout = 0;
int CurrentFile = 0;
long
MaxBufferSize = 0.00;
/* list of ready unix/udp fd's */
fd_set readfds_base, readfds;
fd_set writefds_base, writefds;
fd_set exceptfds_base, exceptfds;
/* list of ready tcp fd's */
fd_set TCPreadfds_base, TCPreadfds;
fd_set TCPwritefds_base, TCPwritefds;
fd_set TCPexceptfds_base, TCPexceptfds;
/* max fd
*/
int
maxfd = -1;
/* UNIX/UDP select timeouts */
struct timeval input_timeout_base, input_timeout;
/* TCP select timout
*/
struct timeval TCPinput_timeout_base, TCPinput_timeout;
/* global flags
*/
int tcp_connected =
0;
int iInit
= 1; /* cleared in init_server */
int parentPID = 0; /*
daemon PID
*/
int tcpPID
= 0; /* tcp listener PID */
int udpPID
= 0; /* udp listener PID */
int VERBOSE = 0; /*
log more info/events
*/
/* prototypes
*/
int decode_args(int,
char **);
int init_server(int,
char **);
int open_log();
int open_unix(void);
int open_udp(void);
int open_tcp(void);
int handle_unix_input(void);
int handle_udp_input(void);
int handle_tcp_input();
int has_input(int);
int
allocate_tcp_buffer(int);
int
deallocate_tcp_buffer(int);
int
get_msg_len(int );
vhsyslog_msg_t *ParseVHsyslogMsg(char *);
void
vhgetpeername(int);
int tag_msg (char
*, char *, int);
int get_current_buffer(void);
char
*vhsyslog_getdate(int);
int
vhsyslogd(void);
int
fork2(void);
int
update_BUFPTRS(void);
int send_to_log(char
*, int);
int split_log(void);
void
log_internal(int, char
*);
int
log_err(int, char
*);
int
lock_BufferFile(int);
int service_tcp_accepts();
void
record_rtStats(int, long);
int
send_rtStats(int);
void
spin(long, int,
int);
void
beep(int);
char
*strrmc(char *,int);
char
*find_proc( char *);
void
VHshutdown();
void
sigpipe(int);
void
sigdie(int);
/*************************************************************************/
/**************************************************************************
* main
*
* log message reciever
*
* returns: -1 if a fatal error occurred.
*
* Revision History
*
who
when
what
*
---
----
----
*
*************************************************************************/
int
main(int argc, char *argv[] ) {
/**************************************************************************/
/* init sockets, logs, etc.... */
if( init_server(argc, argv ) == -1 )
VHshutdown();
if( do_fork) {
/* de-associate
the users control terminal with the daemon */
setpgrp();
switch(
fork() ) {
case 0: /* daemon code comes here */
parentPID = getpid();
vhsyslogd();
break;
case -1:
snprintf(INT_MSG,MSGSIZE,"%s:%d fork() \n%s\n",
__FILE__,__LINE__,strerror(errno));
VHshutdown();
break;
default:
exit(0); /* fg exit */
}/* switch */
}
if( !do_fork) {
parentPID = getpid();
vhsyslogd();
}
/* we should never get here */
snprintf(INT_MSG,MSGSIZE,"%s:%d
[%d] exiting at bottom of main()\n",
__FILE__,__LINE__, getpid() );
VHshutdown();
exit(-1);
}/**************************
end of main *******************************/
/***********************************************************************
* vhsyslogd
*
* waits for syslog messages
* writes them to BufferFile.
*
*
* returns: -1 if a fatal error
occurred.
*
* Revision History
* who
when
what
* ---
----
----
*
**********************************************************************/
int
vhsyslogd() {
int
uidx = 0;
/*********************************************************************/
/* TT 236: TCP input streams drop
almost all messages.
seperate UDP, UNIX and TCP processing into three
threads.
Increase system runtime parameter fs.file-max to
16384 using sysctl.
*/
/* fork TCP handlers
*/
fprintf(stdout,"vhsyslogd pid is:
[%d]\n", parentPID);
while( MAX_TCP_HANDLERS--) {
switch (fork2()) { /*
vhsyslog_common.c */
case 0:
tcpPID=getpid();
(void) service_tcp_accepts();
VHshutdown();
break;
case -1: snprintf(INT_MSG,MSGSIZE,"%s:%d
fork2(tcp)\n %s. Exiting.\n",
__FILE__,__LINE__,strerror(errno));
VHshutdown();
break;
default: break;
}
}
/* TT 236 UDP input streams drop
msgs */
/* fork UDP handlers
*/
while( MAX_UDP_HANDLERS--) {
switch (fork2()) { /*
vhsyslog_common.c */
case 0:
udpPID=getpid();
(void) handle_udp_input();
VHshutdown();
break;
case -1: snprintf(INT_MSG,MSGSIZE,"%s:%d
fork2(udp)\n %s. Exiting.\n",
__FILE__,__LINE__,strerror(errno));
VHshutdown();
break;
default: break;
}
}
/* get rid of any inherited UDP/TCP
descriptors */
for(
uidx=0; uidx<=MAX_UDP; uidx++) {
if(
UDP_DESCRIPTORS[uidx] == -1) break;
close(UDP_DESCRIPTORS[uidx]);
FD_CLR(UDP_DESCRIPTORS[uidx],
&readfds_base);
}
close(iVHsyslogTCP);
FD_CLR(iVHsyslogTCP, &readfds_base);
/* handle UNIX
*/
while(1) {
/* service AF_LOCAL sockets */
if( handle_unix_input() == -1 )
VHshutdown();
readfds = readfds_base;
input_timeout = input_timeout_base;
switch( select(maxfd+1, &readfds,
NULL, NULL, &input_timeout) ) {
case 0: /* no
fd's ready */
break;
case -1: /* fatal
*/
snprintf(INT_MSG,MSGSIZE,"%s:%d \nselect(readfds)\n %s.
Exiting.\n",
__FILE__,__LINE__,strerror(errno));
VHshutdown();
break;
default:
break; /* input ready */
} /* switch */
} /* while */
return(0);
}/************************
end of vhsyslogd *******************************/
/**************************************************************************
* service_tcp_accepts
*
* accepts a ready fd from listen
socket.
* instantiates an accept descriptor
and
* adds it to the ready list.
*
* returns: -1 if a fatal error
occurred.
*
* Revision History
* who
when
what
* ---
---- ----
*
*************************************************************************/
int
service_tcp_accepts() {
int accept_socket = -1;
int len
= 0;
int uidx
= 0;
/*************************************************************************/
/* get rid of any inherited UNIX/UDP
descriptors */
for( uidx=0; uidx<=MAX_UDP; uidx++) {
if( UDP_PORTS[uidx] == -1) break;
close(UDP_DESCRIPTORS[uidx]);
FD_CLR(UDP_DESCRIPTORS[uidx],
&readfds_base);
}
for( uidx=0; uidx<=MAX_UNIX; uidx++)
{
if( UNIX_DESCRIPTORS[uidx] == -1) break;
close(UNIX_DESCRIPTORS[uidx]);
FD_CLR(UNIX_DESCRIPTORS[uidx], &readfds_base);
}
fprintf(stdout,"vhsyslogd TCP pid is: [%d]\n", tcpPID);
strcpy(proc_name,"vhsyslogd_TCP");
I_AM_TCP = 1;
if( shmid != -1)
rtStats->active_tcp_servers++;
while(1) {
/* check for new connections */
readfds = readfds_base;
input_timeout = input_timeout_base;
switch( select(maxfd+1, &readfds,
NULL, NULL, &input_timeout) ) {
case 0: /* no
fd's ready */
break;
case -1: /* fatal
*/
snprintf(INT_MSG,MSGSIZE,
"%s:%d [%d]\nselect(readfds)\n %s.
Exiting.\n",
__FILE__,__LINE__,getpid(),strerror(errno));
VHshutdown();
break;
default:
/* TCP listen socket is ready */
if( FD_ISSET(iVHsyslogTCP, &readfds) ) {
len = sizeof(sVHsyslogTCP);
accept_socket = accept(iVHsyslogTCP,
(struct sockaddr *) &sVHsyslogTCP,
&len);
if( accept_socket == -1) {
snprintf(INT_MSG,MSGSIZE,
"%s:%d [%d] TCP accept(%d)\n%s.",
__FILE__,__LINE__, getpid(),
VHSYSLOGD_TCP,strerror(errno));
log_internal(VHINFO,INT_MSG);
if( !do_fork) fprintf(stderr,"%s",INT_MSG);
close(accept_socket);
if( shmid != -1)
rtStats->tcp_connect_err++;
/* return(-1); */
}
else {
/* allocate a buffer for the connected
client */
if( allocate_tcp_buffer(accept_socket)
== -1)
return(-1);
/* add the accept descriptor to the ready
list */
FD_SET(accept_socket, &TCPreadfds_base);
if( accept_socket > maxfd) maxfd = accept_socket;
if( VERBOSE) {
vhgetpeername(accept_socket);
snprintf(INT_MSG,MSGSIZE,
"%s: [%d] accept from %s.%s\n",__FILE__,
getpid(), peerIP, peerPort );
log_internal(VHINFO,INT_MSG);
}
/* update rtStats
*/
if( shmid != -1) {
rtStats->active_tcp_users++;
}
}
}
break;
} /* switch */
/* service existing clients */
if( handle_tcp_input() == -1 )
VHshutdown();
} /* while(1)
*/
return(0);
}/***********************
end of service_tcp_accepts ***********************/
/**************************************************************************
* handle_tcp_input
*
* read from a TCP descriptor.
* write to TcpBuffers/BufferFile.
*
* returns: -1 if a fatal error occurred.
*
* Revision History
*
who
when
what
*
---
----
----
*
jeffm
13/03/01 added
TcpBuffers.
*
jeffm
07/03/01 got rid of
vhsyslog_msg_t.
* added
xlen prefix read.
*
jeffm
21/01/01 started.
*
*************************************************************************/
int
handle_tcp_input() {
int
tcp_fd
= 0;
int
read_bytes = -1;
int
status
= -1;
int
len = 0;
int
CLIENT_EXITED = 0;
int
FOUND_BUFFER =
0; /*
fd has buffer allocated */
char
buf[MSGSIZE];
char
FullMsg[MSGSIZE];
tcp_buffer_t *current;
/************************************************************************/
/* get TCP fd ready status */
TCPreadfds = TCPreadfds_base;
TCPinput_timeout = TCPinput_timeout_base;
status = select(maxfd+1, &TCPreadfds, NULL, NULL, &TCPinput_timeout);
switch( status ) {
case 0:
return(0);
break;
case -1:
snprintf(INT_MSG,MSGSIZE,"%s:%d TCP select() \n%s
\nExiting.\n",
__FILE__,__LINE__,
strerror(errno));
log_internal(VHFATAL,INT_MSG);
if( !do_fork) fprintf(stderr,"%s",INT_MSG);
return(-1);
break;
default:
break;
}
for( tcp_fd=0; tcp_fd<=maxfd; tcp_fd++) {
if( FD_ISSET(tcp_fd,&TCPreadfds)) {
CLIENT_EXITED = 0;
FOUND_BUFFER = 0;
/*
get the client IP address
*/
vhgetpeername(tcp_fd);
/*
look up the tcp buffer
*/
current = TcpBuffers;
while(
current ) {
if( current->fd == tcp_fd ) {
FOUND_BUFFER = 1;
/* new msg, get the msg len or query cmd */
if( current->len == -999 ) {
switch( (len = get_msg_len(tcp_fd)) ) {
case 0:
CLIENT_EXITED = 1;
break;
case -1:
return(-1);
default:
current->len = len;
strncat(current->buffer,xlen,LEN_TAG);
record_rtStats(3,
len+LEN_TAG );
break;
}
}
break;
} /* if( current->fd == tcp_fd )
*/
current=current->next;
} /* while(
current ) */
if(
CLIENT_EXITED )
continue;
if(
!FOUND_BUFFER ) {
snprintf(INT_MSG,MSGSIZE,
"%s:%d TCP client %s.%s has no buffer allocated. "
"Message ignored.\n",
__FILE__,__LINE__,peerIP,peerPort);
log_internal(VHINFO,INT_MSG);
if( !do_fork) fprintf(stderr,"%s",INT_MSG);
if( shmid != -1)
rtStats->tcp_data_err++;
continue;
}
/*
stream data
*/
if(
current->len > 0) {
memset(buf, (char ) '\0', MSGSIZE);
read_bytes = recv(tcp_fd, buf, current->len, 0);
if( read_bytes == -1) {
snprintf(INT_MSG,MSGSIZE,
"%s:%d Can't read TCP message from %s.%s \n%s\n",
__FILE__,__LINE__,peerIP,peerPort,strerror(errno));
log_internal(VHINFO,INT_MSG);
if( !do_fork) fprintf(stderr,"%s",INT_MSG);
deallocate_tcp_buffer(tcp_fd);
if( shmid != -1)
rtStats->tcp_data_err++;
continue;
}
/* client exited
*/
if( read_bytes == 0 ) {
deallocate_tcp_buffer(tcp_fd);
if( VERBOSE ) {
snprintf(INT_MSG,MSGSIZE,"%s:%s has exited.\n",
peerIP,peerPort);
log_internal(VHINFO,INT_MSG);
if( !do_fork)
fprintf(stderr,"%s",INT_MSG);
}
continue;
}
if( debug && !do_fork && VERBOSE )
printf("TCP DATA: bytes: %d\n<%s>\n",strlen(buf),buf);
strncat(current->buffer,buf,read_bytes);
current->len -= read_bytes;
if( current->len <= 0 ) {
if( debug && !do_fork) {
fprintf(stdout,"[%d] got TCP msg from: %s:%s, "
"bytes:
%06d\n",
getpid(),peerIP,peerPort,
strlen(current->buffer));
}
if( debug && !do_fork &&
VERBOSE)
fprintf(stdout,"\n<%s>\n",current->buffer);
/* make sure message ends in <LF> */
if(
current->buffer[strlen(current->buffer)-1] != '\n' ) {
current->buffer[strlen(current->buffer)] = '\n';
}
/* write the msg to the buffer file */
if(
tag_msg(FullMsg,current->buffer,REMOTE) == -1)
return(-1);
if( send_to_log(FullMsg, 0) == -1)
return(-1);
/* init buffer for next message */
memset(current->buffer, (char ) '\0',
MSGSIZE);
current->len = -999;
} /* if( current->len <= 0 )
*/
} /* if( current->len > 0)
*/
} /* if(
FD_ISSET(tcp_fd,&TCPreadfds))
*/
} /* for( tcp_fd=0; tcp_fd<=maxfd; fd_idx++) */
return(0);
}/****************
handle_tcp_input **************************************/
/*************************************************************************
* allocate_tcp_buffer
*
* allocate and link a node to the end
of TcpBuffers
*
* Revision History
* who
when
what
* ---
----
----
*
*************************************************************************/
int
allocate_tcp_buffer(tcp_fd) {
tcp_buffer_t *NewTcpBuffer, *head, *bottom;
/************************************************************************/
/* allocate a node for the tcp_buffer
list */
if( !(NewTcpBuffer = (tcp_buffer_t *)
calloc(1, sizeof(tcp_buffer_t)))) {
snprintf(INT_MSG,MSGSIZE,
"%s:%d [%d] Can't calloc %d bytes for tcp_buffer. "
"%s \nExiting.\n",
__FILE__,__LINE__,getpid(),sizeof(tcp_buffer_t),
strerror(errno) );
log_internal(VHFATAL,INT_MSG);
if( !do_fork) fprintf(stderr,"%s",INT_MSG);
return(-1);
}
/* init the new node
*/
NewTcpBuffer->len = -999;
NewTcpBuffer->fd =
tcp_fd;
NewTcpBuffer->next = (tcp_buffer_t *) NULL;
/* init the head
*/
if( !TcpBuffers) {
TcpBuffers = NewTcpBuffer;
TcpBuffers->next =
(tcp_buffer_t *) NULL;
}
else {
/*
add the new node to the bottom
*/
bottom = TcpBuffers;
while(
bottom) {
if( bottom->next == (tcp_buffer_t *) NULL) {
bottom->next =
NewTcpBuffer;
break;
}
bottom =
bottom->next;
}
}
if( !do_fork && debug &&
VERBOSE ) {
printf("\ncurrent buffer list:
\n");
head = TcpBuffers;
while(
head) {
printf("buffer: %d \n",head->fd);
head=head->next;
}
}
return(0);
}/************** end of
allocate_tcp_buffer ****************************/
/*************************************************************************
* deallocate_tcp_buffer
*
* deallocate and unlink a node in
TcpBuffers
*
* Revision History
* who
when
what
* ---
----
----
*
*************************************************************************/
int
deallocate_tcp_buffer(tcp_fd) {
tcp_buffer_t *head, *previous_node;
/************************************************************************/
FD_CLR(tcp_fd, &TCPreadfds_base);
close(tcp_fd);
head = TcpBuffers;
previous_node = (tcp_buffer_t *) NULL;
while( head ) {
if( head->fd == tcp_fd) {
/* unlink a node in the middle */
if( previous_node ) {
previous_node->next = head->next;
free(head);
head = (tcp_buffer_t *) NULL;
break;
}
/* unlink the first or last node */
else {
TcpBuffers = head->next;
free(head);
head = (tcp_buffer_t *) NULL;
break;
}
}
previous_node = head;
head = head->next;
}
/* runtime counters
*/
if( shmid != -1) {
rtStats->active_tcp_users--;
}
if( !do_fork && debug &&
VERBOSE ) {
printf("\ncurrent buffer
list: \n");
previous_node = TcpBuffers;
while(
previous_node) {
printf("buffer: %d\n",previous_node->fd);
previous_node = previous_node->next;
}
}
return(0);
} /***************** end
of deallocate_tcp_buffer ************************/
/*************************************************************************
* get_msg_len
*
* get the msg length or status query.
*
* returns:
* >0 message
length.
*
* 0 the client
exited, issused an invalid length/header or
*
issued a status query.
*
* -1 a fatal error
occurred.
*
* Revision History
* who
when
what
* ---
----
----
*
*************************************************************************/
int
get_msg_len(int
tcp_fd) {
int read_bytes = -1;
char
slen[LEN_TAG+1];
int len = 0;
int counter = 0;
int counter2 = 0;
/***********************************************************************/
memset(xlen, (char ) '\0', LEN_TAG);
read_bytes =
read(tcp_fd, xlen, LEN_TAG);
if(
debug && !do_fork && VERBOSE )
printf("TCP LEN: bytes: %d\n<%s>\n",strlen(xlen),xlen);
/*
client exited */
if(
read_bytes == 0 ) {
deallocate_tcp_buffer(tcp_fd);
if( VERBOSE ) {
snprintf(INT_MSG,MSGSIZE,"%s:%s has exited.\n",
peerIP,peerPort);
log_internal(VHINFO,INT_MSG);
}
return(0);
}
if(
read_bytes == -1 ) {
snprintf(INT_MSG,MSGSIZE,"\r%s:%d %s \nCan't get msg length from
"
"%s:%s.\n<%s>\nIgnoring.\n",
__FILE__,__LINE__,
vhsyslog_getdate(1),peerIP,peerPort,strerror(errno));
log_internal(VHINFO,INT_MSG);
if( !do_fork) fprintf(stderr,"%s",INT_MSG);
/* TT 752 ignored return values
*/
(void)
send(tcp_fd,INT_MSG,strlen(INT_MSG),0);
deallocate_tcp_buffer(tcp_fd);
if( shmid != -1)
rtStats->tcp_data_err++;
return(0);
}
/*
service status query
*/
if(
!strncasecmp(xlen,"%%%status$$$",LEN_TAG) ) {
if( send_rtStats(tcp_fd) == -1)
return(-1);
return(0);
}
/*
validate the message header
*/
if(
strncmp(xlen, "LEN=", 4)) {
snprintf(INT_MSG,MSGSIZE,"%s:%d %s\nInvalid header from "
"%s:%s:\n <%s> \nIgnoring.\n",
__FILE__,__LINE__,
vhsyslog_getdate(1),peerIP,peerPort,xlen);
log_internal(VHINFO,INT_MSG);
if( !do_fork) fprintf(stderr,"%s",INT_MSG);
/* TT 752 ignored return values
*/
(void)
send(tcp_fd,INT_MSG,strlen(INT_MSG),0);
deallocate_tcp_buffer(tcp_fd);
if( shmid != -1)
rtStats->tcp_data_err++;
return(0);
}
/*
parse the msg length
*/
counter2 = 0;
for(
counter=4; counter<=9; counter++)
slen[counter2++] = xlen[counter];
/*
compute number of bytes remaining
*/
len = atoi(slen) -
LEN_TAG;
/*
check len
*/
if(
len > MSGSIZE || len <= 0 ){
snprintf(INT_MSG,MSGSIZE,
"%s:%d %s\nInvalid msg length (%s) from %s:%s\n"
"Ignoring.\n",
__FILE__,__LINE__,vhsyslog_getdate(1),
slen,peerIP,peerPort);
log_internal(VHINFO,INT_MSG);
if( !do_fork)
fprintf(stderr,"\r%s",INT_MSG);
deallocate_tcp_buffer(tcp_fd);
if( shmid != -1)
rtStats->tcp_data_err++;
snprintf(INT_MSG,MSGSIZE,"%s:%s has exited.\n",
peerIP,peerPort);
log_internal(VHINFO,INT_MSG);
if( !do_fork) fprintf(stderr,"%s",INT_MSG);
return(0);
}
return(len);
} /**********************
end of get_msg_len ***************************/
/*************************************************************************
* vhgetpeername
*
* populate global peerIP and peerPort.
*
* Revision History
* who
when
what
* ---
----
----
*
*************************************************************************/
void
vhgetpeername(socketFD) {
int
len;
/************************************************************************/
peerIP[0] = (char ) '\0';
peerPort[0] = (char ) '\0';
len
= sizeof(sVHsyslogTCP);
/*
get the client address
*/
if(
getpeername(socketFD,
(struct sockaddr *)
&sVHsyslogTCP,&len) == -1) {
snprintf(peerIP,TINYSTRING,"TCP getpeername failed");
snprintf(peerPort,TINYSTRING,"0000");
snprintf(INT_MSG,MSGSIZE,"%s:%d [%d] can't get peer name of "
"connected TCP client\n",
__FILE__,__LINE__,getpid() );
log_internal(VHINFO,INT_MSG);
if(
!do_fork) fprintf(stderr,"%s",INT_MSG);
}
else
{
snprintf(peerIP,TINYSTRING,"%s",(char
*) inet_ntoa(sVHsyslogTCP.sin_addr));
snprintf(peerPort,TINYSTRING,"%d",ntohs(sVHsyslogTCP.sin_port));
}
return;
} /***************** end
of vhgetpeername *******************************/
/**************************************************************************
* handle_unix_input
*
* reads from a list of local AF_LOCAL sockets.
* writes to VHLOGFILE
*
* returns: -1 if a fatal error occurred.
*
* Revision History
*
who
when
what
*
---
----
----
*
*************************************************************************/
int
handle_unix_input() {
int unix_idx = 0;
int read_bytes = -1;
int len = 0;
char buf[MSGSIZE];
char FullMsg[MSGSIZE];
/************************************************************************/
for(
unix_idx=0; unix_idx<=MAX_UNIX; unix_idx++) {
if( UNIX_DESCRIPTORS[unix_idx] == -1) break;
if(
FD_ISSET(UNIX_DESCRIPTORS[unix_idx],&readfds)) {
/* read the AF_LOCAL msg */
len = sizeof(UNIX_SOCKETS[unix_idx]);
/* unconnected method
read_bytes = recvfrom(UNIX_DESCRIPTORS[unix_idx],buf,MSGSIZE,0,
(struct sockaddr *) &UNIX_SOCKETS[unix_idx],
&len);
*/
read_bytes = recv(UNIX_DESCRIPTORS[unix_idx],buf,MSGSIZE,0);
buf[read_bytes] = (char ) '\0';
if( read_bytes == -1) {
snprintf(INT_MSG,MSGSIZE,"%s:%d
recv(%s)\n%s\nExiting.\n",__FILE__,__LINE__,
UNIX_SOCKNAMES[unix_idx],strerror(errno));
log_internal(VHFATAL,INT_MSG);
if(
!do_fork) fprintf(stderr,"%s",INT_MSG);
return(-1);
}
sSource[0] = (char
) '\0';
snprintf(sSource,PATH_FILENAME_MAX,"%s",UNIX_SOCKNAMES[unix_idx]
);
/* make sure message ends in <LF> */
if( buf[read_bytes-1] != '\n' )
strcat(buf,"\n");
if( debug && !do_fork) {
fprintf(stdout,"\r[%d]
got AF_LOCAL msg from: %s, bytes:
%06d \n",
getpid(), UNIX_SOCKNAMES[unix_idx], strlen(buf));
}
if( tag_msg(FullMsg,buf,SYSLOG) == -1)
return(-1);
if( send_to_log(FullMsg, 0) == -1)
return(-1);
/* update shared memory counters
*/
record_rtStats(1, read_bytes );
} /* if( FD_ISSET(UNIX_DESCRIPTORS[unix_idx],&readfds)
)
*/
} /* for( unix_idx=0;
unix_idx<=MAX_UNIX; unix_idx++)
*/
return(0);
}/**********************
end of handle_unix_input *************************/
/**************************************************************************
* handle_udp_input
*
* reads from a list of UDP sockets.
* writes to VHLOGFILE
*
* returns: -1 if a fatal error
occurred.
*
* Revision History
* who
when
what
* ---
----
----
*************************************************************************/
int
handle_udp_input() {
int
read_bytes = -1;
int
len;
int
udp_idx, uidx;
char
Message[MSGSIZE];
char
FullMsg[MSGSIZE];
/************************************************************************/
fprintf(stdout,"vhsyslogd UDP pid is:
[%d]\n", udpPID);
strcpy(proc_name,"vhsyslogd_UDP");
I_AM_UDP = 1;
if(
shmid != -1)
rtStats->active_udp_servers++;
/* get rid of any inherited UNIX/TCP
descriptors */
for(
uidx=0; uidx<=MAX_UNIX; uidx++) {
if(
UNIX_DESCRIPTORS[uidx] == -1) break;
close(UNIX_DESCRIPTORS[uidx]);
FD_CLR(UNIX_DESCRIPTORS[uidx],
&readfds_base);
}
close(iVHsyslogTCP);
FD_CLR(iVHsyslogTCP, &readfds_base);
while(1) {
readfds = readfds_base;
input_timeout = input_timeout_base;
#if
0
switch( select(maxfd+1, &readfds,
NULL, NULL, &input_timeout) ) {
case 0: /* no
fd's ready */
break;
case -1: /* fatal
*/
snprintf(INT_MSG,MSGSIZE,"%s:%d \nselect(readfds)\n %s.
Exiting.\n",
__FILE__,__LINE__,strerror(errno));
VHshutdown();
break;
default:
break; /* input ready */
} /* switch */
#endif
/* maintain rtStats
*/
if( shmid != -1) {
rtStats->active_udp_users -= active_UDP_fds;
active_UDP_fds = 0;
}
for( udp_idx=0; udp_idx<=MAX_UDP;
udp_idx++) {
if( UDP_PORTS[udp_idx] == -1) break;
if( shmid != -1) {
active_UDP_fds++;
rtStats->active_udp_users++;
}
len = sizeof( UDP_SOCKETS[udp_idx] );
read_bytes =
recvfrom(UDP_DESCRIPTORS[udp_idx], Message,
MSGSIZE, 0,
(struct sockaddr
*)&UDP_SOCKETS[udp_idx],
&len);
Message[read_bytes] = (char ) '\0';
if( Message[read_bytes-1] != (char ) '\n')
strcat(Message,"\n");
/* fill out info for message header */
sSource[0] = (char )
'\0';
snprintf(sSource,PATH_FILENAME_MAX,"%d",UDP_PORTS[udp_idx] );
if( debug
&& !do_fork) {
fprintf(stdout,"\r[%d] got UDP msg from: %s:%s, bytes: %06d \n",
getpid(), MyIP, sSource, read_bytes );
fflush(stdout);
}
record_rtStats(2,
read_bytes );
if( tag_msg(FullMsg,Message,SYSLOG) == -1)
return(-1);
if( send_to_log(FullMsg,0) == -1)
return(-1);
} /*
for(udp_idx=0; udp_idx<=MAX_UDP; udp_idx++) */
}/* while(1)
*/
return(0);
}/****************
handle_udp_input **************************************/
/*************************************************************************
* init_server
*
* setup server signals/sockets/logs etc...
*
* returns: -1 if a fatal error occurred.
*
* Revision History
*
who
when
what
*
---
----
----
*
martinj@nwlink.com
26-apr-01 assist startup
troubleshooters.
*
************************************************************************/
int
init_server(int
Dargc, char *Dargv[] ) {
int counter = 0;
char
FullMsg[MSGSIZE];
int file_max = 0;
FILE *pipefd;
/***********************************************************************/
if(
VERBOSE )
printf("%s:
starting\n",__FUNCTION__);
/* check for known kernel limits
*/
if(
VERBOSE ) {
if ( (pipefd=popen("/sbin/sysctl -n
fs.file-max","r")) != NULL ) {
fscanf(pipefd,"%d", &file_max);
if(
file_max <= 4096) {
fprintf(stderr,"\n\nWARNING
WARNING WARNING "
"WARNING WARNING WARNING"
"\n\nCurrent kernel parameter fs.file-max = %d.\n"
"This setting has caused %s to exhaust all\n"
"available file handles if more than 500\n"
"concurrent TCP clients are connected.\n\n"
"Issue: /sbin/sysctl -w fs.file-max=nnnn\n"
"Where: nnnn is the max number of file handles.\n\n"
"WARNING WARNING WARNING "
"WARNING WARNING WARNING\n\n",
file_max,__FILE__);
}
}
}
/* store BufferFile LOCK token and
proc_name */
snprintf(LOCKtoken,MSGSIZE,"%s.LOCK",VHLOGFILE
);
proc_name = *Dargv;
/* init descriptor sets
*/
FD_ZERO(&readfds_base);
FD_ZERO(&writefds_base);
FD_ZERO(&exceptfds_base);
/* TT 234: buffer file writes lag
vhsyslogd inputs.
configure much shorter vhsyslog.h.VHLOGDAEMON_xSEC_TO
timeouts (currently it's 10 uSecs. seperate UNIX/UDP
and TCP timeout waits. (not serial)
*/
/* UNIX / UDP select timeout
*/
input_timeout_base.tv_sec = (time_t)
VHLOGDAEMON_SEC_TO;
input_timeout_base.tv_usec = (long)
VHLOGDAEMON_uSEC_TO;
/* TCP select timeout
*/
TCPinput_timeout_base = input_timeout_base;
if(
VERBOSE )
printf("%s: unlinking %s\n",__FUNCTION__,LOCKtoken);
/* clear any remenant LOCK tokens
*/
if(
(unlink(LOCKtoken) == -1 )) {
if( errno
!= ENOENT) { /* No such file or dir */
snprintf(INT_MSG,MSGSIZE,
"%s.%d Can't unlink %s. \n%s\n",
__FILE__,__LINE__,LOCKtoken,strerror(errno) );
log_err(VHFATAL,INT_MSG);
return(-1);
}
}
/* set default file permissions
(-rw-r--r-) */
umask(022);
/* get the local machine name and
IP
*/
if(
(uname( &MyUTSname)) != -1) {
/* hostent *gethostbyname is flaky
*/
MyIP[0] = (char ) '\0';
if ( (pipefd=popen("hostname
-i","r")) != NULL ) {
if( fgets(MyIP, sizeof(MyIP),
pipefd) == NULL )
strncpy(MyIP, MyUTSname.nodename, TINYSTRING);
else { /* strip trailing
space and \n */
for( counter=0; counter<=
strlen(MyIP); counter++) {
if( MyIP[counter] == 0x0A ||
MyIP[counter] == 0x20)
MyIP[counter] = (char ) '\0';
}
}
}
else { /* use
nodename
*/
strncpy(MyIP,
MyUTSname.nodename, TINYSTRING);
}
}
else
{ /*
don't tell me your name
*/
strcpy(MyIP,"localhost");
}
/* attach shared memory
*/
shmid = shmget((key_t) shmkey, sizeof(vhsyslogd_stats_t),
0666 | IPC_CREAT);
if(
shmid == -1) {
snprintf(INT_MSG,MSGSIZE,"%s.%d Can't create shared memory region
0x%08x \n%s\n",
__FILE__,__LINE__,shmkey,strerror(errno)
);
log_err(VHINFO,INT_MSG);
if( !do_fork)
fprintf(stderr,"%s",INT_MSG);
}
if(
shmid != -1) {
rtShmem = shmat(shmid, (void *)0, 0);
if( rtShmem == (void
*)-1) {
snprintf(INT_MSG,MSGSIZE,"%s.%d Can't attach shared memory region
%0x08x "
"\n%s\n",
__FILE__,__LINE__,shmkey,strerror(errno) );
log_err(VHINFO,INT_MSG);
if(
!do_fork) fprintf(stderr,"%s",INT_MSG);
shmid = -1;
}
}
/* init rtStats */
if(
shmid != -1) {
rtStats = (vhsyslogd_stats_t *) rtShmem;
strncpy( rtStats->StartupTime, vhsyslog_getdate(1), TINYSTRING);
strncpy( rtStats->Host, MyUTSname.nodename, TINYSTRING);
rtStats->active_udp_servers
= 0;
rtStats->active_tcp_servers
= 0;
rtStats->active_tcp_users = 0;
rtStats->active_udp_users = 0;
rtStats->tcp_data_err = 0;
rtStats->tcp_connect_err = 0;
rtStats->total_msgs = 0;
rtStats->total_tcp_msgs = 0;
rtStats->total_udp_msgs = 0;
rtStats->total_afunix_msgs = 0;
rtStats->total_bytes = 0;
rtStats->total_tcp_bytes = 0;
rtStats->total_udp_bytes = 0;
rtStats->total_afunix_bytes
= 0;
rtStats->total_send_msgs = 0;
rtStats->total_send_bytes = 0;
rtStats->WritePtr = 0;
rtStats->LOCKtoken = 0;
}
if(
VERBOSE )
printf("%s: attached shared memory key
0x%08x\n",__FUNCTION__,shmkey);
/* get command line switches
*/
if(
decode_args(Dargc, Dargv) == -1)
exit(-1);
if(
VERBOSE )
printf("%s: decoded command line args\n",__FUNCTION__);
/* open buffer specified in
BUFPTRS
*/
if(
get_current_buffer() == -1 )
return(-1);
if(
VERBOSE )
printf("%s: get_current_buffer got
%s\n",__FUNCTION__,BufferFile);
/* open the local log
*/
if(
open_log() == -1 )
return(-1);
if(
VERBOSE )
printf("%s: log (%s) opened\n",__FUNCTION__,BufferFile);
log_internal(VHINFO,StartupMsg);
snprintf(INT_MSG,MSGSIZE,"%s: [%d] I am %s
(%s)\n running %s %s\n",
__FILE__,getpid(), MyIP,
MyUTSname.nodename,
MyUTSname.sysname,
MyUTSname.release);
if(
!do_fork) fprintf(stderr,"%s",INT_MSG);
log_internal(VHINFO,INT_MSG);
/* open the local communication
socket
*/
if(
open_unix() == -1 )
return(-1);
/* get a list of UDP descriptors
*/
if(
open_udp() == -1)
return(-1);
/* create a TCP listen socket
*/
if(
open_tcp() == -1)
return(-1);
/* TT 318: daemon fails to note that
it started or stopped
provide handlers for all signals. Format expected
strings and PRI for log
*/
signal(SIGPIPE, sigpipe);
signal(SIGFPE, sigdie);
signal(SIGILL, sigdie);
/* signal(SIGSEGV, sigdie); */
signal(SIGBUS, sigdie);
signal(SIGABRT, sigdie);
signal(SIGIOT, sigdie);
signal(SIGTRAP, sigdie);
signal(SIGHUP, sigdie);
signal(SIGALRM, sigdie);
signal(SIGVTALRM, sigdie);
signal(SIGPROF, sigdie);
signal(SIGXCPU, sigdie);
signal(SIGXFSZ, sigdie);
signal(SIGUSR1, sigdie);
signal(SIGUSR2, sigdie);
signal(SIGSEGV, sigdie);
signal(SIGINT, sigdie);
signal(SIGTERM, sigdie);
signal(SIGQUIT, sigdie);
signal(SIGKILL, sigdie);
snprintf(INT_MSG,MSGSIZE,"<%d>%s
%s[%d]: %s audit log started\n",
0x4d,vhsyslog_getdate(2),
proc_name,getpid(),
version);
strcpy(sSource,"Internal");
tag_msg(FullMsg,INT_MSG,SYSLOG);
if(
VERBOSE )
send_to_log(FullMsg,1); /* ignore max filesize */
if(
!do_fork) fprintf(stderr,"%s\n",INT_MSG);
if(
shmid != -1 ) {
rtStats->last_msg[0] = (char ) '\0';
strncpy(rtStats->last_msg,FullMsg,MSGSIZE);
}
/* set run mode
*/
iInit = 0;
parentPID = getpid();
return(0);
}/************************
end of init_server ****************************/
/**************************************************************************
* get_current_buffer
*
* looks in BUFPTRS for a basename and file number
* and makes a BufferFile name.
*
*
* returns: -1 if a fatal error occurred.
*
* Revision History
*
who
when
what
*
---
----
----
*************************************************************************/
int
get_current_buffer() {
char cFileName[PATH_FILENAME_MAX];
char cDirection[PATH_FILENAME_MAX];
char cFileNumber[TINYSTRING];
char cBuffer[PATH_FILENAME_MAX];
int FOUND_LASTWRITE = 0;
/*************************************************************************/
/* open BUFPTRS */
if( iInit ) {
/*fseek lies if it is used on a file opened as
"a+" */
if( stat(BUFPTRS,&stbuf) == -1) {
if( errno == ENOENT )
{
if( !(fpLastWrite = fopen(BUFPTRS,"a+"))) {
fprintf(stderr,
"%s:%d can't create %s \n%s \nExiting.\n",
__FILE__,__LINE__,BUFPTRS,strerror(errno));
return(-1); /*
fatal */
}
if( VERBOSE )
fprintf(stderr,"%s: initializing %s with default data:\n",
__FILE__,BUFPTRS);
if( fprintf(fpLastWrite,
"##################################################### \n"
"# IT'S PROBABLY OK TO LEAVE THIS FILE ALONE
\n"
"##################################################### \n"
"#
\n"
&nbs