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