diff --git a/examples/ip_address_print.php b/examples/ip_address_print.php index dcb0e5c..3a82373 100644 --- a/examples/ip_address_print.php +++ b/examples/ip_address_print.php @@ -12,7 +12,8 @@ $config = (new Config()) ->set('host', '192.168.1.3') ->set('user', 'admin') - ->set('pass', 'admin'); + ->set('pass', 'admin') + ->set('legacy', true); // Initiate client with config object $client = new Client($config); @@ -21,8 +22,5 @@ $client = new Client($config); $query = new Query('/ip/address/print'); // Send query to RouterOS -$request = $client->write($query); - -// Read answer from RouterOS -$response = $client->read(); +$response = $client->write($query)->read(); print_r($response); diff --git a/examples/vlans_bridge.php b/examples/vlans_bridge.php new file mode 100644 index 0000000..09876b9 --- /dev/null +++ b/examples/vlans_bridge.php @@ -0,0 +1,57 @@ +set('host', '192.168.5.1') + ->set('pass', 'admin') + ->set('user', 'admin') + ->set('legacy', true); + +// Initiate client with config object +$client = new Client($config); + +/* + * Create VLAN 100 on 3-8 ports + * 200 on 9-16 + * 300 on 17-24 + */ +$vlans = [ + 100 => [3, 4, 5, 6, 7, 8], + 200 => [9, 10, 11, 12, 13, 14, 15, 16], + 300 => [17, 18, 19, 20, 21, 22, 23, 24], +]; + +// Run commands for each vlan +foreach ($vlans as $vlanId => $ports) { + + // Add bridges + $query = new Query('/interface/bridge/add'); + $query->add("=name=vlan$vlanId-bridge")->add('vlan-filtering=no'); + $response = $client->write($query)->read(); + print_r($response); + + // Add ports to bridge + foreach ($ports as $port) { + $bridgePort = new Query('/interface/bridge/port/add'); + $bridgePort->add("=bridge=vlan$vlanId-bridge")->add("=pvid=$vlanId")->add("=interface=ether$port"); + $response = $client->write($bridgePort)->read(); + print_r($response); + } + + // Add untaged ports to bridge with tagging + foreach ($ports as $port) { + $vlan = new Query('/interface/bridge/vlan/add'); + $vlan->add("=bridge=vlan$vlanId-bridge")->add("=untagged=ether$port")->add("=vlan-ids=5"); + $response = $client->write($vlan)->read(false); + print_r($response); + } + +} diff --git a/src/Client.php b/src/Client.php index e539459..d4e21e6 100644 --- a/src/Client.php +++ b/src/Client.php @@ -222,8 +222,14 @@ class Client implements Interfaces\ClientInterface // Read length of line $length = $this->getLength($byte); - // Save output line to response array - $response[] = stream_get_contents($this->_socket, $length); + // Save only non empty strings + if ($length > 0) { + // Save output line to response array + $response[] = stream_get_contents($this->_socket, $length); + } else { + // Read next line + stream_get_contents($this->_socket, $length); + } // If we get a !done line in response, change state of $isDone variable $isDone = ('!done' === end($response)); @@ -251,7 +257,8 @@ class Client implements Interfaces\ClientInterface { $result = []; $i = -1; - foreach ($response as $value) { + $lines = \count($response); + foreach ($response as $key => $value) { switch ($value) { case '!re': $i++; @@ -259,9 +266,20 @@ class Client implements Interfaces\ClientInterface case '!fatal': case '!trap': case '!done': + // Check for =ret=, .tag and any other following messages + for ($j = $key + 1; $j <= $lines; $j++) { + // If we have lines after current one + if (isset($response[$j])) { + $this->pregResponse($response[$j], $matches); + if (!empty($matches)) { + $result['after'][$matches[1][0]] = $matches[2][0]; + } + } + } break 2; default: - if (preg_match_all('/^=(.*)=(.*)/', $value, $matches)) { + $this->pregResponse($value, $matches); + if (!empty($matches)) { $result[$i][$matches[1][0]] = $matches[2][0]; } break; @@ -270,6 +288,11 @@ class Client implements Interfaces\ClientInterface return $result; } + private function pregResponse(string $value, &$matches) + { + preg_match_all('/^[=|\.](.*)=(.*)/', $value, $matches); + } + /** * Authorization logic * @@ -281,12 +304,12 @@ class Client implements Interfaces\ClientInterface if ($this->config('legacy')) { // For the first we need get hash with salt $query = new Query('/login'); - $response = $this->write($query)->read(false); + $response = $this->write($query)->read(); // Now need use this hash for authorization $query = (new Query('/login')) ->add('=name=' . $this->config('user')) - ->add('=response=00' . md5(\chr(0) . $this->config('pass') . pack('H*', $response[1]))); + ->add('=response=00' . md5(\chr(0) . $this->config('pass') . pack('H*', $response['after']['ret']))); } else { // Just login with our credentials $query = (new Query('/login')) @@ -305,6 +328,7 @@ class Client implements Interfaces\ClientInterface * Connect to socket server * * @return bool + * @throws ClientException */ public function connect(): bool { @@ -373,9 +397,6 @@ class Client implements Interfaces\ClientInterface */ private function openSocket(): bool { - // Connect to server - $socket = false; - // Default: Context for ssl $context = stream_context_create([ 'ssl' => [