blob: 79822f747a96bf3de7f2a51ee58acd347ed348cc [file] [log] [blame]
Steve DiBenedettoabe9e972014-02-20 15:37:04 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07003 * Copyright (c) 2014 Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology
9 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070024
25#include "face-manager.hpp"
26
Davide Pesavento52a18f92014-04-10 00:55:01 +020027#include "face-flags.hpp"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060028#include "core/logger.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070029#include "core/face-uri.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060030#include "core/network-interface.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070031#include "fw/face-table.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070032#include "face/tcp-factory.hpp"
33#include "face/udp-factory.hpp"
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070034#include "core/config-file.hpp"
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060035
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060036#ifdef HAVE_UNIX_SOCKETS
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070037#include "face/unix-stream-factory.hpp"
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -060038#endif // HAVE_UNIX_SOCKETS
39
Alexander Afanasyev885a85b2014-04-12 21:01:13 -070040#ifdef HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070041#include "face/ethernet-factory.hpp"
Alexander Afanasyev885a85b2014-04-12 21:01:13 -070042#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070043
Davide Pesavento52a18f92014-04-10 00:55:01 +020044#include <ndn-cpp-dev/management/nfd-face-event-notification.hpp>
45
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070046namespace nfd {
47
48NFD_LOG_INIT("FaceManager");
49
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060050const Name FaceManager::COMMAND_PREFIX("/localhost/nfd/faces");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070051
52const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
53 FaceManager::COMMAND_PREFIX.size() +
54 1 + // verb
Steve DiBenedetto7564d972014-03-24 14:28:46 -060055 1; // verb parameters
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070056
57const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
58 FaceManager::COMMAND_UNSIGNED_NCOMPS +
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070059 4; // (timestamp, nonce, signed info tlv, signature tlv)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070060
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060061const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070062 {
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060063 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060064 Name::Component("create"),
65 &FaceManager::createFace
66 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070067
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060068 SignedVerbAndProcessor(
Steve DiBenedetto7564d972014-03-24 14:28:46 -060069 Name::Component("destroy"),
70 &FaceManager::destroyFace
71 ),
72
73 SignedVerbAndProcessor(
74 Name::Component("enable-local-control"),
75 &FaceManager::enableLocalControl
76 ),
77
78 SignedVerbAndProcessor(
79 Name::Component("disable-local-control"),
80 &FaceManager::disableLocalControl
81 ),
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070082 };
83
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060084const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
85 {
86 UnsignedVerbAndProcessor(
87 Name::Component("list"),
88 &FaceManager::listFaces
89 ),
Steve DiBenedettofbb40a82014-03-11 19:40:15 -060090
91 UnsignedVerbAndProcessor(
92 Name::Component("events"),
93 &FaceManager::ignoreUnsignedVerb
94 ),
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -060095 };
96
97const Name FaceManager::LIST_COMMAND_PREFIX("/localhost/nfd/faces/list");
98const size_t FaceManager::LIST_COMMAND_NCOMPS = LIST_COMMAND_PREFIX.size();
99
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600100const Name FaceManager::EVENTS_COMMAND_PREFIX("/localhost/nfd/faces/events");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700101
102FaceManager::FaceManager(FaceTable& faceTable,
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700103 shared_ptr<InternalFace> face)
104 : ManagerBase(face, FACE_MANAGER_PRIVILEGE)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700105 , m_faceTable(faceTable)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600106 , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600107 , m_notificationStream(m_face, EVENTS_COMMAND_PREFIX)
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600108 , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600109 SIGNED_COMMAND_VERBS +
110 (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600111 , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600112 UNSIGNED_COMMAND_VERBS +
113 (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600114
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700115{
116 face->setInterestFilter("/localhost/nfd/faces",
117 bind(&FaceManager::onFaceRequest, this, _2));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600118
119 m_faceTable.onAdd += bind(&FaceManager::onAddFace, this, _1);
120 m_faceTable.onRemove += bind(&FaceManager::onRemoveFace, this, _1);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700121}
122
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600123FaceManager::~FaceManager()
124{
125
126}
127
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700128void
129FaceManager::setConfigFile(ConfigFile& configFile)
130{
131 configFile.addSectionHandler("face_system",
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600132 bind(&FaceManager::onConfig, this, _1, _2, _3));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700133}
134
135
136void
Steve DiBenedetto1a3c6732014-03-13 06:44:05 -0600137FaceManager::onConfig(const ConfigSection& configSection,
138 bool isDryRun,
139 const std::string& filename)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700140{
141 bool hasSeenUnix = false;
142 bool hasSeenTcp = false;
143 bool hasSeenUdp = false;
144 bool hasSeenEther = false;
145
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600146 const std::list<shared_ptr<NetworkInterfaceInfo> > nicList(listNetworkInterfaces());
147
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700148 for (ConfigSection::const_iterator item = configSection.begin();
149 item != configSection.end();
150 ++item)
151 {
152 if (item->first == "unix")
153 {
154 if (hasSeenUnix)
155 throw Error("Duplicate \"unix\" section");
156 hasSeenUnix = true;
157
158 processSectionUnix(item->second, isDryRun);
159 }
160 else if (item->first == "tcp")
161 {
162 if (hasSeenTcp)
163 throw Error("Duplicate \"tcp\" section");
164 hasSeenTcp = true;
165
166 processSectionTcp(item->second, isDryRun);
167 }
168 else if (item->first == "udp")
169 {
170 if (hasSeenUdp)
171 throw Error("Duplicate \"udp\" section");
172 hasSeenUdp = true;
173
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600174 processSectionUdp(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700175 }
176 else if (item->first == "ether")
177 {
178 if (hasSeenEther)
179 throw Error("Duplicate \"ether\" section");
180 hasSeenEther = true;
181
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600182 processSectionEther(item->second, isDryRun, nicList);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700183 }
184 else
185 {
186 throw Error("Unrecognized option \"" + item->first + "\"");
187 }
188 }
189}
190
191void
192FaceManager::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
193{
194 // ; the unix section contains settings of UNIX stream faces and channels
195 // unix
196 // {
197 // listen yes ; set to 'no' to disable UNIX stream listener, default 'yes'
198 // path /var/run/nfd.sock ; UNIX stream listener path
199 // }
200
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600201#if defined(HAVE_UNIX_SOCKETS)
202
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700203 bool needToListen = true;
204 std::string path = "/var/run/nfd.sock";
205
206 for (ConfigSection::const_iterator i = configSection.begin();
207 i != configSection.end();
208 ++i)
209 {
210 if (i->first == "path")
211 {
212 path = i->second.get_value<std::string>();
213 }
214 else if (i->first == "listen")
215 {
216 needToListen = parseYesNo(i, i->first, "unix");
217 }
218 else
219 {
220 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"unix\" section");
221 }
222 }
223
224 if (!isDryRun)
225 {
226 shared_ptr<UnixStreamFactory> factory = make_shared<UnixStreamFactory>();
227 shared_ptr<UnixStreamChannel> unixChannel = factory->createChannel(path);
228
229 if (needToListen)
230 {
231 // Should acceptFailed callback be used somehow?
232 unixChannel->listen(bind(&FaceTable::add, &m_faceTable, _1),
233 UnixStreamChannel::ConnectFailedCallback());
234 }
235
236 m_factories.insert(std::make_pair("unix", factory));
237 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600238#else
239 throw ConfigFile::Error("NFD was compiled without UNIX sockets support, cannot process \"unix\" section");
240#endif // HAVE_UNIX_SOCKETS
241
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700242}
243
244void
245FaceManager::processSectionTcp(const ConfigSection& configSection, bool isDryRun)
246{
247 // ; the tcp section contains settings of TCP faces and channels
248 // tcp
249 // {
250 // listen yes ; set to 'no' to disable TCP listener, default 'yes'
251 // port 6363 ; TCP listener port number
252 // }
253
254 std::string port = "6363";
255 bool needToListen = true;
Steve DiBenedetto95152872014-04-11 12:40:59 -0600256 bool enableV4 = true;
257 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700258
259 for (ConfigSection::const_iterator i = configSection.begin();
260 i != configSection.end();
261 ++i)
262 {
263 if (i->first == "port")
264 {
265 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600266 try
267 {
268 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
269 NFD_LOG_TRACE("TCP port set to " << portNo);
270 }
271 catch (const std::bad_cast& error)
272 {
273 throw ConfigFile::Error("Invalid value for option " +
Steve DiBenedetto95152872014-04-11 12:40:59 -0600274 i->first + "\" in \"tcp\" section");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600275 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700276 }
277 else if (i->first == "listen")
278 {
279 needToListen = parseYesNo(i, i->first, "tcp");
280 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600281 else if (i->first == "enable_v4")
282 {
283 enableV4 = parseYesNo(i, i->first, "tcp");
284 }
285 else if (i->first == "enable_v6")
286 {
287 enableV6 = parseYesNo(i, i->first, "tcp");
288 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700289 else
290 {
291 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"tcp\" section");
292 }
293 }
294
Steve DiBenedetto95152872014-04-11 12:40:59 -0600295 if (!enableV4 && !enableV6)
296 {
297 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
298 " Remove \"tcp\" section to disable TCP channels or"
299 " re-enable at least one channel type.");
300 }
301
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700302 if (!isDryRun)
303 {
304 shared_ptr<TcpFactory> factory = make_shared<TcpFactory>(boost::cref(port));
Steve DiBenedetto95152872014-04-11 12:40:59 -0600305 m_factories.insert(std::make_pair("tcp", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700306
Steve DiBenedetto95152872014-04-11 12:40:59 -0600307 if (enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700308 {
Steve DiBenedetto95152872014-04-11 12:40:59 -0600309 shared_ptr<TcpChannel> ipv4Channel = factory->createChannel("0.0.0.0", port);
310 if (needToListen)
311 {
312 // Should acceptFailed callback be used somehow?
313 ipv4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
314 TcpChannel::ConnectFailedCallback());
315 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700316
Steve DiBenedetto95152872014-04-11 12:40:59 -0600317 m_factories.insert(std::make_pair("tcp4", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700318 }
319
Steve DiBenedetto95152872014-04-11 12:40:59 -0600320 if (enableV6)
321 {
322 shared_ptr<TcpChannel> ipv6Channel = factory->createChannel("::", port);
323 if (needToListen)
324 {
325 // Should acceptFailed callback be used somehow?
326 ipv6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
327 TcpChannel::ConnectFailedCallback());
328 }
329
330 m_factories.insert(std::make_pair("tcp6", factory));
331 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700332 }
333}
334
335void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600336FaceManager::processSectionUdp(const ConfigSection& configSection,
337 bool isDryRun,
338 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700339{
340 // ; the udp section contains settings of UDP faces and channels
341 // udp
342 // {
343 // port 6363 ; UDP unicast port number
344 // idle_timeout 30 ; idle time (seconds) before closing a UDP unicast face
345 // keep_alive_interval 25; interval (seconds) between keep-alive refreshes
346
347 // ; NFD creates one UDP multicast face per NIC
348 // mcast yes ; set to 'no' to disable UDP multicast, default 'yes'
349 // mcast_port 56363 ; UDP multicast port number
350 // mcast_group 224.0.23.170 ; UDP multicast group (IPv4 only)
351 // }
352
353 std::string port = "6363";
Steve DiBenedetto95152872014-04-11 12:40:59 -0600354 bool enableV4 = true;
355 bool enableV6 = true;
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700356 size_t timeout = 30;
357 size_t keepAliveInterval = 25;
358 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600359 std::string mcastGroup = "224.0.23.170";
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700360 std::string mcastPort = "56363";
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600361
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700362
363 for (ConfigSection::const_iterator i = configSection.begin();
364 i != configSection.end();
365 ++i)
366 {
367 if (i->first == "port")
368 {
369 port = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600370 try
371 {
372 uint16_t portNo = boost::lexical_cast<uint16_t>(port);
373 NFD_LOG_TRACE("UDP port set to " << portNo);
374 }
375 catch (const std::bad_cast& error)
376 {
377 throw ConfigFile::Error("Invalid value for option " +
378 i->first + "\" in \"udp\" section");
379 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700380 }
Steve DiBenedetto95152872014-04-11 12:40:59 -0600381 else if (i->first == "enable_v4")
382 {
383 enableV4 = parseYesNo(i, i->first, "udp");
384 }
385 else if (i->first == "enable_v6")
386 {
387 enableV6 = parseYesNo(i, i->first, "udp");
388 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700389 else if (i->first == "idle_timeout")
390 {
391 try
392 {
393 timeout = i->second.get_value<size_t>();
394 }
395 catch (const std::exception& e)
396 {
397 throw ConfigFile::Error("Invalid value for option \"" +
398 i->first + "\" in \"udp\" section");
399 }
400 }
401 else if (i->first == "keep_alive_interval")
402 {
403 try
404 {
405 keepAliveInterval = i->second.get_value<size_t>();
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700406
407 /// \todo Make use of keepAliveInterval
408 (void)(keepAliveInterval);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700409 }
410 catch (const std::exception& e)
411 {
412 throw ConfigFile::Error("Invalid value for option \"" +
413 i->first + "\" in \"udp\" section");
414 }
415 }
416 else if (i->first == "mcast")
417 {
418 useMcast = parseYesNo(i, i->first, "udp");
419 }
420 else if (i->first == "mcast_port")
421 {
422 mcastPort = i->second.get_value<std::string>();
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600423 try
424 {
425 uint16_t portNo = boost::lexical_cast<uint16_t>(mcastPort);
426 NFD_LOG_TRACE("UDP multicast port set to " << portNo);
427 }
428 catch (const std::bad_cast& error)
429 {
430 throw ConfigFile::Error("Invalid value for option " +
431 i->first + "\" in \"udp\" section");
432 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700433 }
434 else if (i->first == "mcast_group")
435 {
436 using namespace boost::asio::ip;
437 mcastGroup = i->second.get_value<std::string>();
438 try
439 {
440 address mcastGroupTest = address::from_string(mcastGroup);
441 if (!mcastGroupTest.is_v4())
442 {
443 throw ConfigFile::Error("Invalid value for option \"" +
444 i->first + "\" in \"udp\" section");
445 }
446 }
447 catch(const std::runtime_error& e)
448 {
449 throw ConfigFile::Error("Invalid value for option \"" +
450 i->first + "\" in \"udp\" section");
451 }
452 }
453 else
454 {
455 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"udp\" section");
456 }
457 }
458
Steve DiBenedetto95152872014-04-11 12:40:59 -0600459 if (!enableV4 && !enableV6)
460 {
461 throw ConfigFile::Error("IPv4 and IPv6 channels have been disabled."
462 " Remove \"udp\" section to disable UDP channels or"
463 " re-enable at least one channel type.");
464 }
465 else if (useMcast && !enableV4)
466 {
467 throw ConfigFile::Error("IPv4 multicast requested, but IPv4 channels"
468 " have been disabled (conflicting configuration options set)");
469 }
470
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700471 /// \todo what is keep alive interval used for?
472
473 if (!isDryRun)
474 {
475 shared_ptr<UdpFactory> factory = make_shared<UdpFactory>(boost::cref(port));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700476 m_factories.insert(std::make_pair("udp", factory));
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700477
Steve DiBenedetto95152872014-04-11 12:40:59 -0600478 if (enableV4)
479 {
480 shared_ptr<UdpChannel> v4Channel =
481 factory->createChannel("0.0.0.0", port, time::seconds(timeout));
482
483 v4Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
484 UdpChannel::ConnectFailedCallback());
485
486 m_factories.insert(std::make_pair("udp4", factory));
487 }
488
489 if (enableV6)
490 {
491 shared_ptr<UdpChannel> v6Channel =
492 factory->createChannel("::", port, time::seconds(timeout));
493
494 v6Channel->listen(bind(&FaceTable::add, &m_faceTable, _1),
495 UdpChannel::ConnectFailedCallback());
496 m_factories.insert(std::make_pair("udp6", factory));
497 }
498
499 if (useMcast && enableV4)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700500 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600501 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
502 i != nicList.end();
503 ++i)
504 {
505 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
506 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
507 {
508 shared_ptr<MulticastUdpFace> newFace =
509 factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
510 mcastGroup, mcastPort);
511
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700512 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600513 }
514 }
515 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700516 }
517}
518
519void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600520FaceManager::processSectionEther(const ConfigSection& configSection,
521 bool isDryRun,
522 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700523{
524 // ; the ether section contains settings of Ethernet faces and channels
525 // ether
526 // {
527 // ; NFD creates one Ethernet multicast face per NIC
528 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
529 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
530 // }
531
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700532#if defined(HAVE_LIBPCAP)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600533
534 using ethernet::Address;
535
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700536 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600537 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700538
539 for (ConfigSection::const_iterator i = configSection.begin();
540 i != configSection.end();
541 ++i)
542 {
543 if (i->first == "mcast")
544 {
545 useMcast = parseYesNo(i, i->first, "ether");
546 }
547
548 else if (i->first == "mcast_group")
549 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600550 mcastGroup = Address::fromString(i->second.get_value<std::string>());
551 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700552 {
553 throw ConfigFile::Error("Invalid value for option \"" +
554 i->first + "\" in \"ether\" section");
555 }
556 }
557 else
558 {
559 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
560 }
561 }
562
563 if (!isDryRun)
564 {
565 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
566 m_factories.insert(std::make_pair("ether", factory));
567
568 if (useMcast)
569 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600570 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
571 i != nicList.end();
572 ++i)
573 {
574 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
575 if (nic->isUp() && nic->isMulticastCapable())
576 {
577 try
578 {
579 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100580 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700581
582 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600583 }
584 catch (const EthernetFactory::Error& factoryError)
585 {
586 NFD_LOG_ERROR(factoryError.what() << ", continuing");
587 }
588 catch (const EthernetFace::Error& faceError)
589 {
590 NFD_LOG_ERROR(faceError.what() << ", continuing");
591 }
592 }
593 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700594 }
595 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600596#else
597 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700598#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700599}
600
601
602void
603FaceManager::onFaceRequest(const Interest& request)
604{
605 const Name& command = request.getName();
606 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600607 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700608
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600609 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
610 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
611 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700612 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600613 (unsignedVerbProcessor->second)(this, boost::cref(request));
614 }
615 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600616 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700617 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700618 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700619 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700620 }
621 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
622 !COMMAND_PREFIX.isPrefixOf(command))
623 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700624 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700625 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700626 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600627 else
628 {
629 validate(request,
630 bind(&FaceManager::onValidatedFaceRequest, this, _1),
631 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
632 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700633}
634
635void
636FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
637{
638 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600639 const Name::Component& verb = command[COMMAND_PREFIX.size()];
640 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700641
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600642 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
643 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700644 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600645 ControlParameters parameters;
646 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700647 {
648 sendResponse(command, 400, "Malformed command");
649 return;
650 }
651
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700652 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600653 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700654 }
655 else
656 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700657 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700658 sendResponse(command, 501, "Unsupported command");
659 }
660
661}
662
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700663void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700664FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
665{
666 m_faceTable.add(newFace);
667
Junxiao Shi6e694322014-04-03 10:27:13 -0700668 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700669}
670
671void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700672FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600673 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700674 const shared_ptr<Face>& newFace)
675{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700676 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600677 parameters.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700678
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600679 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700680}
681
682void
683FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
684{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700685 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600686 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700687}
688
689void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600690FaceManager::createFace(const Interest& request,
691 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700692{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600693 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600694 ndn::nfd::FaceCreateCommand command;
695
696 if (!validateParameters(command, parameters))
697 {
698 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600699 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600700 return;
701 }
702
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700703 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600704 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700705 {
706 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600707 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700708 return;
709 }
710
711 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
712 if (factory == m_factories.end())
713 {
714 sendResponse(requestName, 501, "Unsupported protocol");
715 return;
716 }
717
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600718 try
719 {
720 factory->second->createFace(uri,
721 bind(&FaceManager::onCreated,
722 this, requestName, parameters, _1),
723 bind(&FaceManager::onConnectFailed,
724 this, requestName, _1));
725 }
726 catch (const std::runtime_error& error)
727 {
728 std::string errorMessage = "NFD error: ";
729 errorMessage += error.what();
730
731 NFD_LOG_ERROR(errorMessage);
732 sendResponse(requestName, 500, errorMessage);
733 }
734 catch (const std::logic_error& error)
735 {
736 std::string errorMessage = "NFD error: ";
737 errorMessage += error.what();
738
739 NFD_LOG_ERROR(errorMessage);
740 sendResponse(requestName, 500, errorMessage);
741 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700742}
743
744
745void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600746FaceManager::destroyFace(const Interest& request,
747 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700748{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600749 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600750 ndn::nfd::FaceDestroyCommand command;
751
752 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600753 {
754 sendResponse(requestName, 400, "Malformed command");
755 return;
756 }
757
758 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600759 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700760 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700761 target->close();
762 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600763
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600764 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600765
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700766}
767
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600768void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600769FaceManager::onAddFace(shared_ptr<Face> face)
770{
Junxiao Shi6e694322014-04-03 10:27:13 -0700771 ndn::nfd::FaceEventNotification notification;
772 notification.setKind(ndn::nfd::FACE_EVENT_CREATED)
773 .setFaceId(face->getId())
774 .setRemoteUri(face->getRemoteUri().toString())
775 .setLocalUri(face->getLocalUri().toString())
776 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600777
Junxiao Shi6e694322014-04-03 10:27:13 -0700778 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600779}
780
781void
782FaceManager::onRemoveFace(shared_ptr<Face> face)
783{
Junxiao Shi6e694322014-04-03 10:27:13 -0700784 ndn::nfd::FaceEventNotification notification;
785 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
786 .setFaceId(face->getId())
787 .setRemoteUri(face->getRemoteUri().toString())
788 .setLocalUri(face->getLocalUri().toString())
789 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600790
Junxiao Shi6e694322014-04-03 10:27:13 -0700791 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600792}
793
794
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600795bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600796FaceManager::extractLocalControlParameters(const Interest& request,
797 ControlParameters& parameters,
798 ControlCommand& command,
799 shared_ptr<LocalFace>& outFace,
800 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600801{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600802 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600803 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600804 sendResponse(request.getName(), 400, "Malformed command");
805 return false;
806 }
807
808 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
809
810 if (!static_cast<bool>(face))
811 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700812 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600813 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600814 return false;
815 }
816 else if (!face->isLocal())
817 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700818 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
819 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600820 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600821 return false;
822 }
823
824 outFace = dynamic_pointer_cast<LocalFace>(face);
825 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
826
827 return true;
828}
829
830void
831FaceManager::enableLocalControl(const Interest& request,
832 ControlParameters& parameters)
833{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600834 ndn::nfd::FaceEnableLocalControlCommand command;
835
836
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600837 shared_ptr<LocalFace> face;
838 LocalControlFeature feature;
839
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600840 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600841 {
842 face->setLocalControlHeaderFeature(feature, true);
843 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
844 }
845}
846
847void
848FaceManager::disableLocalControl(const Interest& request,
849 ControlParameters& parameters)
850{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600851 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600852 shared_ptr<LocalFace> face;
853 LocalControlFeature feature;
854
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600855 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600856 {
857 face->setLocalControlHeaderFeature(feature, false);
858 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
859 }
860}
861
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600862void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600863FaceManager::listFaces(const Interest& request)
864{
865 const Name& command = request.getName();
866 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700867
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600868 if (commandNComps < LIST_COMMAND_NCOMPS ||
869 !LIST_COMMAND_PREFIX.isPrefixOf(command))
870 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700871 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600872 sendResponse(command, 400, "Malformed command");
873 return;
874 }
875
876 m_statusPublisher.publish();
877}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700878
879} // namespace nfd