Linux-libre 3.4.39-gnu1
[librecmc/linux-libre.git] / drivers / staging / usbip / userspace / src / usbipd.c
1 /*
2  * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3  *               2005-2007 Takahiro Hirofuchi
4  *
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.
9  *
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.
14  *
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/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include "../config.h"
21 #endif
22
23 #include <errno.h>
24 #include <unistd.h>
25 #include <netdb.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <arpa/inet.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33
34 #ifdef HAVE_LIBWRAP
35 #include <tcpd.h>
36 #endif
37
38 #define _GNU_SOURCE
39 #include <getopt.h>
40 #include <glib.h>
41 #include <signal.h>
42
43 #include "usbip_host_driver.h"
44 #include "usbip_common.h"
45 #include "usbip_network.h"
46
47 #undef  PROGNAME
48 #define PROGNAME "usbipd"
49 #define MAXSOCKFD 20
50
51 GMainLoop *main_loop;
52
53 static const char usbip_version_string[] = PACKAGE_STRING;
54
55 static const char usbipd_help_string[] =
56         "usage: usbipd [options]                        \n"
57         "       -D, --daemon                            \n"
58         "               Run as a daemon process.        \n"
59         "                                               \n"
60         "       -d, --debug                             \n"
61         "               Print debugging information.    \n"
62         "                                               \n"
63         "       -h, --help                              \n"
64         "               Print this help.                \n"
65         "                                               \n"
66         "       -v, --version                           \n"
67         "               Show version.                   \n";
68
69 static void usbipd_help(void)
70 {
71         printf("%s\n", usbipd_help_string);
72 }
73
74 static int recv_request_import(int sockfd)
75 {
76         struct op_import_request req;
77         struct op_common reply;
78         struct usbip_exported_device *edev;
79         struct usbip_usb_device pdu_udev;
80         int found = 0;
81         int error = 0;
82         int rc;
83
84         memset(&req, 0, sizeof(req));
85         memset(&reply, 0, sizeof(reply));
86
87         rc = usbip_net_recv(sockfd, &req, sizeof(req));
88         if (rc < 0) {
89                 dbg("usbip_net_recv failed: import request");
90                 return -1;
91         }
92         PACK_OP_IMPORT_REQUEST(0, &req);
93
94         dlist_for_each_data(host_driver->edev_list, edev,
95                             struct usbip_exported_device) {
96                 if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) {
97                         info("found requested device: %s", req.busid);
98                         found = 1;
99                         break;
100                 }
101         }
102
103         if (found) {
104                 /* should set TCP_NODELAY for usbip */
105                 usbip_net_set_nodelay(sockfd);
106
107                 /* export device needs a TCP/IP socket descriptor */
108                 rc = usbip_host_export_device(edev, sockfd);
109                 if (rc < 0)
110                         error = 1;
111         } else {
112                 info("requested device not found: %s", req.busid);
113                 error = 1;
114         }
115
116         rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT,
117                                       (!error ? ST_OK : ST_NA));
118         if (rc < 0) {
119                 dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT);
120                 return -1;
121         }
122
123         if (error) {
124                 dbg("import request busid %s: failed", req.busid);
125                 return -1;
126         }
127
128         memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
129         usbip_net_pack_usb_device(1, &pdu_udev);
130
131         rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev));
132         if (rc < 0) {
133                 dbg("usbip_net_send failed: devinfo");
134                 return -1;
135         }
136
137         dbg("import request busid %s: complete", req.busid);
138
139         return 0;
140 }
141
142 static int send_reply_devlist(int connfd)
143 {
144         struct usbip_exported_device *edev;
145         struct usbip_usb_device pdu_udev;
146         struct usbip_usb_interface pdu_uinf;
147         struct op_devlist_reply reply;
148         int i;
149         int rc;
150
151         reply.ndev = 0;
152         /* number of exported devices */
153         dlist_for_each_data(host_driver->edev_list, edev,
154                             struct usbip_exported_device) {
155                 reply.ndev += 1;
156         }
157         info("exportable devices: %d", reply.ndev);
158
159         rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK);
160         if (rc < 0) {
161                 dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST);
162                 return -1;
163         }
164         PACK_OP_DEVLIST_REPLY(1, &reply);
165
166         rc = usbip_net_send(connfd, &reply, sizeof(reply));
167         if (rc < 0) {
168                 dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST);
169                 return -1;
170         }
171
172         dlist_for_each_data(host_driver->edev_list, edev,
173                             struct usbip_exported_device) {
174                 dump_usb_device(&edev->udev);
175                 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
176                 usbip_net_pack_usb_device(1, &pdu_udev);
177
178                 rc = usbip_net_send(connfd, &pdu_udev, sizeof(pdu_udev));
179                 if (rc < 0) {
180                         dbg("usbip_net_send failed: pdu_udev");
181                         return -1;
182                 }
183
184                 for (i = 0; i < edev->udev.bNumInterfaces; i++) {
185                         dump_usb_interface(&edev->uinf[i]);
186                         memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf));
187                         usbip_net_pack_usb_interface(1, &pdu_uinf);
188
189                         rc = usbip_net_send(connfd, &pdu_uinf,
190                                             sizeof(pdu_uinf));
191                         if (rc < 0) {
192                                 dbg("usbip_net_send failed: pdu_uinf");
193                                 return -1;
194                         }
195                 }
196         }
197
198         return 0;
199 }
200
201 static int recv_request_devlist(int connfd)
202 {
203         struct op_devlist_request req;
204         int rc;
205
206         memset(&req, 0, sizeof(req));
207
208         rc = usbip_net_recv(connfd, &req, sizeof(req));
209         if (rc < 0) {
210                 dbg("usbip_net_recv failed: devlist request");
211                 return -1;
212         }
213
214         rc = send_reply_devlist(connfd);
215         if (rc < 0) {
216                 dbg("send_reply_devlist failed");
217                 return -1;
218         }
219
220         return 0;
221 }
222
223 static int recv_pdu(int connfd)
224 {
225         uint16_t code = OP_UNSPEC;
226         int ret;
227
228         ret = usbip_net_recv_op_common(connfd, &code);
229         if (ret < 0) {
230                 dbg("could not receive opcode: %#0x", code);
231                 return -1;
232         }
233
234         ret = usbip_host_refresh_device_list();
235         if (ret < 0) {
236                 dbg("could not refresh device list: %d", ret);
237                 return -1;
238         }
239
240         info("received request: %#0x(%d)", code, connfd);
241         switch (code) {
242         case OP_REQ_DEVLIST:
243                 ret = recv_request_devlist(connfd);
244                 break;
245         case OP_REQ_IMPORT:
246                 ret = recv_request_import(connfd);
247                 break;
248         case OP_REQ_DEVINFO:
249         case OP_REQ_CRYPKEY:
250         default:
251                 err("received an unknown opcode: %#0x", code);
252                 ret = -1;
253         }
254
255         if (ret == 0)
256                 info("request %#0x(%d): complete", code, connfd);
257         else
258                 info("request %#0x(%d): failed", code, connfd);
259
260         return ret;
261 }
262
263 #ifdef HAVE_LIBWRAP
264 static int tcpd_auth(int connfd)
265 {
266         struct request_info request;
267         int rc;
268
269         request_init(&request, RQ_DAEMON, PROGNAME, RQ_FILE, connfd, 0);
270         fromhost(&request);
271         rc = hosts_access(&request);
272         if (rc == 0)
273                 return -1;
274
275         return 0;
276 }
277 #endif
278
279 static int do_accept(int listenfd)
280 {
281         int connfd;
282         struct sockaddr_storage ss;
283         socklen_t len = sizeof(ss);
284         char host[NI_MAXHOST], port[NI_MAXSERV];
285         int rc;
286
287         memset(&ss, 0, sizeof(ss));
288
289         connfd = accept(listenfd, (struct sockaddr *) &ss, &len);
290         if (connfd < 0) {
291                 err("failed to accept connection");
292                 return -1;
293         }
294
295         rc = getnameinfo((struct sockaddr *) &ss, len, host, sizeof(host),
296                          port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
297         if (rc)
298                 err("getnameinfo: %s", gai_strerror(rc));
299
300 #ifdef HAVE_LIBWRAP
301         rc = tcpd_auth(connfd);
302         if (rc < 0) {
303                 info("denied access from %s", host);
304                 close(connfd);
305                 return -1;
306         }
307 #endif
308         info("connection from %s:%s", host, port);
309
310         return connfd;
311 }
312
313 gboolean process_request(GIOChannel *gio, GIOCondition condition,
314                          gpointer unused_data)
315 {
316         int listenfd;
317         int connfd;
318
319         (void) unused_data;
320
321         if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
322                 err("unknown condition");
323                 BUG();
324         }
325
326         if (condition & G_IO_IN) {
327                 listenfd = g_io_channel_unix_get_fd(gio);
328                 connfd = do_accept(listenfd);
329                 if (connfd < 0)
330                         return TRUE;
331
332                 recv_pdu(connfd);
333                 close(connfd);
334         }
335
336         return TRUE;
337 }
338
339 static void log_addrinfo(struct addrinfo *ai)
340 {
341         char hbuf[NI_MAXHOST];
342         char sbuf[NI_MAXSERV];
343         int rc;
344
345         rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf),
346                          sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
347         if (rc)
348                 err("getnameinfo: %s", gai_strerror(rc));
349
350         info("listening on %s:%s", hbuf, sbuf);
351 }
352
353 static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[])
354 {
355         struct addrinfo *ai;
356         int ret, nsockfd = 0;
357
358         for (ai = ai_head; ai && nsockfd < MAXSOCKFD; ai = ai->ai_next) {
359                 sockfdlist[nsockfd] = socket(ai->ai_family, ai->ai_socktype,
360                                              ai->ai_protocol);
361                 if (sockfdlist[nsockfd] < 0)
362                         continue;
363
364                 usbip_net_set_reuseaddr(sockfdlist[nsockfd]);
365                 usbip_net_set_nodelay(sockfdlist[nsockfd]);
366
367                 if (sockfdlist[nsockfd] >= FD_SETSIZE) {
368                         close(sockfdlist[nsockfd]);
369                         sockfdlist[nsockfd] = -1;
370                         continue;
371                 }
372
373                 ret = bind(sockfdlist[nsockfd], ai->ai_addr, ai->ai_addrlen);
374                 if (ret < 0) {
375                         close(sockfdlist[nsockfd]);
376                         sockfdlist[nsockfd] = -1;
377                         continue;
378                 }
379
380                 ret = listen(sockfdlist[nsockfd], SOMAXCONN);
381                 if (ret < 0) {
382                         close(sockfdlist[nsockfd]);
383                         sockfdlist[nsockfd] = -1;
384                         continue;
385                 }
386
387                 log_addrinfo(ai);
388                 nsockfd++;
389         }
390
391         if (nsockfd == 0)
392                 return -1;
393
394         dbg("listening on %d address%s", nsockfd, (nsockfd == 1) ? "" : "es");
395
396         return nsockfd;
397 }
398
399 static struct addrinfo *do_getaddrinfo(char *host, int ai_family)
400 {
401         struct addrinfo hints, *ai_head;
402         int rc;
403
404         memset(&hints, 0, sizeof(hints));
405         hints.ai_family   = ai_family;
406         hints.ai_socktype = SOCK_STREAM;
407         hints.ai_flags    = AI_PASSIVE;
408
409         rc = getaddrinfo(host, USBIP_PORT_STRING, &hints, &ai_head);
410         if (rc) {
411                 err("failed to get a network address %s: %s", USBIP_PORT_STRING,
412                     gai_strerror(rc));
413                 return NULL;
414         }
415
416         return ai_head;
417 }
418
419 static void signal_handler(int i)
420 {
421         dbg("received signal: code %d", i);
422
423         if (main_loop)
424                 g_main_loop_quit(main_loop);
425 }
426
427 static void set_signal(void)
428 {
429         struct sigaction act;
430
431         memset(&act, 0, sizeof(act));
432         act.sa_handler = signal_handler;
433         sigemptyset(&act.sa_mask);
434         sigaction(SIGTERM, &act, NULL);
435         sigaction(SIGINT, &act, NULL);
436 }
437
438 static int do_standalone_mode(gboolean daemonize)
439 {
440         struct addrinfo *ai_head;
441         int sockfdlist[MAXSOCKFD];
442         int nsockfd;
443         int i;
444
445         if (usbip_names_init(USBIDS_FILE))
446                 err("failed to open %s", USBIDS_FILE);
447
448         if (usbip_host_driver_open()) {
449                 err("please load " USBIP_CORE_MOD_NAME ".ko and "
450                     USBIP_HOST_DRV_NAME ".ko!");
451                 return -1;
452         }
453
454         if (daemonize) {
455                 if (daemon(0,0) < 0) {
456                         err("daemonizing failed: %s", strerror(errno));
457                         return -1;
458                 }
459
460                 usbip_use_syslog = 1;
461         }
462         set_signal();
463
464         ai_head = do_getaddrinfo(NULL, PF_UNSPEC);
465         if (!ai_head)
466                 return -1;
467
468         info("starting " PROGNAME " (%s)", usbip_version_string);
469
470         nsockfd = listen_all_addrinfo(ai_head, sockfdlist);
471         if (nsockfd <= 0) {
472                 err("failed to open a listening socket");
473                 return -1;
474         }
475
476         for (i = 0; i < nsockfd; i++) {
477                 GIOChannel *gio;
478
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),
481                                process_request, NULL);
482         }
483
484         main_loop = g_main_loop_new(FALSE, FALSE);
485         g_main_loop_run(main_loop);
486
487         info("shutting down " PROGNAME);
488
489         freeaddrinfo(ai_head);
490         usbip_host_driver_close();
491         usbip_names_free();
492
493         return 0;
494 }
495
496 int main(int argc, char *argv[])
497 {
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' },
503                 { NULL,      0,           NULL,  0  }
504         };
505
506         enum {
507                 cmd_standalone_mode = 1,
508                 cmd_help,
509                 cmd_version
510         } cmd;
511
512         gboolean daemonize = FALSE;
513         int opt, rc = -1;
514
515         usbip_use_stderr = 1;
516         usbip_use_syslog = 0;
517
518         if (geteuid() != 0)
519                 err("not running as root?");
520
521         cmd = cmd_standalone_mode;
522         for (;;) {
523                 opt = getopt_long(argc, argv, "Ddhv", longopts, NULL);
524
525                 if (opt == -1)
526                         break;
527
528                 switch (opt) {
529                 case 'D':
530                         daemonize = TRUE;
531                         break;
532                 case 'd':
533                         usbip_use_debug = 1;
534                         break;
535                 case 'h':
536                         cmd = cmd_help;
537                         break;
538                 case 'v':
539                         cmd = cmd_version;
540                         break;
541                 case '?':
542                         usbipd_help();
543                 default:
544                         goto err_out;
545                 }
546         }
547
548         switch (cmd) {
549         case cmd_standalone_mode:
550                 rc = do_standalone_mode(daemonize);
551                 break;
552         case cmd_version:
553                 printf(PROGNAME " (%s)\n", usbip_version_string);
554                 rc = 0;
555                 break;
556         case cmd_help:
557                 usbipd_help();
558                 rc = 0;
559                 break;
560         default:
561                 usbipd_help();
562                 goto err_out;
563         }
564
565 err_out:
566         return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);
567 }