summaryrefslogtreecommitdiff
path: root/zebra/zapi_msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zapi_msg.c')
-rw-r--r--zebra/zapi_msg.c96
1 files changed, 87 insertions, 9 deletions
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 062941a1e4..33972681f8 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -1416,6 +1416,7 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re,
struct nexthop *nexthop = NULL;
struct ipaddr vtep_ip;
struct interface *ifp;
+ int i;
char nhbuf[INET6_ADDRSTRLEN] = "";
switch (api_nh->type) {
@@ -1521,17 +1522,36 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re,
nexthop->weight = api_nh->weight;
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
- if (api_nh->backup_idx < api->backup_nexthop_num) {
- /* Capture backup info */
- SET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
- nexthop->backup_idx = api_nh->backup_idx;
- } else {
- /* Warn about invalid backup index */
+ /* Validate count */
+ if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS) {
if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("%s: invalid backup nh idx %d",
- __func__, api_nh->backup_idx);
+ zlog_debug("%s: invalid backup nh count %d",
+ __func__, api_nh->backup_num);
+ nexthop_free(nexthop);
+ nexthop = NULL;
+ goto done;
+ }
+
+ /* Copy backup info */
+ SET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
+ nexthop->backup_num = api_nh->backup_num;
+
+ for (i = 0; i < api_nh->backup_num; i++) {
+ /* Validate backup index */
+ if (api_nh->backup_idx[i] < api->backup_nexthop_num) {
+ nexthop->backup_idx[i] = api_nh->backup_idx[i];
+ } else {
+ if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s: invalid backup nh idx %d",
+ __func__,
+ api_nh->backup_idx[i]);
+ nexthop_free(nexthop);
+ nexthop = NULL;
+ goto done;
+ }
}
}
+
done:
return nexthop;
}
@@ -1703,7 +1723,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
__func__, nhbuf);
}
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
- nexthop->backup_idx = 0;
+ nexthop->backup_num = 0;
}
/* MPLS labels for BGP-LU or Segment Routing */
@@ -1981,6 +2001,56 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
}
/*
+ * Validate incoming zapi mpls lsp / labels message
+ */
+static int zapi_labels_validate(const struct zapi_labels *zl)
+{
+ int ret = -1;
+ int i, j, idx;
+ uint32_t bits[8];
+ uint32_t ival;
+ const struct zapi_nexthop *znh;
+
+ /* Validate backup info: no duplicates for a single primary */
+ if (zl->backup_nexthop_num == 0) {
+ ret = 0;
+ goto done;
+ }
+
+ for (j = 0; j < zl->nexthop_num; j++) {
+ znh = &zl->nexthops[j];
+
+ memset(bits, 0, sizeof(bits));
+
+ for (i = 0; i < znh->backup_num; i++) {
+ idx = znh->backup_idx[i] / 32;
+
+ ival = 1 << znh->backup_idx[i] % 32;
+
+ /* Check whether value is already used */
+ if (ival & bits[idx]) {
+ /* Fail */
+
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: invalid zapi mpls message: duplicate backup nexthop index %d",
+ __func__,
+ znh->backup_idx[i]);
+ goto done;
+ }
+
+ /* Mark index value */
+ bits[idx] |= ival;
+ }
+ }
+
+ ret = 0;
+
+done:
+
+ return ret;
+}
+
+/*
* Handle request to create an MPLS LSP.
*
* A single message can fully specify an LSP with multiple nexthops.
@@ -2006,6 +2076,10 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
if (!mpls_enabled)
return;
+ /* Validate; will debug on failure */
+ if (zapi_labels_validate(&zl) < 0)
+ return;
+
ret = mpls_zapi_labels_process(true, zvrf, &zl);
if (ret < 0) {
if (IS_ZEBRA_DEBUG_RECV)
@@ -2087,6 +2161,10 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS)
if (!mpls_enabled)
return;
+ /* Validate; will debug on failure */
+ if (zapi_labels_validate(&zl) < 0)
+ return;
+
/* This removes everything, then re-adds from the client's
* zapi message. Since the LSP will be processed later, on this
* this same pthread, all of the changes will 'appear' at once.