1 /* 2 * rpcd - UBUS RPC server 3 * 4 * Copyright (C) 2013-2014 Jo-Philipp Wich <jow@openwrt.org> 5 * 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. 9 * 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. 17 */ 18 19 #include <fcntl.h> 20 #include <errno.h> 21 #include <unistd.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <limits.h> 25 #include <dirent.h> 26 #include <sys/stat.h> 27 #include <sys/wait.h> 28 29 #include <rpcd/exec.h> 30 31 static int 32 rpc_errno_status(void) 33 { 34 switch (errno) 35 { 36 case EACCES: 37 return UBUS_STATUS_PERMISSION_DENIED; 38 39 case ENOTDIR: 40 return UBUS_STATUS_INVALID_ARGUMENT; 41 42 case ENOENT: 43 return UBUS_STATUS_NOT_FOUND; 44 45 case EINVAL: 46 return UBUS_STATUS_INVALID_ARGUMENT; 47 48 default: 49 return UBUS_STATUS_UNKNOWN_ERROR; 50 } 51 } 52 53 const char * 54 rpc_exec_lookup(const char *cmd) 55 { 56 struct stat s; 57 int plen = 0, clen = strlen(cmd) + 1; 58 char *search, *p; 59 static char path[PATH_MAX]; 60 61 if (!stat(cmd, &s) && S_ISREG(s.st_mode)) 62 return cmd; 63 64 search = getenv("PATH"); 65 66 if (!search) 67 search = "/bin:/usr/bin:/sbin:/usr/sbin"; 68 69 p = search; 70 71 do 72 { 73 if (*p != ':' && *p != '\0') 74 continue; 75 76 plen = p - search; 77 78 if ((plen + clen) >= sizeof(path)) 79 continue; 80 81 strncpy(path, search, plen); 82 sprintf(path + plen, "/%s", cmd); 83 84 if (!stat(path, &s) && S_ISREG(s.st_mode)) 85 return path; 86 87 search = p + 1; 88 } 89 while (*p++); 90 91 return NULL; 92 } 93 94 95 static void 96 rpc_ustream_to_blobmsg(struct blob_buf *blob, struct ustream *s, 97 const char *name) 98 { 99 int len; 100 char *rbuf, *wbuf; 101 102 if ((len = ustream_pending_data(s, false)) > 0) 103 { 104 wbuf = blobmsg_alloc_string_buffer(blob, name, len + 1); 105 106 if (!wbuf) 107 return; 108 109 ustream_for_each_read_buffer(s, rbuf, len) 110 { 111 memcpy(wbuf, rbuf, len); 112 wbuf += len; 113 } 114 115 *wbuf = 0; 116 blobmsg_add_string_buffer(blob); 117 } 118 } 119 120 static void 121 rpc_exec_reply(struct rpc_exec_context *c, int rv) 122 { 123 uloop_timeout_cancel(&c->timeout); 124 uloop_process_delete(&c->process); 125 126 if (rv == UBUS_STATUS_OK) 127 { 128 if (!c->stdout_cb && !c->stderr_cb && !c->finish_cb) 129 { 130 blobmsg_add_u32(&c->blob, "code", WEXITSTATUS(c->stat)); 131 rpc_ustream_to_blobmsg(&c->blob, &c->opipe.stream, "stdout"); 132 rpc_ustream_to_blobmsg(&c->blob, &c->epipe.stream, "stderr"); 133 } 134 } 135 136 if (c->finish_cb) 137 rv = c->finish_cb(&c->blob, c->stat, c->priv); 138 139 if (rv == UBUS_STATUS_OK) 140 ubus_send_reply(c->context, &c->request, c->blob.head); 141 142 ubus_complete_deferred_request(c->context, &c->request, rv); 143 144 blob_buf_free(&c->blob); 145 146 ustream_free(&c->opipe.stream); 147 ustream_free(&c->epipe.stream); 148 149 close(c->opipe.fd.fd); 150 close(c->epipe.fd.fd); 151 152 if (c->priv) 153 free(c->priv); 154 155 free(c); 156 } 157 158 static void 159 rpc_exec_reply_cb(struct uloop_timeout *t) 160 { 161 struct rpc_exec_context *c = 162 container_of(t, struct rpc_exec_context, timeout); 163 164 rpc_exec_reply(c, c->deferred_status); 165 } 166 167 static void 168 rpc_exec_schedule_reply(struct rpc_exec_context *c, int rv) 169 { 170 c->deferred_status = rv; 171 c->timeout.cb = rpc_exec_reply_cb; 172 uloop_timeout_set(&c->timeout, 0); 173 } 174 175 static void 176 rpc_exec_timeout_cb(struct uloop_timeout *t) 177 { 178 struct rpc_exec_context *c = 179 container_of(t, struct rpc_exec_context, timeout); 180 181 kill(c->process.pid, SIGKILL); 182 rpc_exec_schedule_reply(c, UBUS_STATUS_TIMEOUT); 183 } 184 185 static void 186 rpc_exec_process_cb(struct uloop_process *p, int stat) 187 { 188 struct rpc_exec_context *c = 189 container_of(p, struct rpc_exec_context, process); 190 191 c->stat = stat; 192 193 ustream_poll(&c->opipe.stream); 194 ustream_poll(&c->epipe.stream); 195 196 close(c->opipe.fd.fd); 197 close(c->epipe.fd.fd); 198 199 ustream_poll(&c->opipe.stream); 200 ustream_poll(&c->epipe.stream); 201 } 202 203 static void 204 rpc_exec_ipipe_write_cb(struct ustream *s, int bytes) 205 { 206 struct rpc_exec_context *c = 207 container_of(s, struct rpc_exec_context, ipipe.stream); 208 209 if (c->stdin_cb(s, c->priv) <= 0) 210 { 211 ustream_free(&c->ipipe.stream); 212 close(c->ipipe.fd.fd); 213 } 214 } 215 216 static void 217 rpc_exec_opipe_read_cb(struct ustream *s, int bytes) 218 { 219 int len, rv; 220 char *buf; 221 struct rpc_exec_context *c = 222 container_of(s, struct rpc_exec_context, opipe.stream); 223 224 if (c->stdout_cb) 225 { 226 do { 227 buf = ustream_get_read_buf(s, &len); 228 229 if (!buf || !len) 230 break; 231 232 rv = c->stdout_cb(&c->blob, buf, len, c->priv); 233 234 if (rv <= 0) 235 break; 236 237 ustream_consume(s, rv); 238 } while(1); 239 } 240 else if (ustream_read_buf_full(s)) 241 { 242 rpc_exec_schedule_reply(c, UBUS_STATUS_NOT_SUPPORTED); 243 } 244 } 245 246 static void 247 rpc_exec_epipe_read_cb(struct ustream *s, int bytes) 248 { 249 int len, rv; 250 char *buf; 251 struct rpc_exec_context *c = 252 container_of(s, struct rpc_exec_context, epipe.stream); 253 254 if (c->stderr_cb) 255 { 256 do { 257 buf = ustream_get_read_buf(s, &len); 258 259 if (!buf || !len) 260 break; 261 262 rv = c->stderr_cb(&c->blob, buf, len, c->priv); 263 264 if (rv <= 0) 265 break; 266 267 ustream_consume(s, rv); 268 } while(1); 269 } 270 else if (ustream_read_buf_full(s)) 271 { 272 rpc_exec_schedule_reply(c, UBUS_STATUS_NOT_SUPPORTED); 273 } 274 } 275 276 static void 277 rpc_exec_opipe_state_cb(struct ustream *s) 278 { 279 struct rpc_exec_context *c = 280 container_of(s, struct rpc_exec_context, opipe.stream); 281 282 if (c->opipe.stream.eof && c->epipe.stream.eof) 283 rpc_exec_schedule_reply(c, UBUS_STATUS_OK); 284 } 285 286 static void 287 rpc_exec_epipe_state_cb(struct ustream *s) 288 { 289 struct rpc_exec_context *c = 290 container_of(s, struct rpc_exec_context, epipe.stream); 291 292 if (c->opipe.stream.eof && c->epipe.stream.eof) 293 rpc_exec_schedule_reply(c, UBUS_STATUS_OK); 294 } 295 296 int 297 rpc_exec(const char **args, rpc_exec_write_cb_t in, 298 rpc_exec_read_cb_t out, rpc_exec_read_cb_t err, 299 rpc_exec_done_cb_t end, void *priv, struct ubus_context *ctx, 300 struct ubus_request_data *req) 301 { 302 pid_t pid; 303 304 int ipipe[2]; 305 int opipe[2]; 306 int epipe[2]; 307 308 const char *cmd; 309 struct rpc_exec_context *c; 310 311 cmd = rpc_exec_lookup(args[0]); 312 313 if (!cmd) 314 return UBUS_STATUS_NOT_FOUND; 315 316 c = malloc(sizeof(*c)); 317 318 if (!c) 319 return UBUS_STATUS_UNKNOWN_ERROR; 320 321 if (pipe(ipipe)) 322 goto fail_ipipe; 323 324 if (pipe(opipe)) 325 goto fail_opipe; 326 327 if (pipe(epipe)) 328 goto fail_epipe; 329 330 switch ((pid = fork())) 331 { 332 case -1: 333 goto fail_fork; 334 335 case 0: 336 uloop_done(); 337 338 dup2(ipipe[0], 0); 339 dup2(opipe[1], 1); 340 dup2(epipe[1], 2); 341 342 close(ipipe[0]); 343 close(ipipe[1]); 344 close(opipe[0]); 345 close(opipe[1]); 346 close(epipe[0]); 347 close(epipe[1]); 348 349 if (execv(cmd, (char * const *)args)) 350 return rpc_errno_status(); 351 352 default: 353 memset(c, 0, sizeof(*c)); 354 blob_buf_init(&c->blob, 0); 355 356 c->stdin_cb = in; 357 c->stdout_cb = out; 358 c->stderr_cb = err; 359 c->finish_cb = end; 360 c->priv = priv; 361 362 ustream_declare_read(c->opipe, opipe[0], opipe); 363 ustream_declare_read(c->epipe, epipe[0], epipe); 364 365 c->process.pid = pid; 366 c->process.cb = rpc_exec_process_cb; 367 uloop_process_add(&c->process); 368 369 c->timeout.cb = rpc_exec_timeout_cb; 370 uloop_timeout_set(&c->timeout, rpc_exec_timeout); 371 372 if (c->stdin_cb) 373 { 374 ustream_declare_write(c->ipipe, ipipe[1], ipipe); 375 rpc_exec_ipipe_write_cb(&c->ipipe.stream, 0); 376 } 377 else 378 { 379 close(ipipe[1]); 380 } 381 382 close(ipipe[0]); 383 close(opipe[1]); 384 close(epipe[1]); 385 386 c->context = ctx; 387 ubus_defer_request(ctx, req, &c->request); 388 } 389 390 return UBUS_STATUS_OK; 391 392 fail_fork: 393 close(epipe[0]); 394 close(epipe[1]); 395 396 fail_epipe: 397 close(opipe[0]); 398 close(opipe[1]); 399 400 fail_opipe: 401 close(ipipe[0]); 402 close(ipipe[1]); 403 404 fail_ipipe: 405 free(c); 406 return rpc_errno_status(); 407 } 408
This page was automatically generated by LXR 0.3.1. • OpenWrt