Revision 8751763c
Added by Chris Buechler over 16 years ago
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
merge Ermal's CP locking changes