return NULL;
 }
 
+static struct tcp_ulp_ops *tcp_ulp_find_id(const int ulp)
+{
+       struct tcp_ulp_ops *e;
+
+       list_for_each_entry_rcu(e, &tcp_ulp_list, list) {
+               if (e->uid == ulp)
+                       return e;
+       }
+
+       return NULL;
+}
+
 static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name)
 {
        const struct tcp_ulp_ops *ulp = NULL;
        return ulp;
 }
 
+static const struct tcp_ulp_ops *__tcp_ulp_lookup(const int uid)
+{
+       const struct tcp_ulp_ops *ulp;
+
+       rcu_read_lock();
+       ulp = tcp_ulp_find_id(uid);
+       if (!ulp || !try_module_get(ulp->owner))
+               ulp = NULL;
+       rcu_read_unlock();
+       return ulp;
+}
+
 /* Attach new upper layer protocol to the list
  * of available protocols.
  */
        int ret = 0;
 
        spin_lock(&tcp_ulp_list_lock);
-       if (tcp_ulp_find(ulp->name)) {
-               pr_notice("%s already registered or non-unique name\n",
-                         ulp->name);
+       if (tcp_ulp_find(ulp->name))
                ret = -EEXIST;
-       } else {
+       else
                list_add_tail_rcu(&ulp->list, &tcp_ulp_list);
-       }
        spin_unlock(&tcp_ulp_list_lock);
 
        return ret;
        if (!ulp_ops)
                return -ENOENT;
 
+       if (!ulp_ops->user_visible) {
+               module_put(ulp_ops->owner);
+               return -ENOENT;
+       }
+
+       err = ulp_ops->init(sk);
+       if (err) {
+               module_put(ulp_ops->owner);
+               return err;
+       }
+
+       icsk->icsk_ulp_ops = ulp_ops;
+       return 0;
+}
+
+int tcp_set_ulp_id(struct sock *sk, int ulp)
+{
+       struct inet_connection_sock *icsk = inet_csk(sk);
+       const struct tcp_ulp_ops *ulp_ops;
+       int err;
+
+       if (icsk->icsk_ulp_ops)
+               return -EEXIST;
+
+       ulp_ops = __tcp_ulp_lookup(ulp);
+       if (!ulp_ops)
+               return -ENOENT;
+
        err = ulp_ops->init(sk);
        if (err) {
                module_put(ulp_ops->owner);