2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
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
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.
15 #include <sys/types.h>
17 #include <sys/utsname.h>
18 #include <sys/types.h>
24 #include <libubox/blobmsg_json.h>
25 #include <libubox/avl-cmp.h>
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
;
41 service_instance_add(struct service
*s
, struct blob_attr
*attr
)
43 struct service_instance
*in
;
45 if (blobmsg_type(attr
) != BLOBMSG_TYPE_TABLE
)
48 in
= calloc(1, sizeof(*in
));
52 instance_init(in
, s
, attr
);
53 vlist_add(&s
->instances
, &in
->node
, (void *) in
->name
);
57 service_instance_update(struct vlist_tree
*tree
, struct vlist_node
*node_new
,
58 struct vlist_node
*node_old
)
60 struct service_instance
*in_o
= NULL
, *in_n
= NULL
;
63 in_o
= container_of(node_old
, struct service_instance
, node
);
66 in_n
= container_of(node_new
, struct service_instance
, node
);
69 DEBUG(2, "Update instance %s::%s\n", in_o
->srv
->name
, in_o
->name
);
70 instance_update(in_o
, in_n
);
73 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 DEBUG(2, "Start instance %s::%s\n", in_n
->srv
->name
, in_n
->name
);
80 trigger_event("instance.update", b
.head
);
83 static struct service
*
84 service_alloc(const char *name
)
89 s
= calloc_a(sizeof(*s
), &new_name
, strlen(name
) + 1);
90 strcpy(new_name
, name
);
92 vlist_init(&s
->instances
, avl_strcmp
, service_instance_update
);
93 s
->instances
.no_delete
= true;
96 INIT_LIST_HEAD(&s
->validators
);
97 blobmsg_list_simple_init(&s
->data_blob
);
105 SERVICE_SET_INSTANCES
,
107 SERVICE_SET_VALIDATE
,
108 SERVICE_SET_AUTOSTART
,
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
},
124 service_update(struct service
*s
, struct blob_attr
**tb
, bool add
)
126 struct blob_attr
*cur
;
136 blobmsg_list_free(&s
->data_blob
);
141 service_validate_del(s
);
143 if (tb
[SERVICE_SET_AUTOSTART
] && !blobmsg_get_bool(tb
[SERVICE_SET_AUTOSTART
]))
144 s
->autostart
= false;
148 if (tb
[SERVICE_SET_TRIGGER
] && blobmsg_data_len(tb
[SERVICE_SET_TRIGGER
])) {
149 s
->trigger
= blob_memdup(tb
[SERVICE_SET_TRIGGER
]);
152 trigger_add(s
->trigger
, s
);
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
);
160 if (tb
[SERVICE_SET_INSTANCES
]) {
162 vlist_update(&s
->instances
);
163 blobmsg_for_each_attr(cur
, tb
[SERVICE_SET_INSTANCES
], rem
) {
164 service_instance_add(s
, cur
);
167 vlist_flush(&s
->instances
);
170 if (tb
[SERVICE_SET_DATA
] && blobmsg_data_len(tb
[SERVICE_SET_DATA
])) {
171 s
->data
= blob_memdup(tb
[SERVICE_SET_DATA
]);
174 blobmsg_list_fill(&s
->data_blob
, blobmsg_data(s
->data
),
175 blobmsg_data_len(s
->data
), false);
180 rc(s
->name
, "running");
186 service_delete(struct service
*s
, bool container
)
188 blobmsg_list_free(&s
->data_blob
);
190 vlist_flush_all(&s
->instances
);
200 static const struct blobmsg_policy service_attrs
[__SERVICE_ATTR_MAX
] = {
201 [SERVICE_ATTR_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
205 SERVICE_DEL_ATTR_NAME
,
206 SERVICE_DEL_ATTR_INSTANCE
,
207 __SERVICE_DEL_ATTR_MAX
,
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
},
216 SERVICE_LIST_ATTR_NAME
,
217 SERVICE_LIST_ATTR_VERBOSE
,
218 __SERVICE_LIST_ATTR_MAX
,
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
},
227 SERVICE_SIGNAL_ATTR_NAME
,
228 SERVICE_SIGNAL_ATTR_INSTANCE
,
229 SERVICE_SIGNAL_ATTR_SIGNAL
,
230 __SERVICE_SIGNAL_ATTR_MAX
,
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
},
240 SERVICE_STATE_ATTR_SPAWN
,
241 SERVICE_STATE_ATTR_NAME
,
242 __SERVICE_STATE_ATTR_MAX
,
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
},
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
},
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
},
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
},
288 CONTAINER_CONSOLE_NAME
,
289 CONTAINER_CONSOLE_INSTANCE
,
290 __CONTAINER_CONSOLE_MAX
,
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
},
298 static inline bool is_container_obj(struct ubus_object
*obj
)
300 return (obj
&& (strcmp(obj
->name
, "container") == 0));
303 static inline void put_namespace(struct blob_buf
*b
, char *name
)
308 snprintf(nsfname
, sizeof(nsfname
), "/proc/self/ns/%s", name
);
310 if (!stat(nsfname
, &statbuf
))
311 blobmsg_add_string(b
, NULL
, name
);
314 static void put_cgroups(struct blob_buf
*b
)
317 static char buf
[512] = "";
320 fd
= open("/sys/fs/cgroup/cgroup.controllers", O_RDONLY
);
324 ret
= read(fd
, &buf
, sizeof(buf
));
325 /* make sure buffer is NULL-terminated */
326 buf
[sizeof(buf
)-1] = '\0';
336 /* replace space with \0 and direct next entry */
340 } else { /* replace trailing new-line with \0 */
342 if (!t
) /* shouldn't happen, but don't segfault if it does */
348 blobmsg_add_string(b
, NULL
, z
);
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
)
357 struct utsname utsbuf
;
359 void *nsarray
, *cgarray
;
361 if (stat("/sbin/ujail", &statbuf
))
362 return UBUS_STATUS_NOT_SUPPORTED
;
364 if (uname(&utsbuf
) < 0)
365 return UBUS_STATUS_UNKNOWN_ERROR
;
367 blob_buf_init(&b
, 0);
368 blobmsg_add_string(&b
, "machine", utsbuf
.machine
);
370 #ifdef SECCOMP_SUPPORT
371 blobmsg_add_u8(&b
, "seccomp", true);
373 blobmsg_add_u8(&b
, "seccomp", false);
376 cgarray
= blobmsg_open_array(&b
, "cgroup");
378 blobmsg_close_array(&b
, cgarray
);
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");
387 put_namespace(&b
, "time");
389 put_namespace(&b
, "user");
390 put_namespace(&b
, "uts");
391 blobmsg_close_array(&b
, nsarray
);
392 ubus_send_reply(ctx
, req
, b
.head
);
394 return UBUS_STATUS_OK
;
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
)
402 struct blob_attr
*tb
[__SERVICE_SET_MAX
], *cur
;
403 struct service
*s
= NULL
;
405 bool container
= is_container_obj(obj
);
406 bool add
= !strcmp(method
, "add");
409 blobmsg_parse(service_set_attrs
, __SERVICE_SET_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
410 cur
= tb
[SERVICE_SET_NAME
];
412 return UBUS_STATUS_INVALID_ARGUMENT
;
414 name
= blobmsg_data(cur
);
417 s
= avl_find_element(&containers
, name
, s
, avl
);
419 s
= avl_find_element(&services
, name
, s
, avl
);
422 DEBUG(2, "Update service %s\n", name
);
423 return service_update(s
, tb
, add
);
426 DEBUG(2, "Create service %s\n", name
);
427 s
= service_alloc(name
);
429 return UBUS_STATUS_UNKNOWN_ERROR
;
431 s
->container
= container
;
433 ret
= service_update(s
, tb
, add
);
438 avl_insert(&containers
, &s
->avl
);
440 service_event("container.start", s
->name
, NULL
);
442 avl_insert(&services
, &s
->avl
);
444 service_event("service.start", s
->name
, NULL
);
450 service_dump(struct service
*s
, bool verbose
)
452 struct service_instance
*in
;
455 c
= blobmsg_open_table(&b
, s
->name
);
458 blobmsg_add_u8(&b
, "autostart", false);
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
);
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
);
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
);
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
)
486 struct blob_attr
*tb
[__SERVICE_LIST_ATTR_MAX
];
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
;
493 blobmsg_parse(service_list_attrs
, __SERVICE_LIST_ATTR_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
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
]);
500 blob_buf_init(&b
, 0);
501 avl_for_each_element(tree
, s
, avl
) {
502 if (name
&& strcmp(s
->name
, name
) != 0)
505 service_dump(s
, verbose
);
508 ubus_send_reply(ctx
, req
, b
.head
);
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
)
518 struct blob_attr
*tb
[__SERVICE_DEL_ATTR_MAX
], *cur
;
520 struct service_instance
*in
;
521 bool container
= is_container_obj(obj
);
523 blobmsg_parse(service_del_attrs
, __SERVICE_DEL_ATTR_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
525 cur
= tb
[SERVICE_DEL_ATTR_NAME
];
527 return UBUS_STATUS_NOT_FOUND
;
530 s
= avl_find_element(&containers
, blobmsg_data(cur
), s
, avl
);
532 s
= avl_find_element(&services
, blobmsg_data(cur
), s
, avl
);
535 return UBUS_STATUS_NOT_FOUND
;
537 cur
= tb
[SERVICE_DEL_ATTR_INSTANCE
];
539 service_delete(s
, container
);
543 in
= vlist_find(&s
->instances
, blobmsg_data(cur
), in
, node
);
545 ERROR("instance %s not found\n", (char *) blobmsg_data(cur
));
546 return UBUS_STATUS_NOT_FOUND
;
549 vlist_delete(&s
->instances
, &in
->node
);
555 service_handle_kill(struct service_instance
*in
, int sig
)
557 if (kill(in
->proc
.pid
, sig
) == 0)
561 case EINVAL
: return UBUS_STATUS_INVALID_ARGUMENT
;
562 case EPERM
: return UBUS_STATUS_PERMISSION_DENIED
;
563 case ESRCH
: return UBUS_STATUS_NOT_FOUND
;
566 return UBUS_STATUS_UNKNOWN_ERROR
;
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
)
574 struct blob_attr
*tb
[__SERVICE_SIGNAL_ATTR_MAX
], *cur
;
576 struct service_instance
*in
;
577 bool container
= is_container_obj(obj
);
581 blobmsg_parse(service_signal_attrs
, __SERVICE_SIGNAL_ATTR_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
583 cur
= tb
[SERVICE_SIGNAL_ATTR_SIGNAL
];
585 sig
= blobmsg_get_u32(cur
);
587 cur
= tb
[SERVICE_SIGNAL_ATTR_NAME
];
589 return UBUS_STATUS_NOT_FOUND
;
592 s
= avl_find_element(&containers
, blobmsg_data(cur
), s
, avl
);
594 s
= avl_find_element(&services
, blobmsg_data(cur
), s
, avl
);
597 return UBUS_STATUS_NOT_FOUND
;
599 cur
= tb
[SERVICE_SIGNAL_ATTR_INSTANCE
];
601 vlist_for_each_element(&s
->instances
, in
, node
)
602 rv
= service_handle_kill(in
, sig
);
607 in
= vlist_find(&s
->instances
, blobmsg_data(cur
), in
, node
);
609 ERROR("instance %s not found\n", blobmsg_get_string(cur
));
610 return UBUS_STATUS_NOT_FOUND
;
613 return service_handle_kill(in
, sig
);
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
)
621 struct blob_attr
*tb
[__SERVICE_STATE_ATTR_MAX
];
623 struct service_instance
*in
;
624 bool container
= is_container_obj(obj
);
627 blobmsg_parse(service_state_attrs
, __SERVICE_STATE_ATTR_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
629 if (!tb
[SERVICE_STATE_ATTR_SPAWN
])
630 return UBUS_STATUS_INVALID_ARGUMENT
;
632 if (!tb
[SERVICE_STATE_ATTR_NAME
])
633 return UBUS_STATUS_NOT_FOUND
;
636 s
= avl_find_element(&containers
, blobmsg_data(tb
[SERVICE_STATE_ATTR_NAME
]), s
, avl
);
638 s
= avl_find_element(&services
, blobmsg_data(tb
[SERVICE_STATE_ATTR_NAME
]), s
, avl
);
641 return UBUS_STATUS_NOT_FOUND
;
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
)
647 else if (!in
->proc
.pending
)
650 instance_stop(in
, false);
653 return UBUS_STATUS_OK
;
657 service_avl_stop_all(struct avl_tree
*sctree
, unsigned int *term_timeout
)
661 avl_for_each_element(sctree
, s
, avl
) {
662 struct service_instance
*in
, *ptr
;
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);
673 service_stop_all(void)
675 unsigned int term_timeout
= 0;
677 service_avl_stop_all(&containers
, &term_timeout
);
678 service_avl_stop_all(&services
, &term_timeout
);
679 procd_inittab_kill();
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
)
689 struct blob_attr
*tb
[__SERVICE_ATTR_MAX
], *cur
;
691 bool container
= is_container_obj(obj
);
693 blobmsg_parse(service_attrs
, __SERVICE_ATTR_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
695 cur
= tb
[SERVICE_SET_NAME
];
697 return UBUS_STATUS_INVALID_ARGUMENT
;
700 s
= avl_find_element(&containers
, blobmsg_data(cur
), s
, avl
);
702 s
= avl_find_element(&services
, blobmsg_data(cur
), s
, avl
);
705 return UBUS_STATUS_NOT_FOUND
;
707 if (!strcmp(method
, "update_start"))
708 vlist_update(&s
->instances
);
710 vlist_flush(&s
->instances
);
715 static void ubus_event_bcast(const char *type
, const char *param1
, const char *val1
,
716 const char *param2
, const char *val2
)
721 blob_buf_init(&b
, 0);
723 blobmsg_add_string(&b
, param1
, val1
);
725 blobmsg_add_string(&b
, param2
, val2
);
726 ubus_notify(ctx
, &main_object
, type
, b
.head
, -1);
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
)
734 struct blob_attr
*tb
[__EVENT_MAX
];
738 return UBUS_STATUS_INVALID_ARGUMENT
;
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
;
744 event
= blobmsg_get_string(tb
[EVENT_TYPE
]);
745 trigger_event(event
, tb
[EVENT_DATA
]);
747 if (!strcmp(event
, "config.change")) {
748 struct blob_attr
*tb2
[__VALIDATE_MAX
];
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
);
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
)
764 struct blob_attr
*tb
[__VALIDATE_MAX
];
765 char *p
= NULL
, *t
= NULL
;
768 return UBUS_STATUS_INVALID_ARGUMENT
;
770 blobmsg_parse(validate_policy
, __VALIDATE_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
771 if (tb
[VALIDATE_SERVICE
]) {
774 if (tb
[VALIDATE_PACKAGE
])
775 p
= blobmsg_get_string(tb
[VALIDATE_PACKAGE
]);
777 if (tb
[VALIDATE_TYPE
])
778 t
= blobmsg_get_string(tb
[VALIDATE_TYPE
]);
780 blob_buf_init(&b
, 0);
781 service_validate_dump_all(&b
, p
, t
);
782 ubus_send_reply(ctx
, req
, b
.head
);
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
)
792 struct service_instance
*in
;
794 struct blob_attr
*tb
[__DATA_MAX
];
795 const char *name
= NULL
;
796 const char *instance
= NULL
;
797 const char *type
= NULL
;
799 blobmsg_parse(get_data_policy
, __DATA_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
801 name
= blobmsg_data(tb
[DATA_NAME
]);
802 if (tb
[DATA_INSTANCE
])
803 instance
= blobmsg_data(tb
[DATA_INSTANCE
]);
805 type
= blobmsg_data(tb
[DATA_TYPE
]);
807 blob_buf_init(&b
, 0);
808 avl_for_each_element(&services
, s
, avl
) {
811 struct blobmsg_list_node
*var
;
813 if (name
&& strcmp(name
, s
->name
))
816 blobmsg_list_for_each(&s
->data_blob
, var
) {
817 if (type
&& strcmp(blobmsg_name(var
->data
), type
))
821 cs
= blobmsg_open_table(&b
, s
->name
);
823 blobmsg_add_blob(&b
, var
->data
);
826 vlist_for_each_element(&s
->instances
, in
, node
) {
829 if (instance
&& strcmp(instance
, in
->name
))
832 blobmsg_list_for_each(&in
->data
, var
) {
834 strcmp(blobmsg_name(var
->data
), type
))
838 cs
= blobmsg_open_table(&b
, s
->name
);
840 ci
= blobmsg_open_table(&b
, in
->name
);
842 blobmsg_add_blob(&b
, var
->data
);
846 blobmsg_close_table(&b
, ci
);
850 blobmsg_close_table(&b
, cs
);
853 ubus_send_reply(ctx
, req
, b
.head
);
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
)
862 bool attach
= !strcmp(method
, "console_attach");
863 struct blob_attr
*tb
[__CONTAINER_CONSOLE_MAX
];
865 struct service_instance
*in
;
868 console_fd
= ubus_request_get_caller_fd(req
);
870 return UBUS_STATUS_INVALID_ARGUMENT
;
875 blobmsg_parse(container_console_policy
, __CONTAINER_CONSOLE_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
876 if (!tb
[CONTAINER_CONSOLE_NAME
])
879 s
= avl_find_element(&containers
, blobmsg_data(tb
[CONTAINER_CONSOLE_NAME
]), s
, avl
);
883 if (tb
[CONTAINER_CONSOLE_INSTANCE
]) {
884 in
= vlist_find(&s
->instances
, blobmsg_data(tb
[CONTAINER_CONSOLE_INSTANCE
]), in
, node
);
886 /* use first element in instances list */
887 vlist_for_each_element(&s
->instances
, in
, node
)
894 if (in
->console
.fd
.fd
< 0) {
896 return UBUS_STATUS_NOT_SUPPORTED
;
899 /* close and replace existing attached console */
900 if (in
->console_client
.fd
.fd
> -1)
901 close(in
->console_client
.fd
.fd
);
903 ustream_fd_init(&in
->console_client
, console_fd
);
905 ustream_fd_init(&in
->console
, console_fd
);
908 return UBUS_STATUS_OK
;
911 return UBUS_STATUS_INVALID_ARGUMENT
;
915 SERVICE_WATCHDOG_MODE
,
916 SERVICE_WATCHDOG_TIMEOUT
,
917 SERVICE_WATCHDOG_NAME
,
918 SERVICE_WATCHDOG_INSTANCE
,
919 __SERVICE_WATCHDOG_MAX
,
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
},
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
)
934 struct blob_attr
*tb
[__SERVICE_WATCHDOG_MAX
] = {0};
936 struct blob_attr
*cur
;
937 struct service_instance
*in
;
939 blobmsg_parse(service_watchdog_policy
, __SERVICE_WATCHDOG_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
940 cur
= tb
[SERVICE_WATCHDOG_NAME
];
942 return UBUS_STATUS_NOT_FOUND
;
944 s
= avl_find_element(&services
, blobmsg_data(cur
), s
, avl
);
946 return UBUS_STATUS_NOT_FOUND
;
948 cur
= tb
[SERVICE_WATCHDOG_INSTANCE
];
950 return UBUS_STATUS_NOT_FOUND
;
952 in
= vlist_find(&s
->instances
, blobmsg_data(cur
), in
, node
);
954 ERROR("instance %s not found\n", blobmsg_get_string(cur
));
955 return UBUS_STATUS_NOT_FOUND
;
958 if (tb
[SERVICE_WATCHDOG_MODE
])
959 in
->watchdog
.mode
= blobmsg_get_u32(tb
[SERVICE_WATCHDOG_MODE
]);
961 if (tb
[SERVICE_WATCHDOG_TIMEOUT
])
962 in
->watchdog
.freq
= blobmsg_get_u32(tb
[SERVICE_WATCHDOG_TIMEOUT
]);
964 if (in
->watchdog
.mode
== INSTANCE_WATCHDOG_MODE_DISABLED
)
965 uloop_timeout_cancel(&in
->watchdog
.timeout
);
967 uloop_timeout_set(&in
->watchdog
.timeout
, in
->watchdog
.freq
* 1000);
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
);
975 ubus_send_reply(ctx
, req
, b
.head
);
977 return UBUS_STATUS_OK
;
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
),
995 static struct ubus_object_type main_object_type
=
996 UBUS_OBJECT_TYPE("service", main_object_methods
);
998 static struct ubus_object main_object
= {
1000 .type
= &main_object_type
,
1001 .methods
= main_object_methods
,
1002 .n_methods
= ARRAY_SIZE(main_object_methods
),
1006 service_start_early(char *name
, char *cmdline
, char *user
, char *group
)
1008 void *instances
, *instance
, *command
, *respawn
;
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
, " ");
1018 blobmsg_add_string(&b
, NULL
, t
);
1019 t
= strtok(NULL
, " ");
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
, "0");
1026 blobmsg_close_array(&b
, respawn
);
1028 blobmsg_add_string(&b
, "user", user
);
1030 blobmsg_add_string(&b
, "group", group
);
1032 blobmsg_close_table(&b
, instance
);
1033 blobmsg_close_table(&b
, instances
);
1035 return service_handle_set(NULL
, NULL
, NULL
, "add", b
.head
);
1038 void service_stopped(struct service
*s
)
1040 if (s
->deleted
&& avl_is_empty(&s
->instances
.avl
)) {
1042 service_event("container.stop", s
->name
, NULL
);
1043 avl_delete(&containers
, &s
->avl
);
1045 service_event("service.stop", s
->name
, NULL
);
1046 avl_delete(&services
, &s
->avl
);
1049 service_validate_del(s
);
1055 void service_event(const char *type
, const char *service
, const char *instance
)
1057 ubus_event_bcast(type
, "service", service
, "instance", instance
);
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
),
1071 static struct ubus_object_type container_object_type
=
1072 UBUS_OBJECT_TYPE("container", container_object_methods
);
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
),
1081 void ubus_init_service(struct ubus_context
*_ctx
)
1083 struct stat statbuf
;
1086 ubus_add_object(ctx
, &main_object
);
1088 if (!stat("/sbin/ujail", &statbuf
))
1089 ubus_add_object(ctx
, &container_object
);