void poll_loop(void) { ITF *itf,*next_itf; ENTRY *entry,*next_entry; VCC *vcc,*next_vcc; int fds,ret; gettimeofday(&now,NULL); while (1) { FD_ZERO(&rset); FD_ZERO(&cset); FD_SET(kernel,&rset); FD_SET(unix_sock,&rset); if (incoming >= 0) FD_SET(incoming,&rset); fds = incoming+1; if (kernel >= fds) fds = kernel+1; if (unix_sock >= fds) fds = unix_sock+1; for (itf = itfs; itf; itf = itf->next) for (entry = itf->table; entry; entry = entry->next) for (vcc = entry->vccs; vcc; vcc = vcc->next) { if (vcc->connecting) FD_SET(vcc->fd,&cset); else FD_SET(vcc->fd,&rset); if (vcc->fd >= fds) fds = vcc->fd+1; } for (entry = unknown_incoming; entry; entry = entry->next) { if (!entry->vccs || entry->vccs->next) { diag(COMPONENT,DIAG_ERROR,"internal error: bad unknown entry"); continue; } FD_SET(entry->vccs->fd,&rset); if (entry->vccs->fd >= fds) fds = entry->vccs->fd+1; } for (vcc = unidirectional_vccs; vcc; vcc = vcc->next) { FD_SET(vcc->fd,&rset); if (vcc->fd >= fds) fds = vcc->fd+1; } ret = select(fds,&rset,&cset,NULL,next_timer()); /* * Now here's something strange: < 0.32 needed the exception mask to be NULL * in order to work, due to a bug in atm_select. In 0.32, this has been fixed. * Also, 2.1 kernels use the poll mechanism and not select, so select is * emulated on top of poll. Now the funny bit is that, as soon as the exception * set is non-NULL, when a non-blocking connect finishes, select returns one * but has none if the possible bits set in either rset or cset. To make things * even stranger, no exception is actually found in sys_select, so this must be * some very odd side-effect ... The work-around for now is to simply pass NULL * for the exception mask (which is the right thing to do anyway, but it'd be * nice if doing a perfectly valid variation wouldn't blow up the system ...) */ #if 0 { int i; for (i = 0; i < sizeof(rset); i++) fprintf(stderr,"%02x:%02x ",((unsigned char *) &rset)[i], ((unsigned char *) &cset)[i]); fprintf(stderr,"\n"); } #endif if (ret < 0) { if (errno != EINTR) perror("select"); } else { diag(COMPONENT,DIAG_DEBUG,"----------"); gettimeofday(&now,NULL); if (FD_ISSET(kernel,&rset)) recv_kernel(); if (FD_ISSET(unix_sock,&rset)) recv_unix(); if (incoming >= 0 && FD_ISSET(incoming,&rset)) accept_new(); for (itf = itfs; itf; itf = next_itf) { next_itf = itf->next; for (entry = itf->table; entry; entry = next_entry) { next_entry = entry->next; for (vcc = entry->vccs; vcc; vcc = next_vcc) { next_vcc = vcc->next; if (FD_ISSET(vcc->fd,&rset)) recv_vcc(vcc); else if (FD_ISSET(vcc->fd,&cset)) complete_connect(vcc); } } } for (entry = unknown_incoming; entry; entry = next_entry) { next_entry = entry->next; if (FD_ISSET(entry->vccs->fd,&rset)) recv_vcc(entry->vccs); } for (vcc = unidirectional_vccs; vcc; vcc = next_vcc) { next_vcc = vcc->next; if (FD_ISSET(vcc->fd,&rset)) drain_vcc(vcc); } expire_timers(); /* expire timers after handling messages to make sure we don't time out unnecessarily because of scheduling delays */ } table_changed(); } }
int main ( int argc, char * argv[] ) { int have_committed = 1; // prevent double commits, 'clean' state to begin with int c; program_name = argv[0]; program_name = "ipbatch CLI"; // this is really important for locating shared libs program_version = IPTABLES_VERSION; c = xtables_init_all(&iptables_globals, NFPROTO_IPV4); if (c < 0) { fprintf(stderr, "%s/%s Failed to initialize xtables\n", program_name, program_version); exit(1); } openlog( "SmoothIPSubsys", LOG_NDELAY | LOG_CONS, LOG_DAEMON ); /* lib_dir = getenv("IPTABLES_LIB_DIR");*/ /* if (!lib_dir)*/ /* lib_dir = IPT_LIB_DIR;*/ /* read lines from STDIN */ char buffer[ BUFFER_SIZE ]; int error = 0; // syslog( LOG_ERR, "Checking input" ); // there are two special commands end is the same as eof and commit // does an early commit rather than the changes only being committed at the end while ( fgets( buffer, BUFFER_SIZE - 2, stdin ) != NULL ){ /* terminate the line at the carriage return */ if ( strlen( buffer ) > BUFFER_SIZE ){ // silently ignore long lines continue; } buffer[ strlen( buffer ) - 1 ] = '\0'; //syslog( LOG_ERR, "Received command %s", buffer ); if ( strcmp( buffer, "end" ) == 0 ){ break; } if ( strcmp( buffer, "commit" ) == 0 ){ /* commit changes */ error = iptc_commit(handle); iptc_free(handle); handle = NULL; have_committed = 1; } else { /* excute the command */ if(!have_committed) { if(table_changed(buffer)) { //syslog( LOG_ERR, "Table change for %s", buffer ); error = iptc_commit(handle); iptc_free(handle); handle = NULL; have_committed = 1; } } if(*buffer) error = execute( buffer ); have_committed = 0; } if ( !error ){ /* if an error has occured then we're */ /* in trouble and might as well just */ /* leave */ syslog( LOG_ERR, "error: %s", iptc_strerror(errno)); return !error; } } //syslog( LOG_ERR, "Finished" ); /* commit the changes, that is flush */ /* the iptables buffer */ if(!have_committed) { error = iptc_commit(handle); iptc_free(handle); handle = NULL; syslog( LOG_ERR, "Unable to commit IPTables rules \"%s\"", iptc_strerror( errno ) ); } return !error; }