summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2014-09-04 13:36:25 -0400
committerAdam Ierymenko <adam.ierymenko@gmail.com>2014-09-04 13:36:25 -0400
commit6df954674289b22c894b16c0969ddca535ef8216 (patch)
tree47137969a2cccada67fd39ae726732b78a8c7201
parent4dbeb97eb9bd67fadd893252de602144d5ed9c23 (diff)
downloadinfinitytier-6df954674289b22c894b16c0969ddca535ef8216.tar.gz
infinitytier-6df954674289b22c894b16c0969ddca535ef8216.zip
Fix for missing broadcast address on Linux Ethernet taps.
-rw-r--r--node/InetAddress.cpp22
-rw-r--r--node/InetAddress.hpp8
-rw-r--r--osnet/LinuxEthernetTap.cpp9
3 files changed, 37 insertions, 2 deletions
diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp
index 88ab6e49..832acf04 100644
--- a/node/InetAddress.cpp
+++ b/node/InetAddress.cpp
@@ -196,6 +196,28 @@ InetAddress InetAddress::netmask() const
return r;
}
+InetAddress InetAddress::broadcast() const
+ throw()
+{
+ InetAddress r(*this);
+ switch(_sa.saddr.sa_family) {
+ case AF_INET:
+ r._sa.sin.sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffff >> netmaskBits()));
+ break;
+ case AF_INET6: {
+ unsigned char *bf = (unsigned char *)r._sa.sin6.sin6_addr.s6_addr;
+ signed int bitsLeft = (signed int)netmaskBits();
+ for(unsigned int i=0;i<16;++i) {
+ if (bitsLeft > 0) {
+ bf[i] |= (unsigned char)((bitsLeft >= 8) ? 0x00 : (0xff >> bitsLeft));
+ bitsLeft -= 8;
+ }
+ }
+ } break;
+ }
+ return r;
+}
+
bool InetAddress::sameNetworkAs(const InetAddress &ipnet) const
throw()
{
diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp
index 7cfb1abe..0ddb2cd4 100644
--- a/node/InetAddress.hpp
+++ b/node/InetAddress.hpp
@@ -218,6 +218,14 @@ public:
throw();
/**
+ * Constructs a broadcast address from a network/netmask address
+ *
+ * @return Broadcast address (only IP portion is meaningful)
+ */
+ InetAddress broadcast() const
+ throw();
+
+ /**
* @return True if this is an IPv4 address
*/
inline bool isV4() const throw() { return (_sa.saddr.sa_family == AF_INET); }
diff --git a/osnet/LinuxEthernetTap.cpp b/osnet/LinuxEthernetTap.cpp
index 7e20b75f..1bd066c3 100644
--- a/osnet/LinuxEthernetTap.cpp
+++ b/osnet/LinuxEthernetTap.cpp
@@ -224,8 +224,13 @@ bool LinuxEthernetTap::addIP(const InetAddress &ip)
long cpid = (long)vfork();
if (cpid == 0) {
Utils::redirectUnixOutputs("/dev/null",(const char *)0);
- ::execl("/sbin/ip","/sbin/ip","addr","add",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
- ::execl("/usr/sbin/ip","/usr/sbin/ip","addr","add",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
+ if (ip.isV4()) {
+ ::execl("/sbin/ip","/sbin/ip","addr","add",ip.toString().c_str(),"broadcast",ip.broadcast().toIpString().c_str(),"dev",_dev.c_str(),(const char *)0);
+ ::execl("/usr/sbin/ip","/usr/sbin/ip","addr","add",ip.toString().c_str(),"broadcast",ip.broadcast().toIpString().c_str(),"dev",_dev.c_str(),(const char *)0);
+ } else {
+ ::execl("/sbin/ip","/sbin/ip","addr","add",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
+ ::execl("/usr/sbin/ip","/usr/sbin/ip","addr","add",ip.toString().c_str(),"dev",_dev.c_str(),(const char *)0);
+ }
::_exit(-1);
} else if (cpid > 0) {
int exitcode = -1;