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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt