Initial import
[project/udebug.git] / ubus.c
1 #include <fnmatch.h>
2 #include <libubus.h>
3 #include "server.h"
4
5 struct ubus_auto_conn conn;
6 struct blob_buf b;
7 static struct ubus_object udebug_object;
8
9 enum {
10 LIST_ATTR_PROCNAME,
11 LIST_ATTR_RINGNAME,
12 LIST_ATTR_PID,
13 LIST_ATTR_UID,
14 __LIST_ATTR_MAX,
15 };
16
17 static const struct blobmsg_policy list_policy[__LIST_ATTR_MAX] = {
18 [LIST_ATTR_PROCNAME] = { "proc_name", BLOBMSG_TYPE_ARRAY },
19 [LIST_ATTR_RINGNAME] = { "ring_name", BLOBMSG_TYPE_ARRAY },
20 [LIST_ATTR_PID] = { "pid", BLOBMSG_TYPE_ARRAY },
21 [LIST_ATTR_UID] = { "uid", BLOBMSG_TYPE_ARRAY },
22 };
23
24 static bool
25 string_array_match(const char *val, struct blob_attr *match)
26 {
27 struct blob_attr *cur;
28 int rem;
29
30 if (!match || !blobmsg_len(match))
31 return true;
32
33 if (blobmsg_check_array(match, BLOBMSG_TYPE_STRING) < 0)
34 return false;
35
36 blobmsg_for_each_attr(cur, match, rem) {
37 if (fnmatch(blobmsg_get_string(cur), val, 0) == 0)
38 return true;
39 }
40
41 return false;
42 }
43
44 static bool
45 int_array_match(unsigned int val, struct blob_attr *match)
46 {
47 struct blob_attr *cur;
48 int rem;
49
50 if (!match || !blobmsg_len(match))
51 return true;
52
53 if (blobmsg_check_array(match, BLOBMSG_TYPE_INT32) < 0)
54 return false;
55
56 blobmsg_for_each_attr(cur, match, rem) {
57 if (val == blobmsg_get_u32(cur))
58 return true;
59 }
60
61 return false;
62 }
63
64 static bool
65 udebug_list_match(struct client_ring *r, struct blob_attr **tb)
66 {
67 return string_array_match(r->cl->proc_name, tb[LIST_ATTR_PROCNAME]) &&
68 string_array_match(r->name, tb[LIST_ATTR_RINGNAME]) &&
69 int_array_match(r->cl->pid, tb[LIST_ATTR_PID]) &&
70 int_array_match(r->cl->uid, tb[LIST_ATTR_UID]);
71 }
72
73 static void
74 udebug_list_add_ring_data(struct client_ring *r)
75 {
76 blobmsg_add_u32(&b, "id", ring_id(r));
77 blobmsg_add_string(&b, "proc_name", r->cl->proc_name);
78 blobmsg_add_string(&b, "ring_name", r->name);
79 blobmsg_add_u32(&b, "pid", r->cl->pid);
80 blobmsg_add_u32(&b, "uid", r->cl->uid);
81 if (r->flags)
82 blobmsg_add_blob(&b, r->flags);
83 }
84
85 void udebug_ubus_ring_notify(struct client_ring *r, bool add)
86 {
87 blob_buf_init(&b, 0);
88 udebug_list_add_ring_data(r);
89 ubus_notify(&conn.ctx, &udebug_object, add ? "add" : "remove", b.head, -1);
90 }
91
92 static void
93 udebug_list_add_ring(struct client_ring *r)
94 {
95 void *c;
96
97 c = blobmsg_open_table(&b, NULL);
98 udebug_list_add_ring_data(r);
99 blobmsg_close_table(&b, c);
100 }
101
102 static int
103 udebug_list(struct ubus_context *ctx, struct ubus_object *obj,
104 struct ubus_request_data *req, const char *method,
105 struct blob_attr *msg)
106 {
107 struct blob_attr *tb[__LIST_ATTR_MAX];
108 struct client_ring *r;
109 void *c;
110
111 blobmsg_parse_attr(list_policy, __LIST_ATTR_MAX, tb, msg);
112
113 blob_buf_init(&b, 0);
114 c = blobmsg_open_array(&b, "results");
115 avl_for_each_element(&rings, r, node)
116 if (udebug_list_match(r, tb))
117 udebug_list_add_ring(r);
118 blobmsg_close_array(&b, c);
119 ubus_send_reply(ctx, req, b.head);
120
121 return 0;
122 }
123
124 static const struct ubus_method udebug_methods[] = {
125 UBUS_METHOD("list", udebug_list, list_policy),
126 };
127
128 static struct ubus_object_type udebug_object_type =
129 UBUS_OBJECT_TYPE("udebug", udebug_methods);
130
131 static struct ubus_object udebug_object = {
132 .name = "udebug",
133 .type = &udebug_object_type,
134 .methods = udebug_methods,
135 .n_methods = ARRAY_SIZE(udebug_methods),
136 };
137
138 static void ubus_connect_cb(struct ubus_context *ctx)
139 {
140 ubus_add_object(ctx, &udebug_object);
141 }
142
143 void udebug_ubus_init(void)
144 {
145 conn.cb = ubus_connect_cb;
146 ubus_auto_connect(&conn);
147 }
148
149 void udebug_ubus_free(void)
150 {
151 ubus_auto_shutdown(&conn);
152 }