add service_validator support
[project/procd.git] / service_validate.c
1 /*
2  * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License version 2.1
6  * as published by the Free Software Foundation
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <libubox/blobmsg_json.h>
15 #include <libubox/avl-cmp.h>
16
17 #include "procd.h"
18 #include "service.h"
19
20 enum {
21         SERVICE_VAL_PACKAGE,
22         SERVICE_VAL_TYPE,
23         SERVICE_VAL_DATA,
24         __SERVICE_VAL_MAX
25 };
26
27 static const struct blobmsg_policy service_validate_attrs[__SERVICE_VAL_MAX] = {
28         [SERVICE_VAL_PACKAGE] = { "package", BLOBMSG_TYPE_STRING },
29         [SERVICE_VAL_TYPE] = { "type", BLOBMSG_TYPE_STRING },
30         [SERVICE_VAL_DATA] = { "data", BLOBMSG_TYPE_TABLE },
31 };
32
33 static struct avl_tree validators;
34
35 void
36 service_validate_dump_all(struct blob_buf *b, char *p, char *s)
37 {
38         struct json_object *r = json_object_new_object();
39         struct validate *v;
40
41         if (!r)
42                 return;
43
44         avl_for_each_element(&validators, v, avl) {
45                 struct json_object *o, *t;
46                 struct vrule *vr;
47
48                 if (p && strcmp(p, v->package))
49                         continue;
50
51                 if (s && strcmp(s, v->type))
52                         continue;
53
54                 o = json_object_object_get(r, v->package);
55                 if (!o) {
56                         o = json_object_new_object();
57                         json_object_object_add(r, v->package, o);
58                 }
59                 t = json_object_object_get(o, v->type);
60                 if (!t) {
61                         t = json_object_new_object();
62                         json_object_object_add(o, v->type, t);
63                 }
64                 avl_for_each_element(&v->rules, vr, avl)
65                         json_object_object_add(t, vr->option, json_object_new_string(vr->rule));
66         }
67         blobmsg_add_object(b, r);
68 }
69
70 void
71 service_validate_dump(struct blob_buf *b, struct service *s)
72 {
73         struct validate *v;
74         void *i = blobmsg_open_array(b, "validate");
75
76         list_for_each_entry(v, &s->validators, list) {
77                 struct vrule *vr;
78                 void *k, *j = blobmsg_open_table(b, "validate");
79
80                 blobmsg_add_string(b, "package", v->package);
81                 blobmsg_add_string(b, "type", v->type);
82                 k = blobmsg_open_table(b, "rules");
83                 avl_for_each_element(&v->rules, vr, avl)
84                         blobmsg_add_string(b, vr->option, vr->rule);
85                 blobmsg_close_table(b, k);
86                 blobmsg_close_table(b, j);
87         }
88         blobmsg_close_array(b, i);
89 }
90
91 void
92 service_validate_del(struct service *s)
93 {
94         struct validate *v, *n;
95
96         if (list_empty(&s->validators))
97                 return;
98
99         list_for_each_entry_safe(v, n, &s->validators, list) {
100                 struct vrule *vr, *a;
101
102                 avl_for_each_element_safe(&v->rules, vr, avl, a) {
103                         avl_delete(&v->rules, &vr->avl);
104                         free(vr);
105                 }
106                 avl_delete(&validators, &v->avl);
107                 list_del(&v->list);
108                 free(v);
109         }
110 }
111
112 void
113 service_validate_add(struct service *s, struct blob_attr *msg)
114 {
115         struct blob_attr *tb[__SERVICE_VAL_MAX];
116         struct validate *v;
117         char *type, *package;
118         struct blob_attr *cur;
119         int rem;
120
121         blobmsg_parse(service_validate_attrs, __SERVICE_VAL_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
122         if (!tb[SERVICE_VAL_PACKAGE] || !tb[SERVICE_VAL_TYPE] || !tb[SERVICE_VAL_DATA])
123                 return;
124
125         v = calloc_a(sizeof(*v), &package, blobmsg_data_len(tb[SERVICE_VAL_PACKAGE]) + 1,
126                          &type, blobmsg_data_len(tb[SERVICE_VAL_TYPE]) + 1);
127         if (!v)
128                 return;
129
130         v->type = type;
131         v->avl.key = v->package = package;
132         strcpy(v->package, blobmsg_get_string(tb[SERVICE_VAL_PACKAGE]));
133         strcpy(v->type, blobmsg_get_string(tb[SERVICE_VAL_TYPE]));
134
135         list_add(&v->list, &s->validators);
136         if (avl_insert(&validators, &v->avl)) {
137                 free(v);
138                 return;
139         }
140         avl_init(&v->rules, avl_strcmp, false, NULL);
141
142         blobmsg_for_each_attr(cur, tb[SERVICE_VAL_DATA], rem) {
143                 char *option;
144                 char *rule;
145                 struct vrule *vr = calloc_a(sizeof(*vr), &option, strlen(blobmsg_name(cur)) + 1,
146                         &rule, strlen(blobmsg_get_string(cur)) + 1);
147
148                 vr->avl.key = vr->option = option;
149                 vr->rule = rule;
150                 strcpy(vr->option, blobmsg_name(cur));
151                 strcpy(vr->rule, blobmsg_get_string(cur));
152                 if (avl_insert(&v->rules, &vr->avl))
153                         free(vr);
154         }
155 }
156
157 void
158 service_validate_init(void)
159 {
160         avl_init(&validators, avl_strcmp, true, NULL);
161 }