See the project wiki for installation instructions and other documentation.
You can download packaged archives (which include dependencies) from SourceForge or the releases page on GitHub.
This package allows you to read and write information from a RouterOS host using the MikroTik RouterOS API protocol.
Home Page: http://pear2.php.net/PEAR2_Net_RouterOS
See the project wiki for installation instructions and other documentation.
You can download packaged archives (which include dependencies) from SourceForge or the releases page on GitHub.
Hi, I need help.
I use this api package to bandwidth test activity. I have test in 5.20 version it's working fine, but when I test in 6.30.4, the async request coult not stop and in session user still logged in (/system user active).
Thanks before
*Sorry for by bad english
Hi!
There an arror in the code of find method, class util. As a result, it returns NOT comma separated, but just concatenated results, leading to any usage failure.
the path:
--- a/<html>Util.php (<b>Today 9:21:05</b>)</html>
+++ b/<html><b>Current File</b></html>
@@ -457,8 +457,8 @@
$idList .= strtolower(
is_string($newId)
? $newId
- : stream_get_contents($newId) . ','
- );
+ : stream_get_contents($newId)
+ ) . ',';
}
} elseif (is_callable($criteria)) {
$idCache = array();
Is the dev version backwards compatible? Needs to write some scripts now, and we are still running 6.42 version. We will be moving up soon.
regards
I'm getting the following error well isntalling with pyrus using php7.0 under ubuntu 16.04 well install just the Net_RouterOS package:
Error: package pear2.php.net/PEAR2_Net_RouterOS could not be installed in registry: The SQLite3 object has not been correctly initialised
Exception: The SQLite3 object has not been correctly initialised
Sqlite is installed for php7.0 currently. Other pyrus projects install correctly. Infact I run that with optional dependencies which install correctly before the Net RouterOS package attempts to intall and fails. Any suggestions?
Will be pear2 / Net_RouterOS put into http://packagist.org repository?
Thanks in advance
v.
After os update login not working ....
I get Error input does not match any value of profile
when trying to add a new Hotspot user:
$object = $util->setMenu('/ip hotspot user')->add(
array(
'name' => $u_name,
'password'=> $u_pass,
'profile' => 'priorityLOW',
)
);
What does it mean/how do can it be fixed?
Hey thanks for this great API, now I'm kinda used to it after 1 month coding
ok back to my question, can where clause use "~" ? in terminal we use it like this
/ip firewall mangle> print where connection-mark~"_2"
Flags: X - disabled, I - invalid, D - dynamic
0 chain=prerouting action=mark-packet new-packet-mark=5UP_2 passthrough=no
connection-mark=5UC_2
1 chain=prerouting action=mark-packet new-packet-mark=5DP_2 passthrough=no
connection-mark=5DC_2
2 chain=prerouting action=mark-packet new-packet-mark=5UJP_2 passthrough=no
connection-mark=5UJC_2
3 chain=prerouting action=mark-packet new-packet-mark=5DJP_2 passthrough=no
connection-mark=5DJC_2
but when I try on API it doesn't work like on terminal, here's my code
$nbr = '2'
$req = new RouterOS\Request('/ip/firewall/mangle/print');
$req->setArgument('.proplist', '.id');
$req->setQuery(RouterOS\Query::where('new-connection-mark','_' . $nbr));
$ncm = $client->sendSync($req)->getProperty('.id');// Get new-connection-mark user id
$removeRequest = new RouterOS\Request('/ip/firewall/mangle/remove');
$removeRequest->setArgument('numbers', $ncm);
$client->sendSync($removeRequest);// Delete by new-connection-mark user
Or maybe something wrong with my code ? I don't know
But if it can use "~" like in terminal, it can be very helpful
Thank you.
PHP Warning: Invalid argument supplied for foreach() in /var/www/php/PEAR2/Cache/SHM/Adapter/APC.php on line 125
PHP Warning: array_search() expects parameter 2 to be array, string given in /var/www/php/PEAR2/Cache/SHM/Adapter/APC.php on line 185
I tried APC 3.1.6 and I got less errors but stil do not work.
Hi, this code should create a logging action and create a rule with it. but the rule creation fails. Only after a reconnection (running script the second time) it creates the rule.
#this part runs only if syslog doesn't exist
$util->setMenu('/system logging action');
$add['name'] = 'syslog';
$add['remote'] = $syslog_ip;
$add['syslog-facility'] = $syslog_facility;
$add['bsd-syslog'] = 'yes';
$add['target'] = 'remote';
$res = $util->add($add);
#this returns 'syslog'
$name = $util->get($res, 'name');
#this part runs always
$util->setMenu('/system logging');
$add['action'] = 'syslog';
$add['topics'] = 'critical,error,warning,info';
#this returns empty script
$res = $util->add($add);
Currently, Client::loop() only loops over a single connection - the one of the client object itself.
This method should be made static, and loop over all opened connections, which would make it far easier to use in scenarios where during the same PHP request, multiple connections to different routers are made at the same time.
Right now, the only way to somewhat effectively deal with those scenarios is to give loop() a timeout, and then execute the next connection's loop(), which is far from ideal, both in performance and in convenience.
Implementing this would not be trivial though, as it may require some refactoring on lower levels, and more than likely will require changes in PEAR2_Net_Transmitter too.
Hi,
First of all, I'd like to thank you for your project. Seems you have put a lot of work into it.
I am not sure if this is the best place to post but other channels seem down.
I am testing this API with a Mikrotik RouterOS v3.20 from a Raspberry PI with PHP5 installed.
When retrieving data from the Mikrotik, it works fine, such as the basic example of the arp table.
$util->setMenu('/ip arp');
foreach ($util->getAll() as $item) {
echo 'IP: ', $item->getProperty('address'),
'---> MAC: ', $item->getProperty('mac-address')."
";
However, when I try to enable/disable or remove an arp entry, nothing happens, not even an error.
$util->setMenu('/ip arp')->remove(8);
or this
$util->setMenu('/ip arp');
$util->disable(RouterOS\Query::where('comment', 'DISABLE ME'));
The api connection is successful, as I see it in the Mikrotik logs, however, nothing happens.
Could the problem be related to the old RouterOS version?
If I perform the command to disable id 8 from the Mikrotik terminal it works, so its the API that somehow fails.
Do you have any idea and suggestions?
Thanks
Rgs
ETienne
From the very first version, persistent connections have been supported in this package.
However, this support has been limited in that it only allows for the reuse of connections when all requests have been completed in a single PHP instance. Furthermore, referencing the same connection twice (or more) in a single PHP instance can produce all sorts of errors when the second connection tries to do anything before the first one is finished.
Persistent data (i.e. response buffers and callbacks) should be shared, so that a request from one variable/instance can resume a request from another one, or start requests that would be finished in the former variable/instance. This entails radical reworks in the internals of the package.
edit: Some attempts at making the above seem to suggest that this is not only hard to implement properly... it's also a bad idea. So instead, persistency will be implemented in a MySQL-ish fashion, where isolation between the different instances is emulated wherever possible. Thus, the only difference between persistent and non-persistent connections should be only in terms of performance.
Hi,
Looking for some help please, when I run the test php script (below) from the CLI I get some errors (below) which I can't seem to find any reports of from a google search or on here and cant figure what's going wrong.
Any help is appreciated.
Thanks
PHP Script
<?php
use PEAR2\Net\RouterOS;
require_once 'PEAR2_Net_RouterOS-1.0.0b6.phar';
try {
$client = new RouterOS\Client('192.168.88.1', 'apiuser', 'example');
echo 'OK';
} catch (Exception $e) {
die($e);
}
?>
Error
exception 'Exception' with message 'Class PEAR2\Net\RouterOS\Client could not be loaded from PEAR2/Net/RouterOS/Client.php, file does not exist (registered paths="phar:///root/PEAR2_Net_RouterOS-1.0.0b6.phar/PEAR2_Net_RouterOS-1.0.0b6/src") [PEAR2_Autoload-@PACKAGE_VERSION@]' in phar:///root/PEAR2_Net_RouterOS-1.0.0b6.phar/PEAR2_Net_RouterOS-1.0.0b6/src/PEAR2/Autoload.php:305
Stack trace:
#0 [internal function]: PEAR2\Autoload::load('PEAR2\\Net\\Route...')
#1 /root/index.php(7): spl_autoload_call('PEAR2\\Net\\Route...')
Hello there, the library is throwing an exception "Cannot unset string offsets" when using persistent connections with PHP7 + apcu.
Anyone else experimenting this problem ?
Here are my system details:
Linux fdtest 4.4.0-87-generic #110-Ubuntu SMP Tue Jul 18 12:55:35 UTC 2017 x86_64
PHP Version 7.0.21-1~ubuntu16.04.1+deb.sury.org+1
APCu Version 5.1.8
The exception is being thrown at line 123 in pear2/net_routeros/src/PEAR2/Net/RouterOS/Registry.php
The line is:
$this->shm->unlock('taglessModeOwner');
Anyone else having this issue ?
Thanks for any advise!
Buen día para todos,
Tengo problemas para realizar el login desde el api con la ultima versión de routeros 6.45.6, me dice que el usuario y la contraseña son incorrectos.
Lo que he investigado es que desde la versión 6.43 hacia arriba un cambio en el inicio de sesión y al parecer hay que agregar el legacy en true.
Agradezco informen si se realizara una actualización o alguien de la comunidad tiene una solución.
Saludos desde Colombia.
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Good day to all,
I have problems logging in from the api with the latest version of routers 6.45.6, it tells me that the username and password are incorrect.
What I have investigated is that from version 6.43 upwards a change in the login and apparently it is necessary to add the legacy to true.
I appreciate informing if an update will be made or someone from the community has a solution.
Greetings from Colombia.
I use this "PEAR2_Net_RouterOS-1.0.0b5.phar" to run my code.
I get this warning " #!/usr/bin/env php".
How to solve it, please ?
Thank you.
P.S. When I use "PEAR2_Net_RouterOS-1.0.0b4.phar". it doesn't warning " #!/usr/bin/env php".
Right now, all arguments are strings... or streams of strings. RouterOS' scripting language defines several types, some of which have direct PHP equivalents. Because it doesn't hint them in any way, there's no way for the client to automatically do type casting.
A good workaround though would be to make classes that when passed to setArgument() can be converted to a proper raw string, and which if constructed from a getArgument() string can give a proper PHP typed value.
IDs will be a particular beneficiary of this.
In terms of the type "IP", there is a need for a little more research.
edit:
There are some talks in internals about a magic __cast() method (or __toInt(), etc.)... if any one of those becomes part of an official PHP release, THAT would be the thing to implement.
Alternatively, if MikroTik implement some form of type hinting (although that's unlikely given this topic in the MikroTik forum), automatic casting would be implemented, with or without PHP magic methods.
If there's a demand, some less elegant alternatives might be implemented.
When trying to assist in this topic at the MikroTik forums I found that Client::completeRequest() fails when called for a request with a callback. It works for other requests, and Client::loop() is unaffected.
Conviniently enough, this is the one situation not covered in the Wiki.
While the basic functionality of the Query class works for most cases, it can quickly become difficult to use (or at the very least lead to verbose code) as the size of the query grows.
A more intuitive approach would be the creation of a query from a string. The string itself should use the familiar syntax from shell's "where" argument... with some reduced functionality of course (e.g. there's no regex in queries yet).
Among other things, I'm still wondering what to call it though... Query::parse(), Query::expression(), Query:fromString()...
Hello,
I've upgraded to version 6.43rc5 only to find out the API login doesn't work as they've changed the way you're supposed to login.
Can I please get a quick tip on how to modify it so I can use the latest update?
hi,
I'm having trouble getting data from the "monitor" subcommands. Am I doing something wrong or are they unsupported?
thanks
MAtteo
the data I would like to fetch:
/interface wireless monitor numbers=0 once
status: running-ap
band: 5ghz-a
frequency: 5185MHz
wireless-protocol: 802.11
noise-floor: -119dBm
overall-tx-ccq: 100%
registered-clients: 1
authenticated-clients: 1
current-distance: 1
current-tx-powers: 6Mbps:20(20/20),9Mbps:20(20/20),12Mbps:20(20/20),18Mbps:20(20/20),24Mbps:20(20/20),36Mbps:18(18/18),48Mbps:17(17/17),
54Mbps:15(15/15)
notify-external-fdb: no
the code I'm using (id is correct, the same code works with a print request):
$editRequest = new RouterOS\Request($query . "/monitor");
$editRequest->setQuery(RouterOS\Query::where('.id', $id));
$editRequest->setArgument('once',"");
$responses = $client->sendSync($editRequest);
below the request I'm generating and the responses I get.
PEAR2\Net\RouterOS\Request Object
(
[_command:PEAR2\Net\RouterOS\Request:private] => /interface/wireless/monitor
[_query:PEAR2\Net\RouterOS\Request:private] => PEAR2\Net\RouterOS\Query Object
(
[words:protected] => Array
(
[0] => Array
(
[0] => .id
[1] => *4
)
)
)
[arguments:protected] => Array
(
[once] =>
)
[_tag:PEAR2\Net\RouterOS\Message:private] =>
)
PEAR2\Net\RouterOS\ResponseCollection Object
(
[responses:protected] => Array
(
[0] => PEAR2\Net\RouterOS\Response Object
(
[unrecognizedWords:protected] => Array
(
)
[_type:PEAR2\Net\RouterOS\Response:private] => !trap
[arguments:protected] => Array
(
[category] => 4
[message] => no such item (4)
)
[_tag:PEAR2\Net\RouterOS\Message:private] =>
)
[1] => PEAR2\Net\RouterOS\Response Object
(
[unrecognizedWords:protected] => Array
(
)
[_type:PEAR2\Net\RouterOS\Response:private] => !done
[arguments:protected] => Array
(
)
[_tag:PEAR2\Net\RouterOS\Message:private] =>
)
)
[responseTypes:protected] => Array
(
[0] => !trap
[1] => !done
)
[responseTags:protected] => Array
(
[0] =>
[1] =>
)
[argumentMap:protected] =>
[position:protected] => 2
)
Right now, the constructor of a Request object is equivalent to using setCommand().
Having support for CLI arguments would make work with this class magnitudes easier.
One limitation that I don't see how to work around is the nameless arguments... commands would have to be explicit, like "/ping address=192.168.0.1" or something, but that's a minor issue IMHO.
I'm trying to test persistent connections, and having some issues in Ubuntu. Specifically, I get:
PEAR2\Net\Transmitter\SocketException: stream_socket_client(): unable to connect to tcp://192.168.1.1:8728/sonar%2Fsonar (Failed to parse address "192.168.1.1:8728/sonar%2Fsonar") in /mnt/hgfs/Sonar/sonar/vendor/pear2/net_transmitter/src/PEAR2/Net/Transmitter/TcpClient.php:222
This seems similar to the issue previously fixed in #27
See https://wiki.mikrotik.com/wiki/Manual:API#Initial_login
But I'm not sure if it is possible to get ROS version before login. But without this change it won't be possible to use Net_RouterOS with v6.43+
I'm trying to print the last x
items of a list, chronologically. As there is no date in this list (I'm trying to print user-manager
last users) so either by name (which has an increment) or by ID.
How can it be done using Net_RouterOS
?
The only idea I came up with, is to count
and then find()
. For instance, for a count of 20, I would then find(15, 16, 17, 18, 19)
to get the last 5 items. Is it a way, the right one, the only one?
Util->get() with Query should return empty array if Query has no result instead of throwing exception 'Error getting property'. Or at least exception should be more specific (eg new exception NotFoundException), so it can be caught.
Using any export command doesn't get the expected results. Using it with a file argument works, but then the problem becomes how to read the contents of the file ('/file print detail=""' misses the contents argument).
There has to be a way to get around this limitation, and extrapolate it into functions that can easily import and export stuff.
I have a piece of code that grabs some device information and saves it into a database.
I have two classes, a RequestHandler class:
$client = new RouterOS\Client($ip, 'admin', 'password', null, false, 10);
$request = new RouterOS\Request('/system identity print');
$request->setTag("deviceIdentity");
$callback = array($responseHandler, 'notifyDeviceInfo');
$client->sendAsync($request, $callback);
$request = new RouterOS\Request('/system license print');
$request->setTag("deviceLicense");
$callback = array($responseHandler, 'notifyDeviceInfo');
$client->sendAsync($request, $callback);
$request = new RouterOS\Request('/system routerboard print');
$request->setTag("deviceRouterboard");
$callback = array($responseHandler, 'notifyDeviceInfo');
$client->sendAsync($request, $callback);
$request = new RouterOS\Request('/system resource print');
$request->setTag("deviceResource");
$callback = array($responseHandler, 'notifyDeviceInfo');
$client->sendAsync($request, $callback);
$client->loop();
And a ResponseHandler class which defines a callback function:
public function notifyDeviceInfo(RouterOS\Response $response) {
switch ($response->getTag()) {
case "deviceIdentity":
$this->identityResponse = $response;
break;
case "deviceLicense":
$this->licenseResponse = $response;
break;
case "deviceRouterboard":
$this->routerboardResponse = $response;
break;
case "deviceResource":
$this->resourceResponse = $response;
break;
}
if ($this->identityResponse && $this->licenseResponse && $this->routerboardResponse && $this->resourceResponse) {
var_dump($this->identityResponse);
var_dump($this->licenseResponse);
var_dump($this->routerboardResponse);
var_dump($this->resourceResponse);
}
}
Even though the commands complete successfully and the resulting variables are of the correct RouterOS\Response
type, the response does not contain any results:
object(PEAR2\Net\RouterOS\Response)#23 (4) {
["unrecognizedWords":protected]=>
array(0) {
}
["_type":"PEAR2\Net\RouterOS\Response":private]=>
string(5) "!done"
["attributes":protected]=>
array(0) {
}
["_tag":"PEAR2\Net\RouterOS\Message":private]=>
string(13) "deviceLicense"
}
I expected the response to look like this:
object(PEAR2\Net\RouterOS\Response)#23 (4) {
["unrecognizedWords":protected]=>
array(0) {
}
["_type":"PEAR2\Net\RouterOS\Response":private]=>
string(3) "!re"
["attributes":protected]=>
array(3) {
["software-id"]=>
string(9) "4YYU-NQ7X"
["nlevel"]=>
string(1) "6"
["features"]=>
string(0) ""
}
["_tag":"PEAR2\Net\RouterOS\Message":private]=>
string(13) "deviceLicense"
}
Do you have an idea of what could be going wrong?
Hi, first I want to thank you all for making this API possible in PHP.
Now I want to represent my issue. Below is part of my code:
$client = new RouterOS\Client(IP, USERNAME, PASSWORD, 8728, false, 10);
$interface_data = $client->sendSync(new RouterOS\Request('/interface/wireless/print'));
// script usually stuck on this line forever after I get interfaces
$reg_table_data = $client->sendSync(new RouterOS\Request('/interface/wireless/registration-table/print'));
What I have noticed, it log in to my device and stays here logged in forever(see image below):
Screenshot
I have about ~500 mikrotik devices and code above is part of the loop. Sometimes it works fine but 50% of time it stuck forever and cannot stop it even with setting php max_execution_time 300.
Any help, suggestion, tip will be highly apprecitated.
Edit: I wanted to note that it happens randomly, it does not stuck always on same device.
QUESTION 1
Hi,
I am attempting retrieve the flag data of an address-list entry to check whether it is disabled or enabled, however none of the following worked.
$printRequest = new RouterOS\Request('/ip firewall address-list print');
$printRequest->setArgument('.list');
$printRequest->setQuery(RouterOS\Query::where('disabled', 'yes'));
echo $name = $client->sendSync($printRequest)->getProperty('.list');
or this
$util->setMenu('/ip firewall address-list');
foreach ($util->getAll() as $item) {
if ('yes' ===$item('disabled')){
echo $item->getProperty('list');
} else {
echo $item->getProperty('list');
}
}
When I use as-value on the console nothing is reported, however, when I use value-list, I get the disabled items I need.
/ip firewall address-list> print value-list where disabled=yes
list: Family Android All
address: 192.168.1.91 192.168.1.94 192.168.1.90-192.168.1.119
dynamic: no no no
/ip firewall address-list> print as-value where disabled=yes
nothing
QUESTION 2
Also tried to retrieve data about my PPPOE internet connection:
/ip firewall address-list> /interface pppoe-client monitor pppoe-out1 once
status: connected
uptime: 22h42m58s
active-links: 1
encoding:
service-name:
ac-name: bsjn1
ac-mac: 28:94:0F:8E:26:00
mtu: 1480
mru: 1492
local-address: xxx.xxx.xxx.xxx
with this script, however, I get an empty page
$responses = $client->sendSync(new RouterOS\Request('/interface pppoe-client monitor pppoe-out1 once'));
foreach ($responses->getType() as $item){
echo 'STATUS: ', $item->getProperty('status'),
"\n";
}
Gets syntax error when used wrong/none existing ip address when creating client object with wrong ip address:
In the following example, if there is no router with the address: 10.20.30.42 then I get the following errors:
Parse error: syntax error, unexpected end of file in /www/cgi-bin/src/PEAR2/Net/Transmitter/Exception.php on line 37
Fatal error: Call to a member function getTransmitter() on a non-object in /www/cgi-bin/src/PEAR2/Net/RouterOS/Client.php on line 747
Exeample:
try{
$client = new RouterOS\Client('10.20.30.42', 'user','PASS');
} catch(Exception $ex){
echo 'Error...';
}
As discussed in this topic at the MikroTik forum, right now, streaming of response values is "all or nothing", but there's no reason it can't be done when a word length is above a certain user defined threshold (off by default, of course).
This will require some significant refactoring on lower levels, but it will certainly pay off as a much more elegant way of dealing with potentially large responses.
Hi,
When I print all the leases:
$array = $util->setMenu('/ip dhcp-server lease')->getAll();
I get an object like this, how can I read this:
object(PEAR2\Net\RouterOS\ResponseCollection)#276 (8) {
["responses":protected]=>
array(263) {
[0]=>
object(PEAR2\Net\RouterOS\Response)#10 (4) {
["unrecognizedWords":protected]=>
array(0) {
}
["_type":"PEAR2\Net\RouterOS\Response":private]=>
string(3) "!re"
["attributes":protected]=>
array(14) {
[".id"]=>
string(3) "*20"
["address"]=>
string(9) "10.0.0.71"
["mac-address"]=>
string(17) "B0:E8:92:30:C9:4D"
["client-id"]=>
string(19) "1:b0:e8:92:30:c9:4d"
["address-lists"]=>
string(0) ""
["server"]=>
string(21) "dhcp1_private_network"
["dhcp-option"]=>
string(0) ""
["status"]=>
string(7) "waiting"
["last-seen"]=>
string(12) "9w3d1h13m15s"
["host-name"]=>
string(11) "EPSON30C94D"
["radius"]=>
string(5) "false"
["dynamic"]=>
string(5) "false"
["blocked"]=>
string(5) "false"
["disabled"]=>
string(5) "false"
}
["_tag":"PEAR2\Net\RouterOS\Message":private]=>
NULL
}
And is it possible to pass a mac address here: '/ip dhcp-server lease'
, so I will only get all this info for 1 mac address instead of all the clients?
We are using this script that we found in the Wiki page:
$client = new RouterOS\Client($ip, 'name', 'name');
$printRequest = new RouterOS\Request('/ip arp print .proplist=mac-address');
$printRequest->setQuery(
RouterOS\Query::where('address', $_SERVER['REMOTE_ADDR'])
);
$mac = $client->sendSync($printRequest)->getProperty('mac-address');
if (null !== $mac) {
echo 'CONNECTED: '.$ip.'<br>MAC: ', $mac;
} else {
echo 'Your IP ('.$ip.$mac.
') is not part of our network, and because of that, we can\'t determine your MAC address';
}
However, we get the following error:
Warning: call_user_func_array() expects parameter 1 to be a valid callback, class 'PEAR2\Net\RouterOS\Response' does not have a method 'getProperty' in/home/admin/web/domain/public_html/PEAR2/Net/RouterOS/ResponseCollection.php on line 356
Has there been some kind of an update, and we are just using an older version of the script?
So far, we are able to establish a connection.
Thanks.
Often I don't need to get a particular property using $response->getProperty('name'), but need all rows as a plain array. There is toArray() method, but it just returns array of Response objects, which has $apttributes property protected. For now I have to use this helper, but it is a quite dirty hack. Is there any better way to get a plain array of response data, or could you please add such method to a ResponseCollection (and also to a Response)?
$plain = [];
/** @var \PEAR2\Net\RouterOS\ResponseCollection $response */
$props = array_keys($response->getPropertyMap());
foreach ($response as $row)
{
$tmp = [];
foreach ($props as $prop)
{
$tmp[$prop] = $row->getProperty($prop);
}
$plain[] = $tmp;
}
After executing a /system reboot
command, the client hangs and does not return.
Example:
$client = new RouterOS\Client($ip, 'admin', 'password', null, false, 10);
$request = new RouterOS\Request('/system reboot');
$client->sendSync($request);
echo 'OK';
In the above example, the echo statement is never reached and 'OK' is never printed to the screen.
The same thing happens with the 'set-and-forget' method (using asynchronous calls).
$client = new RouterOS\Client($ip, 'admin', 'password', null, false, 10);
$request = new RouterOS\Request('/system reboot');
$request->setTag($id);
$client->sendAsync($request);
$client->loop();
echo 'OK';
If I omit the loop()
method, the echo statement is reached but the request is never sent. What am I doing wrong?
This can cause problems when part of the request is normal words, followed by an excessively large word. Particularly damaging for "add" and "remove" requests.
All others API clients don't check for that either, and for a good reason - an excessively large word is about 2GBs of data, so any form of copying is out. Using PHP's copy-on-write mechanism, there might be a way to do something about this, but it's going to be tricky.
For most other clients though, this lack of a check doesn't cause problems, because PEAR2_Net_RouterOS is probably the only client to implicitly send a "/quit" command before closing a connection (in order to prevent connection hangs on older RouterOS versions and some RouterBOARD devices). It is actually the last word of the "/quit" request that ends up being merged with the last "leaked" request, thus causing the "leaked" request to be executed, and the "/quit" to be ignored.
Until this issue is permanently resolved, the only workaround is to simply not contain ~2GBs of data into a single argument/tag/command of a request.
Succed at Localhost... but Failed to Connect at real Host... Userman use VPS...
Controller :
`function __construct(){
parent::__construct();
require_once(APPPATH.'libraries/PEAR2/Autoload.php');
}
function pelanggan_edit(){
try {
$util = new PEAR2\Net\RouterOS\Util($client = new PEAR2\Net\RouterOS\Client('103.xxx.xxx.xxx', 'user', 'password'));
} catch (Exception $e) {
// mengalihkan halaman ke halaman data pelanggan
redirect(base_url().'admin/pelanggan/data?alert=gagal_konek_userman');
}
}`
when I test the count use query,
$count = $util->count(RouterOS\Query::where('disabled','true'));
it will return all value.
Hi, i need to send a command with REGEXP to my ROS and i'm using your API helper.
This is the command:
/ip dhcp-server lease print count-only where active-address~"1.1.1."
I've modified the Query file:
<?php
+ /**
+ * Checks if the property is a regular expresion
+ */
+ const ACTION_REGEXP = '~';
/**
* Sanitizes the action of a condition.
*
* @param string $action The action to sanitize.
*
* @return string The sanitized action.
*/
protected static function sanitizeAction($action)
{
$action = (string) $action;
switch ($action) {
case Query::ACTION_EXIST:
case Query::ACTION_NOT_EXIST:
case Query::ACTION_EQUALS:
case Query::ACTION_LESS_THAN:
case Query::ACTION_GREATHER_THAN:
+ case Query::ACTION_REGEXP:
return $action;
default:
throw new UnexpectedValueException(
'Unknown action specified', 208, null, $action
);
}
}
/**
* Sends the query over a communicator.
*
* @param Communicator $com The communicator to send the query over.
*
* @return int The number of bytes sent.
*/
public function send(Communicator $com)
{
if (!$com->getTransmitter()->isAcceptingData()) {
throw new SocketException(
'Transmitter is invalid. Sending aborted.', 209
);
}
$bytes = 0;
foreach ($this->words as $queryWord) {
list($predicate, $value) = $queryWord;
$prefix = '?' . $predicate;
if (null === $value) {
$bytes += $com->sendWord($prefix);
} else {
+ if(substr($predicate, 0, 1) === '~') {
+ $prefix = '?' . str_replace('~', '', $predicate) . '~';
+ } else {
+ $prefix .= '=';
+ }
if (is_string($value)) {
$bytes += $com->sendWord($prefix . $value);
} else {
$bytes += $com->sendWordFromStream($prefix, $value);
}
}
}
return $bytes;
}
?>
This is my test script:
<?php
namespace PEAR2\Net\RouterOS;
require_once 'PEAR2/Net/RouterOS/Autoload.php';
$client = new Client('192.168.0.1', 'myuser', 'mypass');
$request = new Request('/ip/dhcp-server/lease/print');
$request->setArgument('count-only', '');
$query = Query::where('active-address', '"10.80."', '~');
$request->setQuery($query);
$responses = $client->sendSync($request);
foreach ($responses as $response) {
foreach ($response->getAllArguments() as $name => $value) {
echo "{$name}: {$value}\n";
}
echo "====\n";
}
echo 'END'. "\n\n\n";
?>
I've modified the "sendWord" function inside "Communicator.php" file, adding a
<?php
echo "\n" . "sending word: " . $word . "\n";
?>
for debugging purposes and this is the result:
sending word: /login
sending word:
sending word: /login
sending word: =name=myuser
sending word: =response=myencriptedpassword
sending word:
sending word: /ip/dhcp-server/lease/print
sending word: =count-only=
sending word: ?active-address~"10.80."
sending word:
ret: 0
====
FIN
How can I make this work? thanks for the hard work with your API helper : )
Hello
After upgrading the php libraries, the pear2 / Net_RouterOS scripts stopped working. The message: Unable to connect to RouterOS. After checking with the command:
Php PEAR2_Net_RouterOS-1.0.0b5.phar x.x.64.252 lmsapi xxxxxxx
Error after connecting: Error connecting to RouterOS
Details: (0) Failed to address parse "x.x.64.252:8728/"
It's look like a problem with parse url?
PHP 5.4.45-0+deb7u8 (cli) (built: Mar 27 2017 22:43:09)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
If you use the find method using a Query object as parameter it won't always return a CSV.
This happens in the following piece of code:
if ($criteria instanceof Query) {
foreach ($this->client->sendSync(
new Request($this->menu . '/print .proplist=.id', $criteria)
)->getAllOfType(Response::TYPE_DATA) as $response) {
$newId = $response->getProperty('.id');
$idList .= strtolower(
is_string($newId)
? $newId
: stream_get_contents($newId) . ','
);
}
}
As you can see when adding the new ID to the $newId variable it will only append the comma when it is not a string.
Commands that should work such as:
$util->setMenu('/ip firewall filter');
$util->disable();
don't work when the special dummy rule to show fasttrack counters is present. PHP throws this error:
PEAR2\Net\RouterOS\RouterErrorException: Error when disabling items in /var/www/html/pru/PEAR2_Net_RouterOS-1.0.0b6/src/PEAR2/Net/RouterOS/Util.php:634
Stack trace: #0 /var/www/html/pru/ros_4_fw.php(73): PEAR2\Net\RouterOS\Util->disable() #1 {main}
Response collection: Array ( [0] => PEAR2\Net\RouterOS\Response Object ( [unrecognizedWords:protected] => Array ( ) [_type:PEAR2\Net\RouterOS\Response:private] => !trap [attributes:protected] => Array ( [message] => failure: cannot change builtin ) [_tag:PEAR2\Net\RouterOS\Message:private] => ) [1] => PEAR2\Net\RouterOS\Response Object ( [unrecognizedWords:protected] => Array ( ) [_type:PEAR2\Net\RouterOS\Response:private] => !done [attributes:protected] => Array ( ) [_tag:PEAR2\Net\RouterOS\Message:private] => ) ) `
If we skip that first dummy rule, for example:
$util->disable(1);
no error happens and the rule is correctly disabled.
I did:
in composer.json, section require:
"pear2/net_transmitter": "1.0.0b2", "pear2/net_routeros": "1.0.0b6",
next in console: composer update
next in php code:
`
require_once 'vendor/autoload.php';
try {
$util = new PEAR2\RouterOS\Util($client = new PEAR2\RouterOS\Client('x.x.x.x.', 'admin', ''));
foreach ($util->setMenu('/log')->getAll() as $entry) {
echo $entry('time') . ' ' . $entry('topics') . ' ' . $entry('message') . "\n";
}
} catch (Exception $e) {
echo 'Unable to connect to RouterOS.';
}
`
and I got error:
PHP Fatal error: Class 'PEAR2\RouterOS\Util' not found in /var/www/lmsGitNew/mt-logs.php on line 154
By other classes from Composer working;
When I try to load phar - I got an exception abour wrong namespace
PEAR2\Net\RouterOS\RouterOS\Client
RouterOS written twice, but in client.php - namespace declare with one RouterOS.
And execution fails.
[Mon Sep 01 19:06:55 2014] [warn] [client 141.101.89.158] mod_fcgid: stderr: PHP Fatal error: Uncaught exception 'Exception' with message 'Class PEAR2\Net\RouterOS\RouterOS\Client could not be loaded from PEAR2/Net/RouterOS/RouterOS/Client.php, file does not exist (registered paths="phar:///var/www/clients/client1/web2/web/rs/test2.php/PEAR2_Net_RouterOS-1.0.0b4/src"
) [PEAR2_Autoload-0.2.4]' in phar:///var/www/clients/client1/web2/web/rs/test2.php/PEAR2_Net_RouterOS-1.0.0b4/src/PEAR2/Autoload.php:181
[Mon Sep 01 19:06:55 2014] [warn] [client 141.101.89.158] mod_fcgid: stderr: Stack trace:
[Mon Sep 01 19:06:55 2014] [warn] [client 141.101.89.158] mod_fcgid: stderr: #0 [internal function]: PEAR2\Autoload::load('PEAR2\Net\Route...')
[Mon Sep 01 19:06:55 2014] [warn] [client 141.101.89.158] mod_fcgid: stderr: #1 /var/www/clients/client1/web2/web/rs/test.php(16): spl_autoload_call('PEAR2\Net\Route...')
[Mon Sep 01 19:06:55 2014] [warn] [client 141.101.89.158] mod_fcgid: stderr: #2 {main}
[Mon Sep 01 19:06:55 2014] [warn] [client 141.101.89.158] mod_fcgid: stderr: thrown in phar:///var/www/clients/client1/web2/web/rs/test2.php/PEAR2_Net_RouterOS-1.0.0b4/src/PEAR2/Autoload.php on line 181
how to use custom port api
Good morning, for some time I noticed a certain abnormality in access to mikrotik via api php, previously used a simple class provided, that simple:
https://github.com/BenMenking/routeros-api/blob/master/routeros_api.class.php
then I started using this api because it has many other features, but the same error occurs in both, if l2mtu is configured with values other than 1580 in the access interface it is looping and the php script hangs and does not display any exception, and what's worse is that it causes crashes ...
and the worst thing is that it can connect normally but when requested to get bulk data for example
"/ppp/active/print" ou "/queue/simple/print"
both make the access loop forever if l2mtu for example in 1500, if only generated an exeption or upon reaching the timeout displayed an error.
could someone min help?
because setting up an l2mtu solves but this has happened many times.
I attempted to connect, however I get this error. Is it a php socket problem?
What is my next step in solving this? We are running a Debian server, where the script is located.
PEAR2\Net\Transmitter\SocketException: Failed to connect with socket. in /home/admin/web/domain/public_html/PEAR2/Net/Transmitter/TcpClient.php:199 Stack trace: #0 /home/admin/web/domain/public_html/PEAR2/Net/Transmitter/TcpClient.php(160): PEAR2\Net\Transmitter\TcpClient->createException('Failed to conne...', 8) #1 /home/admin/web/domain/public_html/PEAR2/Net/RouterOS/Communicator.php(141): PEAR2\Net\Transmitter\TcpClient->__construct('xx.29.xx.xx', 8728, false, '60', 'uniroyal%2Funir...', '', Resource id #1) #2 /home/admin/web/domain/public_html/PEAR2/Net/RouterOS/Client.php(139): PEAR2\Net\RouterOS\Communicator->__construct('xx.29.xx.xx', 8728, false, NULL, 'uniroyal/uniroy...', '', NULL) #3 /home/admin/web/domain/public_html/mtk_api.php(18): PEAR2\Net\RouterOS\Client->__construct('xx.29.xx.xx', 'uniroyal', 'uniroyal') #4 {main} Next PEAR2\Net\RouterOS\SocketException: Error connecting to RouterOS in /home/admin/web/domain/public_html/PEAR2/Net/RouterOS/Communicator.php:151 Stack trace: #0 /home/admin/web/domain/public_html/PEAR2/Net/RouterOS/Client.php(139): PEAR2\Net\RouterOS\Communicator->__construct('xx.29.xx.xx', 8728, false, NULL, 'uniroyal/uniroy...', '', NULL) #1 /home/admin/web/domain/public_html/mtk_api.php(18): PEAR2\Net\RouterOS\Client->__construct('xx.29.xx.xx', 'uniroyal', 'uniroyal') #2 {main}
When i use 'composer require pear2/net_routeros:*@beta'
show this error:
Your requirements could not be resolved to an installable set of packages.
Problem 1
- pear2/net_routeros 1.0.0b6 requires pear2/net_transmitter >=1.0.0b1 -> satisfiable by pear2/net_transmitter[1.0.0b1, 1.0.0b2, dev-master] but these conflict with your requirements or minimum-stability.
- pear2/net_routeros 1.0.0b5 requires pear2/net_transmitter >=1.0.0a5 -> satisfiable by pear2/net_transmitter[1.0.0a5, 1.0.0b1, 1.0.0b2, dev-master] but these conflict with your requirements or minimum-stability.
- pear2/net_routeros 1.0.0b4 requires pear2/net_transmitter >=1.0.0a4 -> satisfiable by pear2/net_transmitter[1.0.0a4, 1.0.0a5, 1.0.0b1, 1.0.0b2, dev-master] but these conflict with your requirements or minimum-stability. - Installation request for pear2/net_routeros *@beta -> satisfiable by pear2/net_routeros[1.0.0b4, 1.0.0b5, 1.0.0b6].
Installation failed, deleting ./composer.json.
Why this happen?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.