• 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         SET_DATA_NAME,
309         SET_DATA_INSTANCE,
310         SET_DATA_DATA,
311         __SET_DATA_MAX
312 };
313 
314 static const struct blobmsg_policy set_data_policy[__SET_DATA_MAX] = {
315         [SET_DATA_NAME] = { "name", BLOBMSG_TYPE_STRING },
316         [SET_DATA_INSTANCE] = { "instance", BLOBMSG_TYPE_STRING },
317         [SET_DATA_DATA] = { "data", BLOBMSG_TYPE_TABLE },
318 };
319 
320 enum {
321         CONTAINER_CONSOLE_NAME,
322         CONTAINER_CONSOLE_INSTANCE,
323         __CONTAINER_CONSOLE_MAX,
324 };
325 
326 static const struct blobmsg_policy container_console_policy[__CONTAINER_CONSOLE_MAX] = {
327         [CONTAINER_CONSOLE_NAME] = { "name", BLOBMSG_TYPE_STRING },
328         [CONTAINER_CONSOLE_INSTANCE] = { "instance", BLOBMSG_TYPE_STRING },
329 };
330 
331 static inline bool is_container_obj(struct ubus_object *obj)
332 {
333         return (obj && (strcmp(obj->name, "container") == 0));
334 }
335 
336 static inline void put_namespace(struct blob_buf *b, char *name)
337 {
338         char nsfname[32];
339         struct stat statbuf;
340 
341         snprintf(nsfname, sizeof(nsfname), "/proc/self/ns/%s", name);
342 
343         if (!stat(nsfname, &statbuf))
344                 blobmsg_add_string(b, NULL, name);
345 }
346 
347 static void put_cgroups(struct blob_buf *b)
348 {
349         int fd, ret;
350         static char buf[512] = "";
351         char *t, *z;
352 
353         fd = open("/sys/fs/cgroup/cgroup.controllers", O_RDONLY);
354         if (fd == -1)
355                 return;
356 
357         ret = read(fd, &buf, sizeof(buf));
358         /* make sure buffer is NULL-terminated */
359         buf[sizeof(buf)-1] = '\0';
360 
361         close(fd);
362 
363         if (ret < 2)
364                 return;
365 
366         t = buf;
367         while(t) {
368                 z = t;
369                 /* replace space with \0 and direct next entry */
370                 t = strchr(z, ' ');
371                 if (t) {
372                         *(t++) = '\0';
373                 } else { /* replace trailing new-line with \0 */
374                         t = strchr(z, '\n');
375                         if (!t) /* shouldn't happen, but don't segfault if it does */
376                                 break;
377 
378                         *t = '\0';
379                         t = NULL;
380                 }
381                 blobmsg_add_string(b, NULL, z);
382         }
383 }
384 
385 static int
386 container_handle_features(struct ubus_context *ctx, struct ubus_object *obj,
387                     struct ubus_request_data *req, const char *method,
388                     struct blob_attr *msg)
389 {
390         struct utsname utsbuf;
391         struct stat statbuf;
392         void *nsarray, *cgarray;
393 
394         if (stat("/sbin/ujail", &statbuf))
395                 return UBUS_STATUS_NOT_SUPPORTED;
396 
397         if (uname(&utsbuf) < 0)
398                 return UBUS_STATUS_UNKNOWN_ERROR;
399 
400         blob_buf_init(&b, 0);
401         blobmsg_add_string(&b, "machine", utsbuf.machine);
402 
403 #ifdef SECCOMP_SUPPORT
404         blobmsg_add_u8(&b, "seccomp", true);
405 #else
406         blobmsg_add_u8(&b, "seccomp", false);
407 #endif
408 
409         cgarray = blobmsg_open_array(&b, "cgroup");
410         put_cgroups(&b);
411         blobmsg_close_array(&b, cgarray);
412 
413         nsarray = blobmsg_open_array(&b, "namespaces");
414         put_namespace(&b, "cgroup");
415         put_namespace(&b, "ipc");
416         put_namespace(&b, "mnt");
417         put_namespace(&b, "net");
418         put_namespace(&b, "pid");
419 #ifdef CLONE_NEWTIME
420         put_namespace(&b, "time");
421 #endif
422         put_namespace(&b, "user");
423         put_namespace(&b, "uts");
424         blobmsg_close_array(&b, nsarray);
425         ubus_send_reply(ctx, req, b.head);
426 
427         return UBUS_STATUS_OK;
428 }
429 
430 static int
431 service_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
432                    struct ubus_request_data *req, const char *method,
433                    struct blob_attr *msg)
434 {
435         struct blob_attr *tb[__SERVICE_SET_MAX], *cur;
436         struct service *s = NULL;
437         const char *name;
438         bool container = is_container_obj(obj);
439         bool add = !strcmp(method, "add");
440         int ret;
441 
442         blobmsg_parse(service_set_attrs, __SERVICE_SET_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
443         cur = tb[SERVICE_SET_NAME];
444         if (!cur)
445                 return UBUS_STATUS_INVALID_ARGUMENT;
446 
447         name = blobmsg_data(cur);
448 
449         if (container)
450                 s = avl_find_element(&containers, name, s, avl);
451         else
452                 s = avl_find_element(&services, name, s, avl);
453 
454         if (s) {
455                 P_DEBUG(2, "Update service %s\n", name);
456                 return service_update(s, tb, add, false);
457         }
458 
459         P_DEBUG(2, "Create service %s\n", name);
460         s = service_alloc(name);
461         if (!s)
462                 return UBUS_STATUS_UNKNOWN_ERROR;
463 
464         s->container = container;
465 
466         ret = service_update(s, tb, add, true);
467         if (ret)
468                 return ret;
469 
470         if (container) {
471                 avl_insert(&containers, &s->avl);
472 
473                 service_event("container.start", s->name, NULL);
474         } else {
475                 avl_insert(&services, &s->avl);
476 
477                 service_event("service.start", s->name, NULL);
478         }
479         return 0;
480 }
481 
482 static void
483 service_dump(struct service *s, bool verbose)
484 {
485         struct service_instance *in;
486         void *c, *i;
487 
488         c = blobmsg_open_table(&b, s->name);
489 
490         if (!s->autostart)
491                 blobmsg_add_u8(&b, "autostart", false);
492 
493         if (!avl_is_empty(&s->data_blob.avl)) {
494                 struct blobmsg_list_node *var;
495                 i = blobmsg_open_table(&b, "data");
496                 blobmsg_list_for_each(&s->data_blob, var)
497                         blobmsg_add_blob(&b, var->data);
498                 blobmsg_close_table(&b, i);
499         }
500 
501         if (!avl_is_empty(&s->instances.avl)) {
502                 i = blobmsg_open_table(&b, "instances");
503                 vlist_for_each_element(&s->instances, in, node)
504                         instance_dump(&b, in, verbose);
505                 blobmsg_close_table(&b, i);
506         }
507         if (verbose && s->trigger)
508                 blobmsg_add_blob(&b, s->trigger);
509         if (verbose && !list_empty(&s->validators))
510                 service_validate_dump(&b, s);
511         blobmsg_close_table(&b, c);
512 }
513 
514 static int
515 service_handle_list(struct ubus_context *ctx, struct ubus_object *obj,
516                     struct ubus_request_data *req, const char *method,
517                     struct blob_attr *msg)
518 {
519         struct blob_attr *tb[__SERVICE_LIST_ATTR_MAX];
520         struct service *s;
521         const char *name = NULL;
522         bool verbose = false;
523         bool container = is_container_obj(obj);
524         const struct avl_tree *tree = container?&containers:&services;
525 
526         blobmsg_parse(service_list_attrs, __SERVICE_LIST_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
527 
528         if (tb[SERVICE_LIST_ATTR_VERBOSE])
529                 verbose = blobmsg_get_bool(tb[SERVICE_LIST_ATTR_VERBOSE]);
530         if (tb[SERVICE_LIST_ATTR_NAME])
531                 name = blobmsg_get_string(tb[SERVICE_LIST_ATTR_NAME]);
532 
533         blob_buf_init(&b, 0);
534         avl_for_each_element(tree, s, avl) {
535                 if (name && strcmp(s->name, name) != 0)
536                         continue;
537 
538                 service_dump(s, verbose);
539         }
540 
541         ubus_send_reply(ctx, req, b.head);
542 
543         return 0;
544 }
545 
546 static int
547 service_handle_delete(struct ubus_context *ctx, struct ubus_object *obj,
548                     struct ubus_request_data *req, const char *method,
549                     struct blob_attr *msg)
550 {
551         struct blob_attr *tb[__SERVICE_DEL_ATTR_MAX], *cur;
552         struct service *s;
553         struct service_instance *in;
554         bool container = is_container_obj(obj);
555 
556         blobmsg_parse(service_del_attrs, __SERVICE_DEL_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
557 
558         cur = tb[SERVICE_DEL_ATTR_NAME];
559         if (!cur)
560                 return UBUS_STATUS_NOT_FOUND;
561 
562         if (container)
563                 s = avl_find_element(&containers, blobmsg_data(cur), s, avl);
564         else
565                 s = avl_find_element(&services, blobmsg_data(cur), s, avl);
566 
567         if (!s)
568                 return UBUS_STATUS_NOT_FOUND;
569 
570         cur = tb[SERVICE_DEL_ATTR_INSTANCE];
571         if (!cur) {
572                 service_delete(s, container);
573                 return 0;
574         }
575 
576         in = vlist_find(&s->instances, blobmsg_data(cur), in, node);
577         if (!in) {
578                 ERROR("instance %s not found\n", (char *) blobmsg_data(cur));
579                 return UBUS_STATUS_NOT_FOUND;
580         }
581 
582         vlist_delete(&s->instances, &in->node);
583 
584         return 0;
585 }
586 
587 static int
588 service_handle_kill(struct service_instance *in, int sig)
589 {
590         if (kill(in->proc.pid, sig) == 0)
591                 return 0;
592 
593         switch (errno) {
594         case EINVAL: return UBUS_STATUS_INVALID_ARGUMENT;
595         case EPERM:  return UBUS_STATUS_PERMISSION_DENIED;
596         case ESRCH:  return UBUS_STATUS_NOT_FOUND;
597         }
598 
599         return UBUS_STATUS_UNKNOWN_ERROR;
600 }
601 
602 static int
603 service_handle_signal(struct ubus_context *ctx, struct ubus_object *obj,
604                     struct ubus_request_data *req, const char *method,
605                     struct blob_attr *msg)
606 {
607         struct blob_attr *tb[__SERVICE_SIGNAL_ATTR_MAX], *cur;
608         struct service *s;
609         struct service_instance *in;
610         bool container = is_container_obj(obj);
611         int sig = SIGHUP;
612         int rv = 0;
613 
614         blobmsg_parse(service_signal_attrs, __SERVICE_SIGNAL_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
615 
616         cur = tb[SERVICE_SIGNAL_ATTR_SIGNAL];
617         if (cur)
618                 sig = blobmsg_get_u32(cur);
619 
620         cur = tb[SERVICE_SIGNAL_ATTR_NAME];
621         if (!cur)
622                 return UBUS_STATUS_NOT_FOUND;
623 
624         if (container)
625                 s = avl_find_element(&containers, blobmsg_data(cur), s, avl);
626         else
627                 s = avl_find_element(&services, blobmsg_data(cur), s, avl);
628 
629         if (!s)
630                 return UBUS_STATUS_NOT_FOUND;
631 
632         cur = tb[SERVICE_SIGNAL_ATTR_INSTANCE];
633         if (!cur) {
634                 vlist_for_each_element(&s->instances, in, node)
635                         rv = service_handle_kill(in, sig);
636 
637                 return rv;
638         }
639 
640         in = vlist_find(&s->instances, blobmsg_data(cur), in, node);
641         if (!in) {
642                 ERROR("instance %s not found\n", blobmsg_get_string(cur));
643                 return UBUS_STATUS_NOT_FOUND;
644         }
645 
646         return service_handle_kill(in, sig);
647 }
648 
649 static int
650 service_handle_state(struct ubus_context *ctx, struct ubus_object *obj,
651                      struct ubus_request_data *req, const char *method,
652                      struct blob_attr *msg)
653 {
654         struct blob_attr *tb[__SERVICE_STATE_ATTR_MAX];
655         struct service *s;
656         struct service_instance *in;
657         bool container = is_container_obj(obj);
658         int spawn;
659 
660         blobmsg_parse(service_state_attrs, __SERVICE_STATE_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
661 
662         if (!tb[SERVICE_STATE_ATTR_SPAWN])
663                 return UBUS_STATUS_INVALID_ARGUMENT;
664 
665         if (!tb[SERVICE_STATE_ATTR_NAME])
666                 return UBUS_STATUS_NOT_FOUND;
667 
668         if (container)
669                 s = avl_find_element(&containers, blobmsg_data(tb[SERVICE_STATE_ATTR_NAME]), s, avl);
670         else
671                 s = avl_find_element(&services, blobmsg_data(tb[SERVICE_STATE_ATTR_NAME]), s, avl);
672 
673         if (!s)
674                 return UBUS_STATUS_NOT_FOUND;
675 
676         spawn = !!blobmsg_get_u8(tb[SERVICE_STATE_ATTR_SPAWN]);
677         vlist_for_each_element(&s->instances, in, node) {
678                 if (!!in->proc.pending == !!spawn)
679                         continue;
680                 else if (!in->proc.pending)
681                         instance_start(in);
682                 else
683                         instance_stop(in, false);
684         }
685 
686         return UBUS_STATUS_OK;
687 }
688 
689 static void
690 service_avl_stop_all(struct avl_tree *sctree, unsigned int *term_timeout)
691 {
692         struct service *s;
693 
694         avl_for_each_element(sctree, s, avl) {
695                 struct service_instance *in, *ptr;
696 
697                 vlist_for_each_element_safe(&s->instances, in, node, ptr) {
698                         if (in->term_timeout > *term_timeout)
699                                 *term_timeout = in->term_timeout;
700                         instance_stop(in, true);
701                 }
702         }
703 }
704 
705 void
706 service_stop_all(void)
707 {
708         unsigned int term_timeout = 0;
709 
710         service_avl_stop_all(&containers, &term_timeout);
711         service_avl_stop_all(&services, &term_timeout);
712         procd_inittab_kill();
713 
714         sleep(term_timeout);
715 }
716 
717 static int
718 service_handle_update(struct ubus_context *ctx, struct ubus_object *obj,
719                       struct ubus_request_data *req, const char *method,
720                       struct blob_attr *msg)
721 {
722         struct blob_attr *tb[__SERVICE_ATTR_MAX], *cur;
723         struct service *s;
724         bool container = is_container_obj(obj);
725 
726         blobmsg_parse(service_attrs, __SERVICE_ATTR_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
727 
728         cur = tb[SERVICE_SET_NAME];
729         if (!cur)
730                 return UBUS_STATUS_INVALID_ARGUMENT;
731 
732         if (container)
733                 s = avl_find_element(&containers, blobmsg_data(cur), s, avl);
734         else
735                 s = avl_find_element(&services, blobmsg_data(cur), s, avl);
736 
737         if (!s)
738                 return UBUS_STATUS_NOT_FOUND;
739 
740         if (!strcmp(method, "update_start"))
741                 vlist_update(&s->instances);
742         else
743                 vlist_flush(&s->instances);
744 
745         return 0;
746 }
747 
748 static void ubus_event_bcast(const char *type, const char *param1, const char *val1,
749                              const char *param2, const char *val2)
750 {
751         if (!ctx)
752                 return;
753 
754         blob_buf_init(&b, 0);
755         if (param1 && val1)
756                 blobmsg_add_string(&b, param1, val1);
757         if (param2 && val2)
758                 blobmsg_add_string(&b, param2, val2);
759         ubus_notify(ctx, &main_object, type, b.head, -1);
760 }
761 
762 static int
763 service_handle_event(struct ubus_context *ctx, struct ubus_object *obj,
764                         struct ubus_request_data *req, const char *method,
765                         struct blob_attr *msg)
766 {
767         struct blob_attr *tb[__EVENT_MAX];
768         const char *event;
769 
770         if (!msg)
771                 return UBUS_STATUS_INVALID_ARGUMENT;
772 
773         blobmsg_parse(event_policy, __EVENT_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
774         if (!tb[EVENT_TYPE] || !tb[EVENT_DATA])
775                 return UBUS_STATUS_INVALID_ARGUMENT;
776 
777         event = blobmsg_get_string(tb[EVENT_TYPE]);
778         trigger_event(event, tb[EVENT_DATA]);
779 
780         blob_buf_init(&b, 0);
781         blobmsg_add_string(&b, "type", event);
782         blobmsg_add_blob(&b, tb[EVENT_DATA]);
783         ubus_notify(ctx, &main_object, "event.trigger", b.head, -1);
784 
785         if (!strcmp(event, "config.change")) {
786                 struct blob_attr *tb2[__VALIDATE_MAX];
787 
788                 blobmsg_parse(validate_policy, __VALIDATE_MAX, tb2,
789                               blobmsg_data(tb[EVENT_DATA]), blobmsg_data_len(tb[EVENT_DATA]));
790                 if (tb2[VALIDATE_PACKAGE])
791                         ubus_event_bcast("config.change", "config",
792                                          blobmsg_get_string(tb2[VALIDATE_PACKAGE]), NULL, NULL);
793         }
794         return 0;
795 }
796 
797 static int
798 service_handle_validate(struct ubus_context *ctx, struct ubus_object *obj,
799                         struct ubus_request_data *req, const char *method,
800                         struct blob_attr *msg)
801 {
802         struct blob_attr *tb[__VALIDATE_MAX];
803         char *p = NULL, *t = NULL;
804 
805         if (!msg)
806                 return UBUS_STATUS_INVALID_ARGUMENT;
807 
808         blobmsg_parse(validate_policy, __VALIDATE_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
809         if (tb[VALIDATE_SERVICE]) {
810                 return 0;
811         }
812         if (tb[VALIDATE_PACKAGE])
813                 p = blobmsg_get_string(tb[VALIDATE_PACKAGE]);
814 
815         if (tb[VALIDATE_TYPE])
816                 t = blobmsg_get_string(tb[VALIDATE_TYPE]);
817 
818         blob_buf_init(&b, 0);
819         service_validate_dump_all(&b, p, t);
820         ubus_send_reply(ctx, req, b.head);
821 
822         return 0;
823 }
824 
825 static int
826 service_get_data(struct ubus_context *ctx, struct ubus_object *obj,
827                  struct ubus_request_data *req, const char *method,
828                  struct blob_attr *msg)
829 {
830         struct service_instance *in;
831         struct service *s;
832         struct blob_attr *tb[__DATA_MAX];
833         const char *name = NULL;
834         const char *instance = NULL;
835         const char *type = NULL;
836 
837         blobmsg_parse(get_data_policy, __DATA_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
838         if (tb[DATA_NAME])
839                 name = blobmsg_data(tb[DATA_NAME]);
840         if (tb[DATA_INSTANCE])
841                 instance = blobmsg_data(tb[DATA_INSTANCE]);
842         if (tb[DATA_TYPE])
843                 type = blobmsg_data(tb[DATA_TYPE]);
844 
845         blob_buf_init(&b, 0);
846         avl_for_each_element(&services, s, avl) {
847                 void *cs = NULL;
848                 void *ci = NULL;
849                 struct blobmsg_list_node *var;
850 
851                 if (name && strcmp(name, s->name))
852                         continue;
853 
854                 blobmsg_list_for_each(&s->data_blob, var) {
855                         if (type && strcmp(blobmsg_name(var->data), type))
856                                 continue;
857 
858                         if (!cs)
859                                 cs = blobmsg_open_table(&b, s->name);
860                         if (!ci)
861                                 ci = blobmsg_open_table(&b, "*");
862 
863                         blobmsg_add_blob(&b, var->data);
864                 }
865 
866                 if (ci)
867                         blobmsg_close_table(&b, ci);
868 
869                 vlist_for_each_element(&s->instances, in, node) {
870                         ci = NULL;
871 
872                         if (instance && strcmp(instance, in->name))
873                                 continue;
874 
875                         blobmsg_list_for_each(&in->data, var) {
876                                 if (type &&
877                                     strcmp(blobmsg_name(var->data), type))
878                                         continue;
879 
880                                 if (!cs)
881                                         cs = blobmsg_open_table(&b, s->name);
882                                 if (!ci)
883                                         ci = blobmsg_open_table(&b, in->name);
884 
885                                 blobmsg_add_blob(&b, var->data);
886                         }
887 
888                         if (ci)
889                                 blobmsg_close_table(&b, ci);
890                 }
891 
892                 if (cs)
893                         blobmsg_close_table(&b, cs);
894         }
895 
896         ubus_send_reply(ctx, req, b.head);
897         return 0;
898 }
899 
900 static int
901 service_handle_set_data(struct ubus_context *ctx, struct ubus_object *obj,
902                         struct ubus_request_data *req, const char *method,
903                         struct blob_attr *msg)
904 {
905         struct blob_attr *tb[__SET_DATA_MAX];
906         struct service *s;
907         struct service_instance *in;
908         const char *name;
909         const char *instance = NULL;
910 
911         blobmsg_parse(set_data_policy, __SET_DATA_MAX, tb,
912                       blobmsg_data(msg), blobmsg_data_len(msg));
913 
914         if (!tb[SET_DATA_NAME] || !tb[SET_DATA_DATA])
915                 return UBUS_STATUS_INVALID_ARGUMENT;
916 
917         name = blobmsg_get_string(tb[SET_DATA_NAME]);
918 
919         s = avl_find_element(&services, name, s, avl);
920         if (!s)
921                 return UBUS_STATUS_NOT_FOUND;
922 
923         if (tb[SET_DATA_INSTANCE])
924                 instance = blobmsg_get_string(tb[SET_DATA_INSTANCE]);
925 
926         if (instance) {
927                 in = vlist_find(&s->instances, instance, in, node);
928                 if (!in)
929                         return UBUS_STATUS_NOT_FOUND;
930 
931                 blobmsg_list_free(&in->data);
932                 blobmsg_list_fill(&in->data, blobmsg_data(tb[SET_DATA_DATA]),
933                                   blobmsg_data_len(tb[SET_DATA_DATA]), false);
934         } else {
935                 if (service_update_data(s, tb[SET_DATA_DATA]) < 0)
936                         return UBUS_STATUS_UNKNOWN_ERROR;
937         }
938 
939         return UBUS_STATUS_OK;
940 }
941 
942 static int
943 container_handle_console(struct ubus_context *ctx, struct ubus_object *obj,
944                          struct ubus_request_data *req, const char *method,
945                          struct blob_attr *msg)
946 {
947         bool attach = !strcmp(method, "console_attach");
948         struct blob_attr *tb[__CONTAINER_CONSOLE_MAX];
949         struct service *s;
950         struct service_instance *in;
951         int console_fd = -1;
952 
953         console_fd = ubus_request_get_caller_fd(req);
954         if (console_fd < 0)
955                 return UBUS_STATUS_INVALID_ARGUMENT;
956 
957         if (!msg)
958                 goto err_console_fd;
959 
960         blobmsg_parse(container_console_policy, __CONTAINER_CONSOLE_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
961         if (!tb[CONTAINER_CONSOLE_NAME])
962                 goto err_console_fd;
963 
964         s = avl_find_element(&containers, blobmsg_data(tb[CONTAINER_CONSOLE_NAME]), s, avl);
965         if (!s)
966                 goto err_console_fd;
967 
968         if (tb[CONTAINER_CONSOLE_INSTANCE]) {
969                 in = vlist_find(&s->instances, blobmsg_data(tb[CONTAINER_CONSOLE_INSTANCE]), in, node);
970         } else {
971                 /* use first element in instances list */
972                 vlist_for_each_element(&s->instances, in, node)
973                         break;
974         }
975         if (!in)
976                 goto err_console_fd;
977 
978         if (attach) {
979                 if (in->console.fd.fd < 0) {
980                         close(console_fd);
981                         return UBUS_STATUS_NOT_SUPPORTED;
982                 }
983 
984                 /* close and replace existing attached console */
985                 if (in->console_client.fd.fd > -1)
986                         close(in->console_client.fd.fd);
987 
988                 ustream_fd_init(&in->console_client, console_fd);
989         } else {
990                 ustream_fd_init(&in->console, console_fd);
991         }
992 
993         return UBUS_STATUS_OK;
994 err_console_fd:
995         close(console_fd);
996         return UBUS_STATUS_INVALID_ARGUMENT;
997 }
998 
999 enum {
1000         SERVICE_WATCHDOG_MODE,
1001         SERVICE_WATCHDOG_TIMEOUT,
1002         SERVICE_WATCHDOG_NAME,
1003         SERVICE_WATCHDOG_INSTANCE,
1004         __SERVICE_WATCHDOG_MAX,
1005 };
1006 
1007 static const struct blobmsg_policy service_watchdog_policy[__SERVICE_WATCHDOG_MAX] = {
1008         [SERVICE_WATCHDOG_MODE] = { "mode", BLOBMSG_TYPE_INT32 },
1009         [SERVICE_WATCHDOG_NAME] = { "name", BLOBMSG_TYPE_STRING },
1010         [SERVICE_WATCHDOG_TIMEOUT] = { "timeout", BLOBMSG_TYPE_INT32 },
1011         [SERVICE_WATCHDOG_INSTANCE] = { "instance", BLOBMSG_TYPE_STRING },
1012 };
1013 
1014 static int
1015 service_handle_watchdog(struct ubus_context *ctx, struct ubus_object *obj,
1016                     struct ubus_request_data *req, const char *method,
1017                     struct blob_attr *msg)
1018 {
1019         struct blob_attr *tb[__SERVICE_WATCHDOG_MAX] = {0};
1020         struct service *s;
1021         struct blob_attr *cur;
1022         struct service_instance *in;
1023 
1024         blobmsg_parse(service_watchdog_policy, __SERVICE_WATCHDOG_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
1025         cur = tb[SERVICE_WATCHDOG_NAME];
1026         if (!cur)
1027                 return UBUS_STATUS_NOT_FOUND;
1028 
1029         s = avl_find_element(&services, blobmsg_data(cur), s, avl);
1030         if (!s)
1031                 return UBUS_STATUS_NOT_FOUND;
1032 
1033         cur = tb[SERVICE_WATCHDOG_INSTANCE];
1034         if (!cur)
1035                 return UBUS_STATUS_NOT_FOUND;
1036 
1037         in = vlist_find(&s->instances, blobmsg_data(cur), in, node);
1038         if (!in) {
1039                 ERROR("instance %s not found\n", blobmsg_get_string(cur));
1040                 return UBUS_STATUS_NOT_FOUND;
1041         }
1042 
1043         if (tb[SERVICE_WATCHDOG_MODE])
1044                 in->watchdog.mode = blobmsg_get_u32(tb[SERVICE_WATCHDOG_MODE]);
1045 
1046         if (tb[SERVICE_WATCHDOG_TIMEOUT])
1047                 in->watchdog.freq = blobmsg_get_u32(tb[SERVICE_WATCHDOG_TIMEOUT]);
1048 
1049         if (in->watchdog.mode == INSTANCE_WATCHDOG_MODE_DISABLED)
1050                 uloop_timeout_cancel(&in->watchdog.timeout);
1051         else
1052                 uloop_timeout_set(&in->watchdog.timeout, in->watchdog.freq * 1000);
1053 
1054         blob_buf_init(&b, 0);
1055         blobmsg_add_string(&b, "name", blobmsg_get_string(tb[SERVICE_WATCHDOG_NAME]));
1056         blobmsg_add_string(&b, "instance", blobmsg_get_string(tb[SERVICE_WATCHDOG_INSTANCE]));
1057         blobmsg_add_u32(&b, "mode", in->watchdog.mode);
1058         blobmsg_add_u32(&b, "timeout", in->watchdog.freq);
1059 
1060         ubus_send_reply(ctx, req, b.head);
1061 
1062         return UBUS_STATUS_OK;
1063 }
1064 
1065 static struct ubus_method main_object_methods[] = {
1066         UBUS_METHOD("set", service_handle_set, service_set_attrs),
1067         UBUS_METHOD("add", service_handle_set, service_set_attrs),
1068         UBUS_METHOD("list", service_handle_list, service_list_attrs),
1069         UBUS_METHOD("delete", service_handle_delete, service_del_attrs),
1070         UBUS_METHOD("signal", service_handle_signal, service_signal_attrs),
1071         UBUS_METHOD("update_start", service_handle_update, service_attrs),
1072         UBUS_METHOD("update_complete", service_handle_update, service_attrs),
1073         UBUS_METHOD("event", service_handle_event, event_policy),
1074         UBUS_METHOD("validate", service_handle_validate, validate_policy),
1075         UBUS_METHOD("get_data", service_get_data, get_data_policy),
1076         UBUS_METHOD("set_data", service_handle_set_data, set_data_policy),
1077         UBUS_METHOD("state", service_handle_state, service_state_attrs),
1078         UBUS_METHOD("watchdog", service_handle_watchdog, service_watchdog_policy),
1079 };
1080 
1081 static struct ubus_object_type main_object_type =
1082         UBUS_OBJECT_TYPE("service", main_object_methods);
1083 
1084 static struct ubus_object main_object = {
1085         .name = "service",
1086         .type = &main_object_type,
1087         .methods = main_object_methods,
1088         .n_methods = ARRAY_SIZE(main_object_methods),
1089 };
1090 
1091 int
1092 service_start_early(char *name, char *cmdline, char *user, char *group)
1093 {
1094         void *instances, *instance, *command, *respawn;
1095         char *t;
1096 
1097         blob_buf_init(&b, 0);
1098         blobmsg_add_string(&b, "name", name);
1099         instances = blobmsg_open_table(&b, "instances");
1100         instance = blobmsg_open_table(&b, "instance1");
1101         command = blobmsg_open_array(&b, "command");
1102         t = strtok(cmdline, " ");
1103         while (t) {
1104                 blobmsg_add_string(&b, NULL, t);
1105                 t = strtok(NULL, " ");
1106         }
1107         blobmsg_close_array(&b, command);
1108         respawn = blobmsg_open_array(&b, "respawn");
1109         blobmsg_add_string(&b, NULL, "3600");
1110         blobmsg_add_string(&b, NULL, "1");
1111         blobmsg_add_string(&b, NULL, "");
1112         blobmsg_close_array(&b, respawn);
1113         if (user)
1114                 blobmsg_add_string(&b, "user", user);
1115         if (group)
1116                 blobmsg_add_string(&b, "group", group);
1117 
1118         blobmsg_close_table(&b, instance);
1119         blobmsg_close_table(&b, instances);
1120 
1121         return service_handle_set(NULL, NULL, NULL, "add", b.head);
1122 }
1123 
1124 void service_stopped(struct service *s)
1125 {
1126         if (s->deleted && avl_is_empty(&s->instances.avl)) {
1127                 if (s->container) {
1128                         service_event("container.stop", s->name, NULL);
1129                         avl_delete(&containers, &s->avl);
1130                 } else {
1131                         service_event("service.stop", s->name, NULL);
1132                         avl_delete(&services, &s->avl);
1133                 }
1134                 trigger_del(s);
1135                 service_validate_del(s);
1136                 free(s->trigger);
1137                 free(s);
1138         }
1139 }
1140 
1141 void service_event(const char *type, const char *service, const char *instance)
1142 {
1143         ubus_event_bcast(type, "service", service, "instance", instance);
1144 }
1145 
1146 static struct ubus_method container_object_methods[] = {
1147         UBUS_METHOD("set", service_handle_set, service_set_attrs),
1148         UBUS_METHOD("add", service_handle_set, service_set_attrs),
1149         UBUS_METHOD("list", service_handle_list, service_list_attrs),
1150         UBUS_METHOD("delete", service_handle_delete, service_del_attrs),
1151         UBUS_METHOD("state", service_handle_state, service_state_attrs),
1152         UBUS_METHOD_NOARG("get_features", container_handle_features),
1153         UBUS_METHOD("console_set", container_handle_console, container_console_policy),
1154         UBUS_METHOD("console_attach", container_handle_console, container_console_policy),
1155 };
1156 
1157 static struct ubus_object_type container_object_type =
1158         UBUS_OBJECT_TYPE("container", container_object_methods);
1159 
1160 static struct ubus_object container_object = {
1161         .name = "container",
1162         .type = &container_object_type,
1163         .methods = container_object_methods,
1164         .n_methods = ARRAY_SIZE(container_object_methods),
1165 };
1166 
1167 void ubus_init_service(struct ubus_context *_ctx)
1168 {
1169         struct stat statbuf;
1170 
1171         ctx = _ctx;
1172         ubus_add_object(ctx, &main_object);
1173 
1174         if (!stat("/sbin/ujail", &statbuf))
1175                 ubus_add_object(ctx, &container_object);
1176 }
1177 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt