@@ -33,6 +33,10 @@ bool fib_rule_matchall(const struct fib_rule *rule)
33
33
if (!uid_eq (rule -> uid_range .start , fib_kuid_range_unset .start ) ||
34
34
!uid_eq (rule -> uid_range .end , fib_kuid_range_unset .end ))
35
35
return false;
36
+ if (fib_rule_port_range_set (& rule -> sport_range ))
37
+ return false;
38
+ if (fib_rule_port_range_set (& rule -> dport_range ))
39
+ return false;
36
40
return true;
37
41
}
38
42
EXPORT_SYMBOL_GPL (fib_rule_matchall );
@@ -221,6 +225,26 @@ static int nla_put_uid_range(struct sk_buff *skb, struct fib_kuid_range *range)
221
225
return nla_put (skb , FRA_UID_RANGE , sizeof (out ), & out );
222
226
}
223
227
228
+ static int nla_get_port_range (struct nlattr * pattr ,
229
+ struct fib_rule_port_range * port_range )
230
+ {
231
+ const struct fib_rule_port_range * pr = nla_data (pattr );
232
+
233
+ if (!fib_rule_port_range_valid (pr ))
234
+ return - EINVAL ;
235
+
236
+ port_range -> start = pr -> start ;
237
+ port_range -> end = pr -> end ;
238
+
239
+ return 0 ;
240
+ }
241
+
242
+ static int nla_put_port_range (struct sk_buff * skb , int attrtype ,
243
+ struct fib_rule_port_range * range )
244
+ {
245
+ return nla_put (skb , attrtype , sizeof (* range ), range );
246
+ }
247
+
224
248
static int fib_rule_match (struct fib_rule * rule , struct fib_rules_ops * ops ,
225
249
struct flowi * fl , int flags ,
226
250
struct fib_lookup_arg * arg )
@@ -425,6 +449,17 @@ static int rule_exists(struct fib_rules_ops *ops, struct fib_rule_hdr *frh,
425
449
!uid_eq (r -> uid_range .end , rule -> uid_range .end ))
426
450
continue ;
427
451
452
+ if (r -> ip_proto != rule -> ip_proto )
453
+ continue ;
454
+
455
+ if (!fib_rule_port_range_compare (& r -> sport_range ,
456
+ & rule -> sport_range ))
457
+ continue ;
458
+
459
+ if (!fib_rule_port_range_compare (& r -> dport_range ,
460
+ & rule -> dport_range ))
461
+ continue ;
462
+
428
463
if (!ops -> compare (r , frh , tb ))
429
464
continue ;
430
465
return 1 ;
@@ -569,6 +604,23 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
569
604
rule -> uid_range = fib_kuid_range_unset ;
570
605
}
571
606
607
+ if (tb [FRA_IP_PROTO ])
608
+ rule -> ip_proto = nla_get_u8 (tb [FRA_IP_PROTO ]);
609
+
610
+ if (tb [FRA_SPORT_RANGE ]) {
611
+ err = nla_get_port_range (tb [FRA_SPORT_RANGE ],
612
+ & rule -> sport_range );
613
+ if (err )
614
+ goto errout_free ;
615
+ }
616
+
617
+ if (tb [FRA_DPORT_RANGE ]) {
618
+ err = nla_get_port_range (tb [FRA_DPORT_RANGE ],
619
+ & rule -> dport_range );
620
+ if (err )
621
+ goto errout_free ;
622
+ }
623
+
572
624
if ((nlh -> nlmsg_flags & NLM_F_EXCL ) &&
573
625
rule_exists (ops , frh , tb , rule )) {
574
626
err = - EEXIST ;
@@ -634,6 +686,8 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
634
686
{
635
687
struct net * net = sock_net (skb -> sk );
636
688
struct fib_rule_hdr * frh = nlmsg_data (nlh );
689
+ struct fib_rule_port_range sprange = {0 , 0 };
690
+ struct fib_rule_port_range dprange = {0 , 0 };
637
691
struct fib_rules_ops * ops = NULL ;
638
692
struct fib_rule * rule , * r ;
639
693
struct nlattr * tb [FRA_MAX + 1 ];
@@ -667,6 +721,20 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
667
721
range = fib_kuid_range_unset ;
668
722
}
669
723
724
+ if (tb [FRA_SPORT_RANGE ]) {
725
+ err = nla_get_port_range (tb [FRA_SPORT_RANGE ],
726
+ & sprange );
727
+ if (err )
728
+ goto errout ;
729
+ }
730
+
731
+ if (tb [FRA_DPORT_RANGE ]) {
732
+ err = nla_get_port_range (tb [FRA_DPORT_RANGE ],
733
+ & dprange );
734
+ if (err )
735
+ goto errout ;
736
+ }
737
+
670
738
list_for_each_entry (rule , & ops -> rules_list , list ) {
671
739
if (tb [FRA_PROTOCOL ] &&
672
740
(rule -> proto != nla_get_u8 (tb [FRA_PROTOCOL ])))
@@ -712,6 +780,18 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
712
780
!uid_eq (rule -> uid_range .end , range .end )))
713
781
continue ;
714
782
783
+ if (tb [FRA_IP_PROTO ] &&
784
+ (rule -> ip_proto != nla_get_u8 (tb [FRA_IP_PROTO ])))
785
+ continue ;
786
+
787
+ if (fib_rule_port_range_set (& sprange ) &&
788
+ !fib_rule_port_range_compare (& rule -> sport_range , & sprange ))
789
+ continue ;
790
+
791
+ if (fib_rule_port_range_set (& dprange ) &&
792
+ !fib_rule_port_range_compare (& rule -> dport_range , & dprange ))
793
+ continue ;
794
+
715
795
if (!ops -> compare (rule , frh , tb ))
716
796
continue ;
717
797
@@ -790,7 +870,10 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
790
870
+ nla_total_size (4 ) /* FRA_FWMASK */
791
871
+ nla_total_size_64bit (8 ) /* FRA_TUN_ID */
792
872
+ nla_total_size (sizeof (struct fib_kuid_range ))
793
- + nla_total_size (1 ); /* FRA_PROTOCOL */
873
+ + nla_total_size (1 ) /* FRA_PROTOCOL */
874
+ + nla_total_size (1 ) /* FRA_IP_PROTO */
875
+ + nla_total_size (sizeof (struct fib_rule_port_range )) /* FRA_SPORT_RANGE */
876
+ + nla_total_size (sizeof (struct fib_rule_port_range )); /* FRA_DPORT_RANGE */
794
877
795
878
if (ops -> nlmsg_payload )
796
879
payload += ops -> nlmsg_payload (rule );
@@ -855,7 +938,12 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
855
938
(rule -> l3mdev &&
856
939
nla_put_u8 (skb , FRA_L3MDEV , rule -> l3mdev )) ||
857
940
(uid_range_set (& rule -> uid_range ) &&
858
- nla_put_uid_range (skb , & rule -> uid_range )))
941
+ nla_put_uid_range (skb , & rule -> uid_range )) ||
942
+ (fib_rule_port_range_set (& rule -> sport_range ) &&
943
+ nla_put_port_range (skb , FRA_SPORT_RANGE , & rule -> sport_range )) ||
944
+ (fib_rule_port_range_set (& rule -> dport_range ) &&
945
+ nla_put_port_range (skb , FRA_DPORT_RANGE , & rule -> dport_range )) ||
946
+ (rule -> ip_proto && nla_put_u8 (skb , FRA_IP_PROTO , rule -> ip_proto )))
859
947
goto nla_put_failure ;
860
948
861
949
if (rule -> suppress_ifgroup != -1 ) {
0 commit comments