1 /* 2 * Copyright (C) 2011-2014 Felix Fietkau <nbd@openwrt.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License version 2.1 6 * as published by the Free Software Foundation 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14 #include <sys/types.h> 15 #include <sys/socket.h> 16 #include <unistd.h> 17 #include <fcntl.h> 18 19 #include <libubox/blob.h> 20 #include <libubox/blobmsg.h> 21 22 #include "libubus.h" 23 #include "libubus-internal.h" 24 #include "ubusmsg.h" 25 26 const char *__ubus_strerror[__UBUS_STATUS_LAST] = { 27 [UBUS_STATUS_OK] = "Success", 28 [UBUS_STATUS_INVALID_COMMAND] = "Invalid command", 29 [UBUS_STATUS_INVALID_ARGUMENT] = "Invalid argument", 30 [UBUS_STATUS_METHOD_NOT_FOUND] = "Method not found", 31 [UBUS_STATUS_NOT_FOUND] = "Not found", 32 [UBUS_STATUS_NO_DATA] = "No response", 33 [UBUS_STATUS_PERMISSION_DENIED] = "Permission denied", 34 [UBUS_STATUS_TIMEOUT] = "Request timed out", 35 [UBUS_STATUS_NOT_SUPPORTED] = "Operation not supported", 36 [UBUS_STATUS_UNKNOWN_ERROR] = "Unknown error", 37 [UBUS_STATUS_CONNECTION_FAILED] = "Connection failed", 38 [UBUS_STATUS_NO_MEMORY] = "Out of memory", 39 [UBUS_STATUS_PARSE_ERROR] = "Parsing message data failed", 40 [UBUS_STATUS_SYSTEM_ERROR] = "System error", 41 }; 42 43 struct blob_buf b __hidden = {}; 44 45 struct ubus_pending_msg { 46 struct list_head list; 47 struct ubus_msghdr_buf hdr; 48 }; 49 50 static int ubus_cmp_id(const void *k1, const void *k2, void *ptr) 51 { 52 const uint32_t *id1 = k1, *id2 = k2; 53 54 if (*id1 < *id2) 55 return -1; 56 else 57 return *id1 > *id2; 58 } 59 60 const char *ubus_strerror(int error) 61 { 62 static char err[32]; 63 64 if (error < 0 || error >= __UBUS_STATUS_LAST) 65 goto out; 66 67 if (!__ubus_strerror[error]) 68 goto out; 69 70 return __ubus_strerror[error]; 71 72 out: 73 sprintf(err, "Unknown error: %d", error); 74 return err; 75 } 76 77 static void 78 ubus_queue_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf) 79 { 80 struct ubus_pending_msg *pending; 81 void *data; 82 83 pending = calloc_a(sizeof(*pending), &data, blob_raw_len(buf->data)); 84 85 pending->hdr.data = data; 86 memcpy(&pending->hdr.hdr, &buf->hdr, sizeof(buf->hdr)); 87 memcpy(data, buf->data, blob_raw_len(buf->data)); 88 list_add_tail(&pending->list, &ctx->pending); 89 if (ctx->sock.registered) 90 uloop_timeout_set(&ctx->pending_timer, 1); 91 } 92 93 void __hidden 94 ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd) 95 { 96 switch(buf->hdr.type) { 97 case UBUS_MSG_STATUS: 98 case UBUS_MSG_DATA: 99 ubus_process_req_msg(ctx, buf, fd); 100 break; 101 102 case UBUS_MSG_UNSUBSCRIBE: 103 case UBUS_MSG_NOTIFY: 104 if (ubus_context_is_channel(ctx)) 105 break; 106 /* fallthrough */ 107 case UBUS_MSG_INVOKE: 108 if (ctx->stack_depth) { 109 ubus_queue_msg(ctx, buf); 110 break; 111 } 112 113 ctx->stack_depth++; 114 ubus_process_obj_msg(ctx, buf, fd); 115 ctx->stack_depth--; 116 break; 117 case UBUS_MSG_MONITOR: 118 if (ubus_context_is_channel(ctx)) 119 break; 120 121 if (ctx->monitor_cb) 122 ctx->monitor_cb(ctx, buf->hdr.seq, buf->data); 123 break; 124 } 125 } 126 127 static void ubus_process_pending_msg(struct uloop_timeout *timeout) 128 { 129 struct ubus_context *ctx = container_of(timeout, struct ubus_context, pending_timer); 130 struct ubus_pending_msg *pending; 131 132 while (!list_empty(&ctx->pending)) { 133 if (ctx->stack_depth) 134 break; 135 136 pending = list_first_entry(&ctx->pending, struct ubus_pending_msg, list); 137 list_del(&pending->list); 138 ubus_process_msg(ctx, &pending->hdr, -1); 139 free(pending); 140 } 141 } 142 143 struct ubus_lookup_request { 144 struct ubus_request req; 145 ubus_lookup_handler_t cb; 146 }; 147 148 static void ubus_lookup_cb(struct ubus_request *ureq, int type, struct blob_attr *msg) 149 { 150 struct ubus_lookup_request *req; 151 struct ubus_object_data obj = {}; 152 struct blob_attr **attr; 153 154 req = container_of(ureq, struct ubus_lookup_request, req); 155 attr = ubus_parse_msg(msg, blob_raw_len(msg)); 156 157 if (!attr[UBUS_ATTR_OBJID] || !attr[UBUS_ATTR_OBJPATH] || 158 !attr[UBUS_ATTR_OBJTYPE]) 159 return; 160 161 obj.id = blob_get_u32(attr[UBUS_ATTR_OBJID]); 162 obj.path = blob_data(attr[UBUS_ATTR_OBJPATH]); 163 obj.type_id = blob_get_u32(attr[UBUS_ATTR_OBJTYPE]); 164 obj.signature = attr[UBUS_ATTR_SIGNATURE]; 165 req->cb(ureq->ctx, &obj, ureq->priv); 166 } 167 168 int ubus_lookup(struct ubus_context *ctx, const char *path, 169 ubus_lookup_handler_t cb, void *priv) 170 { 171 struct ubus_lookup_request lookup; 172 173 if (ubus_context_is_channel(ctx)) 174 return UBUS_STATUS_INVALID_ARGUMENT; 175 176 blob_buf_init(&b, 0); 177 if (path) 178 blob_put_string(&b, UBUS_ATTR_OBJPATH, path); 179 180 if (ubus_start_request(ctx, &lookup.req, b.head, UBUS_MSG_LOOKUP, 0) < 0) 181 return UBUS_STATUS_INVALID_ARGUMENT; 182 183 lookup.req.raw_data_cb = ubus_lookup_cb; 184 lookup.req.priv = priv; 185 lookup.cb = cb; 186 return ubus_complete_request(ctx, &lookup.req, 0); 187 } 188 189 static void ubus_lookup_id_cb(struct ubus_request *req, int type, struct blob_attr *msg) 190 { 191 struct blob_attr **attr; 192 uint32_t *id = req->priv; 193 194 attr = ubus_parse_msg(msg, blob_raw_len(msg)); 195 196 if (!attr[UBUS_ATTR_OBJID]) 197 return; 198 199 *id = blob_get_u32(attr[UBUS_ATTR_OBJID]); 200 } 201 202 int ubus_lookup_id(struct ubus_context *ctx, const char *path, uint32_t *id) 203 { 204 struct ubus_request req; 205 206 if (ubus_context_is_channel(ctx)) 207 return UBUS_STATUS_INVALID_ARGUMENT; 208 209 blob_buf_init(&b, 0); 210 if (path) 211 blob_put_string(&b, UBUS_ATTR_OBJPATH, path); 212 213 if (ubus_start_request(ctx, &req, b.head, UBUS_MSG_LOOKUP, 0) < 0) 214 return UBUS_STATUS_INVALID_ARGUMENT; 215 216 req.raw_data_cb = ubus_lookup_id_cb; 217 req.priv = id; 218 219 return ubus_complete_request(ctx, &req, 0); 220 } 221 222 static int ubus_event_cb(struct ubus_context *ctx, struct ubus_object *obj, 223 struct ubus_request_data *req, 224 const char *method, struct blob_attr *msg) 225 { 226 struct ubus_event_handler *ev; 227 228 ev = container_of(obj, struct ubus_event_handler, obj); 229 ev->cb(ctx, ev, method, msg); 230 return 0; 231 } 232 233 static const struct ubus_method event_method = { 234 .name = NULL, 235 .handler = ubus_event_cb, 236 }; 237 238 int ubus_register_event_handler(struct ubus_context *ctx, 239 struct ubus_event_handler *ev, 240 const char *pattern) 241 { 242 struct ubus_object *obj = &ev->obj; 243 struct blob_buf b2 = {}; 244 int ret; 245 246 if (ubus_context_is_channel(ctx)) 247 return UBUS_STATUS_INVALID_ARGUMENT; 248 249 if (!obj->id) { 250 obj->methods = &event_method; 251 obj->n_methods = 1; 252 253 if (!!obj->name ^ !!obj->type) 254 return UBUS_STATUS_INVALID_ARGUMENT; 255 256 ret = ubus_add_object(ctx, obj); 257 if (ret) 258 return ret; 259 } 260 261 /* use a second buffer, ubus_invoke() overwrites the primary one */ 262 blob_buf_init(&b2, 0); 263 blobmsg_add_u32(&b2, "object", obj->id); 264 if (pattern) 265 blobmsg_add_string(&b2, "pattern", pattern); 266 267 ret = ubus_invoke(ctx, UBUS_SYSTEM_OBJECT_EVENT, "register", b2.head, 268 NULL, NULL, 0); 269 blob_buf_free(&b2); 270 271 return ret; 272 } 273 274 int ubus_send_event(struct ubus_context *ctx, const char *id, 275 struct blob_attr *data) 276 { 277 struct ubus_request req; 278 void *s; 279 280 blob_buf_init(&b, 0); 281 blob_put_int32(&b, UBUS_ATTR_OBJID, UBUS_SYSTEM_OBJECT_EVENT); 282 blob_put_string(&b, UBUS_ATTR_METHOD, "send"); 283 s = blob_nest_start(&b, UBUS_ATTR_DATA); 284 blobmsg_add_string(&b, "id", id); 285 blobmsg_add_field(&b, BLOBMSG_TYPE_TABLE, "data", blob_data(data), blob_len(data)); 286 blob_nest_end(&b, s); 287 288 if (ubus_start_request(ctx, &req, b.head, UBUS_MSG_INVOKE, UBUS_SYSTEM_OBJECT_EVENT) < 0) 289 return UBUS_STATUS_INVALID_ARGUMENT; 290 291 return ubus_complete_request(ctx, &req, 0); 292 } 293 294 static void ubus_default_connection_lost(struct ubus_context *ctx) 295 { 296 if (ctx->sock.registered) 297 uloop_end(); 298 } 299 300 static int 301 __ubus_ctx_init(struct ubus_context *ctx) 302 { 303 uloop_init(); 304 memset(ctx, 0, sizeof(*ctx)); 305 306 ctx->sock.fd = -1; 307 ctx->sock.cb = ubus_handle_data; 308 ctx->connection_lost = ubus_default_connection_lost; 309 ctx->pending_timer.cb = ubus_process_pending_msg; 310 311 ctx->msgbuf.data = calloc(1, UBUS_MSG_CHUNK_SIZE); 312 if (!ctx->msgbuf.data) 313 return -1; 314 ctx->msgbuf_data_len = UBUS_MSG_CHUNK_SIZE; 315 316 INIT_LIST_HEAD(&ctx->requests); 317 INIT_LIST_HEAD(&ctx->pending); 318 avl_init(&ctx->objects, ubus_cmp_id, false, NULL); 319 return 0; 320 } 321 322 int ubus_connect_ctx(struct ubus_context *ctx, const char *path) 323 { 324 if (__ubus_ctx_init(ctx)) 325 return -1; 326 327 INIT_LIST_HEAD(&ctx->auto_subscribers); 328 if (ubus_reconnect(ctx, path)) { 329 free(ctx->msgbuf.data); 330 ctx->msgbuf.data = NULL; 331 return -1; 332 } 333 334 return 0; 335 } 336 337 int ubus_channel_connect(struct ubus_context *ctx, int fd, 338 ubus_handler_t handler) 339 { 340 if (__ubus_ctx_init(ctx)) 341 return -1; 342 343 if (ctx->sock.fd >= 0) { 344 if (ctx->sock.registered) 345 uloop_fd_delete(&ctx->sock); 346 347 close(ctx->sock.fd); 348 } 349 350 ctx->sock.eof = false; 351 ctx->sock.error = false; 352 ctx->sock.fd = fd; 353 ctx->local_id = UBUS_CLIENT_ID_CHANNEL; 354 ctx->request_handler = handler; 355 356 fcntl(ctx->sock.fd, F_SETFL, fcntl(ctx->sock.fd, F_GETFL) | O_NONBLOCK | O_CLOEXEC); 357 358 return 0; 359 } 360 361 int ubus_channel_create(struct ubus_context *ctx, int *remote_fd, 362 ubus_handler_t handler) 363 { 364 int sfd[2]; 365 366 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd)) 367 return -1; 368 369 if (ubus_channel_connect(ctx, sfd[0], handler) < 0) { 370 close(sfd[0]); 371 close(sfd[1]); 372 return -1; 373 } 374 375 *remote_fd = sfd[1]; 376 377 return 0; 378 } 379 380 static void ubus_auto_reconnect_cb(struct uloop_timeout *timeout) 381 { 382 struct ubus_auto_conn *conn = container_of(timeout, struct ubus_auto_conn, timer); 383 384 if (!ubus_reconnect(&conn->ctx, conn->path)) 385 ubus_add_uloop(&conn->ctx); 386 else 387 uloop_timeout_set(timeout, 1000); 388 } 389 390 static void ubus_auto_disconnect_cb(struct ubus_context *ctx) 391 { 392 struct ubus_auto_conn *conn = container_of(ctx, struct ubus_auto_conn, ctx); 393 394 conn->timer.cb = ubus_auto_reconnect_cb; 395 uloop_timeout_set(&conn->timer, 1000); 396 } 397 398 static void ubus_auto_connect_cb(struct uloop_timeout *timeout) 399 { 400 struct ubus_auto_conn *conn = container_of(timeout, struct ubus_auto_conn, timer); 401 402 if (ubus_connect_ctx(&conn->ctx, conn->path)) { 403 uloop_timeout_set(timeout, 1000); 404 fprintf(stderr, "failed to connect to ubus\n"); 405 return; 406 } 407 conn->ctx.connection_lost = ubus_auto_disconnect_cb; 408 if (conn->cb) 409 conn->cb(&conn->ctx); 410 ubus_add_uloop(&conn->ctx); 411 } 412 413 void ubus_auto_connect(struct ubus_auto_conn *conn) 414 { 415 conn->timer.cb = ubus_auto_connect_cb; 416 ubus_auto_connect_cb(&conn->timer); 417 } 418 419 struct ubus_context *ubus_connect(const char *path) 420 { 421 struct ubus_context *ctx; 422 423 ctx = calloc(1, sizeof(*ctx)); 424 if (!ctx) 425 return NULL; 426 427 if (ubus_connect_ctx(ctx, path)) { 428 free(ctx); 429 ctx = NULL; 430 } 431 432 return ctx; 433 } 434 435 void ubus_shutdown(struct ubus_context *ctx) 436 { 437 blob_buf_free(&b); 438 if (!ctx) 439 return; 440 uloop_fd_delete(&ctx->sock); 441 close(ctx->sock.fd); 442 uloop_timeout_cancel(&ctx->pending_timer); 443 free(ctx->msgbuf.data); 444 } 445 446 void ubus_free(struct ubus_context *ctx) 447 { 448 ubus_shutdown(ctx); 449 free(ctx); 450 } 451
This page was automatically generated by LXR 0.3.1. • OpenWrt