]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_flowspec_util.c
Merge pull request #3502 from donaldsharp/socket_to_me_baby
[mirror_frr.git] / bgpd / bgp_flowspec_util.c
index 956cf28c211dfc2df74f0a0bada96ccaac4acad3..c6386dcdb56df55dab52f963dbfe97d9b565b28f 100644 (file)
 #include "zebra.h"
 
 #include "prefix.h"
+#include "lib_errors.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 +68,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;
@@ -124,8 +126,9 @@ static bool bgp_flowspec_contains_prefix(struct prefix *pfs,
                                                     len - offset,
                                                     NULL, &error);
                        break;
+               case FLOWSPEC_FRAGMENT:
                case FLOWSPEC_TCP_FLAGS:
-                       ret = bgp_flowspec_tcpflags_decode(
+                       ret = bgp_flowspec_bitmask_decode(
                                                BGP_FLOWSPEC_VALIDATE_ONLY,
                                                nlri_content+offset,
                                                len - offset,
@@ -139,13 +142,6 @@ static bool bgp_flowspec_contains_prefix(struct prefix *pfs,
                                                len - offset, NULL,
                                                &error);
                        break;
-               case FLOWSPEC_FRAGMENT:
-                       ret = bgp_flowspec_fragment_type_decode(
-                                               BGP_FLOWSPEC_VALIDATE_ONLY,
-                                               nlri_content + offset,
-                                               len - offset, NULL,
-                                               &error);
-                       break;
                default:
                        error = -1;
                        break;
@@ -312,14 +308,14 @@ int bgp_flowspec_op_decode(enum bgp_flowspec_util_nlri_t type,
 
 
 /*
- * handle the flowspec tcpflags field
+ * handle the flowspec tcpflags or fragment field
  * return number of bytes analysed
  * if there is an error, the passed error param is used to give error:
  * -1 if decoding error,
  * if result is a string, its assumed length
  *  is BGP_FLOWSPEC_STRING_DISPLAY_MAX
  */
-int bgp_flowspec_tcpflags_decode(enum bgp_flowspec_util_nlri_t type,
+int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
                                 uint8_t *nlri_ptr,
                                 uint32_t max_len,
                                 void *result, int *error)
@@ -348,32 +344,33 @@ int bgp_flowspec_tcpflags_decode(enum bgp_flowspec_util_nlri_t type,
                case BGP_FLOWSPEC_RETURN_STRING:
                        if (op[1] == 1 && loop != 0) {
                                len_written = snprintf(ptr, len_string,
-                                                      ", and ");
+                                                      ",&");
                                len_string -= len_written;
                                ptr += len_written;
                        } else if (op[1] == 0 && loop != 0) {
                                len_written = snprintf(ptr, len_string,
-                                                     ", or ");
+                                                     ",|");
                                len_string -= len_written;
                                ptr += len_written;
                        }
-                       len_written = snprintf(ptr, len_string,
-                                              "tcp flags is ");
-                       len_string -= len_written;
-                       ptr += len_written;
-                       if (op[6] == 1) {
-                               ptr += snprintf(ptr, len_string,
-                                              "not ");
+                       if (op[7] == 1) {
+                               len_written = snprintf(ptr, len_string,
+                                              "= ");
+                               len_string -= len_written;
+                               ptr += len_written;
+                       } else {
+                               len_written = snprintf(ptr, len_string,
+                                                      "∋ ");
                                len_string -= len_written;
                                ptr += len_written;
                        }
-                       if (op[7] == 1) {
-                               ptr += snprintf(ptr, len_string,
-                                              "exactly match ");
+                       if (op[6] == 1) {
+                               len_written = snprintf(ptr, len_string,
+                                              "! ");
                                len_string -= len_written;
                                ptr += len_written;
                        }
-                       ptr += snprintf(ptr, len_string,
+                       len_written = snprintf(ptr, len_string,
                                       "%d", value);
                        len_string -= len_written;
                        ptr += len_written;
@@ -419,92 +416,6 @@ int bgp_flowspec_tcpflags_decode(enum bgp_flowspec_util_nlri_t type,
        return offset;
 }
 
-/*
- * handle the flowspec fragment type field
- * return error (returned values are invalid) or number of bytes analysed
- * -1 if error in decoding
- * >= 0 : number of bytes analysed (ok).
- */
-int bgp_flowspec_fragment_type_decode(enum bgp_flowspec_util_nlri_t type,
-                                     uint8_t *nlri_ptr,
-                                     uint32_t max_len,
-                                     void *result, int *error)
-{
-       int op[8];
-       int len, value, value_size, loop = 0;
-       char *ptr = (char *)result; /* for return_string */
-       struct bgp_pbr_fragment_val *mval =
-               (struct bgp_pbr_fragment_val *)result;
-       uint32_t offset = 0;
-       int len_string = BGP_FLOWSPEC_STRING_DISPLAY_MAX;
-       int len_written;
-
-       *error = 0;
-       do {
-               hex2bin(&nlri_ptr[offset], op);
-               offset++;
-               len = 2 * op[2] + op[3];
-               value_size = 1 << len;
-               value = hexstr2num(&nlri_ptr[offset], value_size);
-               if (value != 1 && value != 2 && value != 4 && value != 8)
-                       *error = -1;
-               offset += value_size;
-               /* TODO : as per RFC5574 : first Fragment bits are Reserved
-                * does that mean that it is not possible
-                * to handle multiple occurences ?
-                * as of today, we only grab the first TCP fragment
-                */
-               if (loop) {
-                       *error = -2;
-                       loop++;
-                       continue;
-               }
-               switch (type) {
-               case BGP_FLOWSPEC_RETURN_STRING:
-                       switch (value) {
-                       case 1:
-                               len_written = snprintf(ptr, len_string,
-                                                      "dont-fragment");
-                               len_string -= len_written;
-                               ptr += len_written;
-                               break;
-                       case 2:
-                               len_written = snprintf(ptr, len_string,
-                                                     "is-fragment");
-                               len_string -= len_written;
-                               ptr += len_written;
-                               break;
-                       case 4:
-                               len_written = snprintf(ptr, len_string,
-                                                      "first-fragment");
-                               len_string -= len_written;
-                               ptr += len_written;
-                               break;
-                       case 8:
-                               len_written = snprintf(ptr, len_string,
-                                                      "last-fragment");
-                               len_string -= len_written;
-                               ptr += len_written;
-                               break;
-                       default:
-                               {}
-                       }
-                       break;
-               case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE:
-                       mval->bitmask = (uint8_t)value;
-                       break;
-               case BGP_FLOWSPEC_VALIDATE_ONLY:
-               default:
-                       /* no action */
-                       break;
-               }
-               loop++;
-       } while (op[0] == 0 && offset < max_len - 1);
-       if (offset > max_len)
-               *error = -1;
-       return offset;
-}
-
 int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
                                  struct bgp_pbr_entry_main *bpem)
 {
@@ -535,10 +446,20 @@ 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)
+                                       memset(prefix, 0,
+                                              sizeof(struct prefix));
+                               else
+                                       bpem->match_bitmask |= bitmask;
+                       }
                        offset += ret;
                        break;
                case FLOWSPEC_IP_PROTOCOL:
@@ -623,56 +544,40 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
                                                        &error);
                        break;
                case FLOWSPEC_TCP_FLAGS:
-                       ret = bgp_flowspec_tcpflags_decode(
+                       ret = bgp_flowspec_bitmask_decode(
                                        BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
                                        nlri_content + offset,
                                        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 */
                        offset += ret;
                        break;
                case FLOWSPEC_FRAGMENT:
-                       ret = bgp_flowspec_fragment_type_decode(
+                       ret = bgp_flowspec_bitmask_decode(
                                        BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
                                        nlri_content + offset,
                                        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_bitmask |= FRAGMENT_PRESENT;
+                               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);
                }
        }
        return error;
 }
-
-
-struct bgp_node *bgp_flowspec_get_match_per_ip(afi_t afi,
-                                              struct bgp_table *rib,
-                                              struct prefix *match,
-                                              int prefix_check)
-{
-       struct bgp_node *rn;
-       struct prefix *prefix;
-
-       for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
-               prefix = &rn->p;
-
-               if (prefix->family != AF_FLOWSPEC)
-                       continue;
-
-               if (bgp_flowspec_contains_prefix(prefix, match, prefix_check))
-                       return rn;
-       }
-       return NULL;
-}