@@ -242,3 +242,188 @@ int mptcp_nl_cmd_remove(struct sk_buff *skb, struct genl_info *info)
242242 sock_put ((struct sock * )msk );
243243 return err ;
244244}
245+
246+ int mptcp_nl_cmd_sf_create (struct sk_buff * skb , struct genl_info * info )
247+ {
248+ struct nlattr * raddr = info -> attrs [MPTCP_PM_ATTR_ADDR_REMOTE ];
249+ struct nlattr * token = info -> attrs [MPTCP_PM_ATTR_TOKEN ];
250+ struct nlattr * laddr = info -> attrs [MPTCP_PM_ATTR_ADDR ];
251+ struct mptcp_addr_info addr_r ;
252+ struct mptcp_addr_info addr_l ;
253+ struct mptcp_sock * msk ;
254+ int err = - EINVAL ;
255+ struct sock * sk ;
256+ u32 token_val ;
257+
258+ if (!laddr || !raddr || !token ) {
259+ GENL_SET_ERR_MSG (info , "missing required inputs" );
260+ return err ;
261+ }
262+
263+ token_val = nla_get_u32 (token );
264+
265+ msk = mptcp_token_get_sock (genl_info_net (info ), token_val );
266+ if (!msk ) {
267+ NL_SET_ERR_MSG_ATTR (info -> extack , token , "invalid token" );
268+ return err ;
269+ }
270+
271+ if (!mptcp_pm_is_userspace (msk )) {
272+ GENL_SET_ERR_MSG (info , "invalid request; userspace PM not selected" );
273+ goto create_err ;
274+ }
275+
276+ err = mptcp_pm_parse_addr (laddr , info , & addr_l );
277+ if (err < 0 ) {
278+ NL_SET_ERR_MSG_ATTR (info -> extack , laddr , "error parsing local addr" );
279+ goto create_err ;
280+ }
281+
282+ if (addr_l .id == 0 ) {
283+ NL_SET_ERR_MSG_ATTR (info -> extack , laddr , "missing local addr id" );
284+ goto create_err ;
285+ }
286+
287+ err = mptcp_pm_parse_addr (raddr , info , & addr_r );
288+ if (err < 0 ) {
289+ NL_SET_ERR_MSG_ATTR (info -> extack , raddr , "error parsing remote addr" );
290+ goto create_err ;
291+ }
292+
293+ sk = & msk -> sk .icsk_inet .sk ;
294+ lock_sock (sk );
295+
296+ err = __mptcp_subflow_connect (sk , & addr_l , & addr_r );
297+
298+ release_sock (sk );
299+
300+ create_err :
301+ sock_put ((struct sock * )msk );
302+ return err ;
303+ }
304+
305+ static struct sock * mptcp_nl_find_ssk (struct mptcp_sock * msk ,
306+ const struct mptcp_addr_info * local ,
307+ const struct mptcp_addr_info * remote )
308+ {
309+ struct sock * sk = & msk -> sk .icsk_inet .sk ;
310+ struct mptcp_subflow_context * subflow ;
311+ struct sock * found = NULL ;
312+
313+ if (local -> family != remote -> family )
314+ return NULL ;
315+
316+ lock_sock (sk );
317+
318+ mptcp_for_each_subflow (msk , subflow ) {
319+ const struct inet_sock * issk ;
320+ struct sock * ssk ;
321+
322+ ssk = mptcp_subflow_tcp_sock (subflow );
323+
324+ if (local -> family != ssk -> sk_family )
325+ continue ;
326+
327+ issk = inet_sk (ssk );
328+
329+ switch (ssk -> sk_family ) {
330+ case AF_INET :
331+ if (issk -> inet_saddr != local -> addr .s_addr ||
332+ issk -> inet_daddr != remote -> addr .s_addr )
333+ continue ;
334+ break ;
335+ #if IS_ENABLED (CONFIG_MPTCP_IPV6 )
336+ case AF_INET6 : {
337+ const struct ipv6_pinfo * pinfo = inet6_sk (ssk );
338+
339+ if (!ipv6_addr_equal (& local -> addr6 , & pinfo -> saddr ) ||
340+ !ipv6_addr_equal (& remote -> addr6 , & ssk -> sk_v6_daddr ))
341+ continue ;
342+ break ;
343+ }
344+ #endif
345+ default :
346+ continue ;
347+ }
348+
349+ if (issk -> inet_sport == local -> port &&
350+ issk -> inet_dport == remote -> port ) {
351+ found = ssk ;
352+ goto found ;
353+ }
354+ }
355+
356+ found :
357+ release_sock (sk );
358+
359+ return found ;
360+ }
361+
362+ int mptcp_nl_cmd_sf_destroy (struct sk_buff * skb , struct genl_info * info )
363+ {
364+ struct nlattr * raddr = info -> attrs [MPTCP_PM_ATTR_ADDR_REMOTE ];
365+ struct nlattr * token = info -> attrs [MPTCP_PM_ATTR_TOKEN ];
366+ struct nlattr * laddr = info -> attrs [MPTCP_PM_ATTR_ADDR ];
367+ struct mptcp_addr_info addr_l ;
368+ struct mptcp_addr_info addr_r ;
369+ struct mptcp_sock * msk ;
370+ struct sock * sk , * ssk ;
371+ int err = - EINVAL ;
372+ u32 token_val ;
373+
374+ if (!laddr || !raddr || !token ) {
375+ GENL_SET_ERR_MSG (info , "missing required inputs" );
376+ return err ;
377+ }
378+
379+ token_val = nla_get_u32 (token );
380+
381+ msk = mptcp_token_get_sock (genl_info_net (info ), token_val );
382+ if (!msk ) {
383+ NL_SET_ERR_MSG_ATTR (info -> extack , token , "invalid token" );
384+ return err ;
385+ }
386+
387+ if (!mptcp_pm_is_userspace (msk )) {
388+ GENL_SET_ERR_MSG (info , "invalid request; userspace PM not selected" );
389+ goto destroy_err ;
390+ }
391+
392+ err = mptcp_pm_parse_addr (laddr , info , & addr_l );
393+ if (err < 0 ) {
394+ NL_SET_ERR_MSG_ATTR (info -> extack , laddr , "error parsing local addr" );
395+ goto destroy_err ;
396+ }
397+
398+ err = mptcp_pm_parse_addr (raddr , info , & addr_r );
399+ if (err < 0 ) {
400+ NL_SET_ERR_MSG_ATTR (info -> extack , raddr , "error parsing remote addr" );
401+ goto destroy_err ;
402+ }
403+
404+ if (addr_l .family != addr_r .family ) {
405+ GENL_SET_ERR_MSG (info , "address families do not match" );
406+ goto destroy_err ;
407+ }
408+
409+ if (!addr_l .port || !addr_r .port ) {
410+ GENL_SET_ERR_MSG (info , "missing local or remote port" );
411+ goto destroy_err ;
412+ }
413+
414+ sk = & msk -> sk .icsk_inet .sk ;
415+ ssk = mptcp_nl_find_ssk (msk , & addr_l , & addr_r );
416+ if (ssk ) {
417+ struct mptcp_subflow_context * subflow = mptcp_subflow_ctx (ssk );
418+
419+ mptcp_subflow_shutdown (sk , ssk , RCV_SHUTDOWN | SEND_SHUTDOWN );
420+ mptcp_close_ssk (sk , ssk , subflow );
421+ err = 0 ;
422+ } else {
423+ err = - ESRCH ;
424+ }
425+
426+ destroy_err :
427+ sock_put ((struct sock * )msk );
428+ return err ;
429+ }
0 commit comments