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 /* 78 * Note: any SCM_RIGHTS fd attached to the original message is not propagated 79 * to the queued copy — the caller must close it (or hand it off) separately. 80 */ 81 static void 82 ubus_queue_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf) 83 { 84 struct ubus_pending_msg *pending; 85 void *data; 86 87 pending = calloc_a(sizeof(*pending), &data, blob_raw_len(buf->data)); 88 if (!pending) 89 return; 90 91 pending->hdr.data = data; 92 memcpy(&pending->hdr.hdr, &buf->hdr, sizeof(buf->hdr)); 93 memcpy(data, buf->data, blob_raw_len(buf->data)); 94 list_add_tail(&pending->list, &ctx->pending); 95 if (ctx->sock.registered) 96 uloop_timeout_set(&ctx->pending_timer, 1); 97 } 98 99 void __hidden 100 ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf, int fd) 101 { 102 switch(buf->hdr.type) { 103 case UBUS_MSG_STATUS: 104 case UBUS_MSG_DATA: 105 ubus_process_req_msg(ctx, buf, fd); 106 return; 107 108 case UBUS_MSG_UNSUBSCRIBE: 109 case UBUS_MSG_NOTIFY: 110 if (ubus_context_is_channel(ctx)) 111 break; 112 /* fallthrough */ 113 case UBUS_MSG_INVOKE: 114 if (ctx->stack_depth) { 115 ubus_queue_msg(ctx, buf); 116 break; 117 } 118 119 ctx->stack_depth++; 120 ubus_process_obj_msg(ctx, buf, fd); 121 ctx->stack_depth--; 122 return; 123 case UBUS_MSG_MONITOR: 124 if (ubus_context_is_channel(ctx)) 125 break; 126 127 if (ctx->monitor_cb) 128 ctx->monitor_cb(ctx, buf->hdr.seq, buf->data); 129 break; 130 } 131 132 if (fd >= 0) 133 close(fd); 134 } 135 136 static void ubus_process_pending_msg(struct uloop_timeout *timeout) 137 { 138 struct ubus_context *ctx = container_of(timeout, struct ubus_context, pending_timer); 139 struct ubus_pending_msg *pending; 140 141 while (!list_empty(&ctx->pending)) { 142 if (ctx->stack_depth) 143 break; 144 145 pending = list_first_entry(&ctx->pending, struct ubus_pending_msg, list); 146 list_del(&pending->list); 147 ubus_process_msg(ctx, &pending->hdr, -1); 148 free(pending); 149 } 150 } 151 152 struct ubus_lookup_request { 153 struct ubus_request req; 154 ubus_lookup_handler_t cb; 155 }; 156 157 static void ubus_lookup_cb(struct ubus_request *ureq, int type, struct blob_attr *msg) 158 { 159 struct ubus_lookup_request *req; 160 struct ubus_object_data obj = {}; 161 struct blob_attr **attr; 162 163 req = container_of(ureq, struct ubus_lookup_request, req); 164 attr = ubus_parse_msg(msg, blob_raw_len(msg)); 165 166 if (!attr[UBUS_ATTR_OBJID] || !attr[UBUS_ATTR_OBJPATH] || 167 !attr[UBUS_ATTR_OBJTYPE]) 168 return; 169 170 obj.id = blob_get_u32(attr[UBUS_ATTR_OBJID]); 171 obj.path = blob_data(attr[UBUS_ATTR_OBJPATH]); 172 obj.type_id = blob_get_u32(attr[UBUS_ATTR_OBJTYPE]); 173 obj.signature = attr[UBUS_ATTR_SIGNATURE]; 174 req->cb(ureq->ctx, &obj, ureq->priv); 175 } 176 177 int ubus_lookup(struct ubus_context *ctx, const char *path, 178 ubus_lookup_handler_t cb, void *priv) 179 { 180 struct ubus_lookup_request lookup; 181 182 if (ubus_context_is_channel(ctx)) 183 return UBUS_STATUS_INVALID_ARGUMENT; 184 185 blob_buf_init(&b, 0); 186 if (path) 187 blob_put_string(&b, UBUS_ATTR_OBJPATH, path); 188 189 if (ubus_start_request(ctx, &lookup.req, b.head, UBUS_MSG_LOOKUP, 0) < 0) 190 return UBUS_STATUS_INVALID_ARGUMENT; 191 192 lookup.req.raw_data_cb = ubus_lookup_cb; 193 lookup.req.priv = priv; 194 lookup.cb = cb; 195 return ubus_complete_request(ctx, &lookup.req, 0); 196 } 197 198 static void ubus_lookup_id_cb(struct ubus_request *req, int type, struct blob_attr *msg) 199 { 200 struct blob_attr **attr; 201 uint32_t *id = req->priv; 202 203 attr = ubus_parse_msg(msg, blob_raw_len(msg)); 204 205 if (!attr[UBUS_ATTR_OBJID]) 206 return; 207 208 *id = blob_get_u32(attr[UBUS_ATTR_OBJID]); 209 } 210 211 int ubus_lookup_id(struct ubus_context *ctx, const char *path, uint32_t *id) 212 { 213 struct ubus_request req; 214 215 if (ubus_context_is_channel(ctx)) 216 return UBUS_STATUS_INVALID_ARGUMENT; 217 218 blob_buf_init(&b, 0); 219 if (path) 220 blob_put_string(&b, UBUS_ATTR_OBJPATH, path); 221 222 if (ubus_start_request(ctx, &req, b.head, UBUS_MSG_LOOKUP, 0) < 0) 223 return UBUS_STATUS_INVALID_ARGUMENT; 224 225 req.raw_data_cb = ubus_lookup_id_cb; 226 req.priv = id; 227 228 return ubus_complete_request(ctx, &req, 0); 229 } 230 231 static int ubus_event_cb(struct ubus_context *ctx, struct ubus_object *obj, 232 struct ubus_request_data *req, 233 const char *method, struct blob_attr *msg) 234 { 235 struct ubus_event_handler *ev; 236 237 ev = container_of(obj, struct ubus_event_handler, obj); 238 ev->cb(ctx, ev, method, msg); 239 return 0; 240 } 241 242 static const struct ubus_method event_method = { 243 .name = NULL, 244 .handler = ubus_event_cb, 245 }; 246 247 int ubus_register_event_handler(struct ubus_context *ctx, 248 struct ubus_event_handler *ev, 249 const char *pattern) 250 { 251 struct ubus_object *obj = &ev->obj; 252 struct blob_buf b2 = {}; 253 int ret; 254 255 if (ubus_context_is_channel(ctx)) 256 return UBUS_STATUS_INVALID_ARGUMENT; 257 258 if (!obj->id) { 259 obj->methods = &event_method; 260 obj->n_methods = 1; 261 262 if (!!obj->name ^ !!obj->type) 263 return UBUS_STATUS_INVALID_ARGUMENT; 264 265 ret = ubus_add_object(ctx, obj); 266 if (ret) 267 return ret; 268 } 269 270 /* use a second buffer, ubus_invoke() overwrites the primary one */ 271 blob_buf_init(&b2, 0); 272 blobmsg_add_u32(&b2, "object", obj->id); 273 if (pattern) 274 blobmsg_add_string(&b2, "pattern", pattern); 275 276 ret = ubus_invoke(ctx, UBUS_SYSTEM_OBJECT_EVENT, "register", b2.head, 277 NULL, NULL, 0); 278 blob_buf_free(&b2); 279 280 return ret; 281 } 282 283 int ubus_send_event(struct ubus_context *ctx, const char *id, 284 struct blob_attr *data) 285 { 286 struct ubus_request req; 287 void *s; 288 289 blob_buf_init(&b, 0); 290 blob_put_int32(&b, UBUS_ATTR_OBJID, UBUS_SYSTEM_OBJECT_EVENT); 291 blob_put_string(&b, UBUS_ATTR_METHOD, "send"); 292 s = blob_nest_start(&b, UBUS_ATTR_DATA); 293 blobmsg_add_string(&b, "id", id); 294 blobmsg_add_field(&b, BLOBMSG_TYPE_TABLE, "data", blob_data(data), blob_len(data)); 295 blob_nest_end(&b, s); 296 297 if (ubus_start_request(ctx, &req, b.head, UBUS_MSG_INVOKE, UBUS_SYSTEM_OBJECT_EVENT) < 0) 298 return UBUS_STATUS_INVALID_ARGUMENT; 299 300 return ubus_complete_request(ctx, &req, 0); 301 } 302 303 static void ubus_default_connection_lost(struct ubus_context *ctx) 304 { 305 if (ctx->sock.registered) 306 uloop_end(); 307 } 308 309 static int 310 __ubus_ctx_init(struct ubus_context *ctx) 311 { 312 uloop_init(); 313 memset(ctx, 0, sizeof(*ctx)); 314 315 ctx->sock.fd = -1; 316 ctx->sock.cb = ubus_handle_data; 317 ctx->connection_lost = ubus_default_connection_lost; 318 ctx->pending_timer.cb = ubus_process_pending_msg; 319 320 ctx->msgbuf.data = calloc(1, UBUS_MSG_CHUNK_SIZE); 321 if (!ctx->msgbuf.data) 322 return -1; 323 ctx->msgbuf_data_len = UBUS_MSG_CHUNK_SIZE; 324 325 INIT_LIST_HEAD(&ctx->requests); 326 INIT_LIST_HEAD(&ctx->pending); 327 avl_init(&ctx->objects, ubus_cmp_id, false, NULL); 328 return 0; 329 } 330 331 int ubus_connect_ctx(struct ubus_context *ctx, const char *path) 332 { 333 if (__ubus_ctx_init(ctx)) 334 return -1; 335 336 INIT_LIST_HEAD(&ctx->auto_subscribers); 337 if (ubus_reconnect(ctx, path)) { 338 free(ctx->msgbuf.data); 339 ctx->msgbuf.data = NULL; 340 return -1; 341 } 342 343 return 0; 344 } 345 346 int ubus_channel_connect(struct ubus_context *ctx, int fd, 347 ubus_handler_t handler) 348 { 349 if (__ubus_ctx_init(ctx)) 350 return -1; 351 352 if (ctx->sock.fd >= 0) { 353 if (ctx->sock.registered) 354 uloop_fd_delete(&ctx->sock); 355 356 close(ctx->sock.fd); 357 } 358 359 int flags = fcntl(fd, F_GETFL); 360 if (flags < 0 || 361 fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0 || 362 fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) { 363 ctx->sock.fd = -1; 364 return -1; 365 } 366 367 ctx->sock.eof = false; 368 ctx->sock.error = false; 369 ctx->sock.fd = fd; 370 ctx->local_id = UBUS_CLIENT_ID_CHANNEL; 371 ctx->request_handler = handler; 372 373 return 0; 374 } 375 376 int ubus_channel_create(struct ubus_context *ctx, int *remote_fd, 377 ubus_handler_t handler) 378 { 379 int sfd[2]; 380 381 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd)) 382 return -1; 383 384 if (ubus_channel_connect(ctx, sfd[0], handler) < 0) { 385 close(sfd[0]); 386 close(sfd[1]); 387 return -1; 388 } 389 390 *remote_fd = sfd[1]; 391 392 return 0; 393 } 394 395 static void ubus_auto_reconnect_cb(struct uloop_timeout *timeout) 396 { 397 struct ubus_auto_conn *conn = container_of(timeout, struct ubus_auto_conn, timer); 398 399 if (!ubus_reconnect(&conn->ctx, conn->path)) 400 ubus_add_uloop(&conn->ctx); 401 else 402 uloop_timeout_set(timeout, 1000); 403 } 404 405 static void ubus_auto_disconnect_cb(struct ubus_context *ctx) 406 { 407 struct ubus_auto_conn *conn = container_of(ctx, struct ubus_auto_conn, ctx); 408 409 conn->timer.cb = ubus_auto_reconnect_cb; 410 uloop_timeout_set(&conn->timer, 1000); 411 } 412 413 static void ubus_auto_connect_cb(struct uloop_timeout *timeout) 414 { 415 struct ubus_auto_conn *conn = container_of(timeout, struct ubus_auto_conn, timer); 416 417 if (ubus_connect_ctx(&conn->ctx, conn->path)) { 418 uloop_timeout_set(timeout, 1000); 419 fprintf(stderr, "failed to connect to ubus\n"); 420 return; 421 } 422 conn->ctx.connection_lost = ubus_auto_disconnect_cb; 423 if (conn->cb) 424 conn->cb(&conn->ctx); 425 ubus_add_uloop(&conn->ctx); 426 } 427 428 void ubus_auto_connect(struct ubus_auto_conn *conn) 429 { 430 conn->timer.cb = ubus_auto_connect_cb; 431 ubus_auto_connect_cb(&conn->timer); 432 } 433 434 struct ubus_context *ubus_connect(const char *path) 435 { 436 struct ubus_context *ctx; 437 438 ctx = calloc(1, sizeof(*ctx)); 439 if (!ctx) 440 return NULL; 441 442 if (ubus_connect_ctx(ctx, path)) { 443 free(ctx); 444 ctx = NULL; 445 } 446 447 return ctx; 448 } 449 450 void ubus_shutdown(struct ubus_context *ctx) 451 { 452 blob_buf_free(&b); 453 if (!ctx) 454 return; 455 uloop_fd_delete(&ctx->sock); 456 if (ctx->sock.fd >= 0) { 457 close(ctx->sock.fd); 458 ctx->sock.fd = -1; 459 } 460 uloop_timeout_cancel(&ctx->pending_timer); 461 free(ctx->msgbuf.data); 462 ctx->msgbuf.data = NULL; 463 } 464 465 void ubus_free(struct ubus_context *ctx) 466 { 467 ubus_shutdown(ctx); 468 free(ctx); 469 } 470
This page was automatically generated by LXR 0.3.1. • OpenWrt