rib+tools: use ndn::nfd::RouteOrigin instead of uint64_t

Change-Id: Ic8cbe95491a41e1d34b66d406da8637aeb5fd9e3
Refs: #3903
diff --git a/rib/route.hpp b/rib/route.hpp
index b93ed0c..f739741 100644
--- a/rib/route.hpp
+++ b/rib/route.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,6 +27,7 @@
 #define NFD_RIB_ROUTE_HPP
 
 #include "core/scheduler.hpp"
+
 #include <ndn-cxx/encoding/nfd-constants.hpp>
 
 namespace nfd {
@@ -39,11 +40,10 @@
 public:
   Route()
     : faceId(0)
-    , origin(0)
+    , origin(ndn::nfd::ROUTE_ORIGIN_APP)
     , flags(0)
     , cost(0)
     , expires(time::steady_clock::TimePoint::min())
-    , m_expirationEvent()
   {
   }
 
@@ -77,7 +77,7 @@
 
 public:
   uint64_t faceId;
-  uint64_t origin;
+  ndn::nfd::RouteOrigin origin;
   uint64_t flags;
   uint64_t cost;
   time::steady_clock::TimePoint expires;
diff --git a/tests/rib/fib-updates-common.hpp b/tests/rib/fib-updates-common.hpp
index df41c3e..59505bc 100644
--- a/tests/rib/fib-updates-common.hpp
+++ b/tests/rib/fib-updates-common.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -23,6 +23,9 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifndef NFD_TESTS_RIB_FIB_UPDATES_COMMON_HPP
+#define NFD_TESTS_RIB_FIB_UPDATES_COMMON_HPP
+
 #include "rib/fib-updater.hpp"
 #include "rib-test-common.hpp"
 #include "tests/identity-management-fixture.hpp"
@@ -67,7 +70,9 @@
   }
 
   void
-  insertRoute(const Name& name, uint64_t faceId, uint64_t origin, uint64_t cost, uint64_t flags)
+  insertRoute(const Name& name, uint64_t faceId,
+              std::underlying_type<ndn::nfd::RouteOrigin>::type origin,
+              uint64_t cost, uint64_t flags)
   {
     Route route = createRoute(faceId, origin, cost, flags);
 
@@ -80,7 +85,8 @@
   }
 
   void
-  eraseRoute(const Name& name, uint64_t faceId, uint64_t origin)
+  eraseRoute(const Name& name, uint64_t faceId,
+             std::underlying_type<ndn::nfd::RouteOrigin>::type origin)
   {
     Route route = createRoute(faceId, origin, 0, 0);
 
@@ -175,3 +181,5 @@
 } // namespace tests
 } // namespace rib
 } // namespace nfd
+
+#endif // NFD_TESTS_RIB_FIB_UPDATES_COMMON_HPP
diff --git a/tests/rib/rib-entry.t.cpp b/tests/rib/rib-entry.t.cpp
index 03cd8b9..65f73dc 100644
--- a/tests/rib/rib-entry.t.cpp
+++ b/tests/rib/rib-entry.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -40,16 +40,16 @@
 
   rib::Route route1;
   route1.faceId = 1;
-  route1.origin = 0;
+  route1.origin = ndn::nfd::ROUTE_ORIGIN_APP;
 
-  std::tie(entryIt, didInsert) =  entry.insertRoute(route1);
+  std::tie(entryIt, didInsert) = entry.insertRoute(route1);
   BOOST_CHECK_EQUAL(entry.getRoutes().size(), 1);
   BOOST_CHECK(entryIt == entry.findRoute(route1));
   BOOST_CHECK(didInsert);
 
   Route route2;
   route2.faceId = 1;
-  route2.origin = 128;
+  route2.origin = ndn::nfd::ROUTE_ORIGIN_NLSR;
 
   std::tie(entryIt, didInsert) = entry.insertRoute(route2);
   BOOST_CHECK_EQUAL(entry.getRoutes().size(), 2);
