@@ -242,3 +242,188 @@ int mptcp_nl_cmd_remove(struct sk_buff *skb, struct genl_info *info)
242
242
sock_put ((struct sock * )msk );
243
243
return err ;
244
244
}
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