linux/tools/usb/usbip/src/usbipd.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
   4 *               2005-2007 Takahiro Hirofuchi
   5 * Copyright (C) 2015-2016 Samsung Electronics
   6 *               Igor Kotrasinski <i.kotrasinsk@samsung.com>
   7 *               Krzysztof Opasiak <k.opasiak@samsung.com>
   8 */
   9
  10#ifdef HAVE_CONFIG_H
  11#include "../config.h"
  12#endif
  13
  14#define _GNU_SOURCE
  15#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_LIBWRAP
  27#include <tcpd.h>
  28#endif
  29
  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  PROGNAME
  42#define PROGNAME "usbipd"
  43#define MAXSOCKFD 20
  44
  45#define MAIN_LOOP_TIMEOUT 10
  46
  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 from
 168         * the exportable device list to avoid:
 169         *      - import requests for devices that are exported only to
 170         *        fail the request.
 171         *      - revealing devices that are imported by a client to
 172         *        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        else
 287                info("request %#0x(%d): failed", code, connfd);
 288
 289        return ret;
 290}
 291
 292#ifdef HAVE_LIBWRAP
 293static 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#endif
 307
 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_LIBWRAP
 330        rc = tcpd_auth(connfd);
 331        if (rc < 0) {
 332                info("denied access from %s", host);
 333                close(connfd);
 334                return -1;
 335        }
 336#endif
 337        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 IPv6
 400                 * (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 disabled
 520         * (default), we use seperate sockets for IPv6 and IPv4 and set
 521         * IPV6_V6ONLY on the IPv6 sockets.
 522         */
 523        if (ipv4 && ipv6)
 524                family = AF_UNSPEC;
 525        else if (ipv4)
 526                family = AF_INET;
 527        else
 528                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_version
 606        } 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