Validate Withdrawn Routes and NLRI 77/78777/4
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 14 Dec 2018 00:36:28 +0000 (01:36 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 14 Dec 2018 00:55:24 +0000 (01:55 +0100)
RFC7606 section 5.3 mandates we perform additional validation
on Withdrawn Routes and NLRI fields. This patch adds that validation.

Change-Id: I3b0497afd3a0622bb681935aba718767a13ae235
JIRA: BGPCEP-359
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
bgp/parser-impl/src/main/java/org/opendaylight/protocol/bgp/parser/impl/message/BGPUpdateMessageParser.java

index a4c166c1326a34f19d1df9aaba989e95d21d0a63..9e86efd026e7bda73541a4033ed99916d944fa07 100755 (executable)
@@ -135,17 +135,17 @@ public final class BGPUpdateMessageParser implements MessageParser, MessageSeria
                 if (isMultiPathSupported) {
                     withdrawnRoutesBuilder.setPathId(PathIdUtil.readPathId(withdrawnRoutesBuffer));
                 }
-                withdrawnRoutesBuilder.setPrefix(Ipv4Util.prefixForByteBuf(withdrawnRoutesBuffer));
+                withdrawnRoutesBuilder.setPrefix(readPrefix(withdrawnRoutesBuffer, errorHandling, "Withdrawn Routes"));
                 withdrawnRoutes.add(withdrawnRoutesBuilder.build());
             }
             withdrawnRoutesBuffer.release();
             builder.setWithdrawnRoutes(withdrawnRoutes);
         }
         final int totalPathAttrLength = buffer.readUnsignedShort();
-
         if (withdrawnRoutesLength == 0 && totalPathAttrLength == 0) {
             return builder.build();
         }
+
         Optional<BGPTreatAsWithdrawException> withdrawCauseOpt;
         if (totalPathAttrLength > 0) {
             final ParsedAttributes attributes = parseAttributes(buffer, totalPathAttrLength, constraint);
@@ -154,13 +154,14 @@ public final class BGPUpdateMessageParser implements MessageParser, MessageSeria
         } else {
             withdrawCauseOpt = Optional.empty();
         }
+
         final List<Nlri> nlri = new ArrayList<>();
         while (buffer.isReadable()) {
             final NlriBuilder nlriBuilder = new NlriBuilder();
             if (isMultiPathSupported) {
                 nlriBuilder.setPathId(PathIdUtil.readPathId(buffer));
             }
-            nlriBuilder.setPrefix(Ipv4Util.prefixForByteBuf(buffer));
+            nlriBuilder.setPrefix(readPrefix(buffer, errorHandling, "NLRI"));
             nlri.add(nlriBuilder.build());
         }
         if (!nlri.isEmpty()) {
@@ -202,6 +203,24 @@ public final class BGPUpdateMessageParser implements MessageParser, MessageSeria
         }
     }
 
+    private static Ipv4Prefix readPrefix(final ByteBuf buf, final RevisedErrorHandling errorHandling,
+            final String fieldName) throws BGPDocumentedException {
+        final int prefixLength = buf.readUnsignedByte();
+        if (errorHandling != RevisedErrorHandling.NONE) {
+            // https://tools.ietf.org/html/rfc7606#section-5.3
+            if (prefixLength > 32) {
+                throw new BGPDocumentedException(fieldName + " length " + prefixLength + " exceeds 32 bytes",
+                    BGPError.ATTR_LENGTH_ERROR);
+            }
+            if (prefixLength > buf.readableBytes() * 8) {
+                throw new BGPDocumentedException(fieldName + " length " + prefixLength
+                    + " exceeds unconsumed field space", BGPError.ATTR_LENGTH_ERROR);
+            }
+        }
+
+        return Ipv4Util.prefixForByteBuf(buf, prefixLength);
+    }
+
     /**
      * Check for presence of well known mandatory path attributes ORIGIN, AS_PATH and NEXT_HOP in Update message.
      *