📄 stub_server.c
字号:
/* * $Id: stub_server.c 42 2007-09-07 12:07:51Z hirofuchi $ * * Copyright (C) 2005-2007 Takahiro Hirofuchi */#ifdef HAVE_CONFIG_H#include "../config.h"#endif#include <unistd.h>#include <netdb.h>#include <strings.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <arpa/inet.h>#include <sys/socket.h>#include <netinet/in.h>#ifdef HAVE_LIBWRAP#include <tcpd.h>#endif#define _GNU_SOURCE#include <getopt.h>#include <signal.h>#include "usbip.h"#include "usbip_network.h"#include <glib.h>static const char version[] = PACKAGE_STRING " ($Id: stub_server.c 42 2007-09-07 12:07:51Z hirofuchi $)";static int send_reply_devlist(int sockfd){ int ret; struct usbip_exported_device *edev; struct op_devlist_reply reply; reply.ndev = 0; /* how many devices are exported ? */ dlist_for_each_data(stub_driver->edev_list, edev, struct usbip_exported_device) { reply.ndev += 1; } dbg("%d devices are exported", reply.ndev); ret = usbip_send_op_common(sockfd, OP_REP_DEVLIST, ST_OK); if (ret < 0) { err("send op_common"); return ret; } PACK_OP_DEVLIST_REPLY(1, &reply); ret = usbip_send(sockfd, (void *) &reply, sizeof(reply)); if (ret < 0) { err("send op_devlist_reply"); return ret; } dlist_for_each_data(stub_driver->edev_list, edev, struct usbip_exported_device) { struct usb_device pdu_udev; dump_usb_device(&edev->udev); memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); pack_usb_device(1, &pdu_udev); ret = usbip_send(sockfd, (void *) &pdu_udev, sizeof(pdu_udev)); if (ret < 0) { err("send pdu_udev"); return ret; } for (int i=0; i < edev->udev.bNumInterfaces; i++) { struct usb_interface pdu_uinf; dump_usb_interface(&edev->uinf[i]); memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf)); pack_usb_interface(1, &pdu_uinf); ret = usbip_send(sockfd, (void *) &pdu_uinf, sizeof(pdu_uinf)); if (ret < 0) { err("send pdu_uinf"); return ret; } } } return 0;}static int recv_request_devlist(int sockfd){ int ret; struct op_devlist_request req; bzero(&req, sizeof(req)); ret = usbip_recv(sockfd, (void *) &req, sizeof(req)); if (ret < 0) { err("recv devlist request"); return -1; } ret = send_reply_devlist(sockfd); if (ret < 0) { err("send devlist reply"); return -1; } return 0;}static int recv_request_import(int sockfd){ int ret; struct op_import_request req; struct op_common reply; struct usbip_exported_device *edev; int found = 0; int error = 0; bzero(&req, sizeof(req)); bzero(&reply, sizeof(reply)); ret = usbip_recv(sockfd, (void *) &req, sizeof(req)); if (ret < 0) { err("recv import request"); return -1; } PACK_OP_IMPORT_REQUEST(0, &req); dlist_for_each_data(stub_driver->edev_list, edev, struct usbip_exported_device) { if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { dbg("found requested device %s", req.busid); found = 1; break; } } if (found) { /* should set TCP_NODELAY for usbip */ usbip_set_nodelay(sockfd); /* export_device needs a TCP/IP socket descriptor */ ret = usbip_stub_export_device(edev, sockfd); if (ret < 0) error = 1; } else { info("not found requested device %s", req.busid); error = 1; } ret = usbip_send_op_common(sockfd, OP_REP_IMPORT, (!error ? ST_OK : ST_NA)); if (ret < 0) { err("send import reply"); return -1; } if (!error) { struct usb_device pdu_udev; memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); pack_usb_device(1, &pdu_udev); ret = usbip_send(sockfd, (void *) &pdu_udev, sizeof(pdu_udev)); if (ret < 0) { err("send devinfo"); return -1; } } return 0;}static int recv_pdu(int sockfd){ int ret; uint16_t code = OP_UNSPEC; ret = usbip_recv_op_common(sockfd, &code); if (ret < 0) { err("recv op_common, %d", ret); return ret; } ret = usbip_stub_refresh_device_list(); if (ret < 0) return -1; switch(code) { case OP_REQ_DEVLIST: ret = recv_request_devlist(sockfd); break; case OP_REQ_IMPORT: ret = recv_request_import(sockfd); break; case OP_REQ_DEVINFO: case OP_REQ_CRYPKEY: default: err("unknown op_code, %d", code); ret = -1; } return ret;}static void log_addrinfo(struct addrinfo *ai){ int ret; char hbuf[NI_MAXHOST]; char sbuf[NI_MAXSERV]; ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV); if (ret) err("getnameinfo, %s", gai_strerror(ret)); info("listen at [%s]:%s", hbuf, sbuf);}static struct addrinfo *my_getaddrinfo(char *host, int ai_family){ int ret; struct addrinfo hints, *ai_head; bzero(&hints, sizeof(hints)); hints.ai_family = ai_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; ret = getaddrinfo(host, USBIP_PORT_STRING, &hints, &ai_head); if (ret) { err("%s: %s", USBIP_PORT_STRING, gai_strerror(ret)); return NULL; } return ai_head;}#define MAXSOCK 20static int listen_all_addrinfo(struct addrinfo *ai_head, int lsock[]){ struct addrinfo *ai; int n = 0; /* number of sockets */ for (ai = ai_head; ai && n < MAXSOCK; ai = ai->ai_next) { int ret; lsock[n] = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (lsock[n] < 0) continue; usbip_set_reuseaddr(lsock[n]); usbip_set_nodelay(lsock[n]); if (lsock[n] >= FD_SETSIZE) { close(lsock[n]); lsock[n] = -1; continue; } ret = bind(lsock[n], ai->ai_addr, ai->ai_addrlen); if (ret < 0) { close(lsock[n]); lsock[n] = -1; continue; } ret = listen(lsock[n], SOMAXCONN); if (ret < 0) { close(lsock[n]); lsock[n] = -1; continue; } log_addrinfo(ai); /* next if succeed */ n++; } if (n == 0) { err("no socket to listen to"); return -1; } dbg("listen %d address%s", n, (n==1)?"":"es"); return n;}#ifdef HAVE_LIBWRAPstatic int tcpd_auth(int csock){ int ret; struct request_info request; request_init(&request, RQ_DAEMON, "usbipd", RQ_FILE, csock, 0); fromhost(&request); ret = hosts_access(&request); if (!ret) return -1; return 0;}#endifstatic int my_accept(int lsock){ int csock; struct sockaddr_storage ss; socklen_t len = sizeof(ss); char host[NI_MAXHOST], port[NI_MAXSERV]; int ret; bzero(&ss, sizeof(ss)); csock = accept(lsock, (struct sockaddr *) &ss, &len); if (csock < 0) { err("accept"); return -1; } ret = getnameinfo((struct sockaddr *) &ss, len, host, sizeof(host), port, sizeof(port), (NI_NUMERICHOST | NI_NUMERICSERV)); if (ret) err("getnameinfo, %s", gai_strerror(ret));#ifdef HAVE_LIBWRAP ret = tcpd_auth(csock); if (ret < 0) { info("deny access from %s", host); close(csock); return -1; }#endif info("connected from %s:%s", host, port); return csock;}GMainLoop *main_loop;static void signal_handler(int i){ dbg("signal catched, code %d", i); if (main_loop) g_main_loop_quit(main_loop);}static void set_signal(void){ struct sigaction act; bzero(&act, sizeof(act)); act.sa_handler = signal_handler; sigemptyset(&act.sa_mask); sigaction(SIGTERM, &act, NULL); sigaction(SIGINT, &act, NULL);}gboolean process_comming_request(GIOChannel *gio, GIOCondition condition, gpointer data){ int ret; if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) g_error("unknown condition"); if (condition & G_IO_IN) { int lsock; int csock; lsock = g_io_channel_unix_get_fd(gio); csock = my_accept(lsock); if (csock < 0) return TRUE; ret = recv_pdu(csock); if (ret < 0) err("process recieved pdu"); close(csock); } return TRUE;}static void do_standalone_mode(gboolean daemonize){ int ret; int lsock[MAXSOCK]; struct addrinfo *ai_head; int n; ret = usbip_names_init(USBIDS_FILE); if (ret) err("open usb.ids"); ret = usbip_stub_driver_open(); if (ret < 0) g_error("driver open failed"); if (daemonize) { if (daemon(0,0) < 0) g_error("daemonizing failed: %s", g_strerror(errno)); usbip_use_syslog = 1; } set_signal(); ai_head = my_getaddrinfo(NULL, PF_UNSPEC); if (!ai_head) return; n = listen_all_addrinfo(ai_head, lsock); if (n <= 0) g_error("no socket to listen to"); for (int i = 0; i < n; i++) { GIOChannel *gio; gio = g_io_channel_unix_new(lsock[i]); g_io_add_watch(gio, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL), process_comming_request, NULL); } info("usbipd start (%s)", version); main_loop = g_main_loop_new(FALSE, FALSE); g_main_loop_run(main_loop); info("shutdown"); freeaddrinfo(ai_head); usbip_names_free(); usbip_stub_driver_close(); return;}static const char help_message[] = "\Usage: usbipd [options] \n\ -D, --daemon \n\ Run as a daemon process. \n\ \n\ -d, --debug \n\ Print debugging information. \n\ \n\ -v, --version \n\ Show version. \n\ \n\ -h, --help \n\ Print this help. \n";static void show_help(void){ printf("%s", help_message);}static const struct option longopts[] = { {"daemon", no_argument, NULL, 'D'}, {"debug", no_argument, NULL, 'd'}, {"version", no_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}};int main(int argc, char *argv[]){ gboolean daemonize = FALSE; enum { cmd_standalone_mode = 1, cmd_help, cmd_version } cmd = cmd_standalone_mode; usbip_use_stderr = 1; usbip_use_syslog = 0; if (geteuid() != 0) g_warning("running non-root?"); for (;;) { int c; int index = 0; c = getopt_long(argc, argv, "vhdD", longopts, &index); if (c == -1) break; switch (c) { case 'd': usbip_use_debug = 1; continue; case 'v': cmd = cmd_version; break; case 'h': cmd = cmd_help; break; case 'D': daemonize = TRUE; break; case '?': show_help(); exit(EXIT_FAILURE); default: err("getopt"); } } switch (cmd) { case cmd_standalone_mode: do_standalone_mode(daemonize); break; case cmd_version: printf("%s\n", version); break; case cmd_help: show_help(); break; default: info("unknown cmd"); show_help(); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -