~ubuntu-branches/ubuntu/quantal/linux-linaro-mx51/quantal

« back to all changes in this revision

Viewing changes to drivers/staging/usbip/userspace/src/usbipd.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-3o58a3c1bj7x00rs
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

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