Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MagnusTiberius/ee8edb14a9be044b15323eb7ffb410cb to your computer and use it in GitHub Desktop.
Save MagnusTiberius/ee8edb14a9be044b15323eb7ffb410cb to your computer and use it in GitHub Desktop.
#include "eipeventd.h"
#include <algorithm>
#include <cstdlib>
#include <memory>
#include <string>
#include <vector>
#include <utility>
#include "jansson.h"
#include "json.h"
#include "timestamp.h"
#include "customevent.h"
using std::string;
using std::vector;
using std::unique_ptr;
int EipEventD::had_hup = 0;
EipEventD::EipEventD()
{
}
EipEventD::~EipEventD()
{
}
void EipEventD::Start()
{
}
/*
* Convert the executable to run as a daemon.
*/
void EipEventD::daemonize(void)
{
pid_t pid, sid, parent;
int lfp = -1;
/* Already a daemon? */
if (getppid() == 1) {
printf("already a daemon\n");
return;
}
#ifdef SUPPORT_RUN_AS
if (getuid() == 0 || geteuid() == 0) {
struct passwd *pw = getpwnam(RUN_AS_USER);
if (pw) {
syslog(LOG_NOTICE, "Setting user to " RUN_AS_USER);
setuid(pw->pw_uid);
}
}
#endif
/* Trap signals we expect to receive */
signal(SIGCHLD, &EipEventD::child_handler);
signal(SIGUSR1, &EipEventD::child_handler);
signal(SIGALRM, &EipEventD::child_handler);
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
syslog(LOG_ERR, "Unable to fork daemon, error (%d)%s", errno, strerror(errno));
printf("Unable to fork daemon, error \n");
exit(EXIT_FAILURE);
}
/* If we got a good PID, we can exit the parent process */
if (pid > 0) {
/* Wait for confirmation from the child via SIGTERM of SIGCHLD, or
* for two seconds to elapse (SIGALRM). pause() should not return.
*/
alarm(2);
pause();
printf("pid > 0\n");
exit(EXIT_FAILURE);
}
/* At this point we are executing as the child process */
parent = getppid();
/* Catch, Ignore and handle signals */
signal(SIGCHLD, SIG_IGN); /* Ignore child */
signal(SIGTSTP, SIG_IGN); /* Ignore tty signals */
signal(SIGTTOU, SIG_IGN); /* Ignore terminal output signal */
signal(SIGTTIN, SIG_IGN); /* Ignore terminal input signal */
signal(SIGHUP, sighup_handler);
signal(SIGTERM, sigterm_handler);
/* Change the file mode mask */
umask(027);
/* Create a new SID for the child process */
if (setsid() < 0) {
syslog(LOG_ERR, "Unable to create a new session, error (%d)%s", errno, strerror(errno));
printf("Unable to create a new session, error \n");
exit(EXIT_FAILURE);
}
/* Change running directory */
if ((chdir("/")) < 0) {
syslog(LOG_ERR, "Unable to change directory to /, error (%d)%s", errno, strerror(errno));
printf("Unable to change directory to /, error\n");
exit(EXIT_FAILURE);
}
freopen("/dev/null", "r", stdin);
//freopen("/dev/null", "w", stdout);
//freopen("/dev/null", "w", stderr);
/* Tell the parent process that we are okay */
kill(parent, SIGUSR1);
}
/*
* Create the pid file used to keep track of this daemon's current
* process id.
*/
pid_t EipEventD::create_pidfile(void)
{
int fd;
pid_t pid;
char buf[20];
if ((fd = open(PID_FILE, O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR)) == -1) {
printf("Unable to open or create pid file: %s\n", PID_FILE);
syslog(LOG_ERR, "Unable to open or create pid file %s: (%d)%s", PID_FILE, errno, strerror(errno));
exit(EXIT_FAILURE);
}
if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
printf("Unable to lock pid file\n");
syslog(LOG_ERR, "Unable to lock pid file %s: (%d)%s", PID_FILE, errno, strerror(errno));
exit(EXIT_FAILURE);
}
/* delete contents of file */
if (ftruncate(fd, 0) == -1) {
printf("Unable to truncate pid file\n");
syslog(LOG_ERR, "Unable to truncate pid file %s: (%d)%s", PID_FILE, errno, strerror(errno));
exit(EXIT_FAILURE);
}
pid = getpid();
snprintf(buf, sizeof(buf), "%ld\n", (long)pid);
if (write(fd, buf, strlen(buf)) != strlen(buf)) {
printf("Unable to write pid to\n");
syslog(LOG_ERR, "Unable to write pid to %s: (%d)%s", PID_FILE, errno, strerror(errno));
exit(EXIT_FAILURE);
}
return pid;
}
/*
* Destroy the pid file used to keep track of this daemon's current
* process id.
*/
int EipEventD::destroy_pidfile()
{
return unlink(PID_FILE);
}
/*
* Handle the HUP signal by indicating it has occurred.
*/
void EipEventD::sighup_handler(int signum)
{
struct sigaction act;
memset(&act, 0, sizeof (act));
EipEventD::had_hup = 1;
syslog(LOG_NOTICE, "HUP received...");
sigemptyset(&act.sa_mask);
act.sa_handler = EipEventD::sighup_handler;
sigaction(SIGHUP, &act, NULL);
}
/*
* Handle the TERM signal by exiting.
*/
void EipEventD::sigterm_handler(int signum)
{
printf("sigterm_handler .... exiting\n");
syslog(LOG_NOTICE, "Exiting...");
closelog();
destroy_pidfile();
exit(EXIT_SUCCESS);
}
/*
* This handler is only present while the parent is running and is intended
* to handle signals generated by the child.
*/
void EipEventD::child_handler(int signum)
{
switch (signum) {
case SIGALRM: exit(EXIT_FAILURE); break;
case SIGUSR1: exit(EXIT_SUCCESS); break;
case SIGCHLD: exit(EXIT_FAILURE); break;
}
}
void EipEventD::print_usage(void)
{
printf("Usage: %s [OPTION]...\n"
"Copyright (C) 2013-2016 \n"
"\n"
"Event Daemon\n"
"\n"
"The following OPTIONS are supported:\n"
" -p, --port PORT list on PORT for incoming log messages\n"
" --help display this help and exit\n"
" --version output version information and exit\n"
"\n", prog_name);
}
void EipEventD::print_version(void)
{
printf("%s %s\n", prog_name, xstr(VERSION));
}
/*
* The main execution loop.
*/
void EipEventD::run(const char *port)
{
char *message = "ECHO Daemon v1.0 \r\n";
ctr1 = 1;
//set of socket descriptors
fd_set readfds;
ClientEvent clientevent;
clientevent.Start();
//initialise all client_socket[] to 0 so not checked
for (i = 0; i < max_clients; i++)
{
client_socket[i] = 0;
}
//create a master socket
if( (master_socket = socket(AF_INET , SOCK_STREAM , 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
//set master socket to allow multiple connections , this is just a good habit, it will work without this
if( setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
//type of socket created
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
//bind the socket to localhost port 8888
if (bind(master_socket, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
printf("Listener on port %d \n", PORT);
//try to specify maximum of 3 pending connections for the master socket
if (listen(master_socket, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
//accept the incoming connection
addrlen = sizeof(address);
puts("Waiting for connections ...");
while(TRUE)
{
//clear the socket set
FD_ZERO(&readfds);
//add master socket to set
FD_SET(master_socket, &readfds);
max_sd = master_socket;
//add child sockets to set
for ( i = 0 ; i < max_clients ; i++)
{
//socket descriptor
sd = client_socket[i];
//if valid socket descriptor then add to read list
if(sd > 0)
FD_SET( sd , &readfds);
//highest file descriptor number, need it for the select function
if(sd > max_sd)
max_sd = sd;
}
//wait for an activity on one of the sockets , timeout is NULL , so wait indefinitely
activity = select( max_sd + 1 , &readfds , NULL , NULL , NULL);
if ((activity < 0) && (errno!=EINTR))
{
printf("select error");
}
//If something happened on the master socket , then its an incoming connection
if (FD_ISSET(master_socket, &readfds))
{
if ((new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
//inform user of socket number - used in send and receive commands
printf("New connection , socket fd is %d , ip is : %s , port : %d \n" , new_socket , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//send new connection greeting message
if( send(new_socket, message, strlen(message), 0) != strlen(message) )
{
perror("send");
}
puts("Welcome message sent successfully");
//add new socket to array of sockets
for (i = 0; i < max_clients; i++)
{
//if position is empty
if( client_socket[i] == 0 )
{
client_socket[i] = new_socket;
printf("Adding to list of sockets as %d\n" , i);
break;
}
}
}
//else its some IO operation on some other socket :)
for (i = 0; i < max_clients; i++)
{
sd = client_socket[i];
if (FD_ISSET( sd , &readfds))
{
//Check if it was for closing , and also read the incoming message
if ((valread = read( sd , buffer, 1024)) == 0)
{
//Somebody disconnected , get his details and print
getpeername(sd , (struct sockaddr*)&address , (socklen_t*)&addrlen);
printf("Host disconnected , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
close( sd );
client_socket[i] = 0;
}
//Echo back the message that came in
else
{
//set the string terminating NULL byte on the end of the data read
buffer[valread] = '\0';
send(sd , buffer , strlen(buffer) , 0 );
if (false)
{
puts("Creating custom event");
CustomEvent ce(clientevent.GetClient(), "TestEvent");
puts("Get root node");
ma_xml_node_t *root_node = ce.GetRootNode();
ma_xml_node_t *node1;
ce.CreateNode(root_node, "Node1", node1);
puts("event send");
ce.Send();
}
if(true)
{
printf("event send ==================...====== %d =====================\n", ctr1);
ma_error_t rc = MA_OK;
ma_custom_event_t *event = NULL;
ma_xml_node_t *root_node = NULL;
rc = ma_custom_event_create(clientevent.GetClient(), "VirusDetectionEvent", &event, &root_node);
ma_xml_node_t *ScannerSoftware_node = NULL;
ma_custom_event_node_create(root_node, "ScannerSoftware", &ScannerSoftware_node);
ma_custom_event_node_attribute_set(ScannerSoftware_node, "ProductName", "VirusScan Enterprise");
ma_xml_node_t *node = NULL;
ma_custom_event_node_create(ScannerSoftware_node, "ProductName", &node);
ma_custom_event_node_set_data(node, "VirusScan Enterprise");
rc = ma_custom_event_send(event);
rc = ma_custom_event_release(event);
printf("event send ==================^^^====== %d =====================\n", ctr1);
ctr1++;
}
}
}
}
}
printf("exiting loop\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment