string RoutingCompiler::debugPrintRule(Rule *r) { RoutingRule *rule = RoutingRule::cast(r); RuleElementRDst *dstrel = rule->getRDst(); RuleElementRItf *itfrel = rule->getRItf(); RuleElementRGtw *gtwrel = rule->getRGtw(); ostringstream str; // str << setw(70) << setfill('-') << "-"; string dst, itf, gtw; FWObject *obj = FWReference::getObject(itfrel->front()); itf = (obj) ? obj->getName() : "NULL"; obj = FWReference::getObject(gtwrel->front()); gtw = (obj) ? obj->getName() : "NULL"; int no = 0; FWObject::iterator i1 = dstrel->begin(); while ( i1!=dstrel->end()) { str << endl; dst = " "; if (i1 != dstrel->end()) { FWObject *o = FWReference::getObject(*i1); dst = (o) ? o->getName() : "NULL"; } int w = 0; if (no==0) { str << rule->getLabel(); w = rule->getLabel().length(); } str << setw(10-w) << setfill(' ') << " "; str << setw(18) << setfill(' ') << dst.c_str() << " "; str << setw(18) << setfill(' ') << itf.c_str() << " "; str << setw(18) << setfill(' ') << gtw.c_str() << " "; str << setw(18) << setfill(' ') << " "; ++no; if ( i1 != dstrel->end() ) ++i1; } return str.str(); }
string RoutingCompiler_cisco::PrintRule::_printRGtw(RoutingRule *rule) { FWObject *ref; RuleElementRGtw *gtwrel = rule->getRGtw(); ref = gtwrel->front(); Address *gtw = Address::cast(FWReference::cast(ref)->getPointer()); if (gtw == NULL) compiler->abort(rule, "Broken GTW"); string gateway = _printAddr(gtw); if (gateway != "default ") return gateway; else return " "; }
bool RoutingCompiler_iosacl::checkRItfAndGw::processNext() { RoutingRule *rule=getNext(); if (rule==NULL) return false; tmp_queue.push_back(rule); RuleElementRItf *itfrel = rule->getRItf(); assert(itfrel); RuleElementRGtw *gtwrel = rule->getRGtw(); assert(gtwrel); if (!itfrel->isAny() && !gtwrel->isAny()) compiler->abort(rule, "Can not use both gateway address and interface in " "IOS routing rule"); return true; }
/* * Replace objects in dst and gw with their ip addresses, except if * interface of the firewall is found in gw, it is left intact because * IOS allows for using interface name as gateway in "ip route" * command. */ bool RoutingCompiler_iosacl::ExpandMultipleAddressesExceptInterface::processNext() { RoutingRule *rule=getNext(); if (rule==NULL) return false; tmp_queue.push_back(rule); RuleElementRDst *dst = rule->getRDst(); assert(dst); compiler->_expand_addr(rule, dst, true); RuleElementRGtw *gtwrel = rule->getRGtw(); assert(gtwrel); Address *gtw = Address::cast( FWReference::cast(gtwrel->front())->getPointer()); if (gtw == NULL) compiler->abort(rule, "Broken GTW"); if (Interface::isA(gtw) && gtw->isChildOf(compiler->fw)) return true; compiler->_expand_addr(rule, gtwrel, false); return true; }
bool RoutingCompiler::interfaceOrGateway::processNext() { RoutingRule *rule = getNext(); if (rule==NULL) return false; tmp_queue.push_back(rule); RuleElementRItf *itfrel = rule->getRItf(); RuleElementRGtw *gtwrel = rule->getRGtw(); if (!itfrel->isAny() && !gtwrel->isAny()) { compiler->abort(rule, "Use either gateway or interface in a routing rule " "but not both at the same time"); } return true; }
/* * Call this after converting to atomic rules by DST to be sure there * is just one object in DST. */ bool RoutingCompiler::sameDestinationDifferentGateways::processNext() { slurp(); if (tmp_queue.size()==0) return false; // map destination to gateway. std::map<string, string> dst_to_gw; std::map<string, string> dst_to_rule; for (deque<Rule*>::iterator k=tmp_queue.begin(); k!=tmp_queue.end(); ++k) { RoutingRule *rule = RoutingRule::cast( *k ); RuleElementRDst *dstrel = rule->getRDst(); Address *dst = Address::cast(FWReference::getObject(dstrel->front())); const InetAddr* dst_addr = dst->getAddressPtr(); const InetAddr* dst_netm = dst->getNetmaskPtr(); string key = dst_addr->toString() + "/" + dst_netm->toString(); // RuleElementRItf *itfrel = rule->getRItf(); // FWObject *itf = FWReference::cast(itfrel->front())->getPointer(); RuleElementRGtw *gtwrel = rule->getRGtw(); Address *gtw = Address::cast(FWReference::getObject(gtwrel->front())); const InetAddr* gtw_addr = gtw->getAddressPtr(); const InetAddr* gtw_netm = gtw->getNetmaskPtr(); string val = gtw_addr->toString() + "/" + gtw_netm->toString(); if (!dst_to_gw[key].empty() && dst_to_gw[key] != val) { compiler->abort( rule, "Rules " + dst_to_rule[key] + " and " + rule->getLabel() + " define routes to the same destination " + key + " via different gateways. This configuration is not supported" " for " + compiler->fw->getStr("host_OS")); } else { dst_to_gw[key] = val; dst_to_rule[key] = rule->getLabel(); } } return true; }
bool RoutingCompiler_pix::emptyRDstOrRItf::processNext() { RoutingRule *rule=getNext(); if (rule==NULL) return false; tmp_queue.push_back(rule); RuleElementRGtw *gtwrel = rule->getRGtw(); RuleElementRItf *itfrel = rule->getRItf(); if (itfrel->isAny() || gtwrel->isAny()) { compiler->abort( rule, "Interface and gateway rule elements can not be empty in " "the PIX routing rule"); } return true; }
string RoutingCompiler_iosacl::PrintRule::_printRGtw(RoutingRule *rule) { FWObject *ref; RuleElementRGtw *gtwrel = rule->getRGtw(); ref = gtwrel->front(); Address *gtw = Address::cast(FWReference::cast(ref)->getPointer()); if (Interface::isA(gtw) && gtw->isChildOf(compiler->fw)) { // gateway is interface of this firewall. Generate command // ip route A.B.C.D N.N.N.N interface metric return gtw->getName() + " "; } string gateway = _printAddr(gtw); if (gateway != "default ") return gateway; else return " "; }
bool RoutingCompiler::competingRules::processNext() { RoutingRule *rule = getNext(); if (rule==NULL) return false; RuleElementRItf *itfrel = rule->getRItf(); FWObject *itf = FWReference::cast(itfrel->front())->getPointer(); RuleElementRGtw *gtwrel = rule->getRGtw(); FWObject *gtw = FWReference::cast(gtwrel->front())->getPointer(); string metric = rule->getMetricAsString(); string label = rule->getSortedDstIds(); ostringstream ostr; ostr << gtw->getId() << "_" << itf->getId(); string combiId = ostr.str(); if( label == "") compiler->abort( rule, "Place 'createSortedDstIdsLabel()' before 'competingRules()' " "in the rule processor chain"); dest_it = rules_seen_so_far.find(label); if( dest_it != rules_seen_so_far.end()) { // a rule with the same destination was already seen ///std::cout << "NO NEW DEST" << std::endl; gtwitf_it = dest_it->second.find(combiId); if( gtwitf_it != dest_it->second.end() ) { // ... this gateway and interface combination were already // seen for this destination ///std::cout << "NO NEW GTWITF" << std::endl; if( gtwitf_it->second.first == metric) { // ... and same metric => rule already exists, skip ///std::cout << "SAME METRIC" << std::endl; string msg; msg = "Routing rules " + gtwitf_it->second.second + " and " + rule->getLabel() + " are identical, skipping the second one. " + "Delete one of them to avoid this warning"; compiler->warning(rule, msg.c_str()); } else { // ... but different metric => what metric should I use? => abort ///std::cout << "DIFFERENT METRIC" << std::endl; string msg; msg = "Routing rules " + gtwitf_it->second.second + " and " + rule->getLabel() + " are identical except for the metric, " + "please delete one of them"; compiler->abort(rule, msg.c_str()); } } else { // ... this gateway and interface combination is new for // this destination ///std::cout << "NEW GTWITF" << std::endl;/// if(false) { // TODO_lowPrio: if ( // !compiler->fw->getOptionsObject()->getBool // ("equal_cost_multi_path") ) ...If multipath is // turned off, perform this check. // iterate all gtwitf combis in the map // dest_it->second and search for the current metric // ... but has the same metric => what route should I // use for this destination? => abort string msg; msg = "Routing rules " + gtwitf_it->second.second + " and " + rule->getLabel() + " have the same destination and same metric," "but different gateway and interface combination. " "Set the metrics to different values or " "enable ECMP (Equal Cost MultiPath) routing"; compiler->abort( msg.c_str() ); } else { // ... and different metric OR equal_cost_multi_path enabled => OK tmp_queue.push_back(rule); } dest_it->second[combiId] = pair< string, string>( metric, rule->getLabel()); } } else { // this destination is new //std::cout << "NEW DEST" << std::endl; /// //ruleinfo tmpRuleInfo = { gtw->getStr("id") + itf->getStr("id"), metric, rule->getLabel()}; //rules_seen_so_far[label] = tmpRuleInfo; map< string, pair< string, string> > gtw_itf_tmp; gtw_itf_tmp[combiId] = pair< string, string>( metric, rule->getLabel()); rules_seen_so_far[label] = gtw_itf_tmp; tmp_queue.push_back(rule); } return true; }