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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt