Project

General

Profile

« Previous | Next » 

Revision 8751763c

Added by Chris Buechler over 16 years ago

merge Ermal's CP locking changes

View differences:

etc/inc/captiveportal.inc
46 46
function captiveportal_configure() {
47 47
	global $config, $g;
48 48

  
49
	$captiveportallck = lock('captiveportal');
50

  
49 51
	if (isset($config['captiveportal']['enable']) &&
50 52
		(($config['captiveportal']['interface'] == "lan") ||
51 53
			isset($config['interfaces'][$config['captiveportal']['interface']]['enable']))) {
......
81 83
                        mwexec("kldload dummynet");
82 84

  
83 85
		/* stop accounting on all clients */
84
		captiveportal_radius_stop_all();
86
		captiveportal_radius_stop_all(true);
85 87

  
86 88
		/* initialize minicron interval value */
87 89
		$croninterval = $config['captiveportal']['croninterval'] ? $config['captiveportal']['croninterval'] : 60;
......
229 231
			"/etc/rc.prunecaptiveportal");
230 232

  
231 233
		/* generate passthru mac database */
232
		captiveportal_passthrumac_configure();
234
		captiveportal_passthrumac_configure(true);
233 235
		/* create allowed ip database and insert ipfw rules to make it so */
234
		captiveportal_allowedip_configure();
236
		captiveportal_allowedip_configure(true);
235 237

  
236 238
		/* generate radius server database */
237 239
		if ($config['captiveportal']['radiusip'] && (!isset($config['captiveportal']['auth_method']) ||
......
277 279
		killbypid("{$g['varrun_path']}/lighty-CaptivePortal.pid");
278 280
		killbypid("{$g['varrun_path']}/minicron.pid");
279 281

  
280
		captiveportal_radius_stop_all();
282
		captiveportal_radius_stop_all(true);
281 283

  
282 284
		mwexec("/sbin/sysctl net.link.ether.ipfw=0");
283 285

  
......
298 300
			mwexec("/sbin/ipfw -f delete set 3");
299 301
		}
300 302
	}
301

  
302
    captiveportal_unlock();
303
	unlock($captiveportallck);
303 304

  
304 305
	return 0;
305 306
}
......
458 459
    if (!$timeout && !$idletimeout && !isset($config['captiveportal']['reauthenticate']) && !isset($config['captiveportal']['radiussession_timeout']))
459 460
        return;
460 461

  
461
    captiveportal_lock();
462
    $captiveportallck = lock('captiveportal');
462 463

  
463 464
    /* read database */
464 465
    $cpdb = captiveportal_read_db();
......
585 586
    /* write database */
586 587
    captiveportal_write_db($cpdb);
587 588

  
588
    captiveportal_unlock();
589
    unlock($captiveportallck);
589 590
}
590 591

  
591 592
/* remove a single client according to the DB entry */
......
632 633

  
633 634
	global $g, $config;
634 635

  
635
	captiveportal_lock();
636
	$captiveportallck = lock('captiveportal');
636 637

  
637 638
	/* read database */
638 639
	$cpdb = captiveportal_read_db();
......
651 652
	/* write database */
652 653
	captiveportal_write_db($cpdb);
653 654

  
654
	captiveportal_unlock();
655
	unlock($captiveportallck);
655 656
}
656 657

  
657 658
/* send RADIUS acct stop for all current clients */
658
function captiveportal_radius_stop_all() {
659
function captiveportal_radius_stop_all($lock = false) {
659 660
	global $g, $config;
660 661

  
661 662
	if (!isset($config['captiveportal']['radacct_enable']))
662 663
		return;
663 664

  
664
	captiveportal_lock();
665
	if (!$lock)
666
		$captiveportallck = lock('captiveportal');
667

  
665 668
	$cpdb = captiveportal_read_db();
666 669

  
667 670
	$radiusservers = captiveportal_get_radius_servers();
......
680 683
								   7); // Admin Reboot
681 684
		}
682 685
	}
683
	captiveportal_unlock();
686
	if (!$lock)
687
		unlock($captiveportallck);
684 688
}
685 689

  
686
function captiveportal_passthrumac_configure() {
690
function captiveportal_passthrumac_configure($lock = false) {
687 691
	global $config, $g;
688 692

  
689
	captiveportal_lock();
693
	if (!$lock)
694
		$captiveportallck = lock('captiveportal');
690 695

  
691 696
	/* clear out passthru macs, if necessary */
692 697
	unlink_if_exists("{$g['vardb_path']}/captiveportal_mac.db");
......
696 701
		$fd = @fopen("{$g['vardb_path']}/captiveportal_mac.db", "w");
697 702
		if (!$fd) {
698 703
			printf("Error: cannot open passthru mac DB file in captiveportal_passthrumac_configure().\n");
699
			captiveportal_unlock();
704
			if (!$lock)
705
				unlock($captiveportallck);
700 706
			return 1;
701 707
		}
702 708

  
......
725 731
			mwexec("/sbin/ipfw add 50 skipto 29900 ip from any to any MAC any {$ptm['mac']} keep-state");
726 732
		}
727 733
	}
728

  
729
	captiveportal_unlock();
734
	if (!$lock)
735
		unlock($captiveportallck);
730 736

  
731 737
	return 0;
732 738
}
733 739

  
734
function captiveportal_allowedip_configure() {
740
function captiveportal_allowedip_configure($lock = false) {
735 741
	global $config, $g;
736 742

  
737
	captiveportal_lock();
743
	if (!$lock)
744
		$captiveportallck = lock('captiveportal');
738 745

  
739 746
	/* clear out existing allowed ips, if necessary */
740 747
	if (file_exists("{$g['vardb_path']}/captiveportal_ip.db")) {
......
763 770
		$fd = @fopen("{$g['vardb_path']}/captiveportal_ip.db", "w");
764 771
		if (!$fd) {
765 772
			printf("Error: cannot open allowed ip DB file in captiveportal_allowedip_configure().\n");
766
			captiveportal_unlock();
773
			if (!$lock)
774
				unlock($captiveportallck);
767 775
			return 1;
768 776
		}
769 777

  
......
775 783
            if (is_null($ruleno)) {
776 784
                printf("Error: system reached maximum login capacity, no free FW rulenos in captiveportal_allowedip_configure().\n");
777 785
                fclose($fd);
778
                captiveportal_unlock();
786
		if (!$lock)
787
			unlock($captiveportallck);
779 788
                return 1;
780 789
            }
781 790

  
......
796 805
        fclose($fd);
797 806
    }
798 807

  
799
    captiveportal_unlock();
808
	if (!$lock)
809
		unlock($captiveportallck);
800 810
    return 0;
801 811
}
802 812

  
......
843 853
        return false;
844 854
}
845 855

  
846
/* lock captive portal information, decide that the lock file is stale after 
847
   10 minutes and EXIT the process to not risk dataloss, issue warning in syslog every 1 minutes */
