• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/procd/service/service.c

  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