blob: 83972534db3b3ae0c963fac7483b5e27d835ed0d [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 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200501 std::list<shared_ptr<NetworkInterfaceInfo> > ipv4MulticastInterfaces;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600502 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
503 i != nicList.end();
504 ++i)
505 {
506 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
507 if (nic->isUp() && nic->isMulticastCapable() && !nic->ipv4Addresses.empty())
508 {
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200509 ipv4MulticastInterfaces.push_back(nic);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600510 }
511 }
Giulio Grassi6d7176d2014-04-16 16:08:48 +0200512
513 bool isNicNameNecessary = false;
514
515#if defined(__linux__)
516 if (ipv4MulticastInterfaces.size() > 1)
517 {
518 //On Linux, if we have more than one MulticastUdpFace we need to specify
519 //the name of the interface
520 isNicNameNecessary = true;
521 }
522#endif
523
524 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i =
525 ipv4MulticastInterfaces.begin();
526 i != ipv4MulticastInterfaces.end();
527 ++i)
528 {
529 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
530 shared_ptr<MulticastUdpFace> newFace;
531 newFace = factory->createMulticastFace(nic->ipv4Addresses[0].to_string(),
532 mcastGroup,
533 mcastPort,
534 isNicNameNecessary ? nic->name : "");
535
536 addCreatedFaceToForwarder(newFace);
537 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600538 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700539 }
540}
541
542void
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600543FaceManager::processSectionEther(const ConfigSection& configSection,
544 bool isDryRun,
545 const std::list<shared_ptr<NetworkInterfaceInfo> >& nicList)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700546{
547 // ; the ether section contains settings of Ethernet faces and channels
548 // ether
549 // {
550 // ; NFD creates one Ethernet multicast face per NIC
551 // mcast yes ; set to 'no' to disable Ethernet multicast, default 'yes'
552 // mcast_group 01:00:5E:00:17:AA ; Ethernet multicast group
553 // }
554
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700555#if defined(HAVE_LIBPCAP)
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600556
557 using ethernet::Address;
558
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700559 bool useMcast = true;
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600560 Address mcastGroup(ethernet::getDefaultMulticastAddress());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700561
562 for (ConfigSection::const_iterator i = configSection.begin();
563 i != configSection.end();
564 ++i)
565 {
566 if (i->first == "mcast")
567 {
568 useMcast = parseYesNo(i, i->first, "ether");
569 }
570
571 else if (i->first == "mcast_group")
572 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600573 mcastGroup = Address::fromString(i->second.get_value<std::string>());
574 if (mcastGroup.isNull())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700575 {
576 throw ConfigFile::Error("Invalid value for option \"" +
577 i->first + "\" in \"ether\" section");
578 }
579 }
580 else
581 {
582 throw ConfigFile::Error("Unrecognized option \"" + i->first + "\" in \"ether\" section");
583 }
584 }
585
586 if (!isDryRun)
587 {
588 shared_ptr<EthernetFactory> factory = make_shared<EthernetFactory>();
589 m_factories.insert(std::make_pair("ether", factory));
590
591 if (useMcast)
592 {
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600593 for (std::list<shared_ptr<NetworkInterfaceInfo> >::const_iterator i = nicList.begin();
594 i != nicList.end();
595 ++i)
596 {
597 const shared_ptr<NetworkInterfaceInfo>& nic = *i;
598 if (nic->isUp() && nic->isMulticastCapable())
599 {
600 try
601 {
602 shared_ptr<EthernetFace> newFace =
Davide Pesaventob60cc122014-03-19 19:26:02 +0100603 factory->createMulticastFace(nic, mcastGroup);
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700604
605 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600606 }
607 catch (const EthernetFactory::Error& factoryError)
608 {
609 NFD_LOG_ERROR(factoryError.what() << ", continuing");
610 }
611 catch (const EthernetFace::Error& faceError)
612 {
613 NFD_LOG_ERROR(faceError.what() << ", continuing");
614 }
615 }
616 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700617 }
618 }
Steve DiBenedetto4aca99c2014-03-11 11:27:54 -0600619#else
620 throw ConfigFile::Error("NFD was compiled without libpcap, cannot process \"ether\" section");
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700621#endif // HAVE_LIBPCAP
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700622}
623
624
625void
626FaceManager::onFaceRequest(const Interest& request)
627{
628 const Name& command = request.getName();
629 const size_t commandNComps = command.size();
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600630 const Name::Component& verb = command.get(COMMAND_PREFIX.size());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700631
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600632 UnsignedVerbDispatchTable::const_iterator unsignedVerbProcessor = m_unsignedVerbDispatch.find(verb);
633 if (unsignedVerbProcessor != m_unsignedVerbDispatch.end())
634 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700635 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600636 (unsignedVerbProcessor->second)(this, boost::cref(request));
637 }
638 else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600639 commandNComps < COMMAND_SIGNED_NCOMPS)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700640 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700641 NFD_LOG_DEBUG("command result: unsigned verb: " << command);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700642 sendResponse(command, 401, "Signature required");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700643 }
644 else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
645 !COMMAND_PREFIX.isPrefixOf(command))
646 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700647 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700648 sendResponse(command, 400, "Malformed command");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700649 }
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600650 else
651 {
652 validate(request,
653 bind(&FaceManager::onValidatedFaceRequest, this, _1),
654 bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
655 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700656}
657
658void
659FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
660{
661 const Name& command = request->getName();
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600662 const Name::Component& verb = command[COMMAND_PREFIX.size()];
663 const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700664
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600665 SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
666 if (signedVerbProcessor != m_signedVerbDispatch.end())
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700667 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600668 ControlParameters parameters;
669 if (!extractParameters(parameterComponent, parameters))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700670 {
671 sendResponse(command, 400, "Malformed command");
672 return;
673 }
674
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700675 NFD_LOG_DEBUG("command result: processing verb: " << verb);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600676 (signedVerbProcessor->second)(this, *request, parameters);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700677 }
678 else
679 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700680 NFD_LOG_DEBUG("command result: unsupported verb: " << verb);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700681 sendResponse(command, 501, "Unsupported command");
682 }
683
684}
685
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700686void
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700687FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
688{
689 m_faceTable.add(newFace);
690
Junxiao Shi6e694322014-04-03 10:27:13 -0700691 //NFD_LOG_DEBUG("Created face " << newFace->getRemoteUri() << " ID " << newFace->getId());
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700692}
693
694void
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700695FaceManager::onCreated(const Name& requestName,
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600696 ControlParameters& parameters,
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700697 const shared_ptr<Face>& newFace)
698{
Alexander Afanasyevbbe3f0c2014-03-23 11:44:01 -0700699 addCreatedFaceToForwarder(newFace);
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600700 parameters.setFaceId(newFace->getId());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700701
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600702 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700703}
704
705void
706FaceManager::onConnectFailed(const Name& requestName, const std::string& reason)
707{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700708 NFD_LOG_DEBUG("Failed to create face: " << reason);
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600709 sendResponse(requestName, 408, reason);
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700710}
711
712void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600713FaceManager::createFace(const Interest& request,
714 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700715{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600716 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600717 ndn::nfd::FaceCreateCommand command;
718
719 if (!validateParameters(command, parameters))
720 {
721 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600722 NFD_LOG_TRACE("invalid control parameters URI");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600723 return;
724 }
725
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700726 FaceUri uri;
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600727 if (!uri.parse(parameters.getUri()))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700728 {
729 sendResponse(requestName, 400, "Malformed command");
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600730 NFD_LOG_TRACE("failed to parse URI");
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700731 return;
732 }
733
734 FactoryMap::iterator factory = m_factories.find(uri.getScheme());
735 if (factory == m_factories.end())
736 {
737 sendResponse(requestName, 501, "Unsupported protocol");
738 return;
739 }
740
Steve DiBenedettoca53ac62014-03-27 19:58:40 -0600741 try
742 {
743 factory->second->createFace(uri,
744 bind(&FaceManager::onCreated,
745 this, requestName, parameters, _1),
746 bind(&FaceManager::onConnectFailed,
747 this, requestName, _1));
748 }
749 catch (const std::runtime_error& error)
750 {
751 std::string errorMessage = "NFD error: ";
752 errorMessage += error.what();
753
754 NFD_LOG_ERROR(errorMessage);
755 sendResponse(requestName, 500, errorMessage);
756 }
757 catch (const std::logic_error& error)
758 {
759 std::string errorMessage = "NFD error: ";
760 errorMessage += error.what();
761
762 NFD_LOG_ERROR(errorMessage);
763 sendResponse(requestName, 500, errorMessage);
764 }
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700765}
766
767
768void
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600769FaceManager::destroyFace(const Interest& request,
770 ControlParameters& parameters)
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700771{
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600772 const Name& requestName = request.getName();
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600773 ndn::nfd::FaceDestroyCommand command;
774
775 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600776 {
777 sendResponse(requestName, 400, "Malformed command");
778 return;
779 }
780
781 shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600782 if (static_cast<bool>(target))
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700783 {
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700784 target->close();
785 }
Steve DiBenedettoba749052014-03-22 19:54:53 -0600786
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600787 sendResponse(requestName, 200, "Success", parameters.wireEncode());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600788
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700789}
790
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600791void
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600792FaceManager::onAddFace(shared_ptr<Face> face)
793{
Junxiao Shi6e694322014-04-03 10:27:13 -0700794 ndn::nfd::FaceEventNotification notification;
795 notification.setKind(ndn::nfd::FACE_EVENT_CREATED)
796 .setFaceId(face->getId())
797 .setRemoteUri(face->getRemoteUri().toString())
798 .setLocalUri(face->getLocalUri().toString())
799 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600800
Junxiao Shi6e694322014-04-03 10:27:13 -0700801 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600802}
803
804void
805FaceManager::onRemoveFace(shared_ptr<Face> face)
806{
Junxiao Shi6e694322014-04-03 10:27:13 -0700807 ndn::nfd::FaceEventNotification notification;
808 notification.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
809 .setFaceId(face->getId())
810 .setRemoteUri(face->getRemoteUri().toString())
811 .setLocalUri(face->getLocalUri().toString())
812 .setFlags(getFaceFlags(*face));
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600813
Junxiao Shi6e694322014-04-03 10:27:13 -0700814 m_notificationStream.postNotification(notification);
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600815}
816
817
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600818bool
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600819FaceManager::extractLocalControlParameters(const Interest& request,
820 ControlParameters& parameters,
821 ControlCommand& command,
822 shared_ptr<LocalFace>& outFace,
823 LocalControlFeature& outFeature)
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600824{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600825 if (!validateParameters(command, parameters))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600826 {
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600827 sendResponse(request.getName(), 400, "Malformed command");
828 return false;
829 }
830
831 shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
832
833 if (!static_cast<bool>(face))
834 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700835 NFD_LOG_DEBUG("command result: faceid " << request.getIncomingFaceId() << " not found");
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600836 sendResponse(request.getName(), 410, "Face not found");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600837 return false;
838 }
839 else if (!face->isLocal())
840 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700841 NFD_LOG_DEBUG("command result: cannot enable local control on non-local faceid " <<
842 face->getId());
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600843 sendResponse(request.getName(), 412, "Face is non-local");
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600844 return false;
845 }
846
847 outFace = dynamic_pointer_cast<LocalFace>(face);
848 outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
849
850 return true;
851}
852
853void
854FaceManager::enableLocalControl(const Interest& request,
855 ControlParameters& parameters)
856{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600857 ndn::nfd::FaceEnableLocalControlCommand command;
858
859
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600860 shared_ptr<LocalFace> face;
861 LocalControlFeature feature;
862
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600863 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600864 {
865 face->setLocalControlHeaderFeature(feature, true);
866 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
867 }
868}
869
870void
871FaceManager::disableLocalControl(const Interest& request,
872 ControlParameters& parameters)
873{
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600874 ndn::nfd::FaceDisableLocalControlCommand command;
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600875 shared_ptr<LocalFace> face;
876 LocalControlFeature feature;
877
Steve DiBenedetto51d242a2014-03-31 13:46:43 -0600878 if (extractLocalControlParameters(request, parameters, command, face, feature))
Steve DiBenedetto7564d972014-03-24 14:28:46 -0600879 {
880 face->setLocalControlHeaderFeature(feature, false);
881 sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
882 }
883}
884
Steve DiBenedettofbb40a82014-03-11 19:40:15 -0600885void
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600886FaceManager::listFaces(const Interest& request)
887{
888 const Name& command = request.getName();
889 const size_t commandNComps = command.size();
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700890
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600891 if (commandNComps < LIST_COMMAND_NCOMPS ||
892 !LIST_COMMAND_PREFIX.isPrefixOf(command))
893 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700894 NFD_LOG_DEBUG("command result: malformed");
Steve DiBenedetto9f6c3642014-03-10 17:02:27 -0600895 sendResponse(command, 400, "Malformed command");
896 return;
897 }
898
899 m_statusPublisher.publish();
900}
Steve DiBenedettoabe9e972014-02-20 15:37:04 -0700901
902} // namespace nfd