Kea 2.0.1
iface_mgr_bsd.cc
Go to the documentation of this file.
1// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#if defined(OS_BSD)
10
11#include <dhcp/iface_mgr.h>
13#include <dhcp/pkt_filter_bpf.h>
16
17#include <sys/types.h>
18#include <sys/socket.h>
19#include <net/if_dl.h>
20#include <net/if.h>
21#include <ifaddrs.h>
22
23using namespace std;
24using namespace isc;
25using namespace isc::asiolink;
26using namespace isc::dhcp;
27
28namespace isc {
29namespace dhcp {
30
32void
34 struct ifaddrs* iflist = 0;// The whole interface list
35 struct ifaddrs* ifptr = 0; // The interface we're processing now
36
37 // Gets list of ifaddrs struct
38 if(getifaddrs(&iflist) != 0) {
39 isc_throw(Unexpected, "Network interfaces detection failed.");
40 }
41
42 typedef map<string, IfacePtr> IfaceLst;
43 IfaceLst::iterator iface_iter;
44 IfaceLst ifaces;
45
46 // First lookup for getting interfaces ...
47 for (ifptr = iflist; ifptr != 0; ifptr = ifptr->ifa_next) {
48 const char * ifname = ifptr->ifa_name;
49 uint ifindex = 0;
50
51 if (!(ifindex = if_nametoindex(ifname))) {
52 // Interface name does not have corresponding index ...
53 freeifaddrs(iflist);
54 isc_throw(Unexpected, "Interface " << ifname << " has no index");
55 }
56
57 if ((iface_iter = ifaces.find(ifname)) != ifaces.end()) {
58 continue;
59 }
60
61 IfacePtr iface(new Iface(ifname, ifindex));
62 iface->setFlags(ifptr->ifa_flags);
63 ifaces.insert(pair<string, IfacePtr>(ifname, iface));
64 }
65
66 // Second lookup to get MAC and IP addresses
67 for (ifptr = iflist; ifptr != 0; ifptr = ifptr->ifa_next) {
68 if ((iface_iter = ifaces.find(ifptr->ifa_name)) == ifaces.end()) {
69 continue;
70 }
71 // Common byte pointer for following data
72 const uint8_t * ptr = 0;
73 if(ifptr->ifa_addr->sa_family == AF_LINK) {
74 // HWAddr
75 struct sockaddr_dl * ldata =
76 reinterpret_cast<struct sockaddr_dl *>(ifptr->ifa_addr);
77 ptr = reinterpret_cast<uint8_t *>(LLADDR(ldata));
78
79 iface_iter->second->setHWType(ldata->sdl_type);
80 iface_iter->second->setMac(ptr, ldata->sdl_alen);
81 } else if(ifptr->ifa_addr->sa_family == AF_INET6) {
82 // IPv6 Addr
83 struct sockaddr_in6 * adata =
84 reinterpret_cast<struct sockaddr_in6 *>(ifptr->ifa_addr);
85 ptr = reinterpret_cast<uint8_t *>(&adata->sin6_addr);
86
87 IOAddress a = IOAddress::fromBytes(AF_INET6, ptr);
88 iface_iter->second->addAddress(a);
89 } else {
90 // IPv4 Addr
91 struct sockaddr_in * adata =
92 reinterpret_cast<struct sockaddr_in *>(ifptr->ifa_addr);
93 ptr = reinterpret_cast<uint8_t *>(&adata->sin_addr);
94
95 IOAddress a = IOAddress::fromBytes(AF_INET, ptr);
96 iface_iter->second->addAddress(a);
97 }
98 }
99
100 freeifaddrs(iflist);
101
102 // Interfaces registering
103 for(IfaceLst::const_iterator iface_iter = ifaces.begin();
104 iface_iter != ifaces.end(); ++iface_iter) {
105 addInterface(iface_iter->second);
106 }
107}
108
114void Iface::setFlags(uint64_t flags) {
115 flags_ = flags;
116
117 flag_loopback_ = flags & IFF_LOOPBACK;
118 flag_up_ = flags & IFF_UP;
119 flag_running_ = flags & IFF_RUNNING;
120 flag_multicast_ = flags & IFF_MULTICAST;
121 flag_broadcast_ = flags & IFF_BROADCAST;
122}
123
124void
125IfaceMgr::setMatchingPacketFilter(const bool direct_response_desired) {
126 // If direct response is desired we have to use BPF. If the direct
127 // response is not desired we use datagram socket supported by the
128 // PktFilterInet class. Note however that on BSD systems binding the
129 // datagram socket to the device is not supported and the server would
130 // have no means to determine on which interface the packet has been
131 // received. Hence, it is discouraged to use PktFilterInet for the
132 // server.
133 if (direct_response_desired) {
135
136 } else {
138
139 }
140}
141
142bool
143IfaceMgr::openMulticastSocket(Iface& iface,
144 const isc::asiolink::IOAddress& addr,
145 const uint16_t port,
146 IfaceMgrErrorMsgCallback error_handler) {
147 try {
148 // This should open a socket, bind it to link-local address
149 // and join multicast group.
150 openSocket(iface.getName(), addr, port, iface.flag_multicast_);
151
152 } catch (const Exception& ex) {
153 IFACEMGR_ERROR(SocketConfigError, error_handler,
154 "Failed to open link-local socket on "
155 " interface " << iface.getName() << ": "
156 << ex.what());
157 return (false);
158
159 }
160 return (true);
161}
162
163int
164IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port,
165 const bool join_multicast) {
166 // On BSD, we bind the socket to in6addr_any and join multicast group
167 // to receive multicast traffic. So, if the multicast is requested,
168 // replace the address specified by the caller with the "unspecified"
169 // address.
170 IOAddress actual_address = join_multicast ? IOAddress("::") : addr;
171 SocketInfo info = packet_filter6_->openSocket(iface, actual_address, port,
172 join_multicast);
173 iface.addSocket(info);
174 return (info.sockfd_);
175}
176
177
178} // end of isc::dhcp namespace
179} // end of dhcp namespace
180
181#endif
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown when an unexpected error condition occurs.
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:931
void setPacketFilter(const PktFilterPtr &packet_filter)
Set packet filter object to handle sending and receiving DHCPv4 messages.
Definition: iface_mgr.cc:388
void detectIfaces()
Detects network interfaces.
int openSocket6(Iface &iface, const isc::asiolink::IOAddress &addr, uint16_t port, const bool join_multicast)
Opens IPv6 socket.
void addInterface(const IfacePtr &iface)
Adds an interface to list of known interfaces.
Definition: iface_mgr.cc:771
void setMatchingPacketFilter(const bool direct_response_desired=false)
Set Packet Filter object to handle send/receive packets.
Represents a single network interface.
Definition: iface_mgr.h:118
uint64_t flags_
Interface flags (this value is as is returned by OS, it may mean different things on different OSes).
Definition: iface_mgr.h:444
bool flag_multicast_
Flag specifies if selected interface is multicast capable.
Definition: iface_mgr.h:435
std::string getName() const
Returns interface name.
Definition: iface_mgr.h:221
void setFlags(uint64_t flags)
Sets flag_*_ fields based on bitmask value returned by OS.
bool flag_running_
Flag specifies if selected interface is running (e.g.
Definition: iface_mgr.h:432
bool flag_loopback_
Specifies if selected interface is loopback.
Definition: iface_mgr.h:425
void addSocket(const SocketInfo &sock)
Adds socket descriptor to an interface.
Definition: iface_mgr.h:318
bool flag_up_
Specifies if selected interface is up.
Definition: iface_mgr.h:428
bool flag_broadcast_
Flag specifies if selected interface is broadcast capable.
Definition: iface_mgr.h:438
Packet handling class using Berkeley Packet Filtering (BPF)
Packet handling class using AF_INET socket family.
IfaceMgr exception thrown thrown when socket opening or configuration failed.
Definition: iface_mgr.h:63
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define IFACEMGR_ERROR(ex_type, handler, stream)
A macro which handles an error in IfaceMgr.
@ info
Definition: db_log.h:120
boost::shared_ptr< PktFilter > PktFilterPtr
Pointer to a PktFilter object.
Definition: pkt_filter.h:134
boost::shared_ptr< Iface > IfacePtr
Type definition for the pointer to an Iface object.
Definition: iface_mgr.h:463
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:624
Defines the logger used by the top-level component of kea-lfc.
Holds information about socket.
Definition: socket_info.h:19