diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 88ab6e490..832acf04c 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 7cfb1abe0..0ddb2cd43 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -217,6 +217,14 @@ public: InetAddress netmask() const 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 */ diff --git a/osnet/LinuxEthernetTap.cpp b/osnet/LinuxEthernetTap.cpp index 7e20b75f1..1bd066c3e 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;