Exemplo n.º 1
0
int
main(int argc, char *argv[])
{
	int c, tout, flags, flush, restore;
	const char *spath, **blsock;
	size_t nblsock, maxblsock;

	setprogname(argv[0]);

	spath = NULL;
	blsock = NULL;
	maxblsock = nblsock = 0;
	flush = 0;
	restore = 0;
	tout = 0;
	flags = O_RDWR|O_EXCL|O_CLOEXEC;
	while ((c = getopt(argc, argv, "C:c:D:dfP:rR:s:t:v")) != -1) {
		switch (c) {
		case 'C':
			controlprog = optarg;
			break;
		case 'c':
			configfile = optarg;
			break;
		case 'D':
			dbfile = optarg;
			break;
		case 'd':
			debug++;
			break;
		case 'f':
			flush++;
			break;
		case 'P':
			spath = optarg;
			break;
		case 'R':
			rulename = optarg;
			break;
		case 'r':
			restore++;
			break;
		case 's':
			if (nblsock >= maxblsock) {
				maxblsock += 10;
				void *p = realloc(blsock,
				    sizeof(*blsock) * maxblsock);
				if (p == NULL)
				    err(EXIT_FAILURE,
					"Can't allocate memory for %zu sockets",
					maxblsock);
				blsock = p;
			}
			blsock[nblsock++] = optarg;
			break;
		case 't':
			tout = atoi(optarg) * 1000;
			break;
		case 'v':
			vflag++;
			break;
		default:
			usage(c);
		}
	}

	argc -= optind;
	if (argc)
		usage(0);

	signal(SIGHUP, sighup);
	signal(SIGINT, sigdone);
	signal(SIGQUIT, sigdone);
	signal(SIGTERM, sigdone);
	signal(SIGUSR1, sigusr1);
	signal(SIGUSR2, sigusr2);

	openlog(getprogname(), LOG_PID, LOG_DAEMON);

	if (debug) {
		lfun = dlog;
		if (tout == 0)
			tout = 5000;
	} else {
		if (tout == 0)
			tout = 15000;
	}

	update_interfaces();
	conf_parse(configfile);
	if (flush) {
		rules_flush();
		flags |= O_TRUNC;
	}

	struct pollfd *pfd = NULL;
	bl_t *bl = NULL;
	size_t nfd = 0;
	size_t maxfd = 0;

	for (size_t i = 0; i < nblsock; i++)
		addfd(&pfd, &bl, &nfd, &maxfd, blsock[i]);
	free(blsock);

	if (spath) {
		FILE *fp = fopen(spath, "r");
		char *line;
		if (fp == NULL)
			err(EXIT_FAILURE, "Can't open `%s'", spath);
		for (; (line = fparseln(fp, NULL, NULL, NULL, 0)) != NULL;
		    free(line))
			addfd(&pfd, &bl, &nfd, &maxfd, line);
		fclose(fp);
	}
	if (nfd == 0)
		addfd(&pfd, &bl, &nfd, &maxfd, _PATH_BLSOCK);

	state = state_open(dbfile, flags, 0600);
	if (state == NULL)
		state = state_open(dbfile,  flags | O_CREAT, 0600);
	if (state == NULL)
		return EXIT_FAILURE;

	if (restore)
		rules_restore();

	if (!debug) {
		if (daemon(0, 0) == -1)
			err(EXIT_FAILURE, "daemon failed");
		if (pidfile(NULL) == -1)
			err(EXIT_FAILURE, "Can't create pidfile");
	}

	for (size_t t = 0; !done; t++) {
		if (readconf) {
			readconf = 0;
			conf_parse(configfile);
		}
		switch (poll(pfd, (nfds_t)nfd, tout)) {
		case -1:
			if (errno == EINTR)
				continue;
			(*lfun)(LOG_ERR, "poll (%m)");
			return EXIT_FAILURE;
		case 0:
			state_sync(state);
			break;
		default:
			for (size_t i = 0; i < nfd; i++)
				if (pfd[i].revents & POLLIN)
					process(bl[i]);
		}
		if (t % 100 == 0)
			state_sync(state);
		if (t % 10000 == 0)
			update_interfaces();
		update();
	}
	state_close(state);
	return 0;
}
Exemplo n.º 2
0
int main(int argc,char *argv[]) {
    struct int_sock *i_s;
    int retval,r;
    struct sigaction s_a;

    if ( (argc>1) && (!strncmp(argv[1],"also_unicast",12)) ) {
        do_unicast_bridging=1;
    } else if ( (argc>1) && (!strncmp(argv[1],"only_broadcast",14)) ) {
        do_multicast_bridging=0;
    }

    openlog("xcec-bridge",LOG_NDELAY,LOGGING_FACILITY);

    FD_ZERO(&select_set.fds);
    select_set.i_s_list=NULL;
    select_set.highest_fd=0;

    s_a.sa_handler=action_handler;
    if (sigemptyset(&s_a.sa_mask)) {
        syslog(LOG_ERR,"problem in sigemptyset: %s -- exiting",
               strerror(errno));
        return 1;
    }
    s_a.sa_flags=0;
    retval=sigaction(UPDATE_SIGNAL,&s_a,NULL);

    if (sigemptyset(&s_a.sa_mask)) {
        syslog(LOG_ERR,"problem in sigemptyset: %s -- exiting",
               strerror(errno));
        return 1;
    }
    if (sigaddset(&s_a.sa_mask,UPDATE_SIGNAL)) {
        syslog(LOG_ERR,"problem in sigaddset: %s -- exiting %s",
               argv[0],strerror(errno));
        return 1;
    }
    r=sigprocmask(SIG_BLOCK,&s_a.sa_mask,NULL);
    if (r) {
        syslog(LOG_ERR,"sigprocmask: %s",strerror(errno));
    }

    syslog(LOG_INFO,"*** started ***");

    update_interfaces();

    while (1) {
        r=sigprocmask(SIG_UNBLOCK,&s_a.sa_mask,NULL);
        if (r) {
            /* while blocked: */
            update_interfaces();

            syslog(LOG_INFO,"sigprocmask (unblock): %s",
                   strerror(errno));
            /* try until sigprocmask is not interrupted by a
             * signal */
            while (sigprocmask(SIG_UNBLOCK,&s_a.sa_mask,NULL)) ;
        }

        memcpy(&work_fd_set,&select_set.fds,sizeof(fd_set));
        retval=select(select_set.highest_fd+1,&work_fd_set,
                      NULL,NULL,NULL);
        r=sigprocmask(SIG_BLOCK,&s_a.sa_mask,NULL);
        if (r) {
            syslog(LOG_INFO,"sigprocmask (block): %s",
                   strerror(errno));
            /* try until sigprocmask is not interrupted by a
             * signal */
            while (sigprocmask(SIG_BLOCK,&s_a.sa_mask,NULL)) ;

            /* when blocked: */
            update_interfaces();
        }

        /* a signal came in after we unblocked
         * or before we blocked? we may process one packet before
         * the list gets updated, but we do this check here never-
         * theless in order to not catch a signal during some
         * system call in update_interfaces
         */
        if (update_interface_trigger) {
            update_interfaces();
        }

        if (retval==-1) {
            if (errno==EINTR) {
                update_interfaces();
            } else if (errno) {
                syslog(LOG_WARNING,"select returned with %s",
                       strerror(errno));
            }
            continue; /* fds are undefined -> no packets came
				     in at this time */
        }

        /* check all fds regardless of retval */
        for (i_s=select_set.i_s_list; i_s; i_s=i_s->next) {
            if (FD_ISSET(i_s->i_fd,&work_fd_set)) {
                process_packet(i_s);
            }
        }
    }

    /* cleanup... no. */
}