diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 6fe6a6bab3f4..7bf6c9a23fa2 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -20,6 +20,7 @@
 #include <asm/unaligned.h>
 #include <linux/inet.h>
 #include <net/ipv6.h>
+#include <net/inet_hashtables.h>
 #include <scsi/scsi_proto.h>
 #include <scsi/iscsi_proto.h>
 #include <scsi/scsi_tcq.h>
@@ -264,13 +265,21 @@ int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg,
 bool iscsit_check_np_match(
 	struct sockaddr_storage *sockaddr,
 	struct iscsi_np *np,
-	int network_transport)
+	int network_transport,
+	char *iface)
 {
 	struct sockaddr_in *sock_in, *sock_in_e;
 	struct sockaddr_in6 *sock_in6, *sock_in6_e;
-	bool ip_match = false;
+	bool ip_match = false, iface_match = false;
 	u16 port, port_e;
 
+	if (iface && np->iface) {
+		if (!    strcmp(iface, np->iface))
+			iface_match = true;
+	} else if (!iface && !np->iface) {
+		iface_match = true;
+	}
+
 	if (sockaddr->ss_family == AF_INET6) {
 		sock_in6 = (struct sockaddr_in6 *)sockaddr;
 		sock_in6_e = (struct sockaddr_in6 *)&np->np_sockaddr;
@@ -294,6 +303,7 @@ bool iscsit_check_np_match(
 	}
 
 	if (ip_match && (port_e == port) &&
+	    iface_match &&
 	    (np->np_network_transport == network_transport))
 		return true;
 
@@ -302,7 +312,8 @@ bool iscsit_check_np_match(
 
 static struct iscsi_np *iscsit_get_np(
 	struct sockaddr_storage *sockaddr,
-	int network_transport)
+	int network_transport,
+	char *iface)
 {
 	struct iscsi_np *np;
 	bool match;
@@ -316,7 +327,7 @@ static struct iscsi_np *iscsit_get_np(
 			continue;
 		}
 
-		match = iscsit_check_np_match(sockaddr, np, network_transport);
+		match = iscsit_check_np_match(sockaddr, np, network_transport, iface);
 		if (match) {
 			/*
 			 * Increment the np_exports reference count now to
@@ -335,17 +346,18 @@ static struct iscsi_np *iscsit_get_np(
 
 struct iscsi_np *iscsit_add_np(
 	struct sockaddr_storage *sockaddr,
-	int network_transport)
+	int network_transport,
+	char *iface)
 {
-	struct iscsi_np *np;
-	int ret;
+	struct iscsi_np	*np;
+	int		ret;
 
 	mutex_lock(&np_lock);
 
 	/*
 	 * Locate the existing struct iscsi_np if already active..
 	 */
-	np = iscsit_get_np(sockaddr, network_transport);
+	np = iscsit_get_np(sockaddr, network_transport, iface);
 	if (np) {
 		mutex_unlock(&np_lock);
 		return np;
@@ -359,6 +371,9 @@ struct iscsi_np *iscsit_add_np(
 
 	np->np_flags |= NPF_IP_NETWORK;
 	np->np_network_transport = network_transport;
+	if (iface) {
+		np->iface = kstrdup(iface, GFP_KERNEL);
+	}
 	spin_lock_init(&np->np_thread_lock);
 	init_completion(&np->np_restart_comp);
 	INIT_LIST_HEAD(&np->np_list);
@@ -468,6 +483,10 @@ int iscsit_del_np(struct iscsi_np *np)
 		&np->np_sockaddr, np->np_transport->name);
 
 	iscsit_put_transport(np->np_transport);
+	if (np->iface) {
+		kfree(np->iface);
+		np->iface = NULL;
+	}
 	kfree(np);
 	return 0;
 }
@@ -1732,7 +1751,7 @@ int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
 		if (!cmd)
 			return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
 						 (unsigned char *)hdr);
-		
+
 		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR,
 					 (unsigned char *)hdr);
 	}
@@ -3343,6 +3362,68 @@ iscsit_send_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 
 #define SENDTARGETS_BUF_LIMIT 32768U
 
+static inline bool match_port(struct sockaddr *addr, struct sock *sk);
+static inline bool match_port(struct sockaddr *addr, struct sock *sk)
+{
+	struct sockaddr_in *sock_in_e;
+	struct sockaddr_in6 *sock_in6_e;
+	u16 port, port_e;
+	__portpair ports;
+
+	port = sk->sk_dport;
+	if (sk->sk_family == AF_INET6) {
+		sock_in6_e = (struct sockaddr_in6 *)addr;
+		port_e = ntohs(sock_in6_e->sin6_port);
+	} else {
+		sock_in_e = (struct sockaddr_in *)addr;
+		port_e = ntohs(sock_in_e->sin_port);
+	}
+	ports = INET_COMBINED_PORTS(port, port_e);
+	return (sk->sk_portpair == ports);
+}
+
+static inline bool match_addr(struct sockaddr *addr, struct sock *sk);
+static inline bool match_addr(struct sockaddr *addr, struct sock *sk)
+{
+	struct sockaddr_in *sock_in_e;
+	struct sockaddr_in6 *sock_in6_e;
+
+	if (inet_addr_is_any(addr))
+		return true;
+	if (sk->sk_family == AF_INET6) {
+		sock_in6_e = (struct sockaddr_in6 *)addr;
+		return (!memcmp(&sk->sk_v6_rcv_saddr,
+					&sock_in6_e->sin6_addr,
+					sizeof(struct in6_addr)));
+	}
+	sock_in_e = (struct sockaddr_in *)addr;
+	return (sk->sk_rcv_saddr == sock_in_e->sin_addr.s_addr);
+}
+
+static bool match_conn(struct iscsi_np *np, struct iscsi_conn *conn);
+static bool match_conn(struct iscsi_np *np, struct iscsi_conn *conn)
+{
+	/*
+	 * when the target listen on ::0 it also replies for 0.0.0.0
+	 * so avoid discarding the packet if it the ss_family does not
+	 * match if the ip we are bound to is one of those.
+	 */
+	if (conn->sock->sk->sk_family != np->np_sockaddr.ss_family
+			&& !inet_addr_is_any((struct sockaddr *)&np->np_sockaddr)) {
+		return false;
+	}
+	if (np->iface != NULL && np->ifindex != conn->sock->sk->sk_bound_dev_if) {
+		return false;
+	}
+	if (!match_port((struct sockaddr *)&np->np_sockaddr, conn->sock->sk)) {
+		return false;
+	}
+	if (!match_addr((struct sockaddr *)&np->np_sockaddr, conn->sock->sk)) {
+		return false;
+	}
+	return true;
+}
+
 static int
 iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
 				  enum iscsit_transport_type network_transport,
@@ -3421,6 +3502,9 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
 				struct iscsi_np *np = tpg_np->tpg_np;
 				struct sockaddr_storage *sockaddr;
 
+				if (match_conn(np, conn) == false)
+					continue;
+
 				if (np->np_network_transport != network_transport)
 					continue;
 
diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h
index b35a96ded9c1..560887c83a23 100644
--- a/drivers/target/iscsi/iscsi_target.h
+++ b/drivers/target/iscsi/iscsi_target.h
@@ -24,9 +24,11 @@ extern void iscsit_login_kref_put(struct kref *);
 extern int iscsit_deaccess_np(struct iscsi_np *, struct iscsi_portal_group *,
 				struct iscsi_tpg_np *);
 extern bool iscsit_check_np_match(struct sockaddr_storage *,
-				struct iscsi_np *, int);
+				struct iscsi_np *, int network_transport,
+				char *iface);
 extern struct iscsi_np *iscsit_add_np(struct sockaddr_storage *,
-				int);
+				int network_transport,
+				char *iface);
 extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *,
 				struct iscsi_portal_group *, bool);
 extern int iscsit_del_np(struct iscsi_np *);
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index 0cedcfe207b5..a1e9217d3479 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -92,7 +92,7 @@ static ssize_t lio_target_np_driver_store(struct config_item *item,
 		}
 
 		tpg_np_new = iscsit_tpg_add_network_portal(tpg,
-					&np->np_sockaddr, tpg_np, type);
+					&np->np_sockaddr, tpg_np, type, np->iface);
 		if (IS_ERR(tpg_np_new)) {
 			rc = PTR_ERR(tpg_np_new);
 			goto out;
@@ -158,7 +158,7 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
 {
 	struct iscsi_portal_group *tpg;
 	struct iscsi_tpg_np *tpg_np;
-	char *str, *str2, *ip_str, *port_str;
+	char *str, *str2, *ip_str, *port_str, *iface_str;
 	struct sockaddr_storage sockaddr = { };
 	int ret;
 	char buf[MAX_PORTAL_LEN + 1] = { };
@@ -202,11 +202,18 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
 		*port_str = '\0'; /* Terminate string for IP */
 		port_str++; /* Skip over ":" */
 	}
-
+	/* now lets look if there is one more ':' with an interface after */
+	iface_str = strstr(port_str, ":");
+	if (iface_str) {
+		/* It is found */
+		*iface_str = '\0'; /* Terminate string for port */
+		iface_str++;
+	}
 	ret = inet_pton_with_scope(&init_net, AF_UNSPEC, ip_str,
 			port_str, &sockaddr);
 	if (ret) {
-		pr_err("malformed ip/port passed: %s\n", name);
+		pr_err("malformed ip/port/interface passed: %s/%s/%s\n",
+			ip_str, port_str, iface_str);
 		return ERR_PTR(ret);
 	}
 
@@ -233,7 +240,7 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
 	 *
 	 */
 	tpg_np = iscsit_tpg_add_network_portal(tpg, &sockaddr, NULL,
-				ISCSI_TCP);
+				ISCSI_TCP, iface_str);
 	if (IS_ERR(tpg_np)) {
 		iscsit_put_tpg(tpg);
 		return ERR_CAST(tpg_np);
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 9c01fb864585..01038fe9f834 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -17,6 +17,7 @@
 #include <linux/tcp.h>        /* TCP_NODELAY */
 #include <net/ip.h>
 #include <net/ipv6.h>         /* ipv6_addr_v4mapped() */
+#include <net/sock.h>          /* sock_bindtoindex() */
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
@@ -856,6 +857,8 @@ int iscsit_setup_np(
 	struct sockaddr_storage *sockaddr)
 {
 	struct socket *sock = NULL;
+	struct net *net = NULL;
+	struct net_device *dev = NULL;
 	int backlog = ISCSIT_TCP_BACKLOG, ret, len;
 
 	switch (np->np_network_transport) {
@@ -902,6 +905,24 @@ int iscsit_setup_np(
 		tcp_sock_set_nodelay(sock->sk);
 	sock_set_reuseaddr(sock->sk);
 	ip_sock_set_freebind(sock->sk);
+	if (np->iface) {
+		net = sock_net(sock->sk);
+		rcu_read_lock();
+		dev = dev_get_by_name_rcu(net, np->iface);
+		if (dev) {
+			np->ifindex = dev->ifindex;
+			rcu_read_unlock();
+			ret = sock_bindtoindex(sock->sk, np->ifindex, true);
+			if (ret < 0) {
+				pr_err("sock_bindtoindex() failed: %d\n", ret);
+				goto fail;
+			}
+		} else {
+			rcu_read_unlock();
+			pr_err("dev_get_by_name_rcu() failed\n");
+			goto fail;
+		}
+	}
 
 	ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len);
 	if (ret < 0) {
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
index 2d5cf1714ae0..2df14a9ab712 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.c
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -423,7 +423,8 @@ struct iscsi_tpg_np *iscsit_tpg_locate_child_np(
 static bool iscsit_tpg_check_network_portal(
 	struct iscsi_tiqn *tiqn,
 	struct sockaddr_storage *sockaddr,
-	int network_transport)
+	int network_transport,
+	char *iface)
 {
 	struct iscsi_portal_group *tpg;
 	struct iscsi_tpg_np *tpg_np;
@@ -438,7 +439,7 @@ static bool iscsit_tpg_check_network_portal(
 			np = tpg_np->tpg_np;
 
 			match = iscsit_check_np_match(sockaddr, np,
-						network_transport);
+						network_transport, iface);
 			if (match)
 				break;
 		}
@@ -456,14 +457,15 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
 	struct iscsi_portal_group *tpg,
 	struct sockaddr_storage *sockaddr,
 	struct iscsi_tpg_np *tpg_np_parent,
-	int network_transport)
+	int network_transport,
+	char *iface)
 {
 	struct iscsi_np *np;
 	struct iscsi_tpg_np *tpg_np;
 
 	if (!tpg_np_parent) {
 		if (iscsit_tpg_check_network_portal(tpg->tpg_tiqn, sockaddr,
-				network_transport)) {
+				network_transport, iface)) {
 			pr_err("Network Portal: %pISc already exists on a"
 				" different TPG on %s\n", sockaddr,
 				tpg->tpg_tiqn->tiqn);
@@ -478,7 +480,7 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
 		return ERR_PTR(-ENOMEM);
 	}
 
-	np = iscsit_add_np(sockaddr, network_transport);
+	np = iscsit_add_np(sockaddr, network_transport, iface);
 	if (IS_ERR(np)) {
 		kfree(tpg_np);
 		return ERR_CAST(np);
diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h
index 88576f5d0ca4..bc8b8e81fdb6 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.h
+++ b/drivers/target/iscsi/iscsi_target_tpg.h
@@ -33,7 +33,7 @@ extern void iscsit_tpg_del_external_nps(struct iscsi_tpg_np *);
 extern struct iscsi_tpg_np *iscsit_tpg_locate_child_np(struct iscsi_tpg_np *, int);
 extern struct iscsi_tpg_np *iscsit_tpg_add_network_portal(struct iscsi_portal_group *,
 			struct sockaddr_storage *, struct iscsi_tpg_np *,
-			int);
+			int network_transport, char *iface);
 extern int iscsit_tpg_del_network_portal(struct iscsi_portal_group *,
 			struct iscsi_tpg_np *);
 extern int iscsit_ta_authentication(struct iscsi_portal_group *, u32);
diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h
index adc87de0362b..8e8aeab4916b 100644
--- a/include/target/iscsi/iscsi_target_core.h
+++ b/include/target/iscsi/iscsi_target_core.h
@@ -795,6 +795,8 @@ struct iscsi_np {
 	void			*np_context;
 	struct iscsit_transport *np_transport;
 	struct list_head	np_list;
+	char 			*iface;
+	int			ifindex;
 } ____cacheline_aligned;
 
 struct iscsi_tpg_np {
