blob: c8dbcf91a8cf0832a9903773df077ae1e202c23d [file] [log] [blame]
Davide Pesavento44deacc2014-02-19 10:48:07 +01001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6
Alexander Afanasyev0eb70652014-02-27 18:35:07 -08007#include "ethernet-factory.hpp"
Davide Pesavento44deacc2014-02-19 10:48:07 +01008#include "core/global-io.hpp"
9
10#include <boost/algorithm/string/predicate.hpp>
11#include <pcap/pcap.h>
12
13namespace nfd {
14
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080015NFD_LOG_INIT("EthernetFactory")
Davide Pesavento44deacc2014-02-19 10:48:07 +010016
17shared_ptr<EthernetFace>
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080018EthernetFactory::createMulticast(const ethernet::Endpoint& interface,
19 const ethernet::Address& address)
Davide Pesavento44deacc2014-02-19 10:48:07 +010020{
21 std::vector<ethernet::Endpoint> ifs = findAllInterfaces();
22 if (std::find(ifs.begin(), ifs.end(), interface) == ifs.end())
23 throw Error(interface + " does not exist");
24
25 if (!address.isMulticast())
26 throw Error(address.toString() + " is not a multicast address");
27
28 shared_ptr<EthernetFace> face = findMulticast(interface, address);
29 if (face)
30 return face;
31
32 shared_ptr<boost::asio::posix::stream_descriptor> socket =
33 make_shared<boost::asio::posix::stream_descriptor>(boost::ref(getGlobalIoService()));
34
35 face = make_shared<EthernetFace>(boost::cref(socket),
36 boost::cref(interface),
37 boost::cref(address));
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080038 face->onFail += bind(&EthernetFactory::afterFaceFailed,
Davide Pesavento44deacc2014-02-19 10:48:07 +010039 this, interface, address);
40 m_multicastFaces[std::make_pair(interface, address)] = face;
41
42 return face;
43}
44
45std::vector<ethernet::Endpoint>
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080046EthernetFactory::findAllInterfaces()
Davide Pesavento44deacc2014-02-19 10:48:07 +010047{
48 std::vector<ethernet::Endpoint> interfaces;
49 char errbuf[PCAP_ERRBUF_SIZE];
50 errbuf[0] = '\0';
51
52 pcap_if_t* alldevs;
53 if (pcap_findalldevs(&alldevs, errbuf) < 0)
54 {
55 NFD_LOG_WARN("pcap_findalldevs() failed: " << errbuf);
56 return interfaces;
57 }
58
59 for (pcap_if_t* device = alldevs; device != 0; device = device->next)
60 {
61 if ((device->flags & PCAP_IF_LOOPBACK) != 0)
62 // ignore loopback devices
63 continue;
64
65 ethernet::Endpoint interface(device->name);
66 if (interface == "any")
67 // ignore libpcap "any" pseudo-device
68 continue;
69 if (boost::starts_with(interface, "nflog") ||
70 boost::starts_with(interface, "nfqueue"))
71 // ignore Linux netfilter devices
72 continue;
Alexander Afanasyevef968e12014-02-27 15:17:50 -080073 if (boost::starts_with(interface, "fw"))
74 // ignore OSX firewire interface
75 continue;
Davide Pesavento44deacc2014-02-19 10:48:07 +010076
77 // maybe add interface addresses too
78 // interface.addAddress ...
79 interfaces.push_back(interface);
80 }
81
82 pcap_freealldevs(alldevs);
83 return interfaces;
84}
85
86void
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080087EthernetFactory::afterFaceFailed(const ethernet::Endpoint& interface,
88 const ethernet::Address& address)
Davide Pesavento44deacc2014-02-19 10:48:07 +010089{
90 NFD_LOG_DEBUG("afterFaceFailed: " << interface << "/" << address);
91 m_multicastFaces.erase(std::make_pair(interface, address));
92}
93
94shared_ptr<EthernetFace>
Alexander Afanasyev0eb70652014-02-27 18:35:07 -080095EthernetFactory::findMulticast(const ethernet::Endpoint& interface,
96 const ethernet::Address& address) const
Davide Pesavento44deacc2014-02-19 10:48:07 +010097{
98 MulticastFacesMap::const_iterator i = m_multicastFaces.find(std::make_pair(interface, address));
99 if (i != m_multicastFaces.end())
100 return i->second;
101 else
102 return shared_ptr<EthernetFace>();
103}
104
105} // namespace nfd