Removed trailing whitespace.
[mirror/scst/.git] / iscsi-scst / usr / iscsi_scstd.c
1 /*
2  *  Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
3  *  Copyright (C) 2007 - 2009 Vladislav Bolkhovitin
4  *  Copyright (C) 2007 - 2009 ID7 Ltd.
5  *
6  *  This program is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU General Public License
8  *  as published by the Free Software Foundation, version 2
9  *  of the License.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  *  GNU General Public License for more details.
15  */
16
17 #include <ctype.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <getopt.h>
25 #include <netdb.h>
26 #include <signal.h>
27
28 #include <sys/poll.h>
29 #include <sys/socket.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <sys/un.h>
33
34 #include <netinet/in.h>
35 #include <netinet/tcp.h>
36 #include <netinet/ip.h>
37 #include <arpa/inet.h>
38
39 #include "iscsid.h"
40 #include "iscsi_adm.h"
41
42 #define LISTEN_MAX              8
43 #define INCOMING_MAX            256
44
45 enum {
46         POLL_LISTEN,
47         POLL_IPC = POLL_LISTEN + LISTEN_MAX,
48         POLL_NL,
49         POLL_ISNS,
50         POLL_SCN_LISTEN,
51         POLL_SCN,
52         POLL_INCOMING,
53         POLL_MAX = POLL_INCOMING + INCOMING_MAX,
54 };
55
56 static char* server_address;
57 uint16_t server_port = ISCSI_LISTEN_PORT;
58
59 static struct pollfd poll_array[POLL_MAX];
60 static struct connection *incoming[INCOMING_MAX];
61 static int incoming_cnt;
62 int ctrl_fd, ipc_fd, nl_fd;
63 int conn_blocked;
64
65 static char program_name[] = "iscsi-scstd";
66
67 static struct option const long_options[] =
68 {
69         {"config", required_argument, 0, 'c'},
70         {"foreground", no_argument, 0, 'f'},
71         {"debug", required_argument, 0, 'd'},
72         {"uid", required_argument, 0, 'u'},
73         {"gid", required_argument, 0, 'g'},
74         {"address", required_argument, 0, 'a'},
75         {"port", required_argument, 0, 'p'},
76         {"version", no_argument, 0, 'v'},
77         {"help", no_argument, 0, 'h'},
78         {0, 0, 0, 0},
79 };
80
81 int init_report_pipe[2];
82
83 static void usage(int status)
84 {
85         if (status != 0)
86                 fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
87         else {
88                 printf("Usage: %s [OPTION]\n", program_name);
89                 printf("\
90 iSCSI target daemon.\n\
91   -c, --config=[path]     Execute in the config file.\n");
92                 printf("\
93   -f, --foreground        make the program run in the foreground\n\
94   -d, --debug debuglevel  print debugging information\n\
95   -u, --uid=uid           run as uid, default is current user\n\
96   -g, --gid=gid           run as gid, default is current user group\n\
97   -a, --address=address   listen on specified local address instead of all\n\
98   -p, --port=port         listen on specified port instead of 3260\n\
99   -h, --help              display this help and exit\n\
100 ");
101         }
102         exit(1);
103 }
104
105 static void set_non_blocking(int fd)
106 {
107         int res = fcntl(fd, F_GETFL);
108
109         if (res != -1) {
110                 res = fcntl(fd, F_SETFL, res | O_NONBLOCK);
111                 if (res)
112                         log_warning("unable to set fd flags (%s)!", strerror(errno));
113         } else
114                 log_warning("unable to get fd flags (%s)!", strerror(errno));
115 }
116
117 static void sock_set_keepalive(int sock, int timeout)
118 {
119         if (timeout) { /* timeout [s] */
120                 int opt = 2;
121
122                 if (setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &opt, sizeof(opt)))
123                         log_warning("unable to set TCP_KEEPCNT on server socket (%s)!", strerror(errno));
124
125                 if (setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &timeout, sizeof(timeout)))
126                         log_warning("unable to set TCP_KEEPIDLE on server socket (%s)!", strerror(errno));
127
128                 opt = 3;
129                 if (setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &opt, sizeof(opt)))
130                         log_warning("unable to set KEEPINTVL on server socket (%s)!", strerror(errno));
131
132                 opt = 1;
133                 if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)))
134                         log_warning("unable to set SO_KEEPALIVE on server socket (%s)!", strerror(errno));
135         }
136 }
137
138 static void create_listen_socket(struct pollfd *array)
139 {
140         struct addrinfo hints, *res, *res0;
141         char servname[64];
142         int i, sock, opt;
143
144         memset(servname, 0, sizeof(servname));
145         snprintf(servname, sizeof(servname), "%d", server_port);
146
147         memset(&hints, 0, sizeof(hints));
148         hints.ai_socktype = SOCK_STREAM;
149         hints.ai_flags = AI_PASSIVE;
150
151         if (getaddrinfo(server_address, servname, &hints, &res0)) {
152                 log_error("Unable to get address info (%s)!", strerror(errno));
153                 exit(1);
154         }
155
156         i = 0;
157         for (res = res0; res && i < LISTEN_MAX; res = res->ai_next) {
158                 sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
159                 if (sock < 0) {
160                         log_error("Unable to create server socket (%s) %d %d %d!",
161                                   strerror(errno), res->ai_family,
162                                   res->ai_socktype, res->ai_protocol);
163                         continue;
164                 }
165
166                 sock_set_keepalive(sock, 50);
167
168                 opt = 1;
169                 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
170                         log_warning("Unable to set SO_REUSEADDR on server socket (%s)!",
171                                     strerror(errno));
172                 opt = 1;
173                 if (res->ai_family == AF_INET6 &&
174                     setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt))) {
175                         log_error("Unable to restrict IPv6 socket (%s)", strerror(errno));
176                         close(sock);
177                         continue;
178                 }
179
180                 if (bind(sock, res->ai_addr, res->ai_addrlen)) {
181                         log_error("Unable to bind server socket (%s)!", strerror(errno));
182                         close(sock);
183                         continue;
184                 }
185
186                 if (listen(sock, INCOMING_MAX)) {
187                         log_error("Unable to listen to server socket (%s)!", strerror(errno));
188                         close(sock);
189                         continue;
190                 }
191
192                 set_non_blocking(sock);
193
194                 array[i].fd = sock;
195                 array[i].events = POLLIN;
196
197                 i++;
198         }
199
200         freeaddrinfo(res0);
201
202         if (i == 0)
203                 exit(1);
204 }
205
206 static void accept_connection(int listen)
207 {
208         struct sockaddr_storage from, to;
209         char portal[50]; /* for full IP6 address + port */
210         socklen_t namesize;
211         struct pollfd *pollfd;
212         struct connection *conn;
213         int fd, i, rc;
214
215         namesize = sizeof(from);
216         if ((fd = accept(listen, (struct sockaddr *)&from, &namesize)) < 0) {
217                 switch (errno) {
218                 case EINTR:
219                 case EAGAIN:
220                 case ENETDOWN:
221                 case EPROTO:
222                 case ENOPROTOOPT:
223                 case EHOSTDOWN:
224                 case ENONET:
225                 case EHOSTUNREACH:
226                 case EOPNOTSUPP:
227                 case ENETUNREACH:
228                         break;
229                 default:
230                         perror("accept(incoming_socket) failed");
231                         exit(1);
232                 }
233                 goto out;
234         }
235
236         namesize = sizeof(to);
237         rc = getsockname(fd, (struct sockaddr *)&to, &namesize);
238         if (rc == 0) {
239                 if (from.ss_family == AF_INET) {
240                         struct sockaddr_in *in = (struct sockaddr_in *)&to;
241                         rc = snprintf(portal, sizeof(portal), "%s:%hu",
242                                 inet_ntoa(in->sin_addr), ntohs(in->sin_port));
243                 } else if (from.ss_family == AF_INET6) {
244                         struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&to;
245                         rc = snprintf(portal, sizeof(portal), "%x:%x:%x:%x:%x:%x:%x:%x.%hu",
246                                 in6->sin6_addr.s6_addr16[7], in6->sin6_addr.s6_addr16[6],
247                                 in6->sin6_addr.s6_addr16[5], in6->sin6_addr.s6_addr16[4],
248                                 in6->sin6_addr.s6_addr16[3], in6->sin6_addr.s6_addr16[2],
249                                 in6->sin6_addr.s6_addr16[1], in6->sin6_addr.s6_addr16[0],
250                                 ntohs(in6->sin6_port));
251                 }
252                 if (rc >= sizeof(portal))
253                         log_error("portal too small %zu (needed %d)", sizeof(portal), rc);
254         } else {
255                 portal[0] = '\0';
256                 perror("getsockname() failed");
257                 goto out_close;
258         }
259
260         if (from.ss_family == AF_INET) {
261                 struct sockaddr_in *in = (struct sockaddr_in *)&from;
262                 log_info("Connect from %s:%hu to %s", inet_ntoa(in->sin_addr),
263                         ntohs(in->sin_port), portal);
264         } else if (from.ss_family == AF_INET6) {
265                 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&from;
266                 log_info("Connect from %x:%x:%x:%x:%x:%x:%x:%x.%hu to %s",
267                         in6->sin6_addr.s6_addr16[7], in6->sin6_addr.s6_addr16[6],
268                         in6->sin6_addr.s6_addr16[5], in6->sin6_addr.s6_addr16[4],
269                         in6->sin6_addr.s6_addr16[3], in6->sin6_addr.s6_addr16[2],
270                         in6->sin6_addr.s6_addr16[1], in6->sin6_addr.s6_addr16[0],
271                         ntohs(in6->sin6_port), portal);
272         }
273
274         if (conn_blocked) {
275                 log_warning("Connection refused due to blocking\n");
276                 goto out_close;
277         }
278
279         for (i = 0; i < INCOMING_MAX; i++) {
280                 if (!incoming[i])
281                         break;
282         }
283         if (i >= INCOMING_MAX) {
284                 log_error("Unable to find incoming slot? %d\n", i);
285                 goto out_close;
286         }
287
288         if (!(conn = conn_alloc())) {
289                 log_error("Fail to allocate %s", "conn\n");
290                 goto out_close;
291         }
292
293         conn->fd = fd;
294         incoming[i] = conn;
295         conn_read_pdu(conn);
296
297         set_non_blocking(fd);
298         pollfd = &poll_array[POLL_INCOMING + i];
299         pollfd->fd = fd;
300         pollfd->events = POLLIN;
301         pollfd->revents = 0;
302
303         incoming_cnt++;
304         if (incoming_cnt >= INCOMING_MAX)
305                 poll_array[POLL_LISTEN].events = 0;
306
307 out:
308         return;
309
310 out_close:
311         close(fd);
312         goto out;
313 }
314
315 static void __set_fd(int idx, int fd)
316 {
317         poll_array[idx].fd = fd;
318         poll_array[idx].events = fd ? POLLIN : 0;
319 }
320
321 void isns_set_fd(int isns, int scn_listen, int scn)
322 {
323         __set_fd(POLL_ISNS, isns);
324         __set_fd(POLL_SCN_LISTEN, scn_listen);
325         __set_fd(POLL_SCN, scn);
326 }
327
328 static void event_conn(struct connection *conn, struct pollfd *pollfd)
329 {
330         int res, opt;
331
332         switch (conn->iostate) {
333         case IOSTATE_READ_BHS:
334         case IOSTATE_READ_AHS_DATA:
335               read_again:
336                 res = read(pollfd->fd, conn->buffer, conn->rwsize);
337                 if (res <= 0) {
338                         if (res == 0 || (errno != EINTR && errno != EAGAIN))
339                                 conn->state = STATE_CLOSE;
340                         else if (errno == EINTR)
341                                 goto read_again;
342                         break;
343                 }
344                 conn->rwsize -= res;
345                 conn->buffer += res;
346                 if (conn->rwsize)
347                         break;
348
349                 switch (conn->iostate) {
350                 case IOSTATE_READ_BHS:
351                         conn->iostate = IOSTATE_READ_AHS_DATA;
352                         conn->req.ahssize = conn->req.bhs.ahslength * 4;
353                         conn->req.datasize = ((conn->req.bhs.datalength[0] << 16) +
354                                               (conn->req.bhs.datalength[1] << 8) +
355                                               conn->req.bhs.datalength[2]);
356                         conn->rwsize = (conn->req.ahssize + conn->req.datasize + 3) & -4;
357                         if (conn->rwsize > INCOMING_BUFSIZE) {
358                                 log_warning("Recv PDU with invalid size %d "
359                                         "(max: %d)", conn->rwsize,
360                                         INCOMING_BUFSIZE);
361                                         conn->state = STATE_CLOSE;
362                                         goto out;
363                         }
364                         if (conn->rwsize) {
365                                 if (!conn->req_buffer) {
366                                         conn->req_buffer = malloc(INCOMING_BUFSIZE);
367                                         if (!conn->req_buffer) {
368                                                 log_error("Failed to alloc recv buffer");
369                                                 conn->state = STATE_CLOSE;
370                                                 goto out;
371                                         }
372                                 }
373                                 conn->buffer = conn->req_buffer;
374                                 conn->req.ahs = conn->buffer;
375                                 conn->req.data = conn->buffer + conn->req.ahssize;
376                                 goto read_again;
377                         }
378
379                 case IOSTATE_READ_AHS_DATA:
380                         conn_write_pdu(conn);
381                         pollfd->events = POLLOUT;
382
383                         log_pdu(2, &conn->req);
384                         if (!cmnd_execute(conn))
385                                 conn->state = STATE_CLOSE;
386                         break;
387                 }
388                 break;
389
390         case IOSTATE_WRITE_BHS:
391         case IOSTATE_WRITE_AHS:
392         case IOSTATE_WRITE_DATA:
393               write_again:
394                 opt = 1;
395                 setsockopt(pollfd->fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
396                 res = write(pollfd->fd, conn->buffer, conn->rwsize);
397                 if (res < 0) {
398                         if (errno != EINTR && errno != EAGAIN)
399                                 conn->state = STATE_CLOSE;
400                         else if (errno == EINTR)
401                                 goto write_again;
402                         break;
403                 }
404
405                 conn->rwsize -= res;
406                 conn->buffer += res;
407                 if (conn->rwsize)
408                         goto write_again;
409
410                 switch (conn->iostate) {
411                 case IOSTATE_WRITE_BHS:
412                         if (conn->rsp.ahssize) {
413                                 conn->iostate = IOSTATE_WRITE_AHS;
414                                 conn->buffer = conn->rsp.ahs;
415                                 conn->rwsize = conn->rsp.ahssize;
416                                 goto write_again;
417                         }
418                 case IOSTATE_WRITE_AHS:
419                         if (conn->rsp.datasize) {
420                                 int o;
421
422                                 conn->iostate = IOSTATE_WRITE_DATA;
423                                 conn->buffer = conn->rsp.data;
424                                 conn->rwsize = conn->rsp.datasize;
425                                 o = conn->rwsize & 3;
426                                 if (o) {
427                                         for (o = 4 - o; o; o--)
428                                                 *((u8 *) conn->buffer + conn->rwsize++) =
429                                                     0;
430                                 }
431                                 goto write_again;
432                         }
433                 case IOSTATE_WRITE_DATA:
434                         opt = 0;
435                         setsockopt(pollfd->fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
436                         cmnd_finish(conn);
437
438                         switch (conn->state) {
439                         case STATE_KERNEL:
440                                 conn_pass_to_kern(conn, pollfd->fd);
441                                 conn->state = STATE_CLOSE;
442                                 break;
443                         case STATE_EXIT:
444                         case STATE_CLOSE:
445                                 break;
446                         default:
447                                 conn_read_pdu(conn);
448                                 pollfd->events = POLLIN;
449                                 break;
450                         }
451                         break;
452                 }
453
454                 break;
455         default:
456                 log_error("illegal iostate %d for port %d!\n", conn->iostate,
457                         pollfd->fd);
458                 exit(1);
459         }
460 out:
461         return;
462 }
463
464 void wait_4_iscsi_event(int timeout)
465 {
466         int res;
467
468         do {
469                 res = poll(&poll_array[POLL_NL], 1, timeout);
470         } while (res < 0 && errno == EINTR);
471
472         if (poll_array[POLL_NL].revents && res > 0)
473                 handle_iscsi_events(nl_fd);
474         else {
475                 log_error("%s: unexpected error %d %d\n", __FUNCTION__, res,
476                         errno);
477         }
478 }
479
480 static void event_loop(int timeout)
481 {
482         int res, i;
483
484         create_listen_socket(poll_array + POLL_LISTEN);
485
486         poll_array[POLL_IPC].fd = ipc_fd;
487         poll_array[POLL_IPC].events = POLLIN;
488         poll_array[POLL_NL].fd = nl_fd;
489         poll_array[POLL_NL].events = POLLIN;
490
491         for (i = 0; i < INCOMING_MAX; i++) {
492                 poll_array[POLL_INCOMING + i].fd = -1;
493                 poll_array[POLL_INCOMING + i].events = 0;
494                 incoming[i] = NULL;
495         }
496
497         close(init_report_pipe[0]);
498         res = 0;
499
500         if (log_daemon)
501                 write(init_report_pipe[1], &res, sizeof(res));
502
503         close(init_report_pipe[1]);
504
505         while (1) {
506                 res = poll(poll_array, POLL_MAX, timeout);
507                 if (res == 0) {
508                         isns_handle(1, &timeout);
509                         continue;
510                 } else if (res < 0) {
511                         if (errno == EINTR)
512                                 continue;
513                         else if (errno == EINVAL)
514                                 log_error("%s: poll() failed with EINVAL. Should "
515                                         "you increase RLIMIT_NOFILE (ulimit -n)? "
516                                         "Or upgrade your kernel? Kernels below 2.6.19 "
517                                         "have a bug, which doesn't allow poll() "
518                                         "to work with >256 file descriptors. See "
519                                         "http://sourceforge.net/mailarchive/forum.php?"
520                                         "thread_name=9392A06CB0FDC847B3A530B3DC174E7B0"
521                                         "55F1EF3%40mse10be1.mse10.exchange.ms&forum_"
522                                         "name=scst-devel for more details. Alternatively, "
523                                         "you can desrease iscsi_scstd.c::INCOMING_MAX "
524                                         "constant to a lower value, e.g. 128, then "
525                                         "recompile and reinstall the user space part "
526                                         "of iSCSI-SCST.", __FUNCTION__);
527                         else
528                                 log_error("%s: poll() failed: %s", __FUNCTION__,
529                                         strerror(errno));
530                         exit(1);
531                 }
532
533                 for (i = 0; i < LISTEN_MAX; i++) {
534                         if (poll_array[POLL_LISTEN + i].revents
535                             && incoming_cnt < INCOMING_MAX)
536                                 accept_connection(poll_array[POLL_LISTEN + i].fd);
537                 }
538
539                 if (poll_array[POLL_NL].revents)
540                         handle_iscsi_events(nl_fd);
541
542                 if (poll_array[POLL_IPC].revents)
543                         iscsi_adm_request_handle(ipc_fd);
544
545                 if (poll_array[POLL_ISNS].revents)
546                         isns_handle(0, &timeout);
547
548                 if (poll_array[POLL_SCN_LISTEN].revents)
549                         isns_scn_handle(1);
550
551                 if (poll_array[POLL_SCN].revents)
552                         isns_scn_handle(0);
553
554                 for (i = 0; i < INCOMING_MAX; i++) {
555                         struct connection *conn = incoming[i];
556                         struct pollfd *pollfd = &poll_array[POLL_INCOMING + i];
557
558                         if (!conn || !pollfd->revents)
559                                 continue;
560
561                         pollfd->revents = 0;
562
563                         event_conn(conn, pollfd);
564
565                         if (conn->state == STATE_CLOSE) {
566                                 log_debug(0, "closing conn %p", conn);
567                                 conn_free_pdu(conn);
568                                 close(pollfd->fd);
569                                 pollfd->fd = -1;
570                                 incoming[i] = NULL;
571                                 incoming_cnt--;
572                         }
573                 }
574         }
575 }
576
577 void init_max_data_seg_len(int max_data_seg_len)
578 {
579         if ((session_keys[key_max_recv_data_length].local_def != -1) ||
580             (session_keys[key_max_recv_data_length].max != -1) ||
581             (session_keys[key_max_xmit_data_length].local_def != -1) ||
582             (session_keys[key_max_xmit_data_length].max != -1) ||
583             (session_keys[key_max_burst_length].local_def != -1) ||
584             (session_keys[key_max_burst_length].max != -1) ||
585             (session_keys[key_first_burst_length].local_def != -1) ||
586             (session_keys[key_first_burst_length].max != -1)) {
587                 log_error("Wrong session_keys initialization");
588                 exit(-1);
589         }
590
591         /* MaxRecvDataSegmentLength */
592         session_keys[key_max_recv_data_length].local_def = max_data_seg_len;
593         session_keys[key_max_recv_data_length].max = max_data_seg_len;
594
595         /* MaxXmitDataSegmentLength */
596         session_keys[key_max_xmit_data_length].local_def = max_data_seg_len;
597         session_keys[key_max_xmit_data_length].max = max_data_seg_len;
598
599         /* MaxBurstLength */
600         session_keys[key_max_burst_length].local_def = max_data_seg_len;
601         session_keys[key_max_burst_length].max = max_data_seg_len;
602
603         /* FirstBurstLength */
604         session_keys[key_first_burst_length].local_def = max_data_seg_len;
605         session_keys[key_first_burst_length].max = max_data_seg_len;
606
607         return;
608 }
609
610 int main(int argc, char **argv)
611 {
612         int ch, longindex, timeout = -1;
613         char *config = NULL;
614         uid_t uid = 0;
615         gid_t gid = 0;
616         char *isns = NULL;
617         int isns_ac = 0;
618         int max_data_seg_len = -1;
619
620         if (pipe(init_report_pipe) == -1) {
621                 perror("pipe failed");
622                 exit(-1);
623         }
624
625         /*
626          * Otherwise we could die in some later write() during the event_loop()
627          * instead of getting EPIPE!
628          */
629         signal(SIGPIPE, SIG_IGN);
630
631         while ((ch = getopt_long(argc, argv, "c:fd:s:u:g:a:p:vh", long_options, &longindex)) >= 0) {
632                 switch (ch) {
633                 case 'c':
634                         config = optarg;
635                         break;
636                 case 'f':
637                         log_daemon = 0;
638                         break;
639                 case 'd':
640                         log_level = strtol(optarg, NULL, 0);
641                         break;
642                 case 'u':
643                         uid = strtoul(optarg, NULL, 0);
644                         break;
645                 case 'g':
646                         gid = strtoul(optarg, NULL, 0);
647                         break;
648                 case 'a':
649                         server_address = strdup(optarg);
650                         if (server_address == NULL) {
651                                 perror("strdup failed");
652                                 exit(-1);
653                         }
654                         break;
655                 case 'p':
656                         server_port = (uint16_t)strtoul(optarg, NULL, 0);
657                         break;
658                 case 'v':
659                         printf("%s version %s\n", program_name, ISCSI_VERSION_STRING);
660                         exit(0);
661                         break;
662                 case 'h':
663                         usage(0);
664                         break;
665                 default:
666                         usage(1);
667                         break;
668                 }
669         }
670
671         if ((nl_fd = nl_open()) < 0) {
672                 perror("netlink open failed");
673                 exit(-1);
674         };
675
676         if ((ctrl_fd = kernel_open(&max_data_seg_len)) < 0)
677                 exit(-1);
678
679         init_max_data_seg_len(max_data_seg_len);
680
681         if ((ipc_fd = iscsi_adm_request_listen()) < 0) {
682                 perror("ipc failed\n");
683                 exit(-1);
684         }
685
686         log_init();
687         if (log_daemon) {
688                 char buf[64];
689                 pid_t pid;
690                 int fd;
691
692                 fd = open("/var/run/iscsi-scstd.pid", O_WRONLY|O_CREAT, 0644);
693                 if (fd < 0) {
694                         log_error("unable to create pid file");
695                         exit(1);
696                 }
697                 pid = fork();
698                 if (pid < 0) {
699                         log_error("starting daemon failed");
700                         exit(1);
701                 } else if (pid) {
702                         int res = -1;
703                         close(init_report_pipe[1]);
704                         if (read(init_report_pipe[0], &res, sizeof(res)) < sizeof(res))
705                                 exit(-1);
706                         else
707                                 exit(res);
708                 }
709
710                 if (chdir("/") < 0) {
711                         log_error("failed to set working dir to /: %m");
712                         exit(1);
713                 }
714
715                 if (lockf(fd, F_TLOCK, 0) < 0) {
716                         log_error("unable to lock pid file");
717                         exit(1);
718                 }
719                 if (ftruncate(fd, 0) < 0) {
720                         log_error("failed to ftruncate the PID file: %m");
721                         exit(1);
722                 }
723
724                 sprintf(buf, "%d\n", getpid());
725                 if (write(fd, buf, strlen(buf)) < strlen(buf)) {
726                         log_error("failed to write PID to PID file: %m");
727                         exit(1);
728                 }
729
730                 close(0);
731                 open("/dev/null", O_RDWR);
732                 dup2(0, 1);
733                 dup2(0, 2);
734                 setsid();
735         }
736
737         config_isns_load(config, &isns, &isns_ac);
738         if (isns)
739                 timeout = isns_init(isns, isns_ac);
740
741         if (config_load(config) != 0)
742                 exit(1);
743
744         if (gid && setgid(gid) < 0)
745                 perror("setgid failed");
746
747         if (uid && setuid(uid) < 0)
748                 perror("setuid failed");
749
750         event_loop(timeout);
751
752         return 0;
753 }