@@ -26,6 +26,7 @@ struct mptcp_pm_addr_entry {
2626 struct list_head list ;
2727 struct mptcp_addr_info addr ;
2828 struct rcu_head rcu ;
29+ struct socket * lsk ;
2930};
3031
3132struct mptcp_pm_add_entry {
@@ -678,6 +679,53 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
678679 return ret ;
679680}
680681
682+ static int mptcp_pm_nl_create_listen_socket (struct sock * sk ,
683+ struct mptcp_pm_addr_entry * entry )
684+ {
685+ struct sockaddr_storage addr ;
686+ struct mptcp_sock * msk ;
687+ struct socket * ssock ;
688+ int backlog = 1024 ;
689+ int err ;
690+
691+ err = sock_create_kern (sock_net (sk ), entry -> addr .family ,
692+ SOCK_STREAM , IPPROTO_MPTCP , & entry -> lsk );
693+ if (err )
694+ return err ;
695+
696+ msk = mptcp_sk (entry -> lsk -> sk );
697+ if (!msk ) {
698+ err = - EINVAL ;
699+ goto out ;
700+ }
701+
702+ ssock = __mptcp_nmpc_socket (msk );
703+ if (!ssock ) {
704+ err = - EINVAL ;
705+ goto out ;
706+ }
707+
708+ mptcp_info2sockaddr (& entry -> addr , & addr , entry -> addr .family );
709+ err = kernel_bind (ssock , (struct sockaddr * )& addr ,
710+ sizeof (struct sockaddr_in ));
711+ if (err ) {
712+ pr_warn ("kernel_bind error, err=%d" , err );
713+ goto out ;
714+ }
715+
716+ err = kernel_listen (ssock , backlog );
717+ if (err ) {
718+ pr_warn ("kernel_listen error, err=%d" , err );
719+ goto out ;
720+ }
721+
722+ return 0 ;
723+
724+ out :
725+ sock_release (entry -> lsk );
726+ return err ;
727+ }
728+
681729int mptcp_pm_nl_get_local_id (struct mptcp_sock * msk , struct sock_common * skc )
682730{
683731 struct mptcp_pm_addr_entry * entry ;
@@ -722,6 +770,8 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
722770 entry -> addr .ifindex = 0 ;
723771 entry -> addr .flags = 0 ;
724772 entry -> addr .id = 0 ;
773+ entry -> addr .port = 0 ;
774+ entry -> lsk = NULL ;
725775 ret = mptcp_pm_nl_append_new_local_addr (pernet , entry );
726776 if (ret < 0 )
727777 kfree (entry );
@@ -891,9 +941,19 @@ static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info)
891941 }
892942
893943 * entry = addr ;
944+ if (entry -> addr .port ) {
945+ ret = mptcp_pm_nl_create_listen_socket (skb -> sk , entry );
946+ if (ret ) {
947+ GENL_SET_ERR_MSG (info , "create listen socket error" );
948+ kfree (entry );
949+ return ret ;
950+ }
951+ }
894952 ret = mptcp_pm_nl_append_new_local_addr (pernet , entry );
895953 if (ret < 0 ) {
896954 GENL_SET_ERR_MSG (info , "too many addresses or duplicate one" );
955+ if (entry -> lsk )
956+ sock_release (entry -> lsk );
897957 kfree (entry );
898958 return ret ;
899959 }
@@ -977,6 +1037,38 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
9771037 return 0 ;
9781038}
9791039
1040+ struct addr_entry_release_work {
1041+ struct rcu_work rwork ;
1042+ struct mptcp_pm_addr_entry * entry ;
1043+ };
1044+
1045+ static void mptcp_pm_release_addr_entry (struct work_struct * work )
1046+ {
1047+ struct addr_entry_release_work * w ;
1048+ struct mptcp_pm_addr_entry * entry ;
1049+
1050+ w = container_of (to_rcu_work (work ), struct addr_entry_release_work , rwork );
1051+ entry = w -> entry ;
1052+ if (entry ) {
1053+ if (entry -> lsk )
1054+ sock_release (entry -> lsk );
1055+ kfree (entry );
1056+ }
1057+ kfree (w );
1058+ }
1059+
1060+ static void mptcp_pm_free_addr_entry (struct mptcp_pm_addr_entry * entry )
1061+ {
1062+ struct addr_entry_release_work * w ;
1063+
1064+ w = kmalloc (sizeof (* w ), GFP_ATOMIC );
1065+ if (w ) {
1066+ INIT_RCU_WORK (& w -> rwork , mptcp_pm_release_addr_entry );
1067+ w -> entry = entry ;
1068+ queue_rcu_work (system_wq , & w -> rwork );
1069+ }
1070+ }
1071+
9801072static int mptcp_nl_cmd_del_addr (struct sk_buff * skb , struct genl_info * info )
9811073{
9821074 struct nlattr * attr = info -> attrs [MPTCP_PM_ATTR_ADDR ];
@@ -1011,7 +1103,7 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
10111103 spin_unlock_bh (& pernet -> lock );
10121104
10131105 mptcp_nl_remove_subflow_and_signal_addr (sock_net (skb -> sk ), & entry -> addr );
1014- kfree_rcu (entry , rcu );
1106+ mptcp_pm_free_addr_entry (entry );
10151107
10161108 return ret ;
10171109}
@@ -1025,7 +1117,7 @@ static void __flush_addrs(struct net *net, struct list_head *list)
10251117 struct mptcp_pm_addr_entry , list );
10261118 mptcp_nl_remove_subflow_and_signal_addr (net , & cur -> addr );
10271119 list_del_rcu (& cur -> list );
1028- kfree_rcu (cur , rcu );
1120+ mptcp_pm_free_addr_entry (cur );
10291121 }
10301122}
10311123
0 commit comments