/**************************************************************************

 * 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