コード例 #1
0
ファイル: io.c プロジェクト: ebichu/dd-wrt
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;
}