Broadcast bridge
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

742 lines
18KB

  1. #!/usr/bin/php
  2. <?php
  3. // file positionen
  4. define('NEWFILE', 'http://10.10.254.100/bridge/config.php?bridgeid=22');
  5. define('OLDFILE', '/var/www/bridge/.config.old');
  6. // rrdsrv on 5001/tcp
  7. define('RRDSRV', "10.10.254.100");
  8. class Cmd {
  9. function run($args) {
  10. echo "$args\n";
  11. exec($args, $tmp);
  12. return $tmp;
  13. }
  14. function ebtables($args) {
  15. return self::run("/sbin/ebtables {$args}");
  16. }
  17. function brctl($args) {
  18. return self::run("/usr/sbin/brctl {$args}");
  19. }
  20. function vconfig($args) {
  21. return self::run("/sbin/vconfig {$args}");
  22. }
  23. function ifconfig($args) {
  24. return self::run("/sbin/ifconfig {$args}");
  25. }
  26. function route($args) {
  27. return self::run("/sbin/route {$args}");
  28. }
  29. function tc($args) {
  30. return self::run("/sbin/tc {$args}");
  31. }
  32. function vtund($args) {
  33. return self::run("/usr/sbin/vtund {$args}");
  34. }
  35. function ip($args) {
  36. return self::run("/sbin/ip {$args}");
  37. }
  38. }
  39. class Config {
  40. function fetch() {
  41. $data = @file_get_contents(NEWFILE);
  42. if (empty($data))
  43. return false;
  44. $arr = @unserialize($data);
  45. if (!is_array($arr))
  46. return false;
  47. return $arr;
  48. }
  49. function getOld() {
  50. if (!file_exists(OLDFILE))
  51. return false;
  52. $data = @file_get_contents(OLDFILE);
  53. $arr = @unserialize($data);
  54. if (!is_array($arr))
  55. return false;
  56. return $arr;
  57. }
  58. function getEmpty() {
  59. return array(
  60. 'bridge' => array(),
  61. 'tunnel' => array(),
  62. 'vlan' => array(),
  63. 'hlsw' => array(),
  64. 'forward' => array()
  65. );
  66. }
  67. function save($arr) {
  68. if ($arr == self::getEmpty())
  69. return;
  70. if (!$fp = @fopen(OLDFILE, "w")) {
  71. echo "write error\n";
  72. return;
  73. }
  74. fwrite($fp, @serialize($arr));
  75. fclose($fp);
  76. }
  77. }
  78. class BaseTables {
  79. function init($bridge) {
  80. // bridge present?
  81. if (!is_dir("/sys/class/net/br0")) {
  82. // create bridge
  83. Cmd::brctl("addbr br0");
  84. } else {
  85. // delete all subdevices
  86. $dir = opendir("/sys/class/net/br0/brif");
  87. while ($dir !== false && (($file = readdir($dir)) !== false)) {
  88. if ($file == "." || $file == "..")
  89. continue;
  90. Cmd::brctl("delif br0 {$file}");
  91. }
  92. closedir($dir);
  93. }
  94. // bridge init
  95. Cmd::brctl("setfd 2");
  96. Cmd::ifconfig("br0 0.0.0.0 up");
  97. // delete all rules & chains
  98. Cmd::ebtables("-t nat -F");
  99. Cmd::ebtables("-t nat -X");
  100. Cmd::ebtables("-t filter -F");
  101. Cmd::ebtables("-t filter -X");
  102. Cmd::ebtables("-t nat -N loop_pkts");
  103. Cmd::ebtables("-t nat -A loop_pkts -j DROP");
  104. // TODO: tap_block wird pakete * interfaces durchlaufen
  105. Cmd::ebtables("-t filter -N tap_block");
  106. Cmd::ebtables("-t filter -A tap_block -j RETURN");
  107. // eigene pakete empfangen -> loop
  108. Cmd::ebtables("-t nat -A PREROUTING -s {$bridge['macmask']} -j loop_pkts");
  109. }
  110. function add_tunnel($tunnels) {
  111. foreach ($tunnels as $tunnel) {
  112. // pakete durch tunnel von anderer Bridge -> ok
  113. // pakete von anderen Bridges auf normalen ports -> loop
  114. Cmd::ebtables("-t nat -A PREROUTING -i {$tunnel['device']} -j ACCEPT");
  115. Cmd::ebtables("-t nat -A PREROUTING -s {$tunnel['macmask']} -j loop_pkts");
  116. // wenns ausm tunnel kommt, nicht in nen tunnel stecken
  117. Cmd::ebtables("-t filter -A FORWARD -i {$tunnel['device']} -j tap_block");
  118. Cmd::ebtables("-t filter -I tap_block 1 -o {$tunnel['device']} -j DROP");
  119. }
  120. // ansonsten alles in den tunnel packen
  121. foreach ($tunnels as $tunnel)
  122. Cmd::ebtables("-t filter -A FORWARD -o {$tunnel['device']} -j ACCEPT");
  123. }
  124. }
  125. class ForwardTables {
  126. function init() {
  127. // delete all vlan devices
  128. $dir = opendir("/sys/class/net/");
  129. while ($dir !== false && (($file = readdir($dir)) !== false)) {
  130. if ($file == "." || $file == "..")
  131. continue;
  132. if (strncmp($file, "eth", 3))
  133. continue;
  134. $part = explode('.', $file);
  135. if (!isset($part[1]))
  136. continue;
  137. $address = Cmd::ip("-4 addr show dev ${file}");
  138. if (count($address))
  139. continue;
  140. Cmd::ifconfig("{$file} down");
  141. Cmd::vconfig("rem {$file}");
  142. }
  143. closedir($dir);
  144. Cmd::ebtables("-t nat -N hlswmaster");
  145. Cmd::ebtables("-t nat -A hlswmaster -j DROP");
  146. Cmd::ebtables("-t nat -N arp_pkts");
  147. Cmd::ebtables("-t nat -A arp_pkts -j DROP");
  148. Cmd::ebtables("-t nat -N nonip_pkts");
  149. Cmd::ebtables("-t nat -A nonip_pkts -j DROP");
  150. Cmd::ebtables("-t nat -N udp_blocked");
  151. Cmd::ebtables("-t nat -A udp_blocked -j DROP");
  152. Cmd::ebtables("-t nat -N udp_forwarded");
  153. Cmd::ebtables("-t nat -A udp_forwarded -j ACCEPT");
  154. Cmd::ebtables("-t nat -N fwdfilter");
  155. Cmd::ebtables("-t nat -A fwdfilter -j udp_blocked");
  156. Cmd::ebtables("-t filter -N hlswmaster");
  157. Cmd::ebtables("-t filter -A hlswmaster -j DROP");
  158. // allow hlsw-master-querys from all clients
  159. // but forward them only to our masters
  160. Cmd::ebtables("-t nat -A PREROUTING -p ipv4 --ip-proto udp --ip-dport 7140 -j ACCEPT");
  161. Cmd::ebtables("-t filter -A FORWARD -p ipv4 --ip-proto udp --ip-dport 7140 -j hlswmaster");
  162. // only allow hlsw-querys from master servers
  163. Cmd::ebtables("-t nat -A PREROUTING -p ipv4 --ip-proto udp --ip-sport 7130:7139 -j hlswmaster");
  164. // udp broadcast und multicast filtern
  165. Cmd::ebtables("-t nat -A PREROUTING -p ipv4 --ip-proto udp --ip-dst 255.255.255.255 -j fwdfilter");
  166. Cmd::ebtables("-t nat -A PREROUTING -p ipv4 --ip-proto udp --ip-dst 224.0.0.0/8 -j fwdfilter");
  167. // udp unicast (falsche netmask beim client) blocken
  168. Cmd::ebtables("-t nat -A PREROUTING -p ipv4 --ip-proto udp -j udp_blocked");
  169. // andere protos fuer stats auseinandernehmen
  170. Cmd::ebtables("-t nat -A PREROUTING -p arp -j arp_pkts");
  171. Cmd::ebtables("-t nat -A PREROUTING -j nonip_pkts");
  172. }
  173. private function add_hlsw($hlsw) {
  174. Cmd::ebtables("-t nat -I hlswmaster 1 -p ipv4 --ip-src {$hlsw['ip']} -j ACCEPT");
  175. Cmd::ebtables("-t filter -I hlswmaster 1 -o {$hlsw['dev']} -j ACCEPT");
  176. }
  177. private function del_hlsw($hlsw) {
  178. Cmd::ebtables("-t nat -D hlswmaster -p ipv4 --ip-src {$hlsw['ip']} -j ACCEPT");
  179. Cmd::ebtables("-t filter -D hlswmaster -o {$hlsw['dev']} -j ACCEPT");
  180. }
  181. private function add_vlan($vlan) {
  182. // vlan 0 and vlan 1 are invalid -> use basename (eth1.1 -> eth1)
  183. $part = explode('.', $vlan['name']);
  184. if (isset($part[1]) && ($part[1] >= 2)) {
  185. Cmd::ifconfig("{$part[0]} 0.0.0.0 up");
  186. Cmd::vconfig("add {$part[0]} {$part[1]}");
  187. }
  188. // add device to bridge
  189. Cmd::ifconfig("{$vlan['name']} 0.0.0.0 up");
  190. Cmd::brctl("addif br0 {$vlan['name']}");
  191. // TODO: bei echten devices kann qdisc noch vorhanden sein
  192. Cmd::tc("qdisc add dev {$vlan['name']} root tbf rate {$vlan['bw']}kbit burst 4k latency 100ms");
  193. // stats
  194. Cmd::ebtables("-t nat -I loop_pkts 1 -i {$vlan['name']} -j DROP");
  195. Cmd::ebtables("-t nat -I arp_pkts 1 -i {$vlan['name']} -j DROP");
  196. Cmd::ebtables("-t nat -I nonip_pkts 1 -i {$vlan['name']} -j DROP");
  197. Cmd::ebtables("-t nat -I udp_blocked 1 -i {$vlan['name']} -j DROP");
  198. Cmd::ebtables("-t nat -I udp_forwarded 1 -i {$vlan['name']} -j ACCEPT");
  199. // ausgehende src-mac anpassen fuer loop detection
  200. // und damit non-cisco HW funktionieren wuerde :)
  201. Cmd::ebtables("-t nat -I POSTROUTING 1 -o {$vlan['name']} -j snat --to-source {$vlan['mac']}");
  202. }
  203. private function del_vlan($vlan) {
  204. // remove from bridge
  205. Cmd::brctl("delif br0 {$vlan['name']}");
  206. Cmd::ifconfig("{$vlan['name']} down");
  207. // remove vlan
  208. $part = explode('.', $vlan['name']);
  209. if (isset($part[1]) && ($part[1] >= 2))
  210. Cmd::vconfig("rem {$vlan['name']}");
  211. // stats
  212. Cmd::ebtables("-t nat -D loop_pkts -i {$vlan['name']} -j DROP");
  213. Cmd::ebtables("-t nat -D arp_pkts -i {$vlan['name']} -j DROP");
  214. Cmd::ebtables("-t nat -D nonip_pkts -i {$vlan['name']} -j DROP");
  215. Cmd::ebtables("-t nat -D udp_blocked -i {$vlan['name']} -j DROP");
  216. Cmd::ebtables("-t nat -D udp_forwarded -i {$vlan['name']} -j ACCEPT");
  217. // snat mac
  218. Cmd::ebtables("-t nat -D POSTROUTING -o {$vlan['name']} -j snat --to-source {$vlan['mac']}");
  219. }
  220. private function add_fwd($fwd) {
  221. $port = $fwd['portlo'];
  222. if ($fwd['porthi'] != 0)
  223. $port .= ':'.$fwd['porthi'];
  224. $target = ($fwd['active'] ? "udp_forwarded" : "udp_blocked");
  225. Cmd::ebtables("-t nat -I fwdfilter 1 -p ipv4 --ip-proto udp --ip-dport {$port} -j {$target}");
  226. }
  227. private function del_fwd($fwd) {
  228. $port = $fwd['portlo'];
  229. if ($fwd['porthi'] != 0)
  230. $port .= ':'.$fwd['porthi'];
  231. $target = ($fwd['active'] ? "udp_forwarded" : "udp_blocked");
  232. Cmd::ebtables("-t nat -D fwdfilter -p ipv4 --ip-proto udp --ip-dport {$port} -j {$target}");
  233. }
  234. function checkDiff($old, $new) {
  235. $oldarr = $old['vlan'];
  236. $newarr = $new['vlan'];
  237. foreach ($newarr as $id => $tmp) {
  238. if (!isset($oldarr[$id])) {
  239. self::add_vlan($tmp);
  240. } else if ($tmp !== $oldarr[$id]) {
  241. // TODO: this is slow
  242. self::del_vlan($oldarr[$id]);
  243. self::add_vlan($tmp);
  244. }
  245. }
  246. foreach ($oldarr as $id => $tmp) {
  247. if (!isset($newarr[$id]))
  248. self::del_vlan($tmp);
  249. }
  250. $oldarr = $old['forward'];
  251. $newarr = $new['forward'];
  252. foreach ($newarr as $id => $tmp) {
  253. if (!isset($oldarr[$id])) {
  254. self::add_fwd($tmp);
  255. } else if ($tmp !== $oldarr[$id]) {
  256. self::del_fwd($oldarr[$id]);
  257. self::add_fwd($tmp);
  258. }
  259. }
  260. foreach ($oldarr as $id => $tmp) {
  261. if (!isset($newarr[$id]))
  262. self::del_fwd($tmp);
  263. }
  264. $oldarr = $old['hlsw'];
  265. $newarr = $new['hlsw'];
  266. foreach ($newarr as $id => $tmp) {
  267. if (!isset($oldarr[$id])) {
  268. self::add_hlsw($tmp);
  269. } else if ($tmp !== $oldarr[$id]) {
  270. self::del_hlsw($oldarr[$id]);
  271. self::add_hlsw($tmp);
  272. }
  273. }
  274. foreach ($oldarr as $id => $tmp) {
  275. if (!isset($newarr[$id]))
  276. self::del_hlsw($tmp);
  277. }
  278. }
  279. }
  280. class Vtund {
  281. function getBaseConfig() {
  282. return "
  283. options {
  284. type stand;
  285. port 5000;
  286. timeout 60;
  287. syslog daemon;
  288. ifconfig /sbin/ifconfig;
  289. }
  290. default {
  291. type ether;
  292. proto udp;
  293. timeout 60;
  294. compress no;
  295. encrypt no;
  296. keepalive yes;
  297. stat no;
  298. speed 0;
  299. multi kill;
  300. up {
  301. ifconfig \"%d 0.0.0.0 up\";
  302. program /usr/sbin/brctl \"addif br0 %d\";
  303. };
  304. down {
  305. program /usr/sbin/brctl \"delif br0 %d\";
  306. ifconfig \"%d down\";
  307. };
  308. }
  309. ";
  310. }
  311. function getSession($tunnel) {
  312. return "
  313. {$tunnel['name']} {
  314. # partner {$tunnel['dest']}
  315. # our mode: {$tunnel['mode']}
  316. device {$tunnel['device']};
  317. password whiterabbit;
  318. }
  319. ";
  320. }
  321. function buildConfig($arr) {
  322. if (!$fp = @fopen("/etc/vtund.conf", "w")) {
  323. echo "could not write vtund config";
  324. return;
  325. }
  326. // basic config
  327. fwrite($fp, self::getBaseConfig());
  328. // add sessions
  329. foreach ($arr as $tunnel)
  330. fwrite($fp, self::getSession($tunnel));
  331. fclose($fp);
  332. }
  333. function init($arr) {
  334. self::buildConfig($arr);
  335. // check if vtund server runs
  336. $srv_running = false;
  337. if (file_exists("/var/run/vtund.pid")) {
  338. $pid = file_get_contents("/var/run/vtund.pid");
  339. // send SIGHUP, to reread the config
  340. $srv_running = posix_kill($pid, 1);
  341. }
  342. // start the server
  343. if (!$srv_running)
  344. Cmd::vtund("-f /etc/vtund.conf -s");
  345. // kill all clients (_our_ clients, not server childs!)
  346. $dir = opendir("/var/run/");
  347. while ($dir !== false && (($file = readdir($dir)) !== false)) {
  348. if ($file == "." || $file == "..")
  349. continue;
  350. if (strncmp($file, "vtund.tap", 9))
  351. continue;
  352. // send SIGTERM to client vtund
  353. $pid = file_get_contents("/var/run/".$file);
  354. posix_kill($pid, 15);
  355. }
  356. closedir($dir);
  357. // start all clients
  358. foreach ($arr as $tunnel) {
  359. if ($tunnel['mode'] == "client")
  360. Cmd::vtund("-f /etc/vtund.conf -p {$tunnel['name']} {$tunnel['dest']}");
  361. }
  362. }
  363. }
  364. class Stats {
  365. private $sock;
  366. private $files = array();
  367. private function write($msg) {
  368. socket_write($this->sock, $msg."\r\n", strlen($msg."\r\n"));
  369. }
  370. private function read() {
  371. while (true) {
  372. $fdset = array($this->sock);
  373. $sel = socket_select($fdset, $write = NULL, $except = NULL, 0, 100000);
  374. if ($sel == 0 || $sel === false)
  375. return false;
  376. return socket_read($this->sock, 1024, PHP_NORMAL_READ);
  377. }
  378. }
  379. private function waitcmd() {
  380. $retval = array();
  381. while (($line = $this->read()) !== false && strlen($line) > 0) {
  382. if (!strncmp($line, 'OK', 2))
  383. break;
  384. if (!strncmp($line, 'ERROR', 2)) {
  385. echo $line;
  386. break;
  387. }
  388. $retval[] = $line;
  389. }
  390. return $retval;
  391. }
  392. function connect($id) {
  393. $this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  394. socket_connect($this->sock, RRDSRV, 5001);
  395. self::write('ls');
  396. $list = self::waitcmd();
  397. foreach ($list as $num => $name)
  398. $list[$num] = substr(trim($name), 2, 32);
  399. $dirname = 'bridge-'.$id;
  400. if (!in_array($dirname, $list)) {
  401. self::write('mkdir '. $dirname);
  402. self::waitcmd();
  403. }
  404. self::write('cd '. $dirname);
  405. self::waitcmd();
  406. self::write('ls');
  407. $list = self::waitcmd();
  408. foreach ($list as $num => $name)
  409. $list[$num] = substr(trim($name), 2, 32);
  410. $this->files = $list;
  411. }
  412. function get_vlans() {
  413. $result = array();
  414. unset($lines);
  415. $lines = Cmd::ebtables('-t nat -L loop_pkts --Lc');
  416. foreach ($lines as $line) {
  417. if (strpos($line, '-i') !== false) {
  418. $parts = explode(' ', $line);
  419. $result[$parts[1]]['loop'] = $parts[11];
  420. }
  421. }
  422. unset($lines);
  423. $lines = Cmd::ebtables('-t nat -L arp_pkts --Lc');
  424. foreach ($lines as $line) {
  425. if (strpos($line, '-i') !== false) {
  426. $parts = explode(' ', $line);
  427. $result[$parts[1]]['arp'] = $parts[11];
  428. }
  429. }
  430. unset($lines);
  431. $lines = Cmd::ebtables('-t nat -L nonip_pkts --Lc');
  432. foreach ($lines as $line) {
  433. if (strpos($line, '-i') !== false) {
  434. $parts = explode(' ', $line);
  435. $result[$parts[1]]['nonip'] = $parts[11];
  436. }
  437. }
  438. unset($lines);
  439. $lines = Cmd::ebtables('-t nat -L udp_blocked --Lc');
  440. foreach ($lines as $line) {
  441. if (strpos($line, '-i') !== false) {
  442. $parts = explode(' ', $line);
  443. $result[$parts[1]]['blocked'] = $parts[11];
  444. }
  445. }
  446. unset($lines);
  447. $lines = Cmd::ebtables('-t nat -L udp_forwarded --Lc');
  448. foreach ($lines as $line) {
  449. if (strpos($line, '-i') !== false) {
  450. $parts = explode(' ', $line);
  451. $result[$parts[1]]['forwarded'] = $parts[11];
  452. }
  453. }
  454. unset($lines);
  455. $lines = Cmd::ebtables('-t nat -L POSTROUTING --Lc');
  456. foreach ($lines as $line) {
  457. if (strpos($line, '-o') !== false) {
  458. $parts = explode(' ', $line);
  459. $result[$parts[1]]['output'] = $parts[14];
  460. }
  461. }
  462. foreach ($result as $name => $data) {
  463. $fullname = "vlan-$name.rrd";
  464. if (!in_array($fullname, $this->files)) {
  465. $cmd = "create $fullname --start now -s 60 ".
  466. 'DS:loop:DERIVE:60:0:10000000 '.
  467. 'DS:arp:DERIVE:60:0:10000000 '.
  468. 'DS:nonip:DERIVE:60:0:10000000 '.
  469. 'DS:block:DERIVE:60:0:10000000 '.
  470. 'DS:fwd:DERIVE:60:0:10000000 '.
  471. 'DS:out:DERIVE:60:0:10000000 '.
  472. 'RRA:AVERAGE:0.5:1:720 RRA:AVERAGE:0.5:5:576 '.
  473. 'RRA:MIN:0.5:1:720 RRA:MIN:0.5:5:576 '.
  474. 'RRA:MAX:0.5:1:720 RRA:MAX:0.5:5:576 ';
  475. self::write($cmd);
  476. self::waitcmd();
  477. }
  478. $cmd = "update $fullname N:{$data['loop']}:{$data['arp']}:{$data['nonip']}:{$data['blocked']}:{$data['forwarded']}:{$data['output']}";
  479. self::write($cmd);
  480. self::waitcmd();
  481. }
  482. }
  483. function get_forwards($forwards) {
  484. $names = array();
  485. foreach ($forwards as $id => $fwd) {
  486. $key = $fwd['portlo'];
  487. if ($fwd['porthi'] != 0)
  488. $key .= ':'.$fwd['porthi'];
  489. $names[$key] = "forward-$id.rrd";
  490. }
  491. $result = array();
  492. $lines = Cmd::ebtables('-t nat -L fwdfilter --Lc');
  493. foreach ($lines as $line) {
  494. if (strpos($line, '-p') !== false) {
  495. $parts = explode(' ', $line);
  496. if (!isset($names[$parts[5]]))
  497. continue;
  498. switch ($parts[7]) {
  499. case 'udp_forwarded,':
  500. $result[$names[$parts[5]]] = "N:{$parts[14]}:0";
  501. break;
  502. case 'udp_blocked,':
  503. $result[$names[$parts[5]]] = "N:0:{$parts[14]}";
  504. break;
  505. }
  506. }
  507. }
  508. foreach ($result as $fullname => $data) {
  509. if (!in_array($fullname, $this->files)) {
  510. $cmd = "create $fullname --start now -s 60 ".
  511. 'DS:fwd:DERIVE:60:0:10000000 '.
  512. 'DS:block:DERIVE:60:0:10000000 '.
  513. 'RRA:AVERAGE:0.5:1:720 RRA:AVERAGE:0.5:5:576 '.
  514. 'RRA:MIN:0.5:1:720 RRA:MIN:0.5:5:576 '.
  515. 'RRA:MAX:0.5:1:720 RRA:MAX:0.5:5:576 ';
  516. self::write($cmd);
  517. self::waitcmd();
  518. }
  519. self::write("update $fullname $data");
  520. self::waitcmd();
  521. }
  522. }
  523. function get_masters($masters) {
  524. $lines_from = Cmd::ebtables('-t nat -L hlswmaster --Lc');
  525. $lines_to = Cmd::ebtables('-t filter -L hlswmaster --Lc');
  526. $result = array();
  527. foreach ($masters as $id => $hlsw) {
  528. foreach ($lines_from as $line) {
  529. if (strpos($line, $hlsw['ip'])) {
  530. $parts = explode(' ', $line);
  531. $from = $parts[13];
  532. break;
  533. }
  534. }
  535. foreach ($lines_to as $line) {
  536. if (strpos($line, $hlsw['dev'])) {
  537. $parts = explode(' ', $line);
  538. $to = $parts[11];
  539. break;
  540. }
  541. }
  542. $result['hlsw-'.$id.'.rrd'] = "N:{$from}:{$to}";
  543. }
  544. foreach ($result as $fullname => $data) {
  545. if (!in_array($fullname, $this->files)) {
  546. $cmd = "create $fullname --start now -s 60 ".
  547. 'DS:from:DERIVE:60:0:10000000 '.
  548. 'DS:to:DERIVE:60:0:10000000 '.
  549. 'RRA:AVERAGE:0.5:1:720 RRA:AVERAGE:0.5:5:576 '.
  550. 'RRA:MIN:0.5:1:720 RRA:MIN:0.5:5:576 '.
  551. 'RRA:MAX:0.5:1:720 RRA:MAX:0.5:5:576 ';
  552. self::write($cmd);
  553. self::waitcmd();
  554. }
  555. self::write("update $fullname $data");
  556. self::waitcmd();
  557. }
  558. }
  559. function close() {
  560. socket_close($this->sock);
  561. }
  562. }
  563. /* teh main */
  564. $init = (isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == "init");
  565. // get old config, fallback to the empty config
  566. $oldarr = Config::getOld();
  567. if ($oldarr === false)
  568. $oldarr = Config::getEmpty();
  569. // get new config, fallback to old config
  570. $newarr = Config::fetch();
  571. if ($newarr === false) {
  572. echo "Fetch failed!\n";
  573. $newarr = $oldarr;
  574. }
  575. // main config changed -> reset everything
  576. if ($oldarr['bridge'] != $newarr['bridge'])
  577. $init = true;
  578. // tunnel config changed -> reset everything
  579. if ($oldarr['tunnel'] != $newarr['tunnel'])
  580. $init = true;
  581. if ($init) {
  582. // basic bridge layout, loop detection
  583. BaseTables::init($newarr['bridge']);
  584. // add bridge rules for tunnels
  585. BaseTables::add_tunnel($newarr['tunnel']);
  586. // vlan + port stuff
  587. ForwardTables::init();
  588. // setup tunnels
  589. Vtund::init($newarr['tunnel']);
  590. // we do a init, so diff between $empty -> $new
  591. $oldarr = Config::getEmpty();
  592. }
  593. // add VLANs, Forward-Ports and HLSW Master Server
  594. ForwardTables::checkDiff($oldarr, $newarr);
  595. // gather stats and send them to rrdtool server via tcp
  596. $stats = new Stats();
  597. $stats->connect($newarr['bridge']['id']);
  598. $stats->get_vlans();
  599. $stats->get_forwards($newarr['forward']);
  600. $stats->get_masters($newarr['hlsw']);
  601. $stats->close();
  602. // save the config
  603. Config::save($newarr);
  604. ?>