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