848
function captiveportal_lock() {
849

  
850
        global $lockfile;
851

  
852
        $n = 1;
853
        while ($n) {
854
                /* open the lock file in append mode to avoid race condition */
855
                if ($fd = @fopen($lockfile, "x")) {
856
                        /* succeeded */
857
                        fclose($fd);
858
						if($n > 10) {
859
						    captiveportal_syslog("LOCKINFO: Waiting for lock for $n seconds/s!");
860
						}
861
                        return;
862
                } else {
863
                        /* file locked, wait and try again */
864
                        sleep(1);
865

  
866
						if(($n % 60) == 0) {
867
						    captiveportal_syslog("LOCKWARNING: waiting for lock for " . $n/60 . " minute/s!");
868
						    if(($n % 600) == 0) {
869
						        captiveportal_syslog("LOCKERROR: waiting for lock for 10 minute/s - EXITING PROCESS!");
870
						        die("Can't get a lock");
871
						    }
872
					    }
873
                }
874
                $n++;
875
        }
876
		/* we never get here */
877
}
878

  
879
/* unlock captive portal information file */
880
function captiveportal_unlock() {
881

  
882
        global $lockfile;
883

  
884
        if (file_exists($lockfile))
885
                unlink($lockfile);
886
}
887

  
888 856
/* log successful captive portal authentication to syslog */
889 857
/* part of this code from php.net */
890 858
function captiveportal_logportalauth($user,$mac,$ip,$status, $message = null) {
......
912 880
    global $g, $config;
913 881

  
914 882
    /* Start locking from the beginning of an authentication session */
915
    captiveportal_lock();
883
    $captiveportallck = lock('captiveportal');
916 884

  
917 885
    $ruleno = captiveportal_get_next_ipfw_ruleno();
918 886

  
887
    unlock($captiveportallck);
888

  
919 889
    /* if the pool is empty, return apprioriate message and fail authentication */
920 890
    if (is_null($ruleno)) {
921 891
        $auth_list = array();
922 892
        $auth_list['auth_val'] = 1;
923 893
        $auth_list['error'] = "System reached maximum login capacity";
924
        captiveportal_unlock();
925 894
        return $auth_list;
926 895
    }
927 896

  
......
934 903
                    $clientmac,
935 904
                    $ruleno);
936 905

  
906

  
907
	$captiveportallck = lock('captiveportal');
937 908
    if ($auth_list['auth_val'] == 2) {
938 909
        captiveportal_logportalauth($username,$clientmac,$clientip,$type);
939 910
        $sessionid = portal_allow($clientip,
......
943 914
                    $auth_list,
944 915
                    $ruleno);
945 916
    }
946
    else {
947
        captiveportal_unlock();
948
    }
917

  
918
    unlock($captiveportallck);
949 919

  
950 920
    return $auth_list;
951 921

  
......
956 926

  
957 927
        global $g;
958 928

  
959
        $cpdb = array();
929
	$cpdb = array();
960 930
        $fd = @fopen("{$g['vardb_path']}/captiveportal.db", "r");
961 931
        if ($fd) {
962 932
                while (!feof($fd)) {
......
1134 1104
    return FALSE ;
1135 1105
}
1136 1106

  
1137
?>
1107
?>
etc/inc/util.inc
343 343
        return $iflist;
344 344
}
345 345

  
346
/* lock configuration file */
347
function lock($lock) {
348
        global $g, $cfglckkeyconsumers;
349
        
350
        if (!$lock)
351
                die("WARNING: You must give a name as parameter to lock() function.");
352
        if (!file_exists("{$g['tmp_path']}/{$lock}.lock"))
353
                @touch("{$g['tmp_path']}/{$lock}.lock");
354
        $config_lock_key = ftok("{$g['tmp_path']}/{$lock}.lock", 'a');
355
        $cfglckkey = sem_get($config_lock_key, 1);
356
        $cfglckkeyconsumers++;
357
        if (!sem_acquire($cfglckkey)) {
358
                log_error("WARNING: lock() -  Could not acquire {$lock} lock!");
359
                sem_remove($cfglckkey);
360
                return NULL;
361
        } else if ($g['debug'])
362
                log_error("lock() -  Got {$file} lock.");
363

  
364
        return $cfglckkey;
365
}
366

  
367
/* unlock configuration file */
368
function unlock($cfglckkey = 0) {
369
        global $g, $cfglckkeyconsumers;
370

  
371
        if (!$cfglckkey)
372
                return;
373

  
374
        if (!sem_release($cfglckkey))
375
                log_error("WARNING: unlock() - Could not unlock lock.");
376
        else {
377
                if ($g['debug'])
378
                        log_error("Released lock.");
379
                sem_remove($cfglckkey);
380
        }
381
        $cfglckkeyconsumers--;
382
}
383

  
346 384
/* wrapper for exec() */
347 385
function mwexec($command, $mute = true) {
348 386

  
usr/local/captiveportal/index.php
219 219
    global $redirurl, $g, $config, $url_redirection, $type;
220 220

  
221 221
    /* See if a ruleno is passed, if not start locking the sessions because this means there isn't one atm */
222
	$lockedcpnow = false;
222 223
    if ($ruleno == null) {
223
        captiveportal_lock();
224
	$cplock = lock('captiveportal');
225
	$lockedcpnow = true;
224 226
        $ruleno = captiveportal_get_next_ipfw_ruleno();
225 227
    }
226 228

  
......
228 230
    if (is_null($ruleno)) {
229 231
        portal_reply_page($redirurl, "error", "System reached maximum login capacity");
230 232
        log_error("WARNING!  Captive portal has reached maximum login capacity");
231
        captiveportal_unlock();
233
	if ($lockedcpnow == true)
234
		unlock($cplock);
232 235
        exit;
233 236
    }
234 237

  
......
325 328
    /* rewrite information to database */
326 329
    captiveportal_write_db($cpdb);
327 330

  
331
	    if ($lockedcpnow == true) 
332
		unlock($cplock);
328 333
    /* redirect user to desired destination */
329 334
    if ($url_redirection)
330 335
        $my_redirurl = $url_redirection;
......
373 378

  
374 379
EOD;
375 380
    } else {
376
		captiveportal_unlock();
377 381
        header("Location: " . $my_redirurl);
378 382
		return $sessionid;
379 383
    }
