]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_flowspec_util.c
pimd: Fix possible read beyond end of data received
[mirror_frr.git] / bgpd / bgp_flowspec_util.c
index 1b874276613c2a32150578c30a3a173761e2cbff..b9a0d81cc5a149207136bf8fbcbbaa031ec89400 100644 (file)
 #include "zebra.h"
 
 #include "prefix.h"
+#include "lib_errors.h"
 
+#include "bgp_route.h"
 #include "bgp_table.h"
 #include "bgp_flowspec_util.h"
 #include "bgp_flowspec_private.h"
 #include "bgp_pbr.h"
+#include "bgp_errors.h"
 
 static void hex2bin(uint8_t *hex, int *bin)
 {
@@ -66,16 +69,16 @@ static int bgp_flowspec_call_non_opaque_decode(uint8_t *nlri_content, int len,
                             len,
                             mval, error);
        if (*error < 0)
-               zlog_err("%s: flowspec_op_decode error %d",
-                        __func__, *error);
+               flog_err(EC_BGP_FLOWSPEC_PACKET,
+                        "%s: flowspec_op_decode error %d", __func__, *error);
        else
                *match_num = *error;
        return ret;
 }
 
-static bool bgp_flowspec_contains_prefix(struct prefix *pfs,
-                                        struct prefix *input,
-                                        int prefix_check)
+bool bgp_flowspec_contains_prefix(struct prefix *pfs,
+                                struct prefix *input,
+                                int prefix_check)
 {
        uint32_t offset = 0;
        int type;
@@ -444,10 +447,19 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
                                        len - offset,
                                        prefix, &error);
                        if (error < 0)
-                               zlog_err("%s: flowspec_ip_address error %d",
+                               flog_err(EC_BGP_FLOWSPEC_PACKET,
+                                        "%s: flowspec_ip_address error %d",
                                         __func__, error);
-                       else
-                               bpem->match_bitmask |= bitmask;
+                       else {
+                               /* if src or dst address is 0.0.0.0,
+                                * ignore that rule
+                                */
+                               if (prefix->family == AF_INET
+                                   && prefix->u.prefix4.s_addr == 0)
+                                       bpem->match_bitmask_iprule |= bitmask;
+                               else
+                                       bpem->match_bitmask |= bitmask;
+                       }
                        offset += ret;
                        break;
                case FLOWSPEC_IP_PROTOCOL:
@@ -538,8 +550,10 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
                                        len - offset,
                                        &bpem->tcpflags, &error);
                        if (error < 0)
-                               zlog_err("%s: flowspec_tcpflags_decode error %d",
-                                        __func__, error);
+                               flog_err(
+                                       EC_BGP_FLOWSPEC_PACKET,
+                                       "%s: flowspec_tcpflags_decode error %d",
+                                       __func__, error);
                        else
                                bpem->match_tcpflags_num = error;
                        /* contains the number of slots used */
@@ -552,36 +566,58 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
                                        len - offset, &bpem->fragment,
                                        &error);
                        if (error < 0)
-                               zlog_err("%s: flowspec_fragment_type_decode error %d",
-                                        __func__, error);
+                               flog_err(
+                                       EC_BGP_FLOWSPEC_PACKET,
+                                       "%s: flowspec_fragment_type_decode error %d",
+                                       __func__, error);
                        else
                                bpem->match_fragment_num = error;
                        offset += ret;
                        break;
                default:
-                       zlog_err("%s: unknown type %d\n", __func__, type);
+                       flog_err(EC_LIB_DEVELOPMENT, "%s: unknown type %d\n",
+                                __func__, type);
                }
        }
+       if (bpem->match_packet_length_num || bpem->match_fragment_num ||
+           bpem->match_tcpflags_num || bpem->match_dscp_num ||
+           bpem->match_packet_length_num || bpem->match_icmp_code_num ||
+           bpem->match_icmp_type_num || bpem->match_port_num ||
+           bpem->match_src_port_num || bpem->match_dst_port_num ||
+           bpem->match_protocol_num || bpem->match_bitmask)
+               bpem->type = BGP_PBR_IPSET;
+       else if ((bpem->match_bitmask_iprule & PREFIX_SRC_PRESENT) ||
+                (bpem->match_bitmask_iprule & PREFIX_DST_PRESENT))
+               /* the extracted policy rule may not need an
+                * iptables/ipset filtering. check this may not be
+                * a standard ip rule : permit any to any ( eg)
+                */
+               bpem->type = BGP_PBR_IPRULE;
+       else
+               bpem->type = BGP_PBR_UNDEFINED;
        return error;
 }
 
-
-struct bgp_node *bgp_flowspec_get_match_per_ip(afi_t afi,
-                                              struct bgp_table *rib,
-                                              struct prefix *match,
-                                              int prefix_check)
+/* return 1 if FS entry invalid or no NH IP */
+int bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
+                             struct prefix *p)
 {
-       struct bgp_node *rn;
-       struct prefix *prefix;
+       struct bgp_pbr_entry_main api;
+       int i;
+       struct bgp_node *rn = pi->net;
+       struct bgp_pbr_entry_action *api_action;
 
-       for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
-               prefix = &rn->p;
-
-               if (prefix->family != AF_FLOWSPEC)
+       memset(&api, 0, sizeof(struct bgp_pbr_entry_main));
+       if (bgp_pbr_build_and_validate_entry(&rn->p, pi, &api) < 0)
+               return 1;
+       for (i = 0; i < api.action_num; i++) {
+               api_action = &api.actions[i];
+               if (api_action->action != ACTION_REDIRECT_IP)
                        continue;
-
-               if (bgp_flowspec_contains_prefix(prefix, match, prefix_check))
-                       return rn;
+               p->family = AF_INET;
+               p->prefixlen = IPV4_MAX_BITLEN;
+               p->u.prefix4 = api_action->u.zr.redirect_ip_v4;
+               return 0;
        }
-       return NULL;
+       return 1;
 }