This is my implementation of the RouterOS api protocol, described at http://wiki.mikrotik.com/wiki/Manual:API
The other C implementations seemed either over complicated, or too simple.
This example logs into a router and lists all interfaces available on the remote device.
struct ros_result *res;
printf("Interfaces:\n");
res = ros_send_command_wait(sock, "/interface/print", "=stats", ".tag=kake", NULL);
while (res && res->re) {
printf(" %20s %20s %20s %20s\n", ros_get(res, "=name"), ros_get(res, "=type"), ros_get(res, "=rx-byte"), ros_get(res, "=tx-byte"));
ros_free_result(res);
res = ros_read_packet(sock);
}
ros_free_result(res);
- Linux
- Mac OSX (llvm/gcc)
- Apple iPhone IOS (llvm/gcc)
- Windows XP
- Windows CE 6.0
- Windows Mobile 5.0 Pocket PC
Licensed under GNU Lesser General Public License (LGPL)
NOTE Library function names and parameters are subject to change. (still alpha stage)
Use the following functions:
- ros_connect
- ros_login
- ros_send_*_wait
- ros_read_packet
- ros_get
- ros_result_free
- ros_disconnect
Use the following functions:
- ros_connect
- ros_login
- ros_set_type
- ros_sentence_new
- ros_sentence_add
- ros_sentence_free
- ros_send_*_cb
- ros_cancel
- ros_get
- ros_result_free
- ros_disconnect
- ros_runloop_once
You can either use the variable argument way, if you have a fixed amount of words in your sentences, or the sentence building way. (read about words and sentences in the Mikrotik API documentation)
- Sending commands (either)
- ros_send_command_wait
- ros_send_command_cb
- Building sentence
- ros_sentence_new
- ros_sentence_add
- ros_sentence_free
- Sending commands (either)
- ros_send_sentence_wait
- ros_send_sentence_cb
You choose ros_send_wait if you want to use blocking functions, and you choose ros_send_cb functions if you are using non-blocking functions. (remember to set the mode you want with ros_set_type)
A wrapper around socket() and connect() functions. Returns socket file descriptor handle. Port is usually ROS_PORT (8729).
A wrapper around close(). Please use this, in case there will be any automatic cleanup in the future.
Before sending any commands, you should log in using ros_login(conn, "user", "password"). The function returns with a true value on success. False on failure.
Send a RouterOS API "sentence" and waits for a response. The first argument after the connection handle is the command. For example "/interface/print". You can have as many "words" (parameters) as you like.
If the result is only one row; result->done will be 1. If it is a list, result->re will be 1 until the last row which will have result->done set to 1.
Server-side problems are reported with ->trap or ->fatal to 1. Problems sending the packet are reported with a NULL pointer.
NOTE The last argument MUST always be NULL.
int ros_send_command_cb(struct ros_connection *connection, void (*callback)(struct ros_result *result), char *command, ...)
Send a RouterOS API "sentence" and immidiatly return. The first argument after the callback identifier is the command. For example "/interface/print". You can have as many "words" (parameters) as you like. The callback should be defined as void callback(struct ros_result *result). For this callback to be fired, you have to pass NULL to the callback parameter in ros_runloop_once().
NOTE The last argument MUST always be NULL.
If the result was result->re you can use ros_read_packet() to get the next row. Use multiple times until result->done is 1.
Retrieve a parameter from the result. For example, if you want to get the name of the interface in a "/interface/print" command. You should call ros_get(result, "=name"); The pointer returned by this function is invalid after ros_free_result().
You should always free a result after usage, or you will experience memory leak.
Look at test3.c for a example of automatic event dispatching using .tags (tags are internally chosen by librouteros).
Works exactly as ros_send_command_wait() except that it does not wait for an answer. You should alwas set a .tag= word if you are awaiting several answers. Returns 1 on success and 0 on failure.
Use this to enter "event" mode. (nonblocking sockets) Usage: ros_set_type(conn, ROS_EVENT);
Use this to cancel a running tag. (You get the id from ros_send_*_cb commands)
Use select/epoll/poll to check for data on conn->socket. When you know there is data present, run the runloop_once() command with a callback function to handle the result. The callback function should be defined as: void callbackname(struct ros_result result); If you want the library to handle the callbacks internally, and spawn the correct callbacks defined in the ros_send__cb functions, you should give NULL as the callback parameter here.
Look at test2.c for a select() example.