@@ -60,6 +60,9 @@ struct tc_object {
6060
6161#if defined(USE_NETLINK ) && (USE_NETLINK == 1 )
6262static int pack_key (struct tc_u32_sel * sel , uint32_t key , uint32_t mask , int off , int offmask );
63+ static int pack_key8 (struct tc_u32_sel * sel , uint32_t key , uint32_t mask , int off , int offmask );
64+ static int pack_key16 (struct tc_u32_sel * sel , uint32_t key , uint32_t mask , int off , int offmask );
65+ static int pack_key32 (struct tc_u32_sel * sel , uint32_t key , uint32_t mask , int off , int offmask );
6366#endif /* USE_NETLINK */
6467
6568
@@ -286,7 +289,7 @@ int tc_add_filter_link(tc_t tc, int ifindex, int prio, int ht, int id, uint32_t
286289 * dst: 16
287290 * addr/mask: ip/0xffffffff
288291 */
289- pack_key (& opt_sel .sel , ip , 0xffffffff , 16 , 0 );
292+ pack_key32 (& opt_sel .sel , ntohl ( ip ) , 0xffffffff , 16 , 0 );
290293 nl_attr_add (& tc -> req .hdr , TCA_U32_SEL , & opt_sel , sizeof (opt_sel .sel ) + opt_sel .sel .nkeys * sizeof (opt_sel .sel .keys [0 ]));
291294 nl_attr_nest_end (& tc -> req .hdr , opts );
292295
@@ -385,9 +388,9 @@ int tc_add_filter_tap2dev(tc_t tc, int ifindex, int prio, int id, uint32_t ip, i
385388 * addr/mask: ip/0xffffffff
386389 */
387390 if (ip ) {
388- pack_key (& opt_sel .sel , ip , 0xffffffff , 16 , 0 );
391+ pack_key32 (& opt_sel .sel , ntohl ( ip ) , 0xffffffff , 16 , 0 );
389392 } else {
390- pack_key (& opt_sel .sel , ip , 0 , 0 , 0 );
393+ pack_key32 (& opt_sel .sel , ntohl ( ip ) , 0 , 0 , 0 );
391394 }
392395 opt_sel .sel .flags |= TC_U32_TERMINAL ;
393396 nl_attr_add (& tc -> req .hdr , TCA_U32_SEL , & opt_sel , sizeof (opt_sel .sel ) + opt_sel .sel .nkeys * sizeof (opt_sel .sel .keys [0 ]));
@@ -442,6 +445,245 @@ int tc_add_filter_tap2dev(tc_t tc, int ifindex, int prio, int id, uint32_t ip, i
442445 return rc ;
443446}
444447
448+ int tc_add_filter_dev2tap_3t (tc_t tc , int ifindex , int prio , int ht , int bkt , int id ,
449+ int proto , uint32_t dst_ip , uint16_t dst_port , int ifindex_to )
450+ {
451+ int rc = 0 ;
452+
453+ #if defined(USE_NETLINK ) && (USE_NETLINK == 1 )
454+ struct tc_qdisc qdisc = {HANDLE_SET (0 , 0 , id ), 0xffff0000 , prio };
455+ char opt_kind [] = "u32" ;
456+ uint32_t opt_ht = HANDLE_SET (ht , bkt , 0 );
457+ struct rtattr * opts = NULL ;
458+ struct {
459+ struct tc_u32_sel sel ;
460+ struct tc_u32_key keys [10 ];
461+ } opt_sel ;
462+
463+ tc_req (tc , ifindex , RTM_NEWTFILTER ,
464+ (NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE ),
465+ qdisc );
466+
467+ nl_attr_add (& tc -> req .hdr , TCA_KIND , opt_kind , sizeof (opt_kind ));
468+
469+ /* [filter] options filling */
470+ opts = nl_attr_nest_start (& tc -> req .hdr , TCA_OPTIONS );
471+ {
472+ struct rtattr * opts_action = NULL ;
473+
474+ /* [action] options filling */
475+ opts_action = nl_attr_nest_start (& tc -> req .hdr , TCA_U32_ACT );
476+ {
477+ int prio = 0 ;
478+ char opt_act_kind [] = "mirred" ;
479+ struct rtattr * opts_action_prio = NULL ;
480+
481+ /* [mirred] options filling */
482+ opts_action_prio = nl_attr_nest_start (& tc -> req .hdr , ++ prio );
483+ nl_attr_add (& tc -> req .hdr , TCA_ACT_KIND , opt_act_kind , sizeof (opt_act_kind ));
484+ {
485+ struct rtattr * opts_action_prio_mirred = NULL ;
486+ struct tc_mirred opt_mirred ;
487+
488+ opts_action_prio_mirred = nl_attr_nest_start (& tc -> req .hdr , TCA_ACT_OPTIONS );
489+ memset (& opt_mirred , 0 , sizeof (opt_mirred ));
490+ opt_mirred .eaction = TCA_EGRESS_REDIR ;
491+ opt_mirred .action = TC_ACT_STOLEN ;
492+ opt_mirred .ifindex = ifindex_to ;
493+ nl_attr_add (& tc -> req .hdr , TCA_MIRRED_PARMS , & opt_mirred , sizeof (opt_mirred ));
494+
495+ nl_attr_nest_end (& tc -> req .hdr , opts_action_prio_mirred );
496+ }
497+
498+ nl_attr_nest_end (& tc -> req .hdr , opts_action_prio );
499+ }
500+
501+ nl_attr_nest_end (& tc -> req .hdr , opts_action );
502+ }
503+
504+ nl_attr_add (& tc -> req .hdr , TCA_U32_HASH , & opt_ht , sizeof (opt_ht ));
505+ memset (& opt_sel , 0 , sizeof (opt_sel ));
506+ /* [match] protocol option */
507+ pack_key8 (& opt_sel .sel , proto , 0xff , 9 , 0 );
508+ /* [match] nofrag option */
509+ pack_key16 (& opt_sel .sel , 0 , 0x3fff , 6 , 0 );
510+ /* [match] dst option */
511+ pack_key32 (& opt_sel .sel , ntohl (dst_ip ), 0xffffffff , 16 , 0 );
512+ /* [match] dport option */
513+ pack_key16 (& opt_sel .sel , ntohs (dst_port ), 0xffff , 22 , 0 );
514+ opt_sel .sel .flags |= TC_U32_TERMINAL ;
515+ nl_attr_add (& tc -> req .hdr , TCA_U32_SEL , & opt_sel , sizeof (opt_sel .sel ) + opt_sel .sel .nkeys * sizeof (opt_sel .sel .keys [0 ]));
516+
517+ nl_attr_nest_end (& tc -> req .hdr , opts );
518+
519+ if (nl_send (tc -> nl , & tc -> req .hdr ) < 0 ) {
520+ rc = -1 ;
521+ goto err ;
522+ }
523+ if (nl_recv (tc -> nl , NULL , NULL ) < 0 ) {
524+ rc = -1 ;
525+ goto err ;
526+ }
527+ #else
528+ char * out_buf = NULL ;
529+ char if_name [IF_NAMESIZE ];
530+ char tap_name [IF_NAMESIZE ];
531+
532+ UNREFERENCED_PARAMETER (tc );
533+
534+ if (NULL == if_indextoname (ifindex , if_name )) {
535+ rc = - errno ;
536+ goto err ;
537+ }
538+
539+ if (NULL == if_indextoname (ifindex_to , tap_name )) {
540+ rc = - errno ;
541+ goto err ;
542+ }
543+
544+ out_buf = sys_exec ("tc filter add dev %s parent ffff: protocol ip "
545+ "prio %d handle ::%x u32 ht %x:%x: "
546+ "match ip protocol %d 0xff "
547+ "match ip nofrag "
548+ "match ip dst %s/32 match ip dport %d 0xffff "
549+ "action mirred egress redirect dev %s "
550+ "> /dev/null 2>&1 || echo $?" ,
551+ if_name , prio , id , ht , bkt , proto ,
552+ sys_ip2str (dst_ip ), ntohs (dst_port ), tap_name );
553+ if (NULL == out_buf || (out_buf [0 ] != '\0' && out_buf [0 ] != '0' )) {
554+ rc = -1 ;
555+ goto err ;
556+ }
557+ #endif /* USE_NETLINK */
558+
559+ err :
560+ return rc ;
561+ }
562+
563+ int tc_add_filter_dev2tap_5t (tc_t tc , int ifindex , int prio , int ht , int bkt , int id ,
564+ int proto , uint32_t dst_ip , uint16_t dst_port , uint32_t src_ip , uint16_t src_port , int ifindex_to )
565+ {
566+ int rc = 0 ;
567+
568+ #if defined(USE_NETLINK ) && (USE_NETLINK == 1 )
569+ struct tc_qdisc qdisc = {HANDLE_SET (0 , 0 , id ), 0xffff0000 , prio };
570+ char opt_kind [] = "u32" ;
571+ uint32_t opt_ht = HANDLE_SET (ht , bkt , 0 );
572+ struct rtattr * opts = NULL ;
573+ struct {
574+ struct tc_u32_sel sel ;
575+ struct tc_u32_key keys [10 ];
576+ } opt_sel ;
577+
578+ tc_req (tc , ifindex , RTM_NEWTFILTER ,
579+ (NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE ),
580+ qdisc );
581+
582+ nl_attr_add (& tc -> req .hdr , TCA_KIND , opt_kind , sizeof (opt_kind ));
583+
584+ /* [filter] options filling */
585+ opts = nl_attr_nest_start (& tc -> req .hdr , TCA_OPTIONS );
586+ {
587+ struct rtattr * opts_action = NULL ;
588+
589+ /* [action] options filling */
590+ opts_action = nl_attr_nest_start (& tc -> req .hdr , TCA_U32_ACT );
591+ {
592+ int prio = 0 ;
593+ char opt_act_kind [] = "mirred" ;
594+ struct rtattr * opts_action_prio = NULL ;
595+
596+ /* [mirred] options filling */
597+ opts_action_prio = nl_attr_nest_start (& tc -> req .hdr , ++ prio );
598+ nl_attr_add (& tc -> req .hdr , TCA_ACT_KIND , opt_act_kind , sizeof (opt_act_kind ));
599+ {
600+ struct rtattr * opts_action_prio_mirred = NULL ;
601+ struct tc_mirred opt_mirred ;
602+
603+ opts_action_prio_mirred = nl_attr_nest_start (& tc -> req .hdr , TCA_ACT_OPTIONS );
604+ memset (& opt_mirred , 0 , sizeof (opt_mirred ));
605+ opt_mirred .eaction = TCA_EGRESS_REDIR ;
606+ opt_mirred .action = TC_ACT_STOLEN ;
607+ opt_mirred .ifindex = ifindex_to ;
608+ nl_attr_add (& tc -> req .hdr , TCA_MIRRED_PARMS , & opt_mirred , sizeof (opt_mirred ));
609+
610+ nl_attr_nest_end (& tc -> req .hdr , opts_action_prio_mirred );
611+ }
612+
613+ nl_attr_nest_end (& tc -> req .hdr , opts_action_prio );
614+ }
615+
616+ nl_attr_nest_end (& tc -> req .hdr , opts_action );
617+ }
618+
619+ nl_attr_add (& tc -> req .hdr , TCA_U32_HASH , & opt_ht , sizeof (opt_ht ));
620+ memset (& opt_sel , 0 , sizeof (opt_sel ));
621+ /* [match] protocol option */
622+ pack_key8 (& opt_sel .sel , proto , 0xff , 9 , 0 );
623+ /* [match] nofrag option */
624+ pack_key16 (& opt_sel .sel , 0 , 0x3fff , 6 , 0 );
625+ /* [match] src option */
626+ pack_key32 (& opt_sel .sel , ntohl (src_ip ), 0xffffffff , 12 , 0 );
627+ /* [match] sport option */
628+ pack_key16 (& opt_sel .sel , ntohs (src_port ), 0xffff , 20 , 0 );
629+ /* [match] dst option */
630+ pack_key32 (& opt_sel .sel , ntohl (dst_ip ), 0xffffffff , 16 , 0 );
631+ /* [match] dport option */
632+ pack_key16 (& opt_sel .sel , ntohs (dst_port ), 0xffff , 22 , 0 );
633+ opt_sel .sel .flags |= TC_U32_TERMINAL ;
634+ nl_attr_add (& tc -> req .hdr , TCA_U32_SEL , & opt_sel , sizeof (opt_sel .sel ) + opt_sel .sel .nkeys * sizeof (opt_sel .sel .keys [0 ]));
635+
636+ nl_attr_nest_end (& tc -> req .hdr , opts );
637+
638+ if (nl_send (tc -> nl , & tc -> req .hdr ) < 0 ) {
639+ rc = -1 ;
640+ goto err ;
641+ }
642+ if (nl_recv (tc -> nl , NULL , NULL ) < 0 ) {
643+ rc = -1 ;
644+ goto err ;
645+ }
646+ #else
647+ char * out_buf = NULL ;
648+ char if_name [IF_NAMESIZE ];
649+ char tap_name [IF_NAMESIZE ];
650+ char str_tmp [100 ];
651+
652+ UNREFERENCED_PARAMETER (tc );
653+
654+ if (NULL == if_indextoname (ifindex , if_name )) {
655+ rc = - errno ;
656+ goto err ;
657+ }
658+
659+ if (NULL == if_indextoname (ifindex_to , tap_name )) {
660+ rc = - errno ;
661+ goto err ;
662+ }
663+
664+ strncpy (str_tmp , sys_ip2str (src_ip ), sizeof (str_tmp ));
665+ str_tmp [sizeof (str_tmp ) - 1 ] = '\0' ;
666+ out_buf = sys_exec ("tc filter add dev %s parent ffff: protocol ip "
667+ "prio %d handle ::%x u32 ht %x:%x: "
668+ "match ip protocol %d 0xff "
669+ "match ip nofrag "
670+ "match ip src %s/32 match ip sport %d 0xffff "
671+ "match ip dst %s/32 match ip dport %d 0xffff "
672+ "action mirred egress redirect dev %s "
673+ "> /dev/null 2>&1 || echo $?" ,
674+ if_name , prio , id , ht , bkt , proto ,
675+ str_tmp , src_port ,
676+ sys_ip2str (dst_ip ), ntohs (dst_port ), tap_name );
677+ if (NULL == out_buf || (out_buf [0 ] != '\0' && out_buf [0 ] != '0' )) {
678+ rc = -1 ;
679+ goto err ;
680+ }
681+ #endif /* USE_NETLINK */
682+
683+ err :
684+ return rc ;
685+ }
686+
445687int tc_del_filter (tc_t tc , int ifindex , int prio , int ht , int bkt , int id )
446688{
447689 int rc = 0 ;
@@ -519,4 +761,44 @@ static int pack_key(struct tc_u32_sel *sel, uint32_t key, uint32_t mask, int of
519761
520762 return 0 ;
521763}
764+
765+ static int pack_key8 (struct tc_u32_sel * sel , uint32_t key , uint32_t mask , int off , int offmask )
766+ {
767+ if ((off & 3 ) == 0 ) {
768+ key <<= 24 ;
769+ mask <<= 24 ;
770+ } else if ((off & 3 ) == 1 ) {
771+ key <<= 16 ;
772+ mask <<= 16 ;
773+ } else if ((off & 3 ) == 2 ) {
774+ key <<= 8 ;
775+ mask <<= 8 ;
776+ }
777+ off &= ~3 ;
778+ key = htonl (key );
779+ mask = htonl (mask );
780+
781+ return pack_key (sel , key , mask , off , offmask );
782+ }
783+
784+ static int pack_key16 (struct tc_u32_sel * sel , uint32_t key , uint32_t mask , int off , int offmask )
785+ {
786+ if ((off & 3 ) == 0 ) {
787+ key <<= 16 ;
788+ mask <<= 16 ;
789+ }
790+ off &= ~3 ;
791+ key = htonl (key );
792+ mask = htonl (mask );
793+
794+ return pack_key (sel , key , mask , off , offmask );
795+ }
796+
797+ static int pack_key32 (struct tc_u32_sel * sel , uint32_t key , uint32_t mask , int off , int offmask )
798+ {
799+ key = htonl (key );
800+ mask = htonl (mask );
801+
802+ return pack_key (sel , key , mask , off , offmask );
803+ }
522804#endif /* USE_NETLINK */
0 commit comments