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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt