mgmt: limit prefix length in fib/add-nexthop

This commit also makes FibManager logging more consistent.

refs #4262

Change-Id: I8e1d58eacfdf0a87d6f94182c78a157421de6f6f
diff --git a/daemon/mgmt/fib-manager.cpp b/daemon/mgmt/fib-manager.cpp
index 7c27649..06e660a 100644
--- a/daemon/mgmt/fib-manager.cpp
+++ b/daemon/mgmt/fib-manager.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -57,31 +57,29 @@
                        const ndn::mgmt::CommandContinuation& done)
 {
   setFaceForSelfRegistration(interest, parameters);
-
   const Name& prefix = parameters.getName();
   FaceId faceId = parameters.getFaceId();
   uint64_t cost = parameters.getCost();
 
-  NFD_LOG_TRACE("add-nexthop prefix: " << prefix
-                << " faceid: " << faceId
-                << " cost: " << cost);
+  if (prefix.size() > Fib::getMaxDepth()) {
+    NFD_LOG_DEBUG("fib/add-nexthop(" << prefix << ',' << faceId << ',' << cost <<
+                  "): FAIL prefix-too-long");
+    return done(ControlResponse(414, "FIB entry prefix cannot exceed " +
+                                ndn::to_string(Fib::getMaxDepth()) + " components"));
+  }
 
   Face* face = m_faceTable.get(faceId);
-  if (face != nullptr) {
-    fib::Entry* entry = m_fib.insert(prefix).first;
-    entry->addNextHop(*face, cost);
-
-    NFD_LOG_DEBUG("add-nexthop result: OK"
-                  << " prefix:" << prefix
-                  << " faceid: " << faceId
-                  << " cost: " << cost);
-
-    return done(ControlResponse(200, "Success").setBody(parameters.wireEncode()));
-  }
-  else {
-    NFD_LOG_INFO("add-nexthop result: FAIL reason: unknown-faceid: " << faceId);
+  if (face == nullptr) {
+    NFD_LOG_DEBUG("fib/add-nexthop(" << prefix << ',' << faceId << ',' << cost <<
+                  "): FAIL unknown-faceid");
     return done(ControlResponse(410, "Face not found"));
   }
+
+  fib::Entry* entry = m_fib.insert(prefix).first;
+  entry->addNextHop(*face, cost);
+
+  NFD_LOG_TRACE("fib/add-nexthop(" << prefix << ',' << faceId << ',' << cost << "): OK");
+  return done(ControlResponse(200, "Success").setBody(parameters.wireEncode()));
 }
 
 void
@@ -90,31 +88,31 @@
                           const ndn::mgmt::CommandContinuation& done)
 {
   setFaceForSelfRegistration(interest, parameters);
-
-  NFD_LOG_TRACE("remove-nexthop prefix: " << parameters.getName()
-                << " faceid: " << parameters.getFaceId());
-
-  Face* face = m_faceTable.get(parameters.getFaceId());
-  if (face != nullptr) {
-    fib::Entry* entry = m_fib.findExactMatch(parameters.getName());
-    if (entry != nullptr) {
-      entry->removeNextHop(*face);
-      NFD_LOG_DEBUG("remove-nexthop result: OK prefix: " << parameters.getName()
-                    << " faceid: " << parameters.getFaceId());
-
-      if (!entry->hasNextHops()) {
-        m_fib.erase(*entry);
-      }
-    }
-    else {
-      NFD_LOG_DEBUG("remove-nexthop result: OK");
-    }
-  }
-  else {
-    NFD_LOG_DEBUG("remove-nexthop result: OK");
-  }
+  const Name& prefix = parameters.getName();
+  FaceId faceId = parameters.getFaceId();
 
   done(ControlResponse(200, "Success").setBody(parameters.wireEncode()));
+
+  Face* face = m_faceTable.get(faceId);
+  if (face == nullptr) {
+    NFD_LOG_TRACE("fib/remove-nexthop(" << prefix << ',' << faceId << "): OK no-face");
+    return;
+  }
+
+  fib::Entry* entry = m_fib.findExactMatch(parameters.getName());
+  if (entry == nullptr) {
+    NFD_LOG_TRACE("fib/remove-nexthop(" << prefix << ',' << faceId << "): OK no-entry");
+    return;
+  }
+
+  entry->removeNextHop(*face);
+  if (!entry->hasNextHops()) {
+    m_fib.erase(*entry);
+    NFD_LOG_TRACE("fib/remove-nexthop(" << prefix << ',' << faceId << "): OK entry-erased");
+  }
+  else {
+    NFD_LOG_TRACE("fib/remove-nexthop(" << prefix << ',' << faceId << "): OK nexthop-removed");
+  }
 }
 
 void
diff --git a/tests/daemon/mgmt/fib-manager.t.cpp b/tests/daemon/mgmt/fib-manager.t.cpp
index 7c86e28..428b15b 100644
--- a/tests/daemon/mgmt/fib-manager.t.cpp
+++ b/tests/daemon/mgmt/fib-manager.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -171,6 +171,24 @@
   BOOST_CHECK_EQUAL(checkNextHop("/hello", nullopt, nullopt, 101), CheckNextHopResult::NO_FIB_ENTRY);
 }
 
+BOOST_AUTO_TEST_CASE(NameTooLong)
+{
+  Name prefix;
+  while (prefix.size() <= FIB_MAX_DEPTH) {
+    prefix.append("A");
+  }
+
+  auto req = makeControlCommandRequest("/localhost/nfd/fib/add-nexthop",
+                                       makeParameters(prefix, addFace()));
+  receiveInterest(req);
+
+  ControlResponse expected(414, "FIB entry prefix cannot exceed " +
+                                ndn::to_string(Fib::getMaxDepth()) + " components");
+  BOOST_CHECK_EQUAL(checkResponse(0, req.getName(), expected), CheckResponseResult::OK);
+
+  BOOST_CHECK_EQUAL(checkNextHop(prefix), CheckNextHopResult::NO_FIB_ENTRY);
+}
+
 BOOST_AUTO_TEST_CASE(ImplicitFaceId)
 {
   auto face1 = addFace();