/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "pgl/pgl.h"
#include "xstd/h/sstream.h"
#include "xstd/String.h"
#include "xstd/NetAddr.h"
#include "xstd/gadgets.h"
#include "pgl/PglArraySym.h"
#include "pgl/PglNetAddrSym.h"
#include "pgl/PglNetAddrParts.h"
#include "pgl/PglNetAddrRange.h"
#include "pgl/pglStrIs.h"
PglNetAddrRange::PglNetAddrRange(): theSubnet(-1) {
}
void PglNetAddrRange::reset() {
PglStrRange::reset();
theAddr = String();
theIfName = String();
theSubnet = -1;
}
void PglNetAddrRange::netmask(InAddress &netm) const {
String str;
startIter();
currentIter(str);
int subnet = theSubnet;
if (subnet < 0) {
// default subnet length is the size of the address: 32 or 128
NetAddr firstNetAddr;
Should(pglIsNetAddr(str, firstNetAddr));
subnet = firstNetAddr.addrN().len() * 8;
}
netm = InAddress::NetMask(subnet);
}
ArraySym *PglNetAddrRange::toSyms(const TokenLoc &loc) const {
ArraySym *arr = new ArraySym(NetAddrSym::TheType);
startIter();
do {
NetAddrSym nas;
currentAddrSym(nas);
if (loc)
nas.loc(loc);
arr->add(nas); // XXX: replace with add(this)
} while (nextIter());
return arr;
}
void PglNetAddrRange::toAddrs(Array<NetAddr*> &addrs) const {
startIter();
do {
String str;
currentIter(str);
NetAddr addr;
Assert(pglIsNetAddr(str, addr));
addrs.append(new NetAddr(addr));
} while (nextIter());
}
void PglNetAddrRange::toAddrs(AddrIter iter) const {
startIter();
do {
String str;
currentIter(str);
NetAddr addr;
Assert(pglIsNetAddr(str, addr));
iter(addr);
} while (nextIter());
}
void PglNetAddrRange::addrAt(int idx, NetAddrSym &nas) const {
startIter();
skipIter(idx);
currentAddrSym(nas);
}
void PglNetAddrRange::currentAddrSym(NetAddrSym &nas) const {
String str;
currentIter(str);
NetAddr addr;
Assert(pglIsNetAddr(str, addr));
nas.val(addr);
if (theIfName)
nas.setIfname(theIfName);
if (theSubnet >= 0)
nas.setSubnet(theSubnet);
}
bool PglNetAddrRange::parse(const String &val) {
PglNetAddrParts parts(val);
if (parts.error()) {
cerr << "error: failed to parse '" << val << "' address range: " <<
parts.error() << endl;
return false;
}
theIfName = parts.ifName();
theSubnet = parts.subnet();
// stored together but parsed separately because bases may differ
theAddr = parts.hosts() + parts.ports();
// IPv6 requires hexidecimal base and needs '[]' escapes handled separately
if (parts.hostKind() == PglNetAddrParts::hkIPv6) {
static const String openb = "[";
static const String closeb = "]";
addRangePoint(openb);
currentBase(16);
// strip '[]'
const String bareHosts = parts.hosts()(1, parts.hosts().len()-1);
if (!PglStrRange::parse(bareHosts))
return false;
addRangePoint(closeb);
} else {
currentBase(10);
if (!PglStrRange::parse(parts.hosts()))
return false;
}
if (parts.ports().len() > 0) {
currentBase(10); // ports are always decimal
return PglStrRange::parse(parts.ports());
} else {
return true;
}
}
bool PglNetAddrRange::canMergeSameType(const StringArrayBlock &b) const {
const PglNetAddrRange &r = (const PglNetAddrRange &)b;
if (!count()) // brand new object
return true;
if ((theIfName || r.theIfName) && theIfName != r.theIfName)
return false;
if (theSubnet != r.theSubnet)
return false;
return PglStrRange::canMergeSameType(r);
}
void PglNetAddrRange::mergeSameType(const StringArrayBlock &b) {
const PglNetAddrRange &r = (const PglNetAddrRange &)b;
theIfName = r.theIfName;
theSubnet = r.theSubnet;
PglStrRange::mergeSameType(r);
}
bool PglNetAddrRange::optRangeBeg(char ch) const {
return ch == '.' || ch == ':';
}
ostream &PglNetAddrRange::print(ostream &os) const {
if (theIfName)
os << theIfName << "::";
PglStrRange::print(os);
if (theSubnet >= 0)
os << '/' << theSubnet;
return os;
}
syntax highlighted by Code2HTML, v. 0.9.1