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