687 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>4 * 2005-2007 Takahiro Hirofuchi5 * Copyright (C) 2015-2016 Samsung Electronics6 * Igor Kotrasinski <i.kotrasinsk@samsung.com>7 * Krzysztof Opasiak <k.opasiak@samsung.com>8 */9 10#ifdef HAVE_CONFIG_H11#include "../config.h"12#endif13 14#define _GNU_SOURCE15#include <errno.h>16#include <unistd.h>17#include <netdb.h>18#include <string.h>19#include <stdlib.h>20#include <sys/types.h>21#include <sys/stat.h>22#include <arpa/inet.h>23#include <sys/socket.h>24#include <netinet/in.h>25 26#ifdef HAVE_LIBWRAP27#include <tcpd.h>28#endif29 30#include <getopt.h>31#include <signal.h>32#include <poll.h>33 34#include "usbip_host_driver.h"35#include "usbip_host_common.h"36#include "usbip_device_driver.h"37#include "usbip_common.h"38#include "usbip_network.h"39#include "list.h"40 41#undef PROGNAME42#define PROGNAME "usbipd"43#define MAXSOCKFD 2044 45#define MAIN_LOOP_TIMEOUT 1046 47#define DEFAULT_PID_FILE "/var/run/" PROGNAME ".pid"48 49static const char usbip_version_string[] = PACKAGE_STRING;50 51static const char usbipd_help_string[] =52 "usage: usbipd [options]\n"53 "\n"54 " -4, --ipv4\n"55 " Bind to IPv4. Default is both.\n"56 "\n"57 " -6, --ipv6\n"58 " Bind to IPv6. Default is both.\n"59 "\n"60 " -e, --device\n"61 " Run in device mode.\n"62 " Rather than drive an attached device, create\n"63 " a virtual UDC to bind gadgets to.\n"64 "\n"65 " -D, --daemon\n"66 " Run as a daemon process.\n"67 "\n"68 " -d, --debug\n"69 " Print debugging information.\n"70 "\n"71 " -PFILE, --pid FILE\n"72 " Write process id to FILE.\n"73 " If no FILE specified, use " DEFAULT_PID_FILE "\n"74 "\n"75 " -tPORT, --tcp-port PORT\n"76 " Listen on TCP/IP port PORT.\n"77 "\n"78 " -h, --help\n"79 " Print this help.\n"80 "\n"81 " -v, --version\n"82 " Show version.\n";83 84static struct usbip_host_driver *driver;85 86static void usbipd_help(void)87{88 printf("%s\n", usbipd_help_string);89}90 91static int recv_request_import(int sockfd)92{93 struct op_import_request req;94 struct usbip_exported_device *edev;95 struct usbip_usb_device pdu_udev;96 struct list_head *i;97 int found = 0;98 int status = ST_OK;99 int rc;100 101 memset(&req, 0, sizeof(req));102 103 rc = usbip_net_recv(sockfd, &req, sizeof(req));104 if (rc < 0) {105 dbg("usbip_net_recv failed: import request");106 return -1;107 }108 PACK_OP_IMPORT_REQUEST(0, &req);109 110 list_for_each(i, &driver->edev_list) {111 edev = list_entry(i, struct usbip_exported_device, node);112 if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) {113 info("found requested device: %s", req.busid);114 found = 1;115 break;116 }117 }118 119 if (found) {120 /* should set TCP_NODELAY for usbip */121 usbip_net_set_nodelay(sockfd);122 123 /* export device needs a TCP/IP socket descriptor */124 status = usbip_export_device(edev, sockfd);125 if (status < 0)126 status = ST_NA;127 } else {128 info("requested device not found: %s", req.busid);129 status = ST_NODEV;130 }131 132 rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT, status);133 if (rc < 0) {134 dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT);135 return -1;136 }137 138 if (status) {139 dbg("import request busid %s: failed", req.busid);140 return -1;141 }142 143 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));144 usbip_net_pack_usb_device(1, &pdu_udev);145 146 rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev));147 if (rc < 0) {148 dbg("usbip_net_send failed: devinfo");149 return -1;150 }151 152 dbg("import request busid %s: complete", req.busid);153 154 return 0;155}156 157static int send_reply_devlist(int connfd)158{159 struct usbip_exported_device *edev;160 struct usbip_usb_device pdu_udev;161 struct usbip_usb_interface pdu_uinf;162 struct op_devlist_reply reply;163 struct list_head *j;164 int rc, i;165 166 /*167 * Exclude devices that are already exported to a client from168 * the exportable device list to avoid:169 * - import requests for devices that are exported only to170 * fail the request.171 * - revealing devices that are imported by a client to172 * another client.173 */174 175 reply.ndev = 0;176 /* number of exported devices */177 list_for_each(j, &driver->edev_list) {178 edev = list_entry(j, struct usbip_exported_device, node);179 if (edev->status != SDEV_ST_USED)180 reply.ndev += 1;181 }182 info("exportable devices: %d", reply.ndev);183 184 rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK);185 if (rc < 0) {186 dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST);187 return -1;188 }189 PACK_OP_DEVLIST_REPLY(1, &reply);190 191 rc = usbip_net_send(connfd, &reply, sizeof(reply));192 if (rc < 0) {193 dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST);194 return -1;195 }196 197 list_for_each(j, &driver->edev_list) {198 edev = list_entry(j, struct usbip_exported_device, node);199 if (edev->status == SDEV_ST_USED)200 continue;201 202 dump_usb_device(&edev->udev);203 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));204 usbip_net_pack_usb_device(1, &pdu_udev);205 206 rc = usbip_net_send(connfd, &pdu_udev, sizeof(pdu_udev));207 if (rc < 0) {208 dbg("usbip_net_send failed: pdu_udev");209 return -1;210 }211 212 for (i = 0; i < edev->udev.bNumInterfaces; i++) {213 dump_usb_interface(&edev->uinf[i]);214 memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf));215 usbip_net_pack_usb_interface(1, &pdu_uinf);216 217 rc = usbip_net_send(connfd, &pdu_uinf,218 sizeof(pdu_uinf));219 if (rc < 0) {220 err("usbip_net_send failed: pdu_uinf");221 return -1;222 }223 }224 }225 226 return 0;227}228 229static int recv_request_devlist(int connfd)230{231 struct op_devlist_request req;232 int rc;233 234 memset(&req, 0, sizeof(req));235 236 rc = usbip_net_recv(connfd, &req, sizeof(req));237 if (rc < 0) {238 dbg("usbip_net_recv failed: devlist request");239 return -1;240 }241 242 rc = send_reply_devlist(connfd);243 if (rc < 0) {244 dbg("send_reply_devlist failed");245 return -1;246 }247 248 return 0;249}250 251static int recv_pdu(int connfd)252{253 uint16_t code = OP_UNSPEC;254 int ret;255 int status;256 257 ret = usbip_net_recv_op_common(connfd, &code, &status);258 if (ret < 0) {259 dbg("could not receive opcode: %#0x", code);260 return -1;261 }262 263 ret = usbip_refresh_device_list(driver);264 if (ret < 0) {265 dbg("could not refresh device list: %d", ret);266 return -1;267 }268 269 info("received request: %#0x(%d)", code, connfd);270 switch (code) {271 case OP_REQ_DEVLIST:272 ret = recv_request_devlist(connfd);273 break;274 case OP_REQ_IMPORT:275 ret = recv_request_import(connfd);276 break;277 case OP_REQ_DEVINFO:278 case OP_REQ_CRYPKEY:279 default:280 err("received an unknown opcode: %#0x", code);281 ret = -1;282 }283 284 if (ret == 0)285 info("request %#0x(%d): complete", code, connfd);286 else287 info("request %#0x(%d): failed", code, connfd);288 289 return ret;290}291 292#ifdef HAVE_LIBWRAP293static int tcpd_auth(int connfd)294{295 struct request_info request;296 int rc;297 298 request_init(&request, RQ_DAEMON, PROGNAME, RQ_FILE, connfd, 0);299 fromhost(&request);300 rc = hosts_access(&request);301 if (rc == 0)302 return -1;303 304 return 0;305}306#endif307 308static int do_accept(int listenfd)309{310 int connfd;311 struct sockaddr_storage ss;312 socklen_t len = sizeof(ss);313 char host[NI_MAXHOST], port[NI_MAXSERV];314 int rc;315 316 memset(&ss, 0, sizeof(ss));317 318 connfd = accept(listenfd, (struct sockaddr *)&ss, &len);319 if (connfd < 0) {320 err("failed to accept connection");321 return -1;322 }323 324 rc = getnameinfo((struct sockaddr *)&ss, len, host, sizeof(host),325 port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);326 if (rc)327 err("getnameinfo: %s", gai_strerror(rc));328 329#ifdef HAVE_LIBWRAP330 rc = tcpd_auth(connfd);331 if (rc < 0) {332 info("denied access from %s", host);333 close(connfd);334 return -1;335 }336#endif337 info("connection from %s:%s", host, port);338 339 return connfd;340}341 342int process_request(int listenfd)343{344 pid_t childpid;345 int connfd;346 347 connfd = do_accept(listenfd);348 if (connfd < 0)349 return -1;350 childpid = fork();351 if (childpid == 0) {352 close(listenfd);353 recv_pdu(connfd);354 exit(0);355 }356 close(connfd);357 return 0;358}359 360static void addrinfo_to_text(struct addrinfo *ai, char buf[],361 const size_t buf_size)362{363 char hbuf[NI_MAXHOST];364 char sbuf[NI_MAXSERV];365 int rc;366 367 buf[0] = '\0';368 369 rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf),370 sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);371 if (rc)372 err("getnameinfo: %s", gai_strerror(rc));373 374 snprintf(buf, buf_size, "%s:%s", hbuf, sbuf);375}376 377static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[],378 int maxsockfd)379{380 struct addrinfo *ai;381 int ret, nsockfd = 0;382 const size_t ai_buf_size = NI_MAXHOST + NI_MAXSERV + 2;383 char ai_buf[ai_buf_size];384 385 for (ai = ai_head; ai && nsockfd < maxsockfd; ai = ai->ai_next) {386 int sock;387 388 addrinfo_to_text(ai, ai_buf, ai_buf_size);389 dbg("opening %s", ai_buf);390 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);391 if (sock < 0) {392 err("socket: %s: %d (%s)",393 ai_buf, errno, strerror(errno));394 continue;395 }396 397 usbip_net_set_reuseaddr(sock);398 usbip_net_set_nodelay(sock);399 /* We use seperate sockets for IPv4 and IPv6400 * (see do_standalone_mode()) */401 usbip_net_set_v6only(sock);402 403 ret = bind(sock, ai->ai_addr, ai->ai_addrlen);404 if (ret < 0) {405 err("bind: %s: %d (%s)",406 ai_buf, errno, strerror(errno));407 close(sock);408 continue;409 }410 411 ret = listen(sock, SOMAXCONN);412 if (ret < 0) {413 err("listen: %s: %d (%s)",414 ai_buf, errno, strerror(errno));415 close(sock);416 continue;417 }418 419 info("listening on %s", ai_buf);420 sockfdlist[nsockfd++] = sock;421 }422 423 return nsockfd;424}425 426static struct addrinfo *do_getaddrinfo(char *host, int ai_family)427{428 struct addrinfo hints, *ai_head;429 int rc;430 431 memset(&hints, 0, sizeof(hints));432 hints.ai_family = ai_family;433 hints.ai_socktype = SOCK_STREAM;434 hints.ai_flags = AI_PASSIVE;435 436 rc = getaddrinfo(host, usbip_port_string, &hints, &ai_head);437 if (rc) {438 err("failed to get a network address %s: %s", usbip_port_string,439 gai_strerror(rc));440 return NULL;441 }442 443 return ai_head;444}445 446static void signal_handler(int i)447{448 dbg("received '%s' signal", strsignal(i));449}450 451static void set_signal(void)452{453 struct sigaction act;454 455 memset(&act, 0, sizeof(act));456 act.sa_handler = signal_handler;457 sigemptyset(&act.sa_mask);458 sigaction(SIGTERM, &act, NULL);459 sigaction(SIGINT, &act, NULL);460 act.sa_handler = SIG_IGN;461 sigaction(SIGCHLD, &act, NULL);462}463 464static const char *pid_file;465 466static void write_pid_file(void)467{468 if (pid_file) {469 dbg("creating pid file %s", pid_file);470 FILE *fp;471 472 fp = fopen(pid_file, "w");473 if (!fp) {474 err("pid_file: %s: %d (%s)",475 pid_file, errno, strerror(errno));476 return;477 }478 fprintf(fp, "%d\n", getpid());479 fclose(fp);480 }481}482 483static void remove_pid_file(void)484{485 if (pid_file) {486 dbg("removing pid file %s", pid_file);487 unlink(pid_file);488 }489}490 491static int do_standalone_mode(int daemonize, int ipv4, int ipv6)492{493 struct addrinfo *ai_head;494 int sockfdlist[MAXSOCKFD];495 int nsockfd, family;496 int i, terminate;497 struct pollfd *fds;498 struct timespec timeout;499 sigset_t sigmask;500 501 if (usbip_driver_open(driver))502 return -1;503 504 if (daemonize) {505 if (daemon(0, 0) < 0) {506 err("daemonizing failed: %s", strerror(errno));507 usbip_driver_close(driver);508 return -1;509 }510 umask(0);511 usbip_use_syslog = 1;512 }513 set_signal();514 write_pid_file();515 516 info("starting " PROGNAME " (%s)", usbip_version_string);517 518 /*519 * To suppress warnings on systems with bindv6only disabled520 * (default), we use seperate sockets for IPv6 and IPv4 and set521 * IPV6_V6ONLY on the IPv6 sockets.522 */523 if (ipv4 && ipv6)524 family = AF_UNSPEC;525 else if (ipv4)526 family = AF_INET;527 else528 family = AF_INET6;529 530 ai_head = do_getaddrinfo(NULL, family);531 if (!ai_head) {532 usbip_driver_close(driver);533 return -1;534 }535 nsockfd = listen_all_addrinfo(ai_head, sockfdlist,536 sizeof(sockfdlist) / sizeof(*sockfdlist));537 freeaddrinfo(ai_head);538 if (nsockfd <= 0) {539 err("failed to open a listening socket");540 usbip_driver_close(driver);541 return -1;542 }543 544 dbg("listening on %d address%s", nsockfd, (nsockfd == 1) ? "" : "es");545 546 fds = calloc(nsockfd, sizeof(struct pollfd));547 for (i = 0; i < nsockfd; i++) {548 fds[i].fd = sockfdlist[i];549 fds[i].events = POLLIN;550 }551 timeout.tv_sec = MAIN_LOOP_TIMEOUT;552 timeout.tv_nsec = 0;553 554 sigfillset(&sigmask);555 sigdelset(&sigmask, SIGTERM);556 sigdelset(&sigmask, SIGINT);557 558 terminate = 0;559 while (!terminate) {560 int r;561 562 r = ppoll(fds, nsockfd, &timeout, &sigmask);563 if (r < 0) {564 dbg("%s", strerror(errno));565 terminate = 1;566 } else if (r) {567 for (i = 0; i < nsockfd; i++) {568 if (fds[i].revents & POLLIN) {569 dbg("read event on fd[%d]=%d",570 i, sockfdlist[i]);571 process_request(sockfdlist[i]);572 }573 }574 } else {575 dbg("heartbeat timeout on ppoll()");576 }577 }578 579 info("shutting down " PROGNAME);580 free(fds);581 usbip_driver_close(driver);582 583 return 0;584}585 586int main(int argc, char *argv[])587{588 static const struct option longopts[] = {589 { "ipv4", no_argument, NULL, '4' },590 { "ipv6", no_argument, NULL, '6' },591 { "daemon", no_argument, NULL, 'D' },592 { "daemon", no_argument, NULL, 'D' },593 { "debug", no_argument, NULL, 'd' },594 { "device", no_argument, NULL, 'e' },595 { "pid", optional_argument, NULL, 'P' },596 { "tcp-port", required_argument, NULL, 't' },597 { "help", no_argument, NULL, 'h' },598 { "version", no_argument, NULL, 'v' },599 { NULL, 0, NULL, 0 }600 };601 602 enum {603 cmd_standalone_mode = 1,604 cmd_help,605 cmd_version606 } cmd;607 608 int daemonize = 0;609 int ipv4 = 0, ipv6 = 0;610 int opt, rc = -1;611 612 pid_file = NULL;613 614 usbip_use_stderr = 1;615 usbip_use_syslog = 0;616 617 if (geteuid() != 0)618 err("not running as root?");619 620 cmd = cmd_standalone_mode;621 driver = &host_driver;622 for (;;) {623 opt = getopt_long(argc, argv, "46DdeP::t:hv", longopts, NULL);624 625 if (opt == -1)626 break;627 628 switch (opt) {629 case '4':630 ipv4 = 1;631 break;632 case '6':633 ipv6 = 1;634 break;635 case 'D':636 daemonize = 1;637 break;638 case 'd':639 usbip_use_debug = 1;640 break;641 case 'h':642 cmd = cmd_help;643 break;644 case 'P':645 pid_file = optarg ? optarg : DEFAULT_PID_FILE;646 break;647 case 't':648 usbip_setup_port_number(optarg);649 break;650 case 'v':651 cmd = cmd_version;652 break;653 case 'e':654 driver = &device_driver;655 break;656 case '?':657 usbipd_help();658 default:659 goto err_out;660 }661 }662 663 if (!ipv4 && !ipv6)664 ipv4 = ipv6 = 1;665 666 switch (cmd) {667 case cmd_standalone_mode:668 rc = do_standalone_mode(daemonize, ipv4, ipv6);669 remove_pid_file();670 break;671 case cmd_version:672 printf(PROGNAME " (%s)\n", usbip_version_string);673 rc = 0;674 break;675 case cmd_help:676 usbipd_help();677 rc = 0;678 break;679 default:680 usbipd_help();681 goto err_out;682 }683 684err_out:685 return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);686}687