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; }
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. */ }