BIND 10 trac1540, updated. 4fd6efcde0f9cb8d7d1513530324a389e32a978d [1540] Moved Linux-specific code to iface_mgr_linux.cc
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Mar 7 20:11:37 UTC 2012
The branch, trac1540 has been updated
via 4fd6efcde0f9cb8d7d1513530324a389e32a978d (commit)
from 4006d91c9555c8dffab444aaa6e83f523ad5b338 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 4fd6efcde0f9cb8d7d1513530324a389e32a978d
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Wed Mar 7 21:11:11 2012 +0100
[1540] Moved Linux-specific code to iface_mgr_linux.cc
-----------------------------------------------------------------------
Summary of changes:
src/lib/dhcp/iface_mgr.cc | 86 ++++++++++-----------------------------
src/lib/dhcp/iface_mgr.h | 24 +++++++++-
src/lib/dhcp/iface_mgr_bsd.cc | 9 ++++
src/lib/dhcp/iface_mgr_linux.cc | 55 +++++++++++++++++++++++++
4 files changed, 107 insertions(+), 67 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc
index e328cda..1ae77f9 100644
--- a/src/lib/dhcp/iface_mgr.cc
+++ b/src/lib/dhcp/iface_mgr.cc
@@ -277,6 +277,9 @@ bool IfaceMgr::openSockets6(uint16_t port) {
return (false);
}
+ // Binding socket to unicast address and then joining multicast group
+ // works well on Mac OS (and possibly other BSDs), but does not work
+ // on Linux.
if ( !joinMulticast(sock, iface->getName(),
string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
close(sock);
@@ -286,7 +289,8 @@ bool IfaceMgr::openSockets6(uint16_t port) {
count++;
#if defined(OS_LINUX)
- // this doesn't work too well on NetBSD
+ // To receive multicast traffic, Linux requires binding socket to
+ // a multicast group. That in turn doesn't work on NetBSD.
int sock2 = openSocket(iface->getName(),
IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
port);
@@ -623,24 +627,8 @@ IfaceMgr::send(const Pkt4Ptr& pkt)
m.msg_iov = &v;
m.msg_iovlen = 1;
-#if defined(OS_LINUX)
- // Setting the interface is a bit more involved.
- //
- // We have to create a "control message", and set that to
- // define the IPv4 packet information. We could set the
- // source address if we wanted, but we can safely let the
- // kernel decide what that should be.
- m.msg_control = &control_buf_[0];
- m.msg_controllen = control_buf_len_;
- struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
- cmsg->cmsg_level = IPPROTO_IP;
- cmsg->cmsg_type = IP_PKTINFO;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
- struct in_pktinfo* pktinfo =(struct in_pktinfo *)CMSG_DATA(cmsg);
- memset(pktinfo, 0, sizeof(struct in_pktinfo));
- pktinfo->ipi_ifindex = pkt->getIndex();
- m.msg_controllen = cmsg->cmsg_len;
-#endif
+ // call OS-specific routines (like setting interface index)
+ os_send4(m, control_buf_, control_buf_len_, pkt);
cout << "Trying to send " << pkt->getBuffer().getLength() << " bytes to "
<< pkt->getRemoteAddr().toText() << ":" << pkt->getRemotePort()
@@ -700,13 +688,11 @@ IfaceMgr::receive4() {
// Now we have a socket, let's get some data from it!
struct sockaddr_in from_addr;
- struct in_addr to_addr;
const uint32_t RCVBUFSIZE = 1500;
static uint8_t buf[RCVBUFSIZE];
memset(&control_buf_[0], 0, control_buf_len_);
memset(&from_addr, 0, sizeof(from_addr));
- memset(&to_addr, 0, sizeof(to_addr));
// Initialize our message header structure.
struct msghdr m;
@@ -737,61 +723,33 @@ IfaceMgr::receive4() {
return (Pkt4Ptr()); // NULL
}
- unsigned int ifindex = iface->getIndex();
-
-#if defined(OS_LINUX)
- struct cmsghdr* cmsg;
- struct in_pktinfo* pktinfo;
-
- int found_pktinfo = 0;
- cmsg = CMSG_FIRSTHDR(&m);
- while (cmsg != NULL) {
- if ((cmsg->cmsg_level == IPPROTO_IP) &&
- (cmsg->cmsg_type == IP_PKTINFO)) {
- pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+ // We have all data let's create Pkt4 object.
+ Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(buf, result));
- ifindex = pktinfo->ipi_ifindex;
- to_addr = pktinfo->ipi_addr;
+ unsigned int ifindex = iface->getIndex();
- // This field is useful, when we are bound to unicast
- // address e.g. 192.0.2.1 and the packet was sent to
- // broadcast. This will return broadcast address, not
- // the address we are bound to.
+ IOAddress from(htonl(from_addr.sin_addr.s_addr));
+ uint16_t from_port = htons(from_addr.sin_port);
- // IOAddress tmp(htonl(pktinfo->ipi_spec_dst.s_addr));
- // cout << "The other addr is: " << tmp.toText() << endl;
+ // Set receiving interface based on information, which socket was used to
+ // receive data. OS-specific info (see os_receive4()) may be more reliable,
+ // so this value may be overwritten.
+ pkt->setIndex(ifindex);
+ pkt->setIface(iface->getName());
+ pkt->setRemoteAddr(from);
+ pkt->setRemotePort(from_port);
+ pkt->setLocalPort(candidate->port_);
- // Perhaps we should uncomment this:
- // to_addr = pktinfo->ipi_spec_dst;
- found_pktinfo = 1;
- }
- cmsg = CMSG_NXTHDR(&m, cmsg);
- }
- if (!found_pktinfo) {
+ if (!os_receive4(m, pkt)) {
cout << "Unable to find pktinfo" << endl;
return (boost::shared_ptr<Pkt4>()); // NULL
}
-#endif
-
- IOAddress to(htonl(to_addr.s_addr));
- IOAddress from(htonl(from_addr.sin_addr.s_addr));
- uint16_t from_port = htons(from_addr.sin_port);
cout << "Received " << result << " bytes from " << from.toText()
<< "/port=" << from_port
- << " sent to " << to.toText() << " over interface "
+ << " sent to " << pkt->getLocalAddr().toText() << " over interface "
<< iface->getFullName() << endl;
- // we have all data let's create Pkt4 object
- Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(buf, result));
-
- pkt->setIface(iface->getName());
- pkt->setIndex(ifindex);
- pkt->setLocalAddr(to);
- pkt->setRemoteAddr(from);
- pkt->setRemotePort(from_port);
- pkt->setLocalPort(candidate->port_);
-
return (pkt);
}
diff --git a/src/lib/dhcp/iface_mgr.h b/src/lib/dhcp/iface_mgr.h
index bb3a73a..4663048 100644
--- a/src/lib/dhcp/iface_mgr.h
+++ b/src/lib/dhcp/iface_mgr.h
@@ -300,7 +300,7 @@ public:
/// (e.g. remove expired leases)
///
/// @return Pkt6 object representing received packet (or NULL)
- boost::shared_ptr<Pkt6> receive6();
+ Pkt6Ptr receive6();
/// @brief Tries to receive IPv4 packet over open IPv4 sockets.
///
@@ -313,7 +313,7 @@ public:
/// (e.g. remove expired leases)
///
/// @return Pkt4 object representing received packet (or NULL)
- boost::shared_ptr<Pkt4> receive4();
+ Pkt4Ptr receive4();
/// Opens UDP/IP socket and binds it to address, interface and port.
///
@@ -439,11 +439,29 @@ protected:
// to people who try to use multicast as source address.
/// length of the control_buf_ array
- int control_buf_len_;
+ size_t control_buf_len_;
/// control-buffer, used in transmission and reception
boost::scoped_array<char> control_buf_;
+
+ /// @brief A wrapper for OS-specific operations before sending IPv4 packet
+ ///
+ /// @param m message header (will be later used for sendmsg() call)
+ /// @param control_buf buffer to be used during transmission
+ /// @param control_buf_len buffer length
+ /// @param pkt packet to be sent
+ void os_send4(struct msghdr& m, boost::scoped_array<char>& control_buf,
+ size_t control_buf_len, const Pkt4Ptr& pkt);
+
+ /// @brief OS-specific operations during IPv4 packet reception
+ ///
+ /// @param m message header (was used during recvmsg() call)
+ /// @param pkt packet received (some fields will be set here)
+ ///
+ /// @return true if successful, false otherwise
+ bool os_receive4(struct msghdr& m, Pkt4Ptr& pkt);
+
private:
/// creates a single instance of this class (a singleton implementation)
diff --git a/src/lib/dhcp/iface_mgr_bsd.cc b/src/lib/dhcp/iface_mgr_bsd.cc
index 7786b92..8e56df0 100644
--- a/src/lib/dhcp/iface_mgr_bsd.cc
+++ b/src/lib/dhcp/iface_mgr_bsd.cc
@@ -33,6 +33,15 @@ IfaceMgr::detectIfaces() {
stubDetectIfaces();
}
+void IfaceMgr::os_send4_setup(struct msghdr& ,
+ boost::scoped_array<char>& ,
+ size_t , const Pkt4Ptr& ) {
+ // do nothing here. There's nothing BSD specific to do and os_send4_setup()
+ // interface is there only to not mix Linux-specific code in common
+ // IfaceMgr file.
+}
+
+
}
#endif
diff --git a/src/lib/dhcp/iface_mgr_linux.cc b/src/lib/dhcp/iface_mgr_linux.cc
index 657c943..91c977c 100644
--- a/src/lib/dhcp/iface_mgr_linux.cc
+++ b/src/lib/dhcp/iface_mgr_linux.cc
@@ -376,6 +376,61 @@ void IfaceMgr::Iface::setFlags(uint32_t flags) {
flag_broadcast_ = flags & IFF_BROADCAST;
}
+void IfaceMgr::os_send4(struct msghdr& m, boost::scoped_array<char>& control_buf,
+ size_t control_buf_len, const Pkt4Ptr& pkt) {
+
+ // Setting the interface is a bit more involved.
+ //
+ // We have to create a "control message", and set that to
+ // define the IPv4 packet information. We could set the
+ // source address if we wanted, but we can safely let the
+ // kernel decide what that should be.
+ m.msg_control = &control_buf[0];
+ m.msg_controllen = control_buf_len;
+ struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
+ cmsg->cmsg_level = IPPROTO_IP;
+ cmsg->cmsg_type = IP_PKTINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ struct in_pktinfo* pktinfo =(struct in_pktinfo *)CMSG_DATA(cmsg);
+ memset(pktinfo, 0, sizeof(struct in_pktinfo));
+ pktinfo->ipi_ifindex = pkt->getIndex();
+ m.msg_controllen = cmsg->cmsg_len;
+}
+
+bool IfaceMgr::os_receive4(struct msghdr& m, Pkt4Ptr& pkt) {
+ struct cmsghdr* cmsg;
+ struct in_pktinfo* pktinfo;
+ struct in_addr to_addr;
+
+ memset(&to_addr, 0, sizeof(to_addr));
+
+ cmsg = CMSG_FIRSTHDR(&m);
+ while (cmsg != NULL) {
+ if ((cmsg->cmsg_level == IPPROTO_IP) &&
+ (cmsg->cmsg_type == IP_PKTINFO)) {
+ pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+
+ pkt->setIndex(pktinfo->ipi_ifindex);
+ pkt->setLocalAddr(IOAddress(htonl(pktinfo->ipi_addr.s_addr)));
+ return (true);
+
+ // This field is useful, when we are bound to unicast
+ // address e.g. 192.0.2.1 and the packet was sent to
+ // broadcast. This will return broadcast address, not
+ // the address we are bound to.
+
+ // IOAddress tmp(htonl(pktinfo->ipi_spec_dst.s_addr));
+ // cout << "The other addr is: " << tmp.toText() << endl;
+
+ // Perhaps we should uncomment this:
+ // to_addr = pktinfo->ipi_spec_dst;
+ }
+ cmsg = CMSG_NXTHDR(&m, cmsg);
+ }
+
+ return (false);
+}
+
}
#endif // if defined(LINUX)
More information about the bind10-changes
mailing list