Пример #1
0
/**********************************************************************
* %FUNCTION: Event_HandleChildExit
* %ARGUMENTS:
*  es -- event selector
*  pid -- process-ID of child to wait for
*  handler -- function to call when child exits
*  data -- data to pass to handler when child exits
* %RETURNS:
*  0 on success, -1 on failure.
* %DESCRIPTION:
*  Sets things up so that when a child exits, handler() will be called
*  with the pid of the child and "data" as arguments.  The call will
*  be synchronous (part of the normal event loop on es).
***********************************************************************/
int
Event_HandleChildExit(EventSelector *es,
		      pid_t pid,
		      void (*handler)(pid_t, int, void *),
		      void *data)
{
    struct ChildEntry *ce;
    sigset_t set;

    if (Event_HandleSignal(es, SIGCHLD, child_handler) < 0) return -1;
    ce = malloc(sizeof(struct ChildEntry));
    if (!ce) return -1;
    ce->pid = pid;
    ce->data = data;
    ce->handler = handler;

    /* Critical section: Don't let SIGCHLD mess hash_insert */
    sigemptyset(&set);
    sigaddset(&set, SIGCHLD);
    sigprocmask(SIG_BLOCK, &set, NULL);

    hash_insert(&child_process_table, ce);

    sigprocmask(SIG_UNBLOCK, &set, NULL);

    return 0;
}
Пример #2
0
/**********************************************************************
* %FUNCTION: Event_HandleChildExit
* %ARGUMENTS:
*  es -- event selector
*  pid -- process-ID of child to wait for
*  handler -- function to call when child exits
*  data -- data to pass to handler when child exits
* %RETURNS:
*  0 on success, -1 on failure.
* %DESCRIPTION:
*  Sets things up so that when a child exits, handler() will be called
*  with the pid of the child and "data" as arguments.  The call will
*  be synchronous (part of the normal event loop on es).
***********************************************************************/
int
Event_HandleChildExit(EventSelector *es,
		      pid_t pid,
		      void (*handler)(pid_t, int, void *),
		      void *data)
{
    struct ChildEntry *ce;

    if (Event_HandleSignal(es, SIGCHLD, child_handler) < 0) return -1;
    ce = malloc(sizeof(struct ChildEntry));
    if (!ce) return -1;
    ce->pid = pid;
    ce->data = data;
    ce->handler = handler;
    hash_insert(&child_process_table, ce);
    return 0;
}
Пример #3
0
/**********************************************************************
* %FUNCTION: network_init
* %ARGUMENTS:
*  es -- an event selector
* %RETURNS:
*  >= 0 if all is OK, <0 if not
* %DESCRIPTION:
*  Initializes network; opens socket on UDP port 1701; sets up
*  event handler for incoming packets.
***********************************************************************/
int
l2tp_network_init(EventSelector *es)
{
    struct sockaddr_in me;
    int flags;

    gethostname(Hostname, sizeof(Hostname));
    Hostname[sizeof(Hostname)-1] = 0;

    Event_HandleSignal(es, SIGINT, sigint_handler);
    if (Sock >= 0) {
	if (NetworkReadHandler) {
	    Event_DelHandler(es, NetworkReadHandler);
	    NetworkReadHandler = NULL;
	}
	close(Sock);
	Sock = -1;
    }
    Sock = socket(PF_INET, SOCK_DGRAM, 0);
    if (Sock < 0) {
	l2tp_set_errmsg("network_init: socket: %s", strerror(errno));
	return -1;
    }

    me.sin_family = AF_INET;
    me.sin_addr = Settings.listen_addr;
    me.sin_port = htons((uint16_t) Settings.listen_port);
    if (bind(Sock, (struct sockaddr *) &me, sizeof(me)) < 0) {
	l2tp_set_errmsg("network_init: bind: %s", strerror(errno));
	close(Sock);
	Sock = -1;
	return -1;
    }

    /* Set socket non-blocking */
    flags = fcntl(Sock, F_GETFL);
    flags |= O_NONBLOCK;
    fcntl(Sock, F_SETFL, flags);

    /* Set up the network read handler */
    Event_AddHandler(es, Sock, EVENT_FLAG_READABLE,
		     network_readable, NULL);
    return Sock;
}
Пример #4
0
int
main(int argc, char *argv[])
{
    EventSelector *es = Event_CreateSelector();
    int i;
    int opt;
    int do_fork = 1;
    int debugmask = 0;

    while((opt = getopt(argc, argv, "d:fh")) != -1) {
	switch(opt) {
	case 'h':
	    usage(argc, argv, EXIT_SUCCESS);
	    break;
	case 'f':
	    do_fork = 0;
	    break;
	case 'd':
	    sscanf(optarg, "%d", &debugmask);
	    break;
	default:
	    usage(argc, argv, EXIT_FAILURE);
	}
    }

    openlog(argv[0], LOG_PID, LOG_DAEMON);
    l2tp_random_init();
    l2tp_tunnel_init(es);
    l2tp_peer_init();
    l2tp_debug_set_bitmask(debugmask);

    /* ASUS if (l2tp_parse_config_file(es, SYSCONFDIR"/l2tp/l2tp.conf") < 0) { */
    if (l2tp_parse_config_file(es, SYSCONFDIR"/l2tp.conf") < 0) {
	l2tp_die();
    }

    if (!l2tp_network_init(es)) {
	l2tp_die();
    }

    /* Daemonize */
    if (do_fork) {
	i = fork();
	if (i < 0) {
	    perror("fork");
	    exit(EXIT_FAILURE);
	} else if (i != 0) {
	    /* Parent */
	    exit(EXIT_SUCCESS);
	}

	setsid();
	signal(SIGHUP, SIG_IGN);
	i = fork();
	if (i < 0) {
	    perror("fork");
	    exit(EXIT_FAILURE);
	} else if (i != 0) {
	    exit(EXIT_SUCCESS);
	}

	chdir("/");

	/* Point stdin/stdout/stderr to /dev/null */
	for (i=0; i<3; i++) {
	    close(i);
	}
	i = open("/dev/null", O_RDWR);
	if (i >= 0) {
	    dup2(i, 0);
	    dup2(i, 1);
	    dup2(i, 2);
	    if (i > 2) close(i);
	}
    }

    Event_HandleSignal(es, SIGINT, sighandler);
    Event_HandleSignal(es, SIGTERM, sighandler);

    while(1) {
	i = Event_HandleEvent(es);
	if (i < 0) {
	    fprintf(stderr, "Event_HandleEvent returned %d\n", i);
	    l2tp_cleanup();
	    exit(EXIT_FAILURE);
	}
    }
    return 0;
}