20 #include "../config.h"
28 #include <sys/types.h>
30 #include <arpa/inet.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
44 #include "usbip_common.h"
48 #define PROGNAME "usbipd"
53 static const char usbip_version_string[] = PACKAGE_STRING;
55 static const char usbipd_help_string[] =
56 "usage: usbipd [options] \n"
58 " Run as a daemon process. \n"
61 " Print debugging information. \n"
64 " Print this help. \n"
69 static void usbipd_help(
void)
71 printf(
"%s\n", usbipd_help_string);
74 static int recv_request_import(
int sockfd)
85 memset(&reply, 0,
sizeof(reply));
89 dbg(
"usbip_net_recv failed: import request");
97 info(
"found requested device: %s",
req.busid);
112 info(
"requested device not found: %s",
req.busid);
124 dbg(
"import request busid %s: failed",
req.busid);
128 memcpy(&pdu_udev, &edev->
udev,
sizeof(pdu_udev));
133 dbg(
"usbip_net_send failed: devinfo");
137 dbg(
"import request busid %s: complete",
req.busid);
142 static int send_reply_devlist(
int connfd)
157 info(
"exportable devices: %d", reply.ndev);
175 memcpy(&pdu_udev, &edev->
udev,
sizeof(pdu_udev));
180 dbg(
"usbip_net_send failed: pdu_udev");
184 for (i = 0; i < edev->
udev.bNumInterfaces; i++) {
186 memcpy(&pdu_uinf, &edev->
uinf[i],
sizeof(pdu_uinf));
192 dbg(
"usbip_net_send failed: pdu_uinf");
201 static int recv_request_devlist(
int connfd)
210 dbg(
"usbip_net_recv failed: devlist request");
214 rc = send_reply_devlist(connfd);
216 dbg(
"send_reply_devlist failed");
223 static int recv_pdu(
int connfd)
230 dbg(
"could not receive opcode: %#0x", code);
236 dbg(
"could not refresh device list: %d", ret);
240 info(
"received request: %#0x(%d)", code, connfd);
243 ret = recv_request_devlist(connfd);
246 ret = recv_request_import(connfd);
251 err(
"received an unknown opcode: %#0x", code);
256 info(
"request %#0x(%d): complete", code, connfd);
258 info(
"request %#0x(%d): failed", code, connfd);
264 static int tcpd_auth(
int connfd)
279 static int do_accept(
int listenfd)
283 socklen_t
len =
sizeof(
ss);
284 char host[NI_MAXHOST],
port[NI_MAXSERV];
289 connfd = accept(listenfd, (
struct sockaddr *) &
ss, &len);
291 err(
"failed to accept connection");
295 rc = getnameinfo((
struct sockaddr *) &
ss, len, host,
sizeof(host),
296 port,
sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
298 err(
"getnameinfo: %s", gai_strerror(rc));
301 rc = tcpd_auth(connfd);
303 info(
"denied access from %s", host);
308 info(
"connection from %s:%s", host, port);
314 gpointer unused_data)
321 if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
322 err(
"unknown condition");
326 if (condition & G_IO_IN) {
327 listenfd = g_io_channel_unix_get_fd(gio);
328 connfd = do_accept(listenfd);
339 static void log_addrinfo(
struct addrinfo *ai)
341 char hbuf[NI_MAXHOST];
342 char sbuf[NI_MAXSERV];
345 rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf,
sizeof(hbuf),
346 sbuf,
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
348 err(
"getnameinfo: %s", gai_strerror(rc));
350 info(
"listening on %s:%s", hbuf, sbuf);
353 static int listen_all_addrinfo(
struct addrinfo *ai_head,
int sockfdlist[])
356 int ret, nsockfd = 0;
358 for (ai = ai_head; ai && nsockfd <
MAXSOCKFD; ai = ai->ai_next) {
359 sockfdlist[nsockfd] =
socket(ai->ai_family, ai->ai_socktype,
361 if (sockfdlist[nsockfd] < 0)
367 if (sockfdlist[nsockfd] >= FD_SETSIZE) {
368 close(sockfdlist[nsockfd]);
369 sockfdlist[nsockfd] = -1;
373 ret = bind(sockfdlist[nsockfd], ai->ai_addr, ai->ai_addrlen);
375 close(sockfdlist[nsockfd]);
376 sockfdlist[nsockfd] = -1;
380 ret = listen(sockfdlist[nsockfd],
SOMAXCONN);
382 close(sockfdlist[nsockfd]);
383 sockfdlist[nsockfd] = -1;
394 dbg(
"listening on %d address%s", nsockfd, (nsockfd == 1) ?
"" :
"es");
399 static struct addrinfo *do_getaddrinfo(
char *host,
int ai_family)
401 struct addrinfo hints, *ai_head;
404 memset(&hints, 0,
sizeof(hints));
405 hints.ai_family = ai_family;
407 hints.ai_flags = AI_PASSIVE;
419 static void signal_handler(
int i)
421 dbg(
"received signal: code %d", i);
427 static void set_signal(
void)
431 memset(&act, 0,
sizeof(act));
432 act.sa_handler = signal_handler;
433 sigemptyset(&act.sa_mask);
438 static int do_standalone_mode(gboolean
daemonize)
440 struct addrinfo *ai_head;
455 if (daemon(0,0) < 0) {
468 info(
"starting " PROGNAME " (%s)", usbip_version_string);
470 nsockfd = listen_all_addrinfo(ai_head, sockfdlist);
472 err(
"failed to open a listening socket");
476 for (i = 0; i < nsockfd; i++) {
479 gio = g_io_channel_unix_new(sockfdlist[i]);
480 g_io_add_watch(gio, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
489 freeaddrinfo(ai_head);
498 static const struct option longopts[] = {
499 {
"daemon", no_argument,
NULL,
'D' },
500 {
"debug", no_argument,
NULL,
'd' },
501 {
"help", no_argument,
NULL,
'h' },
502 {
"version", no_argument,
NULL,
'v' },
507 cmd_standalone_mode = 1,
512 gboolean daemonize =
FALSE;
519 err(
"not running as root?");
521 cmd = cmd_standalone_mode;
523 opt = getopt_long(argc, argv,
"Ddhv", longopts,
NULL);
549 case cmd_standalone_mode:
550 rc = do_standalone_mode(daemonize);
566 return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);