5 static struct ubus_msg_buf
*retmsg
;
6 static int *retmsg_data
;
7 static struct avl_tree clients
;
9 static struct blob_attr
*attrbuf
[UBUS_ATTR_MAX
];
11 typedef int (*ubus_cmd_cb
)(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
);
13 static const struct blob_attr_info ubus_policy
[UBUS_ATTR_MAX
] = {
14 [UBUS_ATTR_SIGNATURE
] = { .type
= BLOB_ATTR_NESTED
},
15 [UBUS_ATTR_OBJTYPE
] = { .type
= BLOB_ATTR_INT32
},
16 [UBUS_ATTR_OBJPATH
] = { .type
= BLOB_ATTR_STRING
},
17 [UBUS_ATTR_OBJID
] = { .type
= BLOB_ATTR_INT32
},
18 [UBUS_ATTR_STATUS
] = { .type
= BLOB_ATTR_INT32
},
21 static struct blob_attr
**ubus_parse_msg(struct blob_attr
*msg
)
23 blob_parse(msg
, attrbuf
, ubus_policy
, UBUS_ATTR_MAX
);
27 static void ubus_msg_init(struct ubus_msg_buf
*ub
, uint8_t type
, uint16_t seq
, uint32_t peer
)
35 static struct ubus_msg_buf
*ubus_msg_from_blob(bool shared
)
37 return ubus_msg_new(b
.head
, blob_raw_len(b
.head
), shared
);
40 static struct ubus_msg_buf
*ubus_reply_from_blob(struct ubus_msg_buf
*ub
, bool shared
)
42 struct ubus_msg_buf
*new;
44 new = ubus_msg_from_blob(shared
);
48 ubus_msg_init(new, UBUS_MSG_DATA
, ub
->hdr
.seq
, ub
->hdr
.peer
);
52 static bool ubusd_send_hello(struct ubus_client
*cl
)
54 struct ubus_msg_buf
*ub
;
57 ub
= ubus_msg_from_blob(true);
61 ubus_msg_init(ub
, UBUS_MSG_HELLO
, 0, cl
->id
.id
);
62 ubus_msg_send(cl
, ub
, true);
66 static int ubusd_send_pong(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
68 ub
->hdr
.type
= UBUS_MSG_DATA
;
69 ubus_msg_send(cl
, ub
, false);
73 static int ubusd_handle_remove_object(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
75 struct ubus_object
*obj
;
77 if (!attr
[UBUS_ATTR_OBJID
])
78 return UBUS_STATUS_INVALID_ARGUMENT
;
80 obj
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
82 return UBUS_STATUS_NOT_FOUND
;
84 if (obj
->client
!= cl
)
85 return UBUS_STATUS_PERMISSION_DENIED
;
88 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
90 /* check if we're removing the object type as well */
91 if (obj
->type
&& obj
->type
->refcount
== 1)
92 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
.id
);
94 ubusd_free_object(obj
);
96 ub
= ubus_reply_from_blob(ub
, true);
98 return UBUS_STATUS_NO_DATA
;
100 ubus_msg_send(cl
, ub
, true);
104 static int ubusd_handle_add_object(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
106 struct ubus_object
*obj
;
108 obj
= ubusd_create_object(cl
, attr
);
110 return UBUS_STATUS_INVALID_ARGUMENT
;
112 blob_buf_init(&b
, 0);
113 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
114 if (attr
[UBUS_ATTR_SIGNATURE
])
115 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
.id
);
117 ub
= ubus_reply_from_blob(ub
, true);
119 return UBUS_STATUS_NO_DATA
;
121 ubus_msg_send(cl
, ub
, true);
125 static void ubusd_send_obj(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct ubus_object
*obj
)
127 struct ubus_method
*m
;
130 blob_buf_init(&b
, 0);
133 blob_put_string(&b
, UBUS_ATTR_OBJPATH
, obj
->path
.key
);
134 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
135 blob_put_int32(&b
, UBUS_ATTR_OBJTYPE
, obj
->type
->id
.id
);
137 s
= blob_nest_start(&b
, UBUS_ATTR_SIGNATURE
);
138 list_for_each_entry(m
, &obj
->type
->methods
, list
)
139 blob_put(&b
, blob_id(m
->data
), blob_data(m
->data
), blob_len(m
->data
));
140 blob_nest_end(&b
, s
);
142 ub
= ubus_reply_from_blob(ub
, true);
146 ubus_msg_send(cl
, ub
, true);
149 static int ubusd_handle_lookup(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
151 struct ubus_object
*obj
;
153 bool wildcard
= false;
157 if (!attr
[UBUS_ATTR_OBJPATH
]) {
158 avl_for_each_element(&path
, obj
, path
)
159 ubusd_send_obj(cl
, ub
, obj
);
163 objpath
= blob_data(attr
[UBUS_ATTR_OBJPATH
]);
164 len
= strlen(objpath
);
165 if (objpath
[len
- 1] != '*') {
166 obj
= avl_find_element(&path
, objpath
, obj
, path
);
168 return UBUS_STATUS_NOT_FOUND
;
170 ubusd_send_obj(cl
, ub
, obj
);
177 obj
= avl_find_ge_element(&path
, objpath
, obj
, path
);
179 return UBUS_STATUS_NOT_FOUND
;
181 while (!strncmp(objpath
, obj
->path
.key
, len
)) {
183 ubusd_send_obj(cl
, ub
, obj
);
184 if (obj
== avl_last_element(&path
, obj
, path
))
186 obj
= avl_next_element(obj
, path
);
190 return UBUS_STATUS_NOT_FOUND
;
195 static int ubusd_handle_invoke(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
197 struct ubus_object
*obj
= NULL
;
201 if (!attr
[UBUS_ATTR_METHOD
] || !attr
[UBUS_ATTR_OBJID
])
202 return UBUS_STATUS_INVALID_ARGUMENT
;
204 id
= ubus_find_id(&objects
, blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
206 return UBUS_STATUS_NOT_FOUND
;
208 obj
= container_of(id
, struct ubus_object
, id
);
210 method
= blob_data(attr
[UBUS_ATTR_METHOD
]);
213 return obj
->recv_msg(cl
, method
, attr
[UBUS_ATTR_DATA
]);
215 blob_buf_init(&b
, 0);
216 blob_put_int32(&b
, UBUS_ATTR_OBJID
, obj
->id
.id
);
217 blob_put_string(&b
, UBUS_ATTR_METHOD
, method
);
218 if (attr
[UBUS_ATTR_DATA
])
219 blob_put(&b
, UBUS_ATTR_DATA
, blob_data(attr
[UBUS_ATTR_DATA
]),
220 blob_len(attr
[UBUS_ATTR_DATA
]));
224 ub
= ubus_reply_from_blob(ub
, true);
226 return UBUS_STATUS_NO_DATA
;
228 ub
->hdr
.type
= UBUS_MSG_INVOKE
;
229 ub
->hdr
.peer
= cl
->id
.id
;
230 ubus_msg_send(obj
->client
, ub
, true);
235 static struct ubus_client
*ubusd_get_client_by_id(uint32_t id
)
237 struct ubus_id
*clid
;
239 clid
= ubus_find_id(&clients
, id
);
243 return container_of(clid
, struct ubus_client
, id
);
246 static int ubusd_handle_response(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
, struct blob_attr
**attr
)
248 struct ubus_object
*obj
;
250 if (!attr
[UBUS_ATTR_OBJID
] ||
251 (ub
->hdr
.type
== UBUS_MSG_STATUS
&& !attr
[UBUS_ATTR_STATUS
]) ||
252 (ub
->hdr
.type
== UBUS_MSG_DATA
&& !attr
[UBUS_ATTR_DATA
]))
255 obj
= ubusd_find_object(blob_get_u32(attr
[UBUS_ATTR_OBJID
]));
259 if (cl
!= obj
->client
)
262 cl
= ubusd_get_client_by_id(ub
->hdr
.peer
);
266 ub
->hdr
.peer
= blob_get_u32(attr
[UBUS_ATTR_OBJID
]);
267 ubus_msg_send(cl
, ub
, true);
275 static const ubus_cmd_cb handlers
[__UBUS_MSG_LAST
] = {
276 [UBUS_MSG_PING
] = ubusd_send_pong
,
277 [UBUS_MSG_ADD_OBJECT
] = ubusd_handle_add_object
,
278 [UBUS_MSG_REMOVE_OBJECT
] = ubusd_handle_remove_object
,
279 [UBUS_MSG_LOOKUP
] = ubusd_handle_lookup
,
280 [UBUS_MSG_INVOKE
] = ubusd_handle_invoke
,
281 [UBUS_MSG_STATUS
] = ubusd_handle_response
,
282 [UBUS_MSG_DATA
] = ubusd_handle_response
,
285 void ubusd_proto_receive_message(struct ubus_client
*cl
, struct ubus_msg_buf
*ub
)
287 ubus_cmd_cb cb
= NULL
;
290 retmsg
->hdr
.seq
= ub
->hdr
.seq
;
291 retmsg
->hdr
.peer
= ub
->hdr
.peer
;
293 if (ub
->hdr
.type
< __UBUS_MSG_LAST
)
294 cb
= handlers
[ub
->hdr
.type
];
297 ret
= cb(cl
, ub
, ubus_parse_msg(ub
->data
));
299 ret
= UBUS_STATUS_INVALID_COMMAND
;
306 *retmsg_data
= htonl(ret
);
307 ubus_msg_send(cl
, retmsg
, false);
310 struct ubus_client
*ubusd_proto_new_client(int fd
, uloop_fd_handler cb
)
312 struct ubus_client
*cl
;
314 cl
= calloc(1, sizeof(*cl
));
318 INIT_LIST_HEAD(&cl
->objects
);
322 if (!ubus_alloc_id(&clients
, &cl
->id
, 0))
325 if (!ubusd_send_hello(cl
))
331 ubus_free_id(&clients
, &cl
->id
);
337 void ubusd_proto_free_client(struct ubus_client
*cl
)
339 struct ubus_object
*obj
;
341 while (!list_empty(&cl
->objects
)) {
342 obj
= list_first_entry(&cl
->objects
, struct ubus_object
, list
);
343 ubusd_free_object(obj
);
346 ubus_free_id(&clients
, &cl
->id
);
349 static void __init
ubusd_proto_init(void)
351 ubus_init_id_tree(&clients
);
353 blob_buf_init(&b
, 0);
354 blob_put_int32(&b
, UBUS_ATTR_STATUS
, 0);
356 retmsg
= ubus_msg_from_blob(false);
360 retmsg
->hdr
.type
= UBUS_MSG_STATUS
;
361 retmsg_data
= blob_data(blob_data(retmsg
->data
));