Kea  2.3.2-git
iface_mgr.cc
Go to the documentation of this file.
1 // Copyright (C) 2011-2022 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(uint32_t 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(uint32_t ifindex, bool need_lock) {
847  if (need_lock) {
848  lock_guard<mutex> lock(mutex_);
849  if (cache_ && (cache_->getIndex() == ifindex)) {
850  return (cache_);
851  }
852  } else {
853  if (cache_ && (cache_->getIndex() == ifindex)) {
854  return (cache_);
855  }
856  }
857  const auto& idx = ifaces_container_.get<1>();
858  auto it = idx.find(ifindex);
859  if (it == idx.end()) {
860  return (IfacePtr()); // not found
861  }
862  if (need_lock) {
863  lock_guard<mutex> lock(mutex_);
864  cache_ = *it;
865  return (cache_);
866  } else {
867  lock_guard<mutex> lock(mutex_);
868  cache_ = *it;
869  return (cache_);
870  }
871 }
872 
873 IfacePtr
874 IfaceCollection::getIfaceInternal(const std::string& ifname, bool need_lock) {
875  if (need_lock) {
876  lock_guard<mutex> lock(mutex_);
877  if (cache_ && (cache_->getName() == ifname)) {
878  return (cache_);
879  }
880  } else {
881  if (cache_ && (cache_->getName() == ifname)) {
882  return (cache_);
883  }
884  }
885  const auto& idx = ifaces_container_.get<2>();
886  auto it = idx.find(ifname);
887  if (it == idx.end()) {
888  return (IfacePtr()); // not found
889  }
890  if (need_lock) {
891  lock_guard<mutex> lock(mutex_);
892  cache_ = *it;
893  return (cache_);
894  } else {
895  lock_guard<mutex> lock(mutex_);
896  cache_ = *it;
897  return (cache_);
898  }
899 }
900 
901 IfacePtr
902 IfaceMgr::getIface(int ifindex) {
903  if ((ifindex < 0) || (ifindex > std::numeric_limits<int32_t>::max())) {
904  return (IfacePtr()); // out of range
905  }
906  return (ifaces_.getIface(ifindex));
907 }
908 
909 IfacePtr
910 IfaceMgr::getIface(const std::string& ifname) {
911  if (ifname.empty()) {
912  return (IfacePtr()); // empty
913  }
914  return (ifaces_.getIface(ifname));
915 }
916 
917 IfacePtr
919  if (pkt->indexSet()) {
920  return (getIface(pkt->getIndex()));
921  } else {
922  return (getIface(pkt->getIface()));
923  }
924 }
925 
926 void
928  ifaces_.clear();
929 }
930 
931 void
933  bound_address_.clear();
934 }
935 
936 void
938  for (IfacePtr iface : ifaces_) {
939  for (SocketInfo sock : iface->getSockets()) {
940  const IOAddress& addr = sock.addr_;
941  if (!addr.isV4()) {
942  continue;
943  }
944  if (bound_address_.count(addr.toUint32()) == 0) {
945  bound_address_.insert(addr);
946  }
947  }
948  }
949 }
950 
951 void
953  for (IfacePtr iface : ifaces_) {
954  iface->clearUnicasts();
955  }
956 }
957 
958 int IfaceMgr::openSocket(const std::string& ifname, const IOAddress& addr,
959  const uint16_t port, const bool receive_bcast,
960  const bool send_bcast) {
961  IfacePtr iface = getIface(ifname);
962  if (!iface) {
963  isc_throw(BadValue, "There is no " << ifname << " interface present.");
964  }
965  if (addr.isV4()) {
966  return openSocket4(*iface, addr, port, receive_bcast, send_bcast);
967 
968  } else if (addr.isV6()) {
969  return openSocket6(*iface, addr, port, receive_bcast);
970 
971  } else {
972  isc_throw(BadValue, "Failed to detect family of address: "
973  << addr);
974  }
975 }
976 
977 int IfaceMgr::openSocketFromIface(const std::string& ifname,
978  const uint16_t port,
979  const uint8_t family) {
980  // Search for specified interface among detected interfaces.
981  for (IfacePtr iface : ifaces_) {
982  if ((iface->getFullName() != ifname) &&
983  (iface->getName() != ifname)) {
984  continue;
985  }
986 
987  // Interface is now detected. Search for address on interface
988  // that matches address family (v6 or v4).
989  Iface::AddressCollection addrs = iface->getAddresses();
990  Iface::AddressCollection::iterator addr_it = addrs.begin();
991  while (addr_it != addrs.end()) {
992  if (addr_it->get().getFamily() == family) {
993  // We have interface and address so let's open socket.
994  // This may cause isc::Unexpected exception.
995  return (openSocket(iface->getName(), *addr_it, port, false));
996  }
997  ++addr_it;
998  }
999  // If we are at the end of address collection it means that we found
1000  // interface but there is no address for family specified.
1001  if (addr_it == addrs.end()) {
1002  // Stringify the family value to append it to exception string.
1003  std::string family_name("AF_INET");
1004  if (family == AF_INET6) {
1005  family_name = "AF_INET6";
1006  }
1007  // We did not find address on the interface.
1008  isc_throw(SocketConfigError, "There is no address for interface: "
1009  << ifname << ", port: " << port << ", address "
1010  " family: " << family_name);
1011  }
1012  }
1013  // If we got here it means that we had not found the specified interface.
1014  // Otherwise we would have returned from previous exist points.
1015  isc_throw(BadValue, "There is no " << ifname << " interface present.");
1016 }
1017 
1019  const uint16_t port) {
1020  // Search through detected interfaces and addresses to match
1021  // local address we got.
1022  for (IfacePtr iface : ifaces_) {
1023  for (Iface::Address a : iface->getAddresses()) {
1024 
1025  // Local address must match one of the addresses
1026  // on detected interfaces. If it does, we have
1027  // address and interface detected so we can open
1028  // socket.
1029  if (a.get() == addr) {
1030  // Open socket using local interface, address and port.
1031  // This may cause isc::Unexpected exception.
1032  return (openSocket(iface->getName(), a, port, false));
1033  }
1034  }
1035  }
1036  // If we got here it means that we did not find specified address
1037  // on any available interface.
1038  isc_throw(BadValue, "There is no such address " << addr);
1039 }
1040 
1042  const uint16_t port) {
1043  try {
1044  // Get local address to be used to connect to remote location.
1045  IOAddress local_address(getLocalAddress(remote_addr, port));
1046  return openSocketFromAddress(local_address, port);
1047  } catch (const Exception& e) {
1049  }
1050 }
1051 
1053 IfaceMgr::getLocalAddress(const IOAddress& remote_addr, const uint16_t port) {
1054  // Create remote endpoint, we will be connecting to it.
1055  boost::scoped_ptr<const UDPEndpoint>
1056  remote_endpoint(static_cast<const UDPEndpoint*>
1057  (UDPEndpoint::create(IPPROTO_UDP, remote_addr, port)));
1058  if (!remote_endpoint) {
1059  isc_throw(Unexpected, "Unable to create remote endpoint");
1060  }
1061 
1062  // Create socket that will be used to connect to remote endpoint.
1063  boost::asio::io_service io_service;
1064  boost::asio::ip::udp::socket sock(io_service);
1065 
1066  boost::system::error_code err_code;
1067  // If remote address is broadcast address we have to
1068  // allow this on the socket.
1069  if (remote_addr.isV4() &&
1070  (remote_addr == IOAddress(DHCP_IPV4_BROADCAST_ADDRESS))) {
1071  // Socket has to be open prior to setting the broadcast
1072  // option. Otherwise set_option will complain about
1073  // bad file descriptor.
1074 
1075  // @todo: We don't specify interface in any way here. 255.255.255.255
1076  // We can very easily end up with a socket working on a different
1077  // interface.
1078 
1079  // zero out the errno to be safe
1080  errno = 0;
1081 
1082  sock.open(boost::asio::ip::udp::v4(), err_code);
1083  if (err_code) {
1084  const char* errstr = strerror(errno);
1085  isc_throw(Unexpected, "failed to open UDPv4 socket, reason:"
1086  << errstr);
1087  }
1088  sock.set_option(boost::asio::socket_base::broadcast(true), err_code);
1089  if (err_code) {
1090  sock.close();
1091  isc_throw(Unexpected, "failed to enable broadcast on the socket");
1092  }
1093  }
1094 
1095  // Try to connect to remote endpoint and check if attempt is successful.
1096  sock.connect(remote_endpoint->getASIOEndpoint(), err_code);
1097  if (err_code) {
1098  sock.close();
1099  isc_throw(Unexpected, "failed to connect to remote endpoint.");
1100  }
1101 
1102  // Once we are connected socket object holds local endpoint.
1103  boost::asio::ip::udp::socket::endpoint_type local_endpoint =
1104  sock.local_endpoint();
1105  boost::asio::ip::address local_address(local_endpoint.address());
1106 
1107  // Close the socket.
1108  sock.close();
1109 
1110  // Return address of local endpoint.
1111  return IOAddress(local_address);
1112 }
1113 
1114 int
1115 IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, const uint16_t port,
1116  const bool receive_bcast, const bool send_bcast) {
1117  // Assuming that packet filter is not null, because its modifier checks it.
1118  SocketInfo info = packet_filter_->openSocket(iface, addr, port,
1119  receive_bcast, send_bcast);
1120  iface.addSocket(info);
1121 
1122  return (info.sockfd_);
1123 }
1124 
1125 bool
1127  IfacePtr iface = getIface(pkt);
1128  if (!iface) {
1129  isc_throw(BadValue, "Unable to send DHCPv6 message. Invalid interface ("
1130  << pkt->getIface() << ") specified.");
1131  }
1132 
1133  // Assuming that packet filter is not null, because its modifier checks it.
1134  // The packet filter returns an int but in fact it either returns 0 or throws.
1135  return (packet_filter6_->send(*iface, getSocket(pkt), pkt) == 0);
1136 }
1137 
1138 bool
1140  IfacePtr iface = getIface(pkt);
1141  if (!iface) {
1142  isc_throw(BadValue, "Unable to send DHCPv4 message. Invalid interface ("
1143  << pkt->getIface() << ") specified.");
1144  }
1145 
1146  // Assuming that packet filter is not null, because its modifier checks it.
1147  // The packet filter returns an int but in fact it either returns 0 or throws.
1148  return (packet_filter_->send(*iface, getSocket(pkt).sockfd_, pkt) == 0);
1149 }
1150 
1151 Pkt4Ptr IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
1152  if (isDHCPReceiverRunning()) {
1153  return (receive4Indirect(timeout_sec, timeout_usec));
1154  }
1155 
1156  return (receive4Direct(timeout_sec, timeout_usec));
1157 }
1158 
1159 Pkt4Ptr IfaceMgr::receive4Indirect(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
1160  // Sanity check for microsecond timeout.
1161  if (timeout_usec >= 1000000) {
1162  isc_throw(BadValue, "fractional timeout must be shorter than"
1163  " one million microseconds");
1164  }
1165 
1166  fd_set sockets;
1167  int maxfd = 0;
1168 
1169  FD_ZERO(&sockets);
1170 
1171  // if there are any callbacks for external sockets registered...
1172  {
1173  std::lock_guard<std::mutex> lock(callbacks_mutex_);
1174  if (!callbacks_.empty()) {
1175  for (SocketCallbackInfo s : callbacks_) {
1176  // Add this socket to listening set
1177  addFDtoSet(s.socket_, maxfd, &sockets);
1178  }
1179  }
1180  }
1181 
1182  // Add Receiver ready watch socket
1183  addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::READY), maxfd, &sockets);
1184 
1185  // Add Receiver error watch socket
1186  addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::ERROR), maxfd, &sockets);
1187 
1188  // Set timeout for our next select() call. If there are
1189  // no DHCP packets to read, then we'll wait for a finite
1190  // amount of time for an IO event. Otherwise, we'll
1191  // poll (timeout = 0 secs). We need to poll, even if
1192  // DHCP packets are waiting so we don't starve external
1193  // sockets under heavy DHCP load.
1194  struct timeval select_timeout;
1195  if (getPacketQueue4()->empty()) {
1196  select_timeout.tv_sec = timeout_sec;
1197  select_timeout.tv_usec = timeout_usec;
1198  } else {
1199  select_timeout.tv_sec = 0;
1200  select_timeout.tv_usec = 0;
1201  }
1202 
1203  // zero out the errno to be safe
1204  errno = 0;
1205 
1206  int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1207 
1208  if ((result == 0) && getPacketQueue4()->empty()) {
1209  // nothing received and timeout has been reached
1210  return (Pkt4Ptr());
1211  } else if (result < 0) {
1212  // In most cases we would like to know whether select() returned
1213  // an error because of a signal being received or for some other
1214  // reason. This is because DHCP servers use signals to trigger
1215  // certain actions, like reconfiguration or graceful shutdown.
1216  // By catching a dedicated exception the caller will know if the
1217  // error returned by the function is due to the reception of the
1218  // signal or for some other reason.
1219  if (errno == EINTR) {
1220  isc_throw(SignalInterruptOnSelect, strerror(errno));
1221  } else if (errno == EBADF) {
1222  int cnt = purgeBadSockets();
1224  "SELECT interrupted by one invalid sockets, purged "
1225  << cnt << " socket descriptors");
1226  } else {
1227  isc_throw(SocketReadError, strerror(errno));
1228  }
1229  }
1230 
1231  // We only check external sockets if select detected an event.
1232  if (result > 0) {
1233  // Check for receiver thread read errors.
1234  if (dhcp_receiver_->isReady(WatchedThread::ERROR)) {
1235  string msg = dhcp_receiver_->getLastError();
1236  dhcp_receiver_->clearReady(WatchedThread::ERROR);
1237  isc_throw(SocketReadError, msg);
1238  }
1239 
1240  // Let's find out which external socket has the data
1241  SocketCallbackInfo ex_sock;
1242  bool found = false;
1243  {
1244  std::lock_guard<std::mutex> lock(callbacks_mutex_);
1245  for (SocketCallbackInfo s : callbacks_) {
1246  if (!FD_ISSET(s.socket_, &sockets)) {
1247  continue;
1248  }
1249  found = true;
1250 
1251  // something received over external socket
1252  if (s.callback_) {
1253  // Note the external socket to call its callback without
1254  // the lock taken so it can be deleted.
1255  ex_sock = s;
1256  break;
1257  }
1258  }
1259  }
1260 
1261  if (ex_sock.callback_) {
1262  // Calling the external socket's callback provides its service
1263  // layer access without integrating any specific features
1264  // in IfaceMgr
1265  ex_sock.callback_(ex_sock.socket_);
1266  }
1267  if (found) {
1268  return (Pkt4Ptr());
1269  }
1270  }
1271 
1272  // If we're here it should only be because there are DHCP packets waiting.
1273  Pkt4Ptr pkt = getPacketQueue4()->dequeuePacket();
1274  if (!pkt) {
1275  dhcp_receiver_->clearReady(WatchedThread::READY);
1276  }
1277 
1278  return (pkt);
1279 }
1280 
1281 Pkt4Ptr IfaceMgr::receive4Direct(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
1282  // Sanity check for microsecond timeout.
1283  if (timeout_usec >= 1000000) {
1284  isc_throw(BadValue, "fractional timeout must be shorter than"
1285  " one million microseconds");
1286  }
1287  boost::scoped_ptr<SocketInfo> candidate;
1288  fd_set sockets;
1289  int maxfd = 0;
1290 
1291  FD_ZERO(&sockets);
1292 
1296  for (IfacePtr iface : ifaces_) {
1297  for (SocketInfo s : iface->getSockets()) {
1298  // Only deal with IPv4 addresses.
1299  if (s.addr_.isV4()) {
1300  // Add this socket to listening set
1301  addFDtoSet(s.sockfd_, maxfd, &sockets);
1302  }
1303  }
1304  }
1305 
1306  // if there are any callbacks for external sockets registered...
1307  {
1308  std::lock_guard<std::mutex> lock(callbacks_mutex_);
1309  if (!callbacks_.empty()) {
1310  for (SocketCallbackInfo s : callbacks_) {
1311  // Add this socket to listening set
1312  addFDtoSet(s.socket_, maxfd, &sockets);
1313  }
1314  }
1315  }
1316 
1317  struct timeval select_timeout;
1318  select_timeout.tv_sec = timeout_sec;
1319  select_timeout.tv_usec = timeout_usec;
1320 
1321  // zero out the errno to be safe
1322  errno = 0;
1323 
1324  int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1325 
1326  if (result == 0) {
1327  // nothing received and timeout has been reached
1328  return (Pkt4Ptr()); // null
1329 
1330  } else if (result < 0) {
1331  // In most cases we would like to know whether select() returned
1332  // an error because of a signal being received or for some other
1333  // reason. This is because DHCP servers use signals to trigger
1334  // certain actions, like reconfiguration or graceful shutdown.
1335  // By catching a dedicated exception the caller will know if the
1336  // error returned by the function is due to the reception of the
1337  // signal or for some other reason.
1338  if (errno == EINTR) {
1339  isc_throw(SignalInterruptOnSelect, strerror(errno));
1340  } else if (errno == EBADF) {
1341  int cnt = purgeBadSockets();
1343  "SELECT interrupted by one invalid sockets, purged "
1344  << cnt << " socket descriptors");
1345  } else {
1346  isc_throw(SocketReadError, strerror(errno));
1347  }
1348  }
1349 
1350  // Let's find out which socket has the data
1351  SocketCallbackInfo ex_sock;
1352  bool found = false;
1353  {
1354  std::lock_guard<std::mutex> lock(callbacks_mutex_);
1355  for (SocketCallbackInfo s : callbacks_) {
1356  if (!FD_ISSET(s.socket_, &sockets)) {
1357  continue;
1358  }
1359  found = true;
1360 
1361  // something received over external socket
1362  if (s.callback_) {
1363  // Note the external socket to call its callback without
1364  // the lock taken so it can be deleted.
1365  ex_sock = s;
1366  break;
1367  }
1368  }
1369  }
1370 
1371  if (ex_sock.callback_) {
1372  // Calling the external socket's callback provides its service
1373  // layer access without integrating any specific features
1374  // in IfaceMgr
1375  ex_sock.callback_(ex_sock.socket_);
1376  }
1377  if (found) {
1378  return (Pkt4Ptr());
1379  }
1380 
1381  // Let's find out which interface/socket has the data
1382  IfacePtr recv_if;
1383  for (IfacePtr iface : ifaces_) {
1384  for (SocketInfo s : iface->getSockets()) {
1385  if (FD_ISSET(s.sockfd_, &sockets)) {
1386  candidate.reset(new SocketInfo(s));
1387  break;
1388  }
1389  }
1390  if (candidate) {
1391  recv_if = iface;
1392  break;
1393  }
1394  }
1395 
1396  if (!candidate || !recv_if) {
1397  isc_throw(SocketReadError, "received data over unknown socket");
1398  }
1399 
1400  // Now we have a socket, let's get some data from it!
1401  // Assuming that packet filter is not null, because its modifier checks it.
1402  return (packet_filter_->receive(*recv_if, *candidate));
1403 }
1404 
1405 Pkt6Ptr
1406 IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
1407  if (isDHCPReceiverRunning()) {
1408  return (receive6Indirect(timeout_sec, timeout_usec));
1409  }
1410 
1411  return (receive6Direct(timeout_sec, timeout_usec));
1412 }
1413 
1414 void
1415 IfaceMgr::addFDtoSet(int fd, int& maxfd, fd_set* sockets) {
1416  if (!sockets) {
1417  isc_throw(BadValue, "addFDtoSet: sockets can't be null");
1418  }
1419 
1420  FD_SET(fd, sockets);
1421  if (maxfd < fd) {
1422  maxfd = fd;
1423  }
1424 }
1425 
1426 Pkt6Ptr
1427 IfaceMgr::receive6Direct(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */ ) {
1428  // Sanity check for microsecond timeout.
1429  if (timeout_usec >= 1000000) {
1430  isc_throw(BadValue, "fractional timeout must be shorter than"
1431  " one million microseconds");
1432  }
1433 
1434  boost::scoped_ptr<SocketInfo> candidate;
1435  fd_set sockets;
1436  int maxfd = 0;
1437 
1438  FD_ZERO(&sockets);
1439 
1443  for (IfacePtr iface : ifaces_) {
1444  for (SocketInfo s : iface->getSockets()) {
1445  // Only deal with IPv6 addresses.
1446  if (s.addr_.isV6()) {
1447  // Add this socket to listening set
1448  addFDtoSet(s.sockfd_, maxfd, &sockets);
1449  }
1450  }
1451  }
1452 
1453  // if there are any callbacks for external sockets registered...
1454  {
1455  std::lock_guard<std::mutex> lock(callbacks_mutex_);
1456  if (!callbacks_.empty()) {
1457  for (SocketCallbackInfo s : callbacks_) {
1458  // Add this socket to listening set
1459  addFDtoSet(s.socket_, maxfd, &sockets);
1460  }
1461  }
1462  }
1463 
1464  struct timeval select_timeout;
1465  select_timeout.tv_sec = timeout_sec;
1466  select_timeout.tv_usec = timeout_usec;
1467 
1468  // zero out the errno to be safe
1469  errno = 0;
1470 
1471  int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1472 
1473  if (result == 0) {
1474  // nothing received and timeout has been reached
1475  return (Pkt6Ptr()); // null
1476 
1477  } else if (result < 0) {
1478  // In most cases we would like to know whether select() returned
1479  // an error because of a signal being received or for some other
1480  // reason. This is because DHCP servers use signals to trigger
1481  // certain actions, like reconfiguration or graceful shutdown.
1482  // By catching a dedicated exception the caller will know if the
1483  // error returned by the function is due to the reception of the
1484  // signal or for some other reason.
1485  if (errno == EINTR) {
1486  isc_throw(SignalInterruptOnSelect, strerror(errno));
1487  } else if (errno == EBADF) {
1488  int cnt = purgeBadSockets();
1490  "SELECT interrupted by one invalid sockets, purged "
1491  << cnt << " socket descriptors");
1492  } else {
1493  isc_throw(SocketReadError, strerror(errno));
1494  }
1495  }
1496 
1497  // Let's find out which socket has the data
1498  SocketCallbackInfo ex_sock;
1499  bool found = false;
1500  {
1501  std::lock_guard<std::mutex> lock(callbacks_mutex_);
1502  for (SocketCallbackInfo s : callbacks_) {
1503  if (!FD_ISSET(s.socket_, &sockets)) {
1504  continue;
1505  }
1506  found = true;
1507 
1508  // something received over external socket
1509  if (s.callback_) {
1510  // Note the external socket to call its callback without
1511  // the lock taken so it can be deleted.
1512  ex_sock = s;
1513  break;
1514  }
1515  }
1516  }
1517 
1518  if (ex_sock.callback_) {
1519  // Calling the external socket's callback provides its service
1520  // layer access without integrating any specific features
1521  // in IfaceMgr
1522  ex_sock.callback_(ex_sock.socket_);
1523  }
1524  if (found) {
1525  return (Pkt6Ptr());
1526  }
1527 
1528  // Let's find out which interface/socket has the data
1529  for (IfacePtr iface : ifaces_) {
1530  for (SocketInfo s : iface->getSockets()) {
1531  if (FD_ISSET(s.sockfd_, &sockets)) {
1532  candidate.reset(new SocketInfo(s));
1533  break;
1534  }
1535  }
1536  if (candidate) {
1537  break;
1538  }
1539  }
1540 
1541  if (!candidate) {
1542  isc_throw(SocketReadError, "received data over unknown socket");
1543  }
1544  // Assuming that packet filter is not null, because its modifier checks it.
1545  return (packet_filter6_->receive(*candidate));
1546 }
1547 
1548 Pkt6Ptr
1549 IfaceMgr::receive6Indirect(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */ ) {
1550  // Sanity check for microsecond timeout.
1551  if (timeout_usec >= 1000000) {
1552  isc_throw(BadValue, "fractional timeout must be shorter than"
1553  " one million microseconds");
1554  }
1555 
1556  fd_set sockets;
1557  int maxfd = 0;
1558 
1559  FD_ZERO(&sockets);
1560 
1561  // if there are any callbacks for external sockets registered...
1562  {
1563  std::lock_guard<std::mutex> lock(callbacks_mutex_);
1564  if (!callbacks_.empty()) {
1565  for (SocketCallbackInfo s : callbacks_) {
1566  // Add this socket to listening set
1567  addFDtoSet(s.socket_, maxfd, &sockets);
1568  }
1569  }
1570  }
1571 
1572  // Add Receiver ready watch socket
1573  addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::READY), maxfd, &sockets);
1574 
1575  // Add Receiver error watch socket
1576  addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::ERROR), maxfd, &sockets);
1577 
1578  // Set timeout for our next select() call. If there are
1579  // no DHCP packets to read, then we'll wait for a finite
1580  // amount of time for an IO event. Otherwise, we'll
1581  // poll (timeout = 0 secs). We need to poll, even if
1582  // DHCP packets are waiting so we don't starve external
1583  // sockets under heavy DHCP load.
1584  struct timeval select_timeout;
1585  if (getPacketQueue6()->empty()) {
1586  select_timeout.tv_sec = timeout_sec;
1587  select_timeout.tv_usec = timeout_usec;
1588  } else {
1589  select_timeout.tv_sec = 0;
1590  select_timeout.tv_usec = 0;
1591  }
1592 
1593  // zero out the errno to be safe
1594  errno = 0;
1595 
1596  int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
1597 
1598  if ((result == 0) && getPacketQueue6()->empty()) {
1599  // nothing received and timeout has been reached
1600  return (Pkt6Ptr());
1601  } else if (result < 0) {
1602  // In most cases we would like to know whether select() returned
1603  // an error because of a signal being received or for some other
1604  // reason. This is because DHCP servers use signals to trigger
1605  // certain actions, like reconfiguration or graceful shutdown.
1606  // By catching a dedicated exception the caller will know if the
1607  // error returned by the function is due to the reception of the
1608  // signal or for some other reason.
1609  if (errno == EINTR) {
1610  isc_throw(SignalInterruptOnSelect, strerror(errno));
1611  } else if (errno == EBADF) {
1612  int cnt = purgeBadSockets();
1614  "SELECT interrupted by one invalid sockets, purged "
1615  << cnt << " socket descriptors");
1616  } else {
1617  isc_throw(SocketReadError, strerror(errno));
1618  }
1619  }
1620 
1621  // We only check external sockets if select detected an event.
1622  if (result > 0) {
1623  // Check for receiver thread read errors.
1624  if (dhcp_receiver_->isReady(WatchedThread::ERROR)) {
1625  string msg = dhcp_receiver_->getLastError();
1626  dhcp_receiver_->clearReady(WatchedThread::ERROR);
1627  isc_throw(SocketReadError, msg);
1628  }
1629 
1630  // Let's find out which external socket has the data
1631  SocketCallbackInfo ex_sock;
1632  bool found = false;
1633  {
1634  std::lock_guard<std::mutex> lock(callbacks_mutex_);
1635  for (SocketCallbackInfo s : callbacks_) {
1636  if (!FD_ISSET(s.socket_, &sockets)) {
1637  continue;
1638  }
1639  found = true;
1640 
1641  // something received over external socket
1642  if (s.callback_) {
1643  // Note the external socket to call its callback without
1644  // the lock taken so it can be deleted.
1645  ex_sock = s;
1646  break;
1647  }
1648  }
1649  }
1650 
1651  if (ex_sock.callback_) {
1652  // Calling the external socket's callback provides its service
1653  // layer access without integrating any specific features
1654  // in IfaceMgr
1655  ex_sock.callback_(ex_sock.socket_);
1656  }
1657  if (found) {
1658  return (Pkt6Ptr());
1659  }
1660  }
1661 
1662  // If we're here it should only be because there are DHCP packets waiting.
1663  Pkt6Ptr pkt = getPacketQueue6()->dequeuePacket();
1664  if (!pkt) {
1665  dhcp_receiver_->clearReady(WatchedThread::READY);
1666  }
1667 
1668  return (pkt);
1669 }
1670 
1671 void
1672 IfaceMgr::receiveDHCP4Packets() {
1673  fd_set sockets;
1674  int maxfd = 0;
1675 
1676  FD_ZERO(&sockets);
1677 
1678  // Add terminate watch socket.
1679  addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE), maxfd, &sockets);
1680 
1681  // Add Interface sockets.
1682  for (IfacePtr iface : ifaces_) {
1683  for (SocketInfo s : iface->getSockets()) {
1684  // Only deal with IPv4 addresses.
1685  if (s.addr_.isV4()) {
1686  // Add this socket to listening set.
1687  addFDtoSet(s.sockfd_, maxfd, &sockets);
1688  }
1689  }
1690  }
1691 
1692  for (;;) {
1693  // Check the watch socket.
1694  if (dhcp_receiver_->shouldTerminate()) {
1695  return;
1696  }
1697 
1698  fd_set rd_set;
1699  FD_COPY(&sockets, &rd_set);
1700 
1701  // zero out the errno to be safe.
1702  errno = 0;
1703 
1704  // Select with null timeouts to wait indefinitely an event
1705  int result = select(maxfd + 1, &rd_set, 0, 0, 0);
1706 
1707  // Re-check the watch socket.
1708  if (dhcp_receiver_->shouldTerminate()) {
1709  return;
1710  }
1711 
1712  if (result == 0) {
1713  // nothing received?
1714  continue;
1715 
1716  } else if (result < 0) {
1717  // This thread should not get signals?
1718  if (errno != EINTR) {
1719  // Signal the error to receive4.
1720  dhcp_receiver_->setError(strerror(errno));
1721  // We need to sleep in case of the error condition to
1722  // prevent the thread from tight looping when result
1723  // gets negative.
1724  sleep(1);
1725  }
1726  continue;
1727  }
1728 
1729  // Let's find out which interface/socket has data.
1730  for (IfacePtr iface : ifaces_) {
1731  for (SocketInfo s : iface->getSockets()) {
1732  if (FD_ISSET(s.sockfd_, &sockets)) {
1733  receiveDHCP4Packet(*iface, s);
1734  // Can take time so check one more time the watch socket.
1735  if (dhcp_receiver_->shouldTerminate()) {
1736  return;
1737  }
1738  }
1739  }
1740  }
1741  }
1742 
1743 }
1744 
1745 void
1746 IfaceMgr::receiveDHCP6Packets() {
1747  fd_set sockets;
1748  int maxfd = 0;
1749 
1750  FD_ZERO(&sockets);
1751 
1752  // Add terminate watch socket.
1753  addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE), maxfd, &sockets);
1754 
1755  // Add Interface sockets.
1756  for (IfacePtr iface : ifaces_) {
1757  for (SocketInfo s : iface->getSockets()) {
1758  // Only deal with IPv6 addresses.
1759  if (s.addr_.isV6()) {
1760  // Add this socket to listening set.
1761  addFDtoSet(s.sockfd_ , maxfd, &sockets);
1762  }
1763  }
1764  }
1765 
1766  for (;;) {
1767  // Check the watch socket.
1768  if (dhcp_receiver_->shouldTerminate()) {
1769  return;
1770  }
1771 
1772  fd_set rd_set;
1773  FD_COPY(&sockets, &rd_set);
1774 
1775  // zero out the errno to be safe.
1776  errno = 0;
1777 
1778  // Note we wait until something happen.
1779  int result = select(maxfd + 1, &rd_set, 0, 0, 0);
1780 
1781  // Re-check the watch socket.
1782  if (dhcp_receiver_->shouldTerminate()) {
1783  return;
1784  }
1785 
1786  if (result == 0) {
1787  // nothing received?
1788  continue;
1789  } else if (result < 0) {
1790  // This thread should not get signals?
1791  if (errno != EINTR) {
1792  // Signal the error to receive6.
1793  dhcp_receiver_->setError(strerror(errno));
1794  // We need to sleep in case of the error condition to
1795  // prevent the thread from tight looping when result
1796  // gets negative.
1797  sleep(1);
1798  }
1799  continue;
1800  }
1801 
1802  // Let's find out which interface/socket has data.
1803  for (IfacePtr iface : ifaces_) {
1804  for (SocketInfo s : iface->getSockets()) {
1805  if (FD_ISSET(s.sockfd_, &sockets)) {
1806  receiveDHCP6Packet(s);
1807  // Can take time so check one more time the watch socket.
1808  if (dhcp_receiver_->shouldTerminate()) {
1809  return;
1810  }
1811  }
1812  }
1813  }
1814  }
1815 }
1816 
1817 void
1818 IfaceMgr::receiveDHCP4Packet(Iface& iface, const SocketInfo& socket_info) {
1819  int len;
1820 
1821  int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1822  if (result < 0) {
1823  // Signal the error to receive4.
1824  dhcp_receiver_->setError(strerror(errno));
1825  return;
1826  }
1827  if (len == 0) {
1828  // Nothing to read.
1829  return;
1830  }
1831 
1832  Pkt4Ptr pkt;
1833 
1834  try {
1835  pkt = packet_filter_->receive(iface, socket_info);
1836  } catch (const std::exception& ex) {
1837  dhcp_receiver_->setError(strerror(errno));
1838  } catch (...) {
1839  dhcp_receiver_->setError("packet filter receive() failed");
1840  }
1841 
1842  if (pkt) {
1843  getPacketQueue4()->enqueuePacket(pkt, socket_info);
1844  dhcp_receiver_->markReady(WatchedThread::READY);
1845  }
1846 }
1847 
1848 void
1849 IfaceMgr::receiveDHCP6Packet(const SocketInfo& socket_info) {
1850  int len;
1851 
1852  int result = ioctl(socket_info.sockfd_, FIONREAD, &len);
1853  if (result < 0) {
1854  // Signal the error to receive6.
1855  dhcp_receiver_->setError(strerror(errno));
1856  return;
1857  }
1858  if (len == 0) {
1859  // Nothing to read.
1860  return;
1861  }
1862 
1863  Pkt6Ptr pkt;
1864 
1865  try {
1866  pkt = packet_filter6_->receive(socket_info);
1867  } catch (const std::exception& ex) {
1868  dhcp_receiver_->setError(ex.what());
1869  } catch (...) {
1870  dhcp_receiver_->setError("packet filter receive() failed");
1871  }
1872 
1873  if (pkt) {
1874  getPacketQueue6()->enqueuePacket(pkt, socket_info);
1875  dhcp_receiver_->markReady(WatchedThread::READY);
1876  }
1877 }
1878 
1879 uint16_t
1881  IfacePtr iface = getIface(pkt);
1882  if (!iface) {
1883  isc_throw(IfaceNotFound, "Tried to find socket for non-existent interface");
1884  }
1885 
1886 
1887  const Iface::SocketCollection& socket_collection = iface->getSockets();
1888 
1889  Iface::SocketCollection::const_iterator candidate = socket_collection.end();
1890 
1891  Iface::SocketCollection::const_iterator s;
1892  for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
1893 
1894  // We should not merge those conditions for debugging reasons.
1895 
1896  // V4 sockets are useless for sending v6 packets.
1897  if (s->family_ != AF_INET6) {
1898  continue;
1899  }
1900 
1901  // Sockets bound to multicast address are useless for sending anything.
1902  if (s->addr_.isV6Multicast()) {
1903  continue;
1904  }
1905 
1906  if (s->addr_ == pkt->getLocalAddr()) {
1907  // This socket is bound to the source address. This is perfect
1908  // match, no need to look any further.
1909  return (s->sockfd_);
1910  }
1911 
1912  // If we don't have any other candidate, this one will do
1913  if (candidate == socket_collection.end()) {
1914  candidate = s;
1915  } else {
1916  // If we want to send something to link-local and the socket is
1917  // bound to link-local or we want to send to global and the socket
1918  // is bound to global, then use it as candidate
1919  if ( (pkt->getRemoteAddr().isV6LinkLocal() &&
1920  s->addr_.isV6LinkLocal()) ||
1921  (!pkt->getRemoteAddr().isV6LinkLocal() &&
1922  !s->addr_.isV6LinkLocal()) ) {
1923  candidate = s;
1924  }
1925  }
1926  }
1927 
1928  if (candidate != socket_collection.end()) {
1929  return (candidate->sockfd_);
1930  }
1931 
1932  isc_throw(SocketNotFound, "Interface " << iface->getFullName()
1933  << " does not have any suitable IPv6 sockets open.");
1934 }
1935 
1936 SocketInfo
1938  IfacePtr iface = getIface(pkt);
1939  if (!iface) {
1940  isc_throw(IfaceNotFound, "Tried to find socket for non-existent interface");
1941  }
1942 
1943  const Iface::SocketCollection& socket_collection = iface->getSockets();
1944  // A candidate being an end of the iterator marks that it is a beginning of
1945  // the socket search and that the candidate needs to be set to the first
1946  // socket found.
1947  Iface::SocketCollection::const_iterator candidate = socket_collection.end();
1948  Iface::SocketCollection::const_iterator s;
1949  for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
1950  if (s->family_ == AF_INET) {
1951  if (s->addr_ == pkt->getLocalAddr()) {
1952  return (*s);
1953  }
1954 
1955  if (candidate == socket_collection.end()) {
1956  candidate = s;
1957  }
1958  }
1959  }
1960 
1961  if (candidate == socket_collection.end()) {
1962  isc_throw(SocketNotFound, "Interface " << iface->getFullName()
1963  << " does not have any suitable IPv4 sockets open.");
1964  }
1965 
1966  return (*candidate);
1967 }
1968 
1969 bool
1971  if (isDHCPReceiverRunning()) {
1972  isc_throw(InvalidOperation, "Cannot reconfigure queueing"
1973  " while DHCP receiver thread is running");
1974  }
1975 
1976  bool enable_queue = false;
1977  if (queue_control) {
1978  try {
1979  enable_queue = data::SimpleParser::getBoolean(queue_control, "enable-queue");
1980  } catch (...) {
1981  // @todo - for now swallow not found errors.
1982  // if not present we assume default
1983  }
1984  }
1985 
1986  if (enable_queue) {
1987  // Try to create the queue as configured.
1988  if (family == AF_INET) {
1989  packet_queue_mgr4_->createPacketQueue(queue_control);
1990  } else {
1991  packet_queue_mgr6_->createPacketQueue(queue_control);
1992  }
1993  } else {
1994  // Destroy the current queue (if one), this inherently disables threading.
1995  if (family == AF_INET) {
1996  packet_queue_mgr4_->destroyPacketQueue();
1997  } else {
1998  packet_queue_mgr6_->destroyPacketQueue();
1999  }
2000  }
2001 
2002  return (enable_queue);
2003 }
2004 
2005 void
2006 Iface::addError(std::string const& message) {
2007  errors_.push_back(message);
2008 }
2009 
2010 void
2012  errors_.clear();
2013 }
2014 
2015 Iface::ErrorBuffer const&
2017  return errors_;
2018 }
2019 
2020 } // end of namespace isc::dhcp
2021 } // end of namespace isc
SocketCallback callback_
A callback that will be called when data arrives over socket_.
Definition: iface_mgr.h:668
void clearIfaces()
Removes detected interfaces.
Definition: iface_mgr.cc:927
IfacePtr getIface(int ifindex)
Returns interface specified interface index.
Definition: iface_mgr.cc:902
Provides a thread and controls for monitoring its activities.
static bool getBoolean(isc::data::ConstElementPtr scope, const std::string &name)
Returns a boolean parameter from a scope.
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:1041
Pkt4Ptr receive4Direct(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv4 packets directly or data from external sockets.
Definition: iface_mgr.cc:1281
void collectBoundAddresses()
Collect the addresses all sockets are bound to.
Definition: iface_mgr.cc:937
IfaceMgr exception thrown thrown when socket opening or configuration failed.
Definition: iface_mgr.h:63
A generic exception that is thrown when a function is not implemented.
Packet Queue Manager for DHPCv6 servers.
bool hasAddress(const isc::asiolink::IOAddress &address) const
Check if the interface has the specified address assigned.
Definition: iface_mgr.cc:239
void addSocket(const SocketInfo &sock)
Adds socket descriptor to an interface.
Definition: iface_mgr.h:321
IfaceMgr exception thrown when there is no suitable socket found.
Definition: iface_mgr.h:93
void setPacketFilter(const PktFilterPtr &packet_filter)
Set packet filter object to handle sending and receiving DHCPv4 messages.
Definition: iface_mgr.cc:389
static const unsigned int MAX_MAC_LEN
Maximum MAC address length (Infiniband uses 20 bytes)
Definition: iface_mgr.h:122
size_t mac_len_
Length of link-layer address (usually 6).
Definition: iface_mgr.h:431
ErrorBuffer const & getErrors() const
Get the consistent list of error messages.
Definition: iface_mgr.cc:2016
Pkt6Ptr receive6Indirect(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv6 packets indirectly or data from external sockets.
Definition: iface_mgr.cc:1549
void addExternalSocket(int socketfd, SocketCallback callback)
Adds external socket and a callback.
Definition: iface_mgr.cc:325
bool delSocket(uint16_t sockfd)
Closes socket.
Definition: iface_mgr.cc:168
IfaceMgr exception thrown thrown when interface detection fails.
Definition: iface_mgr.h:41
void clearErrors()
Clears all errors.
Definition: iface_mgr.cc:2011
void addUnicast(const isc::asiolink::IOAddress &addr)
Adds unicast the server should listen on.
Definition: iface_mgr.cc:212
boost::shared_ptr< Iface > IfacePtr
Type definition for the pointer to an Iface object.
Definition: iface_mgr.h:487
#define FD_COPY(orig, copy)
Definition: iface_mgr.cc:37
void startDHCPReceiver(const uint16_t family)
Starts DHCP packet receiver.
Definition: iface_mgr.cc:765
#define DHCP_IPV4_BROADCAST_ADDRESS
Definition: dhcp4.h:42
int ifindex_
Interface index (a value that uniquely identifies an interface).
Definition: iface_mgr.h:419
void setActive(const isc::asiolink::IOAddress &address, const bool active)
Activates or deactivates address for the interface.
Definition: iface_mgr.cc:256
std::list< SocketInfo > SocketCollection
Type that holds a list of socket information.
Definition: iface_mgr.h:139
STL namespace.
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
int purgeBadSockets()
Scans registered socket set and removes any that are invalid.
Definition: iface_mgr.cc:365
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
PacketQueue6Ptr getPacketQueue6()
Fetches the DHCPv6 receiver packet queue.
Definition: iface_mgr.h:1263
Handles network interfaces, transmission and reception.
Definition: iface_mgr.h:656
Packet handling class using AF_INET socket family.
Represents a single network interface.
Definition: iface_mgr.h:118
int openSocketFromAddress(const isc::asiolink::IOAddress &addr, const uint16_t port)
Opens UDP/IP socket and binds to address specified.
Definition: iface_mgr.cc:1018
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
boost::shared_ptr< PktFilter > PktFilterPtr
Pointer to a PktFilter object.
Definition: pkt_filter.h:134
std::vector< std::string > ErrorBuffer
Type definition for a list of error messages.
Definition: iface_mgr.h:142
int sockfd_
IPv4 or IPv6.
Definition: socket_info.h:26
bool send(const Pkt6Ptr &pkt)
Sends an IPv6 packet.
Definition: iface_mgr.cc:1126
void closeSockets()
Closes all open sockets on interface.
Definition: iface_mgr.cc:76
Keeps callback information for external sockets.
Definition: iface_mgr.h:663
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition: pkt6.h:28
std::string getPlainMac() const
Returns link-layer address a plain text.
Definition: iface_mgr.cc:130
Pkt4Ptr receive4(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv4 packets or data from external sockets.
Definition: iface_mgr.cc:1151
Definition: edns.h:19
IfaceMgr exception thrown when there is no suitable interface.
Definition: iface_mgr.h:86
void deleteExternalSocket(int socketfd)
Deletes external socket.
Definition: iface_mgr.cc:348
BoundAddresses bound_address_
Unordered set of IPv4 bound addresses.
Definition: iface_mgr.h:1460
unsigned int countActive4() const
Returns a number of activated IPv4 addresses on the interface.
Definition: iface_mgr.cc:277
#define IFACEMGR_ERROR(ex_type, handler, iface, stream)
A macro which handles an error in IfaceMgr.
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
A generic exception that is thrown when an unexpected error condition occurs.
void detectIfaces(bool update_only=false)
Detects network interfaces.
Exception thrown when invalid packet filter object specified.
Definition: pkt_filter.h:18
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition: pkt4.h:544
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
void clearUnicasts()
Clears unicast addresses on all interfaces.
Definition: iface_mgr.cc:952
Packet Queue Manager for DHPCv4 servers.
IfacePtr getIface(uint32_t ifindex)
Lookup by interface index.
Definition: iface_mgr.cc:835
void clearBoundAddresses()
Clears the addresses all sockets are bound to.
Definition: iface_mgr.cc:932
IfaceMgr exception thrown thrown when error occurred during reading data from socket.
Definition: iface_mgr.h:71
boost::shared_ptr< isc::dhcp::Pkt > PktPtr
A pointer to either Pkt4 or Pkt6 packet.
Definition: pkt.h:797
void deleteAllExternalSockets()
Deletes all external sockets.
Definition: iface_mgr.cc:383
void addInterface(const IfacePtr &iface)
Adds an interface to list of known interfaces.
Definition: iface_mgr.cc:798
std::function< void(int fd)> SocketCallback
Defines callback used when data is received over external sockets.
Definition: iface_mgr.h:660
This is a base class for exceptions thrown from the DNS library module.
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
Defines the logger used by the top-level component of kea-lfc.
AddressCollection addrs_
List of assigned addresses.
Definition: iface_mgr.h:422
std::list< Address > AddressCollection
Type that defines list of addresses.
Definition: iface_mgr.h:128
boost::shared_ptr< PktFilter6 > PktFilter6Ptr
Pointer to a PktFilter object.
Definition: pkt_filter6.h:136
bool getAddress4(isc::asiolink::IOAddress &address) const
Returns IPv4 address assigned to the interface.
Definition: iface_mgr.cc:223
Exception thrown when a call to select is interrupted by a signal.
Definition: iface_mgr.h:55
std::string getFullName() const
Returns full interface name as "ifname/ifindex" string.
Definition: iface_mgr.cc:123
const Name & name_
Definition: dns/message.cc:693
void closeSockets()
Closes all open sockets.
Definition: iface_mgr.cc:287
A generic exception that is thrown if a function is called in a prohibited way.
bool isDHCPReceiverRunning() const
Returns true if there is a receiver exists and its thread is currently running.
Definition: iface_mgr.h:1287
SocketCollection sockets_
Socket used to send data.
Definition: iface_mgr.h:413
bool delAddress(const isc::asiolink::IOAddress &addr)
Deletes an address from an interface.
Definition: iface_mgr.cc:157
uint8_t mac_[MAX_MAC_LEN]
Link-layer address.
Definition: iface_mgr.h:428
A DHCPv6 packet handling class using datagram sockets.
uint16_t getSocket(const isc::dhcp::Pkt6Ptr &pkt)
Return most suitable socket for transmitting specified IPv6 packet.
Definition: iface_mgr.cc:1880
void addAddress(const isc::asiolink::IOAddress &addr)
Adds an address to an interface.
Definition: iface_mgr.cc:249
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:958
virtual ~IfaceMgr()
Destructor.
Definition: iface_mgr.cc:315
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
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:977
static void addFDtoSet(int fd, int &maxfd, fd_set *sockets)
Convenience method for adding an descriptor to a set.
Definition: iface_mgr.cc:1415
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:1115
PacketQueue4Ptr getPacketQueue4()
Fetches the DHCPv4 receiver packet queue.
Definition: iface_mgr.h:1246
bool isDirectResponseSupported() const
Check if packet be sent directly to the client having no address.
Definition: iface_mgr.cc:320
IfaceMgr()
Protected constructor.
Definition: iface_mgr.cc:185
Pkt6Ptr receive6(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv4 packets or data from external sockets.
Definition: iface_mgr.cc:1406
int openSocket6(Iface &iface, const isc::asiolink::IOAddress &addr, uint16_t port, const bool join_multicast)
Opens IPv6 socket.
int socket_
Socket descriptor of the external socket.
Definition: iface_mgr.h:665
void printIfaces(std::ostream &out=std::cout)
Debugging method that prints out all available interfaces.
Definition: iface_mgr.cc:811
void addError(std::string const &message)
Add an error to the list of messages.
Definition: iface_mgr.cc:2006
Pkt6Ptr receive6Direct(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv6 packets directly or data from external sockets.
Definition: iface_mgr.cc:1427
std::string name_
Network interface name.
Definition: iface_mgr.h:416
A template representing an optional value.
Definition: optional.h:36
void stopDHCPReceiver()
Stops the DHCP packet receiver.
Definition: iface_mgr.cc:299
Pkt4Ptr receive4Indirect(uint32_t timeout_sec, uint32_t timeout_usec=0)
Receive IPv4 packets indirectly or data from external sockets.
Definition: iface_mgr.cc:1159
boost::shared_ptr< IfaceMgr > IfaceMgrPtr
Type definition for the pointer to the IfaceMgr.
Definition: iface_mgr.h:638
void stubDetectIfaces()
Stub implementation of network interface detection.
Definition: iface_mgr.cc:480
Holds information about socket.
Definition: socket_info.h:19
Exception thrown when it is not allowed to set new Packet Filter.
Definition: iface_mgr.h:48
IfaceCollection ifaces_
List of available interfaces.
Definition: iface_mgr.h:1457
bool configureDHCPPacketQueue(const uint16_t family, data::ConstElementPtr queue_control)
Configures DHCP packet queue.
Definition: iface_mgr.cc:1970
void clear()
Clear the collection.
Definition: iface_mgr.h:556
void setMac(const uint8_t *mac, size_t macLen)
Sets MAC address of the interface.
Definition: iface_mgr.cc:144