
#include "captive.h"



/* This program is intended to be run by cron every few minutes.

   It opens the database of currently logged in users, and looks to
   see if any of them have exceeded their time.  If so, the iptables
   rules that granted them red-side access are deleted, forcing them
   to login again.

   The database functions are from the GNU gdbm library.  See the
   comment at the start of captive_adduser.c for more info.
*/



int main( int argc, char *argv[] ) {
	GDBM_FILE dbf;
	datum key, nextkey;
	datum content;
	time_t tp;
	long login_expires_at;


	time( &tp );

	dbf = gdbm_open( "/var/smoothwall/mods/captive/captivedb", 512, GDBM_WRITER, S_IRWXU, NULL );
	if( dbf == NULL ) {
		fprintf( stderr, "Error opening logindb\n" );
		exit(0);
	}


	/* This loop goes through all records in the database, in some unpredictable
           order.  All records are guaranteed to be visited, if we don't delete or
	   change any records partway through.  Therefore, records destined for
	   deletion are put in the user array and deleted later, not immediately. */

	key = gdbm_firstkey ( dbf );
	if( key.dptr != NULL ) key.dptr[key.dsize] = '\0';   /* Add null term, just to be safe. */

	while ( key.dptr ) {
		content = gdbm_fetch( dbf, key );

		if( content.dptr != NULL ) {
			login_expires_at = ((userinfo *)content.dptr)->login_expires_at;
			if( (login_expires_at != 0) && (login_expires_at < (long)tp) ) {

				/* This client's login period has expired.  Delete
				   the associated iptables rules (now) and remove from
				   logindb (later, lest we mess up the sorta-sequential
				   access of all records). */

				iptables_rule( IPTABLES_DEL, ((userinfo *)content.dptr)->ip, ((userinfo *)content.dptr)->mac );

				post_to_log( EVENT_LOGOFF_TIMED, key.dptr, ((userinfo *)content.dptr)->ip,((userinfo *)content.dptr)->mac, (long)tp );

				if( ((userinfo *)content.dptr)->enabled == 2 )
					((userinfo *)content.dptr)->enabled = 0;
				((userinfo *)content.dptr)->logged_in_now = 0;
				((userinfo *)content.dptr)->ip[0] = '\0';
				((userinfo *)content.dptr)->mac[0] = '\0';
				((userinfo *)content.dptr)->login_expires_at = 0;

				gdbm_store( dbf, key, content, GDBM_REPLACE );

			}
			free( content.dptr );

		} else {
			printf( "Error reading captivedb\n" );
			exit(0);
		}

		nextkey = gdbm_nextkey ( dbf, key );
		key = nextkey;
		if( key.dptr != NULL ) key.dptr[key.dsize] = '\0';   /* Add null term, just to be safe. */
	}

	gdbm_close( dbf );


	return 0;
}


