The u-bus (micro version of D-Bus) is an interface that allows users to access and use services from the same place. Some services are built-in to OpenWRT and other services are executable files that we have created ourselves.
Each process or daemon can register set of its own paths/pipes. The communication is made by marshalling data to TLV-format message and sent via Unix socket.
Components
The main component of UBUS framework is the ubus daemon. It must be running before all other stuff can be called. On some devices, it runs with default Unix socket path /var/run/ubus.sock.
Sometimes we need routines from U-Box too (uloop_* routines), such as ubus_add_uloop.
Repository: http://git.openwrt.org/project/ubus.git
UBUS Structure
We connected to ubus via the ubus command line interface, ubus_cli on the figure. The ubus allowed us connect to onion service through the rcpd, which we will discuss in depth later on. Once the onion service executed the requested function, the ouput was relayed back to the ubus_cli via the ubus.
The ubus gives us a very powerful tool for accessing services both locally and remotely.
ubus module in openWRT is located in folder $BASE/openwrt/build_dir/target-arm_cortex-a9_uClibc-0.9.33.2_eabi/ubus-2015-05-25/
From OpenWRT shell, we can list what services are available:
To talk to the service module and perform the supported service, we can type:
Services/Plugins
When we invoke "ubus list", it lists all the services available, either native to OpenWRT or custom made (by third parties). To find which ones are custom services, do:
The rpcd plugin allows users to expose their custom services in the form of executable shell scripts over the ubus.
The module above is generated from code located in $BASE/openwrt/build_dir/target-arm_cortex-a9_uClibc-0.9.33.2_eabi/juci-<uuid>/backend/juci-core, where <uuid> is generated during first make.
On the target, some of the modules stored in /www/cgi-bin/ as webUI interfaces.
To see what functions available for a certain path, type "ubus list -v <path>", an to invoke the RPC function we type "ubus call <path/service> <function> '{<JSON parameters>}'
For example, to call tr069::notify(), we do:
Another example, to get the current firmware version:
U-BUS C Function Calls/API
Function
|
Description
|
---|---|
struct ubus_context *ubus_connect(const char *path)
|
UBUS initialization. Call this at very beginning before we use UBUS. The path is something like "network.interface".
To see the available path on device, type:
ubus list
|
int ubus_connect_ctx(struct ubus_context *ctx, const char *path)
| |
void ubus_auto_connect(struct ubus_auto_conn *conn) | Auto connect UBUS when the connection is lost. The connection is checked every 1000 msecs (1 Second) |
int ubus_reconnect(struct ubus_context *ctx, const char *path) | Try to reconnect existing context to path. This is usually useful when we've had ubus context, but for some reason the connection has severed/disconnected. |
void ubus_free(struct ubus_context *ctx) | It is identical to ubus_shutdown() + freeing the context. |
void ubus_shutdown(struct ubus_context *ctx)
| Shutdown UBUS: free blob buffer, close socket used and free message buffer, but it doesn't free context |
void ubus_auto_shutdown(struct ubus_auto_conn *conn)
| |
const char *ubus_strerror(int error)
| |
inline void ubus_add_uloop(struct ubus_context *ctx) |
Activate UBUS; this tells U-Loop to check for ubus events (listens to ubus).
It is blocking function, meaning that once we call uloop_run, it is waiting for ubus to get something
|
int ubus_lookup(struct ubus_context *ctx, const char *path, ubus_lookup_handler_t cb, void *priv)
|
ctx: ubus context (assigned by ubus_connect())
path: ubus path. For example: "network"
cb: callback routine to be called upon receiving data (currently, it is no effect/not-used)
priv: parameter to pass to remote (seems not used)
|
int ubus_lookup_id(struct ubus_context *ctx, const char *path, uint32_t *id) |
This routine gets id from path. If it is successful, it returns UBUS_STATUS_OK, otherwise UBUS_STATUS_* error-code
Example:
|
int ubus_add_object(struct ubus_context *ctx, struct ubus_object *obj) |
Add a UBUS object into the list of objects to be queried. We must call this routine before doing ubus_lookup_id.
|
int ubus_remove_object(struct ubus_context *ctx, struct ubus_object *obj) | The opposite of ubus_add_object; called when we need to cleanup the pending request |
int ubus_register_subscriber(struct ubus_context *ctx, struct ubus_subscriber *obj) | |
int ubus_subscribe(struct ubus_context *ctx, struct ubus_subscriber *obj, uint32_t id)
| |
int ubus_unsubscribe(struct ubus_context *ctx, struct ubus_subscriber *obj, uint32_t id) | |
int ubus_monitor_start(struct ubus_context *ctx)
| |
int ubus_monitor_stop(struct ubus_context *ctx)
| |
void ubus_complete_request_async(struct ubus_context *ctx, struct ubus_request *req) | |
void ubus_abort_request(struct ubus_context *ctx, struct ubus_request *req)
|
Abort/cancel previous not-yet-sent request pointed by req parameter
|
int ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method, struct blob_attr *msg, struct ubus_request *req)
|
Invoke RPC asynchronously.
method: the name of method to remotely execute
msg: parameters (in the form of BLOB)
req: request object returned (contains sequence number, context, etc.)
|
int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method, struct blob_attr *msg, ubus_data_handler_t cb, void *priv, int timeout)
|
Invoke RPC indicated in passed parameter method. Unlike ubus_invoke_asyn(), the caller doesn't need to call ubus_complete_request() {actually it does internally}.
cb: if not NULL, callback routine to be called once data is available.
This routine internally calls ubus_invoke_async()
|
int ubus_send_reply(struct ubus_context *ctx, struct ubus_request *req, struct blob_attr *msg) | Send reply to the incoming object method call |
int ubus_send_event(struct ubus_context *ctx, const char *id, struct blob_attr *data)
| Send an event indicated in ev parameter with parameter data |
int ubus_register_event_handler(struct ubus_context *ctx, struct ubus_event_handler *ev, const char *pattern) | Register ev handler for event |
int ubus_unregister_event_handler(struct ubus_context *ctx, struct ubus_event_handler *ev) |
EXAMPLES
A very basic client:
(...to be continued....)
How do you make a uci set configuration to update disabled option for wireless config by ubus with a curl?
ReplyDeleteGreat Post.... Thanks
ReplyDeletecurl -d '{ "jsonrpc": "2.0", "id": 1, "method": "call", "params": [ "7cba69a942c0e9db1eb7982cd91f3a48", "file", "read", { "path": "/tmp/hello.karl" } ] }' http://eg-134867.local/ubus
ReplyDeletecurl -d '{ "jsonrpc": "2.0", "id": 1, "method": "call", "params": [ "7cba69a942c0e9db1eb7982cd91f3a48", "file", "read", { "path": "/tmp/hello.karl" } ] }' http://eg-134867.local/ubus
ReplyDeletePlease give an example for UBUS Listen use in client side.
ReplyDelete