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 <netinet/tcp.h>
30 #include <arpa/inet.h>
33 #include "iscsi_proto.h"
34 #include "initiator.h"
35 #include "iscsi_ipc.h"
37 #include "transport.h"
42 #define LOG_CONN_CLOSED(conn) \
44 getnameinfo((struct sockaddr *) &conn->saddr, sizeof(conn->saddr), \
45 conn->host, sizeof(conn->host), NULL, 0, NI_NUMERICHOST); \
46 log_error("Connection to Discovery Address %s closed", conn->host); \
49 #define LOG_CONN_FAIL(conn) \
51 getnameinfo((struct sockaddr *) &conn->saddr, sizeof(conn->saddr), \
52 conn->host, sizeof(conn->host), NULL, 0, NI_NUMERICHOST); \
53 log_error("Connection to Discovery Address %s failed", conn->host); \
59 sigalarm_handler(int unused
)
65 set_non_blocking(int fd
)
67 int res
= fcntl(fd
, F_GETFL
);
70 res
= fcntl(fd
, F_SETFL
, res
| O_NONBLOCK
);
72 log_warning("unable to set fd flags (%s)!",
75 log_warning("unable to get fd flags (%s)!", strerror(errno
));
80 /* not used by anyone */
81 static int get_hwaddress_from_netdev(char *netdev
, char *hwaddress
)
83 struct ifaddrs
*ifap
, *ifa
;
84 struct sockaddr_in
*s4
;
85 struct sockaddr_in6
*s6
;
86 struct ifreq if_hwaddr
;
87 int found
= 0, sockfd
;
88 unsigned char *hwaddr
;
89 char buf
[INET6_ADDRSTRLEN
];
91 if (getifaddrs(&ifap
)) {
92 log_error("Could not match hwaddress %s to netdev. "
93 "getifaddrs failed %d", hwaddress
, errno
);
97 /* Open a basic socket. */
98 sockfd
= socket(AF_INET
, SOCK_DGRAM
, 0);
100 log_error("Could not open socket for ioctl.");
104 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
108 switch (ifa
->ifa_addr
->sa_family
) {
110 s4
= (struct sockaddr_in
*)(ifa
->ifa_addr
);
111 if (!inet_ntop(ifa
->ifa_addr
->sa_family
,
112 (void *)&(s4
->sin_addr
), buf
,
115 log_debug(4, "name %s addr %s\n", ifa
->ifa_name
, buf
);
118 s6
= (struct sockaddr_in6
*)(ifa
->ifa_addr
);
119 if (!inet_ntop(ifa
->ifa_addr
->sa_family
,
120 (void *)&(s6
->sin6_addr
), buf
, INET6_ADDRSTRLEN
))
122 log_debug(4, "name %s addr %s\n", ifa
->ifa_name
, buf
);
128 if (strcmp(ifa
->ifa_name
, netdev
))
131 strncpy(if_hwaddr
.ifr_name
, ifa
->ifa_name
, IFNAMSIZ
);
132 if (ioctl(sockfd
, SIOCGIFHWADDR
, &if_hwaddr
) < 0) {
133 log_error("Could not match %s to netdevice.",
138 /* check for ARPHRD_ETHER (ethernet) */
139 if (if_hwaddr
.ifr_hwaddr
.sa_family
!= 1)
141 hwaddr
= (unsigned char *)if_hwaddr
.ifr_hwaddr
.sa_data
;
143 memset(hwaddress
, 0, ISCSI_MAX_IFACE_LEN
);
144 /* TODO should look and covert so we do not need tmp buf */
145 sprintf(hwaddress
, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
146 hwaddr
[0], hwaddr
[1], hwaddr
[2], hwaddr
[3],
147 hwaddr
[4], hwaddr
[5]);
148 log_debug(4, "Found hardware address %s", hwaddress
);
163 This is
not supported
for now
, because it is
not exactly what we want
.
164 It also turns out that targets will send packets to other interfaces
165 causing all types of weird things to happen
.
168 static int bind_src_by_address(int sockfd
, char *address
)
171 char port
[NI_MAXSERV
];
172 struct sockaddr_storage saddr
;
174 memset(&saddr
, 0, sizeof(struct sockaddr_storage
));
175 if (resolve_address(address
, port
, &saddr
)) {
176 log_error("Could not bind %s to conn.", address
);
180 switch (saddr
.ss_family
) {
182 rc
= bind(sockfd
, (struct sockaddr
*)&saddr
,
183 sizeof(struct sockaddr_in
));
186 rc
= bind(sockfd
, (struct sockaddr
*)&saddr
,
187 sizeof(struct sockaddr_in6
));
193 log_error("Could not bind %s to %d.", address
, sockfd
);
195 log_debug(4, "Bound %s to socket fd %d", address
, sockfd
);
200 static int bind_conn_to_iface(iscsi_conn_t
*conn
, struct iface_rec
*iface
)
202 struct iscsi_session
*session
= conn
->session
;
204 memset(session
->netdev
, 0, IFNAMSIZ
);
205 if (iface_is_bound_by_hwaddr(iface
) &&
206 net_get_netdev_from_hwaddress(iface
->hwaddress
, session
->netdev
)) {
207 log_error("Cannot match %s to net/scsi interface.",
210 } else if (iface_is_bound_by_netdev(iface
))
211 strcpy(session
->netdev
, iface
->netdev
);
212 else if (iface_is_bound_by_ipaddr(iface
)) {
214 * we never supported this but now with offload having to
215 * set the ip address in the iface, useris may forget to
216 * set the offload's transport type and we end up here by
219 log_error("Cannot bind %s to net/scsi interface. This is not "
220 "supported with software iSCSI (iscsi_tcp).",
225 if (strlen(session
->netdev
)) {
228 log_debug(4, "Binding session %d to %s", session
->id
,
230 memset(&ifr
, 0, sizeof(ifr
));
231 strlcpy(ifr
.ifr_name
, session
->netdev
, IFNAMSIZ
);
233 if (setsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_BINDTODEVICE
,
235 strlen(session
->netdev
) + 1) < 0) {
236 log_error("Could not bind connection %d to %s\n",
237 conn
->id
, session
->netdev
);
246 iscsi_io_tcp_connect(iscsi_conn_t
*conn
, int non_blocking
)
249 struct sockaddr_storage
*ss
= &conn
->saddr
;
250 char serv
[NI_MAXSERV
];
252 /* create a socket */
253 conn
->socket_fd
= socket(ss
->ss_family
, SOCK_STREAM
, IPPROTO_TCP
);
255 /* the trasport ep handle is used to bind with */
256 conn
->transport_ep_handle
= conn
->socket_fd
;
258 if (conn
->socket_fd
< 0) {
259 log_error("cannot create TCP socket");
264 if (bind_conn_to_iface(conn
, &conn
->session
->nrec
.iface
))
269 rc
= setsockopt(conn
->socket_fd
, IPPROTO_TCP
, TCP_NODELAY
, &onearg
,
272 log_error("cannot set TCP_NODELAY option on socket");
273 close(conn
->socket_fd
);
274 conn
->socket_fd
= -1;
278 /* optionally set the window sizes */
279 if (conn
->tcp_window_size
) {
280 int window_size
= conn
->tcp_window_size
;
281 socklen_t arglen
= sizeof (window_size
);
283 if (setsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_RCVBUF
,
284 (char *) &window_size
, sizeof (window_size
)) < 0) {
285 log_warning("failed to set TCP recv window size "
286 "to %u", window_size
);
288 if (getsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_RCVBUF
,
289 (char *) &window_size
, &arglen
) >= 0) {
290 log_debug(4, "set TCP recv window size to %u, "
292 conn
->tcp_window_size
, window_size
);
296 window_size
= conn
->tcp_window_size
;
297 arglen
= sizeof (window_size
);
299 if (setsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_SNDBUF
,
300 (char *) &window_size
, sizeof (window_size
)) < 0) {
301 log_warning("failed to set TCP send window size "
302 "to %u", window_size
);
304 if (getsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_SNDBUF
,
305 (char *) &window_size
, &arglen
) >= 0) {
306 log_debug(4, "set TCP send window size to %u, "
308 conn
->tcp_window_size
, window_size
);
314 * Build a TCP connection to the target
316 getnameinfo((struct sockaddr
*) ss
, sizeof(*ss
),
317 conn
->host
, sizeof(conn
->host
), serv
, sizeof(serv
),
318 NI_NUMERICHOST
|NI_NUMERICSERV
);
320 log_debug(1, "connecting to %s:%s", conn
->host
, serv
);
322 set_non_blocking(conn
->socket_fd
);
323 rc
= connect(conn
->socket_fd
, (struct sockaddr
*) ss
, sizeof (*ss
));
328 iscsi_io_tcp_poll(iscsi_conn_t
*conn
, int timeout_ms
)
332 char serv
[NI_MAXSERV
], lserv
[NI_MAXSERV
];
333 struct sockaddr_storage ss
;
334 socklen_t len
= sizeof(ss
);
336 pdesc
.fd
= conn
->socket_fd
;
337 pdesc
.events
= POLLOUT
;
338 rc
= poll(&pdesc
, 1, timeout_ms
);
343 getnameinfo((struct sockaddr
*) &conn
->saddr
,
345 conn
->host
, sizeof(conn
->host
), serv
, sizeof(serv
),
346 NI_NUMERICHOST
|NI_NUMERICSERV
);
348 log_error("cannot make connection to %s:%s (%s)",
349 conn
->host
, serv
, strerror(errno
));
354 if (getsockopt(conn
->socket_fd
, SOL_SOCKET
, SO_ERROR
,
355 (char *) &rc
, &len
) < 0) {
356 log_error("getsockopt for connect poll failed\n");
360 getnameinfo((struct sockaddr
*) &conn
->saddr
,
362 conn
->host
, sizeof(conn
->host
), serv
, sizeof(serv
),
363 NI_NUMERICHOST
|NI_NUMERICSERV
);
365 log_error("connect to %s:%s failed (%s)\n",
366 conn
->host
, serv
, strerror(rc
));
372 getsockname(conn
->socket_fd
, (struct sockaddr
*) &ss
, &len
) >= 0) {
373 getnameinfo((struct sockaddr
*) &conn
->saddr
,
374 sizeof(conn
->saddr
), conn
->host
,
375 sizeof(conn
->host
), serv
, sizeof(serv
),
376 NI_NUMERICHOST
|NI_NUMERICSERV
);
378 getnameinfo((struct sockaddr
*) &ss
, sizeof(ss
),
379 NULL
, 0, lserv
, sizeof(lserv
), NI_NUMERICSERV
);
381 log_debug(1, "connected local port %s to %s:%s",
382 lserv
, conn
->host
, serv
);
388 iscsi_io_tcp_disconnect(iscsi_conn_t
*conn
)
390 if (conn
->socket_fd
>= 0) {
391 log_debug(1, "disconnecting conn %p, fd %d", conn
,
393 close(conn
->socket_fd
);
394 conn
->socket_fd
= -1;
399 iscsi_io_connect(iscsi_conn_t
*conn
)
402 struct sigaction action
;
403 struct sigaction old
;
404 char serv
[NI_MAXSERV
];
406 /* set a timeout, since the socket calls may take a long time to
407 * timeout on their own
409 memset(&action
, 0, sizeof (struct sigaction
));
410 memset(&old
, 0, sizeof (struct sigaction
));
411 action
.sa_sigaction
= NULL
;
413 action
.sa_handler
= sigalarm_handler
;
414 sigaction(SIGALRM
, &action
, &old
);
416 alarm(conn
->login_timeout
);
418 /* perform blocking TCP connect operation when no async request
419 * associated. SendTargets Discovery know to work in such a mode.
421 rc
= iscsi_io_tcp_connect(conn
, 0);
423 log_debug(1, "socket %d connect timed out", conn
->socket_fd
);
427 getnameinfo((struct sockaddr
*) &conn
->saddr
,
429 conn
->host
, sizeof(conn
->host
), serv
, sizeof(serv
),
430 NI_NUMERICHOST
|NI_NUMERICSERV
);
431 log_error("cannot make connection to %s:%s (%d)",
432 conn
->host
, serv
, errno
);
433 close(conn
->socket_fd
);
436 } else if (log_level
> 0) {
437 struct sockaddr_storage ss
;
438 char lserv
[NI_MAXSERV
];
439 socklen_t salen
= sizeof(ss
);
441 if (getsockname(conn
->socket_fd
, (struct sockaddr
*) &ss
,
443 getnameinfo((struct sockaddr
*) &conn
->saddr
,
445 conn
->host
, sizeof(conn
->host
), serv
,
446 sizeof(serv
), NI_NUMERICHOST
|NI_NUMERICSERV
);
448 getnameinfo((struct sockaddr
*) &ss
,
450 NULL
, 0, lserv
, sizeof(lserv
),
453 log_debug(1, "connected local port %s to %s:%s",
454 lserv
, conn
->host
, serv
);
462 sigaction(SIGALRM
, &old
, NULL
);
467 iscsi_io_disconnect(iscsi_conn_t
*conn
)
469 iscsi_io_tcp_disconnect(conn
);
473 iscsi_log_text(struct iscsi_hdr
*pdu
, char *data
)
475 int dlength
= ntoh24(pdu
->dlength
);
477 char *end
= text
+ dlength
;
479 while (text
&& (text
< end
)) {
480 log_debug(4, "> %s", text
);
481 text
+= strlen(text
);
482 while ((text
< end
) && (*text
== '\0'))
488 iscsi_io_send_pdu(iscsi_conn_t
*conn
, struct iscsi_hdr
*hdr
,
489 int hdr_digest
, char *data
, int data_digest
, int timeout
)
492 char *header
= (char *) hdr
;
497 int pdu_length
= sizeof (*hdr
) + hdr
->hlength
+ ntoh24(hdr
->dlength
);
499 struct sigaction action
;
500 struct sigaction old
;
501 iscsi_session_t
*session
= conn
->session
;
503 /* set a timeout, since the socket calls may take a long time
504 * to timeout on their own
507 memset(&action
, 0, sizeof (struct sigaction
));
508 memset(&old
, 0, sizeof (struct sigaction
));
509 action
.sa_sigaction
= NULL
;
511 action
.sa_handler
= sigalarm_handler
;
512 sigaction(SIGALRM
, &action
, &old
);
517 memset(&pad
, 0, sizeof (pad
));
518 memset(&vec
, 0, sizeof (vec
));
520 switch (hdr
->opcode
& ISCSI_OPCODE_MASK
) {
521 case ISCSI_OP_LOGIN
:{
522 struct iscsi_login
*login_hdr
= (struct iscsi_login
*) hdr
;
524 log_debug(4, "sending login PDU with current stage "
525 "%d, next stage %d, transit 0x%x, isid"
526 " 0x%02x%02x%02x%02x%02x%02x exp_statsn %u",
527 ISCSI_LOGIN_CURRENT_STAGE(login_hdr
->flags
),
528 ISCSI_LOGIN_NEXT_STAGE(login_hdr
->flags
),
529 login_hdr
->flags
& ISCSI_FLAG_LOGIN_TRANSIT
,
530 login_hdr
->isid
[0], login_hdr
->isid
[1],
531 login_hdr
->isid
[2], login_hdr
->isid
[3],
532 login_hdr
->isid
[4], login_hdr
->isid
[5],
533 ntohl(login_hdr
->exp_statsn
));
535 iscsi_log_text(hdr
, data
);
539 struct iscsi_text
*text_hdr
= (struct iscsi_text
*) hdr
;
541 log_debug(4, "sending text pdu with CmdSN %x, exp_statsn %u",
542 ntohl(text_hdr
->cmdsn
), ntohl(text_hdr
->cmdsn
));
543 iscsi_log_text(hdr
, data
);
546 case ISCSI_OP_NOOP_OUT
:{
547 struct iscsi_nopout
*nopout_hdr
= (struct iscsi_nopout
*) hdr
;
549 log_debug(4, "sending Nop-out pdu with ttt %x, CmdSN %x:",
550 ntohl(nopout_hdr
->ttt
), ntohl(nopout_hdr
->cmdsn
));
551 iscsi_log_text(hdr
, data
);
555 log_debug(4, "sending pdu opcode 0x%x:", hdr
->opcode
);
559 /* send the PDU header */
560 header
= (char *) hdr
;
561 end
= header
+ sizeof (*hdr
) + hdr
->hlength
;
563 /* send all the data and any padding */
564 if (pdu_length
% ISCSI_PAD_LEN
)
565 pad_bytes
= ISCSI_PAD_LEN
- (pdu_length
% ISCSI_PAD_LEN
);
570 ipc
->send_pdu_begin(session
->t
->handle
, session
->id
,
571 conn
->id
, end
- header
,
572 ntoh24(hdr
->dlength
) + pad_bytes
);
574 while (header
< end
) {
575 vec
[0].iov_base
= header
;
576 vec
[0].iov_len
= end
- header
;
579 rc
= writev(session
->ctrl_fd
, vec
, 1);
581 rc
= ipc
->writev(0, vec
, 1);
583 log_error("socket %d write timed out",
587 } else if ((rc
<= 0) && (errno
!= EAGAIN
)) {
592 log_debug(4, "wrote %d bytes of PDU header", rc
);
597 end
= data
+ ntoh24(hdr
->dlength
);
598 remaining
= ntoh24(hdr
->dlength
) + pad_bytes
;
600 while (remaining
> 0) {
601 vec
[0].iov_base
= data
;
602 vec
[0].iov_len
= end
- data
;
603 vec
[1].iov_base
= (void *) &pad
;
604 vec
[1].iov_len
= pad_bytes
;
607 rc
= writev(session
->ctrl_fd
, vec
, 2);
609 rc
= ipc
->writev(0, vec
, 2);
611 log_error("socket %d write timed out",
615 } else if ((rc
<= 0) && (errno
!= EAGAIN
)) {
620 log_debug(4, "wrote %d bytes of PDU data", rc
);
631 if (ipc
->send_pdu_end(session
->t
->handle
, session
->id
,
643 sigaction(SIGALRM
, &old
, NULL
);
650 iscsi_io_recv_pdu(iscsi_conn_t
*conn
, struct iscsi_hdr
*hdr
,
651 int hdr_digest
, char *data
, int max_data_length
, int data_digest
,
654 uint32_t h_bytes
= 0;
655 uint32_t ahs_bytes
= 0;
656 uint32_t d_bytes
= 0;
657 uint32_t ahslength
= 0;
658 uint32_t dlength
= 0;
662 char *header
= (char *) hdr
;
663 char *end
= data
+ max_data_length
;
664 struct sigaction action
;
665 struct sigaction old
;
666 iscsi_session_t
*session
= conn
->session
;
668 memset(data
, 0, max_data_length
);
670 /* set a timeout, since the socket calls may take a long
671 * time to timeout on their own
674 memset(&action
, 0, sizeof (struct sigaction
));
675 memset(&old
, 0, sizeof (struct sigaction
));
676 action
.sa_sigaction
= NULL
;
678 action
.sa_handler
= sigalarm_handler
;
679 sigaction(SIGALRM
, &action
, &old
);
683 if (ipc
->recv_pdu_begin(conn
)) {
689 /* read a response header */
692 rlen
= read(session
->ctrl_fd
, header
,
693 sizeof (*hdr
) - h_bytes
);
695 rlen
= ipc
->read(header
, sizeof (*hdr
) - h_bytes
);
697 log_error("socket %d header read timed out",
701 } else if (rlen
== 0) {
702 LOG_CONN_CLOSED(conn
);
705 } else if ((rlen
< 0) && (errno
!= EAGAIN
)) {
709 } else if (rlen
> 0) {
710 log_debug(4, "read %d bytes of PDU header", rlen
);
714 } while (h_bytes
< sizeof (*hdr
));
716 log_debug(4, "read %d PDU header bytes, opcode 0x%x, dlength %u, "
717 "data %p, max %u", h_bytes
, hdr
->opcode
,
718 ntoh24(hdr
->dlength
), data
, max_data_length
);
720 /* check for additional headers */
721 ahslength
= hdr
->hlength
; /* already includes padding */
723 log_warning("additional header segment length %u not supported",
729 /* read exactly what we expect, plus padding */
730 dlength
= hdr
->dlength
[0] << 16;
731 dlength
|= hdr
->dlength
[1] << 8;
732 dlength
|= hdr
->dlength
[2];
734 /* if we only expected to receive a header, exit */
738 if (data
+ dlength
> end
) {
739 log_warning("buffer size %u too small for data length %u",
740 max_data_length
, dlength
);
745 /* read the rest into our buffer */
747 while (d_bytes
< dlength
) {
749 rlen
= read(session
->ctrl_fd
, data
+ d_bytes
,
752 rlen
= ipc
->read(data
+ d_bytes
, dlength
- d_bytes
);
754 log_error("socket %d data read timed out",
758 } else if (rlen
== 0) {
759 LOG_CONN_CLOSED(conn
);
762 } else if ((rlen
< 0 && errno
!= EAGAIN
)) {
766 } else if (rlen
> 0) {
767 log_debug(4, "read %d bytes of PDU data", rlen
);
772 /* handle PDU data padding.
773 * data is padded in case of kernel_io */
774 pad
= dlength
% ISCSI_PAD_LEN
;
776 int pad_bytes
= pad
= ISCSI_PAD_LEN
- pad
;
777 char bytes
[ISCSI_PAD_LEN
];
779 while (pad_bytes
> 0) {
780 rlen
= read(conn
->socket_fd
, &bytes
, pad_bytes
);
782 log_error("socket %d pad read timed out",
786 } else if (rlen
== 0) {
787 LOG_CONN_CLOSED(conn
);
790 } else if ((rlen
< 0 && errno
!= EAGAIN
)) {
794 } else if (rlen
> 0) {
795 log_debug(4, "read %d pad bytes", rlen
);
801 switch (hdr
->opcode
) {
802 case ISCSI_OP_TEXT_RSP
:
803 log_debug(4, "finished reading text PDU, %u hdr, %u "
804 "ah, %u data, %u pad",
805 h_bytes
, ahs_bytes
, d_bytes
, pad
);
806 iscsi_log_text(hdr
, data
);
808 case ISCSI_OP_LOGIN_RSP
:{
809 struct iscsi_login_rsp
*login_rsp
=
810 (struct iscsi_login_rsp
*) hdr
;
812 log_debug(4, "finished reading login PDU, %u hdr, "
813 "%u ah, %u data, %u pad",
814 h_bytes
, ahs_bytes
, d_bytes
, pad
);
815 log_debug(4, "login current stage %d, next stage "
817 ISCSI_LOGIN_CURRENT_STAGE(login_rsp
->flags
),
818 ISCSI_LOGIN_NEXT_STAGE(login_rsp
->flags
),
819 login_rsp
->flags
& ISCSI_FLAG_LOGIN_TRANSIT
);
820 iscsi_log_text(hdr
, data
);
823 case ISCSI_OP_ASYNC_EVENT
:
824 /* FIXME: log the event info */
833 sigaction(SIGALRM
, &old
, NULL
);
835 /* finalyze receive transaction */
836 if (ipc
->recv_pdu_end(conn
)) {
841 if (timedout
|| failed
) {
846 return h_bytes
+ ahs_bytes
+ d_bytes
;