380
    captiveportal_unlock();
381 384
    return $sessionid;
382 385
}
383 386

  
......
390 393

  
391 394
    global $g, $config;
392 395

  
393
    captiveportal_lock();
396
    $cplock = lock('captiveportal');
397

  
394 398
    /* read database */
395 399
    $cpdb = captiveportal_read_db();
396 400

  
......
409 413
    /* write database */
410 414
    captiveportal_write_db($cpdb);
411 415

  
412
    captiveportal_unlock();
416
    unlock($cplock);
413 417
}
414 418

  
415
?>
419
?>
usr/local/www/status_captiveportal.php
57 57
}
58 58

  
59 59
$cpdb = array();
60
captiveportal_lock();
61
$fp = @fopen("{$g['vardb_path']}/captiveportal.db","r");
62

  
63
if ($fp) {
64
	while (!feof($fp)) {
65
		$line = trim(fgets($fp));
66
		if ($line) {
67
			$cpent = explode(",", $line);
68
			if ($_GET['showact'])
69
				$cpent[5] = captiveportal_get_last_activity($cpent[1]);
70
			$cpdb[] = $cpent;
71
		}
72
	}
73
	
74
	fclose($fp);
75
	
76
	if ($_GET['order']) {
77
		if ($_GET['order'] == "ip")
78
			$order = 2;
79
		else if ($_GET['order'] == "mac")
80
			$order = 3;
81
		else if ($_GET['order'] == "user")
82
			$order = 4;
83
		else if ($_GET['order'] == "lastact")
84
			$order = 5;
85
		else
86
			$order = 0;
87
		usort($cpdb, "clientcmp");
88
	}
60
$cpcontents = file("/var/db/captiveportal.db", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
61
foreach ($cpcontents as $cpcontent) {
62
        $cpent = explode(",", $cpcontent);
63
        if ($_GET['showact'])
64
                $cpent[5] = captiveportal_get_last_activity($cpent[1]);
65
                $cpdb[] = $cpent;
66
}
67
if ($_GET['order']) {
68
        if ($_GET['order'] == "ip")
69
                $order = 2;
70
        else if ($_GET['order'] == "mac")
71
                $order = 3;
72
        else if ($_GET['order'] == "user")
73
                $order = 4;
74
        else if ($_GET['order'] == "lastact")
75
                $order = 5;
76
        else
77
                $order = 0;
78
        usort($cpdb, "clientcmp");
89 79
}
90
captiveportal_unlock();
91 80
?>
92 81
<table class="sortable" width="100%" border="0" cellpadding="0" cellspacing="0">
93 82
  <tr>

Also available in: Unified diff