/* 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 &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; }