/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "xstd/xstd.h"
#include <unistd.h>
#include <ctype.h>
#include "xstd/h/net/if.h"
#include "xstd/h/netinet.h"
#include "xstd/h/iostream.h"
#include "xstd/h/iomanip.h"
#include "xstd/getIfAddrs.h"
#include "xstd/InetIfReq.h"
#include "xstd/NetIface.h"
#include <sys/ioctl.h>
bool NetIface::GetAddrs(Array<InetIfReq> &addrs, const String &ifname) {
return GetIfAddrs(addrs, ifname);
}
NetIface::NetIface() {
Must(theV4Sock.create(PF_INET, SOCK_DGRAM, 0));
theV6Sock.create(PF_INET6, SOCK_DGRAM, 0);
}
NetIface::~NetIface() {
if (theV4Sock)
theV4Sock.close();
if (theV6Sock)
theV6Sock.close();
}
void NetIface::name(const String &aName) {
theName = aName;
}
bool NetIface::primaries(Primaries &ips) const {
Assert(theName);
InAddress v4;
if (theV4Sock.getV4IfAddr(theName, v4))
ips.vFour = NetAddr(v4, -1);
if (theV6Sock) {
InAddress v6;
if (theV6Sock.getV6IfAddr(theName, v6))
ips.vSix = NetAddr(v6, -1);
}
return ips.vFour || ips.vSix;
}
void NetIface::getAliases(Array<InetIfReq> &aliases) const {
Assert(theName);
Must(GetAddrs(aliases, theName));
Primaries primes;
if (!primaries(primes))
return;
// remove primary address from the aliases array (if any)
if (primes.vFour)
ejectPrimary(primes.vFour, aliases);
if (primes.vSix)
ejectPrimary(primes.vSix, aliases);
}
void NetIface::ejectPrimary(const NetAddr &primary, Array<InetIfReq> &all) const {
int paIdx = -1;
for (int i = 0; paIdx < 0 && i < all.count(); ++i) {
if (all[i].addrN() == primary.addrN())
paIdx = i;
}
Must(paIdx >= 0);
if (paIdx < all.count()-1)
all.memmove(paIdx, all.items()+paIdx+1, all.count()-paIdx-1);
all.pop();
}
int NetIface::delAliases() {
Assert(theName);
Array<InetIfReq> olds;
getAliases(olds);
// reverse order seems to be important on Linux where
// one cannot delete :1 after deleting :0
int delCount = 0;
for (int i = olds.count() - 1; i >= 0; --i) {
if (delAlias(olds[i].addrN(), i))
delCount++;
}
return delCount;
}
bool NetIface::delAlias(const InAddress &addr, int idx) {
Assert(theName);
switch (addr.family()) {
case AF_INET: {
InetIfAliasReq r(theName);
r.addr(addr);
return theV4Sock.delIfAddr(r, idx);
}
case AF_INET6: {
// XXX: implement
return false;
}
default: {
Error::Last(EINVAL);
return false;
}
}
Assert(false);
return false;
}
bool NetIface::addAlias(const InAddress &addr, int idx, const InAddress &netmask) {
Assert(theName);
switch (addr.family()) {
case AF_INET: {
InetIfAliasReq r(theName);
r.addr(addr);
r.mask(netmask);
r.broad(addr.broadcast(netmask));
return theV4Sock.addV4IfAddr(r, idx) || !Error::LastExcept(EEXIST);
}
case AF_INET6: {
Inet6IfAliasReq r(theName, addr, netmask);
return theV6Sock.addV6IfAddr(r, idx) || !Error::LastExcept(EEXIST);
}
default: {
Error::Last(EINVAL);
return false;
}
}
Assert(false);
return false;
}
bool NetIface::addAliases(const Array<InAddress> &aliases, const InAddress &netmask) {
for (int i = 0; i < aliases.count(); ++i) {
if (!addAlias(aliases[i], i, netmask))
return false;
}
return true;
}
syntax highlighted by Code2HTML, v. 0.9.1