Esempio n. 1
0
/**
 * 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;
}