~smb/ubuntu/oneiric/iscsitarget/proposed

« back to all changes in this revision

Viewing changes to .pc/debian-changes-1.4.20.2-5/usr/ietd.c

  • Committer: Stefan Bader
  • Date: 2011-06-29 11:04:54 UTC
  • mfrom: (2.1.13 experimental)
  • Revision ID: stefan.bader@canonical.com-20110629110454-zgjumob6217p3p1a
* Resynchronise with Debian experimental. Remaining changes:
  - If module unloading fails after stopping ietd, report it but still
    exit zero since this doesn't justify causing package operations to
    fail.
  - Install README.initiators and README.mcs.
* Sync to 1.4.20 branch. This is equivalent of 1.4.20.3 and includes all
  commits up till revision 1.4.20@453
* Add linux-headers packages to Suggests (Closes: #628428)
* Sync to 1.4.20 branch. This is equivalent of 1.4.20.3 and includes all
  commits up till revision 1.4.20@445
  (Closes: #618682, #622318, #610309)
* Last upload was incorrect. Really upload to unstable now
* Upload to unstable
* NIPQUAD definition has been removed in kernel 2.6.36,
  adjust kernel/conn.c accordingly so iscsitarget compiles
  against kernel 2.6.36. (Closes: #604641)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2002-2003 Ardis Technolgies <roman@ardistech.com>
 
3
 *
 
4
 * Released under the terms of the GNU GPL v2.0.
 
5
 */
 
6
 
 
7
#include <ctype.h>
 
8
#include <errno.h>
 
9
#include <fcntl.h>
 
10
#include <stdio.h>
 
11
#include <stdlib.h>
 
12
#include <string.h>
 
13
#include <unistd.h>
 
14
#include <getopt.h>
 
15
#include <netdb.h>
 
16
#include <signal.h>
 
17
 
 
18
#include <sys/poll.h>
 
19
#include <sys/socket.h>
 
20
#include <sys/stat.h>
 
21
#include <sys/types.h>
 
22
#include <sys/un.h>
 
23
 
 
24
#include <netinet/in.h>
 
25
#include <netinet/tcp.h>
 
26
#include <netinet/ip.h>
 
27
#include <arpa/inet.h>
 
28
 
 
29
#include "iscsid.h"
 
30
#include "ietadm.h"
 
31
 
 
32
static char* server_address;
 
33
uint16_t server_port = ISCSI_LISTEN_PORT;
 
34
 
 
35
struct pollfd poll_array[POLL_MAX];
 
36
static struct connection *incoming[INCOMING_MAX];
 
37
static int incoming_cnt;
 
38
int ctrl_fd, ipc_fd, nl_fd;
 
39
 
 
40
static char program_name[] = "iscsid";
 
41
 
 
42
static struct option const long_options[] =
 
43
{
 
44
        {"config", required_argument, 0, 'c'},
 
45
        {"foreground", no_argument, 0, 'f'},
 
46
        {"debug", required_argument, 0, 'd'},
 
47
        {"uid", required_argument, 0, 'u'},
 
48
        {"gid", required_argument, 0, 'g'},
 
49
        {"address", required_argument, 0, 'a'},
 
50
        {"port", required_argument, 0, 'p'},
 
51
        {"version", no_argument, 0, 'v'},
 
52
        {"help", no_argument, 0, 'h'},
 
53
        {0, 0, 0, 0},
 
54
};
 
55
 
 
56
/* This will be configurable by command line options */
 
57
extern struct config_operations plain_ops;
 
58
struct config_operations *cops = &plain_ops;
 
59
 
 
60
static void usage(int status)
 
61
{
 
62
        if (status != 0)
 
63
                fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
 
64
        else {
 
65
                printf("Usage: %s [OPTION]\n", program_name);
 
66
                printf("\
 
67
iSCSI target daemon.\n\
 
68
  -c, --config=[path]     Execute in the config file.\n");
 
69
                printf("\
 
70
  -f, --foreground        make the program run in the foreground\n\
 
71
  -d, --debug debuglevel  print debugging information\n\
 
72
  -u, --uid=uid           run as uid, default is current user\n\
 
73
  -g, --gid=gid           run as gid, default is current user group\n\
 
74
  -a, --address=address   listen on specified local address instead of all\n\
 
75
  -p, --port=port         listen on specified port instead of 3260\n\
 
76
  -h, --help              display this help and exit\n\
 
77
");
 
78
        }
 
79
        exit(1);
 
80
}
 
81
 
 
82
static int check_version(void)
 
83
{
 
84
        struct module_info info;
 
85
        int err;
 
86
 
 
87
        memset(&info, 0x0, sizeof(info));
 
88
 
 
89
        err = ki->module_info(&info);
 
90
        if (err)
 
91
                return 0;
 
92
 
 
93
        return !strncmp(info.version, IET_VERSION_STRING, sizeof(info.version));
 
94
}
 
95
 
 
96
static void set_non_blocking(int fd)
 
97
{
 
98
        int res = fcntl(fd, F_GETFL);
 
99
 
 
100
        if (res != -1) {
 
101
                res = fcntl(fd, F_SETFL, res | O_NONBLOCK);
 
102
                if (res)
 
103
                        log_warning("unable to set fd flags (%s)!", strerror(errno));
 
104
        } else
 
105
                log_warning("unable to get fd flags (%s)!", strerror(errno));
 
106
}
 
107
 
 
108
static void create_listen_socket(struct pollfd *array)
 
109
{
 
110
        struct addrinfo hints, *res, *res0;
 
111
        char servname[64];
 
112
        int i, sock, opt;
 
113
 
 
114
        memset(servname, 0, sizeof(servname));
 
115
        snprintf(servname, sizeof(servname), "%d", server_port);
 
116
 
 
117
        memset(&hints, 0, sizeof(hints));
 
118
        hints.ai_socktype = SOCK_STREAM;
 
119
        hints.ai_flags = AI_PASSIVE;
 
120
 
 
121
        if (getaddrinfo(server_address, servname, &hints, &res0)) {
 
122
                log_error("unable to get address info (%s)!",
 
123
                        (errno == EAI_SYSTEM) ? strerror(errno) :
 
124
                                                gai_strerror(errno));
 
125
                exit(1);
 
126
        }
 
127
 
 
128
        for (i = 0, res = res0; res && i < LISTEN_MAX; i++, res = res->ai_next) {
 
129
                sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 
130
                if (sock < 0) {
 
131
                        log_error("unable to create server socket (%s) %d %d %d!",
 
132
                                  strerror(errno), res->ai_family,
 
133
                                  res->ai_socktype, res->ai_protocol);
 
134
                        continue;
 
135
                }
 
136
 
 
137
                opt = 1;
 
138
                if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)))
 
139
                        log_warning("unable to set SO_KEEPALIVE on server socket (%s)!",
 
140
                                    strerror(errno));
 
141
 
 
142
                opt = 1;
 
143
                if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
 
144
                        log_warning("unable to set SO_REUSEADDR on server socket (%s)!",
 
145
                                    strerror(errno));
 
146
 
 
147
                opt = 1;
 
148
                if (res->ai_family == AF_INET6 &&
 
149
                    setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)))
 
150
                        continue;
 
151
 
 
152
                if (bind(sock, res->ai_addr, res->ai_addrlen)) {
 
153
                        log_error("unable to bind server socket (%s)!", strerror(errno));
 
154
                        continue;
 
155
                }
 
156
 
 
157
                if (listen(sock, INCOMING_MAX)) {
 
158
                        log_error("unable to listen to server socket (%s)!", strerror(errno));
 
159
                        continue;
 
160
                }
 
161
 
 
162
                set_non_blocking(sock);
 
163
 
 
164
                array[i].fd = sock;
 
165
                array[i].events = POLLIN;
 
166
        }
 
167
 
 
168
        freeaddrinfo(res0);
 
169
}
 
170
 
 
171
static void accept_connection(int listen)
 
172
{
 
173
        struct sockaddr_storage from;
 
174
        socklen_t namesize;
 
175
        struct pollfd *pollfd;
 
176
        struct connection *conn;
 
177
        int fd, i;
 
178
 
 
179
        namesize = sizeof(from);
 
180
        if ((fd = accept(listen, (struct sockaddr *) &from, &namesize)) < 0) {
 
181
                if (errno != EINTR && errno != EAGAIN) {
 
182
                        perror("accept(incoming_socket)");
 
183
                        exit(1);
 
184
                }
 
185
                return;
 
186
        }
 
187
 
 
188
        for (i = 0; i < INCOMING_MAX; i++) {
 
189
                if (!incoming[i])
 
190
                        break;
 
191
        }
 
192
        if (i >= INCOMING_MAX) {
 
193
                log_error("unable to find incoming slot? %d\n", i);
 
194
                exit(1);
 
195
        }
 
196
 
 
197
        if (!(conn = conn_alloc())) {
 
198
                log_error("fail to allocate %s", "conn\n");
 
199
                exit(1);
 
200
        }
 
201
        conn->fd = fd;
 
202
        incoming[i] = conn;
 
203
        conn_read_pdu(conn);
 
204
 
 
205
        set_non_blocking(fd);
 
206
        pollfd = &poll_array[POLL_INCOMING + i];
 
207
        pollfd->fd = fd;
 
208
        pollfd->events = POLLIN;
 
209
        pollfd->revents = 0;
 
210
 
 
211
        incoming_cnt++;
 
212
        if (incoming_cnt >= INCOMING_MAX)
 
213
                poll_array[POLL_LISTEN].events = 0;
 
214
}
 
