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");
367 if (bind_conn_to_iface(conn
, &conn
->session
->nrec
.iface
))
372 rc
= setsockopt(conn
->socket_fd
, IPPROTO_TCP
, TCP_NODELAY
, &onearg
,
375 log_error("cannot set TCP_NODELAY option on socket");
376 close(conn
->socket_fd
);
377 conn
->socket_fd
= -1;
381 /* optionally set the window sizes */
382 if (conn
->tcp_window_size
) {
383 int window_size
= conn
->tcp_window_size
;
384 socklen_t arglen
= sizeof (window_size
);
386 if (setsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_RCVBUF
,
387 (char *) &window_size
, sizeof (window_size
)) < 0) {
388 log_warning("failed to set TCP recv window size "
389 "to %u", window_size
);
391 if (getsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_RCVBUF
,
392 (char *) &window_size
, &arglen
) >= 0) {
393 log_debug(4, "set TCP recv window size to %u, "
395 conn
->tcp_window_size
, window_size
);
399 window_size
= conn
->tcp_window_size
;
400 arglen
= sizeof (window_size
);
402 if (setsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_SNDBUF
,
403 (char *) &window_size
, sizeof (window_size
)) < 0) {
404 log_warning("failed to set TCP send window size "
405 "to %u", window_size
);
407 if (getsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_SNDBUF
,
408 (char *) &window_size
, &arglen
) >= 0) {
409 log_debug(4, "set TCP send window size to %u, "
411 conn
->tcp_window_size
, window_size
);
417 * Build a TCP connection to the target
419 getnameinfo((struct sockaddr
*) ss
, sizeof(*ss
),
420 conn
->host
, sizeof(conn
->host
), serv
, sizeof(serv
),
421 NI_NUMERICHOST
|NI_NUMERICSERV
);
423 log_debug(1, "connecting to %s:%s", conn
->host
, serv
);
425 set_non_blocking(conn
->socket_fd
);
427 if (conn
->session
->netdev
[0])
428 set_dcb_priority(conn
, conn
->session
->netdev
);
430 rc
= connect(conn
->socket_fd
, (struct sockaddr
*) ss
, sizeof (*ss
));
435 iscsi_io_tcp_poll(iscsi_conn_t
*conn
, int timeout_ms
)
439 char serv
[NI_MAXSERV
], lserv
[NI_MAXSERV
];
440 struct sockaddr_storage ss
;
443 pdesc
.fd
= conn
->socket_fd
;
444 pdesc
.events
= POLLOUT
;
445 rc
= poll(&pdesc
, 1, timeout_ms
);
450 getnameinfo((struct sockaddr
*) &conn
->saddr
,
452 conn
->host
, sizeof(conn
->host
), serv
, sizeof(serv
),
453 NI_NUMERICHOST
|NI_NUMERICSERV
);
455 log_error("cannot make connection to %s:%s (%s)",
456 conn
->host
, serv
, strerror(errno
));
461 if (getsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_ERROR
,
462 (char *) &rc
, &len
) < 0) {
463 log_error("getsockopt for connect poll failed\n");
467 getnameinfo((struct sockaddr
*) &conn
->saddr
,
469 conn
->host
, sizeof(conn
->host
), serv
, sizeof(serv
),
470 NI_NUMERICHOST
|NI_NUMERICSERV
);
472 log_error("connect to %s:%s failed (%s)\n",
473 conn
->host
, serv
, strerror(rc
));
478 if (log_level
> 0 || !conn
->session
->netdev
[0])
479 rc
= getsockname(conn
->socket_fd
, (struct sockaddr
*)&ss
, &len
);
480 if (log_level
> 0 && rc
>= 0) {
481 getnameinfo((struct sockaddr
*) &conn
->saddr
,
482 sizeof(conn
->saddr
), conn
->host
,
483 sizeof(conn
->host
), serv
, sizeof(serv
),
484 NI_NUMERICHOST
|NI_NUMERICSERV
);
486 getnameinfo((struct sockaddr
*) &ss
, sizeof(ss
),
487 NULL
, 0, lserv
, sizeof(lserv
), NI_NUMERICSERV
);
489 log_debug(1, "connected local port %s to %s:%s",
490 lserv
, conn
->host
, serv
);
493 if (!conn
->session
->netdev
[0] && rc
>= 0) {
497 rc
= getifaddrs(&ifa
);
499 log_error("getifaddrs failed with %d\n", errno
);
501 ifname
= find_ifname(ifa
, (union sockaddr_u
*)&ss
);
503 set_dcb_priority(conn
, ifname
);
512 iscsi_io_tcp_disconnect(iscsi_conn_t
*conn
)
514 if (conn
->socket_fd
>= 0) {
515 log_debug(1, "disconnecting conn %p, fd %d", conn
,
517 close(conn
->socket_fd
);
518 conn
->socket_fd
= -1;
523 iscsi_io_connect(iscsi_conn_t
*conn
)
526 struct sigaction action
;
527 struct sigaction old
;
529 /* set a timeout, since the socket calls may take a long time to
530 * timeout on their own
532 memset(&action
, 0, sizeof (struct sigaction
));
533 memset(&old
, 0, sizeof (struct sigaction
));
534 action
.sa_sigaction
= NULL
;
536 action
.sa_handler
= sigalarm_handler
;
537 sigaction(SIGALRM
, &action
, &old
);
539 alarm(conn
->login_timeout
);
541 /* perform blocking TCP connect operation when no async request
542 * associated. SendTargets Discovery know to work in such a mode.
544 rc
= iscsi_io_tcp_connect(conn
, 0);
546 log_error("connect to %s timed out", conn
->host
);
548 log_debug(1, "socket %d connect timed out", conn
->socket_fd
);
552 log_error("cannot make connection to %s: %s",
553 conn
->host
, strerror(errno
));
554 close(conn
->socket_fd
);
557 } else if (log_level
> 0) {
558 struct sockaddr_storage ss
;
559 char lserv
[NI_MAXSERV
];
560 char serv
[NI_MAXSERV
];
561 socklen_t salen
= sizeof(ss
);
563 if (getsockname(conn
->socket_fd
, (struct sockaddr
*) &ss
,
565 getnameinfo((struct sockaddr
*) &conn
->saddr
,
567 conn
->host
, sizeof(conn
->host
), serv
,
568 sizeof(serv
), NI_NUMERICHOST
|NI_NUMERICSERV
);
570 getnameinfo((struct sockaddr
*) &ss
,
572 NULL
, 0, lserv
, sizeof(lserv
),
575 log_debug(1, "connected local port %s to %s:%s",
576 lserv
, conn
->host
, serv
);
584 sigaction(SIGALRM
, &old
, NULL
);
589 iscsi_io_disconnect(iscsi_conn_t
*conn
)
591 iscsi_io_tcp_disconnect(conn
);
595 iscsi_log_text(struct iscsi_hdr
*pdu
, char *data
)
597 int dlength
= ntoh24(pdu
->dlength
);
599 char *end
= text
+ dlength
;
601 while (text
&& (text
< end
)) {
602 log_debug(4, "> %s", text
);
603 text
+= strlen(text
);
604 while ((text
< end
) && (*text
== '\0'))
610 iscsi_io_send_pdu(iscsi_conn_t
*conn
, struct iscsi_hdr
*hdr
,
611 int hdr_digest
, char *data
, int data_digest
, int timeout
)
614 char *header
= (char *) hdr
;
619 int pdu_length
= sizeof (*hdr
) + hdr
->hlength
+ ntoh24(hdr
->dlength
);
621 struct sigaction action
;
622 struct sigaction old
;
623 iscsi_session_t
*session
= conn
->session
;
625 /* set a timeout, since the socket calls may take a long time
626 * to timeout on their own
628 if (!session
->use_ipc
) {
629 memset(&action
, 0, sizeof (struct sigaction
));
630 memset(&old
, 0, sizeof (struct sigaction
));
631 action
.sa_sigaction
= NULL
;
633 action
.sa_handler
= sigalarm_handler
;
634 sigaction(SIGALRM
, &action
, &old
);
639 memset(&pad
, 0, sizeof (pad
));
640 memset(&vec
, 0, sizeof (vec
));
642 switch (hdr
->opcode
& ISCSI_OPCODE_MASK
) {
643 case ISCSI_OP_LOGIN
:{
644 struct iscsi_login
*login_hdr
= (struct iscsi_login
*) hdr
;
646 log_debug(4, "sending login PDU with current stage "
647 "%d, next stage %d, transit 0x%x, isid"
648 " 0x%02x%02x%02x%02x%02x%02x exp_statsn %u",
649 ISCSI_LOGIN_CURRENT_STAGE(login_hdr
->flags
),
650 ISCSI_LOGIN_NEXT_STAGE(login_hdr
->flags
),
651 login_hdr
->flags
& ISCSI_FLAG_LOGIN_TRANSIT
,
652 login_hdr
->isid
[0], login_hdr
->isid
[1],
653 login_hdr
->isid
[2], login_hdr
->isid
[3],
654 login_hdr
->isid
[4], login_hdr
->isid
[5],
655 ntohl(login_hdr
->exp_statsn
));
657 iscsi_log_text(hdr
, data
);
661 struct iscsi_text
*text_hdr
= (struct iscsi_text
*) hdr
;
663 log_debug(4, "sending text pdu with CmdSN %x, exp_statsn %u",
664 ntohl(text_hdr
->cmdsn
), ntohl(text_hdr
->cmdsn
));
665 iscsi_log_text(hdr
, data
);
668 case ISCSI_OP_NOOP_OUT
:{
669 struct iscsi_nopout
*nopout_hdr
= (struct iscsi_nopout
*) hdr
;
671 log_debug(4, "sending Nop-out pdu with ttt %x, CmdSN %x:",
672 ntohl(nopout_hdr
->ttt
), ntohl(nopout_hdr
->cmdsn
));
673 iscsi_log_text(hdr
, data
);
677 log_debug(4, "sending pdu opcode 0x%x:", hdr
->opcode
);
681 /* send the PDU header */
682 header
= (char *) hdr
;
683 end
= header
+ sizeof (*hdr
) + hdr
->hlength
;
685 /* send all the data and any padding */
686 if (pdu_length
% ISCSI_PAD_LEN
)
687 pad_bytes
= ISCSI_PAD_LEN
- (pdu_length
% ISCSI_PAD_LEN
);
691 if (session
->use_ipc
)
692 ipc
->send_pdu_begin(session
->t
->handle
, session
->id
,
693 conn
->id
, end
- header
,
694 ntoh24(hdr
->dlength
) + pad_bytes
);
696 while (header
< end
) {
697 vec
[0].iov_base
= header
;
698 vec
[0].iov_len
= end
- header
;
700 if (!session
->use_ipc
)
701 rc
= writev(conn
->socket_fd
, vec
, 1);
703 rc
= ipc
->writev(0, vec
, 1);
705 log_error("socket %d write timed out",
709 } else if ((rc
<= 0) && (errno
!= EAGAIN
)) {
714 log_debug(4, "wrote %d bytes of PDU header", rc
);
719 end
= data
+ ntoh24(hdr
->dlength
);
720 remaining
= ntoh24(hdr
->dlength
) + pad_bytes
;
722 while (remaining
> 0) {
723 vec
[0].iov_base
= data
;
724 vec
[0].iov_len
= end
- data
;
725 vec
[1].iov_base
= (void *) &pad
;
726 vec
[1].iov_len
= pad_bytes
;
728 if (!session
->use_ipc
)
729 rc
= writev(conn
->socket_fd
, vec
, 2);
731 rc
= ipc
->writev(0, vec
, 2);
733 log_error("socket %d write timed out",
737 } else if ((rc
<= 0) && (errno
!= EAGAIN
)) {
742 log_debug(4, "wrote %d bytes of PDU data", rc
);
752 if (session
->use_ipc
) {
753 if (ipc
->send_pdu_end(session
->t
->handle
, session
->id
,
763 if (!session
->use_ipc
) {
765 sigaction(SIGALRM
, &old
, NULL
);
772 iscsi_io_recv_pdu(iscsi_conn_t
*conn
, struct iscsi_hdr
*hdr
,
773 int hdr_digest
, char *data
, int max_data_length
, int data_digest
,
776 uint32_t h_bytes
= 0;
777 uint32_t ahs_bytes
= 0;
778 uint32_t d_bytes
= 0;
779 uint32_t ahslength
= 0;
780 uint32_t dlength
= 0;
784 char *header
= (char *) hdr
;
785 char *end
= data
+ max_data_length
;
786 struct sigaction action
;
787 struct sigaction old
;
788 iscsi_session_t
*session
= conn
->session
;
790 memset(data
, 0, max_data_length
);
792 /* set a timeout, since the socket calls may take a long
793 * time to timeout on their own
795 if (!session
->use_ipc
) {
796 memset(&action
, 0, sizeof (struct sigaction
));
797 memset(&old
, 0, sizeof (struct sigaction
));
798 action
.sa_sigaction
= NULL
;
800 action
.sa_handler
= sigalarm_handler
;
801 sigaction(SIGALRM
, &action
, &old
);
805 failed
= ipc
->recv_pdu_begin(conn
);
806 if (failed
== -EAGAIN
)
808 else if (failed
< 0) {
814 /* read a response header */
816 if (!session
->use_ipc
)
817 rlen
= read(conn
->socket_fd
, header
,
818 sizeof (*hdr
) - h_bytes
);
820 rlen
= ipc
->read(header
, sizeof (*hdr
) - h_bytes
);
822 log_error("socket %d header read timed out",
826 } else if (rlen
== 0) {
827 LOG_CONN_CLOSED(conn
);
830 } else if ((rlen
< 0) && (errno
!= EAGAIN
)) {
834 } else if (rlen
> 0) {
835 log_debug(4, "read %d bytes of PDU header", rlen
);
839 } while (h_bytes
< sizeof (*hdr
));
841 log_debug(4, "read %d PDU header bytes, opcode 0x%x, dlength %u, "
842 "data %p, max %u", h_bytes
, hdr
->opcode
& ISCSI_OPCODE_MASK
,
843 ntoh24(hdr
->dlength
), data
, max_data_length
);
845 /* check for additional headers */
846 ahslength
= hdr
->hlength
; /* already includes padding */
848 log_warning("additional header segment length %u not supported",
854 /* read exactly what we expect, plus padding */
855 dlength
= hdr
->dlength
[0] << 16;
856 dlength
|= hdr
->dlength
[1] << 8;
857 dlength
|= hdr
->dlength
[2];
859 /* if we only expected to receive a header, exit */
863 if (data
+ dlength
> end
) {
864 log_warning("buffer size %u too small for data length %u",
865 max_data_length
, dlength
);
870 /* read the rest into our buffer */
872 while (d_bytes
< dlength
) {
873 if (!session
->use_ipc
)
874 rlen
= read(conn
->socket_fd
, data
+ d_bytes
,
877 rlen
= ipc
->read(data
+ d_bytes
, dlength
- d_bytes
);
879 log_error("socket %d data read timed out",
883 } else if (rlen
== 0) {
884 LOG_CONN_CLOSED(conn
);
887 } else if ((rlen
< 0 && errno
!= EAGAIN
)) {
891 } else if (rlen
> 0) {
892 log_debug(4, "read %d bytes of PDU data", rlen
);
897 /* handle PDU data padding.
898 * data is padded in case of kernel_io */
899 pad
= dlength
% ISCSI_PAD_LEN
;
900 if (pad
&& !session
->use_ipc
) {
901 int pad_bytes
= pad
= ISCSI_PAD_LEN
- pad
;
902 char bytes
[ISCSI_PAD_LEN
];
904 while (pad_bytes
> 0) {
905 rlen
= read(conn
->socket_fd
, &bytes
, pad_bytes
);
907 log_error("socket %d pad read timed out",
911 } else if (rlen
== 0) {
912 LOG_CONN_CLOSED(conn
);
915 } else if ((rlen
< 0 && errno
!= EAGAIN
)) {
919 } else if (rlen
> 0) {
920 log_debug(4, "read %d pad bytes", rlen
);
926 switch (hdr
->opcode
) {
927 case ISCSI_OP_TEXT_RSP
:
928 log_debug(4, "finished reading text PDU, %u hdr, %u "
929 "ah, %u data, %u pad",
930 h_bytes
, ahs_bytes
, d_bytes
, pad
);
931 iscsi_log_text(hdr
, data
);
933 case ISCSI_OP_LOGIN_RSP
:{
934 struct iscsi_login_rsp
*login_rsp
=
935 (struct iscsi_login_rsp
*) hdr
;
937 log_debug(4, "finished reading login PDU, %u hdr, "
938 "%u ah, %u data, %u pad",
939 h_bytes
, ahs_bytes
, d_bytes
, pad
);
940 log_debug(4, "login current stage %d, next stage "
942 ISCSI_LOGIN_CURRENT_STAGE(login_rsp
->flags
),
943 ISCSI_LOGIN_NEXT_STAGE(login_rsp
->flags
),
944 login_rsp
->flags
& ISCSI_FLAG_LOGIN_TRANSIT
);
945 iscsi_log_text(hdr
, data
);
948 case ISCSI_OP_ASYNC_EVENT
:
949 /* FIXME: log the event info */
956 if (!session
->use_ipc
) {
958 sigaction(SIGALRM
, &old
, NULL
);
960 /* finalyze receive transaction */
961 if (ipc
->recv_pdu_end(conn
)) {
966 if (timedout
|| failed
) {
971 return h_bytes
+ ahs_bytes
+ d_bytes
;