Refactoring to the daemon. usbipd_dev.c is device-side specific code extracted from usbipd.c. usbipd.c is left as common parts for both device(stub)-side and application(vhci)-side daemon. Signed-off-by: Nobuo Iwata <nobuo.iwata@xxxxxxxxxxxxxxx> --- tools/usb/usbip/src/Makefile.am | 2 +- tools/usb/usbip/src/usbipd.c | 235 +++------------------------- tools/usb/usbip/src/usbipd.h | 39 +++++ tools/usb/usbip/src/usbipd_dev.c | 256 +++++++++++++++++++++++++++++++ 4 files changed, 316 insertions(+), 216 deletions(-) diff --git a/tools/usb/usbip/src/Makefile.am b/tools/usb/usbip/src/Makefile.am index 42760c3..1aa5156 100644 --- a/tools/usb/usbip/src/Makefile.am +++ b/tools/usb/usbip/src/Makefile.am @@ -9,4 +9,4 @@ usbip_SOURCES := usbip.h utils.h usbip.c utils.c usbip_network.c \ usbip_bind.c usbip_unbind.c usbip_port.c \ usbip_connect.c usbip_disconnect.c -usbipd_SOURCES := usbip_network.h usbipd.c usbip_network.c +usbipd_SOURCES := usbip_network.h usbipd.c usbipd_dev.c usbip_network.c diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c index a0972de..ef60026 100644 --- a/tools/usb/usbip/src/usbipd.c +++ b/tools/usb/usbip/src/usbipd.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 matt mooney <mfm@xxxxxxxxxxxxx> + * Copyright (C) 2015 Nobuo Iwata + * 2011 matt mooney <mfm@xxxxxxxxxxxxx> * 2005-2007 Takahiro Hirofuchi * Copyright (C) 2015-2016 Samsung Electronics * Igor Kotrasinski <i.kotrasinsk@xxxxxxxxxxx> @@ -43,25 +44,19 @@ #include <signal.h> #include <poll.h> -#include "usbip_host_driver.h" -#include "usbip_host_common.h" -#include "usbip_device_driver.h" #include "usbip_common.h" #include "usbip_network.h" +#include "usbipd.h" #include "list.h" -#undef PROGNAME -#define PROGNAME "usbipd" #define MAXSOCKFD 20 #define MAIN_LOOP_TIMEOUT 10 -#define DEFAULT_PID_FILE "/var/run/" PROGNAME ".pid" - static const char usbip_version_string[] = PACKAGE_STRING; static const char usbipd_help_string[] = - "usage: usbipd [options]\n" + "usage: %s [options]\n" "\n" " -4, --ipv4\n" " Bind to IPv4. Default is both.\n" @@ -82,7 +77,7 @@ static const char usbipd_help_string[] = "\n" " -PFILE, --pid FILE\n" " Write process id to FILE.\n" - " If no FILE specified, use " DEFAULT_PID_FILE "\n" + " If no FILE specified, use %s.\n" "\n" " -tPORT, --tcp-port PORT\n" " Listen on TCP/IP port PORT.\n" @@ -93,198 +88,9 @@ static const char usbipd_help_string[] = " -v, --version\n" " Show version.\n"; -static struct usbip_host_driver *driver; - static void usbipd_help(void) { - printf("%s\n", usbipd_help_string); -} - -static int recv_request_import(int sockfd) -{ - struct op_import_request req; - struct usbip_exported_device *edev; - struct usbip_usb_device pdu_udev; - struct list_head *i; - int found = 0; - int error = 0; - int rc; - - memset(&req, 0, sizeof(req)); - - rc = usbip_net_recv(sockfd, &req, sizeof(req)); - if (rc < 0) { - dbg("usbip_net_recv failed: import request"); - return -1; - } - PACK_OP_IMPORT_REQUEST(0, &req); - - list_for_each(i, &driver->edev_list) { - edev = list_entry(i, struct usbip_exported_device, node); - if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { - info("found requested device: %s", req.busid); - found = 1; - break; - } - } - - if (found) { - /* should set TCP_NODELAY for usbip */ - usbip_net_set_nodelay(sockfd); - - /* export device needs a TCP/IP socket descriptor */ - rc = usbip_export_device(edev, sockfd); - if (rc < 0) - error = 1; - } else { - info("requested device not found: %s", req.busid); - error = 1; - } - - rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT, - (!error ? ST_OK : ST_NA)); - if (rc < 0) { - dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT); - return -1; - } - - if (error) { - dbg("import request busid %s: failed", req.busid); - return -1; - } - - memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); - usbip_net_pack_usb_device(1, &pdu_udev); - - rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev)); - if (rc < 0) { - dbg("usbip_net_send failed: devinfo"); - return -1; - } - - dbg("import request busid %s: complete", req.busid); - - return 0; -} - -static int send_reply_devlist(int connfd) -{ - struct usbip_exported_device *edev; - struct usbip_usb_device pdu_udev; - struct usbip_usb_interface pdu_uinf; - struct op_devlist_reply reply; - struct list_head *j; - int rc, i; - - reply.ndev = 0; - /* number of exported devices */ - list_for_each(j, &driver->edev_list) { - reply.ndev += 1; - } - info("exportable devices: %d", reply.ndev); - - rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK); - if (rc < 0) { - dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST); - return -1; - } - PACK_OP_DEVLIST_REPLY(1, &reply); - - rc = usbip_net_send(connfd, &reply, sizeof(reply)); - if (rc < 0) { - dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST); - return -1; - } - - list_for_each(j, &driver->edev_list) { - edev = list_entry(j, struct usbip_exported_device, node); - dump_usb_device(&edev->udev); - memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); - usbip_net_pack_usb_device(1, &pdu_udev); - - rc = usbip_net_send(connfd, &pdu_udev, sizeof(pdu_udev)); - if (rc < 0) { - dbg("usbip_net_send failed: pdu_udev"); - return -1; - } - - for (i = 0; i < edev->udev.bNumInterfaces; i++) { - dump_usb_interface(&edev->uinf[i]); - memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf)); - usbip_net_pack_usb_interface(1, &pdu_uinf); - - rc = usbip_net_send(connfd, &pdu_uinf, - sizeof(pdu_uinf)); - if (rc < 0) { - err("usbip_net_send failed: pdu_uinf"); - return -1; - } - } - } - - return 0; -} - -static int recv_request_devlist(int connfd) -{ - struct op_devlist_request req; - int rc; - - memset(&req, 0, sizeof(req)); - - rc = usbip_net_recv(connfd, &req, sizeof(req)); - if (rc < 0) { - dbg("usbip_net_recv failed: devlist request"); - return -1; - } - - rc = send_reply_devlist(connfd); - if (rc < 0) { - dbg("send_reply_devlist failed"); - return -1; - } - - return 0; -} - -static int recv_pdu(int connfd) -{ - uint16_t code = OP_UNSPEC; - int ret; - - ret = usbip_net_recv_op_common(connfd, &code); - if (ret < 0) { - dbg("could not receive opcode: %#0x", code); - return -1; - } - - ret = usbip_refresh_device_list(driver); - if (ret < 0) { - dbg("could not refresh device list: %d", ret); - return -1; - } - - info("received request: %#0x(%d)", code, connfd); - switch (code) { - case OP_REQ_DEVLIST: - ret = recv_request_devlist(connfd); - break; - case OP_REQ_IMPORT: - ret = recv_request_import(connfd); - break; - case OP_REQ_DEVINFO: - case OP_REQ_CRYPKEY: - default: - err("received an unknown opcode: %#0x", code); - ret = -1; - } - - if (ret == 0) - info("request %#0x(%d): complete", code, connfd); - else - info("request %#0x(%d): failed", code, connfd); - - return ret; + printf(usbipd_help_string, usbip_progname, usbip_default_pid_file); } #ifdef HAVE_LIBWRAP @@ -303,12 +109,11 @@ static int tcpd_auth(int connfd) } #endif -static int do_accept(int listenfd) +static int do_accept(int listenfd, char *host, char *port) { int connfd; struct sockaddr_storage ss; socklen_t len = sizeof(ss); - char host[NI_MAXHOST], port[NI_MAXSERV]; int rc; memset(&ss, 0, sizeof(ss)); @@ -319,8 +124,8 @@ static int do_accept(int listenfd) return -1; } - rc = getnameinfo((struct sockaddr *)&ss, len, host, sizeof(host), - port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); + rc = getnameinfo((struct sockaddr *)&ss, len, host, NI_MAXHOST, + port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); if (rc) err("getnameinfo: %s", gai_strerror(rc)); @@ -341,14 +146,15 @@ int process_request(int listenfd) { pid_t childpid; int connfd; + char host[NI_MAXHOST], port[NI_MAXSERV]; - connfd = do_accept(listenfd); + connfd = do_accept(listenfd, host, port); if (connfd < 0) return -1; childpid = fork(); if (childpid == 0) { close(listenfd); - recv_pdu(connfd); + usbip_recv_pdu(connfd, host, port); exit(0); } close(connfd); @@ -503,13 +309,13 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6) struct timespec timeout; sigset_t sigmask; - if (usbip_driver_open(driver)) + if (usbip_open_driver()) return -1; if (daemonize) { if (daemon(0, 0) < 0) { err("daemonizing failed: %s", strerror(errno)); - usbip_driver_close(driver); + usbip_close_driver(); return -1; } umask(0); @@ -534,7 +340,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6) ai_head = do_getaddrinfo(NULL, family); if (!ai_head) { - usbip_driver_close(driver); + usbip_close_driver(); return -1; } nsockfd = listen_all_addrinfo(ai_head, sockfdlist, @@ -542,7 +348,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6) freeaddrinfo(ai_head); if (nsockfd <= 0) { err("failed to open a listening socket"); - usbip_driver_close(driver); + usbip_close_driver(); return -1; } @@ -583,7 +389,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6) info("shutting down " PROGNAME); free(fds); - usbip_driver_close(driver); + usbip_close_driver(); return 0; } @@ -594,7 +400,6 @@ int main(int argc, char *argv[]) { "ipv4", no_argument, NULL, '4' }, { "ipv6", no_argument, NULL, '6' }, { "daemon", no_argument, NULL, 'D' }, - { "daemon", no_argument, NULL, 'D' }, { "debug", no_argument, NULL, 'd' }, { "device", no_argument, NULL, 'e' }, { "pid", optional_argument, NULL, 'P' }, @@ -623,7 +428,7 @@ int main(int argc, char *argv[]) err("not running as root?"); cmd = cmd_standalone_mode; - driver = &host_driver; + usbip_init_driver(); for (;;) { opt = getopt_long(argc, argv, "46DdeP::t:hv", longopts, NULL); @@ -647,7 +452,7 @@ int main(int argc, char *argv[]) cmd = cmd_help; break; case 'P': - pid_file = optarg ? optarg : DEFAULT_PID_FILE; + pid_file = optarg ? optarg : usbip_default_pid_file; break; case 't': usbip_setup_port_number(optarg); @@ -656,7 +461,7 @@ int main(int argc, char *argv[]) cmd = cmd_version; break; case 'e': - driver = &device_driver; + usbip_update_driver(); break; case '?': usbipd_help(); diff --git a/tools/usb/usbip/src/usbipd.h b/tools/usb/usbip/src/usbipd.h new file mode 100644 index 0000000..df514f7 --- /dev/null +++ b/tools/usb/usbip/src/usbipd.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 Nobuo Iwata + * 2011 matt mooney <mfm@xxxxxxxxxxxxx> + * 2005-2007 Takahiro Hirofuchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __USBIPD_H +#define __USBIPD_H + +#include "usbip_common.h" + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +extern char *usbip_progname; +extern char *usbip_default_pid_file; + +int usbip_recv_pdu(int connfd, char *host, char *port); + +void usbip_init_driver(void); +void usbip_update_driver(void); +int usbip_open_driver(void); +void usbip_close_driver(void); + +#endif /* __USBIPD_H */ diff --git a/tools/usb/usbip/src/usbipd_dev.c b/tools/usb/usbip/src/usbipd_dev.c new file mode 100644 index 0000000..372b2bd --- /dev/null +++ b/tools/usb/usbip/src/usbipd_dev.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2015 Nobuo Iwata + * 2011 matt mooney <mfm@xxxxxxxxxxxxx> + * 2005-2007 Takahiro Hirofuchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#define _GNU_SOURCE +#include <errno.h> +#include <unistd.h> +#include <netdb.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <arpa/inet.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#include "usbip_host_driver.h" +#include "usbip_host_common.h" +#include "usbip_device_driver.h" +#include "usbip_common.h" +#include "usbip_network.h" +#include "list.h" + +char *usbip_progname = "usbipd"; +char *usbip_default_pid_file = "/var/run/usbipd"; + +static struct usbip_host_driver *driver; + +void usbip_init_driver(void) +{ + driver = &host_driver; +} + +void usbip_update_driver(void) +{ + driver = &device_driver; +} + +int usbip_open_driver(void) +{ + return usbip_driver_open(driver); +} + +void usbip_close_driver(void) +{ + usbip_driver_close(driver); +} + +static int recv_request_import(int sockfd) +{ + struct op_import_request req; + struct op_common reply; + struct usbip_exported_device *edev; + struct usbip_usb_device pdu_udev; + struct list_head *i; + int found = 0; + int error = 0; + int rc; + + memset(&req, 0, sizeof(req)); + memset(&reply, 0, sizeof(reply)); + + rc = usbip_net_recv(sockfd, &req, sizeof(req)); + if (rc < 0) { + dbg("usbip_net_recv failed: import request"); + return -1; + } + PACK_OP_IMPORT_REQUEST(0, &req); + + list_for_each(i, &driver->edev_list) { + edev = list_entry(i, struct usbip_exported_device, node); + if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { + info("found requested device: %s", req.busid); + found = 1; + break; + } + } + + if (found) { + /* should set TCP_NODELAY for usbip */ + usbip_net_set_nodelay(sockfd); + + /* export device needs a TCP/IP socket descriptor */ + rc = usbip_export_device(edev, sockfd); + if (rc < 0) + error = 1; + } else { + info("requested device not found: %s", req.busid); + error = 1; + } + + rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT, + (!error ? ST_OK : ST_NA)); + if (rc < 0) { + dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT); + return -1; + } + + if (error) { + dbg("import request busid %s: failed", req.busid); + return -1; + } + + memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); + usbip_net_pack_usb_device(1, &pdu_udev); + + rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev)); + if (rc < 0) { + dbg("usbip_net_send failed: devinfo"); + return -1; + } + + dbg("import request busid %s: complete", req.busid); + + return 0; +} + +static int send_reply_devlist(int connfd) +{ + struct usbip_exported_device *edev; + struct usbip_usb_device pdu_udev; + struct usbip_usb_interface pdu_uinf; + struct op_devlist_reply reply; + struct list_head *j; + int rc, i; + + reply.ndev = 0; + /* number of exported devices */ + list_for_each(j, &driver->edev_list) { + reply.ndev += 1; + } + info("exportable devices: %d", reply.ndev); + + rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK); + if (rc < 0) { + dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST); + return -1; + } + PACK_OP_DEVLIST_REPLY(1, &reply); + + rc = usbip_net_send(connfd, &reply, sizeof(reply)); + if (rc < 0) { + dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST); + return -1; + } + + list_for_each(j, &driver->edev_list) { + edev = list_entry(j, struct usbip_exported_device, node); + dump_usb_device(&edev->udev); + memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); + usbip_net_pack_usb_device(1, &pdu_udev); + + rc = usbip_net_send(connfd, &pdu_udev, sizeof(pdu_udev)); + if (rc < 0) { + dbg("usbip_net_send failed: pdu_udev"); + return -1; + } + + for (i = 0; i < edev->udev.bNumInterfaces; i++) { + dump_usb_interface(&edev->uinf[i]); + memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf)); + usbip_net_pack_usb_interface(1, &pdu_uinf); + + rc = usbip_net_send(connfd, &pdu_uinf, + sizeof(pdu_uinf)); + if (rc < 0) { + err("usbip_net_send failed: pdu_uinf"); + return -1; + } + } + } + + return 0; +} + +static int recv_request_devlist(int connfd) +{ + struct op_devlist_request req; + int rc; + + memset(&req, 0, sizeof(req)); + + rc = usbip_net_recv(connfd, &req, sizeof(req)); + if (rc < 0) { + dbg("usbip_net_recv failed: devlist request"); + return -1; + } + + rc = send_reply_devlist(connfd); + if (rc < 0) { + dbg("send_reply_devlist failed"); + return -1; + } + + return 0; +} + +int usbip_recv_pdu(int connfd, char *host, char *port) +{ + uint16_t code = OP_UNSPEC; + int ret; + + ret = usbip_net_recv_op_common(connfd, &code); + if (ret < 0) { + dbg("could not receive opcode: %#0x", code); + return -1; + } + + ret = usbip_refresh_device_list(driver); + if (ret < 0) { + dbg("could not refresh device list: %d", ret); + return -1; + } + + info("received request: %#0x(%d)", code, connfd); + switch (code) { + case OP_REQ_DEVLIST: + ret = recv_request_devlist(connfd); + break; + case OP_REQ_IMPORT: + ret = recv_request_import(connfd); + break; + case OP_REQ_DEVINFO: + case OP_REQ_CRYPKEY: + default: + err("received an unknown opcode: %#0x", code); + ret = -1; + } + + if (ret == 0) + info("request %#0x(%s:%s): complete", code, host, port); + else + info("request %#0x(%s:%s): failed", code, host, port); + + return ret; +} + -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html