⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stub_server.c

📁 linux virtual usb host source
💻 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 + -