2e610c7268af6cc86acf0c6e020b6847f85a9d17
[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
19 #include "service.h"
20
21 enum {
22 SERVICE_VAL_PACKAGE,
23 SERVICE_VAL_TYPE,
24 SERVICE_VAL_DATA,
25 __SERVICE_VAL_MAX
26 };
27
28 static const struct blobmsg_policy service_validate_attrs[__SERVICE_VAL_MAX] = {
29 [SERVICE_VAL_PACKAGE] = { "package", BLOBMSG_TYPE_STRING },
30 [SERVICE_VAL_TYPE] = { "type", BLOBMSG_TYPE_STRING },
31 [SERVICE_VAL_DATA] = { "data", BLOBMSG_TYPE_TABLE },
32 };
33
34 static struct avl_tree validators;
35
36 void
37 service_validate_dump_all(struct blob_buf *b, char *p, char *s)
38 {
39 struct json_object *r = json_object_new_object();
40 struct validate *v;
41
42 if (!r)
43 return;
44
45 avl_for_each_element(&validators, v, avl) {
46 struct json_object *o, *t;
47 struct vrule *vr;
48
49 if (p && strcmp(p, v->package))
50 continue;
51
52 if (s && strcmp(s, v->type))
53 continue;
54
55 o = json_object_object_get(r, v->package);
56 if (!o) {
57 o = json_object_new_object();
58 json_object_object_add(r, v->package, o);
59 }
60 t = json_object_object_get(o, v->type);
61 if (!t) {
62 t = json_object_new_object();
63 json_object_object_add(o, v->type, t);
64 }
65 avl_for_each_element(&v->rules, vr, avl)
66 json_object_object_add(t, vr->option, json_object_new_string(vr->rule));
67 }
68 blobmsg_add_object(b, r);
69 }
70
71 void
72 service_validate_dump(struct blob_buf *b, struct service *s)
73 {
74 struct validate *v;
75 void *i = blobmsg_open_array(b, "validate");
76
77 list_for_each_entry(v, &s->validators, list) {
78 struct vrule *vr;
79 void *k, *j = blobmsg_open_table(b, "validate");
80
81 blobmsg_add_string(b, "package", v->package);
82 blobmsg_add_string(b, "type", v->type);
83 k = blobmsg_open_table(b, "rules");
84 avl_for_each_element(&v->rules, vr, avl)
85 blobmsg_add_string(b, vr->option, vr->rule);
86 blobmsg_close_table(b, k);
87 blobmsg_close_table(b, j);
88 }
89 blobmsg_close_array(b, i);
90 }
91
92 void
93 service_validate_del(struct service *s)
94 {
95 struct validate *v, *n;
96
97 if (list_empty(&s->validators))
98 return;
99
100 list_for_each_entry_safe(v, n, &s->validators, list) {
101 struct vrule *vr, *a;
102
103 avl_remove_all_elements(&v->rules, vr, avl, a)
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 }