blob: 47d7c8a6504d768392cc3067d526439058c48bde [file] [log] [blame]
Tomas Cejkaac49c6e2012-07-30 17:10:25 +02001<?php
2/*!
3 * \file phpmynetconf.php
4 * \brief NETCONF PHP gateway for Apache module of Netopeer
5 * \author Tomas Cejka <cejkat@cesnet.cz>
6 * \date 2012
7 */
8/*
9 * Copyright (C) 2011-2012 CESNET
10 *
11 * LICENSE TERMS
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in
20 * the documentation and/or other materials provided with the
21 * distribution.
22 * 3. Neither the name of the Company nor the names of its contributors
23 * may be used to endorse or promote products derived from this
24 * software without specific prior written permission.
25 *
26 * ALTERNATIVELY, provided that this notice is retained in full, this
27 * product may be distributed under the terms of the GNU General Public
28 * License (GPL) version 2 or later, in which case the provisions
29 * of the GPL apply INSTEAD OF those given above.
30 *
31 * This software is provided ``as is'', and any express or implied
32 * warranties, including, but not limited to, the implied warranties of
33 * merchantability and fitness for a particular purpose are disclaimed.
34 * In no event shall the company or contributors be liable for any
35 * direct, indirect, incidental, special, exemplary, or consequential
36 * damages (including, but not limited to, procurement of substitute
37 * goods or services; loss of use, data, or profits; or business
38 * interruption) however caused and on any theory of liability, whether
39 * in contract, strict liability, or tort (including negligence or
40 * otherwise) arising in any way out of the use of this software, even
41 * if advised of the possibility of such damage.
42 *
43 */
44
45/* Enumeration of Message type (taken from mod_netconf.c) */
46class MsgType {
47 const REPLY_OK = 0;
48 const REPLY_DATA = 1;
49 const REPLY_ERROR = 2;
50 const REPLY_INFO = 3;
51 const MSG_CONNECT = 4;
52 const MSG_DISCONNECT = 5;
53 const MSG_GET = 6;
54 const MSG_GETCONFIG = 7;
55 const MSG_EDITCONFIG = 8;
56 const MSG_COPYCONFIG = 9;
57 const MSG_DELETECONFIG = 10;
58 const MSG_LOCK = 11;
59 const MSG_UNLOCK = 12;
60 const MSG_KILL = 13;
61 const MSG_INFO = 14;
62 const MSG_GENERIC = 15;
63};
64
65/**
66 \brief Read response from socket
67 \param[in,out] $sock socket descriptor
68 \return trimmed string that was read
69 */
70function readnetconf(&$sock)
71{
72 $response = "";
73 do {
74 $tmp = "";
75 $tmp = fread($sock, 4096);
76 if ($tmp != "") {
77 $response .= $tmp;
78 }
79 if (strlen($tmp) < 4096) {
80 break;
81 }
82 } while ($tmp != "");
83 return trim($response);
84}
85
86function printJsonError() {
87 switch (json_last_error()) {
88 case JSON_ERROR_NONE:
89 echo 'No errors';
90 break;
91 case JSON_ERROR_DEPTH:
92 echo 'Maximum stack depth exceeded';
93 break;
94 case JSON_ERROR_STATE_MISMATCH:
95 echo 'Underflow or the modes mismatch';
96 break;
97 case JSON_ERROR_CTRL_CHAR:
98 echo 'Unexpected control character found';
99 break;
100 case JSON_ERROR_SYNTAX:
101 echo 'Syntax error, malformed JSON';
102 break;
103 case JSON_ERROR_UTF8:
104 echo 'Malformed UTF-8 characters, possibly incorrectly encoded';
105 break;
106 default:
107 echo 'Unknown error';
108 break;
109 }
110}
111
112/**
113 \brief Prints formatted XML
114 */
115function printxml($string)
116{
117 $xmlObj = simplexml_load_string("<rootnode>".str_replace('<?xml version="1.0" encoding="UTF-8"?>', "", $string)."</rootnode>");
118 echo("<pre>".htmlspecialchars($xmlObj->asXML())."</pre>");
119}
120
121/**
122 \param[in,out] $sock socket descriptor
123 \return 0 on success
124*/
125function handle_connect(&$sock)
126{
127 $connect = json_encode(array("type" => MsgType::MSG_CONNECT,
128 "host" => $_REQUEST["host"],
129 "port" => 22,
130 "user" => $_REQUEST["user"],
131 "pass" => $_REQUEST["pass"]
132 ));
133 fwrite($sock, $connect);
134 $response = readnetconf($sock);
135 $decoded = json_decode($response, true);
136 echo "<h2>CONNECT</h2>";
137 if ($decoded["type"] == MsgType::REPLY_OK) {
138 $sessionkey = $decoded["session"];
139 if (!isset($_SESSION["keys"])) {
140 $_SESSION["keys"] = array("$sessionkey");
141 } else {
142 $_SESSION["keys"][] = $sessionkey;
143 }
144 if (!isset($_SESSION["hosts"])) {
145 $_SESSION["hosts"] = array($_REQUEST["host"]);
146 } else {
147 $_SESSION["hosts"][] = $_REQUEST["host"];
148 }
149 echo "Successfully connected.";
150 return 0;
151 } else {
152 echo "Could not connect.";
153 var_dump($decoded);
154 return 1;
155 }
156}
157
158/**
159 \return 0 on success
160 */
161function check_logged_keys()
162{
163 if (!isset($_SESSION["keys"])) {
164 echo "Not logged in.";
165 return 1;
166 }
167 if (!isset($_REQUEST["key"])) {
168 echo "No Index of key.";
169 return 1;
170 }
171 if (!isset($_SESSION["keys"][$_REQUEST["key"]])) {
172 echo "Bad Index of key.";
173 return 1;
174 }
175 return 0;
176}
177
178/**
179 \param[in,out] $sock socket descriptor
180 \param[in] $params array of values for mod_netconf (type, params...)
181 \return array - response from mod_netconf
182*/
183function execute_operation(&$sock, $params)
184{
185 $operation = json_encode($params);
186 fwrite($sock, $operation);
187 $response = readnetconf($sock);
188 return json_decode($response, true);
189}
190
191/**
192 \param[in,out] $sock socket descriptor
193 \return 0 on success
194*/
195function handle_get(&$sock)
196{
197 if (check_logged_keys() != 0) {
198 return 1;
199 }
200 $sessionkey = $_SESSION["keys"][$_REQUEST["key"]];
201
Tomas Cejkacb2765e2012-08-03 20:40:48 +0200202 $params = array("type" => MsgType::MSG_GET,
Tomas Cejkaac49c6e2012-07-30 17:10:25 +0200203 "session" => $sessionkey,
Tomas Cejkacb2765e2012-08-03 20:40:48 +0200204 "source" => "running");
205 if (isset($_REQUEST["filter"]) && $_REQUEST["filter"] != "") {
206 $params["filter"] = $_REQUEST["filter"];
207 }
208 $decoded = execute_operation($sock, $params);
Tomas Cejkaac49c6e2012-07-30 17:10:25 +0200209
210 echo "<h2>GET-CONFIG</h2>";
211 printxml($decoded["data"]);
212}
213
214/**
215 \param[in,out] $sock socket descriptor
216 \return 0 on success
217*/
218function handle_getconfig(&$sock)
219{
220 if (check_logged_keys() != 0) {
221 return 1;
222 }
223 $sessionkey = $_SESSION["keys"][$_REQUEST["key"]];
Tomas Cejkacb2765e2012-08-03 20:40:48 +0200224 $params = array("type" => MsgType::MSG_GETCONFIG,
Tomas Cejkaac49c6e2012-07-30 17:10:25 +0200225 "session" => $sessionkey,
Tomas Cejkacb2765e2012-08-03 20:40:48 +0200226 "source" => (isset($_REQUEST["source"])?$_REQUEST["source"]:"running"));
227 if (isset($_REQUEST["filter"]) && $_REQUEST["filter"] != "") {
228 $params["filter"] = $_REQUEST["filter"];
229 }
230 $decoded = execute_operation($sock, $params);
Tomas Cejkaac49c6e2012-07-30 17:10:25 +0200231
232 echo "<h2>GET-CONFIG</h2>";
233 printxml($decoded["data"]);
234 return 0;
235}
236
237/**
238 \param[in,out] $sock socket descriptor
239 \return 0 on success
240*/
241function handle_disconnect(&$sock)
242{
243 if (check_logged_keys() != 0) {
244 return 1;
245 }
246 $sessionkey = $_SESSION["keys"][$_REQUEST["key"]];
247 $decoded = execute_operation($sock,
248 array( "type" => MsgType::MSG_DISCONNECT,
249 "session" => $sessionkey));
250 echo "<h2>Disconnect</h2>";
251 if ($decoded["type"] == MsgType::REPLY_OK) {
252 echo "Successfully disconnected.";
253 } else {
254 echo "Error occured.";
255 var_dump($decoded);
256 }
257 unset($_SESSION["keys"][$_REQUEST["key"]]);
258 unset($_SESSION["hosts"][$_REQUEST["key"]]);
259 $_SESSION["keys"] = array_values($_SESSION["keys"]);
260 $_SESSION["hosts"] = array_values($_SESSION["hosts"]);
261}
262
263/* main part of script */
264session_start();
265
266if (!isset($_REQUEST["command"])) {
267 echo "<h2>Connect to new NETCONF server</h2>
268 <form action='?' method='POST'>
269 <input type='hidden' name='command' value='connect'>
270 <label for='host'>Hostname:</label><input type='text' name='host'><br>
271 <label for='user'>Username:</label><input type='text' name='user'><br>
272 <label for='pass'>Password:</label><input type='password' name='pass'><br>
273 <input type='submit' value='Login'>
274 </form>";
Tomas Cejkaac49c6e2012-07-30 17:10:25 +0200275 if (isset($_SESSION["keys"])) {
276 echo "<h2>Already connected nodes</h2>";
277 $keys = $_SESSION["keys"];
278 $i = 0;
279 foreach ($keys as $k) {
Tomas Cejkacb2765e2012-08-03 20:40:48 +0200280 echo "$i ".$_SESSION["hosts"][$i]."
281<form action='?' method='GET'>
282<input type='hidden' name='command' value='get'>
283<input type='hidden' name='key' value='$i'>
284<label for='get-filter'>Filter:</label><input type='text' name='filter'>
285<input type='submit' value='Execute Get'></form>
286<form action='?' method='GET'>
287<input type='hidden' name='command' value='getconfig'>
288<input type='hidden' name='key' value='$i'>
289<label for='get-filter'>Filter:</label><input type='text' name='filter'>
290<select name='source'><option value='running'>Running</option>
291<option value='startup'>Start-up</option>
292<option value='candidate'>Candidate</option></select>
293<input type='submit' value='Execute Get-config'></form>
294<a href='?command=disconnect&amp;key=$i'><button>disconnect</button></a><br>";
Tomas Cejkaac49c6e2012-07-30 17:10:25 +0200295 $i++;
296 }
297 }
298 exit(0);
299}
300
301if (isset($_REQUEST["command"])) {
302 $errno = 0;
303 $errstr = "";
304 $sock = fsockopen('unix:///tmp/mod_netconf.sock', NULL, $errno, $errstr);
305 if ($errno != 0) {
306 echo "Could not connect to socket.";
307 echo "$errstr";
308 return 1;
309 }
310 stream_set_timeout($sock, 1, 100);
311 echo "<a href='?'>Back</a>";
312
313 if ($_REQUEST["command"] === "connect") {
314 handle_connect($sock);
315 } else if ($_REQUEST["command"] === "get") {
316 handle_get($sock);
317 } else if ($_REQUEST["command"] === "getconfig") {
318 handle_getconfig($sock);
319 } else if ($_REQUEST["command"] === "disconnect") {
320 handle_disconnect($sock);
321 } else {
322 printf("Not implemented yet. (%s)", $_REQUEST["command"]);
323 }
324 fclose($sock);
325 exit(0);
326}
327
328