4 * Copyright (C) 2002 Cisco Systems, Inc.
5 * maintained by linux-iscsi-devel@lists.sourceforge.net
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * See the file COPYING included with this distribution for more details.
28 #include <sys/ioctl.h>
29 #include <sys/types.h>
31 #include <netinet/tcp.h>
32 #include <arpa/inet.h>
35 #include "iscsi_proto.h"
36 #include "iscsi_settings.h"
37 #include "initiator.h"
38 #include "iscsi_ipc.h"
40 #include "transport.h"
46 #define LOG_CONN_CLOSED(conn) \
48 getnameinfo((struct sockaddr *) &conn->saddr, sizeof(conn->saddr), \
49 conn->host, sizeof(conn->host), NULL, 0, NI_NUMERICHOST); \
50 log_error("Connection to Discovery Address %s closed", conn->host); \
53 #define LOG_CONN_FAIL(conn) \
55 getnameinfo((struct sockaddr *) &conn->saddr, sizeof(conn->saddr), \
56 conn->host, sizeof(conn->host), NULL, 0, NI_NUMERICHOST); \
57 log_error("Connection to Discovery Address %s failed", conn->host); \
61 struct sockaddr_storage ss
;
63 struct sockaddr_in si
;
64 struct sockaddr_in6 si6
;
70 sigalarm_handler(int unused
)
76 set_non_blocking(int fd
)
78 int res
= fcntl(fd
, F_GETFL
);
81 res
= fcntl(fd
, F_SETFL
, res
| O_NONBLOCK
);
83 log_warning("unable to set fd flags (%s)!",
86 log_warning("unable to get fd flags (%s)!", strerror(errno
));
90 static int select_priority(struct iscsi_conn
*conn
, int pri_mask
)
98 * TODO: Configure priority selection from the mask
99 * For now, just always take the highest
102 /* Find highest bit set */
103 while ((msk
= pri_mask
& (pri_mask
- 1)))
106 return ffs(pri_mask
) - 1;
110 inet_cmp_addr(const union sockaddr_u
*s1
, const union sockaddr_u
*s2
)
112 const struct sockaddr_in
*si1
= &s1
->si
;
113 const struct sockaddr_in
*si2
= &s2
->si
;
115 return si1
->sin_addr
.s_addr
!= si2
->sin_addr
.s_addr
;
119 inet6_cmp_addr(const union sockaddr_u
*s1
, const union sockaddr_u
*s2
)
121 const struct sockaddr_in6
*si1
= &s1
->si6
;
122 const struct sockaddr_in6
*si2
= &s2
->si6
;
124 return memcmp(&si1
->sin6_addr
, &si2
->sin6_addr
, sizeof(si1
->sin6_addr
));
128 find_ifname(const struct ifaddrs
*ifa
, const union sockaddr_u
*ss
)
130 for (; ifa
; ifa
= ifa
->ifa_next
) {
134 if (ss
->ss
.ss_family
!= ifa
->ifa_addr
->sa_family
)
136 switch (ss
->ss
.ss_family
) {
138 if (inet_cmp_addr(ss
, (union sockaddr_u
*)ifa
->ifa_addr
) == 0)
139 return ifa
->ifa_name
;
142 if (inet6_cmp_addr(ss
, (union sockaddr_u
*)ifa
->ifa_addr
) == 0)
143 return ifa
->ifa_name
;
151 static void set_dcb_priority(struct iscsi_conn
*conn
, const char *devname
)
155 pri_mask
= get_dcb_app_pri_by_stream_port(devname
, ISCSI_DEFAULT_PORT
);
157 log_debug(2, "Getting priority for %s returned %d",
159 else if (pri_mask
== 0)
160 log_debug(2, "No priority for %s", devname
);
162 int pri
= select_priority(conn
, pri_mask
);
165 log_debug(1, "Setting socket %d priority to %d",
166 conn
->socket_fd
, pri
);
167 rc
= setsockopt(conn
->socket_fd
, SOL_SOCKET
,
168 SO_PRIORITY
, &pri
, sizeof(pri
));
170 log_warning("Setting socket %d priority to %d failed "
171 "with errno %d", conn
->socket_fd
,
178 /* not used by anyone */
179 static int get_hwaddress_from_netdev(char *netdev
, char *hwaddress
)
181 struct ifaddrs
*ifap
, *ifa
;
182 struct sockaddr_in
*s4
;
183 struct sockaddr_in6
*s6
;
184 struct ifreq if_hwaddr
;
185 int found
= 0, sockfd
;
186 unsigned char *hwaddr
;
187 char buf
[INET6_ADDRSTRLEN
];
189 if (getifaddrs(&ifap
)) {
190 log_error("Could not match hwaddress %s to netdev. "
191 "getifaddrs failed %d", hwaddress
, errno
);
195 /* Open a basic socket. */
196 sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0);
198 log_error("Could not open socket for ioctl.");
202 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
206 switch (ifa
->ifa_addr
->sa_family
) {
208 s4
= (struct sockaddr_in
*)(ifa
->ifa_addr
);
209 if (!inet_ntop(ifa
->ifa_addr
->sa_family
,
210 (void *)&(s4
->sin_addr
), buf
,
213 log_debug(4, "name %s addr %s\n", ifa
->ifa_name
, buf
);
216 s6
= (struct sockaddr_in6
*)(ifa
->ifa_addr
);
217 if (!inet_ntop(ifa
->ifa_addr
->sa_family
,
218 (void *)&(s6
->sin6_addr
), buf
, INET6_ADDRSTRLEN
))
220 log_debug(4, "name %s addr %s\n", ifa
->ifa_name
, buf
);
226 if (strcmp(ifa
->ifa_name
, netdev
))
229 strncpy(if_hwaddr
.ifr_name
, ifa
->ifa_name
, IFNAMSIZ
);
230 if (ioctl(sockfd
, SIOCGIFHWADDR
, &if_hwaddr
) < 0) {
231 log_error("Could not match %s to netdevice.",
236 /* check for ARPHRD_ETHER (ethernet) */
237 if (if_hwaddr
.ifr_hwaddr
.sa_family
!= 1)
239 hwaddr
= (unsigned char *)if_hwaddr
.ifr_hwaddr
.sa_data
;
241 memset(hwaddress
, 0, ISCSI_MAX_IFACE_LEN
);
242 /* TODO should look and covert so we do not need tmp buf */
243 sprintf(hwaddress
, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
244 hwaddr
[0], hwaddr
[1], hwaddr
[2], hwaddr
[3],
245 hwaddr
[4], hwaddr
[5]);
246 log_debug(4, "Found hardware address %s", hwaddress
);
261 This is
not supported
for now
, because it is
not exactly what we want
.
262 It also turns out that targets will send packets to other interfaces
263 causing all types of weird things to happen
.
266 static int bind_src_by_address(int sockfd
, char *address
)
269 char port
[NI_MAXSERV
];
270 struct sockaddr_storage saddr
;
272 memset(&saddr
, 0, sizeof(struct sockaddr_storage
));
273 if (resolve_address(address
, port
, &saddr
)) {
274 log_error("Could not bind %s to conn.", address
);
278 switch (saddr
.ss_family
) {
280 rc
= bind(sockfd
, (struct sockaddr
*)&saddr
,
281 sizeof(struct sockaddr_in
));
284 rc
= bind(sockfd
, (struct sockaddr
*)&saddr
,
285 sizeof(struct sockaddr_in6
));
291 log_error("Could not bind %s to %d.", address
, sockfd
);
293 log_debug(4, "Bound %s to socket fd %d", address
, sockfd
);
298 static int bind_conn_to_iface(iscsi_conn_t
*conn
, struct iface_rec
*iface
)
300 struct iscsi_session
*session
= conn
->session
;
302 if (strcmp(iface
->transport_name
, DEFAULT_TRANSPORT
))
305 memset(session
->netdev
, 0, IFNAMSIZ
);
306 if (iface_is_bound_by_hwaddr(iface
)) {
307 if (net_get_netdev_from_hwaddress(iface
->hwaddress
,
309 log_error("Cannot match %s to net/scsi interface.",
313 } else if (iface_is_bound_by_netdev(iface
)) {
314 strcpy(session
->netdev
, iface
->netdev
);
315 } else if (iface_is_bound_by_ipaddr(iface
)) {
317 * we never supported this but now with offload having to
318 * set the ip address in the iface, useris may forget to
319 * set the offload's transport type and we end up here by
322 log_error("Cannot bind %s to net/scsi interface. This is not "
323 "supported with software iSCSI (iscsi_tcp).",
328 if (strlen(session
->netdev
)) {
331 log_debug(4, "Binding session %d to %s", session
->id
,
333 memset(&ifr
, 0, sizeof(ifr
));
334 strlcpy(ifr
.ifr_name
, session
->netdev
, IFNAMSIZ
);
336 if (setsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_BINDTODEVICE
,
338 strlen(session
->netdev
) + 1) < 0) {
339 log_error("Could not bind connection %d to %s\n",
340 conn
->id
, session
->netdev
);
349 iscsi_io_tcp_connect(iscsi_conn_t
*conn
, int non_blocking
)
352 struct sockaddr_storage
*ss
= &conn
->saddr
;
353 char serv
[NI_MAXSERV
];
355 /* create a socket */
356 conn
->socket_fd
= socket(ss
->ss_family
, SOCK_STREAM
, IPPROTO_TCP
);
358 /* the trasport ep handle is used to bind with */
359 conn
->transport_ep_handle
= conn
->socket_fd
;
361 if (conn
->socket_fd
< 0) {
362 log_error("cannot create TCP socket");
366 if (bind_conn_to_iface(conn
, &conn
->session
->nrec
.iface
))
370 rc
= setsockopt(conn
->socket_fd
, IPPROTO_TCP
, TCP_NODELAY
, &onearg
,
373 log_error("cannot set TCP_NODELAY option on socket");
374 close(conn
->socket_fd
);
375 conn
->socket_fd
= -1;
379 /* optionally set the window sizes */
380 if (conn
->tcp_window_size
) {
381 int window_size
= conn
->tcp_window_size
;
382 socklen_t arglen
= sizeof (window_size
);
384 if (setsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_RCVBUF
,
385 (char *) &window_size
, sizeof (window_size
)) < 0) {
386 log_warning("failed to set TCP recv window size "
387 "to %u", window_size
);
389 if (getsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_RCVBUF
,
390 (char *) &window_size
, &arglen
) >= 0) {
391 log_debug(4, "set TCP recv window size to %u, "
393 conn
->tcp_window_size
, window_size
);
397 window_size
= conn
->tcp_window_size
;
398 arglen
= sizeof (window_size
);
400 if (setsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_SNDBUF
,
401 (char *) &window_size
, sizeof (window_size
)) < 0) {
402 log_warning("failed to set TCP send window size "
403 "to %u", window_size
);
405 if (getsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_SNDBUF
,
406 (char *) &window_size
, &arglen
) >= 0) {
407 log_debug(4, "set TCP send window size to %u, "
409 conn
->tcp_window_size
, window_size
);
415 * Build a TCP connection to the target
417 getnameinfo((struct sockaddr
*) ss
, sizeof(*ss
),
418 conn
->host
, sizeof(conn
->host
), serv
, sizeof(serv
),
419 NI_NUMERICHOST
|NI_NUMERICSERV
);
421 log_debug(1, "connecting to %s:%s", conn
->host
, serv
);
423 set_non_blocking(conn
->socket_fd
);
425 if (conn
->session
->netdev
[0])
426 set_dcb_priority(conn
, conn
->session
->netdev
);
428 rc
= connect(conn
->socket_fd
, (struct sockaddr
*) ss
, sizeof (*ss
));
433 iscsi_io_tcp_poll(iscsi_conn_t
*conn
, int timeout_ms
)
437 char serv
[NI_MAXSERV
], lserv
[NI_MAXSERV
];
438 struct sockaddr_storage ss
;
441 pdesc
.fd
= conn
->socket_fd
;
442 pdesc
.events
= POLLOUT
;
443 rc
= poll(&pdesc
, 1, timeout_ms
);
448 getnameinfo((struct sockaddr
*) &conn
->saddr
,
450 conn
->host
, sizeof(conn
->host
), serv
, sizeof(serv
),
451 NI_NUMERICHOST
|NI_NUMERICSERV
);
453 log_error("cannot make connection to %s:%s (%s)",
454 conn
->host
, serv
, strerror(errno
));
459 if (getsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_ERROR
,
460 (char *) &rc
, &len
) < 0) {
461 log_error("getsockopt for connect poll failed\n");
465 getnameinfo((struct sockaddr
*) &conn
->saddr
,
467 conn
->host
, sizeof(conn
->host
), serv
, sizeof(serv
),
468 NI_NUMERICHOST
|NI_NUMERICSERV
);
470 log_error("connect to %s:%s failed (%s)\n",
471 conn
->host
, serv
, strerror(rc
));
476 if (log_level
> 0 || !conn
->session
->netdev
[0])
477 rc
= getsockname(conn
->socket_fd
, (struct sockaddr
*)&ss
, &len
);
478 if (log_level
> 0 && rc
>= 0) {
479 getnameinfo((struct sockaddr
*) &conn
->saddr
,
480 sizeof(conn
->saddr
), conn
->host
,
481 sizeof(conn
->host
), serv
, sizeof(serv
),
482 NI_NUMERICHOST
|NI_NUMERICSERV
);
484 getnameinfo((struct sockaddr
*) &ss
, sizeof(ss
),
485 NULL
, 0, lserv
, sizeof(lserv
), NI_NUMERICSERV
);
487 log_debug(1, "connected local port %s to %s:%s",
488 lserv
, conn
->host
, serv
);
491 if (!conn
->session
->netdev
[0] && rc
>= 0) {
495 rc
= getifaddrs(&ifa
);
497 log_error("getifaddrs failed with %d\n", errno
);
499 ifname
= find_ifname(ifa
, (union sockaddr_u
*)&ss
);
501 set_dcb_priority(conn
, ifname
);
510 iscsi_io_tcp_disconnect(iscsi_conn_t
*conn
)
512 if (conn
->socket_fd
>= 0) {
513 log_debug(1, "disconnecting conn %p, fd %d", conn
,
515 close(conn
->socket_fd
);
516 conn
->socket_fd
= -1;
521 iscsi_io_connect(iscsi_conn_t
*conn
)
524 struct sigaction action
;
525 struct sigaction old
;
527 /* set a timeout, since the socket calls may take a long time to
528 * timeout on their own
530 memset(&action
, 0, sizeof (struct sigaction
));
531 memset(&old
, 0, sizeof (struct sigaction
));
532 action
.sa_sigaction
= NULL
;
534 action
.sa_handler
= sigalarm_handler
;
535 sigaction(SIGALRM
, &action
, &old
);
537 alarm(conn
->login_timeout
);
539 /* perform blocking TCP connect operation when no async request
540 * associated. SendTargets Discovery know to work in such a mode.
542 rc
= iscsi_io_tcp_connect(conn
, 0);
544 log_error("connect to %s timed out", conn
->host
);
546 log_debug(1, "socket %d connect timed out", conn
->socket_fd
);
550 log_error("cannot make connection to %s: %s",
551 conn
->host
, strerror(errno
));
552 close(conn
->socket_fd
);
555 } else if (log_level
> 0) {
556 struct sockaddr_storage ss
;
557 char lserv
[NI_MAXSERV
];
558 char serv
[NI_MAXSERV
];
559 socklen_t salen
= sizeof(ss
);
561 if (getsockname(conn
->socket_fd
, (struct sockaddr
*) &ss
,
563 getnameinfo((struct sockaddr
*) &conn
->saddr
,
565 conn
->host
, sizeof(conn
->host
), serv
,
566 sizeof(serv
), NI_NUMERICHOST
|NI_NUMERICSERV
);
568 getnameinfo((struct sockaddr
*) &ss
,
570 NULL
, 0, lserv
, sizeof(lserv
),
573 log_debug(1, "connected local port %s to %s:%s",
574 lserv
, conn
->host
, serv
);
582 sigaction(SIGALRM
, &old
, NULL
);
587 iscsi_io_disconnect(iscsi_conn_t
*conn
)
589 iscsi_io_tcp_disconnect(conn
);
593 iscsi_log_text(struct iscsi_hdr
*pdu
, char *data
)
595 int dlength
= ntoh24(pdu
->dlength
);
597 char *end
= text
+ dlength
;
599 while (text
&& (text
< end
)) {
600 log_debug(4, "> %s", text
);
601 text
+= strlen(text
);
602 while ((text
< end
) && (*text
== '\0'))
608 iscsi_io_send_pdu(iscsi_conn_t
*conn
, struct iscsi_hdr
*hdr
,
609 int hdr_digest
, char *data
, int data_digest
, int timeout
)
612 char *header
= (char *) hdr
;
617 int pdu_length
= sizeof (*hdr
) + hdr
->hlength
+ ntoh24(hdr
->dlength
);
619 struct sigaction action
;
620 struct sigaction old
;
621 iscsi_session_t
*session
= conn
->session
;
623 /* set a timeout, since the socket calls may take a long time
624 * to timeout on their own
626 if (!session
->use_ipc
) {
627 memset(&action
, 0, sizeof (struct sigaction
));
628 memset(&old
, 0, sizeof (struct sigaction
));
629 action
.sa_sigaction
= NULL
;
631 action
.sa_handler
= sigalarm_handler
;
632 sigaction(SIGALRM
, &action
, &old
);
637 memset(&pad
, 0, sizeof (pad
));
638 memset(&vec
, 0, sizeof (vec
));
640 switch (hdr
->opcode
& ISCSI_OPCODE_MASK
) {
641 case ISCSI_OP_LOGIN
:{
642 struct iscsi_login
*login_hdr
= (struct iscsi_login
*) hdr
;
644 log_debug(4, "sending login PDU with current stage "
645 "%d, next stage %d, transit 0x%x, isid"
646 " 0x%02x%02x%02x%02x%02x%02x exp_statsn %u",
647 ISCSI_LOGIN_CURRENT_STAGE(login_hdr
->flags
),
648 ISCSI_LOGIN_NEXT_STAGE(login_hdr
->flags
),
649 login_hdr
->flags
& ISCSI_FLAG_LOGIN_TRANSIT
,
650 login_hdr
->isid
[0], login_hdr
->isid
[1],
651 login_hdr
->isid
[2], login_hdr
->isid
[3],
652 login_hdr
->isid
[4], login_hdr
->isid
[5],
653 ntohl(login_hdr
->exp_statsn
));
655 iscsi_log_text(hdr
, data
);
659 struct iscsi_text
*text_hdr
= (struct iscsi_text
*) hdr
;
661 log_debug(4, "sending text pdu with CmdSN %x, exp_statsn %u",
662 ntohl(text_hdr
->cmdsn
), ntohl(text_hdr
->cmdsn
));
663 iscsi_log_text(hdr
, data
);
666 case ISCSI_OP_NOOP_OUT
:{
667 struct iscsi_nopout
*nopout_hdr
= (struct iscsi_nopout
*) hdr
;
669 log_debug(4, "sending Nop-out pdu with ttt %x, CmdSN %x:",
670 ntohl(nopout_hdr
->ttt
), ntohl(nopout_hdr
->cmdsn
));
671 iscsi_log_text(hdr
, data
);
675 log_debug(4, "sending pdu opcode 0x%x:", hdr
->opcode
);
679 /* send the PDU header */
680 header
= (char *) hdr
;
681 end
= header
+ sizeof (*hdr
) + hdr
->hlength
;
683 /* send all the data and any padding */
684 if (pdu_length
% ISCSI_PAD_LEN
)
685 pad_bytes
= ISCSI_PAD_LEN
- (pdu_length
% ISCSI_PAD_LEN
);
689 if (session
->use_ipc
)
690 ipc
->send_pdu_begin(session
->t
->handle
, session
->id
,
691 conn
->id
, end
- header
,
692 ntoh24(hdr
->dlength
) + pad_bytes
);
694 while (header
< end
) {
695 vec
[0].iov_base
= header
;
696 vec
[0].iov_len
= end
- header
;
698 if (!session
->use_ipc
)
699 rc
= writev(conn
->socket_fd
, vec
, 1);
701 rc
= ipc
->writev(0, vec
, 1);
703 log_error("socket %d write timed out",
707 } else if ((rc
<= 0) && (errno
!= EAGAIN
)) {
712 log_debug(4, "wrote %d bytes of PDU header", rc
);
717 end
= data
+ ntoh24(hdr
->dlength
);
718 remaining
= ntoh24(hdr
->dlength
) + pad_bytes
;
720 while (remaining
> 0) {
721 vec
[0].iov_base
= data
;
722 vec
[0].iov_len
= end
- data
;
723 vec
[1].iov_base
= (void *) &pad
;
724 vec
[1].iov_len
= pad_bytes
;
726 if (!session
->use_ipc
)
727 rc
= writev(conn
->socket_fd
, vec
, 2);
729 rc
= ipc
->writev(0, vec
, 2);
731 log_error("socket %d write timed out",
735 } else if ((rc
<= 0) && (errno
!= EAGAIN
)) {
740 log_debug(4, "wrote %d bytes of PDU data", rc
);
750 if (session
->use_ipc
) {
751 if (ipc
->send_pdu_end(session
->t
->handle
, session
->id
,
761 if (!session
->use_ipc
) {
763 sigaction(SIGALRM
, &old
, NULL
);
770 iscsi_io_recv_pdu(iscsi_conn_t
*conn
, struct iscsi_hdr
*hdr
,
771 int hdr_digest
, char *data
, int max_data_length
, int data_digest
,
774 uint32_t h_bytes
= 0;
775 uint32_t ahs_bytes
= 0;
776 uint32_t d_bytes
= 0;
777 uint32_t ahslength
= 0;
778 uint32_t dlength
= 0;
782 char *header
= (char *) hdr
;
783 char *end
= data
+ max_data_length
;
784 struct sigaction action
;
785 struct sigaction old
;
786 iscsi_session_t
*session
= conn
->session
;
788 memset(data
, 0, max_data_length
);
790 /* set a timeout, since the socket calls may take a long
791 * time to timeout on their own
793 if (!session
->use_ipc
) {
794 memset(&action
, 0, sizeof (struct sigaction
));
795 memset(&old
, 0, sizeof (struct sigaction
));
796 action
.sa_sigaction
= NULL
;
798 action
.sa_handler
= sigalarm_handler
;
799 sigaction(SIGALRM
, &action
, &old
);
803 failed
= ipc
->recv_pdu_begin(conn
);
804 if (failed
== -EAGAIN
)
806 else if (failed
< 0) {
812 /* read a response header */
814 if (!session
->use_ipc
)
815 rlen
= read(conn
->socket_fd
, header
,
816 sizeof (*hdr
) - h_bytes
);
818 rlen
= ipc
->read(header
, sizeof (*hdr
) - h_bytes
);
820 log_error("socket %d header read timed out",
824 } else if (rlen
== 0) {
825 LOG_CONN_CLOSED(conn
);
828 } else if ((rlen
< 0) && (errno
!= EAGAIN
)) {
832 } else if (rlen
> 0) {
833 log_debug(4, "read %d bytes of PDU header", rlen
);
837 } while (h_bytes
< sizeof (*hdr
));
839 log_debug(4, "read %d PDU header bytes, opcode 0x%x, dlength %u, "
840 "data %p, max %u", h_bytes
, hdr
->opcode
& ISCSI_OPCODE_MASK
,
841 ntoh24(hdr
->dlength
), data
, max_data_length
);
843 /* check for additional headers */
844 ahslength
= hdr
->hlength
; /* already includes padding */
846 log_warning("additional header segment length %u not supported",
852 /* read exactly what we expect, plus padding */
853 dlength
= hdr
->dlength
[0] << 16;
854 dlength
|= hdr
->dlength
[1] << 8;
855 dlength
|= hdr
->dlength
[2];
857 /* if we only expected to receive a header, exit */
861 if (data
+ dlength
> end
) {
862 log_warning("buffer size %u too small for data length %u",
863 max_data_length
, dlength
);
868 /* read the rest into our buffer */
870 while (d_bytes
< dlength
) {
871 if (!session
->use_ipc
)
872 rlen
= read(conn
->socket_fd
, data
+ d_bytes
,
875 rlen
= ipc
->read(data
+ d_bytes
, dlength
- d_bytes
);
877 log_error("socket %d data read timed out",
881 } else if (rlen
== 0) {
882 LOG_CONN_CLOSED(conn
);
885 } else if ((rlen
< 0 && errno
!= EAGAIN
)) {
889 } else if (rlen
> 0) {
890 log_debug(4, "read %d bytes of PDU data", rlen
);
895 /* handle PDU data padding.
896 * data is padded in case of kernel_io */
897 pad
= dlength
% ISCSI_PAD_LEN
;
898 if (pad
&& !session
->use_ipc
) {
899 int pad_bytes
= pad
= ISCSI_PAD_LEN
- pad
;
900 char bytes
[ISCSI_PAD_LEN
];
902 while (pad_bytes
> 0) {
903 rlen
= read(conn
->socket_fd
, &bytes
, pad_bytes
);
905 log_error("socket %d pad read timed out",
909 } else if (rlen
== 0) {
910 LOG_CONN_CLOSED(conn
);
913 } else if ((rlen
< 0 && errno
!= EAGAIN
)) {
917 } else if (rlen
> 0) {
918 log_debug(4, "read %d pad bytes", rlen
);
924 switch (hdr
->opcode
) {
925 case ISCSI_OP_TEXT_RSP
:
926 log_debug(4, "finished reading text PDU, %u hdr, %u "
927 "ah, %u data, %u pad",
928 h_bytes
, ahs_bytes
, d_bytes
, pad
);
929 iscsi_log_text(hdr
, data
);
931 case ISCSI_OP_LOGIN_RSP
:{
932 struct iscsi_login_rsp
*login_rsp
=
933 (struct iscsi_login_rsp
*) hdr
;
935 log_debug(4, "finished reading login PDU, %u hdr, "
936 "%u ah, %u data, %u pad",
937 h_bytes
, ahs_bytes
, d_bytes
, pad
);
938 log_debug(4, "login current stage %d, next stage "
940 ISCSI_LOGIN_CURRENT_STAGE(login_rsp
->flags
),
941 ISCSI_LOGIN_NEXT_STAGE(login_rsp
->flags
),
942 login_rsp
->flags
& ISCSI_FLAG_LOGIN_TRANSIT
);
943 iscsi_log_text(hdr
, data
);
946 case ISCSI_OP_ASYNC_EVENT
:
947 /* FIXME: log the event info */
954 if (!session
->use_ipc
) {
956 sigaction(SIGALRM
, &old
, NULL
);
958 /* finalyze receive transaction */
959 if (ipc
->recv_pdu_end(conn
)) {
964 if (timedout
|| failed
) {
969 return h_bytes
+ ahs_bytes
+ d_bytes
;