/*
 * Run a ''system'' command.  pipe the output to all of the clients.
 */
static void do_system(const char* cmd)
{
    /* The handles of the pipes */
    int pipetochild[2], pipefromchild[2];
    int pid;
    char buf[256];
    int n;

    if((print_output & 2) != 0)
	printf("Starting a ''system'' command\n");

    /* Create the pipes */
    if (pipe (pipetochild))
    {
	printf("pipe creation (do_system)\n");
	perror (progname);
	return;
	/*exit (EXIT_FAILURE);*/
    }

    if (pipe (pipefromchild))
    {
	printf("pipe creation (do_system 2)\n");
	perror (progname);
	return;
	/*exit (EXIT_FAILURE);*/
    }

    /* FORK so that the child can execute (inhereting files) */
    pid = fork ();
    switch (pid)
    {
    case -1:
	printf("fork -> -1 (do_system)\n");
	perror (progname);
	return;

    case 0:
        signal (SIGPIPE, SIG_IGN);

	/* Switch of buffering of STDOUT (hopefully) */
	fflush (stdout);
	if (setvbuf (stdout, NULL, _IONBF, BUFSIZ) != 0)
	{
	    perror (progname);
	    _exit (EXIT_FAILURE);
	}

        if((print_output & 2) != 0)
	    printf ("Child (PID %i); parent PID is %i\n", getpid (), getppid ());

	/* Setup the child's STDOUT */
	if (dup2 (pipefromchild[PIPE_WRITEEND], STDOUT_FILENO) == -1)
	{
	    perror (progname);
	    _exit (EXIT_FAILURE);
	}
	close (pipefromchild[PIPE_READEND]);
	close (pipefromchild[PIPE_WRITEEND]);

	/* Setup the childs STDIN */
	if (dup2 (pipetochild[PIPE_READEND], STDIN_FILENO) == -1)
	{
	    perror (progname);
	    _exit (EXIT_FAILURE);
	}
	close (pipetochild[PIPE_READEND]);
	close (pipetochild[PIPE_WRITEEND]);

	/* Run the child program */
	system(cmd);

	/* exiting this function is OK! */
	_exit (EXIT_SUCCESS);
	break; 

    default:
	/*printf ("Parent (PID %i); child PID is %i\n", getpid (), pid);*/
	;
    }

    close (pipefromchild[PIPE_WRITEEND]);
    close (pipetochild[PIPE_READEND]);

    if((print_output & 2) != 0)
	printf("Doing ''system'' command\n");

    do
    {
	n = read(pipefromchild[PIPE_READEND], buf, sizeof(buf));
	if(n > 0)
	{
	    buf[n] = 0;
	    write_to_clients(buf, n);
	    if((print_output & 1) != 0)
		printf("%s", buf);
	}
    }
    while(n > 0);

    if((print_output & 2) != 0)
	printf("''system'' command ended\n");

    close(pipefromchild[PIPE_READEND]);
    close(pipetochild[PIPE_WRITEEND]);
}
Example #2
0
int main(int argc, char **argv)
{
	struct producer_config pc;
	struct consumer_config cc;
	struct flow_table flowtable;
	pthread_t tid[4];

	if (argc != 2) {
		fprintf(stderr, "usage: %s <model-file>\n", argv[0]);
		return ERROR;
	}

	if (setup_packet_capture(&pc, NETFILTER) != 0) {
		fprintf(stderr,
			"%s: error setting up packet capture interface!\n",
			argv[0]);
		return ERROR;
	}

	if (listen_for_requests(&cc, SERVER_PORT) != 0) {
		fprintf(stderr, "%s: error listening for client requests!\n",
			argv[0]);
		return ERROR;
	}

	if ((cc.model = svm_load_model(argv[1])) == 0) {
		fprintf(stderr, "could not open model file %s\n", argv[1]);
		return ERROR;
	}

	/* everything is sent in network byte order */
	cc.n_max_payload = htonl(MAX_PAYLOAD);

	/* initialize tables and stuff */
	flowtable_init(&flowtable, FLOW_ENTRIES);
	cc.keep_going = &keep_going;
	pc.keep_going = &keep_going;
	cc.flowtable = &flowtable;
	pc.flowtable = &flowtable;

	if ((cc.x =
	     (struct svm_node *)malloc(max_nr_attr *
				       sizeof(struct svm_node))) == NULL) {
		fprintf(stderr, "could not allocate memory for svm_node!\n");
		flowtable_finit(&flowtable);
		svm_destroy_model(cc.model);
		close_pcap_interface(&pc.pcap);
		return 1;
	}

	if (init_send_buffers(&cc.sb, SEND_BUFFER_SIZE, SEND_BUFFERS) != 0) {
		fprintf(stderr, "could not initialize send buffers!\n");
		free(cc.x);
		flowtable_finit(&flowtable);
		svm_destroy_model(cc.model);
		close_pcap_interface(&pc.pcap);
		return 1;
	}

	signal(SIGINT, siginthandler);
	signal(SIGPIPE, SIG_IGN);

	/* let the games begin! */
	if (pthread_create(&tid[0], NULL, produce_flowtable, (void *)&pc) != 0) {
		fprintf(stderr, "could not spawn thread\n");
		return ERROR;
	}

	if (pthread_create(&tid[1], NULL, consume_flowtable, (void *)&cc) != 0) {
		fprintf(stderr, "could not spawn thread\n");
		return ERROR;
	}

	if (pthread_create
	    (&tid[2], NULL, accept_connections_for_flows, (void *)&cc) != 0) {
		fprintf(stderr, "%s: could not spawn thread\n", argv[0]);
		return ERROR;
	}
#if 0
	if (pthread_create(&tid[3], NULL, write_to_clients, (void *)&cc) != 0) {
		fprintf(stderr, "could not spawn thread\n");
		return ERROR;
	}
	/* done with everything */
	for (i = 0; i < 4; ++i)
		if (pthread_join(tid[i], NULL) != 0)
			fprintf(stderr, "%s: error waiting for thread %ld\n",
				argv[0], tid[i]);
#endif
	write_to_clients((void *)&cc);
	svm_destroy_model(cc.model);
	flowtable_finit(&flowtable);

	print_pcap_stats(stdout, &pc.pcap);
	close_pcap_interface(&pc.pcap);

	return 0;
}
static void do_server(int port)
{
    fd_set readfds;
    int server;
    struct sockaddr_in saserver;
    command* cp;
    int maxd, n;
    int flg;
    btcli child;
    char buf[2048];

    /* Create a socket, and start listening. */

    server = socket (AF_INET, SOCK_STREAM, 0);
    if (server == -1)
    {
	printf("socket creation failed!\n");
	perror (progname);
	exit (EXIT_FAILURE);
    }

    memset (&saserver, 0, sizeof (saserver));
    saserver.sin_family = AF_INET;
    saserver.sin_addr.s_addr = INADDR_ANY;
    saserver.sin_port = htons (port);

    if (bind (server, (struct sockaddr *) &saserver, sizeof (saserver)))
    {
	printf("socket bind failed!\n");
	perror (progname);
	exit (EXIT_FAILURE);
    }

    if (listen (server, 1))
    {
	printf("listen failed!\n");
	perror (progname);
	exit (EXIT_FAILURE);
    }

    /*
     * This loop below is controlled by ''mode''.  It takes on a
     * number of different values, at different times to mean
     * different things.
     *  RUN	- We might have a BTCLI running, but should
     *            keep pumping data anyway.
     *  DIE	- We should exit as soon as possible.
     *            We should kill btcli, and btclid.
     *            All connected users are dropped
     *  START   - We should start a copy of btcli
     *  STOP    - We should kill the current copy of BTCLI.
     *  RESTART - We should kill btcli, and then start it again
     *  SHELL   - We should stop btcli, run a command and restart btcli
     *  DEVINFO - Output the parameters to btcli
     * 
     */
    mode = MODE_RUN;

    /*
    Change to having one big loop (not two nested)
    Select on the following things:
    ''accept'' on the socket server, so that new people can telnet in.
    ''read'' from each of the sockets for commands.
    ''read'' from stdin, to check that no one is typing on the screen.
    ''read'' from the btcli (if it exists), and buffer the data
    */

    child.pid = 0;
    child.read = child.write = -1;
    start_btcli(&child);

    if((print_output & 2) != 0)
	printf("Starting 'do_server' loop\n");

    set_non_block(server);

    set_non_block(STDIN_FILENO);

    setbuf(stdin, NULL);

    flg = fcntl(STDIN_FILENO, F_GETFL);
/*  if((print_output & 2) != 0)
	printf("STDIN Flags = 0x%x\n", flg);*/

    fcntl(STDIN_FILENO, F_SETFL, flg|O_NDELAY);

    flg = fcntl(STDIN_FILENO, F_GETFL);
/*  if((print_output & 2) != 0)
	printf("STDIN Flags = 0x%x\n", flg);*/

    cmd_stdin.ptr = 0;
    cmd_stdin.handle = STDIN_FILENO;
    cmd_stdin.next = NULL;
    cmd_head = &cmd_stdin;

    do
    {
	FD_ZERO (&readfds);

	FD_SET (server, &readfds);
	maxd = server;

	/* Read from btcli */
	if(child.read != -1)
	{
	    FD_SET (child.read, &readfds);
	    if(child.read > maxd)
		maxd = child.read;
	}

	/* Read from the ''command'' list (stdin and socket connections) */
	for(cp = cmd_head; cp != NULL; cp = cp->next)
	{
	    if (cp->handle >= 0)
	    {
		FD_SET (cp->handle, &readfds);
		if(cp->handle > maxd)
		    maxd = cp->handle;
	    }
	}

	/* Perform the select */
	/* printf ("[%d\n", count_clients()); */
  	n = select (maxd + 1, &readfds, NULL, NULL, NULL);
	/* printf ("]\n"); */

	if (n == -1)
	{
	    printf("select -> got -1\n");
	    perror (progname);
	    continue;
	}

	/* Someone want to connect to the socket */
	if (FD_ISSET (server, &readfds))
	{
	    /* Add to list of clients */
	    add_client(server);
	}

	/* read the output from btcli */
	if (child.read != -1 && FD_ISSET (child.read, &readfds))
	{
	    n = read (child.read, buf, sizeof (buf) - 1);
	    if(n > 0)
	    {
		 /*
		  * (Has anyone noticed this is C, not C++?)
		  * If there isn't a newline at the end, add one.
		  * This is bad if we got a partial line; we
		  * could do tricks with select to help here.
		  */
		 if (n < sizeof(buf) - 1 && buf[n-1] != '\n')
		      buf[n++] = '\n';
		 buf[n] = '\0';

		/* Output the data from btcli to the screen */
		if ((print_output & 1) != 0)
		{
		    printf ("%s\0", buf);
		}

		/* output the data to the sockets */
		write_to_clients(buf, n);
	    }
	    else
	    {
		/* we failed to read anything from btcli (but select said that we could) */
		if (n < 0)
		{
		    printf("read (from child) -> got -1\n");
		    perror (progname);
		}
/*		mode = MODE_RESTART;*/
		/* Wait for explicit instruction to restart */
		mode = MODE_STOP;
	    }
	}

	/* This is where we handle data coming in from the socket
	   connection. */
	for (cp = cmd_head; cp != NULL; cp = cp->next)
	{
	    if (cp->handle >= 0 && FD_ISSET (cp->handle, &readfds))
	    {
#ifdef SIGALRM
		if(cp->handle == STDIN_FILENO)
		    alarm (1);
#endif
		n = read (cp->handle, buf, sizeof (buf) - 1);
#ifdef SIGALRM
		if(cp->handle == STDIN_FILENO)
		    alarm (0);
#endif
		if (n > 0)
		{
		    buf[n] = 0;
		    command_add_frag(cp, child.write, buf, n);
		}
		else
		{
		    if(n < 0)
		    {
			if(errno != EINTR)
			{
			    printf("read (from client) -> got -1\n");
			    perror (progname);
			}
		    }
		    else
		    {
			if((print_output & 2) != 0)
			    printf ("EOF on client\n");
		    }
		    if(cp->handle != STDIN_FILENO)
		    {
			close(cp->handle);	/* Close the socket handle (needed!?) */
			cp->handle = -1;	/* Mark the client for removal */
		    }
		}
	    }
	}
	remove_clients();

	/* Now we do different thing if we have been given a special btclid command */

	switch (mode)
	{
	case MODE_RESTART:

	    if((print_output & 2) != 0)
		printf("ReStarting\n");

	    close_btcli(&child);
	    start_btcli(&child);

	    mode = MODE_RUN;

	    break;

	case MODE_SHELL:

	    close_btcli(&child);

	    if((print_output & 2) != 0)
		printf("Running shell command ''%s''\n", shell);

	    do_system(shell);

	    memset(shell, 0, sizeof(shell));

	    start_btcli(&child);

	    mode = MODE_RUN;

	    break;

	case MODE_DEVINFO:

	    strcpy(buf, "ARGS:");
	    for(n=1; (n<64)&&(args[n]!=NULL); n++)
	    {
		strcat(buf, " ");
		strcat(buf, args[n]);
	    }
	    strcat(buf, "\r\n");

	    write_to_clients(buf, strlen(buf));

	    if((print_output & 1) != 0)
		printf ("%s", buf);

	    mode = MODE_RUN;

	    break;

	case MODE_STOP:

	    if(child.pid != 0)
		close_btcli(&child);

	    mode = MODE_RUN;

	    break;

	case MODE_START:

	    if(child.pid == 0)
		start_btcli(&child);

	    mode = MODE_RUN;

	    break;
	}
    }
    while (mode != MODE_DIE);

    close_btcli(&child);

    close (server);
}