diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 8d209b9..c16d672 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -68,6 +68,7 @@ struct iscsi_context { char connected_portal[MAX_STRING_SIZE+1]; char portal[MAX_STRING_SIZE+1]; char alias[MAX_STRING_SIZE+1]; + char bind_interfaces[MAX_STRING_SIZE+1]; char user[MAX_STRING_SIZE+1]; char passwd[MAX_STRING_SIZE+1]; @@ -102,6 +103,7 @@ struct iscsi_context { int login_attempts; int is_loggedin; int is_reconnecting; + int bind_interface_cnt; int chap_a; int chap_i; diff --git a/include/iscsi.h b/include/iscsi.h index 6ac7f0e..fde65c8 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -1028,6 +1028,13 @@ iscsi_set_tcp_keepintvl(struct iscsi_context *iscsi, int value); EXTERN void iscsi_set_tcp_syncnt(struct iscsi_context *iscsi, int value); +/* + * This function is to set the interface that outbound connections for this socket are bound to. + * You max specify more than one interface here separated by comma. + */ +EXTERN void +iscsi_set_bind_interfaces(struct iscsi_context *iscsi, char * interfaces); + #ifdef __cplusplus } #endif diff --git a/lib/init.c b/lib/init.c index 2fdc3c2..2540779 100644 --- a/lib/init.c +++ b/lib/init.c @@ -134,6 +134,10 @@ iscsi_create_context(const char *initiator_name) iscsi_set_tcp_syncnt(iscsi,atoi(getenv("LIBISCSI_TCP_SYNCNT"))); } + if (getenv("LIBISCSI_BIND_INTERFACES") != NULL) { + iscsi_set_bind_interfaces(iscsi,getenv("LIBISCSI_BIND_INTERFACES")); + } + return iscsi; } diff --git a/lib/libiscsi.def b/lib/libiscsi.def index c3a915c..95f4552 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -79,6 +79,7 @@ iscsi_set_tcp_keepidle iscsi_set_tcp_keepcnt iscsi_set_tcp_keepintvl iscsi_set_tcp_syncnt +iscsi_set_bind_interface iscsi_startstopunit_sync iscsi_startstopunit_task iscsi_synchronizecache10_sync diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index ddf3e1a..4eaeb67 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -77,6 +77,7 @@ iscsi_set_tcp_keepidle iscsi_set_tcp_keepcnt iscsi_set_tcp_keepintvl iscsi_set_tcp_syncnt +iscsi_set_bind_interface iscsi_startstopunit_sync iscsi_startstopunit_task iscsi_synchronizecache10_sync diff --git a/lib/socket.c b/lib/socket.c index 0566dc9..84b427e 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -216,6 +216,30 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal, set_tcp_syncnt(iscsi); } +#if __linux + if (iscsi->bind_interfaces[0]) { + char *pchr = iscsi->bind_interfaces, *pchr2; + int iface_n = rand()%iscsi->bind_interface_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;} + } while (pchr2); + + int res = setsockopt(iscsi->fd, SOL_SOCKET, SO_BINDTODEVICE, pchr, strlen(pchr)); + if (res < 0) { + DPRINTF(iscsi,1,"failed to bind to interface '%s': %s",pchr,strerror(errno)); + } else { + DPRINTF(iscsi,3,"successfully bound to interface '%s'",pchr); + } + if (pchr2) pchr2[0]=','; + } +#endif + if (connect(iscsi->fd, ai->ai_addr, socksize) != 0 && errno != EINPROGRESS) { iscsi_set_error(iscsi, "Connect failed with errno : " @@ -647,3 +671,21 @@ int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, in return 0; } + +void iscsi_set_bind_interfaces(struct iscsi_context *iscsi, char * interfaces) +{ +#if __linux + strncpy(iscsi->bind_interfaces,interfaces,MAX_STRING_SIZE); + iscsi->bind_interface_cnt=0; + char * pchr = interfaces; + char * pchr2 = NULL; + do { + pchr2 = strchr(pchr,','); + if (pchr2) {pchr=pchr2+1;} + iscsi->bind_interface_cnt++; + } while (pchr2); + DPRINTF(iscsi,2,"will bind to one of the following %d interface(s) on next socket creation: %s",iscsi->bind_interface_cnt,interfaces); +#else + DPRINTF(iscsi,1,"binding to an interface is not supported on your OS"); +#endif +}