2 * rpcd - UBUS RPC server
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 static struct blob_buf buf
;
30 static const struct blobmsg_policy rpc_file_policy
[__RPC_F_MAX
] = {
31 [RPC_F_PATH
] = { .name
= "path", .type
= BLOBMSG_TYPE_STRING
},
32 [RPC_F_DATA
] = { .name
= "data", .type
= BLOBMSG_TYPE_STRING
},
42 static const struct blobmsg_policy rpc_exec_policy
[__RPC_E_MAX
] = {
43 [RPC_E_CMD
] = { .name
= "command", .type
= BLOBMSG_TYPE_STRING
},
44 [RPC_E_PARM
] = { .name
= "params", .type
= BLOBMSG_TYPE_ARRAY
},
45 [RPC_E_ENV
] = { .name
= "env", .type
= BLOBMSG_TYPE_TABLE
},
48 static const char *d_types
[] = {
51 [DT_DIR
] = "directory",
56 [DT_UNKNOWN
] = "unknown",
61 rpc_errno_status(void)
66 return UBUS_STATUS_PERMISSION_DENIED
;
69 return UBUS_STATUS_INVALID_ARGUMENT
;
72 return UBUS_STATUS_NOT_FOUND
;
75 return UBUS_STATUS_INVALID_ARGUMENT
;
78 return UBUS_STATUS_UNKNOWN_ERROR
;
82 static struct blob_attr
**
83 rpc_check_path(struct blob_attr
*msg
, char **path
, struct stat
*s
)
85 static struct blob_attr
*tb
[__RPC_F_MAX
];
87 blobmsg_parse(rpc_file_policy
, __RPC_F_MAX
, tb
, blob_data(msg
), blob_len(msg
));
95 *path
= blobmsg_data(tb
[RPC_F_PATH
]);
104 rpc_file_read(struct ubus_context
*ctx
, struct ubus_object
*obj
,
105 struct ubus_request_data
*req
, const char *method
,
106 struct blob_attr
*msg
)
113 if (!rpc_check_path(msg
, &path
, &s
))
114 return rpc_errno_status();
116 if (s
.st_size
>= RPC_FILE_MAX_SIZE
)
117 return UBUS_STATUS_NOT_SUPPORTED
;
119 if ((fd
= open(path
, O_RDONLY
)) < 0)
120 return rpc_errno_status();
122 /* some sysfs files do not report a length */
124 s
.st_size
= RPC_FILE_MIN_SIZE
;
126 blob_buf_init(&buf
, 0);
128 wbuf
= blobmsg_alloc_string_buffer(&buf
, "data", s
.st_size
+ 1);
132 rv
= UBUS_STATUS_UNKNOWN_ERROR
;
136 if ((len
= read(fd
, wbuf
, s
.st_size
)) <= 0)
138 rv
= UBUS_STATUS_NO_DATA
;
143 blobmsg_add_string_buffer(&buf
);
145 ubus_send_reply(ctx
, req
, buf
.head
);
154 rpc_file_write(struct ubus_context
*ctx
, struct ubus_object
*obj
,
155 struct ubus_request_data
*req
, const char *method
,
156 struct blob_attr
*msg
)
161 struct blob_attr
**tb
;
163 if (!(tb
= rpc_check_path(msg
, &path
, &s
)))
164 return rpc_errno_status();
167 return UBUS_STATUS_INVALID_ARGUMENT
;
169 if ((fd
= open(path
, O_WRONLY
)) < 0)
170 return rpc_errno_status();
172 write(fd
, blobmsg_data(tb
[RPC_F_DATA
]), blobmsg_data_len(tb
[RPC_F_DATA
]));
179 rpc_file_list(struct ubus_context
*ctx
, struct ubus_object
*obj
,
180 struct ubus_request_data
*req
, const char *method
,
181 struct blob_attr
*msg
)
189 if (!rpc_check_path(msg
, &path
, &s
))
190 return rpc_errno_status();
192 if ((fd
= opendir(path
)) == NULL
)
193 return rpc_errno_status();
195 blob_buf_init(&buf
, 0);
196 c
= blobmsg_open_array(&buf
, "entries");
198 while ((e
= readdir(fd
)) != NULL
)
200 if (!strcmp(e
->d_name
, ".") || !strcmp(e
->d_name
, ".."))
203 d
= blobmsg_open_table(&buf
, NULL
);
204 blobmsg_add_string(&buf
, "name", e
->d_name
);
205 blobmsg_add_string(&buf
, "type", d_types
[e
->d_type
]);
206 blobmsg_close_table(&buf
, d
);
209 blobmsg_close_array(&buf
, c
);
210 ubus_send_reply(ctx
, req
, buf
.head
);
216 rpc_file_stat(struct ubus_context
*ctx
, struct ubus_object
*obj
,
217 struct ubus_request_data
*req
, const char *method
,
218 struct blob_attr
*msg
)
224 if (!rpc_check_path(msg
, &path
, &s
))
225 return rpc_errno_status();
227 blob_buf_init(&buf
, 0);
229 type
= S_ISREG(s
.st_mode
) ? DT_REG
:
230 S_ISDIR(s
.st_mode
) ? DT_DIR
:
231 S_ISCHR(s
.st_mode
) ? DT_CHR
:
232 S_ISBLK(s
.st_mode
) ? DT_BLK
:
233 S_ISFIFO(s
.st_mode
) ? DT_FIFO
:
234 S_ISLNK(s
.st_mode
) ? DT_LNK
:
235 S_ISSOCK(s
.st_mode
) ? DT_SOCK
:
238 blobmsg_add_string(&buf
, "path", path
);
239 blobmsg_add_string(&buf
, "type", d_types
[type
]);
240 blobmsg_add_u32(&buf
, "size", s
.st_size
);
241 blobmsg_add_u32(&buf
, "mode", s
.st_mode
);
242 blobmsg_add_u32(&buf
, "atime", s
.st_atime
);
243 blobmsg_add_u32(&buf
, "mtime", s
.st_mtime
);
244 blobmsg_add_u32(&buf
, "ctime", s
.st_ctime
);
245 blobmsg_add_u32(&buf
, "inode", s
.st_ino
);
246 blobmsg_add_u32(&buf
, "uid", s
.st_uid
);
247 blobmsg_add_u32(&buf
, "gid", s
.st_gid
);
249 ubus_send_reply(ctx
, req
, buf
.head
);
255 rpc_file_exec_lookup(const char *cmd
)
258 int plen
= 0, clen
= strlen(cmd
) + 1;
260 static char path
[PATH_MAX
];
262 if (!stat(cmd
, &s
) && S_ISREG(s
.st_mode
))
265 search
= getenv("PATH");
268 search
= "/bin:/usr/bin:/sbin:/usr/sbin";
274 if (*p
!= ':' && *p
!= '\0')
279 if ((plen
+ clen
) >= sizeof(path
))
282 strncpy(path
, search
, plen
);
283 sprintf(path
+ plen
, "/%s", cmd
);
285 if (!stat(path
, &s
) && S_ISREG(s
.st_mode
))
297 rpc_ustream_to_blobmsg(struct ustream
*s
, const char *name
)
302 if ((len
= ustream_pending_data(s
, false)) > 0)
304 wbuf
= blobmsg_alloc_string_buffer(&buf
, name
, len
+ 1);
309 ustream_for_each_read_buffer(s
, rbuf
, len
)
311 memcpy(wbuf
, rbuf
, len
);
316 blobmsg_add_string_buffer(&buf
);
321 rpc_file_exec_reply(struct rpc_file_exec_context
*c
, int rv
)
323 uloop_timeout_cancel(&c
->timeout
);
324 uloop_process_delete(&c
->process
);
326 if (rv
== UBUS_STATUS_OK
)
328 blob_buf_init(&buf
, 0);
330 blobmsg_add_u32(&buf
, "code", WEXITSTATUS(c
->stat
));
332 rpc_ustream_to_blobmsg(&c
->opipe
.stream
, "stdout");
333 rpc_ustream_to_blobmsg(&c
->epipe
.stream
, "stderr");
335 ubus_send_reply(c
->context
, &c
->request
, buf
.head
);
338 ubus_complete_deferred_request(c
->context
, &c
->request
, rv
);
340 ustream_free(&c
->opipe
.stream
);
341 ustream_free(&c
->epipe
.stream
);
343 close(c
->opipe
.fd
.fd
);
344 close(c
->epipe
.fd
.fd
);
350 rpc_file_exec_timeout_cb(struct uloop_timeout
*t
)
352 struct rpc_file_exec_context
*c
=
353 container_of(t
, struct rpc_file_exec_context
, timeout
);
355 kill(c
->process
.pid
, SIGKILL
);
356 rpc_file_exec_reply(c
, UBUS_STATUS_TIMEOUT
);
360 rpc_file_exec_process_cb(struct uloop_process
*p
, int stat
)
362 struct rpc_file_exec_context
*c
=
363 container_of(p
, struct rpc_file_exec_context
, process
);
367 ustream_poll(&c
->opipe
.stream
);
368 ustream_poll(&c
->epipe
.stream
);
372 rpc_file_exec_opipe_read_cb(struct ustream
*s
, int bytes
)
374 struct rpc_file_exec_context
*c
=
375 container_of(s
, struct rpc_file_exec_context
, opipe
.stream
);
377 if (ustream_read_buf_full(s
))
378 rpc_file_exec_reply(c
, UBUS_STATUS_NOT_SUPPORTED
);
382 rpc_file_exec_epipe_read_cb(struct ustream
*s
, int bytes
)
384 struct rpc_file_exec_context
*c
=
385 container_of(s
, struct rpc_file_exec_context
, epipe
.stream
);
387 if (ustream_read_buf_full(s
))
388 rpc_file_exec_reply(c
, UBUS_STATUS_NOT_SUPPORTED
);
392 rpc_file_exec_opipe_state_cb(struct ustream
*s
)
394 struct rpc_file_exec_context
*c
=
395 container_of(s
, struct rpc_file_exec_context
, opipe
.stream
);
397 if (c
->opipe
.stream
.eof
&& c
->epipe
.stream
.eof
)
398 rpc_file_exec_reply(c
, UBUS_STATUS_OK
);
402 rpc_file_exec_epipe_state_cb(struct ustream
*s
)
404 struct rpc_file_exec_context
*c
=
405 container_of(s
, struct rpc_file_exec_context
, epipe
.stream
);
407 if (c
->opipe
.stream
.eof
&& c
->epipe
.stream
.eof
)
408 rpc_file_exec_reply(c
, UBUS_STATUS_OK
);
412 rpc_file_exec_run(const char *cmd
,
413 const struct blob_attr
*arg
, const struct blob_attr
*env
,
414 struct ubus_context
*ctx
, struct ubus_request_data
*req
)
422 struct blob_attr
*cur
;
427 struct rpc_file_exec_context
*c
;
429 cmd
= rpc_file_exec_lookup(cmd
);
432 return UBUS_STATUS_NOT_FOUND
;
434 c
= malloc(sizeof(*c
));
437 return UBUS_STATUS_UNKNOWN_ERROR
;
439 if (pipe(opipe
) || pipe(epipe
))
440 return rpc_errno_status();
442 switch ((pid
= fork()))
445 return rpc_errno_status();
460 args
= malloc(sizeof(char *) * arglen
);
463 return UBUS_STATUS_UNKNOWN_ERROR
;
465 args
[0] = (char *)cmd
;
470 blobmsg_for_each_attr(cur
, arg
, rem
)
472 if (blobmsg_type(cur
) != BLOBMSG_TYPE_STRING
)
477 if (!(args
= realloc(args
, sizeof(char *) * arglen
)))
478 return UBUS_STATUS_UNKNOWN_ERROR
;
480 args
[arglen
-2] = blobmsg_data(cur
);
481 args
[arglen
-1] = NULL
;
487 blobmsg_for_each_attr(cur
, env
, rem
)
489 if (blobmsg_type(cur
) != BLOBMSG_TYPE_STRING
)
492 setenv(blobmsg_name(cur
), blobmsg_data(cur
), 1);
496 if (execv(cmd
, args
))
497 return rpc_errno_status();
500 memset(c
, 0, sizeof(*c
));
502 ustream_declare(c
->opipe
, opipe
[0], exec_opipe
);
503 ustream_declare(c
->epipe
, epipe
[0], exec_epipe
);
505 c
->process
.pid
= pid
;
506 c
->process
.cb
= rpc_file_exec_process_cb
;
507 uloop_process_add(&c
->process
);
509 c
->timeout
.cb
= rpc_file_exec_timeout_cb
;
510 uloop_timeout_set(&c
->timeout
, RPC_FILE_MAX_RUNTIME
);
516 ubus_defer_request(ctx
, req
, &c
->request
);
519 return UBUS_STATUS_OK
;
523 rpc_file_exec(struct ubus_context
*ctx
, struct ubus_object
*obj
,
524 struct ubus_request_data
*req
, const char *method
,
525 struct blob_attr
*msg
)
527 struct blob_attr
*tb
[__RPC_E_MAX
];
529 blobmsg_parse(rpc_exec_policy
, __RPC_E_MAX
, tb
,
530 blob_data(msg
), blob_len(msg
));
533 return UBUS_STATUS_INVALID_ARGUMENT
;
535 return rpc_file_exec_run(blobmsg_data(tb
[RPC_E_CMD
]),
536 tb
[RPC_E_PARM
], tb
[RPC_E_ENV
], ctx
, req
);
541 rpc_file_api_init(const struct rpc_daemon_ops
*o
, struct ubus_context
*ctx
)
543 static const struct ubus_method file_methods
[] = {
544 UBUS_METHOD("read", rpc_file_read
, rpc_file_policy
),
545 UBUS_METHOD("write", rpc_file_write
, rpc_file_policy
),
546 UBUS_METHOD("list", rpc_file_list
, rpc_file_policy
),
547 UBUS_METHOD("stat", rpc_file_stat
, rpc_file_policy
),
548 UBUS_METHOD("exec", rpc_file_exec
, rpc_exec_policy
),
551 static struct ubus_object_type file_type
=
552 UBUS_OBJECT_TYPE("luci-rpc-file", file_methods
);
554 static struct ubus_object obj
= {
557 .methods
= file_methods
,
558 .n_methods
= ARRAY_SIZE(file_methods
),
561 return ubus_add_object(ctx
, &obj
);
564 const struct rpc_plugin rpc_plugin
= {
565 .init
= rpc_file_api_init