/** * finds interface of the firewall associated with the netzone * that object 'obj' belongs to. Returns interface ID * */ int Helper::findInterfaceByNetzone(const InetAddr *addr, const InetAddr *nm) throw(FWException) { #if DEBUG_NETZONE_OPS cerr << "Helper::findInterfaceByNetzone"; cerr << " matching to"; cerr << " addr=" << addr; if (addr) cerr << " " << addr->toString(); cerr << " nm=" << nm; if (nm) cerr << " " << nm->toString(); cerr << endl; #endif Firewall *fw = compiler->fw; map<int,FWObject*> zones; list<FWObject*> l2 = fw->getByTypeDeep(Interface::TYPENAME); for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i) { Interface *iface = Interface::cast(*i); if (iface->isDedicatedFailover()) continue; if (iface->isUnprotected()) continue; // NOTE: "network_zone" is globally unique string ID int netzone_id = FWObjectDatabase::getIntId(iface->getStr("network_zone")); if (netzone_id != -1) { FWObject *netzone = fw->getRoot()->findInIndex(netzone_id); list<FWObject*> nz; expand_group_recursive(netzone, nz); #if DEBUG_NETZONE_OPS cerr << "Helper::findInterfaceByNetzone"; cerr << " netzone_id=" << netzone_id << " " << iface->getStr("network_zone") << " " << netzone->getName() << endl; #endif for (list<FWObject*>::iterator j=nz.begin(); j!=nz.end(); ++j) { Address *netzone_addr = Address::cast(*j); if (netzone_addr == NULL) continue; #if DEBUG_NETZONE_OPS cerr << "Helper::findInterfaceByNetzone"; cerr << " " << netzone_addr->getName() << " " << netzone_addr->getAddressPtr()->toString() << endl; #endif // if addr==NULL, return id of the interfacce that has // net_zone=="any" if (addr==NULL) { if (netzone_addr->getId()==FWObjectDatabase::ANY_ADDRESS_ID) return iface->getId(); // id of the interface } else { // see SF bug 3213019 // skip ipv6 addresses in network zone group if (netzone_addr->getAddressPtr()->addressFamily() != addr->addressFamily()) continue; const InetAddr *nz_addr = netzone_addr->getAddressPtr(); const InetAddr *nz_netm = netzone_addr->getNetmaskPtr(); if (nm != NULL && nz_netm != NULL) { InetAddrMask nz_subnet(*nz_addr, *nz_netm); InetAddrMask other_subnet(*addr, *nm); vector<InetAddrMask> ovr = libfwbuilder::getOverlap(nz_subnet, other_subnet); #if DEBUG_NETZONE_OPS cerr << "Helper::findInterfaceByNetzone"; cerr << " addr=" << other_subnet.toString(); cerr << " nz=" << nz_subnet.toString(); cerr << " overlap:"; cerr << " ovr.size()=" << ovr.size(); if (ovr.size() > 0) cerr << " ovr.front()=" << ovr.front().toString(); cerr << endl; #endif if (ovr.size()==0) continue; // if nz_subnet is equal or wider than other_subnet, // getOverlap() returns subnet object equal to other_subnet // If other_subnet is wider, returned object is equal // to nz_subnet. If they intersect but one does not fit // completely in the other, returned object is not equal // to either. if (ovr.front() == other_subnet) { zones[iface->getId()] = netzone_addr; #if DEBUG_NETZONE_OPS cerr << "Helper::findInterfaceByNetzone"; cerr << " match" << endl; #endif } } else { if (netzone_addr->belongs(*addr)) { zones[iface->getId()] = netzone_addr; #if DEBUG_NETZONE_OPS cerr << "Helper::findInterfaceByNetzone"; cerr << " match" << endl; #endif } } } } } } /* * now compare dimensions of all netzones that contain address obj and * pick the one with smallest dimension */ int res_id = -1; unsigned long res_dim = LONG_MAX; for (map<int,FWObject*>::iterator i=zones.begin(); i!=zones.end(); ++i) { int iface_id = (*i).first; FWObject *netzone = (*i).second; unsigned long dim = calculateDimension(netzone); #if DEBUG_NETZONE_OPS cerr << "Helper::findInterfaceByNetzone"; cerr << " netzone=" << netzone->getName() << " dim=" << dim << " res_dim=" << res_dim << endl; #endif if (dim<=res_dim) { res_id = iface_id; res_dim = dim; } } #if DEBUG_NETZONE_OPS cerr << "Helper::findInterfaceByNetzone"; cerr << " Result after scanning network zones: " << res_id << endl; #endif /* * Subnets defined by addresses of interfaces are automatically part * of the corresponding network zones */ if (res_id == -1) res_id = findInterfaceByAddress(addr, nm); if (res_id == -1) { QString err = QObject::tr("Can not find interface with network zone " "that includes address '%1%2'"); throw(FWException(err .arg((addr)?addr->toString().c_str():"NULL") .arg((nm)?QString("/%1").arg(nm->toString().c_str()):"") .toStdString())); } #if DEBUG_NETZONE_OPS cerr << "Helper::findInterfaceByNetzone"; cerr << " returning " << res_id << endl; #endif return res_id; }