int set_tcp_syncnt(struct iscsi_context *iscsi) { if (set_tcp_sockopt(iscsi->fd, TCP_SYNCNT, iscsi->tcp_syncnt) != 0) { iscsi_set_error(iscsi, "TCP: Failed to set tcp syn retries. Error %s(%d)", strerror(errno), errno); return -1; } ISCSI_LOG(iscsi, 3, "TCP_SYNCNT set to %d",iscsi->tcp_syncnt); return 0; }
int set_tcp_user_timeout(struct iscsi_context *iscsi) { if (set_tcp_sockopt(iscsi->fd, TCP_USER_TIMEOUT, iscsi->tcp_user_timeout) != 0) { iscsi_set_error(iscsi, "TCP: Failed to set tcp user timeout. Error %s(%d)", strerror(errno), errno); return -1; } ISCSI_LOG(iscsi, 3, "TCP_USER_TIMEOUT set to %d",iscsi->tcp_user_timeout); return 0; }
static int iscsi_tcp_connect(struct iscsi_context *iscsi, union socket_address *sa, int ai_family) { int socksize; iscsi->fd = socket(ai_family, SOCK_STREAM, 0); if (iscsi->fd == -1) { iscsi_set_error(iscsi, "Failed to open iscsi socket. " "Errno:%s(%d).", strerror(errno), errno); return -1; } if (iscsi->old_iscsi && iscsi->fd != iscsi->old_iscsi->fd) { if (dup2(iscsi->fd, iscsi->old_iscsi->fd) == -1) { return -1; } close(iscsi->fd); iscsi->fd = iscsi->old_iscsi->fd; } set_nonblocking(iscsi->fd); iscsi_set_tcp_keepalive(iscsi, iscsi->tcp_keepidle, iscsi->tcp_keepcnt, iscsi->tcp_keepintvl); if (iscsi->tcp_user_timeout > 0) { set_tcp_user_timeout(iscsi); } if (iscsi->tcp_syncnt > 0) { set_tcp_syncnt(iscsi); } #if __linux if (iscsi->bind_interfaces[0]) { char *pchr = iscsi->bind_interfaces, *pchr2; int iface_n = iface_rr++%iscsi->bind_interfaces_cnt; int iface_c = 0; do { pchr2 = strchr(pchr,','); if (iface_c == iface_n) { if (pchr2) pchr2[0]=0x00; break; } if (pchr2) {pchr=pchr2+1;} iface_c++; } while (pchr2); int res = setsockopt(iscsi->fd, SOL_SOCKET, SO_BINDTODEVICE, pchr, strlen(pchr)); if (res < 0) { ISCSI_LOG(iscsi,1,"failed to bind to interface '%s': %s",pchr,strerror(errno)); } else { ISCSI_LOG(iscsi,3,"successfully bound to interface '%s'",pchr); } if (pchr2) pchr2[0]=','; } #endif if (set_tcp_sockopt(iscsi->fd, TCP_NODELAY, 1) != 0) { ISCSI_LOG(iscsi,1,"failed to set TCP_NODELAY sockopt: %s",strerror(errno)); } else { ISCSI_LOG(iscsi,3,"TCP_NODELAY set to 1"); } socksize = sizeof(struct sockaddr_in); // Work-around for now, need to fix it if (connect(iscsi->fd, &sa->sa, socksize) != 0 && errno != EINPROGRESS) { iscsi_set_error(iscsi, "Connect failed with errno : " "%s(%d)", strerror(errno), errno); close(iscsi->fd); iscsi->fd = -1; return -1; } return 0; }
static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_storage *s) { int socksize; assert(rpc->magic == RPC_CONTEXT_MAGIC); switch (s->ss_family) { case AF_INET: socksize = sizeof(struct sockaddr_in); rpc->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); #ifdef HAVE_NETINET_TCP_H if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) { set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt); } #endif break; case AF_INET6: socksize = sizeof(struct sockaddr_in6); rpc->fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); #ifdef HAVE_NETINET_TCP_H if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) { set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt); } #endif break; default: rpc_set_error(rpc, "Can not handle AF_FAMILY:%d", s->ss_family); return -1; } if (rpc->fd == -1) { rpc_set_error(rpc, "Failed to open socket"); return -1; } /* Some systems allow you to set capabilities on an executable * to allow the file to be executed with privilege to bind to * privileged system ports, even if the user is not root. * * Opportunistically try to bind the socket to a low numbered * system port in the hope that the user is either root or the * executable has the CAP_NET_BIND_SERVICE. * * As soon as we fail the bind() with EACCES we know we will never * be able to bind to a system port so we terminate the loop. * * On linux, use * sudo setcap 'cap_net_bind_service=+ep' /path/executable * to make the executable able to bind to a system port. * * On Windows, there is no concept of privileged ports. Thus * binding will usually succeed. */ { struct sockaddr_storage ss; static int portOfs = 0; const int firstPort = 512; /* >= 512 according to Sun docs */ const int portCount = IPPORT_RESERVED - firstPort; int startOfs, port, rc; if (portOfs == 0) { portOfs = time(NULL) % 400; } startOfs = portOfs; do { rc = -1; port = htons(firstPort + portOfs); portOfs = (portOfs + 1) % portCount; /* skip well-known ports */ if (!getservbyport(port, "tcp")) { memset(&ss, 0, sizeof(ss)); switch (s->ss_family) { case AF_INET: ((struct sockaddr_in *)&ss)->sin_port = port; ((struct sockaddr_in *)&ss)->sin_family = AF_INET; #ifdef HAVE_SOCKADDR_LEN ((struct sockaddr_in *)&ss)->sin_len = sizeof(struct sockaddr_in); #endif break; case AF_INET6: ((struct sockaddr_in6 *)&ss)->sin6_port = port; ((struct sockaddr_in6 *)&ss)->sin6_family = AF_INET6; #ifdef HAVE_SOCKADDR_LEN ((struct sockaddr_in6 *)&ss)->sin6_len = sizeof(struct sockaddr_in6); #endif break; } rc = bind(rpc->fd, (struct sockaddr *)&ss, socksize); #if !defined(WIN32) /* we got EACCES, so don't try again */ if (rc != 0 && errno == EACCES) break; #endif } } while (rc != 0 && portOfs != startOfs); } set_nonblocking(rpc->fd); set_nolinger(rpc->fd); if (connect(rpc->fd, (struct sockaddr *)s, socksize) != 0 && errno != EINPROGRESS) { rpc_set_error(rpc, "connect() to server failed. %s(%d)", strerror(errno), errno); return -1; } return 0; }