static int
 iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
-                   struct iscsi_cls_conn *cls_conn, uint32_t transport_fd,
+                   struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
                    int is_leading)
 {
        struct iscsi_conn *conn = cls_conn->dd_data;
        int err;
 
        /* lookup for existing socket */
-       sock = sockfd_lookup(transport_fd, &err);
+       sock = sockfd_lookup((int)transport_eph, &err);
        if (!sock) {
                printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);
                return -EEXIST;
 
        return err;
 }
 
+static int
+iscsi_if_transport_ep(struct iscsi_transport *transport,
+                     struct iscsi_uevent *ev, int msg_type)
+{
+       struct sockaddr *dst_addr;
+       int rc = 0;
+
+       switch (msg_type) {
+       case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
+               if (!transport->ep_connect)
+                       return -EINVAL;
+
+               dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
+               rc = transport->ep_connect(dst_addr,
+                                          ev->u.ep_connect.non_blocking,
+                                          &ev->r.ep_connect_ret.handle);
+               break;
+       case ISCSI_UEVENT_TRANSPORT_EP_POLL:
+               if (!transport->ep_poll)
+                       return -EINVAL;
+
+               ev->r.retcode = transport->ep_poll(ev->u.ep_poll.ep_handle,
+                                                  ev->u.ep_poll.timeout_ms);
+               break;
+       case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+               if (!transport->ep_disconnect)
+                       return -EINVAL;
+
+               transport->ep_disconnect(ev->u.ep_disconnect.ep_handle);
+               break;
+       }
+       return rc;
+}
+
 static int
 iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 
                if (session && conn)
                        ev->r.retcode = transport->bind_conn(session, conn,
-                                       ev->u.b_conn.transport_fd,
+                                       ev->u.b_conn.transport_eph,
                                        ev->u.b_conn.is_leading);
                else
                        err = -EINVAL;
        case ISCSI_UEVENT_GET_STATS:
                err = iscsi_if_get_stats(transport, nlh);
                break;
+       case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
+       case ISCSI_UEVENT_TRANSPORT_EP_POLL:
+       case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+               err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
+               break;
        default:
                err = -EINVAL;
                break;
 
        ISCSI_UEVENT_GET_STATS          = UEVENT_BASE + 10,
        ISCSI_UEVENT_GET_PARAM          = UEVENT_BASE + 11,
 
+       ISCSI_UEVENT_TRANSPORT_EP_CONNECT       = UEVENT_BASE + 12,
+       ISCSI_UEVENT_TRANSPORT_EP_POLL          = UEVENT_BASE + 13,
+       ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT    = UEVENT_BASE + 14,
+
        /* up events */
        ISCSI_KEVENT_RECV_PDU           = KEVENT_BASE + 1,
        ISCSI_KEVENT_CONN_ERROR         = KEVENT_BASE + 2,
                struct msg_bind_conn {
                        uint32_t        sid;
                        uint32_t        cid;
-                       uint32_t        transport_fd;
+                       uint64_t        transport_eph;
                        uint32_t        is_leading;
                } b_conn;
                struct msg_destroy_conn {
                        uint32_t        sid;
                        uint32_t        cid;
                } get_stats;
+               struct msg_transport_connect {
+                       uint32_t        non_blocking;
+               } ep_connect;
+               struct msg_transport_poll {
+                       uint64_t        ep_handle;
+                       uint32_t        timeout_ms;
+               } ep_poll;
+               struct msg_transport_disconnect {
+                       uint64_t        ep_handle;
+               } ep_disconnect;
        } u;
        union {
                /* messages k -> u */
                        uint32_t        cid;
                        uint32_t        error; /* enum iscsi_err */
                } connerror;
+               struct msg_transport_connect_ret {
+                       uint64_t        handle;
+               } ep_connect_ret;
        } r;
 } __attribute__ ((aligned (sizeof(uint64_t))));
 
 
                                uint32_t cid);
        int (*bind_conn) (struct iscsi_cls_session *session,
                          struct iscsi_cls_conn *cls_conn,
-                         uint32_t transport_fd, int is_leading);
+                         uint64_t transport_eph, int is_leading);
        int (*start_conn) (struct iscsi_cls_conn *conn);
        void (*stop_conn) (struct iscsi_cls_conn *conn, int flag);
        void (*destroy_conn) (struct iscsi_cls_conn *conn);
        int (*xmit_mgmt_task) (struct iscsi_conn *conn,
                               struct iscsi_mgmt_task *mtask);
        void (*session_recovery_timedout) (struct iscsi_cls_session *session);
+       int (*ep_connect) (struct sockaddr *dst_addr, int non_blocking,
+                          uint64_t *ep_handle);
+       int (*ep_poll) (uint64_t ep_handle, int timeout_ms);
+       void (*ep_disconnect) (uint64_t ep_handle);
 };
 
 /*