1 /* 2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org> 3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License version 2.1 7 * as published by the Free Software Foundation 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15 #include <sys/types.h> 16 #include <sys/stat.h> 17 #include <sys/utsname.h> 18 #include <sys/types.h> 19 #include <fcntl.h> 20 21 #include <unistd.h> 22 #include <sched.h> 23 24 #include <libubox/blobmsg_json.h> 25 #include <libubox/avl-cmp.h> 26 27 #include "../procd.h" 28 29 #include "service.h" 30 #include "instance.h" 31 32 #include "../rcS.h" 33 34 AVL_TREE(services, avl_strcmp, false, NULL); 35 AVL_TREE(containers, avl_strcmp, false, NULL); 36 static struct blob_buf b; 37 static struct ubus_context *ctx; 38 static struct ubus_object main_object; 39 40 static void 41 service_instance_add(struct service *s, struct blob_attr *attr) 42 { 43 struct service_instance *in; 44 45 if (blobmsg_type(attr) != BLOBMSG_TYPE_TABLE) 46 return; 47 48 in = calloc(1, sizeof(*in)); 49 if (!in) 50 return; 51 52 instance_init(in, s, attr); 53 vlist_add(&s->instances, &in->node, (void *) in->name); 54 } 55 56 void service_data_trigger(struct blobmsg_list *list) 57 { 58 struct blobmsg_list_node *node; 59 60 avl_for_each_element(&list->avl, node, avl) { 61 blob_buf_init(&b, 0); 62 blobmsg_add_string(&b, "name", blobmsg_name(node->data)); 63 trigger_event("service.data.update", b.head); 64 } 65 } 66 67 static void 68 service_instance_update(struct vlist_tree *tree, struct vlist_node *node_new, 69 struct vlist_node *node_old) 70 { 71 struct service_instance *in_o = NULL, *in_n = NULL; 72 73 if (node_old) 74 in_o = container_of(node_old, struct service_instance, node); 75 76 if (node_new) 77 in_n = container_of(node_new, struct service_instance, node); 78 79 if (in_o && in_n) { 80 P_DEBUG(2, "Update instance %s::%s\n", in_o->srv->name, in_o->name); 81 instance_update(in_o, in_n); 82 instance_free(in_n); 83 } else if (in_o) { 84 P_DEBUG(2, "Stop instance %s::%s\n", in_o->srv->name, in_o->name); 85 instance_stop(in_o, true); 86 } else if (in_n && in_n->srv->autostart) { 87 P_DEBUG(2, "Start instance %s::%s\n", in_n->srv->name, in_n->name); 88 instance_start(in_n); 89 } 90 blob_buf_init(&b, 0); 91 trigger_event("instance.update", b.head); 92 } 93 94 static struct service * 95 service_alloc(const char *name) 96 { 97 struct service *s; 98 char *new_name; 99 100 s = calloc_a(sizeof(*s), &new_name, strlen(name) + 1); 101 strcpy(new_name, name); 102 103 vlist_init(&s->instances, avl_strcmp, service_instance_update); 104 s->instances.no_delete = true; 105 s->name = new_name; 106 s->avl.key = s->name; 107 INIT_LIST_HEAD(&s->validators); 108 blobmsg_list_simple_init(&s->data_blob); 109 110 return s; 111 } 112 113 enum { 114 SERVICE_SET_NAME, 115 SERVICE_SET_SCRIPT, 116 SERVICE_SET_INSTANCES, 117 SERVICE_SET_TRIGGER, 118 SERVICE_SET_VALIDATE, 119 SERVICE_SET_AUTOSTART, 120 SERVICE_SET_DATA, 121 __SERVICE_SET_MAX 122 }; 123 124 static const struct blobmsg_policy service_set_attrs[__SERVICE_SET_MAX] = { 125 [SERVICE_SET_NAME] = { "name", BLOBMSG_TYPE_STRING }, 126 [SERVICE_SET_SCRIPT] = { "script", BLOBMSG_TYPE_STRING }, 127 [SERVICE_SET_INSTANCES] = { "instances", BLOBMSG_TYPE_TABLE }, 128 [SERVICE_SET_TRIGGER] = { "triggers", BLOBMSG_TYPE_ARRAY }, 129 [SERVICE_SET_VALIDATE] = { "validate", BLOBMSG_TYPE_ARRAY }, 130 [SERVICE_SET_AUTOSTART] = { "autostart", BLOBMSG_TYPE_BOOL }, 131 [SERVICE_SET_DATA] = { "data", BLOBMSG_TYPE_TABLE }, 132 }; 133 134 static int 135 service_update_data(struct service *s, struct blob_attr *data) 136 { 137 if (blob_attr_equal(s->data, data)) 138 return 0; 139 140 service_data_trigger(&s->data_blob); 141 blobmsg_list_free(&s->data_blob); 142 143 free(s->data); 144 s->data = blob_memdup(data); 145 if (!s->data) 146 return -1; 147 148 blobmsg_list_fill(&s->data_blob, blobmsg_data(s->data), 149 blobmsg_data_len(s->data), false); 150 service_data_trigger(&s->data_blob); 151 152 return 0; 153 } 154 155 static int 156 service_update(struct service *s, struct blob_attr **tb, bool add, bool init) 157 { 158 struct blob_attr *cur; 159 int rem; 160 161 if (tb[SERVICE_SET_AUTOSTART]) 162 s->autostart = blobmsg_get_bool(tb[SERVICE_SET_AUTOSTART]); 163 else if (init) 164 s->autostart = true; 165 166 if (tb[SERVICE_SET_TRIGGER]) { 167 free(s->trigger); 168 s->trigger = blob_memdup(tb[SERVICE_SET_TRIGGER]); 169 if (!s->trigger) 170 return -1; 171 172 trigger_del(s); 173 trigger_add(s->trigger, s); 174 } 175 176 if (tb[SERVICE_SET_VALIDATE]) { 177 service_validate_del(s); 178 blobmsg_for_each_attr(cur, tb[SERVICE_SET_VALIDATE], rem) 179 service_validate_add(s, cur); 180 } 181 182 if (tb[SERVICE_SET_INSTANCES]) { 183 if (!add) 184 vlist_update(&s->instances); 185 blobmsg_for_each_attr(cur, tb[SERVICE_SET_INSTANCES], rem) { 186 service_instance_add(s, cur); 187 } 188 if (!add) 189 vlist_flush(&s->instances); 190 } 191 192 if (tb[SERVICE_SET_DATA] && 193 service_update_data(s, tb[SERVICE_SET_DATA]) < 0) 194 return -1; 195 196 s->deleted = false; 197 198 if (init || tb[SERVICE_SET_INSTANCES]) 199 rc(s->name, "running"); 200 201 return 0; 202 } 203 204 static void 205 service_delete(struct service *s, bool container) 206 { 207 blobmsg_list_free(&s->data_blob); 208 free(s->data); 209 s->data = NULL; 210 vlist_flush_all(&s->instances); 211 s->deleted = true; 212 service_stopped(s); 213 } 214 215 enum { 216 SERVICE_ATTR_NAME, 217 __SERVICE_ATTR_MAX, 218 }; 219 220 static const struct blobmsg_policy service_attrs[__SERVICE_ATTR_MAX] = { 221 [SERVICE_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING }, 222 }; 223 224 enum { 225 SERVICE_DEL_ATTR_NAME, 226 SERVICE_DEL_ATTR_INSTANCE, 227 __SERVICE_DEL_ATTR_MAX, 228 }; 229 230 static const struct blobmsg_policy service_del_attrs[__SERVICE_DEL_ATTR_MAX] = { 231 [SERVICE_DEL_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING }, 232 [SERVICE_DEL_ATTR_INSTANCE] = { "instance", BLOBMSG_TYPE_STRING }, 233 }; 234 235 enum { 236 SERVICE_LIST_ATTR_NAME, 237 SERVICE_LIST_ATTR_VERBOSE, 238 __SERVICE_LIST_ATTR_MAX, 239 }; 240 241 static const struct blobmsg_policy service_list_attrs[__SERVICE_LIST_ATTR_MAX] = { 242 [SERVICE_LIST_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING }, 243 [SERVICE_LIST_ATTR_VERBOSE] = { "verbose", BLOBMSG_TYPE_BOOL }, 244 }; 245 246 enum { 247 SERVICE_SIGNAL_ATTR_NAME, 248 SERVICE_SIGNAL_ATTR_INSTANCE, 249 SERVICE_SIGNAL_ATTR_SIGNAL, 250 __SERVICE_SIGNAL_ATTR_MAX, 251 }; 252 253 static const struct blobmsg_policy service_signal_attrs[__SERVICE_SIGNAL_ATTR_MAX] = { 254 [SERVICE_SIGNAL_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING }, 255 [SERVICE_SIGNAL_ATTR_INSTANCE] = { "instance", BLOBMSG_TYPE_STRING }, 256 [SERVICE_SIGNAL_ATTR_SIGNAL] = { "signal", BLOBMSG_TYPE_INT32 }, 257 }; 258 259 enum { 260 SERVICE_STATE_ATTR_SPAWN, 261 SERVICE_STATE_ATTR_NAME, 262 __SERVICE_STATE_ATTR_MAX, 263 }; 264 265 static const struct blobmsg_policy service_state_attrs[__SERVICE_STATE_ATTR_MAX] = { 266 [SERVICE_STATE_ATTR_SPAWN] = { "spawn", BLOBMSG_TYPE_BOOL }, 267 [SERVICE_STATE_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING }, 268 }; 269 270 enum { 271 EVENT_TYPE, 272 EVENT_DATA, 273 __EVENT_MAX 274 }; 275 276 static const struct blobmsg_policy event_policy[__EVENT_MAX] = { 277 [EVENT_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING }, 278 [EVENT_DATA] = { .name = "data", .type = BLOBMSG_TYPE_TABLE }, 279 }; 280 281 enum { 282 VALIDATE_PACKAGE, 283 VALIDATE_TYPE, 284 VALIDATE_SERVICE, 285 __VALIDATE_MAX 286 }; 287 288 static const struct blobmsg_policy validate_policy[__VALIDATE_MAX] = { 289 [VALIDATE_PACKAGE] = { .name = "package", .type = BLOBMSG_TYPE_STRING }, 290 [VALIDATE_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING }, 291 [VALIDATE_SERVICE] = { .name = "service", .type = BLOBMSG_TYPE_STRING }, 292 }; 293 294 enum { 295 DATA_NAME, 296 DATA_INSTANCE, 297 DATA_TYPE, 298 __DATA_MAX 299 }; 300 301 static const struct blobmsg_policy get_data_policy[] = { 302 [DATA_NAME] = { "name", BLOBMSG_TYPE_STRING }, 303 [DATA_INSTANCE] = { "instance", BLOBMSG_TYPE_STRING }, 304 [DATA_TYPE] = { "type", BLOBMSG_TYPE_STRING }, 305 }; 306 307 enum { 308 CONTAINER_CONSOLE_NAME, 309 CONTAINER_CONSOLE_INSTANCE, 310 __CONTAINER_CONSOLE_MAX, 311 }; 312 313 static const struct blobmsg_policy container_console_policy[__CONTAINER_CONSOLE_MAX] = { 314 [CONTAINER_CONSOLE_NAME] = { "name", BLOBMSG_TYPE_STRING }, 315 [CONTAINER_CONSOLE_INSTANCE] = { "instance", BLOBMSG_TYPE_STRING }, 316 }; 317 318 static inline bool is_container_obj(struct ubus_object *obj) 319 { 320 return (obj && (strcmp(obj->name, "container") == 0)); 321 } 322 323 static inline void put_namespace(struct blob_buf *b, char *name) 324 { 325 char nsfname[32]; 326 struct stat statbuf; 327 328 snprintf(nsfname, sizeof(nsfname), "/proc/self/ns/%s", name); 329 330 if (!stat(nsfname, &statbuf)) 331 blobmsg_add_string(b, NULL, name); 332 } 333 334 static void put_cgroups(struct blob_buf *b) 335 { 336 int fd, ret; 337 static char buf[512] = ""; 338 char *t, *z; 339 340 fd = open("/sys/fs/cgroup/cgroup.controllers", O_RDONLY); 341 if (fd == -1) 342 return; 343 344 ret = read(fd, &buf, sizeof(buf)); 345 /* make sure buffer is NULL-terminated */ 346 buf[sizeof(buf)-1] = '\0'; 347 348 close(fd); 349 350 if (ret < 2) 351 return; 352 353 t = buf; 354 while(t) { 355 z = t; 356 /* replace space with \0 and direct next entry */ 357 t = strchr(z, ' '); 358 if (t) { 359 *(t++) = '\0'; 360 } else { /* replace trailing new-line with \0 */ 361 t = strchr(z, '\n'); 362 if (!t) /* shouldn't happen, but don't segfault if it does */ 363 break; 364 365 *t = '\0'; 366 t = NULL; 367 } 368 blobmsg_add_string(b, NULL, z); 369 } 370 } 371 372 static int 373 container_handle_features(struct ubus_context *ctx, struct ubus_object *obj, 374 struct ubus_request_data *req, const char *method, 375 struct blob_attr *msg) 376 { 377 struct utsname utsbuf; 378 struct stat statbuf; 379 void *nsarray, *cgarray; 380 381 if (stat("/sbin/ujail", &statbuf)) 382 return UBUS_STATUS_NOT_SUPPORTED; 383 384 if (uname(&utsbuf) < 0) 385 return UBUS_STATUS_UNKNOWN_ERROR; 386 387 blob_buf_init(&b, 0); 388 blobmsg_add_string(&b, "machine", utsbuf.machine); 389 390 #ifdef SECCOMP_SUPPORT 391 blobmsg_add_u8(&b, "seccomp", true); 392 #else 393 blobmsg_add_u8(&b, "seccomp", false); 394 #endif 395 396 cgarray = blobmsg_open_array(&b, "cgroup"); 397 put_cgroups(&b); 398 blobmsg_close_array(&b, cgarray); 399 400 nsarray = blobmsg_open_array(&b, "namespaces"); 401 put_namespace(&b, "cgroup"); 402 put_namespace(&b, "ipc"); 403 put_namespace(&b, "mnt"); 404 put_namespace(&b, "net"); 405 put_namespace(&b, "pid"); 406 #ifdef CLONE_NEWTIME 407 put_namespace(&b, "time"); 408 #endif 409 put_namespace(&b, "user"); 410 put_namespace(&b, "uts"); 411 blobmsg_close_array(&b, nsarray); 412 ubus_send_reply(ctx, req, b.head); 413 414 return UBUS_STATUS_OK; 415 } 416 417 static int 418 service_handle_set(struct ubus_context *ctx, struct ubus_object *obj, 419 struct ubus_request_data *req, const char *method, 420 struct blob_attr *msg) 421 { 422 struct blob_attr *tb[__SERVICE_SET_MAX], *cur; 423 struct service *s = NULL; 424 const char *name; 425 bool container = is_container_obj(obj); 426 bool add = !strcmp(method, "add"); 427 int ret; 428 429 blobmsg_parse(service_set_attrs, __SERVICE_SET_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 430 cur = tb[SERVICE_SET_NAME]; 431 if (!cur) 432 return UBUS_STATUS_INVALID_ARGUMENT; 433 434 name = blobmsg_data(cur); 435 436 if (container) 437 s = avl_find_element(&containers, name, s, avl); 438 else 439 s = avl_find_element(&services, name, s, avl); 440 441 if (s) { 442 P_DEBUG(2, "Update service %s\n", name); 443 return service_update(s, tb, add, false); 444 } 445 446 P_DEBUG(2, "Create service %s\n", name); 447 s = service_alloc(name); 448 if (!s) 449 return UBUS_STATUS_UNKNOWN_ERROR; 450 451 s->container = container; 452 453 ret = service_update(s, tb, add, true); 454 if (ret) 455 return ret; 456 457 if (container) { 458 avl_insert(&containers, &s->avl); 459 460 service_event("container.start", s->name, NULL); 461 } else { 462 avl_insert(&services, &s->avl); 463 464 service_event("service.start", s->name, NULL); 465 } 466 return 0; 467 } 468 469 static void 470 service_dump(struct service *s, bool verbose) 471 { 472 struct service_instance *in; 473 void *c, *i; 474 475 c = blobmsg_open_table(&b, s->name); 476 477 if (!s->autostart) 478 blobmsg_add_u8(&b, "autostart", false); 479 480 if (!avl_is_empty(&s->data_blob.avl)) { 481 struct blobmsg_list_node *var; 482 i = blobmsg_open_table(&b, "data"); 483 blobmsg_list_for_each(&s->data_blob, var) 484 blobmsg_add_blob(&b, var->data); 485 blobmsg_close_table(&b, i); 486 } 487 488 if (!avl_is_empty(&s->instances.avl)) { 489 i = blobmsg_open_table(&b, "instances"); 490 vlist_for_each_element(&s->instances, in, node) 491 instance_dump(&b, in, verbose); 492 blobmsg_close_table(&b, i); 493 } 494 if (verbose && s->trigger) 495 blobmsg_add_blob(&b, s->trigger); 496 if (verbose && !list_empty(&s->validators)) 497 service_validate_dump(&b, s); 498 blobmsg_close_table(&b, c); 499 } 500 501 static int 502 service_handle_list(struct ubus_context *ctx, struct ubus_object *obj, 503 struct ubus_request_data *req, const char *method, 504 struct blob_attr *msg) 505 { 506 struct blob_attr *tb[__SERVICE_LIST_ATTR_MAX]; 507 struct service *s; 508 const char *name = NULL; 509 bool verbose = false; 510 bool container = is_container_obj(obj); 511 const struct avl_tree *tree = container?&containers:&services; 512 513 blobmsg_parse(service_list_attrs, __SERVICE_LIST_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 514 515 if (tb[SERVICE_LIST_ATTR_VERBOSE]) 516 verbose = blobmsg_get_bool(tb[SERVICE_LIST_ATTR_VERBOSE]); 517 if (tb[SERVICE_LIST_ATTR_NAME]) 518 name = blobmsg_get_string(tb[SERVICE_LIST_ATTR_NAME]); 519 520 blob_buf_init(&b, 0); 521 avl_for_each_element(tree, s, avl) { 522 if (name && strcmp(s->name, name) != 0) 523 continue; 524 525 service_dump(s, verbose); 526 } 527 528 ubus_send_reply(ctx, req, b.head); 529 530 return 0; 531 } 532 533 static int 534 service_handle_delete(struct ubus_context *ctx, struct ubus_object *obj, 535 struct ubus_request_data *req, const char *method, 536 struct blob_attr *msg) 537 { 538 struct blob_attr *tb[__SERVICE_DEL_ATTR_MAX], *cur; 539 struct service *s; 540 struct service_instance *in; 541 bool container = is_container_obj(obj); 542 543 blobmsg_parse(service_del_attrs, __SERVICE_DEL_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 544 545 cur = tb[SERVICE_DEL_ATTR_NAME]; 546 if (!cur) 547 return UBUS_STATUS_NOT_FOUND; 548 549 if (container) 550 s = avl_find_element(&containers, blobmsg_data(cur), s, avl); 551 else 552 s = avl_find_element(&services, blobmsg_data(cur), s, avl); 553 554 if (!s) 555 return UBUS_STATUS_NOT_FOUND; 556 557 cur = tb[SERVICE_DEL_ATTR_INSTANCE]; 558 if (!cur) { 559 service_delete(s, container); 560 return 0; 561 } 562 563 in = vlist_find(&s->instances, blobmsg_data(cur), in, node); 564 if (!in) { 565 ERROR("instance %s not found\n", (char *) blobmsg_data(cur)); 566 return UBUS_STATUS_NOT_FOUND; 567 } 568 569 vlist_delete(&s->instances, &in->node); 570 571 return 0; 572 } 573 574 static int 575 service_handle_kill(struct service_instance *in, int sig) 576 { 577 if (kill(in->proc.pid, sig) == 0) 578 return 0; 579 580 switch (errno) { 581 case EINVAL: return UBUS_STATUS_INVALID_ARGUMENT; 582 case EPERM: return UBUS_STATUS_PERMISSION_DENIED; 583 case ESRCH: return UBUS_STATUS_NOT_FOUND; 584 } 585 586 return UBUS_STATUS_UNKNOWN_ERROR; 587 } 588 589 static int 590 service_handle_signal(struct ubus_context *ctx, struct ubus_object *obj, 591 struct ubus_request_data *req, const char *method, 592 struct blob_attr *msg) 593 { 594 struct blob_attr *tb[__SERVICE_SIGNAL_ATTR_MAX], *cur; 595 struct service *s; 596 struct service_instance *in; 597 bool container = is_container_obj(obj); 598 int sig = SIGHUP; 599 int rv = 0; 600 601 blobmsg_parse(service_signal_attrs, __SERVICE_SIGNAL_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 602 603 cur = tb[SERVICE_SIGNAL_ATTR_SIGNAL]; 604 if (cur) 605 sig = blobmsg_get_u32(cur); 606 607 cur = tb[SERVICE_SIGNAL_ATTR_NAME]; 608 if (!cur) 609 return UBUS_STATUS_NOT_FOUND; 610 611 if (container) 612 s = avl_find_element(&containers, blobmsg_data(cur), s, avl); 613 else 614 s = avl_find_element(&services, blobmsg_data(cur), s, avl); 615 616 if (!s) 617 return UBUS_STATUS_NOT_FOUND; 618 619 cur = tb[SERVICE_SIGNAL_ATTR_INSTANCE]; 620 if (!cur) { 621 vlist_for_each_element(&s->instances, in, node) 622 rv = service_handle_kill(in, sig); 623 624 return rv; 625 } 626 627 in = vlist_find(&s->instances, blobmsg_data(cur), in, node); 628 if (!in) { 629 ERROR("instance %s not found\n", blobmsg_get_string(cur)); 630 return UBUS_STATUS_NOT_FOUND; 631 } 632 633 return service_handle_kill(in, sig); 634 } 635 636 static int 637 service_handle_state(struct ubus_context *ctx, struct ubus_object *obj, 638 struct ubus_request_data *req, const char *method, 639 struct blob_attr *msg) 640 { 641 struct blob_attr *tb[__SERVICE_STATE_ATTR_MAX]; 642 struct service *s; 643 struct service_instance *in; 644 bool container = is_container_obj(obj); 645 int spawn; 646 647 blobmsg_parse(service_state_attrs, __SERVICE_STATE_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 648 649 if (!tb[SERVICE_STATE_ATTR_SPAWN]) 650 return UBUS_STATUS_INVALID_ARGUMENT; 651 652 if (!tb[SERVICE_STATE_ATTR_NAME]) 653 return UBUS_STATUS_NOT_FOUND; 654 655 if (container) 656 s = avl_find_element(&containers, blobmsg_data(tb[SERVICE_STATE_ATTR_NAME]), s, avl); 657 else 658 s = avl_find_element(&services, blobmsg_data(tb[SERVICE_STATE_ATTR_NAME]), s, avl); 659 660 if (!s) 661 return UBUS_STATUS_NOT_FOUND; 662 663 spawn = !!blobmsg_get_u8(tb[SERVICE_STATE_ATTR_SPAWN]); 664 vlist_for_each_element(&s->instances, in, node) { 665 if (!!in->proc.pending == !!spawn) 666 continue; 667 else if (!in->proc.pending) 668 instance_start(in); 669 else 670 instance_stop(in, false); 671 } 672 673 return UBUS_STATUS_OK; 674 } 675 676 static void 677 service_avl_stop_all(struct avl_tree *sctree, unsigned int *term_timeout) 678 { 679 struct service *s; 680 681 avl_for_each_element(sctree, s, avl) { 682 struct service_instance *in, *ptr; 683 684 vlist_for_each_element_safe(&s->instances, in, node, ptr) { 685 if (in->term_timeout > *term_timeout) 686 *term_timeout = in->term_timeout; 687 instance_stop(in, true); 688 } 689 } 690 } 691 692 void 693 service_stop_all(void) 694 { 695 unsigned int term_timeout = 0; 696 697 service_avl_stop_all(&containers, &term_timeout); 698 service_avl_stop_all(&services, &term_timeout); 699 procd_inittab_kill(); 700 701 sleep(term_timeout); 702 } 703 704 static int 705 service_handle_update(struct ubus_context *ctx, struct ubus_object *obj, 706 struct ubus_request_data *req, const char *method, 707 struct blob_attr *msg) 708 { 709 struct blob_attr *tb[__SERVICE_ATTR_MAX], *cur; 710 struct service *s; 711 bool container = is_container_obj(obj); 712 713 blobmsg_parse(service_attrs, __SERVICE_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 714 715 cur = tb[SERVICE_SET_NAME]; 716 if (!cur) 717 return UBUS_STATUS_INVALID_ARGUMENT; 718 719 if (container) 720 s = avl_find_element(&containers, blobmsg_data(cur), s, avl); 721 else 722 s = avl_find_element(&services, blobmsg_data(cur), s, avl); 723 724 if (!s) 725 return UBUS_STATUS_NOT_FOUND; 726 727 if (!strcmp(method, "update_start")) 728 vlist_update(&s->instances); 729 else 730 vlist_flush(&s->instances); 731 732 return 0; 733 } 734 735 static void ubus_event_bcast(const char *type, const char *param1, const char *val1, 736 const char *param2, const char *val2) 737 { 738 if (!ctx) 739 return; 740 741 blob_buf_init(&b, 0); 742 if (param1 && val1) 743 blobmsg_add_string(&b, param1, val1); 744 if (param2 && val2) 745 blobmsg_add_string(&b, param2, val2); 746 ubus_notify(ctx, &main_object, type, b.head, -1); 747 } 748 749 static int 750 service_handle_event(struct ubus_context *ctx, struct ubus_object *obj, 751 struct ubus_request_data *req, const char *method, 752 struct blob_attr *msg) 753 { 754 struct blob_attr *tb[__EVENT_MAX]; 755 const char *event; 756 757 if (!msg) 758 return UBUS_STATUS_INVALID_ARGUMENT; 759 760 blobmsg_parse(event_policy, __EVENT_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 761 if (!tb[EVENT_TYPE] || !tb[EVENT_DATA]) 762 return UBUS_STATUS_INVALID_ARGUMENT; 763 764 event = blobmsg_get_string(tb[EVENT_TYPE]); 765 trigger_event(event, tb[EVENT_DATA]); 766 767 if (!strcmp(event, "config.change")) { 768 struct blob_attr *tb2[__VALIDATE_MAX]; 769 770 blobmsg_parse(validate_policy, __VALIDATE_MAX, tb2, 771 blobmsg_data(tb[EVENT_DATA]), blobmsg_data_len(tb[EVENT_DATA])); 772 if (tb2[VALIDATE_PACKAGE]) 773 ubus_event_bcast("config.change", "config", 774 blobmsg_get_string(tb2[VALIDATE_PACKAGE]), NULL, NULL); 775 } 776 return 0; 777 } 778 779 static int 780 service_handle_validate(struct ubus_context *ctx, struct ubus_object *obj, 781 struct ubus_request_data *req, const char *method, 782 struct blob_attr *msg) 783 { 784 struct blob_attr *tb[__VALIDATE_MAX]; 785 char *p = NULL, *t = NULL; 786 787 if (!msg) 788 return UBUS_STATUS_INVALID_ARGUMENT; 789 790 blobmsg_parse(validate_policy, __VALIDATE_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 791 if (tb[VALIDATE_SERVICE]) { 792 return 0; 793 } 794 if (tb[VALIDATE_PACKAGE]) 795 p = blobmsg_get_string(tb[VALIDATE_PACKAGE]); 796 797 if (tb[VALIDATE_TYPE]) 798 t = blobmsg_get_string(tb[VALIDATE_TYPE]); 799 800 blob_buf_init(&b, 0); 801 service_validate_dump_all(&b, p, t); 802 ubus_send_reply(ctx, req, b.head); 803 804 return 0; 805 } 806 807 static int 808 service_get_data(struct ubus_context *ctx, struct ubus_object *obj, 809 struct ubus_request_data *req, const char *method, 810 struct blob_attr *msg) 811 { 812 struct service_instance *in; 813 struct service *s; 814 struct blob_attr *tb[__DATA_MAX]; 815 const char *name = NULL; 816 const char *instance = NULL; 817 const char *type = NULL; 818 819 blobmsg_parse(get_data_policy, __DATA_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 820 if (tb[DATA_NAME]) 821 name = blobmsg_data(tb[DATA_NAME]); 822 if (tb[DATA_INSTANCE]) 823 instance = blobmsg_data(tb[DATA_INSTANCE]); 824 if (tb[DATA_TYPE]) 825 type = blobmsg_data(tb[DATA_TYPE]); 826 827 blob_buf_init(&b, 0); 828 avl_for_each_element(&services, s, avl) { 829 void *cs = NULL; 830 void *ci = NULL; 831 struct blobmsg_list_node *var; 832 833 if (name && strcmp(name, s->name)) 834 continue; 835 836 blobmsg_list_for_each(&s->data_blob, var) { 837 if (type && strcmp(blobmsg_name(var->data), type)) 838 continue; 839 840 if (!cs) 841 cs = blobmsg_open_table(&b, s->name); 842 if (!ci) 843 ci = blobmsg_open_table(&b, "*"); 844 845 blobmsg_add_blob(&b, var->data); 846 } 847 848 if (ci) 849 blobmsg_close_table(&b, ci); 850 851 vlist_for_each_element(&s->instances, in, node) { 852 ci = NULL; 853 854 if (instance && strcmp(instance, in->name)) 855 continue; 856 857 blobmsg_list_for_each(&in->data, var) { 858 if (type && 859 strcmp(blobmsg_name(var->data), type)) 860 continue; 861 862 if (!cs) 863 cs = blobmsg_open_table(&b, s->name); 864 if (!ci) 865 ci = blobmsg_open_table(&b, in->name); 866 867 blobmsg_add_blob(&b, var->data); 868 } 869 870 if (ci) 871 blobmsg_close_table(&b, ci); 872 } 873 874 if (cs) 875 blobmsg_close_table(&b, cs); 876 } 877 878 ubus_send_reply(ctx, req, b.head); 879 return 0; 880 } 881 882 static int 883 container_handle_console(struct ubus_context *ctx, struct ubus_object *obj, 884 struct ubus_request_data *req, const char *method, 885 struct blob_attr *msg) 886 { 887 bool attach = !strcmp(method, "console_attach"); 888 struct blob_attr *tb[__CONTAINER_CONSOLE_MAX]; 889 struct service *s; 890 struct service_instance *in; 891 int console_fd = -1; 892 893 console_fd = ubus_request_get_caller_fd(req); 894 if (console_fd < 0) 895 return UBUS_STATUS_INVALID_ARGUMENT; 896 897 if (!msg) 898 goto err_console_fd; 899 900 blobmsg_parse(container_console_policy, __CONTAINER_CONSOLE_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 901 if (!tb[CONTAINER_CONSOLE_NAME]) 902 goto err_console_fd; 903 904 s = avl_find_element(&containers, blobmsg_data(tb[CONTAINER_CONSOLE_NAME]), s, avl); 905 if (!s) 906 goto err_console_fd; 907 908 if (tb[CONTAINER_CONSOLE_INSTANCE]) { 909 in = vlist_find(&s->instances, blobmsg_data(tb[CONTAINER_CONSOLE_INSTANCE]), in, node); 910 } else { 911 /* use first element in instances list */ 912 vlist_for_each_element(&s->instances, in, node) 913 break; 914 } 915 if (!in) 916 goto err_console_fd; 917 918 if (attach) { 919 if (in->console.fd.fd < 0) { 920 close(console_fd); 921 return UBUS_STATUS_NOT_SUPPORTED; 922 } 923 924 /* close and replace existing attached console */ 925 if (in->console_client.fd.fd > -1) 926 close(in->console_client.fd.fd); 927 928 ustream_fd_init(&in->console_client, console_fd); 929 } else { 930 ustream_fd_init(&in->console, console_fd); 931 } 932 933 return UBUS_STATUS_OK; 934 err_console_fd: 935 close(console_fd); 936 return UBUS_STATUS_INVALID_ARGUMENT; 937 } 938 939 enum { 940 SERVICE_WATCHDOG_MODE, 941 SERVICE_WATCHDOG_TIMEOUT, 942 SERVICE_WATCHDOG_NAME, 943 SERVICE_WATCHDOG_INSTANCE, 944 __SERVICE_WATCHDOG_MAX, 945 }; 946 947 static const struct blobmsg_policy service_watchdog_policy[__SERVICE_WATCHDOG_MAX] = { 948 [SERVICE_WATCHDOG_MODE] = { "mode", BLOBMSG_TYPE_INT32 }, 949 [SERVICE_WATCHDOG_NAME] = { "name", BLOBMSG_TYPE_STRING }, 950 [SERVICE_WATCHDOG_TIMEOUT] = { "timeout", BLOBMSG_TYPE_INT32 }, 951 [SERVICE_WATCHDOG_INSTANCE] = { "instance", BLOBMSG_TYPE_STRING }, 952 }; 953 954 static int 955 service_handle_watchdog(struct ubus_context *ctx, struct ubus_object *obj, 956 struct ubus_request_data *req, const char *method, 957 struct blob_attr *msg) 958 { 959 struct blob_attr *tb[__SERVICE_WATCHDOG_MAX] = {0}; 960 struct service *s; 961 struct blob_attr *cur; 962 struct service_instance *in; 963 964 blobmsg_parse(service_watchdog_policy, __SERVICE_WATCHDOG_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); 965 cur = tb[SERVICE_WATCHDOG_NAME]; 966 if (!cur) 967 return UBUS_STATUS_NOT_FOUND; 968 969 s = avl_find_element(&services, blobmsg_data(cur), s, avl); 970 if (!s) 971 return UBUS_STATUS_NOT_FOUND; 972 973 cur = tb[SERVICE_WATCHDOG_INSTANCE]; 974 if (!cur) 975 return UBUS_STATUS_NOT_FOUND; 976 977 in = vlist_find(&s->instances, blobmsg_data(cur), in, node); 978 if (!in) { 979 ERROR("instance %s not found\n", blobmsg_get_string(cur)); 980 return UBUS_STATUS_NOT_FOUND; 981 } 982 983 if (tb[SERVICE_WATCHDOG_MODE]) 984 in->watchdog.mode = blobmsg_get_u32(tb[SERVICE_WATCHDOG_MODE]); 985 986 if (tb[SERVICE_WATCHDOG_TIMEOUT]) 987 in->watchdog.freq = blobmsg_get_u32(tb[SERVICE_WATCHDOG_TIMEOUT]); 988 989 if (in->watchdog.mode == INSTANCE_WATCHDOG_MODE_DISABLED) 990 uloop_timeout_cancel(&in->watchdog.timeout); 991 else 992 uloop_timeout_set(&in->watchdog.timeout, in->watchdog.freq * 1000); 993 994 blob_buf_init(&b, 0); 995 blobmsg_add_string(&b, "name", blobmsg_get_string(tb[SERVICE_WATCHDOG_NAME])); 996 blobmsg_add_string(&b, "instance", blobmsg_get_string(tb[SERVICE_WATCHDOG_INSTANCE])); 997 blobmsg_add_u32(&b, "mode", in->watchdog.mode); 998 blobmsg_add_u32(&b, "timeout", in->watchdog.freq); 999 1000 ubus_send_reply(ctx, req, b.head); 1001 1002 return UBUS_STATUS_OK; 1003 } 1004 1005 static struct ubus_method main_object_methods[] = { 1006 UBUS_METHOD("set", service_handle_set, service_set_attrs), 1007 UBUS_METHOD("add", service_handle_set, service_set_attrs), 1008 UBUS_METHOD("list", service_handle_list, service_list_attrs), 1009 UBUS_METHOD("delete", service_handle_delete, service_del_attrs), 1010 UBUS_METHOD("signal", service_handle_signal, service_signal_attrs), 1011 UBUS_METHOD("update_start", service_handle_update, service_attrs), 1012 UBUS_METHOD("update_complete", service_handle_update, service_attrs), 1013 UBUS_METHOD("event", service_handle_event, event_policy), 1014 UBUS_METHOD("validate", service_handle_validate, validate_policy), 1015 UBUS_METHOD("get_data", service_get_data, get_data_policy), 1016 UBUS_METHOD("state", service_handle_state, service_state_attrs), 1017 UBUS_METHOD("watchdog", service_handle_watchdog, service_watchdog_policy), 1018 }; 1019 1020 static struct ubus_object_type main_object_type = 1021 UBUS_OBJECT_TYPE("service", main_object_methods); 1022 1023 static struct ubus_object main_object = { 1024 .name = "service", 1025 .type = &main_object_type, 1026 .methods = main_object_methods, 1027 .n_methods = ARRAY_SIZE(main_object_methods), 1028 }; 1029 1030 int 1031 service_start_early(char *name, char *cmdline, char *user, char *group) 1032 { 1033 void *instances, *instance, *command, *respawn; 1034 char *t; 1035 1036 blob_buf_init(&b, 0); 1037 blobmsg_add_string(&b, "name", name); 1038 instances = blobmsg_open_table(&b, "instances"); 1039 instance = blobmsg_open_table(&b, "instance1"); 1040 command = blobmsg_open_array(&b, "command"); 1041 t = strtok(cmdline, " "); 1042 while (t) { 1043 blobmsg_add_string(&b, NULL, t); 1044 t = strtok(NULL, " "); 1045 } 1046 blobmsg_close_array(&b, command); 1047 respawn = blobmsg_open_array(&b, "respawn"); 1048 blobmsg_add_string(&b, NULL, "3600"); 1049 blobmsg_add_string(&b, NULL, "1"); 1050 blobmsg_add_string(&b, NULL, ""); 1051 blobmsg_close_array(&b, respawn); 1052 if (user) 1053 blobmsg_add_string(&b, "user", user); 1054 if (group) 1055 blobmsg_add_string(&b, "group", group); 1056 1057 blobmsg_close_table(&b, instance); 1058 blobmsg_close_table(&b, instances); 1059 1060 return service_handle_set(NULL, NULL, NULL, "add", b.head); 1061 } 1062 1063 void service_stopped(struct service *s) 1064 { 1065 if (s->deleted && avl_is_empty(&s->instances.avl)) { 1066 if (s->container) { 1067 service_event("container.stop", s->name, NULL); 1068 avl_delete(&containers, &s->avl); 1069 } else { 1070 service_event("service.stop", s->name, NULL); 1071 avl_delete(&services, &s->avl); 1072 } 1073 trigger_del(s); 1074 service_validate_del(s); 1075 free(s->trigger); 1076 free(s); 1077 } 1078 } 1079 1080 void service_event(const char *type, const char *service, const char *instance) 1081 { 1082 ubus_event_bcast(type, "service", service, "instance", instance); 1083 } 1084 1085 static struct ubus_method container_object_methods[] = { 1086 UBUS_METHOD("set", service_handle_set, service_set_attrs), 1087 UBUS_METHOD("add", service_handle_set, service_set_attrs), 1088 UBUS_METHOD("list", service_handle_list, service_list_attrs), 1089 UBUS_METHOD("delete", service_handle_delete, service_del_attrs), 1090 UBUS_METHOD("state", service_handle_state, service_state_attrs), 1091 UBUS_METHOD_NOARG("get_features", container_handle_features), 1092 UBUS_METHOD("console_set", container_handle_console, container_console_policy), 1093 UBUS_METHOD("console_attach", container_handle_console, container_console_policy), 1094 }; 1095 1096 static struct ubus_object_type container_object_type = 1097 UBUS_OBJECT_TYPE("container", container_object_methods); 1098 1099 static struct ubus_object container_object = { 1100 .name = "container", 1101 .type = &container_object_type, 1102 .methods = container_object_methods, 1103 .n_methods = ARRAY_SIZE(container_object_methods), 1104 }; 1105 1106 void ubus_init_service(struct ubus_context *_ctx) 1107 { 1108 struct stat statbuf; 1109 1110 ctx = _ctx; 1111 ubus_add_object(ctx, &main_object); 1112 1113 if (!stat("/sbin/ujail", &statbuf)) 1114 ubus_add_object(ctx, &container_object); 1115 } 1116
This page was automatically generated by LXR 0.3.1. • OpenWrt