2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
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.
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.
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/>.
20 #include "../config.h"
29 #include <sys/types.h>
31 #include <arpa/inet.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
43 #include "usbip_host_driver.h"
44 #include "usbip_common.h"
45 #include "usbip_network.h"
49 #define PROGNAME "usbipd"
52 #define MAIN_LOOP_TIMEOUT 10
54 #define DEFAULT_PID_FILE "/var/run/" PROGNAME ".pid"
56 static const char usbip_version_string
[] = PACKAGE_STRING
;
58 static const char usbipd_help_string
[] =
59 "usage: usbipd [options]\n"
62 " Bind to IPv4. Default is both.\n"
65 " Bind to IPv6. Default is both.\n"
68 " Run as a daemon process.\n"
71 " Print debugging information.\n"
73 " -PFILE, --pid FILE\n"
74 " Write process id to FILE.\n"
75 " If no FILE specified, use " DEFAULT_PID_FILE
"\n"
77 " -tPORT, --tcp-port PORT\n"
78 " Listen on TCP/IP port PORT.\n"
86 static void usbipd_help(void)
88 printf("%s\n", usbipd_help_string
);
91 static int recv_request_import(int sockfd
)
93 struct op_import_request req
;
94 struct usbip_exported_device
*edev
;
95 struct usbip_usb_device pdu_udev
;
101 memset(&req
, 0, sizeof(req
));
103 rc
= usbip_net_recv(sockfd
, &req
, sizeof(req
));
105 dbg("usbip_net_recv failed: import request");
108 PACK_OP_IMPORT_REQUEST(0, &req
);
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
);
120 /* should set TCP_NODELAY for usbip */
121 usbip_net_set_nodelay(sockfd
);
123 /* export device needs a TCP/IP socket descriptor */
124 rc
= usbip_host_export_device(edev
, sockfd
);
128 info("requested device not found: %s", req
.busid
);
132 rc
= usbip_net_send_op_common(sockfd
, OP_REP_IMPORT
,
133 (!error
? ST_OK
: ST_NA
));
135 dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT
);
140 dbg("import request busid %s: failed", req
.busid
);
144 memcpy(&pdu_udev
, &edev
->udev
, sizeof(pdu_udev
));
145 usbip_net_pack_usb_device(1, &pdu_udev
);
147 rc
= usbip_net_send(sockfd
, &pdu_udev
, sizeof(pdu_udev
));
149 dbg("usbip_net_send failed: devinfo");
153 dbg("import request busid %s: complete", req
.busid
);
158 static int send_reply_devlist(int connfd
)
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
;
168 /* number of exported devices */
169 list_for_each(j
, &host_driver
->edev_list
) {
172 info("exportable devices: %d", reply
.ndev
);
174 rc
= usbip_net_send_op_common(connfd
, OP_REP_DEVLIST
, ST_OK
);
176 dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST
);
179 PACK_OP_DEVLIST_REPLY(1, &reply
);
181 rc
= usbip_net_send(connfd
, &reply
, sizeof(reply
));
183 dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST
);
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
);
193 rc
= usbip_net_send(connfd
, &pdu_udev
, sizeof(pdu_udev
));
195 dbg("usbip_net_send failed: pdu_udev");
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
);
204 rc
= usbip_net_send(connfd
, &pdu_uinf
,
207 err("usbip_net_send failed: pdu_uinf");
216 static int recv_request_devlist(int connfd
)
218 struct op_devlist_request req
;
221 memset(&req
, 0, sizeof(req
));
223 rc
= usbip_net_recv(connfd
, &req
, sizeof(req
));
225 dbg("usbip_net_recv failed: devlist request");
229 rc
= send_reply_devlist(connfd
);
231 dbg("send_reply_devlist failed");
238 static int recv_pdu(int connfd
)
240 uint16_t code
= OP_UNSPEC
;
243 ret
= usbip_net_recv_op_common(connfd
, &code
);
245 dbg("could not receive opcode: %#0x", code
);
249 ret
= usbip_host_refresh_device_list();
251 dbg("could not refresh device list: %d", ret
);
255 info("received request: %#0x(%d)", code
, connfd
);
258 ret
= recv_request_devlist(connfd
);
261 ret
= recv_request_import(connfd
);
266 err("received an unknown opcode: %#0x", code
);
271 info("request %#0x(%d): complete", code
, connfd
);
273 info("request %#0x(%d): failed", code
, connfd
);
279 static int tcpd_auth(int connfd
)
281 struct request_info request
;
284 request_init(&request
, RQ_DAEMON
, PROGNAME
, RQ_FILE
, connfd
, 0);
286 rc
= hosts_access(&request
);
294 static int do_accept(int listenfd
)
297 struct sockaddr_storage ss
;
298 socklen_t len
= sizeof(ss
);
299 char host
[NI_MAXHOST
], port
[NI_MAXSERV
];
302 memset(&ss
, 0, sizeof(ss
));
304 connfd
= accept(listenfd
, (struct sockaddr
*)&ss
, &len
);
306 err("failed to accept connection");
310 rc
= getnameinfo((struct sockaddr
*)&ss
, len
, host
, sizeof(host
),
311 port
, sizeof(port
), NI_NUMERICHOST
| NI_NUMERICSERV
);
313 err("getnameinfo: %s", gai_strerror(rc
));
316 rc
= tcpd_auth(connfd
);
318 info("denied access from %s", host
);
323 info("connection from %s:%s", host
, port
);
328 int process_request(int listenfd
)
333 connfd
= do_accept(listenfd
);
346 static void addrinfo_to_text(struct addrinfo
*ai
, char buf
[],
347 const size_t buf_size
)
349 char hbuf
[NI_MAXHOST
];
350 char sbuf
[NI_MAXSERV
];
355 rc
= getnameinfo(ai
->ai_addr
, ai
->ai_addrlen
, hbuf
, sizeof(hbuf
),
356 sbuf
, sizeof(sbuf
), NI_NUMERICHOST
| NI_NUMERICSERV
);
358 err("getnameinfo: %s", gai_strerror(rc
));
360 snprintf(buf
, buf_size
, "%s:%s", hbuf
, sbuf
);
363 static int listen_all_addrinfo(struct addrinfo
*ai_head
, int sockfdlist
[],
367 int ret
, nsockfd
= 0;
368 const size_t ai_buf_size
= NI_MAXHOST
+ NI_MAXSERV
+ 2;
369 char ai_buf
[ai_buf_size
];
371 for (ai
= ai_head
; ai
&& nsockfd
< maxsockfd
; ai
= ai
->ai_next
) {
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
);
378 err("socket: %s: %d (%s)",
379 ai_buf
, errno
, strerror(errno
));
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
);
389 if (sock
>= FD_SETSIZE
) {
390 err("FD_SETSIZE: %s: sock=%d, max=%d",
391 ai_buf
, sock
, FD_SETSIZE
);
396 ret
= bind(sock
, ai
->ai_addr
, ai
->ai_addrlen
);
398 err("bind: %s: %d (%s)",
399 ai_buf
, errno
, strerror(errno
));
404 ret
= listen(sock
, SOMAXCONN
);
406 err("listen: %s: %d (%s)",
407 ai_buf
, errno
, strerror(errno
));
412 info("listening on %s", ai_buf
);
413 sockfdlist
[nsockfd
++] = sock
;
419 static struct addrinfo
*do_getaddrinfo(char *host
, int ai_family
)
421 struct addrinfo hints
, *ai_head
;
424 memset(&hints
, 0, sizeof(hints
));
425 hints
.ai_family
= ai_family
;
426 hints
.ai_socktype
= SOCK_STREAM
;
427 hints
.ai_flags
= AI_PASSIVE
;
429 rc
= getaddrinfo(host
, usbip_port_string
, &hints
, &ai_head
);
431 err("failed to get a network address %s: %s", usbip_port_string
,
439 static void signal_handler(int i
)
441 dbg("received '%s' signal", strsignal(i
));
444 static void set_signal(void)
446 struct sigaction act
;
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
);
457 static const char *pid_file
;
459 static void write_pid_file(void)
462 dbg("creating pid file %s", pid_file
);
465 fp
= fopen(pid_file
, "w");
467 err("pid_file: %s: %d (%s)",
468 pid_file
, errno
, strerror(errno
));
471 fprintf(fp
, "%d\n", getpid());
476 static void remove_pid_file(void)
479 dbg("removing pid file %s", pid_file
);
484 static int do_standalone_mode(int daemonize
, int ipv4
, int ipv6
)
486 struct addrinfo
*ai_head
;
487 int sockfdlist
[MAXSOCKFD
];
491 struct timespec timeout
;
494 if (usbip_host_driver_open()) {
495 err("please load " USBIP_CORE_MOD_NAME
".ko and "
496 USBIP_HOST_DRV_NAME
".ko!");
501 if (daemon(0, 0) < 0) {
502 err("daemonizing failed: %s", strerror(errno
));
503 usbip_host_driver_close();
507 usbip_use_syslog
= 1;
512 info("starting " PROGNAME
" (%s)", usbip_version_string
);
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.
526 ai_head
= do_getaddrinfo(NULL
, family
);
528 usbip_host_driver_close();
531 nsockfd
= listen_all_addrinfo(ai_head
, sockfdlist
,
532 sizeof(sockfdlist
) / sizeof(*sockfdlist
));
533 freeaddrinfo(ai_head
);
535 err("failed to open a listening socket");
536 usbip_host_driver_close();
540 dbg("listening on %d address%s", nsockfd
, (nsockfd
== 1) ? "" : "es");
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
;
547 timeout
.tv_sec
= MAIN_LOOP_TIMEOUT
;
550 sigfillset(&sigmask
);
551 sigdelset(&sigmask
, SIGTERM
);
552 sigdelset(&sigmask
, SIGINT
);
558 r
= ppoll(fds
, nsockfd
, &timeout
, &sigmask
);
560 dbg("%s", strerror(errno
));
563 for (i
= 0; i
< nsockfd
; i
++) {
564 if (fds
[i
].revents
& POLLIN
) {
565 dbg("read event on fd[%d]=%d",
567 process_request(sockfdlist
[i
]);
571 dbg("heartbeat timeout on ppoll()");
575 info("shutting down " PROGNAME
);
577 usbip_host_driver_close();
582 int main(int argc
, char *argv
[])
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' },
598 cmd_standalone_mode
= 1,
604 int ipv4
= 0, ipv6
= 0;
609 usbip_use_stderr
= 1;
610 usbip_use_syslog
= 0;
613 err("not running as root?");
615 cmd
= cmd_standalone_mode
;
617 opt
= getopt_long(argc
, argv
, "46DdP::t:hv", longopts
, NULL
);
639 pid_file
= optarg
? optarg
: DEFAULT_PID_FILE
;
642 usbip_setup_port_number(optarg
);
658 case cmd_standalone_mode
:
659 rc
= do_standalone_mode(daemonize
, ipv4
, ipv6
);
663 printf(PROGNAME
" (%s)\n", usbip_version_string
);
676 return (rc
> -1 ? EXIT_SUCCESS
: EXIT_FAILURE
);