215
 
 
216
static void __set_fd(int idx, int fd)
 
217
{
 
218
        poll_array[idx].fd = fd;
 
219
        poll_array[idx].events = fd ? POLLIN : 0;
 
220
}
 
221
 
 
222
void isns_set_fd(int isns, int scn_listen, int scn)
 
223
{
 
224
        __set_fd(POLL_ISNS, isns);
 
225
        __set_fd(POLL_SCN_LISTEN, scn_listen);
 
226
        __set_fd(POLL_SCN, scn);
 
227
}
 
228
 
 
229
void event_loop(int timeout)
 
230
{
 
231
        int res, i, opt;
 
232
        struct connection *conn;
 
233
        struct pollfd *pollfd;
 
234
 
 
235
        create_listen_socket(poll_array + POLL_LISTEN);
 
236
 
 
237
        poll_array[POLL_IPC].fd = ipc_fd;
 
238
        poll_array[POLL_IPC].events = POLLIN;
 
239
        poll_array[POLL_NL].fd = nl_fd;
 
240
        poll_array[POLL_NL].events = POLLIN;
 
241
 
 
242
        for (i = 0; i < INCOMING_MAX; i++) {
 
243
                poll_array[POLL_INCOMING + i].fd = -1;
 
244
                poll_array[POLL_INCOMING + i].events = 0;
 
245
                incoming[i] = NULL;
 
246
        }
 
247
 
 
248
        while (1) {
 
249
                res = poll(poll_array, POLL_MAX, timeout);
 
250
                if (res == 0) {
 
251
                        isns_handle(1, &timeout);
 
252
                        continue;
 
253
                } else if (res < 0) {
 
254
                        if (res < 0 && errno != EINTR) {
 
255
                                perror("poll()");
 
256
                                exit(1);
 
257
                        }
 
258
                        continue;
 
259
                }
 
260
 
 
261
                for (i = 0; i < LISTEN_MAX; i++) {
 
262
                        if (poll_array[POLL_LISTEN + i].revents
 
263
                            && incoming_cnt < INCOMING_MAX)
 
264
                                accept_connection(poll_array[POLL_LISTEN + i].fd);
 
265
                }
 
266
 
 
267
                if (poll_array[POLL_NL].revents)
 
268
                        handle_iscsi_events(nl_fd);
 
269
 
 
270
                if (poll_array[POLL_IPC].revents)
 
271
                        ietadm_request_handle(ipc_fd);
 
272
 
 
273
                if (poll_array[POLL_ISNS].revents)
 
274
                        isns_handle(0, &timeout);
 
275
 
 
276
                if (poll_array[POLL_SCN_LISTEN].revents)
 
277
                        isns_scn_handle(1);
 
278
 
 
279
                if (poll_array[POLL_SCN].revents)
 
280
                        isns_scn_handle(0);
 
281
 
 
282
                for (i = 0; i < INCOMING_MAX; i++) {
 
283
                        conn = incoming[i];
 
284
                        pollfd = &poll_array[POLL_INCOMING + i];
 
285
                        if (!conn || !pollfd->revents)
 
286
                                continue;
 
287
 
 
288
                        pollfd->revents = 0;
 
289
 
 
290
                        switch (conn->iostate) {
 
291
                        case IOSTATE_READ_BHS:
 
292
                        case IOSTATE_READ_AHS_DATA:
 
293
                        read_again:
 
294
                                res = read(pollfd->fd, conn->buffer, conn->rwsize);
 
295
                                if (res <= 0) {
 
296
                                        if (res == 0 || (errno != EINTR && errno != EAGAIN))
 
297
                                                conn->state = STATE_CLOSE;
 
298
                                        else if (errno == EINTR)
 
299
                                                goto read_again;
 
300
                                        break;
 
301
                                }
 
302
                                conn->rwsize -= res;
 
303
                                conn->buffer += res;
 
304
                                if (conn->rwsize)
 
305
                                        break;
 
306
 
 
307
                                switch (conn->iostate) {
 
308
                                case IOSTATE_READ_BHS:
 
309
                                        conn->iostate = IOSTATE_READ_AHS_DATA;
 
310
                                        conn->req.ahssize = conn->req.bhs.ahslength * 4;
 
311
                                        conn->req.datasize = ((conn->req.bhs.datalength[0] << 16) +
 
312
                                                              (conn->req.bhs.datalength[1] << 8) +
 
313
                                                              conn->req.bhs.datalength[2]);
 
314
                                        conn->rwsize = (conn->req.ahssize + conn->req.datasize + 3) & -4;
 
315
                                        if (conn->rwsize > INCOMING_BUFSIZE) {
 
316
                                                log_warning("Recv PDU with "
 
317
                                                            "invalid size %d "
 
318
                                                            "(max: %d)",
 
319
                                                            conn->rwsize,
 
320
                                                            INCOMING_BUFSIZE);
 
321
                                                conn->state = STATE_CLOSE;
 
322
                                                goto conn_close;
 
323
                                        }
 
324
                                        if (conn->rwsize) {
 
325
                                                if (!conn->req_buffer) {
 
326
                                                        conn->req_buffer = malloc(INCOMING_BUFSIZE);
 
327
                                                        if (!conn->req_buffer) {
 
328
                                                                log_error("Failed to alloc recv buffer");
 
329
                                                                conn->state = STATE_CLOSE;
 
330
                                                                goto conn_close;
 
331
                                                        }
 
332
                                                }
 
333
                                                conn->buffer = conn->req_buffer;
 
334
                                                conn->req.ahs = conn->buffer;
 
335
                                                conn->req.data = conn->buffer + conn->req.ahssize;
 
336
                                                goto read_again;
 
337
                                        }
 
338
 
 
339
                                case IOSTATE_READ_AHS_DATA:
 
340
                                        conn_write_pdu(conn);
 
341
                                        pollfd->events = POLLOUT;
 
342
 
 
343
                                        log_pdu(2, &conn->req);
 
344
                                        if (!cmnd_execute(conn))
 
345
                                                conn->state = STATE_CLOSE;
 
346
                                        break;
 
347
                                }
 
348
                                break;
 
349
 
 
350
                        case IOSTATE_WRITE_BHS:
 
351
                        case IOSTATE_WRITE_AHS:
 
352
                        case IOSTATE_WRITE_DATA:
 
353
                        write_again:
 
354
                                opt = 1;
 
355
                                setsockopt(pollfd->fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
 
356
                                res = write(pollfd->fd, conn->buffer, conn->rwsize);
 
357
                                if (res < 0) {
 
358
                                        if (errno != EINTR && errno != EAGAIN)
 
359
                                                conn->state = STATE_CLOSE;
 
360
                                        else if (errno == EINTR)
 
361
                                                goto write_again;
 
362
                                        break;
 
363
                                }
 
364
 
 
365
                                conn->rwsize -= res;
 
366
                                conn->buffer += res;
 
367
                                if (conn->rwsize)
 
368
                                        goto write_again;
 
369
 
 
370
                                switch (conn->iostate) {
 
371
                                case IOSTATE_WRITE_BHS:
 
372
                                        if (conn->rsp.ahssize) {
 
373
                                                conn->iostate = IOSTATE_WRITE_AHS;
 
374
                                                conn->buffer = conn->rsp.ahs;
 
375
                                                conn->rwsize = conn->rsp.ahssize;
 
376
                                                goto write_again;
 
377
                                        }
 
378
                                case IOSTATE_WRITE_AHS:
 
379
                                        if (conn->rsp.datasize) {
 
380
                                                int o;
 
381
 
 
382
                                                conn->iostate = IOSTATE_WRITE_DATA;
 
383
                                                conn->buffer = conn->rsp.data;
 
384
                                                conn->rwsize = conn->rsp.datasize;
 
385
                                                o = conn->rwsize & 3;
 
386
                                                if (o) {
 
387
                                                        for (o = 4 - o; o; o--)
 
388
                                                                *((u8 *)conn->buffer + conn->rwsize++) = 0;
 
389
                                                }
 
390
                                                goto write_again;
 
391
                                        }
 
392
                                case IOSTATE_WRITE_DATA:
 
393
                                        opt = 0;
 
394
                                        setsockopt(pollfd->fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
 
395
                                        cmnd_finish(conn);
 
396
 
 
397
                                        switch (conn->state) {
 
398
                                        case STATE_KERNEL:
 
399
                                                conn_take_fd(conn, pollfd->fd);
 
400
                                                conn->state = STATE_CLOSE;
 
401
                                                break;
 
402
                                        case STATE_EXIT:
 
403
                                        case STATE_CLOSE:
 
404
                                                break;
 
405
                                        default:
 
406
                                                conn_read_pdu(conn);
 
407
                                                pollfd->events = POLLIN;
 
408
                                                break;
 
409
                                        }
 
410
                                        break;
 
411
                                }
 
412
 
 
413
                                break;
 
414
                        default:
 
415
                                log_error("illegal iostate %d for port %d!\n", conn->iostate, i);
 
416
                                exit(1);
 
417
                        }
 
418
 
 
419
                conn_close:
 
420
                        if (conn->state == STATE_CLOSE) {
 
421
                                struct session *session = conn->session;
 
422
                                log_debug(1, "connection closed");
 
423
                                conn_free_pdu(conn);
 
424
                                conn_free(conn);
 
425
                                close(pollfd->fd);
 
426
                                pollfd->fd = -1;
 
427
                                incoming[i] = NULL;
 
428
                                incoming_cnt--;
 
429
                                if (session && session->conn_cnt <= 0)
 
430
                                        session_remove(session);
 
431
                        }
 
432
                }
 
433
        }
 
434
}
 
435
 
 
436
int main(int argc, char **argv)
 
437
{
 
438
        int ch, longindex, timeout = -1;
 
439
        char *config = NULL, pid_buf[64];
 
440
        uid_t uid = 0;
 
441
        gid_t gid = 0;
 
442
        char *isns = NULL;
 
443
        int isns_ac = 0, pid_fd;
 
444
 
 
445
        /* otherwise we would die in some later write() during the event_loop
 
446
         * instead of getting EPIPE! */
 
447
        signal(SIGPIPE, SIG_IGN);
 
448
 
 
449
        while ((ch = getopt_long(argc, argv, "c:fd:s:u:g:a:p:vh", long_options, &longindex)) >= 0) {
 
450
                switch (ch) {
 
451
                case 'c':
 
452
                        config = optarg;
 
453
                        break;
 
454
                case 'f':
 
455
                        log_daemon = 0;
 
456
                        break;
 
457
                case 'd':
 
458
                        log_level = atoi(optarg);
 
459
                        break;
 
460
                case 'u':
 
461
                        uid = strtoul(optarg, NULL, 10);
 
462
                        break;
 
463
                case 'g':
 
464
                        gid = strtoul(optarg, NULL, 10);
 
465
                        break;
 
466
                case 'a':
 
467
                        server_address = strdup(optarg);
 
468
                        break;
 
469
                case 'p':
 
470
                        server_port = (uint16_t)strtoul(optarg, NULL, 10);
 
471
                        break;
 
472
                case 'v':
 
473
                        printf("%s version %s\n", program_name, IET_VERSION_STRING);
 
474
                        exit(0);
 
475
                        break;
 
476
                case 'h':
 
477
                        usage(0);
 
478
                        break;
 
479
                default:
 
480
                        usage(1);
 
481
                        break;
 
482
                }
 
483
        }
 
484
 
 
485
        if (log_daemon) {
 
486
                pid_t pid;
 
487
 
 
488
                log_init();
 
489
 
 
490
                pid = fork();
 
491
                if (pid < 0) {
 
492
                        log_error("error starting daemon: %m");
 
493
                        exit(-1);
 
494
                } else if (pid)
 
495
                        exit(0);
 
496
 
 
497
                close(0);
 
498
                open("/dev/null", O_RDWR);
 
499
                dup2(0, 1);
 
500
                dup2(0, 2);
 
501
 
 
502
                setsid();
 
503
 
 
504
                if (chdir("/") < 0) {
 
505
                        log_error("failed to set working dir to /: %m");
 
506
                        exit(-1);
 
507
                }
 
508
        }
 
509
 
 
510
        pid_fd = open("/var/run/ietd.pid", O_WRONLY|O_CREAT, 0644);
 
511
        if (pid_fd < 0) {
 
512
                log_error("unable to create pid file: %m");
 
513
                exit(-1);
 
514
        }
 
515
 
 
516
        if (lockf(pid_fd, F_TLOCK, 0) < 0) {
 
517
                log_error("unable to lock pid file: %m");
 
518
                exit(-1);
 
519
        }
 
520
 
 
521
        if (ftruncate(pid_fd, 0) < 0) {
 
522
                log_error("failed to ftruncate the PID file: %m");
 
523
                exit(-1);
 
524
        }
 
525
 
 
526
        sprintf(pid_buf, "%d\n", getpid());
 
527
        if (write(pid_fd, pid_buf, strlen(pid_buf)) < strlen(pid_buf)) {
 
528
                log_error("failed to write PID to PID file: %m");
 
529
                exit(-1);
 
530
        }
 
531
 
 
532
        if ((ipc_fd = ietadm_request_listen()) < 0) {
 
533
                log_error("unable to open ipc fd: %m");
 
534
                exit(-1);
 
535
        }
 
536
 
 
537
        if ((ctrl_fd = ki->ctldev_open()) < 0) {
 
538
                log_error("unable to open ctldev fd: %m");
 
539
                exit(-1);
 
540
        }
 
541
 
 
542
        if (!check_version()) {
 
543
                log_error("kernel module version mismatch!");
 
544
                exit(-1);
 
545
        }
 
546
 
 
547
        if ((nl_fd = nl_open()) < 0) {
 
548
                log_error("unable to open netlink fd: %m");
 
549
                exit(-1);
 
550
        }
 
551
 
 
552
        cops->init(config, &isns, &isns_ac);
 
553
        if (isns)
 
554
                timeout = isns_init(isns, isns_ac);
 
555
 
 
556
        if (gid && setgid(gid) < 0) {
 
557
                log_error("unable to setgid: %m");
 
558
                exit(-1);
 
559
        }
 
560
 
 
561
        if (uid && setuid(uid) < 0) {
 
562
                log_error("unable to setuid: %m");
 
563
                exit(-1);
 
564
        }
 
565
 
 
566
        event_loop(timeout);
 
567
 
 
568
        return 0;
 
569
}