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");
185 static void _service_stopped(struct service
*s
, bool container
);
188 service_delete(struct service
*s
, bool container
)
190 blobmsg_list_free(&s
->data_blob
);
192 vlist_flush_all(&s
->instances
);
194 _service_stopped(s
, container
);
202 static const struct blobmsg_policy service_attrs
[__SERVICE_ATTR_MAX
] = {
203 [SERVICE_ATTR_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
207 SERVICE_DEL_ATTR_NAME
,
208 SERVICE_DEL_ATTR_INSTANCE
,
209 __SERVICE_DEL_ATTR_MAX
,
212 static const struct blobmsg_policy service_del_attrs
[__SERVICE_DEL_ATTR_MAX
] = {
213 [SERVICE_DEL_ATTR_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
214 [SERVICE_DEL_ATTR_INSTANCE
] = { "instance", BLOBMSG_TYPE_STRING
},
218 SERVICE_LIST_ATTR_NAME
,
219 SERVICE_LIST_ATTR_VERBOSE
,
220 __SERVICE_LIST_ATTR_MAX
,
223 static const struct blobmsg_policy service_list_attrs
[__SERVICE_LIST_ATTR_MAX
] = {
224 [SERVICE_LIST_ATTR_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
225 [SERVICE_LIST_ATTR_VERBOSE
] = { "verbose", BLOBMSG_TYPE_BOOL
},
229 SERVICE_SIGNAL_ATTR_NAME
,
230 SERVICE_SIGNAL_ATTR_INSTANCE
,
231 SERVICE_SIGNAL_ATTR_SIGNAL
,
232 __SERVICE_SIGNAL_ATTR_MAX
,
235 static const struct blobmsg_policy service_signal_attrs
[__SERVICE_SIGNAL_ATTR_MAX
] = {
236 [SERVICE_SIGNAL_ATTR_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
237 [SERVICE_SIGNAL_ATTR_INSTANCE
] = { "instance", BLOBMSG_TYPE_STRING
},
238 [SERVICE_SIGNAL_ATTR_SIGNAL
] = { "signal", BLOBMSG_TYPE_INT32
},
242 SERVICE_STATE_ATTR_SPAWN
,
243 SERVICE_STATE_ATTR_NAME
,
244 __SERVICE_STATE_ATTR_MAX
,
247 static const struct blobmsg_policy service_state_attrs
[__SERVICE_STATE_ATTR_MAX
] = {
248 [SERVICE_STATE_ATTR_SPAWN
] = { "spawn", BLOBMSG_TYPE_BOOL
},
249 [SERVICE_STATE_ATTR_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
258 static const struct blobmsg_policy event_policy
[__EVENT_MAX
] = {
259 [EVENT_TYPE
] = { .name
= "type", .type
= BLOBMSG_TYPE_STRING
},
260 [EVENT_DATA
] = { .name
= "data", .type
= BLOBMSG_TYPE_TABLE
},
270 static const struct blobmsg_policy validate_policy
[__VALIDATE_MAX
] = {
271 [VALIDATE_PACKAGE
] = { .name
= "package", .type
= BLOBMSG_TYPE_STRING
},
272 [VALIDATE_TYPE
] = { .name
= "type", .type
= BLOBMSG_TYPE_STRING
},
273 [VALIDATE_SERVICE
] = { .name
= "service", .type
= BLOBMSG_TYPE_STRING
},
283 static const struct blobmsg_policy get_data_policy
[] = {
284 [DATA_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
285 [DATA_INSTANCE
] = { "instance", BLOBMSG_TYPE_STRING
},
286 [DATA_TYPE
] = { "type", BLOBMSG_TYPE_STRING
},
290 CONTAINER_CONSOLE_NAME
,
291 CONTAINER_CONSOLE_INSTANCE
,
292 __CONTAINER_CONSOLE_MAX
,
295 static const struct blobmsg_policy container_console_policy
[__CONTAINER_CONSOLE_MAX
] = {
296 [CONTAINER_CONSOLE_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
297 [CONTAINER_CONSOLE_INSTANCE
] = { "instance", BLOBMSG_TYPE_STRING
},
300 static inline bool is_container_obj(struct ubus_object
*obj
)
302 return (obj
&& (strcmp(obj
->name
, "container") == 0));
305 static inline void put_namespace(struct blob_buf
*b
, char *name
)
310 snprintf(nsfname
, sizeof(nsfname
), "/proc/self/ns/%s", name
);
312 if (!stat(nsfname
, &statbuf
))
313 blobmsg_add_string(b
, NULL
, name
);
316 static void put_cgroups(struct blob_buf
*b
)
319 static char buf
[512] = "";
322 fd
= open("/sys/fs/cgroup/cgroup.controllers", O_RDONLY
);
326 ret
= read(fd
, &buf
, sizeof(buf
));
335 /* replace space with \0 and direct next entry */
339 } else { /* replace trailing new-line with \0 */
341 if (!t
) /* shouldn't happen, but don't segfault if it does */
347 blobmsg_add_string(b
, NULL
, z
);
352 container_handle_features(struct ubus_context
*ctx
, struct ubus_object
*obj
,
353 struct ubus_request_data
*req
, const char *method
,
354 struct blob_attr
*msg
)
356 struct utsname utsbuf
;
358 void *nsarray
, *cgarray
;
360 if (stat("/sbin/ujail", &statbuf
))
361 return UBUS_STATUS_NOT_SUPPORTED
;
363 if (uname(&utsbuf
) < 0)
364 return UBUS_STATUS_UNKNOWN_ERROR
;
366 blob_buf_init(&b
, 0);
367 blobmsg_add_string(&b
, "machine", utsbuf
.machine
);
369 #ifdef SECCOMP_SUPPORT
370 blobmsg_add_u8(&b
, "seccomp", true);
372 blobmsg_add_u8(&b
, "seccomp", false);
375 cgarray
= blobmsg_open_array(&b
, "cgroup");
377 blobmsg_close_array(&b
, cgarray
);
379 nsarray
= blobmsg_open_array(&b
, "namespaces");
380 put_namespace(&b
, "cgroup");
381 put_namespace(&b
, "ipc");
382 put_namespace(&b
, "mnt");
383 put_namespace(&b
, "net");
384 put_namespace(&b
, "pid");
386 put_namespace(&b
, "time");
388 put_namespace(&b
, "user");
389 put_namespace(&b
, "uts");
390 blobmsg_close_array(&b
, nsarray
);
391 ubus_send_reply(ctx
, req
, b
.head
);
393 return UBUS_STATUS_OK
;
397 service_handle_set(struct ubus_context
*ctx
, struct ubus_object
*obj
,
398 struct ubus_request_data
*req
, const char *method
,
399 struct blob_attr
*msg
)
401 struct blob_attr
*tb
[__SERVICE_SET_MAX
], *cur
;
402 struct service
*s
= NULL
;
404 bool container
= is_container_obj(obj
);
405 bool add
= !strcmp(method
, "add");
408 blobmsg_parse(service_set_attrs
, __SERVICE_SET_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
409 cur
= tb
[SERVICE_SET_NAME
];
411 return UBUS_STATUS_INVALID_ARGUMENT
;
413 name
= blobmsg_data(cur
);
416 s
= avl_find_element(&containers
, name
, s
, avl
);
418 s
= avl_find_element(&services
, name
, s
, avl
);
421 DEBUG(2, "Update service %s\n", name
);
422 return service_update(s
, tb
, add
);
425 DEBUG(2, "Create service %s\n", name
);
426 s
= service_alloc(name
);
428 return UBUS_STATUS_UNKNOWN_ERROR
;
430 ret
= service_update(s
, tb
, add
);
435 avl_insert(&containers
, &s
->avl
);
437 service_event("container.start", s
->name
, NULL
);
439 avl_insert(&services
, &s
->avl
);
441 service_event("service.start", s
->name
, NULL
);
447 service_dump(struct service
*s
, bool verbose
)
449 struct service_instance
*in
;
452 c
= blobmsg_open_table(&b
, s
->name
);
455 blobmsg_add_u8(&b
, "autostart", false);
457 if (!avl_is_empty(&s
->data_blob
.avl
)) {
458 struct blobmsg_list_node
*var
;
459 i
= blobmsg_open_table(&b
, "data");
460 blobmsg_list_for_each(&s
->data_blob
, var
)
461 blobmsg_add_blob(&b
, var
->data
);
462 blobmsg_close_table(&b
, i
);
465 if (!avl_is_empty(&s
->instances
.avl
)) {
466 i
= blobmsg_open_table(&b
, "instances");
467 vlist_for_each_element(&s
->instances
, in
, node
)
468 instance_dump(&b
, in
, verbose
);
469 blobmsg_close_table(&b
, i
);
471 if (verbose
&& s
->trigger
)
472 blobmsg_add_blob(&b
, s
->trigger
);
473 if (verbose
&& !list_empty(&s
->validators
))
474 service_validate_dump(&b
, s
);
475 blobmsg_close_table(&b
, c
);
479 service_handle_list(struct ubus_context
*ctx
, struct ubus_object
*obj
,
480 struct ubus_request_data
*req
, const char *method
,
481 struct blob_attr
*msg
)
483 struct blob_attr
*tb
[__SERVICE_LIST_ATTR_MAX
];
485 const char *name
= NULL
;
486 bool verbose
= false;
487 bool container
= is_container_obj(obj
);
488 const struct avl_tree
*tree
= container
?&containers
:&services
;
490 blobmsg_parse(service_list_attrs
, __SERVICE_LIST_ATTR_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
492 if (tb
[SERVICE_LIST_ATTR_VERBOSE
])
493 verbose
= blobmsg_get_bool(tb
[SERVICE_LIST_ATTR_VERBOSE
]);
494 if (tb
[SERVICE_LIST_ATTR_NAME
])
495 name
= blobmsg_get_string(tb
[SERVICE_LIST_ATTR_NAME
]);
497 blob_buf_init(&b
, 0);
498 avl_for_each_element(tree
, s
, avl
) {
499 if (name
&& strcmp(s
->name
, name
) != 0)
502 service_dump(s
, verbose
);
505 ubus_send_reply(ctx
, req
, b
.head
);
511 service_handle_delete(struct ubus_context
*ctx
, struct ubus_object
*obj
,
512 struct ubus_request_data
*req
, const char *method
,
513 struct blob_attr
*msg
)
515 struct blob_attr
*tb
[__SERVICE_DEL_ATTR_MAX
], *cur
;
517 struct service_instance
*in
;
518 bool container
= is_container_obj(obj
);
520 blobmsg_parse(service_del_attrs
, __SERVICE_DEL_ATTR_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
522 cur
= tb
[SERVICE_DEL_ATTR_NAME
];
524 return UBUS_STATUS_NOT_FOUND
;
527 s
= avl_find_element(&containers
, blobmsg_data(cur
), s
, avl
);
529 s
= avl_find_element(&services
, blobmsg_data(cur
), s
, avl
);
532 return UBUS_STATUS_NOT_FOUND
;
534 cur
= tb
[SERVICE_DEL_ATTR_INSTANCE
];
536 service_delete(s
, container
);
540 in
= vlist_find(&s
->instances
, blobmsg_data(cur
), in
, node
);
542 ERROR("instance %s not found\n", (char *) blobmsg_data(cur
));
543 return UBUS_STATUS_NOT_FOUND
;
546 vlist_delete(&s
->instances
, &in
->node
);
552 service_handle_kill(struct service_instance
*in
, int sig
)
554 if (kill(in
->proc
.pid
, sig
) == 0)
558 case EINVAL
: return UBUS_STATUS_INVALID_ARGUMENT
;
559 case EPERM
: return UBUS_STATUS_PERMISSION_DENIED
;
560 case ESRCH
: return UBUS_STATUS_NOT_FOUND
;
563 return UBUS_STATUS_UNKNOWN_ERROR
;
567 service_handle_signal(struct ubus_context
*ctx
, struct ubus_object
*obj
,
568 struct ubus_request_data
*req
, const char *method
,
569 struct blob_attr
*msg
)
571 struct blob_attr
*tb
[__SERVICE_SIGNAL_ATTR_MAX
], *cur
;
573 struct service_instance
*in
;
574 bool container
= is_container_obj(obj
);
578 blobmsg_parse(service_signal_attrs
, __SERVICE_SIGNAL_ATTR_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
580 cur
= tb
[SERVICE_SIGNAL_ATTR_SIGNAL
];
582 sig
= blobmsg_get_u32(cur
);
584 cur
= tb
[SERVICE_SIGNAL_ATTR_NAME
];
586 return UBUS_STATUS_NOT_FOUND
;
589 s
= avl_find_element(&containers
, blobmsg_data(cur
), s
, avl
);
591 s
= avl_find_element(&services
, blobmsg_data(cur
), s
, avl
);
594 return UBUS_STATUS_NOT_FOUND
;
596 cur
= tb
[SERVICE_SIGNAL_ATTR_INSTANCE
];
598 vlist_for_each_element(&s
->instances
, in
, node
)
599 rv
= service_handle_kill(in
, sig
);
604 in
= vlist_find(&s
->instances
, blobmsg_data(cur
), in
, node
);
606 ERROR("instance %s not found\n", blobmsg_get_string(cur
));
607 return UBUS_STATUS_NOT_FOUND
;
610 return service_handle_kill(in
, sig
);
614 service_handle_state(struct ubus_context
*ctx
, struct ubus_object
*obj
,
615 struct ubus_request_data
*req
, const char *method
,
616 struct blob_attr
*msg
)
618 struct blob_attr
*tb
[__SERVICE_STATE_ATTR_MAX
];
620 struct service_instance
*in
;
621 bool container
= is_container_obj(obj
);
624 blobmsg_parse(service_state_attrs
, __SERVICE_STATE_ATTR_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
626 if (!tb
[SERVICE_STATE_ATTR_SPAWN
])
627 return UBUS_STATUS_INVALID_ARGUMENT
;
629 if (!tb
[SERVICE_STATE_ATTR_NAME
])
630 return UBUS_STATUS_NOT_FOUND
;
633 s
= avl_find_element(&containers
, blobmsg_data(tb
[SERVICE_STATE_ATTR_NAME
]), s
, avl
);
635 s
= avl_find_element(&services
, blobmsg_data(tb
[SERVICE_STATE_ATTR_NAME
]), s
, avl
);
638 return UBUS_STATUS_NOT_FOUND
;
640 spawn
= !!blobmsg_get_u8(tb
[SERVICE_STATE_ATTR_SPAWN
]);
641 vlist_for_each_element(&s
->instances
, in
, node
) {
642 if (!!in
->proc
.pending
== !!spawn
)
644 else if (!in
->proc
.pending
)
647 instance_stop(in
, false);
650 return UBUS_STATUS_OK
;
654 service_handle_update(struct ubus_context
*ctx
, struct ubus_object
*obj
,
655 struct ubus_request_data
*req
, const char *method
,
656 struct blob_attr
*msg
)
658 struct blob_attr
*tb
[__SERVICE_ATTR_MAX
], *cur
;
660 bool container
= is_container_obj(obj
);
662 blobmsg_parse(service_attrs
, __SERVICE_ATTR_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
664 cur
= tb
[SERVICE_SET_NAME
];
666 return UBUS_STATUS_INVALID_ARGUMENT
;
669 s
= avl_find_element(&containers
, blobmsg_data(cur
), s
, avl
);
671 s
= avl_find_element(&services
, blobmsg_data(cur
), s
, avl
);
674 return UBUS_STATUS_NOT_FOUND
;
676 if (!strcmp(method
, "update_start"))
677 vlist_update(&s
->instances
);
679 vlist_flush(&s
->instances
);
684 static void ubus_event_bcast(const char *type
, const char *param1
, const char *val1
,
685 const char *param2
, const char *val2
)
690 blob_buf_init(&b
, 0);
692 blobmsg_add_string(&b
, param1
, val1
);
694 blobmsg_add_string(&b
, param2
, val2
);
695 ubus_notify(ctx
, &main_object
, type
, b
.head
, -1);
699 service_handle_event(struct ubus_context
*ctx
, struct ubus_object
*obj
,
700 struct ubus_request_data
*req
, const char *method
,
701 struct blob_attr
*msg
)
703 struct blob_attr
*tb
[__EVENT_MAX
];
707 return UBUS_STATUS_INVALID_ARGUMENT
;
709 blobmsg_parse(event_policy
, __EVENT_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
710 if (!tb
[EVENT_TYPE
] || !tb
[EVENT_DATA
])
711 return UBUS_STATUS_INVALID_ARGUMENT
;
713 event
= blobmsg_get_string(tb
[EVENT_TYPE
]);
714 trigger_event(event
, tb
[EVENT_DATA
]);
716 if (!strcmp(event
, "config.change")) {
717 struct blob_attr
*tb2
[__VALIDATE_MAX
];
719 blobmsg_parse(validate_policy
, __VALIDATE_MAX
, tb2
,
720 blobmsg_data(tb
[EVENT_DATA
]), blobmsg_data_len(tb
[EVENT_DATA
]));
721 if (tb2
[VALIDATE_PACKAGE
])
722 ubus_event_bcast("config.change", "config",
723 blobmsg_get_string(tb2
[VALIDATE_PACKAGE
]), NULL
, NULL
);
729 service_handle_validate(struct ubus_context
*ctx
, struct ubus_object
*obj
,
730 struct ubus_request_data
*req
, const char *method
,
731 struct blob_attr
*msg
)
733 struct blob_attr
*tb
[__VALIDATE_MAX
];
734 char *p
= NULL
, *t
= NULL
;
737 return UBUS_STATUS_INVALID_ARGUMENT
;
739 blobmsg_parse(validate_policy
, __VALIDATE_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
740 if (tb
[VALIDATE_SERVICE
]) {
743 if (tb
[VALIDATE_PACKAGE
])
744 p
= blobmsg_get_string(tb
[VALIDATE_PACKAGE
]);
746 if (tb
[VALIDATE_TYPE
])
747 t
= blobmsg_get_string(tb
[VALIDATE_TYPE
]);
749 blob_buf_init(&b
, 0);
750 service_validate_dump_all(&b
, p
, t
);
751 ubus_send_reply(ctx
, req
, b
.head
);
757 service_get_data(struct ubus_context
*ctx
, struct ubus_object
*obj
,
758 struct ubus_request_data
*req
, const char *method
,
759 struct blob_attr
*msg
)
761 struct service_instance
*in
;
763 struct blob_attr
*tb
[__DATA_MAX
];
764 const char *name
= NULL
;
765 const char *instance
= NULL
;
766 const char *type
= NULL
;
768 blobmsg_parse(get_data_policy
, __DATA_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
770 name
= blobmsg_data(tb
[DATA_NAME
]);
771 if (tb
[DATA_INSTANCE
])
772 instance
= blobmsg_data(tb
[DATA_INSTANCE
]);
774 type
= blobmsg_data(tb
[DATA_TYPE
]);
776 blob_buf_init(&b
, 0);
777 avl_for_each_element(&services
, s
, avl
) {
780 struct blobmsg_list_node
*var
;
782 if (name
&& strcmp(name
, s
->name
))
785 blobmsg_list_for_each(&s
->data_blob
, var
) {
786 if (type
&& strcmp(blobmsg_name(var
->data
), type
))
790 cs
= blobmsg_open_table(&b
, s
->name
);
792 blobmsg_add_blob(&b
, var
->data
);
795 vlist_for_each_element(&s
->instances
, in
, node
) {
798 if (instance
&& strcmp(instance
, in
->name
))
801 blobmsg_list_for_each(&in
->data
, var
) {
803 strcmp(blobmsg_name(var
->data
), type
))
807 cs
= blobmsg_open_table(&b
, s
->name
);
809 ci
= blobmsg_open_table(&b
, in
->name
);
811 blobmsg_add_blob(&b
, var
->data
);
815 blobmsg_close_table(&b
, ci
);
819 blobmsg_close_table(&b
, cs
);
822 ubus_send_reply(ctx
, req
, b
.head
);
827 container_handle_console(struct ubus_context
*ctx
, struct ubus_object
*obj
,
828 struct ubus_request_data
*req
, const char *method
,
829 struct blob_attr
*msg
)
831 bool attach
= !strcmp(method
, "console_attach");
832 struct blob_attr
*tb
[__CONTAINER_CONSOLE_MAX
];
834 struct service_instance
*in
;
837 console_fd
= ubus_request_get_caller_fd(req
);
839 return UBUS_STATUS_INVALID_ARGUMENT
;
844 blobmsg_parse(container_console_policy
, __CONTAINER_CONSOLE_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
845 if (!tb
[CONTAINER_CONSOLE_NAME
])
848 s
= avl_find_element(&containers
, blobmsg_data(tb
[CONTAINER_CONSOLE_NAME
]), s
, avl
);
852 if (tb
[CONTAINER_CONSOLE_INSTANCE
]) {
853 in
= vlist_find(&s
->instances
, blobmsg_data(tb
[CONTAINER_CONSOLE_INSTANCE
]), in
, node
);
855 /* use first element in instances list */
856 vlist_for_each_element(&s
->instances
, in
, node
)
863 if (in
->console
.fd
.fd
< 0) {
865 return UBUS_STATUS_NOT_SUPPORTED
;
868 /* close and replace existing attached console */
869 if (in
->console_client
.fd
.fd
> -1)
870 close(in
->console_client
.fd
.fd
);
872 ustream_fd_init(&in
->console_client
, console_fd
);
874 ustream_fd_init(&in
->console
, console_fd
);
877 return UBUS_STATUS_OK
;
880 return UBUS_STATUS_INVALID_ARGUMENT
;
884 SERVICE_WATCHDOG_MODE
,
885 SERVICE_WATCHDOG_TIMEOUT
,
886 SERVICE_WATCHDOG_NAME
,
887 SERVICE_WATCHDOG_INSTANCE
,
888 __SERVICE_WATCHDOG_MAX
,
891 static const struct blobmsg_policy service_watchdog_policy
[__SERVICE_WATCHDOG_MAX
] = {
892 [SERVICE_WATCHDOG_MODE
] = { "mode", BLOBMSG_TYPE_INT32
},
893 [SERVICE_WATCHDOG_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
894 [SERVICE_WATCHDOG_TIMEOUT
] = { "timeout", BLOBMSG_TYPE_INT32
},
895 [SERVICE_WATCHDOG_INSTANCE
] = { "instance", BLOBMSG_TYPE_STRING
},
899 service_handle_watchdog(struct ubus_context
*ctx
, struct ubus_object
*obj
,
900 struct ubus_request_data
*req
, const char *method
,
901 struct blob_attr
*msg
)
903 struct blob_attr
*tb
[__SERVICE_WATCHDOG_MAX
] = {0};
905 struct blob_attr
*cur
;
906 struct service_instance
*in
;
908 blobmsg_parse(service_watchdog_policy
, __SERVICE_WATCHDOG_MAX
, tb
, blobmsg_data(msg
), blobmsg_data_len(msg
));
909 cur
= tb
[SERVICE_WATCHDOG_NAME
];
911 return UBUS_STATUS_NOT_FOUND
;
913 s
= avl_find_element(&services
, blobmsg_data(cur
), s
, avl
);
915 return UBUS_STATUS_NOT_FOUND
;
917 cur
= tb
[SERVICE_WATCHDOG_INSTANCE
];
919 return UBUS_STATUS_NOT_FOUND
;
921 in
= vlist_find(&s
->instances
, blobmsg_data(cur
), in
, node
);
923 ERROR("instance %s not found\n", blobmsg_get_string(cur
));
924 return UBUS_STATUS_NOT_FOUND
;
927 if (tb
[SERVICE_WATCHDOG_MODE
])
928 in
->watchdog
.mode
= blobmsg_get_u32(tb
[SERVICE_WATCHDOG_MODE
]);
930 if (tb
[SERVICE_WATCHDOG_TIMEOUT
])
931 in
->watchdog
.freq
= blobmsg_get_u32(tb
[SERVICE_WATCHDOG_TIMEOUT
]);
933 if (in
->watchdog
.mode
== INSTANCE_WATCHDOG_MODE_DISABLED
)
934 uloop_timeout_cancel(&in
->watchdog
.timeout
);
936 uloop_timeout_set(&in
->watchdog
.timeout
, in
->watchdog
.freq
* 1000);
938 blob_buf_init(&b
, 0);
939 blobmsg_add_string(&b
, "name", blobmsg_get_string(tb
[SERVICE_WATCHDOG_NAME
]));
940 blobmsg_add_string(&b
, "instance", blobmsg_get_string(tb
[SERVICE_WATCHDOG_INSTANCE
]));
941 blobmsg_add_u32(&b
, "mode", in
->watchdog
.mode
);
942 blobmsg_add_u32(&b
, "timeout", in
->watchdog
.freq
);
944 ubus_send_reply(ctx
, req
, b
.head
);
946 return UBUS_STATUS_OK
;
949 static struct ubus_method main_object_methods
[] = {
950 UBUS_METHOD("set", service_handle_set
, service_set_attrs
),
951 UBUS_METHOD("add", service_handle_set
, service_set_attrs
),
952 UBUS_METHOD("list", service_handle_list
, service_list_attrs
),
953 UBUS_METHOD("delete", service_handle_delete
, service_del_attrs
),
954 UBUS_METHOD("signal", service_handle_signal
, service_signal_attrs
),
955 UBUS_METHOD("update_start", service_handle_update
, service_attrs
),
956 UBUS_METHOD("update_complete", service_handle_update
, service_attrs
),
957 UBUS_METHOD("event", service_handle_event
, event_policy
),
958 UBUS_METHOD("validate", service_handle_validate
, validate_policy
),
959 UBUS_METHOD("get_data", service_get_data
, get_data_policy
),
960 UBUS_METHOD("state", service_handle_state
, service_state_attrs
),
961 UBUS_METHOD("watchdog", service_handle_watchdog
, service_watchdog_policy
),
964 static struct ubus_object_type main_object_type
=
965 UBUS_OBJECT_TYPE("service", main_object_methods
);
967 static struct ubus_object main_object
= {
969 .type
= &main_object_type
,
970 .methods
= main_object_methods
,
971 .n_methods
= ARRAY_SIZE(main_object_methods
),
975 service_start_early(char *name
, char *cmdline
, char *user
, char *group
)
977 void *instances
, *instance
, *command
, *respawn
;
980 blob_buf_init(&b
, 0);
981 blobmsg_add_string(&b
, "name", name
);
982 instances
= blobmsg_open_table(&b
, "instances");
983 instance
= blobmsg_open_table(&b
, "instance1");
984 command
= blobmsg_open_array(&b
, "command");
985 t
= strtok(cmdline
, " ");
987 blobmsg_add_string(&b
, NULL
, t
);
988 t
= strtok(NULL
, " ");
990 blobmsg_close_array(&b
, command
);
991 respawn
= blobmsg_open_array(&b
, "respawn");
992 blobmsg_add_string(&b
, NULL
, "3600");
993 blobmsg_add_string(&b
, NULL
, "1");
994 blobmsg_add_string(&b
, NULL
, "0");
995 blobmsg_close_array(&b
, respawn
);
997 blobmsg_add_string(&b
, "user", user
);
999 blobmsg_add_string(&b
, "group", group
);
1001 blobmsg_close_table(&b
, instance
);
1002 blobmsg_close_table(&b
, instances
);
1004 return service_handle_set(NULL
, NULL
, NULL
, "add", b
.head
);
1007 void service_stopped(struct service
*s
)
1009 _service_stopped(s
, false);
1012 static void _service_stopped(struct service
*s
, bool container
)
1014 if (s
->deleted
&& avl_is_empty(&s
->instances
.avl
)) {
1016 service_event("container.stop", s
->name
, NULL
);
1017 avl_delete(&containers
, &s
->avl
);
1019 service_event("service.stop", s
->name
, NULL
);
1020 avl_delete(&services
, &s
->avl
);
1023 service_validate_del(s
);
1029 void service_event(const char *type
, const char *service
, const char *instance
)
1031 ubus_event_bcast(type
, "service", service
, "instance", instance
);
1034 static struct ubus_method container_object_methods
[] = {
1035 UBUS_METHOD("set", service_handle_set
, service_set_attrs
),
1036 UBUS_METHOD("add", service_handle_set
, service_set_attrs
),
1037 UBUS_METHOD("list", service_handle_list
, service_list_attrs
),
1038 UBUS_METHOD("delete", service_handle_delete
, service_del_attrs
),
1039 UBUS_METHOD("state", service_handle_state
, service_state_attrs
),
1040 UBUS_METHOD_NOARG("get_features", container_handle_features
),
1041 UBUS_METHOD("console_set", container_handle_console
, container_console_policy
),
1042 UBUS_METHOD("console_attach", container_handle_console
, container_console_policy
),
1045 static struct ubus_object_type container_object_type
=
1046 UBUS_OBJECT_TYPE("container", container_object_methods
);
1048 static struct ubus_object container_object
= {
1049 .name
= "container",
1050 .type
= &container_object_type
,
1051 .methods
= container_object_methods
,
1052 .n_methods
= ARRAY_SIZE(container_object_methods
),
1055 void ubus_init_service(struct ubus_context
*_ctx
)
1057 struct stat statbuf
;
1060 ubus_add_object(ctx
, &main_object
);
1062 if (!stat("/sbin/ujail", &statbuf
))
1063 ubus_add_object(ctx
, &container_object
);