2 * Copyright (C) 2015 John Cripin <blogic@openwrt.org>
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
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.
16 #include <libubox/blob.h>
17 #include <libubox/blobmsg.h>
20 #include <libubox/avl-cmp.h>
22 static struct ubus_event_handler acl_event
;
23 static struct ubus_request acl_req
;
24 static struct blob_attr
*acl_blob
;
26 static int acl_cmp(const void *k1
, const void *k2
, void *ptr
)
28 const struct ubus_acl_key
*key1
= k1
;
29 const struct ubus_acl_key
*key2
= k2
;
32 if (key1
->user
&& key2
->user
)
33 ret
= strcmp(key1
->user
, key2
->user
);
37 if (key1
->group
&& key2
->group
)
38 ret
= strcmp(key1
->group
, key2
->group
);
42 return strcmp(key1
->object
, key2
->object
);
45 AVL_TREE(acl_objects
, acl_cmp
, true, NULL
);
55 static const struct blobmsg_policy acl_obj_policy
[__ACL_OBJ_MAX
] = {
56 [ACL_OBJ_OBJECT
] = { .name
= "obj", .type
= BLOBMSG_TYPE_STRING
},
57 [ACL_OBJ_USER
] = { .name
= "user", .type
= BLOBMSG_TYPE_STRING
},
58 [ACL_OBJ_GROUP
] = { .name
= "group", .type
= BLOBMSG_TYPE_STRING
},
59 [ACL_OBJ_ACL
] = { .name
= "acl", .type
= BLOBMSG_TYPE_TABLE
},
63 acl_add(struct blob_attr
*obj
)
65 struct blob_attr
*tb
[__ACL_OBJ_MAX
];
66 struct acl_object
*acl
;
68 blobmsg_parse(acl_obj_policy
, __ACL_OBJ_MAX
, tb
, blobmsg_data(obj
),
69 blobmsg_data_len(obj
));
71 if (!tb
[ACL_OBJ_OBJECT
] || !tb
[ACL_OBJ_ACL
])
74 if (!tb
[ACL_OBJ_USER
] && !tb
[ACL_OBJ_GROUP
])
77 acl
= calloc(1, sizeof(*acl
));
81 acl
->avl
.key
= &acl
->key
;
82 acl
->key
.object
= blobmsg_get_string(tb
[ACL_OBJ_OBJECT
]);
83 acl
->key
.user
= blobmsg_get_string(tb
[ACL_OBJ_USER
]);
84 acl
->key
.group
= blobmsg_get_string(tb
[ACL_OBJ_GROUP
]);
85 acl
->acl
= tb
[ACL_OBJ_ACL
];
86 avl_insert(&acl_objects
, &acl
->avl
);
95 static const struct blobmsg_policy acl_policy
[__ACL_POLICY_MAX
] = {
96 [ACL_POLICY_SEQ
] = { .name
= "seq", .type
= BLOBMSG_TYPE_INT32
},
97 [ACL_POLICY_ACL
] = { .name
= "acl", .type
= BLOBMSG_TYPE_ARRAY
},
100 static void acl_recv_cb(struct ubus_request
*req
,
101 int type
, struct blob_attr
*msg
)
103 struct blob_attr
*tb
[__ACL_POLICY_MAX
];
104 struct blob_attr
*cur
;
108 struct acl_object
*p
, *q
;
110 avl_for_each_element_safe(&acl_objects
, p
, avl
, q
) {
111 avl_delete(&acl_objects
, &p
->avl
);
116 acl_blob
= blob_memdup(msg
);
117 blobmsg_parse(acl_policy
, __ACL_POLICY_MAX
, tb
, blobmsg_data(msg
),
118 blobmsg_data_len(msg
));
120 if (!tb
[ACL_POLICY_SEQ
] && !tb
[ACL_POLICY_ACL
])
123 blobmsg_for_each_attr(cur
, tb
[ACL_POLICY_ACL
], rem
)
127 static void acl_query(struct ubus_context
*ctx
)
129 ubus_invoke_async(ctx
, UBUS_SYSTEM_OBJECT_ACL
, "query", NULL
, &acl_req
);
130 acl_req
.data_cb
= acl_recv_cb
;
131 ubus_complete_request_async(ctx
, &acl_req
);
134 static void acl_subscribe_cb(struct ubus_context
*ctx
, struct ubus_event_handler
*ev
,
135 const char *type
, struct blob_attr
*msg
)
137 if (strcmp(type
, "ubus.acl.sequence"))
142 int ubus_register_acl(struct ubus_context
*ctx
)
146 acl_event
.cb
= acl_subscribe_cb
;
148 ret
= ubus_register_event_handler(ctx
, &acl_event
, "ubus.acl.sequence");