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