diff --git a/tests/rib/rib-manager.t.cpp b/tests/rib/rib-manager.t.cpp
index 0264b9f..117b264 100644
--- a/tests/rib/rib-manager.t.cpp
+++ b/tests/rib/rib-manager.t.cpp
@@ -137,26 +137,26 @@
   }
 
 public:
-  ControlParameters
-  makeRegisterParameters(const Name& name, uint64_t id = 0,
+  static ControlParameters
+  makeRegisterParameters(const Name& name, uint64_t faceId = 0,
                          time::milliseconds expiry = time::milliseconds::max())
   {
     return ControlParameters()
       .setName(name)
-      .setFaceId(id)
-      .setOrigin(128)
+      .setFaceId(faceId)
+      .setOrigin(ndn::nfd::ROUTE_ORIGIN_NLSR)
       .setCost(10)
       .setFlags(0)
       .setExpirationPeriod(expiry);
   }
 
-  ControlParameters
-  makeUnregisterParameters(const Name& name, uint64_t id = 0)
+  static ControlParameters
+  makeUnregisterParameters(const Name& name, uint64_t faceId = 0)
   {
     return ControlParameters()
       .setName(name)
-      .setFaceId(id)
-      .setOrigin(128);
+      .setFaceId(faceId)
+      .setOrigin(ndn::nfd::ROUTE_ORIGIN_NLSR);
   }
 
   void
diff --git a/tests/rib/rib-test-common.hpp b/tests/rib/rib-test-common.hpp
index 997b455..3a09d4b 100644
--- a/tests/rib/rib-test-common.hpp
+++ b/tests/rib/rib-test-common.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -23,6 +23,9 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifndef NFD_TESTS_RIB_RIB_TEST_COMMON_HPP
+#define NFD_TESTS_RIB_RIB_TEST_COMMON_HPP
+
 #include "rib/route.hpp"
 
 namespace nfd {
@@ -30,11 +33,14 @@
 namespace tests {
 
 inline Route
-createRoute(uint64_t faceId, uint64_t origin, uint64_t cost, uint64_t flags)
+createRoute(uint64_t faceId,
+            std::underlying_type<ndn::nfd::RouteOrigin>::type origin,
+            uint64_t cost = 0,
+            uint64_t flags = 0)
 {
   Route temp;
   temp.faceId = faceId;
-  temp.origin = origin;
+  temp.origin = static_cast<ndn::nfd::RouteOrigin>(origin);
   temp.cost = cost;
   temp.flags = flags;
 
@@ -44,3 +50,5 @@
 } // namespace tests
 } // namespace rib
 } // namespace nfd
+
+#endif // NFD_TESTS_RIB_RIB_TEST_COMMON_HPP
diff --git a/tests/rib/rib.t.cpp b/tests/rib/rib.t.cpp
index 51a8040..d856f94 100644
--- a/tests/rib/rib.t.cpp
+++ b/tests/rib/rib.t.cpp
@@ -1,6 +1,6 @@
- /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -25,10 +25,9 @@
 
 #include "rib/rib.hpp"
 
+#include "rib-test-common.hpp"
 #include "tests/test-common.hpp"
 
-#include <ndn-cxx/encoding/tlv-nfd.hpp>
-
 namespace nfd {
 namespace rib {
 namespace tests {
@@ -39,40 +38,28 @@
 {
   rib::Rib rib;
 
-  Route root;
   Name name1("/");
-  root.faceId = 1;
-  root.origin = 20;
-  rib.insert(name1, root);
+  rib.insert(name1, createRoute(1, 20));
 
-  Route route1;
   Name name2("/hello");
-  route1.faceId = 2;
-  route1.origin = 20;
-  rib.insert(name2, route1);
+  rib.insert(name2, createRoute(2, 20));
 
-  Route route2;
   Name name3("/hello/world");
-  route2.faceId = 3;
-  route2.origin = 20;
-  rib.insert(name3, route2);
+  rib.insert(name3, createRoute(3, 20));
 
   shared_ptr<rib::RibEntry> ribEntry = rib.findParent(name3);
-  BOOST_REQUIRE(static_cast<bool>(ribEntry));
+  BOOST_REQUIRE(ribEntry != nullptr);
   BOOST_CHECK_EQUAL(ribEntry->getRoutes().front().faceId, 2);
 
   ribEntry = rib.findParent(name2);
-  BOOST_REQUIRE(static_cast<bool>(ribEntry));
+  BOOST_REQUIRE(ribEntry != nullptr);
   BOOST_CHECK_EQUAL(ribEntry->getRoutes().front().faceId, 1);
 
-  Route route3;
   Name name4("/hello/test/foo/bar");
-  route2.faceId = 3;
-  route2.origin = 20;
-  rib.insert(name4, route3);
+  rib.insert(name4, createRoute(3, 20));
 
   ribEntry = rib.findParent(name4);
-  BOOST_CHECK(ribEntry != shared_ptr<rib::RibEntry>());
+  BOOST_REQUIRE(ribEntry != nullptr);
   BOOST_CHECK(ribEntry->getRoutes().front().faceId == 2);
 }
 
@@ -80,33 +67,21 @@
 {
   rib::Rib rib;
 
-  Route route1;
   Name name1("/");
-  route1.faceId = 1;
-  route1.origin = 20;
-  rib.insert(name1, route1);
+  rib.insert(name1, createRoute(1, 20));
 
-  Route route2;
   Name name2("/hello/world");
-  route2.faceId = 2;
-  route2.origin = 20;
-  rib.insert(name2, route2);
+  rib.insert(name2, createRoute(2, 20));
 
-  Route route3;
   Name name3("/hello/test/foo/bar");
-  route3.faceId = 3;
-  route3.origin = 20;
-  rib.insert(name3, route3);
+  rib.insert(name3, createRoute(3, 20));
 
   BOOST_CHECK_EQUAL((rib.find(name1)->second)->getChildren().size(), 2);
   BOOST_CHECK_EQUAL((rib.find(name2)->second)->getChildren().size(), 0);
   BOOST_CHECK_EQUAL((rib.find(name3)->second)->getChildren().size(), 0);
 
-  Route entry4;
   Name name4("/hello");
-  entry4.faceId = 4;
-  entry4.origin = 20;
-  rib.insert(name4, entry4);
+  rib.insert(name4, createRoute(4, 20));
 
   BOOST_CHECK_EQUAL((rib.find(name1)->second)->getChildren().size(), 1);
   BOOST_CHECK_EQUAL((rib.find(name2)->second)->getChildren().size(), 0);
@@ -126,30 +101,22 @@
 {
   rib::Rib rib;
 
-  Route route1;
+  Route route1 = createRoute(1, 20);
   Name name1("/");
-  route1.faceId = 1;
-  route1.origin = 20;
   rib.insert(name1, route1);
 
-  Route route2;
+  Route route2 = createRoute(2, 20);
   Name name2("/hello/world");
-  route2.faceId = 2;
-  route2.origin = 20;
   rib.insert(name2, route2);
 
-  Route route3;
+  Route route3 = createRoute(1, 20);
   Name name3("/hello/world");
-  route3.faceId = 1;
-  route3.origin = 20;
   rib.insert(name3, route3);
 
-  Route entry4;
+  Route route4 = createRoute(1, 20);
   Name name4("/not/inserted");
-  entry4.faceId = 1;
-  entry4.origin = 20;
 
-  rib.erase(name4, entry4);
+  rib.erase(name4, route4);
   rib.erase(name1, route1);
 
   BOOST_CHECK(rib.find(name1) == rib.end());
@@ -164,30 +131,22 @@
 
   BOOST_CHECK(rib.find(name2) == rib.end());
 
-  rib.erase(name4, entry4);
+  rib.erase(name4, route4);
 }
 
 BOOST_AUTO_TEST_CASE(EraseRibEntry)
 {
   rib::Rib rib;
 
-  Route route1;
   Name name1("/");
-  route1.faceId = 1;
-  route1.origin = 20;
-  rib.insert(name1, route1);
+  rib.insert(name1, createRoute(1, 20));
 
-  Route route2;
+  Route route2 = createRoute(2, 20);
   Name name2("/hello");
-  route2.faceId = 2;
-  route2.origin = 20;
   rib.insert(name2, route2);
 
-  Route route3;
   Name name3("/hello/world");
-  route3.faceId = 1;
-  route3.origin = 20;
-  rib.insert(name3, route3);
+  rib.insert(name3, createRoute(1, 20));
 
   shared_ptr<rib::RibEntry> ribEntry1 = rib.find(name1)->second;
   shared_ptr<rib::RibEntry> ribEntry2 = rib.find(name2)->second;
@@ -208,7 +167,6 @@
   Route route1;
   Name name1("/hello/world");
   route1.faceId = 1;
-  route1.origin = 20;
   route1.cost = 10;
   route1.flags = ndn::nfd::ROUTE_FLAG_CHILD_INHERIT | ndn::nfd::ROUTE_FLAG_CAPTURE;
   route1.expires = time::steady_clock::now() + time::milliseconds(1500);
@@ -222,7 +180,6 @@
   Route route2;
   Name name2("/hello/world");
   route2.faceId = 1;
-  route2.origin = 20;
   route2.cost = 100;
   route2.flags = ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;
   route2.expires = time::steady_clock::now() + time::seconds(0);
@@ -241,7 +198,7 @@
   rib.insert(name3, route2);
   BOOST_CHECK_EQUAL(rib.size(), 3);
 
-  route2.origin = 1;
+  route2.origin = ndn::nfd::ROUTE_ORIGIN_AUTOCONF;
   rib.insert(name3, route2);
   BOOST_CHECK_EQUAL(rib.size(), 4);
 
@@ -252,12 +209,12 @@
   rib.erase(name4, route2);
   BOOST_CHECK_EQUAL(rib.size(), 3);
 
-  route2.origin = 20;
+  route2.origin = ndn::nfd::ROUTE_ORIGIN_APP;
   rib.erase(name4, route2);
   BOOST_CHECK_EQUAL(rib.size(), 2);
 
-  BOOST_CHECK_EQUAL(rib.find(name2, route2), static_cast<Route*>(0));
-  BOOST_CHECK_NE(rib.find(name1, route1), static_cast<Route*>(0));
+  BOOST_CHECK(rib.find(name2, route2) == nullptr);
+  BOOST_CHECK(rib.find(name1, route1) != nullptr);
 
   rib.erase(name1, route1);
   BOOST_CHECK_EQUAL(rib.size(), 1);
@@ -270,15 +227,8 @@
   Route route;
   Name name("/hello/world");
 
-  Route route1;
-  route1.faceId = 1;
-  route1.origin = 20;
-  route1.cost = 10;
-
-  Route route2;
-  route2.faceId = 2;
-  route2.origin = 30;
-  route2.cost = 20;
+  Route route1 = createRoute(1, 20, 10);
+  Route route2 = createRoute(2, 30, 20);
 
   RibRouteRef routeInfo;
 
@@ -333,31 +283,24 @@
   rib.erase(name, route);
   BOOST_CHECK_EQUAL(nBeforeRemoveRouteInvocations, 2);
   BOOST_CHECK_EQUAL(nAfterEraseEntryInvocations, 1);
-
 }
 
 BOOST_AUTO_TEST_CASE(Output)
 {
   rib::Rib rib;
 
-  Route root;
+  Route root = createRoute(1, 20);
   Name name1("/");
-  root.faceId = 1;
-  root.origin = 20;
   root.expires = time::steady_clock::TimePoint::max();
   rib.insert(name1, root);
 
-  Route route1;
+  Route route1 = createRoute(2, 20);
   Name name2("/hello");
-  route1.faceId = 2;
-  route1.origin = 20;
   route1.expires = time::steady_clock::TimePoint::max();
   rib.insert(name2, route1);
 
-  Route route2;
+  Route route2 = createRoute(3, 20);
   Name name3("/hello/world");
-  route2.faceId = 3;
-  route2.origin = 20;
   route2.expires = time::steady_clock::TimePoint::max();
   rib.insert(name3, route2);
 
diff --git a/tools/nfd-autoreg.cpp b/tools/nfd-autoreg.cpp
index 1ecd6e5..ca52e9b 100644
--- a/tools/nfd-autoreg.cpp
+++ b/tools/nfd-autoreg.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -41,17 +41,12 @@
 #include "core/network.hpp"
 
 using namespace ndn::nfd;
-using ndn::Face;
-using ndn::KeyChain;
-using ndn::nfd::FaceEventNotification;
 using ndn::util::FaceUri;
 using ::nfd::Network;
 
 namespace ndn {
 namespace nfd_autoreg {
 
-namespace po = boost::program_options;
-
 class AutoregServer : boost::noncopyable
 {
 public:
@@ -123,10 +118,9 @@
   }
 
   void
-  registerPrefixesForFace(uint64_t faceId,
-                          const std::vector<ndn::Name>& prefixes)
+  registerPrefixesForFace(uint64_t faceId, const std::vector<Name>& prefixes)
   {
-    for (std::vector<ndn::Name>::const_iterator prefix = prefixes.begin();
+    for (std::vector<Name>::const_iterator prefix = prefixes.begin();
          prefix != prefixes.end();
          ++prefix)
       {
@@ -179,37 +173,35 @@
       }
   }
 
-
   void
   signalHandler()
   {
     m_face.shutdown();
   }
 
-
   void
   usage(std::ostream& os,
-        const po::options_description& optionDesciption,
+        const boost::program_options::options_description& desc,
         const char* programName)
   {
     os << "Usage:\n"
        << "  " << programName << " --prefix=</autoreg/prefix> [--prefix=/another/prefix] ...\n"
        << "\n";
-    os << optionDesciption;
+    os << desc;
   }
 
   void
   startProcessing()
   {
     std::cerr << "AUTOREG prefixes: " << std::endl;
-    for (std::vector<ndn::Name>::const_iterator prefix = m_autoregPrefixes.begin();
+    for (std::vector<Name>::const_iterator prefix = m_autoregPrefixes.begin();
          prefix != m_autoregPrefixes.end();
          ++prefix)
       {
         std::cout << "  " << *prefix << std::endl;
       }
     std::cerr << "ALL-FACES-AUTOREG prefixes: " << std::endl;
-    for (std::vector<ndn::Name>::const_iterator prefix = m_allFacesPrefixes.begin();
+    for (std::vector<Name>::const_iterator prefix = m_allFacesPrefixes.begin();
          prefix != m_allFacesPrefixes.end();
          ++prefix)
       {
@@ -248,8 +240,8 @@
   startFetchingFaceStatusDataset()
   {
     m_controller.fetch<FaceDataset>(
-      [this] (const std::vector<ndn::nfd::FaceStatus>& faces) {
-        for (const ndn::nfd::FaceStatus& faceStatus : faces) {
+      [this] (const std::vector<FaceStatus>& faces) {
+        for (const auto& faceStatus : faces) {
           registerPrefixesIfNeeded(faceStatus.getFaceId(), FaceUri(faceStatus.getRemoteUri()),
                                    faceStatus.getFacePersistency());
         }
@@ -260,20 +252,22 @@
   int
   main(int argc, char* argv[])
   {
+    namespace po = boost::program_options;
+
     po::options_description optionDesciption;
     optionDesciption.add_options()
       ("help,h", "produce help message")
-      ("prefix,i", po::value<std::vector<ndn::Name> >(&m_autoregPrefixes)->composing(),
+      ("prefix,i", po::value<std::vector<Name>>(&m_autoregPrefixes)->composing(),
        "prefix that should be automatically registered when new a remote non-local face is "
        "established")
-      ("all-faces-prefix,a", po::value<std::vector<ndn::Name> >(&m_allFacesPrefixes)->composing(),
+      ("all-faces-prefix,a", po::value<std::vector<Name>>(&m_allFacesPrefixes)->composing(),
        "prefix that should be automatically registered for all TCP and UDP non-local faces "
        "(blacklists and whitelists do not apply to this prefix)")
       ("cost,c", po::value<uint64_t>(&m_cost)->default_value(255),
        "FIB cost which should be assigned to autoreg nexthops")
-      ("whitelist,w", po::value<std::vector<Network> >(&m_whiteList)->composing(),
+      ("whitelist,w", po::value<std::vector<Network>>(&m_whiteList)->composing(),
        "Whitelisted network, e.g., 192.168.2.0/24 or ::1/128")
-      ("blacklist,b", po::value<std::vector<Network> >(&m_blackList)->composing(),
+      ("blacklist,b", po::value<std::vector<Network>>(&m_blackList)->composing(),
        "Blacklisted network, e.g., 192.168.2.32/30 or ::1/128")
       ("version,V", "show version and exit")
       ;
@@ -284,7 +278,7 @@
         po::store(po::command_line_parser(argc, argv).options(optionDesciption).run(), options);
         po::notify(options);
       }
-    catch (std::exception& e)
+    catch (const std::exception& e)
       {
         std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
         usage(std::cerr, optionDesciption, argv[0]);
@@ -323,7 +317,7 @@
         startFetchingFaceStatusDataset();
         startProcessing();
       }
-    catch (std::exception& e)
+    catch (const std::exception& e)
       {
         std::cerr << "ERROR: " << e.what() << std::endl;
         return 2;
@@ -337,8 +331,8 @@
   KeyChain m_keyChain;
   Controller m_controller;
   FaceMonitor m_faceMonitor;
-  std::vector<ndn::Name> m_autoregPrefixes;
-  std::vector<ndn::Name> m_allFacesPrefixes;
+  std::vector<Name> m_autoregPrefixes;
+  std::vector<Name> m_allFacesPrefixes;
   uint64_t m_cost;
   std::vector<Network> m_whiteList;
   std::vector<Network> m_blackList;
diff --git a/tools/nfdc/legacy-nfdc.cpp b/tools/nfdc/legacy-nfdc.cpp
index 5f4f81f..e0e6bcd 100644
--- a/tools/nfdc/legacy-nfdc.cpp
+++ b/tools/nfdc/legacy-nfdc.cpp
@@ -341,6 +341,7 @@
   bool wantCapture = false;
   bool wantPermanentFace = false;
   int64_t expires = -1;
+  std::underlying_type<ndn::nfd::RouteOrigin>::type origin = ndn::nfd::ROUTE_ORIGIN_STATIC;
 
   namespace po = boost::program_options;
   po::options_description options;
@@ -349,7 +350,7 @@
     (",C", po::bool_switch(&wantCapture))
     (",c", po::value<uint64_t>(&p.m_cost))
     (",e", po::value<int64_t>(&expires))
-    (",o", po::value<uint64_t>(&p.m_origin))
+    (",o", po::value<std::underlying_type<ndn::nfd::RouteOrigin>::type>(&origin))
     (",P", po::bool_switch(&wantPermanentFace));
   po::variables_map vm;
   std::vector<std::string> unparsed;
@@ -376,6 +377,7 @@
     // accept negative values as no expiration
     p.m_expires = time::milliseconds(expires);
   }
+  p.m_origin = static_cast<ndn::nfd::RouteOrigin>(origin);
   if (wantPermanentFace) {
     p.m_facePersistency = ndn::nfd::FACE_PERSISTENCY_PERMANENT;
   }
diff --git a/tools/nfdc/legacy-nfdc.hpp b/tools/nfdc/legacy-nfdc.hpp
index 6ae9abe..ada0a7d 100644
--- a/tools/nfdc/legacy-nfdc.hpp
+++ b/tools/nfdc/legacy-nfdc.hpp
@@ -27,6 +27,8 @@
 #define NFD_TOOLS_NFDC_LEGACY_NFDC_HPP
 
 #include "execute-command.hpp"
+
+#include <ndn-cxx/encoding/nfd-constants.hpp>
 #include <ndn-cxx/mgmt/nfd/controller.hpp>
 
 namespace nfd {
@@ -160,7 +162,7 @@
   uint64_t m_flags;
   uint64_t m_cost;
   uint64_t m_faceId;
-  uint64_t m_origin;
+  ndn::nfd::RouteOrigin m_origin;
   time::milliseconds m_expires;
   std::string m_name;
   ndn::nfd::FacePersistency m_facePersistency;
diff --git a/tools/nfdc/rib-module.cpp b/tools/nfdc/rib-module.cpp
index ffcb18c..5ca7195 100644
--- a/tools/nfdc/rib-module.cpp
+++ b/tools/nfdc/rib-module.cpp
@@ -191,7 +191,7 @@
       text::ItemAttributes ia;
       ctx.out << ia("prefix") << resp.getName()
               << ia("nexthop") << resp.getFaceId()
-              << ia("origin") << static_cast<RouteOrigin>(resp.getOrigin())
+              << ia("origin") << resp.getOrigin()
               << ia("cost") << resp.getCost()
               << ia("flags") << static_cast<ndn::nfd::RouteFlags>(resp.getFlags());
       if (resp.hasExpirationPeriod()) {
@@ -245,7 +245,7 @@
         text::ItemAttributes ia;
         ctx.out << ia("prefix") << resp.getName()
                 << ia("nexthop") << resp.getFaceId()
-                << ia("origin") << static_cast<RouteOrigin>(resp.getOrigin())
+                << ia("origin") << resp.getOrigin()
                 << '\n';
       },
       ctx.makeCommandFailureHandler("removing route"),
@@ -290,7 +290,7 @@
   for (const Route& route : item.getRoutes()) {
     os << "<route>"
        << "<faceId>" << route.getFaceId() << "</faceId>"
-       << "<origin>" << static_cast<RouteOrigin>(route.getOrigin()) << "</origin>"
+       << "<origin>" << route.getOrigin() << "</origin>"
        << "<cost>" << route.getCost() << "</cost>";
     if (route.getFlags() == ndn::nfd::ROUTE_FLAGS_NONE) {
        os << "<flags/>";
@@ -352,14 +352,9 @@
     os << ia("prefix") << entry.getName();
   }
   os << ia("nexthop") << route.getFaceId();
-  os << ia("origin") << static_cast<RouteOrigin>(route.getOrigin());
+  os << ia("origin") << route.getOrigin();
   os << ia("cost") << route.getCost();
   os << ia("flags") << static_cast<ndn::nfd::RouteFlags>(route.getFlags());
-
-  // 'origin' field is printed as a number, because printing 'origin' as string may mislead user
-  // into passing strings to 'origin' command line argument which currently only accepts numbers.
-  ///\todo #3987 print 'origin' with RouteOrigin stream insertion operator
-
   if (route.hasExpirationPeriod()) {
     os << ia("expires") << text::formatDuration(route.getExpirationPeriod());
   }