add_port_profile.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. <?php
  2. //-
  3. // Copyright (c) 2011-2017 Joe Clarke <jclarke@cisco.com>
  4. // All rights reserved.
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions
  7. // are met:
  8. // 1. Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // 2. Redistributions in binary form must reproduce the above copyright
  11. // notice, this list of conditions and the following disclaimer in the
  12. // documentation and/or other materials provided with the distribution.
  13. // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  14. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16. // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19. // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20. // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23. // SUCH DAMAGE.
  24. include_once 'db.inc.php';
  25. include_once 'swreg/swreg.inc.php';
  26. require_once 'Log.php';
  27. require_once 'functions.php';
  28. $dsn = "$db_driver:host=$db_host;dbname=$db_name";
  29. $options = [
  30. PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  31. PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
  32. PDO::ATTR_EMULATE_PREPARES => false,
  33. ];
  34. try {
  35. $dbh = new PDO($dsn, $db_user, $db_pass, $options);
  36. } catch (PDOException $e) {
  37. die($e->getMessage());
  38. }
  39. $logger = Log::singleton('file', LOGFILE, TOOL_NAME . ' : Add Port Profile');
  40. if ($logger === false) {
  41. die("Failed to open logfile.\n");
  42. }
  43. $mask = Log::MAX(LOG_LEVEL);
  44. $logger->setMask($mask);
  45. $base = get_base($_SERVER['SCRIPT_NAME']);
  46. $errors = array();
  47. if (isset($_REQUEST['submit'])) {
  48. $pname = $_REQUEST['pname'];
  49. $pid = $_REQUEST['pid'];
  50. $vlans = $_REQUEST['vlan'];
  51. $start_ports = $_REQUEST['start_port'];
  52. $end_ports = $_REQUEST['end_port'];
  53. if (!isset($pname) || !isset($pid) || $pname == '') {
  54. array_push($errors, 'You must specify a profile name and PID');
  55. } else {
  56. $profile = '';
  57. $seen_sports = array();
  58. $seen_eports = array();
  59. $max_port = 0;
  60. for ($i = 0; $i < count($start_ports); ++$i) {
  61. $vlan = $vlans[$i];
  62. $start_port = $start_ports[$i];
  63. $end_port = $end_ports[$i];
  64. $row = $i + 1;
  65. if ($vlan == '__BOGUS__') {
  66. continue;
  67. }
  68. if ($start_port == '__BOGUS__' || $end_port == '__BOGUS__') {
  69. array_push($errors, "You must select a starting and ending port at row $row");
  70. continue;
  71. }
  72. if ($pid != '__ANY__') {
  73. preg_match("/\/(\d+)$/", $start_port, $sm);
  74. if ($sm[1] > $end_port) {
  75. array_push($errors, "Starting port must be less than equal to the ending port at row $row");
  76. continue;
  77. }
  78. } elseif ($vlan == 'DYNAMIC') {
  79. array_push($errors, "In order to make ports dynamic, you must choose an explicit PID at row $row");
  80. continue;
  81. }
  82. if (isset($seen_sports[$start_port])) {
  83. array_push($errors, "Starting port $start_port was already used at row {$seen_sports[$start_port]}");
  84. continue;
  85. }
  86. $seen_sports[$start_port] = $row;
  87. if (isset($seen_eports[$end_port])) {
  88. array_push($errors, "Ending port $end_port was already used at row {$seen_eports[$end_port]}");
  89. continue;
  90. }
  91. $seen_eports[$end_port] = $row;
  92. $profile .= generate_port_profile($start_port, $end_port, $vlan, $pid);
  93. $profile .= "!\n";
  94. if ($pid != '__ANY__' && $end_port > $max_port) {
  95. $max_port = $end_port;
  96. }
  97. }
  98. if ($profile == '') {
  99. array_push($errors, 'No profile ranges specified');
  100. }
  101. if (!preg_match("/^[\w\d\-_]+$/", $pname)) {
  102. array_push($errors, 'Profile name can only contain letters, numbers, hyphens, and underscores');
  103. }
  104. if ($pid != '__ANY__') {
  105. $ports = 8;
  106. foreach ($PID_PORTS as $pp => $np) {
  107. if ($pid == $pp) {
  108. $ports = $np;
  109. break;
  110. }
  111. }
  112. if ($max_port != $ports) {
  113. array_push($errors, 'All ports must be specified for a port profile');
  114. }
  115. }
  116. }
  117. if (count($errors) == 0) {
  118. $fd = fopen(PORT_PROFILE_DIR . "/{$pname}.tmpl", 'w');
  119. fwrite($fd, $profile);
  120. fclose($fd);
  121. $sql = 'INSERT INTO EXCEPTIONS VALUES (?, ?, ?)';
  122. try {
  123. $sth = $dbh->prepare($sql);
  124. /*if (isset($PID_MAP[$pid])) {
  125. $pid = $PID_MAP[$pid];
  126. }*/
  127. $sth->execute(array($pname, $pid, "{$pname}.tmpl"));
  128. $sth->closeCursor();
  129. $logger->info("User {$_SERVER['REMOTE_USER']} add port profile: name={$pname}, pid={$pid}, path={$pname}.tmpl");
  130. } catch (PDOException $e) {
  131. array_push($errors, "Failed to add new exception: {$e->getMessage()}");
  132. }
  133. cleanup();
  134. if (count($errors) == 0) {
  135. header("Location: $base/port_profiles.php");
  136. exit;
  137. }
  138. }
  139. }
  140. $nports = array_values($PID_PORTS);
  141. rsort($nports, SORT_NUMERIC);
  142. $mport = $nports[0];
  143. print_header(TOOL_NAME . ': Add Port Profile');
  144. ?>
  145. <body class="flex" onLoad='purgePorts(); updatePorts("__ANY__", 0, 0, 1, 0); return true;'>
  146. <script>
  147. var lastStart = 1;
  148. var PID_PORTS = [];
  149. var PORT_PATTERNS = [];
  150. <?php
  151. foreach ($PID_PORTS as $pp => $np) {
  152. ?>
  153. PID_PORTS["<?= $pp ?>"] = <?= $np ?>;
  154. <?php
  155. }
  156. foreach ($PORT_PATTERNS as $p => $pa) {
  157. ?>
  158. PORT_PATTERNS["<?= $p ?>"] = "<?= $pa ?>";
  159. <?php
  160. }
  161. ?>
  162. function setLastStart(port, increment) {
  163. var regex = /([0-9]+)$/;
  164. try {
  165. var matches = regex.exec(port);
  166. lastStart = matches[1];
  167. if (increment) {
  168. lastStart++;
  169. }
  170. } catch (err) { }
  171. }
  172. function purgePorts() {
  173. for (var i = 0; i < <?= $mport ?>; i++) {
  174. var sSelect = document.getElementById("start_port[" + i + "]");
  175. var eSelect = document.getElementById("end_port[" + i + "]");
  176. deleteOptions(sSelect);
  177. deleteOptions(eSelect);
  178. createOption(sSelect, '--Please Select--', '__BOGUS__');
  179. createOption(eSelect, '--Please Select--', '__BOGUS__');
  180. }
  181. }
  182. function updatePorts(pid, sidx, eidx, send, eend) {
  183. if (typeof send === undefined) {
  184. send = <?= $mport ?>;
  185. }
  186. if (typeof eend === undefined) {
  187. eend = <?= $mport ?>;
  188. }
  189. for (var i = sidx; i < send; i++) {
  190. var sSelect = document.getElementById("start_port[" + i + "]");
  191. if (pid == "__ANY__") {
  192. createOption(sSelect, 'First Switch Port', '%%START_PORT%%');
  193. } else {
  194. endp = PID_PORTS[pid] + 1;
  195. ppat = PORT_PATTERNS[pid];
  196. for (var j = lastStart; j < endp; j++) {
  197. createOption(sSelect, ppat + j, ppat + j);
  198. }
  199. }
  200. }
  201. for (var i = eidx; i < eend; i++) {
  202. var eSelect = document.getElementById("end_port[" + i + "]");
  203. if (pid == "__ANY__") {
  204. createOption(eSelect, 'Last Switch Port', '%%MAX_PORT%%');
  205. } else {
  206. endp = PID_PORTS[pid] + 1;
  207. for (var j = lastStart; j < endp; j++) {
  208. createOption(eSelect, j, j);
  209. }
  210. }
  211. }
  212. }
  213. </script>
  214. <div id="headswreg">
  215. <div id="header">
  216. <h1>
  217. <?= TOOL_NAME ?>: Add Port Profile
  218. </h1>
  219. </div>
  220. <br />
  221. </div>
  222. <form name="port_profile_add_form" method="POST" action="<?= $_SERVER['PHP_SELF'] ?>">
  223. <div class="apage">
  224. <table class="noborder" summary="Profile Options">
  225. <tr>
  226. <td class="left_act">Profile Name:
  227. <input type="text" name="pname" size="16">
  228. </td>
  229. <td>Select PID:
  230. <select name="pid" id="pid"
  231. onChange='purgePorts(); updatePorts(this.options[this.selectedIndex].value, 0, 0, 1, 0); return true;'>
  232. <option value="__ANY__" selected>Any</option>
  233. <?php
  234. foreach ($PID_PORTS as $p => $n) {
  235. ?>
  236. <option value="<?= $p ?>">
  237. <?= $p ?>
  238. </option>
  239. <?php
  240. }
  241. ?>
  242. </select>
  243. </td>
  244. </tr>
  245. </table>
  246. </div>
  247. <div id="page">
  248. <div id="itemhead">
  249. <h2 class="tabletitle">Port Profile</h2>
  250. </div>
  251. <div align="center">
  252. <?php
  253. foreach ($errors as $error) {
  254. ?>
  255. <p class="error">
  256. <?= $error ?>
  257. </p>
  258. <?php
  259. }
  260. ?>
  261. </div>
  262. <table class="full" summary="New Port Profile Table">
  263. <thead>
  264. <tr>
  265. <th>Row No.</th>
  266. <th>Starting Port</th>
  267. <th>Ending Port</th>
  268. <th>VLAN</th>
  269. </tr>
  270. </thead>
  271. <tbody>
  272. <?php
  273. for ($i = 0; $i < $mport; ++$i) {
  274. ?>
  275. <tr <?= get_row_color($i) ?>>
  276. <td>
  277. <?= $i + 1 ?>.
  278. </td>
  279. <td><select name="start_port[<?= $i ?>]" id="start_port[<?= $i ?>]"
  280. onChange='setLastStart(this.options[this.selectedIndex].value, false); pSelect = document.getElementById("pid"); updatePorts(pSelect.options[pSelect.selectedIndex].value, <?= $i + 1 ?>, <?= $i ?>, <?= $i + 1 ?>, <?= $i + 1 ?>); return true;'>
  281. </select></td>
  282. <td><select name="end_port[<?= $i ?>]" id="end_port[<?= $i ?>]"
  283. onChange='setLastStart(this.options[this.selectedIndex].value, true); pSelect = document.getElementById("pid"); updatePorts(pSelect.options[pSelect.selectedIndex].value, <?= $i + 1 ?>, <?= $i + 1 ?>, <?= $i + 2 ?>, <?= $i + 1 ?>); return true;'>
  284. </select></td>
  285. <td><select name="vlan[<?= $i ?>]">
  286. <option value="__BOGUS__" selected>--Please Select--</option>
  287. <option value="DYNAMIC">DYNAMIC</option>
  288. <option value="TRUNK">TRUNK</option>
  289. <option value="UPLINK TRUNK">UPLINK TRUNK</option>
  290. <option disabled>
  291. &#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;</option>
  292. <?php
  293. ksort($VLANS);
  294. foreach ($VLANS as $vn => $vi) {
  295. ?>
  296. <option value="<?= $vn ?>">
  297. <?= $vn ?>
  298. </option>
  299. <?php
  300. } ?>
  301. </select></td>
  302. </tr>
  303. <?php
  304. }
  305. ?>
  306. </tbody>
  307. </table>
  308. <br />
  309. <div align="center">
  310. <input type="reset" name="reset" value="Reset">
  311. <input type="submit" name="preview" value="Preview"
  312. onClick='this.form.action="<?= $base ?>/profile_preview.php"; this.form.target="_blank";'>
  313. <input type="submit" name="submit" value="Add"
  314. onClick='this.form.action="<?= $_SERVER['PHP_SELF'] ?>"; this.form.target="_self";'>
  315. </div>
  316. <table class="noborder" summary="Return Table">
  317. <tr>
  318. <td class="left_act">
  319. <a href="<?= $base ?>/port_profiles.php">&lt;&lt;&lt;Return to Main Page</a>
  320. </td>
  321. </tr>
  322. </table>
  323. </div>
  324. </form>
  325. </body>
  326. </html>
  327. <?php
  328. cleanup();
  329. ?>