MPTCP_PM_ADDR_FLAG_SIGNAL;
 }
 
+/* caller must ensure the RCU grace period is already elapsed */
+static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
+{
+       if (entry->lsk)
+               sock_release(entry->lsk);
+       kfree(entry);
+}
+
 static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
                                             struct mptcp_pm_addr_entry *entry)
 {
-       struct mptcp_pm_addr_entry *cur;
+       struct mptcp_pm_addr_entry *cur, *del_entry = NULL;
        unsigned int addr_max;
        int ret = -EINVAL;
 
        list_for_each_entry(cur, &pernet->local_addr_list, list) {
                if (addresses_equal(&cur->addr, &entry->addr,
                                    address_use_port(entry) &&
-                                   address_use_port(cur)))
-                       goto out;
+                                   address_use_port(cur))) {
+                       /* allow replacing the exiting endpoint only if such
+                        * endpoint is an implicit one and the user-space
+                        * did not provide an endpoint id
+                        */
+                       if (!(cur->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT))
+                               goto out;
+                       if (entry->addr.id)
+                               goto out;
+
+                       pernet->addrs--;
+                       entry->addr.id = cur->addr.id;
+                       list_del_rcu(&cur->list);
+                       del_entry = cur;
+                       break;
+               }
        }
 
        if (!entry->addr.id) {
 
 out:
        spin_unlock_bh(&pernet->lock);
+
+       /* just replaced an existing entry, free it */
+       if (del_entry) {
+               synchronize_rcu();
+               __mptcp_pm_release_addr_entry(del_entry);
+       }
        return ret;
 }
 
        entry->addr.id = 0;
        entry->addr.port = 0;
        entry->ifindex = 0;
-       entry->flags = 0;
+       entry->flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
        entry->lsk = NULL;
        ret = mptcp_pm_nl_append_new_local_addr(pernet, entry);
        if (ret < 0)
                return -EINVAL;
        }
 
+       if (addr.flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
+               GENL_SET_ERR_MSG(info, "can't create IMPLICIT endpoint");
+               return -EINVAL;
+       }
+
        entry = kmalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry) {
                GENL_SET_ERR_MSG(info, "can't allocate addr");
 }
 
 static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
-                                                  struct mptcp_addr_info *addr)
+                                                  const struct mptcp_pm_addr_entry *entry)
 {
-       struct mptcp_sock *msk;
-       long s_slot = 0, s_num = 0;
+       const struct mptcp_addr_info *addr = &entry->addr;
        struct mptcp_rm_list list = { .nr = 0 };
+       long s_slot = 0, s_num = 0;
+       struct mptcp_sock *msk;
 
        pr_debug("remove_id=%d", addr->id);
 
 
                lock_sock(sk);
                remove_subflow = lookup_subflow_by_saddr(&msk->conn_list, addr);
-               mptcp_pm_remove_anno_addr(msk, addr, remove_subflow);
+               mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
+                                         !(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
                if (remove_subflow)
                        mptcp_pm_remove_subflow(msk, &list);
                release_sock(sk);
        return 0;
 }
 
-/* caller must ensure the RCU grace period is already elapsed */
-static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
-{
-       if (entry->lsk)
-               sock_release(entry->lsk);
-       kfree(entry);
-}
-
 static int mptcp_nl_remove_id_zero_address(struct net *net,
                                           struct mptcp_addr_info *addr)
 {
        __clear_bit(entry->addr.id, pernet->id_bitmap);
        spin_unlock_bh(&pernet->lock);
 
-       mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
+       mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), entry);
        synchronize_rcu();
        __mptcp_pm_release_addr_entry(entry);