@@ -206,6 +206,26 @@ static int nla_put_uid_range(struct sk_buff *skb, struct fib_kuid_range *range)
206206 return nla_put (skb , FRA_UID_RANGE , sizeof (out ), & out );
207207}
208208
209+ static int nla_get_port_range (struct nlattr * pattr ,
210+ struct fib_rule_port_range * port_range )
211+ {
212+ const struct fib_rule_port_range * pr = nla_data (pattr );
213+
214+ if (!fib_rule_port_range_valid (pr ))
215+ return - EINVAL ;
216+
217+ port_range -> start = pr -> start ;
218+ port_range -> end = pr -> end ;
219+
220+ return 0 ;
221+ }
222+
223+ static int nla_put_port_range (struct sk_buff * skb , int attrtype ,
224+ struct fib_rule_port_range * range )
225+ {
226+ return nla_put (skb , attrtype , sizeof (* range ), range );
227+ }
228+
209229static int fib_rule_match (struct fib_rule * rule , struct fib_rules_ops * ops ,
210230 struct flowi * fl , int flags ,
211231 struct fib_lookup_arg * arg )
@@ -551,6 +571,8 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh)
551571{
552572 struct net * net = sock_net (skb -> sk );
553573 struct fib_rule_hdr * frh = nlmsg_data (nlh );
574+ struct fib_rule_port_range sprange = {0 , 0 };
575+ struct fib_rule_port_range dprange = {0 , 0 };
554576 struct fib_rules_ops * ops = NULL ;
555577 struct fib_rule * rule , * tmp ;
556578 struct nlattr * tb [FRA_MAX + 1 ];
@@ -584,6 +606,20 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh)
584606 range = fib_kuid_range_unset ;
585607 }
586608
609+ if (tb [FRA_SPORT_RANGE ]) {
610+ err = nla_get_port_range (tb [FRA_SPORT_RANGE ],
611+ & sprange );
612+ if (err )
613+ goto errout ;
614+ }
615+
616+ if (tb [FRA_DPORT_RANGE ]) {
617+ err = nla_get_port_range (tb [FRA_DPORT_RANGE ],
618+ & dprange );
619+ if (err )
620+ goto errout ;
621+ }
622+
587623 list_for_each_entry (rule , & ops -> rules_list , list ) {
588624 if (frh -> action && (frh -> action != rule -> action ))
589625 continue ;
@@ -625,6 +661,18 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh)
625661 !uid_eq (rule -> uid_range .end , range .end )))
626662 continue ;
627663
664+ if (tb [FRA_IP_PROTO ] &&
665+ (rule -> ip_proto != nla_get_u8 (tb [FRA_IP_PROTO ])))
666+ continue ;
667+
668+ if (fib_rule_port_range_set (& sprange ) &&
669+ !fib_rule_port_range_compare (& rule -> sport_range , & sprange ))
670+ continue ;
671+
672+ if (fib_rule_port_range_set (& dprange ) &&
673+ !fib_rule_port_range_compare (& rule -> dport_range , & dprange ))
674+ continue ;
675+
628676 if (!ops -> compare (rule , frh , tb ))
629677 continue ;
630678
@@ -694,6 +742,12 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
694742 + nla_total_size (4 ) /* FRA_FWMASK */
695743 + nla_total_size_64bit (8 ) /* FRA_TUN_ID */
696744 + nla_total_size (sizeof (struct fib_kuid_range ));
745+ + nla_total_size (8 ); /* FRA_TUN_ID */
746+ + nla_total_size (sizeof (struct fib_kuid_range ))
747+ + nla_total_size (1 ) /* FRA_PROTOCOL */
748+ + nla_total_size (1 ) /* FRA_IP_PROTO */
749+ + nla_total_size (sizeof (struct fib_rule_port_range )) /* FRA_SPORT_RANGE */
750+ + nla_total_size (sizeof (struct fib_rule_port_range )); /* FRA_DPORT_RANGE */
697751
698752 if (ops -> nlmsg_payload )
699753 payload += ops -> nlmsg_payload (rule );
@@ -755,7 +809,12 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
755809 (rule -> l3mdev &&
756810 nla_put_u8 (skb , FRA_L3MDEV , rule -> l3mdev )) ||
757811 (uid_range_set (& rule -> uid_range ) &&
758- nla_put_uid_range (skb , & rule -> uid_range )))
812+ nla_put_uid_range (skb , & rule -> uid_range )) ||
813+ (fib_rule_port_range_set (& rule -> sport_range ) &&
814+ nla_put_port_range (skb , FRA_SPORT_RANGE , & rule -> sport_range )) ||
815+ (fib_rule_port_range_set (& rule -> dport_range ) &&
816+ nla_put_port_range (skb , FRA_DPORT_RANGE , & rule -> dport_range )) ||
817+ (rule -> ip_proto && nla_put_u8 (skb , FRA_IP_PROTO , rule -> ip_proto )))
759818 goto nla_put_failure ;
760819
761820 if (rule -> suppress_ifgroup != -1 ) {
0 commit comments