]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/rule_netlink.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / zebra / rule_netlink.c
index 08a675ef3a108331ab6d4d962dfd4bac07e0df91..c7832992ea06e50f507678e5561776e5ad11d42b 100644 (file)
@@ -1,24 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Zebra Policy Based Routing (PBR) interaction with the kernel using
  * netlink.
  * Copyright (C) 2018  Cumulus Networks, Inc.
- *
- * This file is part of FRR.
- *
- * FRR is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * FRR is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with FRR; see the file COPYING.  If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
  */
 
 #include <zebra.h>
@@ -42,6 +26,7 @@
 #include "zebra/zebra_pbr.h"
 #include "zebra/zebra_errors.h"
 #include "zebra/zebra_dplane.h"
+#include "zebra/zebra_trace.h"
 
 /* definitions */
 
  * Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer
  * or the number of bytes written to buf.
  */
-static ssize_t
-netlink_rule_msg_encode(int cmd, const struct zebra_dplane_ctx *ctx,
-                       uint32_t filter_bm, uint32_t priority, uint32_t table,
-                       const struct prefix *src_ip,
-                       const struct prefix *dst_ip, uint32_t fwmark,
-                       uint8_t dsfield, void *buf, size_t buflen)
+static ssize_t netlink_rule_msg_encode(
+       int cmd, const struct zebra_dplane_ctx *ctx, uint32_t filter_bm,
+       uint32_t priority, uint32_t table, const struct prefix *src_ip,
+       const struct prefix *dst_ip, uint32_t fwmark, uint8_t dsfield,
+       uint8_t ip_protocol, void *buf, size_t buflen)
 {
        uint8_t protocol = RTPROT_ZEBRA;
        int family;
@@ -136,6 +120,10 @@ netlink_rule_msg_encode(int cmd, const struct zebra_dplane_ctx *ctx,
        if (filter_bm & PBR_FILTER_DSFIELD)
                req->frh.tos = dsfield;
 
+       /* protocol to match on */
+       if (filter_bm & PBR_FILTER_IP_PROTOCOL)
+               nl_attr_put8(&req->n, buflen, FRA_IP_PROTO, ip_protocol);
+
        /* Route table to use to forward, if filter criteria matches. */
        if (table < 256)
                req->frh.table = table;
@@ -168,7 +156,8 @@ static ssize_t netlink_rule_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf,
                dplane_ctx_rule_get_table(ctx), dplane_ctx_rule_get_src_ip(ctx),
                dplane_ctx_rule_get_dst_ip(ctx),
                dplane_ctx_rule_get_fwmark(ctx),
-               dplane_ctx_rule_get_dsfield(ctx), buf, buflen);
+               dplane_ctx_rule_get_dsfield(ctx),
+               dplane_ctx_rule_get_ipproto(ctx), buf, buflen);
 }
 
 static ssize_t netlink_oldrule_msg_encoder(struct zebra_dplane_ctx *ctx,
@@ -181,7 +170,8 @@ static ssize_t netlink_oldrule_msg_encoder(struct zebra_dplane_ctx *ctx,
                dplane_ctx_rule_get_old_src_ip(ctx),
                dplane_ctx_rule_get_old_dst_ip(ctx),
                dplane_ctx_rule_get_old_fwmark(ctx),
-               dplane_ctx_rule_get_old_dsfield(ctx), buf, buflen);
+               dplane_ctx_rule_get_old_dsfield(ctx),
+               dplane_ctx_rule_get_old_ipproto(ctx), buf, buflen);
 }
 
 /* Public functions */
@@ -236,6 +226,9 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        char *ifname;
        struct zebra_pbr_rule rule = {};
        uint8_t proto = 0;
+       uint8_t ip_proto = 0;
+
+       frrtrace(3, frr_zebra, netlink_rule_change, h, ns_id, startup);
 
        /* Basic validation followed by extracting attributes. */
        if (h->nlmsg_type != RTM_NEWRULE && h->nlmsg_type != RTM_DELRULE)
@@ -312,6 +305,9 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        if (tb[FRA_PROTOCOL])
                proto = *(uint8_t *)RTA_DATA(tb[FRA_PROTOCOL]);
 
+       if (tb[FRA_IP_PROTO])
+               ip_proto = *(uint8_t *)RTA_DATA(tb[FRA_IP_PROTO]);
+
        ifname = (char *)RTA_DATA(tb[FRA_IFNAME]);
        strlcpy(rule.ifname, ifname, sizeof(rule.ifname));
 
@@ -326,7 +322,7 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                        ret = dplane_pbr_rule_delete(&rule);
 
                        zlog_debug(
-                               "%s: %s leftover rule: family %s IF %s Pref %u Src %pFX Dst %pFX Table %u",
+                               "%s: %s leftover rule: family %s IF %s Pref %u Src %pFX Dst %pFX Table %u ip-proto: %u",
                                __func__,
                                ((ret == ZEBRA_DPLANE_REQUEST_FAILURE)
                                         ? "Failed to remove"
@@ -334,7 +330,7 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                                nl_family_to_str(frh->family), rule.ifname,
                                rule.rule.priority, &rule.rule.filter.src_ip,
                                &rule.rule.filter.dst_ip,
-                               rule.rule.action.table);
+                               rule.rule.action.table, ip_proto);
                }
 
                /* TBD */
@@ -349,11 +345,12 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
 
        if (IS_ZEBRA_DEBUG_KERNEL)
                zlog_debug(
-                       "Rx %s family %s IF %s Pref %u Src %pFX Dst %pFX Table %u",
+                       "Rx %s family %s IF %s Pref %u Src %pFX Dst %pFX Table %u ip-proto: %u",
                        nl_msg_type_to_str(h->nlmsg_type),
                        nl_family_to_str(frh->family), rule.ifname,
                        rule.rule.priority, &rule.rule.filter.src_ip,
-                       &rule.rule.filter.dst_ip, rule.rule.action.table);
+                       &rule.rule.filter.dst_ip, rule.rule.action.table,
+                       ip_proto);
 
        return kernel_pbr_rule_del(&rule);
 }
@@ -393,7 +390,7 @@ int netlink_rules_read(struct zebra_ns *zns)
                return ret;
 
        ret = netlink_parse_info(netlink_rule_change, &zns->netlink_cmd,
-                                &dp_info, 0, 1);
+                                &dp_info, 0, true);
        if (ret < 0)
                return ret;
 
@@ -402,7 +399,7 @@ int netlink_rules_read(struct zebra_ns *zns)
                return ret;
 
        ret = netlink_parse_info(netlink_rule_change, &zns->netlink_cmd,
-                                &dp_info, 0, 1);
+                                &dp_info, 0, true);
        return ret;
 }