Commit 084c9790 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[1239] OpenSockets4() and receive4() implemented in IfaceMgr.

parent 1ee6d8e7
...@@ -31,6 +31,9 @@ Dhcpv4Srv::Dhcpv4Srv(uint16_t port) { ...@@ -31,6 +31,9 @@ Dhcpv4Srv::Dhcpv4Srv(uint16_t port) {
IfaceMgr::instance(); IfaceMgr::instance();
/// @todo: instantiate LeaseMgr here once it is imlpemented. /// @todo: instantiate LeaseMgr here once it is imlpemented.
IfaceMgr::instance().printIfaces();
IfaceMgr::instance().openSockets4();
setServerID(); setServerID();
...@@ -47,7 +50,7 @@ Dhcpv4Srv::run() { ...@@ -47,7 +50,7 @@ Dhcpv4Srv::run() {
boost::shared_ptr<Pkt4> query; // client's message boost::shared_ptr<Pkt4> query; // client's message
boost::shared_ptr<Pkt4> rsp; // server's response boost::shared_ptr<Pkt4> rsp; // server's response
#if 0 #if 1
// uncomment this once ticket 1239 is merged. // uncomment this once ticket 1239 is merged.
query = IfaceMgr::instance().receive4(); query = IfaceMgr::instance().receive4();
#endif #endif
...@@ -99,9 +102,9 @@ Dhcpv4Srv::run() { ...@@ -99,9 +102,9 @@ Dhcpv4Srv::run() {
if (rsp->pack()) { if (rsp->pack()) {
cout << "Packet assembled correctly." << endl; cout << "Packet assembled correctly." << endl;
} }
#if 0 #if 1
// uncomment this once ticket 1240 is merged. // uncomment this once ticket 1240 is merged.
IfaceMgr::instance().send4(rsp); IfaceMgr::instance().send(rsp);
#endif #endif
} }
} }
......
...@@ -36,7 +36,7 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port) { ...@@ -36,7 +36,7 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port) {
IfaceMgr::instance(); IfaceMgr::instance();
// Now try to open IPv6 sockets on detected interfaces. // Now try to open IPv6 sockets on detected interfaces.
IfaceMgr::instance().openSockets(port); IfaceMgr::instance().openSockets6(port);
/// @todo: instantiate LeaseMgr here once it is imlpemented. /// @todo: instantiate LeaseMgr here once it is imlpemented.
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <dhcp/dhcp4.h>
#include <dhcp/dhcp6.h> #include <dhcp/dhcp6.h>
#include <dhcp/iface_mgr.h> #include <dhcp/iface_mgr.h>
#include <exceptions/exceptions.h> #include <exceptions/exceptions.h>
...@@ -191,9 +192,52 @@ IfaceMgr::detectIfaces() { ...@@ -191,9 +192,52 @@ IfaceMgr::detectIfaces() {
} }
} }
void bool IfaceMgr::openSockets4(uint16_t port) {
IfaceMgr::openSockets(uint16_t port) { int sock;
int count = 0;
for (IfaceCollection::iterator iface=ifaces_.begin();
iface!=ifaces_.end();
++iface) {
cout << "Trying interface " << iface->getFullName() << endl;
#if 0
// uncomment when trac1237 (interface detection) is merged
if (iface->flag_loopback_ ||
!iface->flag_up_ ||
!iface->flag_running_) {
continue;
}
#endif
AddressCollection addrs = iface->getAddresses();
for (AddressCollection::iterator addr= addrs.begin();
addr != addrs.end();
++addr) {
// skip IPv4 addresses
if (addr->getFamily() != AF_INET) {
continue;
}
sock = openSocket(iface->getName(), *addr, port);
if (sock<0) {
cout << "Failed to open unicast socket." << endl;
return (false);
}
count++;
}
}
return (count > 0);
}
bool IfaceMgr::openSockets6(uint16_t port) {
int sock1, sock2; int sock1, sock2;
int count = 0;
for (IfaceCollection::iterator iface = ifaces_.begin(); for (IfaceCollection::iterator iface = ifaces_.begin();
iface != ifaces_.end(); ++iface) { iface != ifaces_.end(); ++iface) {
...@@ -228,6 +272,8 @@ IfaceMgr::openSockets(uint16_t port) { ...@@ -228,6 +272,8 @@ IfaceMgr::openSockets(uint16_t port) {
} }
} }
} }
return (count > 0);
} }
void void
...@@ -514,10 +560,138 @@ IfaceMgr::send(boost::shared_ptr<Pkt4>& ) ...@@ -514,10 +560,138 @@ IfaceMgr::send(boost::shared_ptr<Pkt4>& )
boost::shared_ptr<Pkt4> boost::shared_ptr<Pkt4>
IfaceMgr::receive4() { IfaceMgr::receive4() {
isc_throw(NotImplemented, "Pkt4 reception not implemented yet.");
// TODO: To be implemented (ticket #1239) const SocketInfo* candidate = 0;
return (boost::shared_ptr<Pkt4>()); // NULL IfaceCollection::const_iterator iface;
for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
#if 0
// uncomment when trac1237 (interface detection) is merged
// Let's skip loopback and downed interfaces.
if (iface->flag_loopback_ ||
!iface->flag_up_ ||
!iface->flag_running_) {
continue;
}
#endif
SocketCollection::const_iterator s = iface->sockets_.begin();
while (s != iface->sockets_.end()) {
// We don't want IPv6 addresses here.
if (s->addr_.getFamily() != AF_INET) {
++s;
continue;
}
// This address looks good.
if (!candidate) {
candidate = &(*s);
break;
}
++s;
}
if (candidate) {
break;
}
}
if (!candidate) {
isc_throw(Unexpected, "Failed to find any suitable sockets on all interfaces.");
}
cout << "Trying to receive over UDP4 socket " << candidate->sockfd_ << " bound to "
<< candidate->addr_.toText() << "/port=" << candidate->port_ << " on "
<< iface->getFullName() << endl;
// Now we have a socket, let's get some data from it!
struct msghdr m;
struct iovec v;
int result;
struct cmsghdr* cmsg;
struct in_pktinfo* pktinfo;
struct sockaddr_in from_addr;
struct in_addr to_addr;
unsigned int ifindex = 0;
boost::shared_ptr<Pkt4> pkt;
const uint32_t RCVBUFSIZE = 1500;
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.
memset(&m, 0, sizeof(m));
// Point so we can get the from address.
m.msg_name = &from_addr;
m.msg_namelen = sizeof(from_addr);
v.iov_base = (void*)buf;
v.iov_len = RCVBUFSIZE;
m.msg_iov = &v;
m.msg_iovlen = 1;
/*
* Getting the interface is a bit more involved.
*
* We set up some space for a "control message". We have
* previously asked the kernel to give us packet
* information (when we initialized the interface), so we
* should get the destination address from that.
*/
m.msg_control = &control_buf_[0];
m.msg_controllen = control_buf_len_;
result = recvmsg(candidate->sockfd_, &m, 0);
if (result < 0) {
cout << "Failed to receive UDP4 data." << endl;
return (boost::shared_ptr<Pkt4>()); // NULL
}
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);
ifindex = pktinfo->ipi_ifindex;
to_addr = pktinfo->ipi_addr;
// to_addr = pktinfo->ipi_spec_dst;
found_pktinfo = 1;
}
cmsg = CMSG_NXTHDR(&m, cmsg);
}
if (!found_pktinfo) {
cout << "Unable to find pktinfo" << endl;
return (boost::shared_ptr<Pkt4>()); // NULL
}
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 "
<< iface->getFullName() << endl;
// we have all data let's create Pkt4 object
pkt = boost::shared_ptr<Pkt4>(new Pkt4(buf, result));
pkt->setLocalAddr(to);
pkt->setRemotePort(from_port);
pkt->setLocalPort(candidate->port_);
// pkt->setRemoteAddr(from);
return (pkt);
} }
boost::shared_ptr<Pkt6> boost::shared_ptr<Pkt6>
...@@ -585,12 +759,16 @@ IfaceMgr::receive6() { ...@@ -585,12 +759,16 @@ IfaceMgr::receive6() {
SocketCollection::const_iterator s = iface->sockets_.begin(); SocketCollection::const_iterator s = iface->sockets_.begin();
const SocketInfo* candidate = 0; const SocketInfo* candidate = 0;
while (s != iface->sockets_.end()) { while (s != iface->sockets_.end()) {
if (s->addr_.getFamily() != AF_INET6) {
++s;
continue;
}
if (s->addr_.getAddress().to_v6().is_multicast()) { if (s->addr_.getAddress().to_v6().is_multicast()) {
candidate = &(*s); candidate = &(*s);
break; break;
} }
if (!candidate) { if (!candidate) {
candidate = &(*s); // it's not multicast, but it's better than none candidate = &(*s); // it's not multicast, but it's better than nothing
} }
++s; ++s;
} }
...@@ -599,7 +777,7 @@ IfaceMgr::receive6() { ...@@ -599,7 +777,7 @@ IfaceMgr::receive6() {
<< " does not have any sockets open."); << " does not have any sockets open.");
} }
cout << "Trying to receive over socket " << candidate->sockfd_ << " bound to " cout << "Trying to receive over UDP6 socket " << candidate->sockfd_ << " bound to "
<< candidate->addr_.toText() << "/port=" << candidate->port_ << " on " << candidate->addr_.toText() << "/port=" << candidate->port_ << " on "
<< iface->getFullName() << endl; << iface->getFullName() << endl;
result = recvmsg(candidate->sockfd_, &m, 0); result = recvmsg(candidate->sockfd_, &m, 0);
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <boost/scoped_array.hpp> #include <boost/scoped_array.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <asiolink/io_address.h> #include <asiolink/io_address.h>
#include <dhcp/dhcp6.h>
#include <dhcp/dhcp4.h>
#include <dhcp/pkt4.h> #include <dhcp/pkt4.h>
#include <dhcp/pkt6.h> #include <dhcp/pkt6.h>
...@@ -299,13 +301,22 @@ public: ...@@ -299,13 +301,22 @@ public:
/// Will throw exception if socket creation fails. /// Will throw exception if socket creation fails.
/// ///
/// @param port specifies port number (usually DHCP6_SERVER_PORT) /// @param port specifies port number (usually DHCP6_SERVER_PORT)
void openSockets(uint16_t port); ///
/// @return true if any sockets were open
bool openSockets6(uint16_t port = DHCP6_SERVER_PORT);
/// @brief Closes all open sockets. /// @brief Closes all open sockets.
/// Is used in destructor, but also from Dhcpv4_srv and Dhcpv6_srv classes. /// Is used in destructor, but also from Dhcpv4_srv and Dhcpv6_srv classes.
void closeSockets(); void closeSockets();
/// Opens IPv4 sockets on detected interfaces.
/// Will throw exception if socket creation fails.
///
/// @param port specifies port number (usually DHCP6_SERVER_PORT)
///
/// @return true if any sockets were open
bool openSockets4(uint16_t port = DHCP4_SERVER_PORT);
// don't use private, we need derived classes in tests // don't use private, we need derived classes in tests
protected: protected:
......
...@@ -77,8 +77,8 @@ Pkt4::Pkt4(const uint8_t* data, size_t len) ...@@ -77,8 +77,8 @@ Pkt4::Pkt4(const uint8_t* data, size_t len)
{ {
if (len < DHCPV4_PKT_HDR_LEN) { if (len < DHCPV4_PKT_HDR_LEN) {
isc_throw(OutOfRange, "Truncated DHCPv4 packet (len=" << len isc_throw(OutOfRange, "Truncated DHCPv4 packet (len=" << len
<< " received, at least " << DHCPV4_PKT_HDR_LEN << ") received, at least " << DHCPV4_PKT_HDR_LEN
<< "is expected"); << " is expected.");
} }
data_.resize(len); data_.resize(len);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment