1 // Copyright (C) 2011-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 #include <asiolink/asio_wrapper.h>
9 #include <asiolink/io_error.h>
10 #include <asiolink/udp_endpoint.h>
11 #include <dhcp/dhcp4.h>
12 #include <dhcp/dhcp6.h>
13 #include <dhcp/iface_mgr.h>
14 #include <dhcp/iface_mgr_error_handler.h>
15 #include <dhcp/pkt_filter_inet.h>
16 #include <dhcp/pkt_filter_inet6.h>
17 #include <exceptions/exceptions.h>
18 #include <util/io/pktinfo_utilities.h>
19 #include <util/multi_threading_mgr.h>
20 
21 #include <boost/scoped_ptr.hpp>
22 
23 #include <cstring>
24 #include <errno.h>
25 #include <fstream>
26 #include <functional>
27 #include <limits>
28 #include <sstream>
29 
30 #include <arpa/inet.h>
31 #include <netinet/in.h>
32 #include <string.h>
33 #include <sys/ioctl.h>
34 #include <sys/select.h>
35 
36 #ifndef FD_COPY
37 #define FD_COPY(orig, copy) \
38     do { \
39         memmove(copy, orig, sizeof(fd_set)); \
40     } while (0)
41 #endif
42 
43 using namespace std;
44 using namespace isc::asiolink;
45 using namespace isc::util;
46 using namespace isc::util::io;
47 using namespace isc::util::io::internal;
48 
49 namespace isc {
50 namespace dhcp {
51 
52 IfaceMgr&
instance()53 IfaceMgr::instance() {
54     return (*instancePtr());
55 }
56 
57 const IfaceMgrPtr&
instancePtr()58 IfaceMgr::instancePtr() {
59     static IfaceMgrPtr iface_mgr(new IfaceMgr());
60     return (iface_mgr);
61 }
62 
Iface(const std::string & name,unsigned int ifindex)63 Iface::Iface(const std::string& name, unsigned int ifindex)
64     :name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
65      flag_loopback_(false), flag_up_(false), flag_running_(false),
66      flag_multicast_(false), flag_broadcast_(false), flags_(0),
67      inactive4_(false), inactive6_(false)
68 {
69     // Sanity checks.
70     if (name.empty()) {
71         isc_throw(BadValue, "Interface name must not be empty");
72     }
73     memset(mac_, 0, sizeof(mac_));
74 }
75 
76 void
closeSockets()77 Iface::closeSockets() {
78     // Close IPv4 sockets.
79     closeSockets(AF_INET);
80     // Close IPv6 sockets.
81     closeSockets(AF_INET6);
82 }
83 
84 void
closeSockets(const uint16_t family)85 Iface::closeSockets(const uint16_t family) {
86     // Check that the correct 'family' value has been specified.
87     // The possible values are AF_INET or AF_INET6. Note that, in
88     // the current code they are used to differentiate that the
89     // socket is used to transmit IPv4 or IPv6 traffic. However,
90     // the actual family types of the sockets may be different,
91     // e.g. for LPF we are using raw sockets of AF_PACKET family.
92     //
93     // @todo Consider replacing the AF_INET and AF_INET6 with some
94     // enum which will not be confused with the actual socket type.
95     if ((family != AF_INET) && (family != AF_INET6)) {
96         isc_throw(BadValue, "Invalid socket family " << family
97                   << " specified when requested to close all sockets"
98                   << " which belong to this family");
99     }
100 
101     // Search for the socket of the specific type.
102     SocketCollection::iterator sock = sockets_.begin();
103     while (sock != sockets_.end()) {
104         if (sock->family_ == family) {
105             // Close and delete the socket and move to the
106             // next one.
107             close(sock->sockfd_);
108             // Close fallback socket if open.
109             if (sock->fallbackfd_ >= 0) {
110                 close(sock->fallbackfd_);
111             }
112             sockets_.erase(sock++);
113 
114         } else {
115             // Different type of socket. Let's move
116             // to the next one.
117             ++sock;
118 
119         }
120     }
121 }
122 
123 std::string
getFullName() const124 Iface::getFullName() const {
125     ostringstream tmp;
126     tmp << name_ << "/" << ifindex_;
127     return (tmp.str());
128 }
129 
130 std::string
getPlainMac() const131 Iface::getPlainMac() const {
132     ostringstream tmp;
133     tmp.fill('0');
134     tmp << hex;
135     for (int i = 0; i < mac_len_; i++) {
136         tmp.width(2);
137         tmp <<  static_cast<int>(mac_[i]);
138         if (i < mac_len_-1) {
139             tmp << ":";
140         }
141     }
142     return (tmp.str());
143 }
144 
setMac(const uint8_t * mac,size_t len)145 void Iface::setMac(const uint8_t* mac, size_t len) {
146     if (len > MAX_MAC_LEN) {
147         isc_throw(OutOfRange, "Interface " << getFullName()
148                   << " was detected to have link address of length "
149                   << len << ", but maximum supported length is "
150                   << MAX_MAC_LEN);
151     }
152     mac_len_ = len;
153     if (len > 0) {
154         memcpy(mac_, mac, len);
155     }
156 }
157 
delAddress(const isc::asiolink::IOAddress & addr)158 bool Iface::delAddress(const isc::asiolink::IOAddress& addr) {
159     for (AddressCollection::iterator a = addrs_.begin();
160          a!=addrs_.end(); ++a) {
161         if (a->get() == addr) {
162             addrs_.erase(a);
163             return (true);
164         }
165     }
166     return (false);
167 }
168 
delSocket(const uint16_t sockfd)169 bool Iface::delSocket(const uint16_t sockfd) {
170     list<SocketInfo>::iterator sock = sockets_.begin();
171     while (sock!=sockets_.end()) {
172         if (sock->sockfd_ == sockfd) {
173             close(sockfd);
174             // Close fallback socket if open.
175             if (sock->fallbackfd_ >= 0) {
176                 close(sock->fallbackfd_);
177             }
178             sockets_.erase(sock);
179             return (true); //socket found
180         }
181         ++sock;
182     }
183     return (false); // socket not found
184 }
185 
IfaceMgr()186 IfaceMgr::IfaceMgr()
187     : packet_filter_(new PktFilterInet()),
188       packet_filter6_(new PktFilterInet6()),
189       test_mode_(false),
190       allow_loopback_(false) {
191 
192     // Ensure that PQMs have been created to guarantee we have
193     // default packet queues in place.
194     try {
195         packet_queue_mgr4_.reset(new PacketQueueMgr4());
196         packet_queue_mgr6_.reset(new PacketQueueMgr6());
197     } catch (const std::exception& ex) {
198         isc_throw(Unexpected, "Failed to create PacketQueueManagers: " << ex.what());
199     }
200 
201     try {
202 
203         // required for sending/receiving packets
204         // let's keep it in front, just in case someone
205         // wants to send anything during initialization
206         detectIfaces();
207 
208     } catch (const std::exception& ex) {
209         isc_throw(IfaceDetectError, ex.what());
210     }
211 }
212 
addUnicast(const isc::asiolink::IOAddress & addr)213 void Iface::addUnicast(const isc::asiolink::IOAddress& addr) {
214     for (Address a : unicasts_) {
215         if (a.get() == addr) {
216             isc_throw(BadValue, "Address " << addr
217                       << " already defined on the " << name_ << " interface.");
218         }
219     }
220     unicasts_.push_back(Optional<IOAddress>(addr));
221 }
222 
223 bool
getAddress4(isc::asiolink::IOAddress & address) const224 Iface::getAddress4(isc::asiolink::IOAddress& address) const {
225     // Iterate over existing addresses assigned to the interface.
226     // Try to find the one that is IPv4.
227     for (Address addr : getAddresses()) {
228         // If address is IPv4, we assign it to the function argument
229         // and return true.
230         if (addr.get().isV4()) {
231             address = addr.get();
232             return (true);
233         }
234     }
235     // There is no IPv4 address assigned to this interface.
236     return (false);
237 }
238 
239 bool
hasAddress(const isc::asiolink::IOAddress & address) const240 Iface::hasAddress(const isc::asiolink::IOAddress& address) const {
241     for (Address addr : getAddresses()) {
242         if (address == addr.get()) {
243             return (true);
244         }
245     }
246     return (false);
247 }
248 
249 void
addAddress(const isc::asiolink::IOAddress & addr)250 Iface::addAddress(const isc::asiolink::IOAddress& addr) {
251     addrs_.push_back(Address(addr));
252 }
253 
254 void
setActive(const IOAddress & address,const bool active)255 Iface::setActive(const IOAddress& address, const bool active) {
256     for (AddressCollection::iterator addr_it = addrs_.begin();
257          addr_it != addrs_.end(); ++addr_it) {
258         if (address == addr_it->get()) {
259             addr_it->unspecified(!active);
260             return;
261         }
262     }
263     isc_throw(BadValue, "specified address " << address << " was not"
264               " found on the interface " << getName());
265 }
266 
267 void
setActive(const bool active)268 Iface::setActive(const bool active) {
269     for (AddressCollection::iterator addr_it = addrs_.begin();
270          addr_it != addrs_.end(); ++addr_it) {
271         addr_it->unspecified(!active);
272     }
273 }
274 
275 unsigned int
countActive4() const276 Iface::countActive4() const {
277     uint16_t count = 0;
278     for (Address addr : addrs_) {
279         if (!addr.unspecified() && addr.get().isV4()) {
280             ++count;
281         }
282     }
283     return (count);
284 }
285 
closeSockets()286 void IfaceMgr::closeSockets() {
287     // Clears bound addresses.
288     clearBoundAddresses();
289 
290     // Stops the receiver thread if there is one.
291     stopDHCPReceiver();
292 
293     for (IfacePtr iface : ifaces_) {
294         iface->closeSockets();
295     }
296 }
297 
stopDHCPReceiver()298 void IfaceMgr::stopDHCPReceiver() {
299     if (isDHCPReceiverRunning()) {
300         dhcp_receiver_->stop();
301     }
302 
303     dhcp_receiver_.reset();
304 
305     if (getPacketQueue4()) {
306         getPacketQueue4()->clear();
307     }
308 
309     if (getPacketQueue6()) {
310         getPacketQueue6()->clear();
311     }
312 }
313 
~IfaceMgr()314 IfaceMgr::~IfaceMgr() {
315     closeSockets();
316 }
317 
318 bool
isDirectResponseSupported() const319 IfaceMgr::isDirectResponseSupported() const {
320     return (packet_filter_->isDirectResponseSupported());
321 }
322 
323 void
addExternalSocket(int socketfd,SocketCallback callback)324 IfaceMgr::addExternalSocket(int socketfd, SocketCallback callback) {
325     if (socketfd < 0) {
326         isc_throw(BadValue, "Attempted to install callback for invalid socket "
327                   << socketfd);
328     }
329     std::lock_guard<std::mutex> lock(callbacks_mutex_);
330     for (SocketCallbackInfo s : callbacks_) {
331         // There's such a socket description there already.
332         // Update the callback and we're done
333         if (s.socket_ == socketfd) {
334             s.callback_ = callback;
335             return;
336         }
337     }
338 
339     // Add a new entry to the callbacks vector
340     SocketCallbackInfo x;
341     x.socket_ = socketfd;
342     x.callback_ = callback;
343     callbacks_.push_back(x);
344 }
345 
346 void
deleteExternalSocket(int socketfd)347 IfaceMgr::deleteExternalSocket(int socketfd) {
348     std::lock_guard<std::mutex> lock(callbacks_mutex_);
349     deleteExternalSocketInternal(socketfd);
350 }
351 
352 void
deleteExternalSocketInternal(int socketfd)353 IfaceMgr::deleteExternalSocketInternal(int socketfd) {
354     for (SocketCallbackInfoContainer::iterator s = callbacks_.begin();
355          s != callbacks_.end(); ++s) {
356         if (s->socket_ == socketfd) {
357             callbacks_.erase(s);
358             return;
359         }
360     }
361 }
362 
363 int
purgeBadSockets()364 IfaceMgr::purgeBadSockets() {
365     std::lock_guard<std::mutex> lock(callbacks_mutex_);
366     std::vector<int> bad_fds;
367     for (SocketCallbackInfo s : callbacks_) {
368         errno = 0;
369         if (fcntl(s.socket_, F_GETFD) < 0 && (errno == EBADF)) {
370             bad_fds.push_back(s.socket_);
371         }
372     }
373 
374     for (auto bad_fd : bad_fds) {
375         deleteExternalSocketInternal(bad_fd);
376     }
377 
378     return (bad_fds.size());
379 }
380 
381 void
deleteAllExternalSockets()382 IfaceMgr::deleteAllExternalSockets() {
383     std::lock_guard<std::mutex> lock(callbacks_mutex_);
384     callbacks_.clear();
385 }
386 
387 void
setPacketFilter(const PktFilterPtr & packet_filter)388 IfaceMgr::setPacketFilter(const PktFilterPtr& packet_filter) {
389     // Do not allow null pointer.
390     if (!packet_filter) {
391         isc_throw(InvalidPacketFilter, "NULL packet filter object specified for"
392                   " DHCPv4");
393     }
394     // Different packet filters use different socket types. It does not make
395     // sense to allow the change of packet filter when there are IPv4 sockets
396     // open because they can't be used by the receive/send functions of the
397     // new packet filter. Below, we check that there are no open IPv4 sockets.
398     // If we find at least one, we have to fail. However, caller still has a
399     // chance to replace the packet filter if he closes sockets explicitly.
400     if (hasOpenSocket(AF_INET)) {
401         // There is at least one socket open, so we have to fail.
402         isc_throw(PacketFilterChangeDenied,
403                   "it is not allowed to set new packet"
404                   << " filter when there are open IPv4 sockets - need"
405                   << " to close them first");
406     }
407     // Everything is fine, so replace packet filter.
408     packet_filter_ = packet_filter;
409 }
410 
411 void
setPacketFilter(const PktFilter6Ptr & packet_filter)412 IfaceMgr::setPacketFilter(const PktFilter6Ptr& packet_filter) {
413     if (!packet_filter) {
414         isc_throw(InvalidPacketFilter, "NULL packet filter object specified for"
415                   " DHCPv6");
416     }
417 
418     if (hasOpenSocket(AF_INET6)) {
419         // There is at least one socket open, so we have to fail.
420         isc_throw(PacketFilterChangeDenied,
421                   "it is not allowed to set new packet"
422                   << " filter when there are open IPv6 sockets - need"
423                   << " to close them first");
424     }
425 
426     packet_filter6_ = packet_filter;
427 }
428 
429 bool
hasOpenSocket(const uint16_t family) const430 IfaceMgr::hasOpenSocket(const uint16_t family) const {
431     // Iterate over all interfaces and search for open sockets.
432     for (IfacePtr iface : ifaces_) {
433         for (SocketInfo sock : iface->getSockets()) {
434             // Check if the socket matches specified family.
435             if (sock.family_ == family) {
436                 // There is at least one socket open, so return.
437                 return (true);
438             }
439         }
440     }
441     // There are no open sockets found for the specified family.
442     return (false);
443 }
444 
445 bool
hasOpenSocket(const IOAddress & addr) const446 IfaceMgr::hasOpenSocket(const IOAddress& addr) const {
447     // Fast track for IPv4 using bound addresses.
448     if (addr.isV4() && !bound_address_.empty()) {
449         return (bound_address_.count(addr.toUint32()) != 0);
450     }
451     // Iterate over all interfaces and search for open sockets.
452     for (IfacePtr iface : ifaces_) {
453         for (SocketInfo sock : iface->getSockets()) {
454             // Check if the socket address matches the specified address or
455             // if address is unspecified (in6addr_any).
456             if (sock.addr_ == addr) {
457                 return (true);
458             } else if (sock.addr_.isV6Zero()) {
459                 // Handle the case that the address is unspecified (any).
460                 // This happens only with IPv6 so we do not check IPv4.
461                 // In this case, we should check if the specified address
462                 // belongs to any of the interfaces.
463                 for (IfacePtr it : ifaces_) {
464                     for (Iface::Address a : it->getAddresses()) {
465                         if (addr == a.get()) {
466                             return (true);
467                         }
468                     }
469                 }
470                 // The address does not belongs to any interface.
471                 return (false);
472             }
473         }
474     }
475     // There are no open sockets found for the specified family.
476     return (false);
477 }
478 
stubDetectIfaces()479 void IfaceMgr::stubDetectIfaces() {
480     string ifaceName;
481     const string v4addr("127.0.0.1"), v6addr("::1");
482 
483     // This is a stub implementation for interface detection. Actual detection
484     // is faked by detecting loopback interface (lo or lo0). It will eventually
485     // be removed once we have actual implementations for all supported systems.
486 
487     if (if_nametoindex("lo") > 0) {
488         ifaceName = "lo";
489         // this is Linux-like OS
490     } else if (if_nametoindex("lo0") > 0) {
491         ifaceName = "lo0";
492         // this is BSD-like OS
493     } else {
494         // we give up. What OS is this, anyway? Solaris? Hurd?
495         isc_throw(NotImplemented,
496                   "Interface detection on this OS is not supported.");
497     }
498 
499     IfacePtr iface(new Iface(ifaceName, if_nametoindex(ifaceName.c_str())));
500     iface->flag_up_ = true;
501     iface->flag_running_ = true;
502 
503     // Note that we claim that this is not a loopback. iface_mgr tries to open a
504     // socket on all interfaces that are up, running and not loopback. As this is
505     // the only interface we were able to detect, let's pretend this is a normal
506     // interface.
507     iface->flag_loopback_ = false;
508     iface->flag_multicast_ = true;
509     iface->flag_broadcast_ = true;
510     iface->setHWType(HWTYPE_ETHERNET);
511 
512     iface->addAddress(IOAddress(v4addr));
513     iface->addAddress(IOAddress(v6addr));
514     addInterface(iface);
515 }
516 
517 bool
openSockets4(const uint16_t port,const bool use_bcast,IfaceMgrErrorMsgCallback error_handler)518 IfaceMgr::openSockets4(const uint16_t port, const bool use_bcast,
519                        IfaceMgrErrorMsgCallback error_handler) {
520     int count = 0;
521     int bcast_num = 0;
522 
523     for (IfacePtr iface : ifaces_) {
524         // If the interface is inactive, there is nothing to do. Simply
525         // proceed to the next detected interface.
526         if (iface->inactive4_) {
527             continue;
528 
529         } else {
530             // If the interface has been specified in the configuration that
531             // it should be used to listen the DHCP traffic we have to check
532             // that the interface configuration is valid and that the interface
533             // is not a loopback interface. In both cases, we want to report
534             // that the socket will not be opened.
535             // Relax the check when the loopback interface was explicitly
536             // allowed
537             if (iface->flag_loopback_ && !allow_loopback_) {
538                 IFACEMGR_ERROR(SocketConfigError, error_handler,
539                                "must not open socket on the loopback"
540                                " interface " << iface->getName());
541                 continue;
542 
543             }
544 
545             if (!iface->flag_up_) {
546                 IFACEMGR_ERROR(SocketConfigError, error_handler,
547                                "the interface " << iface->getName()
548                                << " is down");
549                 continue;
550             }
551 
552             if (!iface->flag_running_) {
553                 IFACEMGR_ERROR(SocketConfigError, error_handler,
554                                "the interface " << iface->getName()
555                                << " is not running");
556                 continue;
557             }
558 
559             IOAddress out_address("0.0.0.0");
560             if (!iface->getAddress4(out_address)) {
561                 IFACEMGR_ERROR(SocketConfigError, error_handler,
562                                "the interface " << iface->getName()
563                                << " has no usable IPv4 addresses configured");
564                 continue;
565             }
566         }
567 
568         for (Iface::Address addr : iface->getAddresses()) {
569             // Skip non-IPv4 addresses and those that weren't selected..
570             if (addr.unspecified() || !addr.get().isV4()) {
571                 continue;
572             }
573 
574             // If selected interface is broadcast capable set appropriate
575             // options on the socket so as it can receive and send broadcast
576             // messages.
577             if (iface->flag_broadcast_ && use_bcast) {
578                 // The DHCP server must have means to determine which interface
579                 // the broadcast packets are coming from. This is achieved by
580                 // binding a socket to the device (interface) and specialized
581                 // packet filters (e.g. BPF and LPF) implement this mechanism.
582                 // If the PktFilterInet (generic one) is used, the socket is
583                 // bound to INADDR_ANY which effectively binds the socket to
584                 // all addresses on all interfaces. So, only one of those can
585                 // be opened. Currently, the direct response support is
586                 // provided by the PktFilterLPF and PktFilterBPF, so by checking
587                 // the support for direct response we actually determine that
588                 // one of those objects is in use. For all other objects we
589                 // assume that binding to the device is not supported and we
590                 // cease opening sockets and display the appropriate message.
591                 if (!isDirectResponseSupported() && bcast_num > 0) {
592                     IFACEMGR_ERROR(SocketConfigError, error_handler,
593                                    "Binding socket to an interface is not"
594                                    " supported on this OS; therefore only"
595                                    " one socket listening to broadcast traffic"
596                                    " can be opened. Sockets will not be opened"
597                                    " on remaining interfaces");
598                     continue;
599 
600                 } else {
601                     try {
602                         // We haven't open any broadcast sockets yet, so we can
603                         // open at least one more.
604                         openSocket(iface->getName(), addr.get(), port, true, true);
605                     } catch (const Exception& ex) {
606                         IFACEMGR_ERROR(SocketConfigError, error_handler,
607                                        "failed to open socket on interface "
608                                        << iface->getName() << ", reason: "
609                                        << ex.what());
610                         continue;
611 
612                     }
613                     // Binding socket to an interface is not supported so we
614                     // can't open any more broadcast sockets. Increase the
615                     // number of open broadcast sockets.
616                     ++bcast_num;
617                 }
618 
619             } else {
620                 try {
621                     // Not broadcast capable, do not set broadcast flags.
622                     openSocket(iface->getName(), addr.get(), port, false, false);
623                 } catch (const Exception& ex) {
624                     IFACEMGR_ERROR(SocketConfigError, error_handler,
625                                    "failed to open socket on interface "
626                                    << iface->getName() << ", reason: "
627                                    << ex.what());
628                     continue;
629                 }
630 
631             }
632             ++count;
633 
634         }
635     }
636 
637     // If we have open sockets, start the receiver.
638     if (count > 0) {
639         // Collects bound addresses.
640         collectBoundAddresses();
641 
642         // Starts the receiver thread (if queueing is enabled).
643         startDHCPReceiver(AF_INET);
644     }
645 
646     return (count > 0);
647 }
648 
649 bool
openSockets6(const uint16_t port,IfaceMgrErrorMsgCallback error_handler)650 IfaceMgr::openSockets6(const uint16_t port,
651                        IfaceMgrErrorMsgCallback error_handler) {
652     int count = 0;
653 
654     for (IfacePtr iface : ifaces_) {
655         if (iface->inactive6_) {
656             continue;
657 
658         } else {
659             // If the interface has been specified in the configuration that
660             // it should be used to listen the DHCP traffic we have to check
661             // that the interface configuration is valid and that the interface
662             // is not a loopback interface. In both cases, we want to report
663             // that the socket will not be opened.
664             // Relax the check when the loopback interface was explicitly
665             // allowed
666             if (iface->flag_loopback_ && !allow_loopback_) {
667                 IFACEMGR_ERROR(SocketConfigError, error_handler,
668                                "must not open socket on the loopback"
669                                " interface " << iface->getName());
670                 continue;
671 
672             } else if (!iface->flag_up_) {
673                 IFACEMGR_ERROR(SocketConfigError, error_handler,
674                                "the interface " << iface->getName()
675                                << " is down");
676                 continue;
677             } else if (!iface->flag_running_) {
678                 IFACEMGR_ERROR(SocketConfigError, error_handler,
679                                "the interface " << iface->getName()
680                                << " is not running");
681                 continue;
682             }
683 
684         }
685 
686         // Open unicast sockets if there are any unicast addresses defined
687         for (Iface::Address addr : iface->getUnicasts()) {
688 
689             try {
690                 openSocket(iface->getName(), addr, port);
691             } catch (const Exception& ex) {
692                 IFACEMGR_ERROR(SocketConfigError, error_handler,
693                                "Failed to open unicast socket on  interface "
694                                << iface->getName() << ", reason: "
695                                << ex.what());
696                 continue;
697             }
698 
699             count++;
700 
701         }
702 
703         for (Iface::Address addr : iface->getAddresses()) {
704 
705             // Skip all but V6 addresses.
706             if (!addr.get().isV6()) {
707                 continue;
708             }
709 
710             // Bind link-local addresses only. Otherwise we bind several sockets
711             // on interfaces that have several global addresses. For examples
712             // with interface with 2 global addresses, we would bind 3 sockets
713             // (one for link-local and two for global). That would result in
714             // getting each message 3 times.
715             if (!addr.get().isV6LinkLocal()){
716                 continue;
717             }
718 
719             // Run OS-specific function to open a socket capable of receiving
720             // packets sent to All_DHCP_Relay_Agents_and_Servers multicast
721             // address.
722             if (openMulticastSocket(*iface, addr, port, error_handler)) {
723                 ++count;
724             }
725 
726         }
727     }
728 
729     // If we have open sockets, start the receiver.
730     if (count > 0) {
731         // starts the receiver thread (if queueing is enabled).
732         startDHCPReceiver(AF_INET6);
733     }
734     return (count > 0);
735 }
736 
737 void
startDHCPReceiver(const uint16_t family)738 IfaceMgr::startDHCPReceiver(const uint16_t family) {
739     if (isDHCPReceiverRunning()) {
740         isc_throw(InvalidOperation, "a receiver thread already exists");
741     }
742 
743     switch (family) {
744     case AF_INET:
745         // If the queue doesn't exist, packet queing has been configured
746         // as disabled. If there is no queue, we do not create a receiver.
747         if(!getPacketQueue4()) {
748             return;
749         }
750 
751         dhcp_receiver_.reset(new WatchedThread());
752         dhcp_receiver_->start(std::bind(&IfaceMgr::receiveDHCP4Packets, this));
753         break;
754     case AF_INET6:
755         // If the queue doesn't exist, packet queing has been configured
756         // as disabled. If there is no queue, we do not create a receiver.
757         if(!getPacketQueue6()) {
758             return;
759         }
760 
761         dhcp_receiver_.reset(new WatchedThread());
762         dhcp_receiver_->start(std::bind(&IfaceMgr::receiveDHCP6Packets, this));
763         break;
764     default:
765         isc_throw (BadValue, "startDHCPReceiver: invalid family: " << family);
766         break;
767     }
768 }
769 
770 void
addInterface(const IfacePtr & iface)771 IfaceMgr::addInterface(const IfacePtr& iface) {
772     for (const IfacePtr& existing : ifaces_) {
773         if ((existing->getName() == iface->getName()) ||
774             (existing->getIndex() == iface->getIndex())) {
775             isc_throw(Unexpected, "Can't add " << iface->getFullName() <<
776                       " when " << existing->getFullName() <<
777                       " already exists.");
778         }
779     }
780     ifaces_.push_back(iface);
781 }
782 
783 void
printIfaces(std::ostream & out)784 IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
785     for (IfacePtr iface : ifaces_) {
786         const Iface::AddressCollection& addrs = iface->getAddresses();
787 
788         out << "Detected interface " << iface->getFullName()
789             << ", hwtype=" << iface->getHWType()
790             << ", mac=" << iface->getPlainMac();
791         out << ", flags=" << hex << iface->flags_ << dec << "("
792             << (iface->flag_loopback_?"LOOPBACK ":"")
793             << (iface->flag_up_?"UP ":"")
794             << (iface->flag_running_?"RUNNING ":"")
795             << (iface->flag_multicast_?"MULTICAST ":"")
796             << (iface->flag_broadcast_?"BROADCAST ":"")
797             << ")" << endl;
798         out << "  " << addrs.size() << " addr(s):";
799 
800         for (Iface::Address addr : addrs) {
801             out << "  " << addr.get().toText();
802         }
803         out << endl;
804     }
805 }
806 
807 IfacePtr
getIface(uint32_t ifindex)808 IfaceCollection::getIface(uint32_t ifindex) {
809     return (getIfaceInternal(ifindex, MultiThreadingMgr::instance().getMode()));
810 }
811 
812 
813 IfacePtr
getIface(const std::string & ifname)814 IfaceCollection::getIface(const std::string& ifname) {
815     return (getIfaceInternal(ifname, MultiThreadingMgr::instance().getMode()));
816 }
817 
818 IfacePtr
getIfaceInternal(uint32_t ifindex,bool need_lock)819 IfaceCollection::getIfaceInternal(uint32_t ifindex, bool need_lock) {
820     if (need_lock) {
821         lock_guard<mutex> lock(mutex_);
822         if (cache_ && (cache_->getIndex() == ifindex)) {
823             return (cache_);
824         }
825     } else {
826         if (cache_ && (cache_->getIndex() == ifindex)) {
827             return (cache_);
828         }
829     }
830     const auto& idx = ifaces_container_.get<1>();
831     auto it = idx.find(ifindex);
832     if (it == idx.end()) {
833         return (IfacePtr()); // not found
834     }
835     if (need_lock) {
836         lock_guard<mutex> lock(mutex_);
837         cache_ = *it;
838         return (cache_);
839     } else {
840         lock_guard<mutex> lock(mutex_);
841         cache_ = *it;
842         return (cache_);
843     }
844 }
845 
846 IfacePtr
getIfaceInternal(const std::string & ifname,bool need_lock)847 IfaceCollection::getIfaceInternal(const std::string& ifname, bool need_lock) {
848     if (need_lock) {
849         lock_guard<mutex> lock(mutex_);
850         if (cache_ && (cache_->getName() == ifname)) {
851             return (cache_);
852         }
853     } else {
854         if (cache_ && (cache_->getName() == ifname)) {
855             return (cache_);
856         }
857     }
858     const auto& idx = ifaces_container_.get<2>();
859     auto it = idx.find(ifname);
860     if (it == idx.end()) {
861         return (IfacePtr()); // not found
862     }
863     if (need_lock) {
864         lock_guard<mutex> lock(mutex_);
865         cache_ = *it;
866         return (cache_);
867     } else {
868         lock_guard<mutex> lock(mutex_);
869         cache_ = *it;
870         return (cache_);
871     }
872 }
873 
874 IfacePtr
getIface(int ifindex)875 IfaceMgr::getIface(int ifindex) {
876     if ((ifindex < 0) || (ifindex > std::numeric_limits<int32_t>::max())) {
877         return (IfacePtr()); // out of range
878     }
879     return (ifaces_.getIface(ifindex));
880 }
881 
882 IfacePtr
getIface(const std::string & ifname)883 IfaceMgr::getIface(const std::string& ifname) {
884     if (ifname.empty()) {
885         return (IfacePtr()); // empty
886     }
887     return (ifaces_.getIface(ifname));
888 }
889 
890 IfacePtr
getIface(const PktPtr & pkt)891 IfaceMgr::getIface(const PktPtr& pkt) {
892     if (pkt->indexSet()) {
893         return (getIface(pkt->getIndex()));
894     } else {
895         return (getIface(pkt->getIface()));
896     }
897 }
898 
899 void
clearIfaces()900 IfaceMgr::clearIfaces() {
901     ifaces_.clear();
902 }
903 
904 void
clearBoundAddresses()905 IfaceMgr::clearBoundAddresses() {
906     bound_address_.clear();
907 }
908 
909 void
collectBoundAddresses()910 IfaceMgr::collectBoundAddresses() {
911     for (IfacePtr iface : ifaces_) {
912         for (SocketInfo sock : iface->getSockets()) {
913             const IOAddress& addr = sock.addr_;
914             if (!addr.isV4()) {
915                 continue;
916             }
917             if (bound_address_.count(addr.toUint32()) == 0) {
918                 bound_address_.insert(addr);
919             }
920         }
921     }
922 }
923 
924 void
clearUnicasts()925 IfaceMgr::clearUnicasts() {
926     for (IfacePtr iface : ifaces_) {
927         iface->clearUnicasts();
928     }
929 }
930 
openSocket(const std::string & ifname,const IOAddress & addr,const uint16_t port,const bool receive_bcast,const bool send_bcast)931 int IfaceMgr::openSocket(const std::string& ifname, const IOAddress& addr,
932                          const uint16_t port, const bool receive_bcast,
933                          const bool send_bcast) {
934     IfacePtr iface = getIface(ifname);
935     if (!iface) {
936         isc_throw(BadValue, "There is no " << ifname << " interface present.");
937     }
938     if (addr.isV4()) {
939         return openSocket4(*iface, addr, port, receive_bcast, send_bcast);
940 
941     } else if (addr.isV6()) {
942         return openSocket6(*iface, addr, port, receive_bcast);
943 
944     } else {
945         isc_throw(BadValue, "Failed to detect family of address: "
946                   << addr);
947     }
948 }
949 
openSocketFromIface(const std::string & ifname,const uint16_t port,const uint8_t family)950 int IfaceMgr::openSocketFromIface(const std::string& ifname,
951                                   const uint16_t port,
952                                   const uint8_t family) {
953     // Search for specified interface among detected interfaces.
954     for (IfacePtr iface : ifaces_) {
955         if ((iface->getFullName() != ifname) &&
956             (iface->getName() != ifname)) {
957             continue;
958         }
959 
960         // Interface is now detected. Search for address on interface
961         // that matches address family (v6 or v4).
962         Iface::AddressCollection addrs = iface->getAddresses();
963         Iface::AddressCollection::iterator addr_it = addrs.begin();
964         while (addr_it != addrs.end()) {
965             if (addr_it->get().getFamily() == family) {
966                 // We have interface and address so let's open socket.
967                 // This may cause isc::Unexpected exception.
968                 return (openSocket(iface->getName(), *addr_it, port, false));
969             }
970             ++addr_it;
971         }
972         // If we are at the end of address collection it means that we found
973         // interface but there is no address for family specified.
974         if (addr_it == addrs.end()) {
975             // Stringify the family value to append it to exception string.
976             std::string family_name("AF_INET");
977             if (family == AF_INET6) {
978                 family_name = "AF_INET6";
979             }
980             // We did not find address on the interface.
981             isc_throw(SocketConfigError, "There is no address for interface: "
982                       << ifname << ", port: " << port << ", address "
983                       " family: " << family_name);
984         }
985     }
986     // If we got here it means that we had not found the specified interface.
987     // Otherwise we would have returned from previous exist points.
988     isc_throw(BadValue, "There is no " << ifname << " interface present.");
989 }
990 
openSocketFromAddress(const IOAddress & addr,const uint16_t port)991 int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
992                                     const uint16_t port) {
993     // Search through detected interfaces and addresses to match
994     // local address we got.
995     for (IfacePtr iface : ifaces_) {
996         for (Iface::Address a : iface->getAddresses()) {
997 
998             // Local address must match one of the addresses
999             // on detected interfaces. If it does, we have
1000             // address and interface detected so we can open
1001             // socket.
1002             if (a.get() == addr) {
1003                 // Open socket using local interface, address and port.
1004                 // This may cause isc::Unexpected exception.
1005                 return (openSocket(iface->getName(), a, port, false));
1006             }
1007         }
1008     }
1009     // If we got here it means that we did not find specified address
1010     // on any available interface.
1011     isc_throw(BadValue, "There is no such address " << addr);
1012 }
1013 
openSocketFromRemoteAddress(const IOAddress & remote_addr,const uint16_t port)1014 int IfaceMgr::openSocketFromRemoteAddress(const IOAddress& remote_addr,
1015                                           const uint16_t port) {
1016     try {
1017         // Get local address to be used to connect to remote location.
1018         IOAddress local_address(getLocalAddress(remote_addr, port));
1019         return openSocketFromAddress(local_address, port);
1020     } catch (const Exception& e) {
1021         isc_throw(SocketConfigError, e.what());
1022     }
1023 }
1024 
1025 isc::asiolink::IOAddress
getLocalAddress(const IOAddress & remote_addr,const uint16_t port)1026 IfaceMgr::getLocalAddress(const IOAddress& remote_addr, const uint16_t port) {
1027     // Create remote endpoint, we will be connecting to it.
1028     boost::scoped_ptr<const UDPEndpoint>
1029         remote_endpoint(static_cast<const UDPEndpoint*>
1030                         (UDPEndpoint::create(IPPROTO_UDP, remote_addr, port)));
1031     if (!remote_endpoint) {
1032         isc_throw(Unexpected, "Unable to create remote endpoint");
1033     }
1034 
1035     // Create socket that will be used to connect to remote endpoint.
1036     boost::asio::io_service io_service;
1037     boost::asio::ip::udp::socket sock(io_service);
1038 
1039     boost::system::error_code err_code;
1040     // If remote address is broadcast address we have to
1041     // allow this on the socket.
1042     if (remote_addr.isV4() &&
1043         (remote_addr == IOAddress(DHCP_IPV4_BROADCAST_ADDRESS))) {
1044         // Socket has to be open prior to setting the broadcast
1045         // option. Otherwise set_option will complain about
1046         // bad file descriptor.
1047 
1048         // @todo: We don't specify interface in any way here. 255.255.255.255
1049         // We can very easily end up with a socket working on a different
1050         // interface.
1051 
1052         // zero out the errno to be safe
1053         errno = 0;
1054 
1055         sock.open(boost::asio::ip::udp::v4(), err_code);
1056         if (err_code) {
1057             const char* errstr = strerror(errno);
1058             isc_throw(Unexpected, "failed to open UDPv4 socket, reason:"
1059                       << errstr);
1060         }
1061         sock.set_option(boost::asio::socket_base::broadcast(true), err_code);
1062         if (err_code) {
1063             sock.close();
1064             isc_throw(Unexpected, "failed to enable broadcast on the socket");
1065         }
1066     }
1067 
1068     // Try to connect to remote endpoint and check if attempt is successful.
1069     sock.connect(remote_endpoint->getASIOEndpoint(), err_code);
1070     if (err_code) {
1071         sock.close();
1072         isc_throw(Unexpected, "failed to connect to remote endpoint.");
1073     }
1074 
1075     // Once we are connected socket object holds local endpoint.
1076     boost::asio::ip::udp::socket::endpoint_type local_endpoint =
1077         sock.local_endpoint();
1078     boost::asio::ip::address local_address(local_endpoint.address());
1079 
1080     // Close the socket.
1081     sock.close();
1082 
1083     // Return address of local endpoint.
1084     return IOAddress(local_address);
1085 }
1086 
1087 int
openSocket4(Iface & iface,const IOAddress & addr,const uint16_t port,const bool receive_bcast,const bool send_bcast)1088 IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr,
1089                           const uint16_t port, const bool receive_bcast,
1090                           const bool send_bcast) {
1091 
1092     // Assuming that packet filter is not null, because its modifier checks it.
1093     SocketInfo info = packet_filter_->openSocket(iface, addr, port,
1094                                                  receive_bcast, send_bcast);
1095     iface.addSocket(info);
1096 
1097     return (info.sockfd_);
1098 }
1099 
1100 bool
send(const Pkt6Ptr & pkt)1101 IfaceMgr::send(const Pkt6Ptr& pkt) {
1102     IfacePtr iface = getIface(pkt);
1103     if (!iface) {
1104         isc_throw(BadValue, "Unable to send DHCPv6 message. Invalid interface ("
1105                   << pkt->getIface() << ") specified.");
1106     }
1107 
1108     // Assuming that packet filter is not null, because its modifier checks it.
1109     // The packet filter returns an int but in fact it either returns 0 or throws.
1110     return (packet_filter6_->send(*iface, getSocket(pkt), pkt) == 0);
1111 }
1112 
1113 bool
send(const Pkt4Ptr & pkt)1114 IfaceMgr::send(const Pkt4Ptr& pkt) {
1115     IfacePtr iface = getIface(pkt);
1116     if (!iface) {
1117         isc_throw(BadValue, "Unable to send DHCPv4 message. Invalid interface ("
1118                   << pkt->getIface() << ") specified.");
1119     }
1120 
1121     // Assuming that packet filter is not null, because its modifier checks it.
1122     // The packet filter returns an int but in fact it either returns 0 or throws.
1123     return (packet_filter_->send(*iface, getSocket(pkt).sockfd_, pkt) == 0);
1124 }
1125 
receive4(uint32_t timeout_sec,uint32_t timeout_usec)1126 Pkt4Ptr IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
1127     if (isDHCPReceiverRunning()) {
1128         return (receive4Indirect(timeout_sec, timeout_usec));
1129     }
1130 
1131     return (receive4Direct(timeout_sec, timeout_usec));
1132 }
1133 
receive4Indirect(uint32_t timeout_sec,uint32_t timeout_usec)1134 Pkt4Ptr IfaceMgr::receive4Indirect(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
1135     // Sanity check for microsecond timeout.
1136     if (timeout_usec >= 1000000) {
1137         isc_throw(BadValue, "fractional timeout must be shorter than"
1138                   " one million microseconds");
1139     }
1140 
1141     fd_set sockets;
1142     int maxfd = 0;
1143 
1144     FD_ZERO(&sockets);
1145 
1146     // if there are any callbacks for external sockets registered...
1147     {
1148         std::lock_guard<std::mutex> lock(callbacks_mutex_);
1149         if (!callbacks_.empty()) {
1150             for (SocketCallbackInfo s : callbacks_) {
1151                 // Add this socket to listening set
1152                 addFDtoSet(s.socket_, maxfd, &sockets);
1153             }
1154         }
1155     }
1156 
1157     // Add Receiver ready watch socket
1158     addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::READY), maxfd, &sockets);
1159 
1160     // Add Receiver error watch socket
1161     addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::ERROR), maxfd, &sockets);
1162 
1163     // Set timeout for our next select() call.  If there are
1164     // no DHCP packets to read, then we'll wait for a finite
1165     // amount of time for an IO event.  Otherwise, we'll
1166     // poll (timeout = 0 secs).  We need to poll, even if
1167     // DHCP packets are waiting so we don't starve external
1168     // sockets under heavy DHCP load.
1169     struct timeval select_timeout;
1170     if (getPacketQueue4()->empty()) {
1171         select_timeout.tv_sec = timeout_sec;
1172         select_timeout.tv_usec = timeout_usec;
1173     } else {
1174         select_timeout.tv_sec = 0;
1175         select_timeout.tv_usec = 0;
1176     }
1177 
1178     // zero out the errno to be safe
1179     errno = 0;
1180 
1181     int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1182 
1183     if ((result == 0) && getPacketQueue4()->empty()) {
1184         // nothing received and timeout has been reached
1185         return (Pkt4Ptr());
1186     } else if (result < 0) {
1187         // In most cases we would like to know whether select() returned
1188         // an error because of a signal being received  or for some other
1189         // reason. This is because DHCP servers use signals to trigger
1190         // certain actions, like reconfiguration or graceful shutdown.
1191         // By catching a dedicated exception the caller will know if the
1192         // error returned by the function is due to the reception of the
1193         // signal or for some other reason.
1194         if (errno == EINTR) {
1195             isc_throw(SignalInterruptOnSelect, strerror(errno));
1196         } else if (errno == EBADF) {
1197             int cnt = purgeBadSockets();
1198             isc_throw(SocketReadError,
1199                       "SELECT interrupted by one invalid sockets, purged "
1200                        << cnt << " socket descriptors");
1201         } else {
1202             isc_throw(SocketReadError, strerror(errno));
1203         }
1204     }
1205 
1206     // We only check external sockets if select detected an event.
1207     if (result > 0) {
1208         // Check for receiver thread read errors.
1209         if (dhcp_receiver_->isReady(WatchedThread::ERROR)) {
1210             string msg = dhcp_receiver_->getLastError();
1211             dhcp_receiver_->clearReady(WatchedThread::ERROR);
1212             isc_throw(SocketReadError, msg);
1213         }
1214 
1215         // Let's find out which external socket has the data
1216         SocketCallbackInfo ex_sock;
1217         bool found = false;
1218         {
1219             std::lock_guard<std::mutex> lock(callbacks_mutex_);
1220             for (SocketCallbackInfo s : callbacks_) {
1221                 if (!FD_ISSET(s.socket_, &sockets)) {
1222                     continue;
1223                 }
1224                 found = true;
1225 
1226                 // something received over external socket
1227                 if (s.callback_) {
1228                     // Note the external socket to call its callback without
1229                     // the lock taken so it can be deleted.
1230                     ex_sock = s;
1231                     break;
1232                 }
1233             }
1234         }
1235 
1236         if (ex_sock.callback_) {
1237             // Calling the external socket's callback provides its service
1238             // layer access without integrating any specific features
1239             // in IfaceMgr
1240             ex_sock.callback_(ex_sock.socket_);
1241         }
1242         if (found) {
1243             return (Pkt4Ptr());
1244         }
1245     }
1246 
1247     // If we're here it should only be because there are DHCP packets waiting.
1248     Pkt4Ptr pkt = getPacketQueue4()->dequeuePacket();
1249     if (!pkt) {
1250         dhcp_receiver_->clearReady(WatchedThread::READY);
1251     }
1252 
1253     return (pkt);
1254 }
1255 
receive4Direct(uint32_t timeout_sec,uint32_t timeout_usec)1256 Pkt4Ptr IfaceMgr::receive4Direct(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
1257     // Sanity check for microsecond timeout.
1258     if (timeout_usec >= 1000000) {
1259         isc_throw(BadValue, "fractional timeout must be shorter than"
1260                   " one million microseconds");
1261     }
1262     boost::scoped_ptr<SocketInfo> candidate;
1263     fd_set sockets;
1264     int maxfd = 0;
1265 
1266     FD_ZERO(&sockets);
1267 
1268     /// @todo: marginal performance optimization. We could create the set once
1269     /// and then use its copy for select(). Please note that select() modifies
1270     /// provided set to indicated which sockets have something to read.
1271     for (IfacePtr iface : ifaces_) {
1272         for (SocketInfo s : iface->getSockets()) {
1273             // Only deal with IPv4 addresses.
1274             if (s.addr_.isV4()) {
1275                 // Add this socket to listening set
1276                 addFDtoSet(s.sockfd_, maxfd, &sockets);
1277             }
1278         }
1279     }
1280 
1281     // if there are any callbacks for external sockets registered...
1282     {
1283         std::lock_guard<std::mutex> lock(callbacks_mutex_);
1284         if (!callbacks_.empty()) {
1285             for (SocketCallbackInfo s : callbacks_) {
1286                 // Add this socket to listening set
1287                 addFDtoSet(s.socket_, maxfd, &sockets);
1288             }
1289         }
1290     }
1291 
1292     struct timeval select_timeout;
1293     select_timeout.tv_sec = timeout_sec;
1294     select_timeout.tv_usec = timeout_usec;
1295 
1296     // zero out the errno to be safe
1297     errno = 0;
1298 
1299     int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1300 
1301     if (result == 0) {
1302         // nothing received and timeout has been reached
1303         return (Pkt4Ptr()); // null
1304 
1305     } else if (result < 0) {
1306         // In most cases we would like to know whether select() returned
1307         // an error because of a signal being received  or for some other
1308         // reason. This is because DHCP servers use signals to trigger
1309         // certain actions, like reconfiguration or graceful shutdown.
1310         // By catching a dedicated exception the caller will know if the
1311         // error returned by the function is due to the reception of the
1312         // signal or for some other reason.
1313         if (errno == EINTR) {
1314             isc_throw(SignalInterruptOnSelect, strerror(errno));
1315         } else if (errno == EBADF) {
1316             int cnt = purgeBadSockets();
1317             isc_throw(SocketReadError,
1318                       "SELECT interrupted by one invalid sockets, purged "
1319                        << cnt << " socket descriptors");
1320         } else {
1321             isc_throw(SocketReadError, strerror(errno));
1322         }
1323     }
1324 
1325     // Let's find out which socket has the data
1326     SocketCallbackInfo ex_sock;
1327     bool found = false;
1328     {
1329         std::lock_guard<std::mutex> lock(callbacks_mutex_);
1330         for (SocketCallbackInfo s : callbacks_) {
1331             if (!FD_ISSET(s.socket_, &sockets)) {
1332                 continue;
1333             }
1334             found = true;
1335 
1336             // something received over external socket
1337             if (s.callback_) {
1338                 // Note the external socket to call its callback without
1339                 // the lock taken so it can be deleted.
1340                 ex_sock = s;
1341                 break;
1342             }
1343         }
1344     }
1345 
1346     if (ex_sock.callback_) {
1347         // Calling the external socket's callback provides its service
1348         // layer access without integrating any specific features
1349         // in IfaceMgr
1350         ex_sock.callback_(ex_sock.socket_);
1351     }
1352     if (found) {
1353         return (Pkt4Ptr());
1354     }
1355 
1356     // Let's find out which interface/socket has the data
1357     IfacePtr recv_if;
1358     for (IfacePtr iface : ifaces_) {
1359         for (SocketInfo s : iface->getSockets()) {
1360             if (FD_ISSET(s.sockfd_, &sockets)) {
1361                 candidate.reset(new SocketInfo(s));
1362                 break;
1363             }
1364         }
1365         if (candidate) {
1366             recv_if = iface;
1367             break;
1368         }
1369     }
1370 
1371     if (!candidate || !recv_if) {
1372         isc_throw(SocketReadError, "received data over unknown socket");
1373     }
1374 
1375     // Now we have a socket, let's get some data from it!
1376     // Assuming that packet filter is not null, because its modifier checks it.
1377     return (packet_filter_->receive(*recv_if, *candidate));
1378 }
1379 
1380 Pkt6Ptr
receive6(uint32_t timeout_sec,uint32_t timeout_usec)1381 IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
1382     if (isDHCPReceiverRunning()) {
1383         return (receive6Indirect(timeout_sec, timeout_usec));
1384     }
1385 
1386     return (receive6Direct(timeout_sec, timeout_usec));
1387 }
1388 
1389 void
addFDtoSet(int fd,int & maxfd,fd_set * sockets)1390 IfaceMgr::addFDtoSet(int fd, int& maxfd, fd_set* sockets) {
1391     if (!sockets) {
1392         isc_throw(BadValue, "addFDtoSet: sockets can't be null");
1393     }
1394 
1395     FD_SET(fd, sockets);
1396     if (maxfd < fd) {
1397         maxfd = fd;
1398     }
1399 }
1400 
1401 Pkt6Ptr
receive6Direct(uint32_t timeout_sec,uint32_t timeout_usec)1402 IfaceMgr::receive6Direct(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */ ) {
1403     // Sanity check for microsecond timeout.
1404     if (timeout_usec >= 1000000) {
1405         isc_throw(BadValue, "fractional timeout must be shorter than"
1406                   " one million microseconds");
1407     }
1408 
1409     boost::scoped_ptr<SocketInfo> candidate;
1410     fd_set sockets;
1411     int maxfd = 0;
1412 
1413     FD_ZERO(&sockets);
1414 
1415     /// @todo: marginal performance optimization. We could create the set once
1416     /// and then use its copy for select(). Please note that select() modifies
1417     /// provided set to indicated which sockets have something to read.
1418     for (IfacePtr iface : ifaces_) {
1419         for (SocketInfo s : iface->getSockets()) {
1420             // Only deal with IPv6 addresses.
1421             if (s.addr_.isV6()) {
1422                 // Add this socket to listening set
1423                 addFDtoSet(s.sockfd_, maxfd, &sockets);
1424             }
1425         }
1426     }
1427 
1428     // if there are any callbacks for external sockets registered...
1429     {
1430         std::lock_guard<std::mutex> lock(callbacks_mutex_);
1431         if (!callbacks_.empty()) {
1432             for (SocketCallbackInfo s : callbacks_) {
1433                 // Add this socket to listening set
1434                 addFDtoSet(s.socket_, maxfd, &sockets);
1435             }
1436         }
1437     }
1438 
1439     struct timeval select_timeout;
1440     select_timeout.tv_sec = timeout_sec;
1441     select_timeout.tv_usec = timeout_usec;
1442 
1443     // zero out the errno to be safe
1444     errno = 0;
1445 
1446     int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1447 
1448     if (result == 0) {
1449         // nothing received and timeout has been reached
1450         return (Pkt6Ptr()); // null
1451 
1452     } else if (result < 0) {
1453         // In most cases we would like to know whether select() returned
1454         // an error because of a signal being received  or for some other
1455         // reason. This is because DHCP servers use signals to trigger
1456         // certain actions, like reconfiguration or graceful shutdown.
1457         // By catching a dedicated exception the caller will know if the
1458         // error returned by the function is due to the reception of the
1459         // signal or for some other reason.
1460         if (errno == EINTR) {
1461             isc_throw(SignalInterruptOnSelect, strerror(errno));
1462         } else if (errno == EBADF) {
1463             int cnt = purgeBadSockets();
1464             isc_throw(SocketReadError,
1465                       "SELECT interrupted by one invalid sockets, purged "
1466                        << cnt << " socket descriptors");
1467         } else {
1468             isc_throw(SocketReadError, strerror(errno));
1469         }
1470     }
1471 
1472     // Let's find out which socket has the data
1473     SocketCallbackInfo ex_sock;
1474     bool found = false;
1475     {
1476         std::lock_guard<std::mutex> lock(callbacks_mutex_);
1477         for (SocketCallbackInfo s : callbacks_) {
1478             if (!FD_ISSET(s.socket_, &sockets)) {
1479                 continue;
1480             }
1481             found = true;
1482 
1483             // something received over external socket
1484             if (s.callback_) {
1485                 // Note the external socket to call its callback without
1486                 // the lock taken so it can be deleted.
1487                 ex_sock = s;
1488                 break;
1489             }
1490         }
1491     }
1492 
1493     if (ex_sock.callback_) {
1494         // Calling the external socket's callback provides its service
1495         // layer access without integrating any specific features
1496         // in IfaceMgr
1497         ex_sock.callback_(ex_sock.socket_);
1498     }
1499     if (found) {
1500         return (Pkt6Ptr());
1501     }
1502 
1503     // Let's find out which interface/socket has the data
1504     for (IfacePtr iface : ifaces_) {
1505         for (SocketInfo s : iface->getSockets()) {
1506             if (FD_ISSET(s.sockfd_, &sockets)) {
1507                 candidate.reset(new SocketInfo(s));
1508                 break;
1509             }
1510         }
1511         if (candidate) {
1512             break;
1513         }
1514     }
1515 
1516     if (!candidate) {
1517         isc_throw(SocketReadError, "received data over unknown socket");
1518     }
1519     // Assuming that packet filter is not null, because its modifier checks it.
1520     return (packet_filter6_->receive(*candidate));
1521 }
1522 
1523 Pkt6Ptr
receive6Indirect(uint32_t timeout_sec,uint32_t timeout_usec)1524 IfaceMgr::receive6Indirect(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */ ) {
1525     // Sanity check for microsecond timeout.
1526     if (timeout_usec >= 1000000) {
1527         isc_throw(BadValue, "fractional timeout must be shorter than"
1528                   " one million microseconds");
1529     }
1530 
1531     fd_set sockets;
1532     int maxfd = 0;
1533 
1534     FD_ZERO(&sockets);
1535 
1536     // if there are any callbacks for external sockets registered...
1537     {
1538         std::lock_guard<std::mutex> lock(callbacks_mutex_);
1539         if (!callbacks_.empty()) {
1540             for (SocketCallbackInfo s : callbacks_) {
1541                 // Add this socket to listening set
1542                 addFDtoSet(s.socket_, maxfd, &sockets);
1543             }
1544         }
1545     }
1546 
1547     // Add Receiver ready watch socket
1548     addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::READY), maxfd, &sockets);
1549 
1550     // Add Receiver error watch socket
1551     addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::ERROR), maxfd, &sockets);
1552 
1553     // Set timeout for our next select() call.  If there are
1554     // no DHCP packets to read, then we'll wait for a finite
1555     // amount of time for an IO event.  Otherwise, we'll
1556     // poll (timeout = 0 secs).  We need to poll, even if
1557     // DHCP packets are waiting so we don't starve external
1558     // sockets under heavy DHCP load.
1559     struct timeval select_timeout;
1560     if (getPacketQueue6()->empty()) {
1561         select_timeout.tv_sec = timeout_sec;
1562         select_timeout.tv_usec = timeout_usec;
1563     } else {
1564         select_timeout.tv_sec = 0;
1565         select_timeout.tv_usec = 0;
1566     }
1567 
1568     // zero out the errno to be safe
1569     errno = 0;
1570 
1571     int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1572 
1573     if ((result == 0) && getPacketQueue6()->empty()) {
1574         // nothing received and timeout has been reached
1575         return (Pkt6Ptr());
1576     } else if (result < 0) {
1577         // In most cases we would like to know whether select() returned
1578         // an error because of a signal being received  or for some other
1579         // reason. This is because DHCP servers use signals to trigger
1580         // certain actions, like reconfiguration or graceful shutdown.
1581         // By catching a dedicated exception the caller will know if the
1582         // error returned by the function is due to the reception of the
1583         // signal or for some other reason.
1584         if (errno == EINTR) {
1585             isc_throw(SignalInterruptOnSelect, strerror(errno));
1586         } else if (errno == EBADF) {
1587             int cnt = purgeBadSockets();
1588             isc_throw(SocketReadError,
1589                       "SELECT interrupted by one invalid sockets, purged "
1590                        << cnt << " socket descriptors");
1591         } else {
1592             isc_throw(SocketReadError, strerror(errno));
1593         }
1594     }
1595 
1596     // We only check external sockets if select detected an event.
1597     if (result > 0) {
1598         // Check for receiver thread read errors.
1599         if (dhcp_receiver_->isReady(WatchedThread::ERROR)) {
1600             string msg = dhcp_receiver_->getLastError();
1601             dhcp_receiver_->clearReady(WatchedThread::ERROR);
1602             isc_throw(SocketReadError, msg);
1603         }
1604 
1605         // Let's find out which external socket has the data
1606         SocketCallbackInfo ex_sock;
1607         bool found = false;
1608         {
1609             std::lock_guard<std::mutex> lock(callbacks_mutex_);
1610             for (SocketCallbackInfo s : callbacks_) {
1611                 if (!FD_ISSET(s.socket_, &sockets)) {
1612                     continue;
1613                 }
1614                 found = true;
1615 
1616                 // something received over external socket
1617                 if (s.callback_) {
1618                     // Note the external socket to call its callback without
1619                     // the lock taken so it can be deleted.
1620                     ex_sock = s;
1621                     break;
1622                 }
1623             }
1624         }
1625 
1626         if (ex_sock.callback_) {
1627             // Calling the external socket's callback provides its service
1628             // layer access without integrating any specific features
1629             // in IfaceMgr
1630             ex_sock.callback_(ex_sock.socket_);
1631         }
1632         if (found) {
1633             return (Pkt6Ptr());
1634         }
1635     }
1636 
1637     // If we're here it should only be because there are DHCP packets waiting.
1638     Pkt6Ptr pkt = getPacketQueue6()->dequeuePacket();
1639     if (!pkt) {
1640         dhcp_receiver_->clearReady(WatchedThread::READY);
1641     }
1642 
1643     return (pkt);
1644 }
1645 
1646 void
receiveDHCP4Packets()1647 IfaceMgr::receiveDHCP4Packets() {
1648     fd_set sockets;
1649     int maxfd = 0;
1650 
1651     FD_ZERO(&sockets);
1652 
1653     // Add terminate watch socket.
1654     addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE), maxfd, &sockets);
1655 
1656     // Add Interface sockets.
1657     for (IfacePtr iface : ifaces_) {
1658         for (SocketInfo s : iface->getSockets()) {
1659             // Only deal with IPv4 addresses.
1660             if (s.addr_.isV4()) {
1661                 // Add this socket to listening set.
1662                 addFDtoSet(s.sockfd_, maxfd, &sockets);
1663             }
1664         }
1665     }
1666 
1667     for (;;) {
1668         // Check the watch socket.
1669         if (dhcp_receiver_->shouldTerminate()) {
1670             return;
1671         }
1672 
1673         fd_set rd_set;
1674         FD_COPY(&sockets, &rd_set);
1675 
1676         // zero out the errno to be safe.
1677         errno = 0;
1678 
1679         // Select with null timeouts to wait indefinitely an event
1680         int result = select(maxfd + 1, &rd_set, 0, 0, 0);
1681 
1682         // Re-check the watch socket.
1683         if (dhcp_receiver_->shouldTerminate()) {
1684             return;
1685         }
1686 
1687         if (result == 0) {
1688             // nothing received?
1689             continue;
1690 
1691         } else if (result < 0) {
1692             // This thread should not get signals?
1693             if (errno != EINTR) {
1694                 // Signal the error to receive4.
1695                 dhcp_receiver_->setError(strerror(errno));
1696                 // We need to sleep in case of the error condition to
1697                 // prevent the thread from tight looping when result
1698                 // gets negative.
1699                 sleep(1);
1700             }
1701             continue;
1702         }
1703 
1704         // Let's find out which interface/socket has data.
1705         for (IfacePtr iface : ifaces_) {
1706             for (SocketInfo s : iface->getSockets()) {
1707                 if (FD_ISSET(s.sockfd_, &sockets)) {
1708                     receiveDHCP4Packet(*iface, s);
1709                     // Can take time so check one more time the watch socket.
1710                     if (dhcp_receiver_->shouldTerminate()) {
1711                         return;
1712                     }
1713                 }
1714             }
1715         }
1716     }
1717 
1718 }
1719 
1720 void
receiveDHCP6Packets()1721 IfaceMgr::receiveDHCP6Packets() {
1722     fd_set sockets;
1723     int maxfd = 0;
1724 
1725     FD_ZERO(&sockets);
1726 
1727     // Add terminate watch socket.
1728     addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE), maxfd, &sockets);
1729 
1730     // Add Interface sockets.
1731     for (IfacePtr iface : ifaces_) {
1732         for (SocketInfo s : iface->getSockets()) {
1733             // Only deal with IPv6 addresses.
1734             if (s.addr_.isV6()) {
1735                 // Add this socket to listening set.
1736                 addFDtoSet(s.sockfd_ , maxfd, &sockets);
1737             }
1738         }
1739     }
1740 
1741     for (;;) {
1742         // Check the watch socket.
1743         if (dhcp_receiver_->shouldTerminate()) {
1744             return;
1745         }
1746 
1747         fd_set rd_set;
1748         FD_COPY(&sockets, &rd_set);
1749 
1750         // zero out the errno to be safe.
1751         errno = 0;
1752 
1753         // Note we wait until something happen.
1754         int result = select(maxfd + 1, &rd_set, 0, 0, 0);
1755 
1756         // Re-check the watch socket.
1757         if (dhcp_receiver_->shouldTerminate()) {
1758             return;
1759         }
1760 
1761         if (result == 0) {
1762             // nothing received?
1763             continue;
1764         } else if (result < 0) {
1765             // This thread should not get signals?
1766             if (errno != EINTR) {
1767                 // Signal the error to receive6.
1768                 dhcp_receiver_->setError(strerror(errno));
1769                 // We need to sleep in case of the error condition to
1770                 // prevent the thread from tight looping when result
1771                 // gets negative.
1772                 sleep(1);
1773             }
1774             continue;
1775         }
1776 
1777         // Let's find out which interface/socket has data.
1778         for (IfacePtr iface : ifaces_) {
1779             for (SocketInfo s : iface->getSockets()) {
1780                 if (FD_ISSET(s.sockfd_, &sockets)) {
1781                     receiveDHCP6Packet(s);
1782                     // Can take time so check one more time the watch socket.
1783                     if (dhcp_receiver_->shouldTerminate()) {
1784                         return;
1785                     }
1786                 }
1787             }
1788         }
1789     }
1790 }
1791 
1792 void
receiveDHCP4Packet(Iface & iface,const SocketInfo & socket_info)1793 IfaceMgr::receiveDHCP4Packet(Iface& iface, const SocketInfo& socket_info) {
1794     int len;
1795 
1796     int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1797     if (result < 0) {
1798         // Signal the error to receive4.
1799         dhcp_receiver_->setError(strerror(errno));
1800         return;
1801     }
1802     if (len == 0) {
1803         // Nothing to read.
1804         return;
1805     }
1806 
1807     Pkt4Ptr pkt;
1808 
1809     try {
1810         pkt = packet_filter_->receive(iface, socket_info);
1811     } catch (const std::exception& ex) {
1812         dhcp_receiver_->setError(strerror(errno));
1813     } catch (...) {
1814         dhcp_receiver_->setError("packet filter receive() failed");
1815     }
1816 
1817     if (pkt) {
1818         getPacketQueue4()->enqueuePacket(pkt, socket_info);
1819         dhcp_receiver_->markReady(WatchedThread::READY);
1820     }
1821 }
1822 
1823 void
receiveDHCP6Packet(const SocketInfo & socket_info)1824 IfaceMgr::receiveDHCP6Packet(const SocketInfo& socket_info) {
1825     int len;
1826 
1827     int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1828     if (result < 0) {
1829         // Signal the error to receive6.
1830         dhcp_receiver_->setError(strerror(errno));
1831         return;
1832     }
1833     if (len == 0) {
1834         // Nothing to read.
1835         return;
1836     }
1837 
1838     Pkt6Ptr pkt;
1839 
1840     try {
1841         pkt = packet_filter6_->receive(socket_info);
1842     } catch (const std::exception& ex) {
1843         dhcp_receiver_->setError(ex.what());
1844     } catch (...) {
1845         dhcp_receiver_->setError("packet filter receive() failed");
1846     }
1847 
1848     if (pkt) {
1849         getPacketQueue6()->enqueuePacket(pkt, socket_info);
1850         dhcp_receiver_->markReady(WatchedThread::READY);
1851     }
1852 }
1853 
1854 uint16_t
getSocket(const isc::dhcp::Pkt6Ptr & pkt)1855 IfaceMgr::getSocket(const isc::dhcp::Pkt6Ptr& pkt) {
1856     IfacePtr iface = getIface(pkt);
1857     if (!iface) {
1858         isc_throw(IfaceNotFound, "Tried to find socket for non-existent interface");
1859     }
1860 
1861 
1862     const Iface::SocketCollection& socket_collection = iface->getSockets();
1863 
1864     Iface::SocketCollection::const_iterator candidate = socket_collection.end();
1865 
1866     Iface::SocketCollection::const_iterator s;
1867     for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
1868 
1869         // We should not merge those conditions for debugging reasons.
1870 
1871         // V4 sockets are useless for sending v6 packets.
1872         if (s->family_ != AF_INET6) {
1873             continue;
1874         }
1875 
1876         // Sockets bound to multicast address are useless for sending anything.
1877         if (s->addr_.isV6Multicast()) {
1878             continue;
1879         }
1880 
1881         if (s->addr_ == pkt->getLocalAddr()) {
1882             // This socket is bound to the source address. This is perfect
1883             // match, no need to look any further.
1884             return (s->sockfd_);
1885         }
1886 
1887         // If we don't have any other candidate, this one will do
1888         if (candidate == socket_collection.end()) {
1889             candidate = s;
1890         } else {
1891             // If we want to send something to link-local and the socket is
1892             // bound to link-local or we want to send to global and the socket
1893             // is bound to global, then use it as candidate
1894             if ( (pkt->getRemoteAddr().isV6LinkLocal() &&
1895                 s->addr_.isV6LinkLocal()) ||
1896                  (!pkt->getRemoteAddr().isV6LinkLocal() &&
1897                   !s->addr_.isV6LinkLocal()) ) {
1898                 candidate = s;
1899             }
1900         }
1901     }
1902 
1903     if (candidate != socket_collection.end()) {
1904         return (candidate->sockfd_);
1905     }
1906 
1907     isc_throw(SocketNotFound, "Interface " << iface->getFullName()
1908               << " does not have any suitable IPv6 sockets open.");
1909 }
1910 
1911 SocketInfo
getSocket(const isc::dhcp::Pkt4Ptr & pkt)1912 IfaceMgr::getSocket(const isc::dhcp::Pkt4Ptr& pkt) {
1913     IfacePtr iface = getIface(pkt);
1914     if (!iface) {
1915         isc_throw(IfaceNotFound, "Tried to find socket for non-existent interface");
1916     }
1917 
1918     const Iface::SocketCollection& socket_collection = iface->getSockets();
1919     // A candidate being an end of the iterator marks that it is a beginning of
1920     // the socket search and that the candidate needs to be set to the first
1921     // socket found.
1922     Iface::SocketCollection::const_iterator candidate = socket_collection.end();
1923     Iface::SocketCollection::const_iterator s;
1924     for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
1925         if (s->family_ == AF_INET) {
1926             if (s->addr_ == pkt->getLocalAddr()) {
1927                 return (*s);
1928             }
1929 
1930             if (candidate == socket_collection.end()) {
1931                 candidate = s;
1932             }
1933         }
1934     }
1935 
1936     if (candidate == socket_collection.end()) {
1937         isc_throw(SocketNotFound, "Interface " << iface->getFullName()
1938                   << " does not have any suitable IPv4 sockets open.");
1939     }
1940 
1941     return (*candidate);
1942 }
1943 
1944 bool
configureDHCPPacketQueue(uint16_t family,data::ConstElementPtr queue_control)1945 IfaceMgr::configureDHCPPacketQueue(uint16_t family, data::ConstElementPtr queue_control) {
1946     if (isDHCPReceiverRunning()) {
1947         isc_throw(InvalidOperation, "Cannot reconfigure queueing"
1948                                     " while DHCP receiver thread is running");
1949     }
1950 
1951     bool enable_queue = false;
1952     if (queue_control) {
1953         try {
1954             enable_queue = data::SimpleParser::getBoolean(queue_control, "enable-queue");
1955         } catch (...) {
1956             // @todo - for now swallow not found errors.
1957             // if not present we assume default
1958         }
1959     }
1960 
1961     if (enable_queue) {
1962         // Try to create the queue as configured.
1963         if (family == AF_INET) {
1964             packet_queue_mgr4_->createPacketQueue(queue_control);
1965         } else {
1966             packet_queue_mgr6_->createPacketQueue(queue_control);
1967         }
1968     } else {
1969         // Destroy the current queue (if one), this inherently disables threading.
1970         if (family == AF_INET) {
1971             packet_queue_mgr4_->destroyPacketQueue();
1972         } else {
1973             packet_queue_mgr6_->destroyPacketQueue();
1974         }
1975     }
1976 
1977     return(enable_queue);
1978 }
1979 
1980 } // end of namespace isc::dhcp
1981 } // end of namespace isc
1982